326 lines
9.1 KiB
C++
326 lines
9.1 KiB
C++
#define __BSD_VISIBLE 1
|
|
#include <gint/display.h>
|
|
#include <gint/keyboard.h>
|
|
#include <gint/defs/util.h>
|
|
#include <gint/gint.h>
|
|
#include <azur/gint/render.h>
|
|
#include <math.h>
|
|
#include <libprof.h>
|
|
#include "azuray.h"
|
|
|
|
/* Map data as produced by the fxconv converter. */
|
|
typedef struct {
|
|
u16 width, height;
|
|
u8 *cells;
|
|
} map_asset_t;
|
|
|
|
extern map_asset_t const map_1;
|
|
|
|
struct MapInstance: public azuray::Map
|
|
{
|
|
using Texture = azuray::Texture;
|
|
map_asset_t const *M;
|
|
|
|
MapInstance(map_asset_t const *M_init):
|
|
Map(M_init->width, M_init->height), M {M_init}
|
|
{
|
|
/* Generate walls from blocks */
|
|
for(uint z = 0; z < this->height; z++) {
|
|
for(uint x = 0; x <= this->width; x++) {
|
|
Texture t;
|
|
if(isCellSolid(x-1, z) || isCellSolid(x, z))
|
|
t = _blockTexture();
|
|
setXWall(x, z, t, t);
|
|
}
|
|
}
|
|
for(uint z = 0; z <= this->height; z++) {
|
|
for(uint x = 0; x < this->width; x++) {
|
|
Texture t;
|
|
if(isCellSolid(x, z-1) || isCellSolid(x, z))
|
|
t = _blockTexture();
|
|
setZWall(x, z, t, t);
|
|
}
|
|
}
|
|
|
|
/* Add a few transparent "gates" for testing */
|
|
Texture gate = _gateTexture();
|
|
for(uint z = 0; z < this->height; z++) {
|
|
if(_walkable(0, z))
|
|
setXWall(1, z, gate, gate);
|
|
if(_walkable(this->width-1, z)) {
|
|
setXWall(this->width - 1, z, gate, gate);
|
|
setXWall(this->width, z, gate, gate);
|
|
}
|
|
}
|
|
setXWall(6, 5, gate, gate);
|
|
}
|
|
|
|
|
|
/* Generate a random texture for the side of a block. */
|
|
Texture _blockTexture()
|
|
{
|
|
/* Select tile #0, #1, #6 or #7 semi-randomly */
|
|
static int dist[] = { 0, 0, 0, 1, 1, 1, 6, 7 };
|
|
int tile_no = dist[rand() % 8];
|
|
|
|
Texture t;
|
|
t.type = Texture::TypeImage;
|
|
t.combining = false;
|
|
t.imageIndex = tile_no;
|
|
return t;
|
|
}
|
|
/* Partially-transparent gate sprite texture. */
|
|
Texture _gateTexture()
|
|
{
|
|
Texture t;
|
|
t.type = Texture::TypeImage;
|
|
t.combining = true;
|
|
t.imageIndex = 3;
|
|
return t;
|
|
}
|
|
|
|
/*** Physics ***/
|
|
|
|
bool _walkable(uint x, uint z)
|
|
{
|
|
/* Lines are top-down in the asset but bottom-up in coordinates */
|
|
z = M->height - z - 1;
|
|
return x < M->width && z < M->height && !M->cells[z * M->width + x];
|
|
}
|
|
|
|
bool isXWallSolid(uint x, uint z, bool) override
|
|
{
|
|
return !_walkable(x-1, z) || !_walkable(x, z);
|
|
}
|
|
bool isZWallSolid(uint x, uint z, bool) override
|
|
{
|
|
return !_walkable(x, z-1) || !_walkable(x, z);
|
|
}
|
|
bool isCellSolid(uint x, uint z) override
|
|
{
|
|
return x < width && z < height && !_walkable(x, z);
|
|
}
|
|
|
|
};
|
|
|
|
static num num_cos_dl(num a)
|
|
{
|
|
num u = 1.0;
|
|
int p = 7;
|
|
for(p = 2 * p - 1; p >= 1; p -= 2)
|
|
u = num(1) - a * a / (p * p + p) * u;
|
|
return u;
|
|
}
|
|
|
|
num num_cos(num a)
|
|
{
|
|
if(a < 0) a = -a;
|
|
a = a % num(6.28319);
|
|
if(a > num(3.14159)) a -= num(6.28319);
|
|
return num_cos_dl(a);
|
|
}
|
|
|
|
num num_sin(num a)
|
|
{
|
|
return num_cos(a - num(1.57080));
|
|
}
|
|
|
|
#define RGB24(HEX) \
|
|
(((HEX >> 8) & 0xf800) | \
|
|
((HEX >> 5) & 0x07e0) | \
|
|
((HEX >> 3) & 0x001f))
|
|
|
|
std::unique_ptr<azuray::ImageBank> setupImageBank()
|
|
{
|
|
/* Load textures from the tileset into the texture bank */
|
|
extern image_t const img_tileset;
|
|
int texCount = img_tileset.height / 16;
|
|
|
|
auto IB = azuray::mkImageBank(texCount, 16, img_tileset.palette);
|
|
if(!IB)
|
|
return IB;
|
|
|
|
for(int i = 0; i < texCount; i++) {
|
|
image_t sub;
|
|
image_sub(&img_tileset, 0, 16*i, 16, 16, &sub);
|
|
IB->loadImage(i, &sub);
|
|
}
|
|
return IB;
|
|
}
|
|
|
|
int main(void)
|
|
{
|
|
prof_init();
|
|
azrp_config_scale(1);
|
|
|
|
vec3 pos(4.5, 0.5, 3.5);
|
|
vec3 dir;
|
|
num angle = 0;
|
|
|
|
bool infoview = false;
|
|
bool freeze_infoview = false;
|
|
|
|
num depth = azuray::depthForFOV(100_n);
|
|
|
|
int render_us_prev_frame = 0;
|
|
azuray::PerfInfo perf_prev_frame {};
|
|
|
|
MapInstance MI(&map_1);
|
|
auto IB = setupImageBank();
|
|
|
|
while(1) {
|
|
dir = vec3(num_cos(angle), 0, -num_sin(angle));
|
|
|
|
/*** Rendering ***/
|
|
|
|
azuray::perf_reset();
|
|
prof_t perf_render = prof_make();
|
|
prof_enter(perf_render);
|
|
|
|
int bg = C_RGB(0, 0, 0);
|
|
int floor1 = C_RGB(10, 6, 3);
|
|
int floor2 = C_RGB(12, 8, 2);
|
|
azrp_clear(bg);
|
|
azuray::draw_floor(MI, pos, dir, depth, floor1, floor2);
|
|
azuray::draw_walls(MI, *IB, pos, dir, depth);
|
|
|
|
if(render_us_prev_frame > 0) {
|
|
int color = C_WHITE;
|
|
if(render_us_prev_frame > 33000)
|
|
color = C_RGB(31, 20, 0);
|
|
if(render_us_prev_frame > 50000)
|
|
color = C_RED;
|
|
azrp_print_opt(DWIDTH/2, 1, NULL, color, DTEXT_CENTER,
|
|
DTEXT_TOP, "%d ms (%d FPS)",
|
|
render_us_prev_frame,
|
|
1000000 / render_us_prev_frame);
|
|
}
|
|
if(infoview) {
|
|
char str[32];
|
|
pos.x.strToBuffer(str);
|
|
azrp_print_opt(1, 1, NULL, C_WHITE, DTEXT_LEFT, DTEXT_TOP,
|
|
"x: %.8s", str);
|
|
pos.z.strToBuffer(str);
|
|
azrp_print_opt(1, 11, NULL, C_WHITE, DTEXT_LEFT, DTEXT_TOP,
|
|
"z: %.8s", str);
|
|
angle.strToBuffer(str);
|
|
azrp_print_opt(1, 21, NULL, C_WHITE, DTEXT_LEFT, DTEXT_TOP,
|
|
"angle: %.8s", str);
|
|
|
|
static int colors[] = {
|
|
RGB24(0x264653),
|
|
RGB24(0x2a9d8f),
|
|
RGB24(0xe9c46a),
|
|
RGB24(0xf4a261),
|
|
RGB24(0xe76f51),
|
|
};
|
|
static char const * const desc[] = {
|
|
"Raycast",
|
|
"Render walls",
|
|
"Bound floor",
|
|
"Render floor",
|
|
};
|
|
|
|
if(render_us_prev_frame > 0) {
|
|
int times[4];
|
|
times[0] = prof_time(perf_prev_frame.time_raycast);
|
|
times[1] = prof_time(perf_prev_frame.time_shader_walls);
|
|
times[2] = prof_time(perf_prev_frame.time_floor_y);
|
|
times[3] = prof_time(perf_prev_frame.time_floor_x);
|
|
/* Remove floor_x from floor_y */
|
|
times[2] -= times[3];
|
|
|
|
int fields[4], w = 120;
|
|
for(int i = 0; i < 4; i++)
|
|
fields[i] = times[i] * w / render_us_prev_frame;
|
|
|
|
int x = DWIDTH - w - 5, y = 4, h = 8;
|
|
azrp_rect(x, y, w, h, C_RGB(15, 15, 15));
|
|
|
|
for(int i = 0; i < 4; i++) {
|
|
azrp_rect(x, y, fields[i], h, colors[i]);
|
|
azrp_print_opt(x+fields[i]/2, y+h+1, NULL, C_WHITE,
|
|
DTEXT_CENTER, DTEXT_TOP, "%d", (times[i]+500) / 1000);
|
|
x += fields[i];
|
|
}
|
|
|
|
y += h+12;
|
|
x = DWIDTH-12;
|
|
for(int i = 0; i < 4; i++) {
|
|
azrp_rect(x, y+1, 7, 7, colors[i]);
|
|
azrp_text_opt(x-4, y, NULL, C_WHITE, DTEXT_RIGHT,
|
|
DTEXT_TOP, desc[i], -1);
|
|
y += 11;
|
|
}
|
|
if(freeze_infoview) {
|
|
azrp_print_opt(DWIDTH-1, y, NULL, 0x5555, DTEXT_RIGHT,
|
|
DTEXT_TOP, "S-VARS: unfreeze");
|
|
}
|
|
}
|
|
}
|
|
azrp_update();
|
|
|
|
prof_leave(perf_render);
|
|
if(!freeze_infoview) {
|
|
render_us_prev_frame = prof_time(perf_render);
|
|
perf_prev_frame = azuray::perf_get();
|
|
}
|
|
|
|
/*** Input ***/
|
|
|
|
cleareventflips();
|
|
clearevents();
|
|
|
|
vec3 move_dir = {0, 0, 0};
|
|
|
|
if(keydown(KEY_F2))
|
|
move_dir += vec3(dir.z, 0, -dir.x);
|
|
if(keydown(KEY_F1))
|
|
move_dir += -vec3(dir.z, 0, -dir.x);
|
|
if(keydown(KEY_UP))
|
|
move_dir += dir;
|
|
if(keydown(KEY_DOWN))
|
|
move_dir += -dir;
|
|
if(keydown(KEY_RIGHT))
|
|
angle = (angle + .1_n) % 6.28319_n;
|
|
if(keydown(KEY_LEFT))
|
|
angle = (angle - .1_n + 6.28319_n) % 6.28319_n;
|
|
if(keydown(KEY_PLUS))
|
|
pos.y = min(pos.y + .1_n, 1_n);
|
|
if(keydown(KEY_MINUS))
|
|
pos.y = max(pos.y - .1_n, 0_n);
|
|
|
|
if(keypressed(KEY_MENU))
|
|
gint_osmenu();
|
|
if(keypressed(KEY_EXIT))
|
|
break;
|
|
if(keypressed(KEY_VARS) && !keydown(KEY_SHIFT))
|
|
infoview = !infoview;
|
|
if(keypressed(KEY_VARS) && keydown(KEY_SHIFT))
|
|
freeze_infoview = !freeze_infoview;
|
|
if(keypressed(KEY_F4)) {
|
|
pos.x = 2.550979_n;
|
|
pos.z = 3.719253_n;
|
|
angle = -0.29986_n;
|
|
}
|
|
if(keypressed(KEY_F5)) {
|
|
pos.x = 5.513748_n;
|
|
pos.z = 5.348083_n;
|
|
angle = 0_n;
|
|
}
|
|
if(keypressed(KEY_F6)) {
|
|
pos.x = 2.489120_n;
|
|
pos.z = 3.642013_n;
|
|
angle = -2.59976_n;
|
|
}
|
|
|
|
/*** Physics ***/
|
|
|
|
num speed = 0.1;
|
|
if(move_dir.x != 0 || move_dir.z != 0)
|
|
pos = azuray::physics_move(MI, pos, move_dir, speed);
|
|
}
|
|
|
|
return 0;
|
|
}
|