blob: 13911e621867dc31e702154322a8088e4ae496b5 [file] [log] [blame] [edit]
#include <string>
#include <cstring>
#include <memory>
#include <cstdlib>
#include "tilemap-test.hpp"
using namespace blit;
TileMap* background;
TileMap* environment;
/* setup */
void init() {
blit::set_screen_mode(ScreenMode::lores);
// fix tile ids from .tmx file
for (auto i = 0; i < (64 * 64); i++) {
if (layer_environment[i] != 0)
layer_environment[i]--;
}
//sprites.generate_mipmaps(3);
screen.sprites = SpriteSheet::load(packed_data);
environment = new TileMap((uint8_t*)layer_environment, nullptr, Size(64, 64), screen.sprites);
}
Mat3 world_transform;
float deg2rad(float a) {
return a * (pi / 180.0f);
}
uint32_t current_time;
std::function<Mat3(uint8_t)> dream = [](uint8_t y) -> Mat3 {
float progress = (sinf(current_time / 2000.0f) + 1.0f) * 0.6f; // two second animation
progress = progress > 1.0f ? 1.0f : progress;
screen.alpha = progress * 255.0f;
float step = (current_time / 200.0f) + (y / 10.0f);
float x_offset = (sinf(step) * (cosf(step) * 50.0f)) * (1.0f - progress);
Mat3 transform = Mat3::identity();
transform *= Mat3::translation(Vec2(256, 156)); // offset to middle of world
transform *= Mat3::translation(Vec2(x_offset, 0)); // apply dream effect wave
transform *= Mat3::translation(Vec2(-80, -60)); // transform to centre of framebuffer
return transform;
};
std::function<Mat3(uint8_t)> rotozoom = [](uint8_t y) -> Mat3 {
float progress = (sinf(current_time / 2000.0f) + 1.0f) / 2.0f; // two second animation
float angle = (1.0f - progress) * 360.0f;
float scale = progress;
Mat3 transform = Mat3::identity();
transform *= Mat3::translation(Vec2(256, 156)); // offset to middle of world
transform *= Mat3::rotation(deg2rad(angle)); // apply dream effect wave
transform *= Mat3::scale(Vec2(scale, scale)); // apply dream effect wave
transform *= Mat3::translation(Vec2(-80, -60)); // transform to centre of framebuffer
return transform;
};
std::function<Mat3(uint8_t)> zoom = [](uint8_t y) -> Mat3 {
float progress = (sinf(current_time / 1000.0f) + 1.0f) / 2.0f; // two second animation
float scale = progress;
Mat3 transform = Mat3::identity();
transform *= Mat3::translation(Vec2(256, 156)); // offset to middle of world
transform *= Mat3::scale(Vec2(scale, scale)); // apply dream effect wave
transform *= Mat3::translation(Vec2(-80, -60)); // transform to centre of framebuffer
return transform;
};
std::function<Mat3(uint8_t)> perspective = [](uint8_t y) -> Mat3 {
float progress = (sinf(current_time / 2000.0f) + 1.0f) / 2.0f; // two second animation
progress = progress > 1.0f ? 1.0f : progress;
screen.alpha = y + (255 - 120);
float scale = y / 30.0f;
Mat3 transform = Mat3::identity();
transform *= Mat3::translation(Vec2(156, 130 + progress * 80.0f)); // offset to middle of world
transform *= Mat3::scale(Vec2(1.0f / scale, 1.0f / scale)); // apply dream effect wave
transform *= Mat3::translation(Vec2(-80, -60)); // transform to centre of framebuffer
return transform;
};
std::function<Mat3(uint8_t)> water = [](uint8_t y) -> Mat3 {
float step = (current_time / 200.0f) + (y / 10.0f);
float x_offset = (sinf(step) + sinf(step / 3.0f) + sinf(step * 2.0f)) * 2.0f;
Mat3 transform = Mat3::identity();
transform *= Mat3::translation(Vec2(156, 130)); // offset to middle of world
transform *= Mat3::translation(Vec2(x_offset, 0)); // apply dream effect wave
transform *= Mat3::translation(Vec2(-80, -60)); // transform to centre of framebuffer
return transform;
};
std::function<Mat3(uint8_t)> warp = [](uint8_t y) -> Mat3 {
float step = (current_time / 1000.0f) + (y / 100.0f);
float x_offset = (sinf(step) * (cosf(step) * 50.0f));
float angle = sinf(current_time / 500.0f) * 50.0f;
Mat3 transform = Mat3::identity();
transform *= Mat3::translation(Vec2(140, 140)); // offset to middle of world
transform *= Mat3::translation(Vec2(x_offset, 0)); // apply dream effect wave
transform *= Mat3::rotation(deg2rad(angle)); // apply dream effect wave
transform *= Mat3::translation(Vec2(-80, -60)); // transform to centre of framebuffer
return transform;
};
std::function<Mat3(uint8_t)> ripple = [](uint8_t y) -> Mat3 {
float step = (current_time / 250.0f) + (y / 25.0f);
float scale = (sinf(step) / 4.0f) + 1.0f;
Mat3 transform = Mat3::identity();
transform *= Mat3::translation(Vec2(256, 156)); // offset to middle of world
transform *= Mat3::scale(Vec2(scale, scale)); // apply dream effect wave
transform *= Mat3::translation(Vec2(-80, -60)); // transform to centre of framebuffer
return transform;
};
std::function<Mat3(uint8_t)> betamax = [](uint8_t y) -> Mat3 {
float step = (current_time / 250.0f) + (y / 25.0f);
int8_t scale = int8_t((sinf(step) + 1.0f) * 5);
Point shake((blit::random() % scale) - scale / 2, (blit::random() % scale) - scale / 2);
Mat3 transform = Mat3::identity();
transform *= Mat3::translation(Vec2(256 + shake.x, 156 + shake.y)); // offset to middle of world
transform *= Mat3::translation(Vec2(-80, -60)); // transform to centre of framebuffer
return transform;
};
std::function<Mat3(uint8_t)> shake = [](uint8_t y) -> Mat3 {
static uint32_t last_time = 0;
static Point shake(0, 0);
if (current_time != last_time) {
last_time = current_time;
uint8_t clamp = 20;
shake = Point(blit::random() % clamp, blit::random() % clamp);
float scale = sinf(current_time / 300.0f);
scale = scale < 0.0f ? 0.0f : scale;
shake *= scale;
}
Mat3 transform = Mat3::identity();
transform *= Mat3::translation(Vec2(256 + shake.x, 156 + shake.y)); // offset to middle of world
transform *= Mat3::translation(Vec2(-80, -60)); // transform to centre of framebuffer
return transform;
};
std::function<Mat3(uint8_t)> effect_callbacks[]{
zoom,
dream,
ripple,
rotozoom,
warp,
perspective,
water,
betamax,
shake
};
std::vector<std::string> effect_names = {
"zoom",
"dream",
"ripple",
"rotozoom",
"warp",
"perspective",
"water",
"betamax",
"shake"
};
uint8_t effect = 0;
void render(uint32_t time_ms) {
current_time = time_ms;
screen.alpha = 255;
screen.pen = Pen(39, 39, 54);
screen.clear();
screen.alpha = 255;
screen.mask = nullptr;
uint32_t ms_start = now();
environment->draw(&screen, Rect(0, 0, 160, 120), effect_callbacks[effect]);
screen.alpha = 255;
for (auto i = 0; i < effect_names.size(); i++) {
if (effect == i)
screen.pen = Pen(255, 255, 255);
else
screen.pen = Pen(255, 255, 255, 100);
screen.text(effect_names[i], minimal_font, Rect(2, 2 + (i * 10), 100, 10));
}
uint32_t ms_end = now();
/*
// 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(ms_end - ms_start);
screen.text(fms, minimal_font, Rect(3, 120 - 9, 10, 16));
int block_size = 4;
for (int i = 0; i < (ms_end - ms_start); 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));
}
*/
screen.watermark();
}
uint32_t last_buttons = 0;
void update(uint32_t time) {
if (buttons != last_buttons) {
if (pressed(Button::DPAD_DOWN)) {
effect = effect == effect_names.size() - 1 ? 0 : effect + 1;
}
if (pressed(Button::DPAD_UP)) {
effect = effect == 0 ? effect_names.size() - 1 : effect - 1;
}
}
last_buttons = buttons;
}