blob: 5e6b9b1d0c37bc052c6d03fc29ed5802cd262edd [file] [log] [blame] [edit]
#include <string>
#include <cstring>
#include <memory>
#include <cstdlib>
#include "tilt.hpp"
using namespace blit;
#define GRAIN_COUNT 5000
uint8_t grain_mask[160 * 120];
bool is_occupied(const Point &p) {
return grain_mask[p.x + (p.y * 160)] != 0;
}
void set_occupied(const Point &p) {
grain_mask[p.x + (p.y * 160)] = 1;
}
void clear_occupied(const Point &p) {
grain_mask[p.x + (p.y * 160)] = 0;
}
float deg2rad(float a) {
return a * (pi / 180.0f);
}
Vec2 gravity(0, 1000.0f);
Pen colours[] = {
Pen(7, 254, 9),
Pen(230, 194, 41),
Pen(239, 45, 86),
Pen(241, 113, 5),
Pen(26, 143, 227),
Pen(201, 26, 227),
};
struct grain {
bool test_move(const Point &tp) {
if (screen.bounds.contains(tp)) {
if ( (tp.x == (int)p.x && tp.y == (int)p.y) ||
!is_occupied(tp) ) {
return true;
}
}
return false;
}
bool update(const float td) {
v += (gravity * td);
if (v.length() > 50.0f) {
v.normalize();
v *= 50.0f;
}
// test point is along the velocity vector
Vec2 np = p;
Vec2 tp = p + (v * td);
bool found = false;
if ((found = test_move(tp))) {
np = tp;
} else {
// optimised -45 degree rotations
float rx = v.x * 0.70710f - v.y * -0.70710f;
float ry = v.x * -0.70710f + v.y * 0.70710f;
v.x = rx;
v.y = ry;
tp = p + (v * td);
if ((found = test_move(tp))) {
np = tp;
}
else {
// optimised 90 degree rotations
float rx = -v.y;
float ry = v.x;
v.x = rx;
v.y = ry;
tp = p + (v * td);
if ((found = test_move(tp))) {
np = tp;
}
}
}
// update the position of our grain
if (found) {
clear_occupied(p);
p = np;
set_occupied(np);
}
else {
v = Vec2(0, 0);
}
return true;
}
public:
Vec2 p = Vec2(0, 0);
Vec2 v = Vec2(0, 1);
uint8_t c = 0;
};
grain grains[GRAIN_COUNT];
/* setup */
void init() {
for (auto &g : grains) {
do {
g.p = Vec2(Vec2(rand() % 160, rand() % 120));
g.c = rand() % 6;
} while (is_occupied(g.p));
}
}
uint32_t update_time_ms = 0;
void render(uint32_t time_ms) {
screen.pen = Pen(0, 0, 0, 255);
screen.clear();
for (auto &g : grains) {
screen.pen = colours[g.c];
screen.pixel(g.p);
}
screen.pen = Pen(255, 255, 255);
Point centre = Point(80, 60);
screen.line(centre, centre + (gravity * 20.0f));
screen.watermark();
// draw FPS meter
screen.alpha = 255;
screen.pen = Pen(0, 0, 0);
screen.rectangle(Rect(1, 120 - 10, 12, 9));
screen.pen = Pen(255, 255, 255, 200);
std::string fms = std::to_string(update_time_ms);
screen.text(fms, minimal_font, Rect(3, 120 - 9, 10, 16));
int block_size = 4;
for (uint32_t i = 0; i < update_time_ms; i++) {
screen.pen = Pen(i * 5, 255 - (i * 5), 0);
screen.rectangle(Rect(i * (block_size + 1) + 1 + 13, screen.bounds.h - block_size - 1, block_size, block_size));
}
}
void update(uint32_t time_ms) {
static uint32_t last_time_ms = time_ms;
// smoke_generator.update(time_ms);
/*
if (pressed(button::DPAD_LEFT)) {
gravity.rotate(0.01f);
}
if (pressed(button::DPAD_RIGHT)) {
gravity.rotate(-0.01f);
}
if (pressed(button::DPAD_UP)) {
gravity *= 1.01f;
}
if (pressed(button::DPAD_DOWN)) {
gravity /= 1.01f;
}
*/
gravity.x = blit::tilt.x;
gravity.y = blit::tilt.y;
gravity *= 1000.0f;
float td = (time_ms - last_time_ms) / 1000.0f;
uint32_t ms_start = now();
for (auto &g : grains) {
g.update(td);
}
uint32_t ms_end = now();
update_time_ms = ms_end - ms_start;
last_time_ms = time_ms;
}