From b6fb44c80afdf082a276fb7dbe62318fe0c7a0d0 Mon Sep 17 00:00:00 2001 From: Lephenixnoir Date: Sun, 28 May 2023 10:07:53 +0200 Subject: [PATCH] platform colors and blue platform effect --- src/game.cpp | 15 +++--- src/game.h | 13 ++++-- src/generator/gen2.cpp | 12 +++-- src/main.cpp | 23 +++++++++- src/render.cpp | 101 ++++++++++++++++++++++++++++++++++++++++- src/render.h | 19 +++++++- 6 files changed, 161 insertions(+), 22 deletions(-) diff --git a/src/game.cpp b/src/game.cpp index e1ac31d..1498936 100644 --- a/src/game.cpp +++ b/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 diff --git a/src/game.h b/src/game.h index db99d72..884bd36 100644 --- a/src/game.h +++ b/src/game.h @@ -6,6 +6,7 @@ #include "level.h" #include +#include /* A player's movement and data information. */ struct player @@ -85,6 +86,10 @@ struct game struct { bool footer; /* Show performance footer */ } debug; + + struct { + prof_t effect_bpp; + } perf; }; //======= Functions on the game world space =======// @@ -116,10 +121,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__ */ diff --git a/src/generator/gen2.cpp b/src/generator/gen2.cpp index ca16052..fd4c337 100644 --- a/src/generator/gen2.cpp +++ b/src/generator/gen2.cpp @@ -4,7 +4,7 @@ #include /* 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; diff --git a/src/main.cpp b/src/main.cpp index f25d961..dd41f81 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -56,6 +56,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,10 +69,14 @@ 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(); @@ -82,7 +88,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 +110,15 @@ 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); + } + prof_leave_norec(perf_comp); azrp_update(); @@ -203,7 +218,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 @@ -236,6 +251,9 @@ int play_level(int level_id) last_frame_us = prof_time(perf_frame); } + if(effect_bpp) + image_free(effect_bpp); + timer_stop(timer); return 0; } @@ -246,6 +264,7 @@ int main(void) __printf_enable_fp(); prof_init(); + render_init(); space_init(); extern font_t font_boson; diff --git a/src/render.cpp b/src/render.cpp index 5372ebc..afbe9f1 100644 --- a/src/render.cpp +++ b/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,46 @@ void render_anim_frame(int x, int y, struct anim *anim, int frame) y + anim->y_offsets[frame] - anim->y_anchor, anim->frames[frame]); } + +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; + } + } +} diff --git a/src/render.h b/src/render.h index ca5787f..af4eed4 100644 --- a/src/render.h +++ b/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. */ @@ -82,4 +95,8 @@ void render_dots(std::initializer_list const &&points); /* 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__ */