Compare commits
3 Commits
08411fc90c
...
4b835efb83
Author | SHA1 | Date |
---|---|---|
Lephenixnoir | 4b835efb83 | |
Lephenixnoir | 0b99ee6a38 | |
Lephenixnoir | b6fb44c80a |
|
@ -28,6 +28,7 @@ set(ASSETS
|
|||
assets-cg/bosonx_logo_empty.png
|
||||
assets-cg/lepheyatis_logo.png
|
||||
assets-cg/font_boson.png
|
||||
assets-cg/font_energy.png
|
||||
assets-cg/erik_running.gif
|
||||
assets-cg/erik_jumping.gif
|
||||
assets-cg/stages/stage1.png
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 789 B |
|
@ -33,6 +33,11 @@ font_boson.png:
|
|||
proportional: true
|
||||
height: 9
|
||||
|
||||
font_energy.png:
|
||||
type: bopti-image
|
||||
name: img_font_energy
|
||||
profile: p8_rgb565a
|
||||
|
||||
*.gif:
|
||||
custom-type: animation
|
||||
name_regex: (.*)\.gif anim_\1
|
||||
|
|
15
src/game.cpp
15
src/game.cpp
|
@ -154,19 +154,18 @@ num game_height_at(struct game *game, num z, int face)
|
|||
: -KILL_PLANE_RADIUS;
|
||||
}
|
||||
|
||||
#if 0
|
||||
bool game_player_above_platform(struct game *game, num height)
|
||||
const struct platform *game_platform_under_player(struct game const *game,
|
||||
struct player const *player)
|
||||
{
|
||||
struct player const *player = &game->player;
|
||||
if(player->stance != player::Running)
|
||||
return NULL;
|
||||
|
||||
for(auto const &p: game->level.platform_buffer) {
|
||||
if(player->platform == p.face
|
||||
&& player->z >= p.z && player->z <= p.z + p.length
|
||||
&& height >= space_platform_height(p.height)) {
|
||||
return true;
|
||||
&& player->z >= p.z && player->z <= p.z + p.length) {
|
||||
return &p;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
|
18
src/game.h
18
src/game.h
|
@ -6,6 +6,7 @@
|
|||
#include "level.h"
|
||||
|
||||
#include <gint/display.h>
|
||||
#include <libprof.h>
|
||||
|
||||
/* A player's movement and data information. */
|
||||
struct player
|
||||
|
@ -67,7 +68,10 @@ struct player
|
|||
|
||||
//======= Data =======//
|
||||
|
||||
/* TODO: Energy -> speed multiplier, skin, others? */
|
||||
/* Energy collected, in percent */
|
||||
num energy_percent;
|
||||
|
||||
/* TODO: Skin, others? */
|
||||
};
|
||||
|
||||
/* Dynamic information about one or multiple attempts at a single level. */
|
||||
|
@ -85,6 +89,10 @@ struct game
|
|||
struct {
|
||||
bool footer; /* Show performance footer */
|
||||
} debug;
|
||||
|
||||
struct {
|
||||
prof_t effect_bpp;
|
||||
} perf;
|
||||
};
|
||||
|
||||
//======= Functions on the game world space =======//
|
||||
|
@ -116,10 +124,8 @@ void game_advance(struct game *game);
|
|||
/* Get platform height at the provided position. */
|
||||
num game_height_at(struct game *game, num z, int face);
|
||||
|
||||
#if 0
|
||||
/* Check if the player would be standing over a platform with the provided
|
||||
height coordinate. This ignores player's height value. */
|
||||
bool game_player_above_platform(struct game *game, num height);
|
||||
#endif
|
||||
/* Returns the platform on which the player is running, if any. */
|
||||
const struct platform *game_platform_under_player(struct game const *game,
|
||||
struct player const *player);
|
||||
|
||||
#endif /* __GAME_H__ */
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
#include <stdlib.h>
|
||||
|
||||
/* Geometric parameters */
|
||||
#define G_PLATFORM_LEN num(3.0)
|
||||
#define G_PLATFORM_LEN num(2.5)
|
||||
#define G_PLATFORM_SPC num(0.5)
|
||||
#define G_PLATFORM_LEN_INITIAL num(6.0)
|
||||
/* Probabilities */
|
||||
|
@ -39,7 +39,8 @@ AcceleronGenerator::AcceleronGenerator():
|
|||
....R..... [h=8]
|
||||
....|.....
|
||||
....|.....
|
||||
...B|..... [h=5]
|
||||
....|.....
|
||||
...B...... [h=5]
|
||||
...|.#.... [h=4]
|
||||
...|.|....
|
||||
....#..... [h=1]
|
||||
|
@ -90,22 +91,23 @@ static num generate_ascending_funnel(struct level *level, num z)
|
|||
p.length = G_PLATFORM_LEN * 3;
|
||||
p.height = 8;
|
||||
level->platform_buffer.push_back(p);
|
||||
z += G_PLATFORM_LEN * 3 + G_PLATFORM_SPC;
|
||||
|
||||
p.type = PLATFORM_BLUE;
|
||||
p.face = 3;
|
||||
p.z = z + G_PLATFORM_LEN * 2;
|
||||
p.z = z;
|
||||
p.length = G_PLATFORM_LEN * 3;
|
||||
p.height = 5;
|
||||
level->platform_buffer.push_back(p);
|
||||
|
||||
p.type = PLATFORM_WHITE;
|
||||
p.face = 5;
|
||||
p.z = z + G_PLATFORM_LEN * 3;
|
||||
p.z = z + G_PLATFORM_LEN;
|
||||
p.length = G_PLATFORM_LEN * 2;
|
||||
p.height = 4;
|
||||
level->platform_buffer.push_back(p);
|
||||
|
||||
z += G_PLATFORM_LEN * 5 + G_PLATFORM_SPC;
|
||||
z += G_PLATFORM_LEN * 3 + G_PLATFORM_SPC;
|
||||
|
||||
/* Exit platform */
|
||||
p.type = PLATFORM_WHITE;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include "level.h"
|
||||
#include "generator.h"
|
||||
#include "util.h"
|
||||
#include <gint/display.h>
|
||||
|
||||
struct level level_create(int level)
|
||||
|
@ -7,14 +8,18 @@ struct level level_create(int level)
|
|||
struct level l;
|
||||
|
||||
switch(level) {
|
||||
default:
|
||||
l.gen = std::make_unique<struct gen1>();
|
||||
l.bgcolor = RGB24(0x49759f);
|
||||
break;
|
||||
case 2:
|
||||
l.gen = std::make_unique<AcceleronGenerator>();
|
||||
l.bgcolor = RGB24(0xe7c272);
|
||||
break;
|
||||
case 3:
|
||||
l.gen = std::make_unique<struct gen3>();
|
||||
l.bgcolor = C_WHITE;
|
||||
break;
|
||||
default:
|
||||
l.gen = std::make_unique<struct gen1>();
|
||||
}
|
||||
return l;
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@ struct Generator;
|
|||
struct level {
|
||||
std::vector<struct platform> platform_buffer;
|
||||
std::unique_ptr<Generator> gen;
|
||||
uint16_t bgcolor;
|
||||
};
|
||||
|
||||
|
||||
|
|
45
src/main.cpp
45
src/main.cpp
|
@ -39,6 +39,7 @@ int play_level(int level_id)
|
|||
player->height = 1.0;
|
||||
player->vheight = 0.0;
|
||||
player->frame = 0;
|
||||
player->energy_percent = 0.0;
|
||||
|
||||
/* FPS regulation setup */
|
||||
int volatile need_frame = 1;
|
||||
|
@ -56,6 +57,8 @@ int play_level(int level_id)
|
|||
camera->platform,
|
||||
str(camera->angle_vector));
|
||||
|
||||
image_t *effect_bpp = NULL;
|
||||
|
||||
bool game_run = true;
|
||||
while(game_run) {
|
||||
while(!need_frame) sleep();
|
||||
|
@ -67,14 +70,18 @@ int play_level(int level_id)
|
|||
game.t += dt;
|
||||
prof_t perf_frame = prof_make();
|
||||
prof_enter_norec(perf_frame);
|
||||
game.perf.effect_bpp = prof_make();
|
||||
|
||||
level_update(&game.level, player->z);
|
||||
camera_track(camera, player);
|
||||
|
||||
struct platform const *standing_on = game_platform_under_player(&game,
|
||||
&game.player);
|
||||
|
||||
//======= Rendering =======//
|
||||
|
||||
azrp_perf_clear();
|
||||
azrp_clear(RGB24(0x49759f));
|
||||
azrp_clear(game.level.bgcolor);
|
||||
|
||||
prof_t perf_comp = prof_make();
|
||||
prof_enter_norec(perf_comp);
|
||||
|
@ -82,7 +89,7 @@ int play_level(int level_id)
|
|||
for(auto it = game.level.platform_buffer.rbegin();
|
||||
it != game.level.platform_buffer.rend();
|
||||
++it) {
|
||||
int color = camera_platform_color(&game.camera, it->face);
|
||||
int color = render_platform_color(&*it, &game.camera, game.t);
|
||||
struct prect p = space_platform_position(&*it);
|
||||
|
||||
/* Near plane clipping */
|
||||
|
@ -104,6 +111,21 @@ int play_level(int level_id)
|
|||
render_anim_frame((int)player_dot.x, (int)player_dot.y,
|
||||
player_anim, player_frame);
|
||||
|
||||
if(standing_on && standing_on->type == PLATFORM_BLUE) {
|
||||
prof_enter(game.perf.effect_bpp);
|
||||
render_effect_bpp(&effect_bpp, game.t);
|
||||
azrp_image((int)player_dot.x - effect_bpp->width / 2,
|
||||
(int)player_dot.y - effect_bpp->height + 2,
|
||||
effect_bpp);
|
||||
prof_leave(game.perf.effect_bpp);
|
||||
}
|
||||
|
||||
/* Render energy score */
|
||||
char energy_str[32];
|
||||
sprintf(energy_str, "%.2f%%", (float)player->energy_percent);
|
||||
azrp_rect(DWIDTH-100, 4, 96, 20, AZRP_RECT_DARKEN);
|
||||
render_energy_str(DWIDTH-8, 8, DTEXT_RIGHT, energy_str);
|
||||
|
||||
prof_leave_norec(perf_comp);
|
||||
azrp_update();
|
||||
|
||||
|
@ -173,7 +195,8 @@ int play_level(int level_id)
|
|||
|
||||
//======= Simulation =======//
|
||||
|
||||
player->z += player->vz * dt;
|
||||
num vz = player->vz * (num(1) + player->energy_percent / 200);
|
||||
player->z += vz * dt;
|
||||
player->height += player->vheight * dt;
|
||||
|
||||
/* Apply gravity */
|
||||
|
@ -203,7 +226,7 @@ int play_level(int level_id)
|
|||
&& player->jump_t > TIME_JUMP_THRUST_MIN
|
||||
&& !keydown(player->jump_key)) {
|
||||
player->stance = player::Falling;
|
||||
player->vheight = 0.0;
|
||||
player->vheight = -1;
|
||||
}
|
||||
|
||||
if(player->height >= floor - STEP_HEIGHT
|
||||
|
@ -231,11 +254,18 @@ int play_level(int level_id)
|
|||
if(death_1 || death_2)
|
||||
break;
|
||||
|
||||
if(standing_on && standing_on->type == PLATFORM_BLUE) {
|
||||
player->energy_percent += dt * vz * 5.5;
|
||||
}
|
||||
|
||||
game_advance(&game);
|
||||
prof_leave_norec(perf_frame);
|
||||
last_frame_us = prof_time(perf_frame);
|
||||
}
|
||||
|
||||
if(effect_bpp)
|
||||
image_free(effect_bpp);
|
||||
|
||||
timer_stop(timer);
|
||||
return 0;
|
||||
}
|
||||
|
@ -246,6 +276,7 @@ int main(void)
|
|||
|
||||
__printf_enable_fp();
|
||||
prof_init();
|
||||
render_init();
|
||||
space_init();
|
||||
|
||||
extern font_t font_boson;
|
||||
|
@ -259,12 +290,6 @@ int main(void)
|
|||
log_init(true);
|
||||
#endif
|
||||
|
||||
azrp_config_scale(1);
|
||||
azrp_shader_clear_configure();
|
||||
azrp_shader_image_p8_configure();
|
||||
azrp_shader_image_p4_configure();
|
||||
azrp_shader_triangle_configure();
|
||||
|
||||
while (1) {
|
||||
if (menu_title() != 0) {
|
||||
gint_osmenu();
|
||||
|
|
150
src/render.cpp
150
src/render.cpp
|
@ -72,7 +72,7 @@ void camera_project_prect(struct camera *camera, struct prect *p)
|
|||
p->fr.y = -p->fr.y * far_f + half_screen.y;
|
||||
}
|
||||
|
||||
int camera_platform_color(struct camera *camera, int platform_id)
|
||||
int camera_platform_color(struct camera const *camera, int platform_id)
|
||||
{
|
||||
/* Accounting for the full angle is too precise and results in weird
|
||||
color jumps at different times across platforms, instead switch at half
|
||||
|
@ -86,6 +86,62 @@ int camera_platform_color(struct camera *camera, int platform_id)
|
|||
return C_RGB(gray, gray, gray);
|
||||
}
|
||||
|
||||
//======= Rendering tools =======//
|
||||
|
||||
static uint16_t blue_ramp[32];
|
||||
|
||||
static void split_RGB(uint32_t RGB, int *R, int *G, int *B)
|
||||
{
|
||||
*R = (RGB >> 16) & 0xff;
|
||||
*G = (RGB >> 8) & 0xff;
|
||||
*B = (RGB >> 0) & 0xff;
|
||||
}
|
||||
|
||||
static uint32_t make_RGB(int R, int G, int B)
|
||||
{
|
||||
return ((R & 0xff) << 16) | ((G & 0xff) << 8) | (B & 0xff);
|
||||
}
|
||||
|
||||
static void gradient(uint32_t RGB1, uint32_t RGB2, uint16_t *gradient, int N)
|
||||
{
|
||||
int R1, G1, B1, R2, G2, B2;
|
||||
split_RGB(RGB1, &R1, &G1, &B1);
|
||||
split_RGB(RGB2, &R2, &G2, &B2);
|
||||
|
||||
for(int i = 0; i < N; i++) {
|
||||
int R = ((N-1-i) * R1 + i * R2) / (N-1);
|
||||
int G = ((N-1-i) * G1 + i * G2) / (N-1);
|
||||
int B = ((N-1-i) * B1 + i * B2) / (N-1);
|
||||
gradient[i] = RGB24(make_RGB(R, G, B));
|
||||
}
|
||||
}
|
||||
|
||||
void render_init(void)
|
||||
{
|
||||
/* Generate a gradient ramp for blue platforms */
|
||||
gradient(0x5090d0, 0x2060b0, blue_ramp, 32);
|
||||
}
|
||||
|
||||
uint16_t render_color_blue_platform(num t)
|
||||
{
|
||||
int step = (int)(32 * t.frac()) & 31;
|
||||
int phase = (int)t & 1;
|
||||
return phase ? blue_ramp[31 - step] : blue_ramp[step];
|
||||
}
|
||||
|
||||
uint16_t render_platform_color(struct platform const *p,
|
||||
struct camera const *camera, num t)
|
||||
{
|
||||
if(p->type == PLATFORM_WHITE)
|
||||
return camera_platform_color(camera, p->face);
|
||||
if(p->type == PLATFORM_BLUE)
|
||||
return render_color_blue_platform(t);
|
||||
if(p->type == PLATFORM_RED)
|
||||
return RGB24(0xd06060);
|
||||
|
||||
return RGB24(0xff00ff);
|
||||
}
|
||||
|
||||
void render_triangle(vec3 *p1, vec3 *p2, vec3 *p3, int color)
|
||||
{
|
||||
azrp_triangle(
|
||||
|
@ -109,3 +165,95 @@ void render_anim_frame(int x, int y, struct anim *anim, int frame)
|
|||
y + anim->y_offsets[frame] - anim->y_anchor,
|
||||
anim->frames[frame]);
|
||||
}
|
||||
|
||||
static bool render_energy_str_glyph_params(int c, int *ix, int *w)
|
||||
{
|
||||
if(c >= '0' && c <= '9') {
|
||||
*ix = 13 * (c - '0') - (c >= '2' ? 3 : 0);
|
||||
*w = (c == '1') ? 8 : 11;
|
||||
return true;
|
||||
}
|
||||
if(c == '.') {
|
||||
*ix = 127;
|
||||
*w = 4;
|
||||
return true;
|
||||
}
|
||||
if(c == '%') {
|
||||
*ix = 132;
|
||||
*w = 8;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void render_energy_str(int x, int y, int halign, char const *str)
|
||||
{
|
||||
extern image_t img_font_energy;
|
||||
int ix, w;
|
||||
|
||||
/* First compute width of string */
|
||||
int total_width = 0;
|
||||
for(int i = 0; str[i]; i++) {
|
||||
if(render_energy_str_glyph_params(str[i], &ix, &w))
|
||||
total_width += w + 2;
|
||||
}
|
||||
total_width -= (total_width ? 2 : 0);
|
||||
|
||||
/* Apply horizontal alignment */
|
||||
if(halign == DTEXT_CENTER)
|
||||
x -= total_width >> 1;
|
||||
if(halign == DTEXT_RIGHT)
|
||||
x -= total_width - 1;
|
||||
|
||||
/* Render string */
|
||||
for(int i = 0; str[i]; i++) {
|
||||
if(!render_energy_str_glyph_params(str[i], &ix, &w))
|
||||
continue;
|
||||
azrp_subimage(x, y, &img_font_energy, ix, 0, w,
|
||||
img_font_energy.height, DIMAGE_NONE);
|
||||
x += w + 2;
|
||||
}
|
||||
}
|
||||
|
||||
void render_effect_bpp(image_t **image, num t)
|
||||
{
|
||||
enum { BPP_PARTICLE = 0x81 };
|
||||
static uint16_t bpp_palette[] = {
|
||||
[0] = RGB24(0xff00ff), /* alpha */
|
||||
[BPP_PARTICLE-0x80] = RGB24(0x5090d0),
|
||||
};
|
||||
static int const bpp_W = 34;
|
||||
static int const bpp_H = 68;
|
||||
|
||||
if(!*image) {
|
||||
*image = image_alloc(bpp_W, bpp_H, IMAGE_P8_RGB565A);
|
||||
image_set_palette(*image, bpp_palette, 1, false);
|
||||
}
|
||||
|
||||
image_clear(*image);
|
||||
uint8_t *pixels = (uint8_t *)(*image)->data;
|
||||
|
||||
for(int i = 0; i < 24; i++) {
|
||||
/* Particule #i appears after i 32-th of a second */
|
||||
num start = num(i) / 32;
|
||||
if(t < start)
|
||||
continue;
|
||||
num16 local_time = num16(2 * ((t - start) % num(0.5)));
|
||||
|
||||
int x0_int = (23 * i) % (bpp_W - 2);
|
||||
|
||||
num16 x0 = num16(x0_int);
|
||||
num16 y0 = num16(bpp_H - 1 - ((37 * i) & 15));
|
||||
|
||||
num16 vx = num16(bpp_W / 2 - x0_int) / 4;
|
||||
|
||||
num16 x = x0 + vx * local_time;
|
||||
num16 y = y0 - (bpp_H - 16) * local_time;
|
||||
|
||||
for(int dy = 0; dy <= 3; dy++)
|
||||
for(int dx = 0; dx <= 3; dx++) {
|
||||
pixels[((int)y + dy) * (*image)->stride + (int)x + dx] =
|
||||
BPP_PARTICLE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
22
src/render.h
22
src/render.h
|
@ -69,7 +69,20 @@ vec3 camera_project_point(struct camera *, vec3 point);
|
|||
void camera_project_prect(struct camera *, struct prect *rect);
|
||||
|
||||
/* Compute the platform's color based on the camera's angle. */
|
||||
int camera_platform_color(struct camera *camera, int platform_id);
|
||||
int camera_platform_color(struct camera const *camera, int platform_id);
|
||||
|
||||
//======= Rendering tools =======//
|
||||
|
||||
/* Initialize/precompute globals. */
|
||||
void render_init(void);
|
||||
|
||||
/* Color of a blue platform at the specified world time. */
|
||||
uint16_t render_color_blue_platform(num t);
|
||||
|
||||
/* Color of the provided platform viewed from the provided camera at the given
|
||||
world time. */
|
||||
uint16_t render_platform_color(struct platform const *p,
|
||||
struct camera const *camera, num t);
|
||||
|
||||
/* Queue an Azur command to render the triangle defined by p1/p2/p3. Only the
|
||||
x/y coordinates are used, z is ignored. */
|
||||
|
@ -79,7 +92,14 @@ void render_triangle(vec3 *p1, vec3 *p2, vec3 *p3, int color);
|
|||
used, z is ignored. */
|
||||
void render_dots(std::initializer_list<vec3> const &&points);
|
||||
|
||||
/* Render an energy string (energy font, characters supported: 0-9.%) */
|
||||
void render_energy_str(int x, int y, int halign, char const *str);
|
||||
|
||||
/* Render a frame of an animation. */
|
||||
void render_anim_frame(int x, int y, struct anim *anim, int frame);
|
||||
|
||||
/* Render the blue platform particle effect at time t. If *image is NULL,
|
||||
creates it automatically. */
|
||||
void render_effect_bpp(image_t **image, num t);
|
||||
|
||||
#endif /* __RENDERH__ */
|
||||
|
|
Loading…
Reference in New Issue