platform colors and blue platform effect

This commit is contained in:
Lephenixnoir 2023-05-28 10:07:53 +02:00
parent 08411fc90c
commit b6fb44c80a
Signed by: Lephenixnoir
GPG Key ID: 1BBA026E13FC0495
6 changed files with 161 additions and 22 deletions

View File

@ -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

View File

@ -6,6 +6,7 @@
#include "level.h"
#include <gint/display.h>
#include <libprof.h>
/* 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__ */

View File

@ -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;

View File

@ -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;

View File

@ -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;
}
}
}

View File

@ -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<vec3> 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__ */