blob: 8ef1917d2f98158834fb6facbd847d2a526960a5 [file] [log] [blame] [edit]
#include <string>
#include <memory>
#include <cstdlib>
#include <array>
#include "tunnel.hpp"
#include "assets.hpp"
using namespace blit;
const uint16_t screen_width = 160;
const uint16_t screen_height = 120;
Surface *ss_ship = Surface::load(packed_data_ship);
/* setup */
void init() {
screen.alpha = 255;
screen.mask = nullptr;
screen.pen = Pen(0, 0, 0, 0);
screen.clear();
screen.sprites = Surface::load(packed_data);
}
void tunnel_test(uint32_t time_ms) {
Point mipmap_offset[5] = {
Point(0, 0),
Point(128, 0),
Point(128, 64),
Point(128, 96),
Point(128, 112)
};
uint8_t mipmap_size[5] = {
128,
64,
32,
16,
8
};
float x = time_ms / 1000.0;
float y = 1.0;
for (int scanline = 0; scanline < screen.bounds.w; scanline++) {
float z = 3.0; // Distance from our imaginary wall plane
z += sinf((time_ms + scanline) / 1000.0f);
y = sinf((time_ms + scanline) / 200.0f);
int offset = scanline;
int wall_height = screen.bounds.h / z;
int wall_offset_top = (screen.bounds.h - wall_height) / 2;
float wall_offset = y * (wall_height / 4.0f);
wall_offset_top -= wall_offset;
int mipmap_index = 0;
if (wall_height <= 8) {
mipmap_index = 4;
}
if (wall_height <= 16) {
mipmap_index = 3;
}
if (wall_height <= 32) {
mipmap_index = 2;
}
if (wall_height <= 64) {
mipmap_index = 1;
}
Point texture_origin = mipmap_offset[mipmap_index];
uint8_t texture_size = mipmap_size[mipmap_index];
for (int wall_y = 0; wall_y < wall_height; wall_y++) {
Vec2 uv(
(float(scanline) / wall_height) + x,
(float(wall_y) / wall_height)
);
uv.x -= floorf(uv.x);
uv.y -= floorf(uv.y);
uint8_t *fragment_c = screen.sprites->ptr(Point(
texture_origin.x + (uv.x * texture_size),
texture_origin.y + (uv.y * texture_size)
));
screen.pen = screen.sprites->palette[*fragment_c];
screen.alpha = 255;
screen.pixel(Point(
scanline,
wall_offset_top + wall_y
));
}
for (int ceil_y = 0; ceil_y < wall_offset_top; ceil_y++) {
float distance = (float)screen.bounds.h / (2.0f * (screen.bounds.h - ceil_y - wall_offset) - screen.bounds.h);
float weight = distance / z;
float t_size = float(screen.bounds.h) / distance;
int mipmap_index = 0;
if (t_size <= 8) {
mipmap_index = 4;
}
if (t_size <= 16) {
mipmap_index = 3;
}
if (t_size <= 32) {
mipmap_index = 2;
}
if (t_size <= 64) {
mipmap_index = 1;
}
Point texture_origin = mipmap_offset[mipmap_index];
uint8_t texture_size = mipmap_size[mipmap_index];
Vec2 uv(
(float(scanline) / wall_height) + x,
0.5
);
uv.x = uv.x * weight;
uv.x += x * (1.0f - weight);
uv.y = uv.y * weight;
uv.y += z * (1.0f - weight);
uv.x -= floorf(uv.x);
uv.y -= floorf(uv.y);
uint8_t *fragment_c = screen.sprites->ptr(Point(
texture_origin.x + (uv.x * texture_size),
texture_origin.y + (uv.y * texture_size)
));
screen.pen = screen.sprites->palette[*fragment_c];
screen.alpha = 200;
screen.pixel(Point(scanline, ceil_y));
}
for (int floor_y = wall_offset_top + wall_height; floor_y < screen.bounds.h; floor_y++) {
float distance = (float)screen.bounds.h / (2.0f * (floor_y + wall_offset) - screen.bounds.h);
float weight = distance / z;
float t_size = float(screen.bounds.h) / distance;
int mipmap_index = 0;
if (t_size <= 8) {
mipmap_index = 4;
}
if (t_size <= 16) {
mipmap_index = 3;
}
if (t_size <= 32) {
mipmap_index = 2;
}
if (t_size <= 64) {
mipmap_index = 1;
}
Point texture_origin = mipmap_offset[mipmap_index];
uint8_t texture_size = mipmap_size[mipmap_index];
Vec2 uv(
(float(scanline) / wall_height) + x,
0.1f
);
uv.x = uv.x * weight;
uv.x += x * (1.0f - weight);
uv.y = uv.y * weight;
uv.y += z * (1.0f - weight);
uv.x -= floorf(uv.x);
uv.y -= floorf(uv.y);
uint8_t *fragment_c = screen.sprites->ptr(Point(
texture_origin.x + (uv.x * texture_size),
texture_origin.y + (uv.y * texture_size)
));
screen.pen = screen.sprites->palette[*fragment_c];
screen.alpha = 200;
screen.pixel(Point(scanline, floor_y));
}
}
}
void tunnel_test1(uint8_t time_ms) {
int max_stripe_height = (screen.bounds.h / 3);
int min_stripe_height = 40;
for (int scanline = 0; scanline < screen.bounds.w; scanline++) {
screen.alpha = 255;
int offset = scanline * 2;
//float time_offset = (time_ms + offset) / 100.0f;
float x = (sinf(float(time_ms + offset) / 1000.0f) + 1.0f) / 2.0f;
float y = (sinf(float(time_ms + offset + 1000) / 2000.0f) + 1.0f) / 2.0f;
float stripe_height = min_stripe_height + max_stripe_height * y;
float stripe_offset_top = (screen.bounds.h / 4) * x;
float t_scale = float(min_stripe_height + max_stripe_height) / stripe_height;
/*screen.pen = rgba(255, 200, 200);
screen.line(
point(scanline, stripe_offset_top),
point(scanline, stripe_offset_top + stripe_height)
);*/
Vec2 c(((scanline * t_scale) + (time_ms / 5.0f)), 0);
screen.stretch_blit_vspan(screen.sprites, Point(int(c.x) % 128, int(c.y) % 128), 128, Point(scanline, stripe_offset_top), stripe_height);
for (int f = 0; f < screen.bounds.h - stripe_height - stripe_offset_top - 1; f++) {
float distance = (float)(screen.bounds.h - stripe_height - stripe_offset_top - 1) / f;
c.y = distance * stripe_height;
/*while (c.y < 0) {
c.y = 127 - c.y;
}
while (c.y > 127) {
c.y -= 127;
}*/
c.x -= (scanline - (screen.bounds.w / 2)) / 200.0f;
/*while (c.x < 0) {
c.x = 127 - c.x;
}
while (c.x > 127) {
c.x -= 127;
}*/
uint8_t *fragment_c = screen.sprites->ptr(int(c.x) % 128, int(c.y) % 128);
screen.pen = screen.sprites->palette[*fragment_c];
screen.alpha = 200;
screen.pixel(Point(scanline, (stripe_offset_top + stripe_height) + f - 1));
}
}
}
void render(uint32_t time_ms) {
uint32_t ms_start = now();
screen.pen = Pen(0, 0, 0, 255);
screen.clear();
tunnel_test(time_ms);
screen.alpha = 255;
int x = 20 + (sinf(time_ms / 1000.0f) * 10.0f);
int y = 40 + (sinf(time_ms / 1500.0f) * 30.0f);
screen.blit(ss_ship, Rect(0, 0, 64, 32), Point(x, y));
uint32_t ms_end = now();
screen.mask = nullptr;
screen.pen = Pen(255, 0, 0);
for (uint32_t i = 0; i < (ms_end - ms_start); i++) {
screen.pen = Pen(i * 5, 255 - (i * 5), 0);
screen.rectangle(Rect(i * 3 + 1, screen.bounds.h - 3, 2, 2));
}
}
void update(uint32_t time) {
}