From 5e44eb2e3c7b1462d20b17022c7a34185d9eaa45 Mon Sep 17 00:00:00 2001 From: Lephenixnoir Date: Sat, 3 Jun 2023 21:01:19 +0200 Subject: [PATCH] make red platforms fall + clarify lots of space-related stuff --- src/game.cpp | 41 ++++++++++++++--------------------------- src/game.h | 17 ++++++++--------- src/generator.h | 8 ++++++++ src/generator/gen1.cpp | 3 ++- src/generator/gen2.cpp | 34 +++++++++++++++++----------------- src/generator/gen3.cpp | 2 +- src/level.h | 10 +++++++++- src/main.cpp | 15 +++++++++++++-- src/settings.h | 18 ++++++++++-------- 9 files changed, 82 insertions(+), 66 deletions(-) diff --git a/src/game.cpp b/src/game.cpp index 9a3c225..cb142c3 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -24,11 +24,10 @@ vec2 player::world_angle_vector() const return vec2(num_cos(angle), num_sin(angle)); } - vec3 player::pos() const { /* Local position without accounting for current platform's angle */ - vec3 pos(0, -space_platform_distance() + this->height, this->z); + vec3 pos(0, -space_cylinder_quasiradius() + this->height, this->z); return vec_rotate_around_z(pos, this->world_angle_vector()); } @@ -78,12 +77,12 @@ void player::get_anim(struct anim **anim, int *frame) //======= Functions on the game world space =======// -static vec2 platform_rotations[PLATFORM_COUNT]; -static num platform_distance; +static vec2 _platform_rotations[PLATFORM_COUNT]; +static num _cylinder_quasiradius; -num space_platform_distance(void) +num space_cylinder_quasiradius(void) { - return platform_distance; + return _cylinder_quasiradius; } /* We can't use a constructor function because g++ already generates a call to @@ -94,32 +93,22 @@ void space_init(void) for(int i = 0; i < PLATFORM_COUNT; i++) { num angle = arc * i - (arc / 2); - platform_rotations[i] = vec2(num_cos(angle), num_sin(angle)); + _platform_rotations[i] = vec2(num_cos(angle), num_sin(angle)); } - platform_distance = LEVEL_RADIUS * num_cos(arc / 2); -} - -num space_platform_dist_from_center(int height_value) -{ - return LEVEL_RADIUS * (num(12 - height_value) / 12); -} - -num space_platform_height(int height_value) -{ - return LEVEL_RADIUS - space_platform_dist_from_center(height_value); + _cylinder_quasiradius = LEVEL_RADIUS * num_cos(arc / 2); } struct prect space_platform_position(struct platform const *p) { struct prect r; - vec3 radius(0, -space_platform_dist_from_center(p->height), p->z); + vec3 radius(0, -space_cylinder_quasiradius() + p->height, p->z); int angle_l = p->face; int angle_r = (p->face + 1) % PLATFORM_COUNT; - r.nl = r.fl = vec_rotate_around_z(radius, platform_rotations[angle_l]); - r.nr = r.fr = vec_rotate_around_z(radius, platform_rotations[angle_r]); + r.nl = r.fl = vec_rotate_around_z(radius, _platform_rotations[angle_l]); + r.nr = r.fr = vec_rotate_around_z(radius, _platform_rotations[angle_r]); r.fl.z += p->length; r.fr.z += p->length; @@ -146,25 +135,23 @@ void game_advance(struct game *game) num game_height_at(struct game *game, num z, int face) { - int max_h = -1; + num max_h = -KILL_PLANE_RADIUS; for(auto const &p: game->level.platform_buffer) { if(p.face == face && z >= p.z && z <= p.z + p.length) max_h = (max_h >= p.height) ? max_h : p.height; } - return max_h >= 0 - ? space_platform_height(max_h) - : -KILL_PLANE_RADIUS; + return max_h; } -const struct platform *game_platform_under_player(struct game const *game, +struct platform *game_platform_under_player(struct game *game, struct player const *player) { if(player->stance != player::Running) return NULL; - for(auto const &p: game->level.platform_buffer) { + for(auto &p: game->level.platform_buffer) { if(player->platform == p.face && player->z >= p.z && player->z <= p.z + p.length) { return &p; diff --git a/src/game.h b/src/game.h index c4fc9c8..4ab99bf 100644 --- a/src/game.h +++ b/src/game.h @@ -46,7 +46,7 @@ struct player num jump_t; /* Key to watch to end the jump. */ int jump_key; - /* Current height relative to current platform (world units). */ + /* Current height relative to cylinder (world units). */ num height; /* Vertical speed (world units/s). */ num vheight; @@ -107,12 +107,11 @@ consteval num space_platform_arc() return num(2 * 3.14159 / PLATFORM_COUNT); } -/* Height (in world coordinates in the range [-LEVEL_RADIUS..0]) of a platform - whose height value in the `struct platform` is given as parameter. */ -num space_platform_height(int height_value); - -/* Distance between the center of the world and a platform's plane. */ -num space_platform_distance(void); +/* Distance between the center of the world cylinder and the center point of a + platform at default height. This is almost equal to the cylinder's radius, + but not quite, because the platform's edges touch the cylinder and the + platform itself cuts into it. */ +num space_cylinder_quasiradius(void); /* Position, in world units, of the provided flat platform. */ struct prect space_platform_position(struct platform const *p); @@ -126,7 +125,7 @@ void game_advance(struct game *game); num game_height_at(struct game *game, num z, int face); /* Returns the platform on which the player is running, if any. */ -const struct platform *game_platform_under_player(struct game const *game, +struct platform *game_platform_under_player(struct game *game, struct player const *player); -#endif /* __GAME_H__ */ +#endif /* __GAME_H__ */ diff --git a/src/generator.h b/src/generator.h index 1d28727..fe0465b 100644 --- a/src/generator.h +++ b/src/generator.h @@ -3,6 +3,7 @@ #include #include "settings.h" +#include "level.h" using namespace libnum; //======= Generation utilities =======// @@ -96,6 +97,11 @@ struct Generator /* Generate more stuff. */ virtual void generate(struct level *) = 0; virtual ~Generator() = default; + + inline void add(struct level *level, struct platform &p) const { + p.falling = false; + level->platform_buffer.push_back(p); + } }; struct gen1: public Generator @@ -115,6 +121,8 @@ struct AcceleronGenerator: public Generator void generate(struct level *) override; ~AcceleronGenerator() override = default; + num generate_ascending_funnel(struct level *level, num z); + num m_z; bool m_initial; int m_phase; diff --git a/src/generator/gen1.cpp b/src/generator/gen1.cpp index b33d3a5..11bac28 100644 --- a/src/generator/gen1.cpp +++ b/src/generator/gen1.cpp @@ -29,7 +29,8 @@ void gen1::generate(struct level *level) p.face = 0; p.z = m_z; p.length = PLATFORM_LEN_INITIAL; - p.height = 0; + p.height = 0.0; + p.falling = false; level->platform_buffer.push_back(p); m_z += p.length; diff --git a/src/generator/gen2.cpp b/src/generator/gen2.cpp index fd4c337..a927b50 100644 --- a/src/generator/gen2.cpp +++ b/src/generator/gen2.cpp @@ -46,7 +46,7 @@ AcceleronGenerator::AcceleronGenerator(): ....#..... [h=1] Returns updated z. */ -static num generate_ascending_funnel(struct level *level, num z) +num AcceleronGenerator::generate_ascending_funnel(struct level *level, num z) { /* Ascending funnel */ for(int i = 0; i < 5; i++) { @@ -57,12 +57,12 @@ static num generate_ascending_funnel(struct level *level, num z) p.face = i + 2*j; p.z = z; p.length = G_PLATFORM_LEN; - p.height = i; + p.height = i * PLATFORM_HEIGHT_STEP; if(num_rand() <= P_ASCF_RED) p.type = PLATFORM_RED; - level->platform_buffer.push_back(p); + add(level, p); } z += G_PLATFORM_LEN + G_PLATFORM_SPC; } @@ -74,11 +74,11 @@ static num generate_ascending_funnel(struct level *level, num z) p.face = 4; p.z = z; p.length = G_PLATFORM_LEN; - p.height = i + 5; - level->platform_buffer.push_back(p); + p.height = (i + 5) * PLATFORM_HEIGHT_STEP; + add(level, p); p.face = (i & 1) ? 3 : 5; - level->platform_buffer.push_back(p); + add(level, p); z += G_PLATFORM_LEN + G_PLATFORM_SPC; } @@ -89,23 +89,23 @@ static num generate_ascending_funnel(struct level *level, num z) p.face = 4; p.z = z; p.length = G_PLATFORM_LEN * 3; - p.height = 8; - level->platform_buffer.push_back(p); + p.height = 8 * PLATFORM_HEIGHT_STEP; + add(level, p); z += G_PLATFORM_LEN * 3 + G_PLATFORM_SPC; p.type = PLATFORM_BLUE; p.face = 3; p.z = z; p.length = G_PLATFORM_LEN * 3; - p.height = 5; - level->platform_buffer.push_back(p); + p.height = 5 * PLATFORM_HEIGHT_STEP; + add(level, p); p.type = PLATFORM_WHITE; p.face = 5; p.z = z + G_PLATFORM_LEN; p.length = G_PLATFORM_LEN * 2; - p.height = 4; - level->platform_buffer.push_back(p); + p.height = 4 * PLATFORM_HEIGHT_STEP; + add(level, p); z += G_PLATFORM_LEN * 3 + G_PLATFORM_SPC; @@ -114,8 +114,8 @@ static num generate_ascending_funnel(struct level *level, num z) p.face = 4; p.z = z; p.length = G_PLATFORM_LEN; - p.height = 0; - level->platform_buffer.push_back(p); + p.height = 0.0; + add(level, p); z += G_PLATFORM_LEN + G_PLATFORM_SPC; return z; @@ -130,16 +130,16 @@ void AcceleronGenerator::generate(struct level *level) p.face = 0; p.z = m_z; p.length = G_PLATFORM_LEN_INITIAL; - p.height = 0; + p.height = 0.0; - level->platform_buffer.push_back(p); + add(level, p); m_z += p.length; m_initial = false; } /* Phase #0: Ascending funnel and long/tight red platform */ if(m_phase == 0) { - m_z = generate_ascending_funnel(level, m_z); + m_z = this->generate_ascending_funnel(level, m_z); m_checkerboard_carver.force_to_match(4); m_phase = 1; } diff --git a/src/generator/gen3.cpp b/src/generator/gen3.cpp index db2c7d4..f5840e2 100644 --- a/src/generator/gen3.cpp +++ b/src/generator/gen3.cpp @@ -13,7 +13,7 @@ void gen3::generate(struct level *level) { struct platform p; for(int i = 0; i < 3; i++) { - if(m_path_carvers[i].next(SECTION_LENGTH, &p)) { + if(m_path_carvers[i].next(3.0, &p)) { level->platform_buffer.push_back(p); } } diff --git a/src/level.h b/src/level.h index 6e8c92f..5811ff5 100644 --- a/src/level.h +++ b/src/level.h @@ -14,11 +14,19 @@ typedef enum { } platform_type_t; struct platform { + /* Face number along the level's cylinder */ int face; + /* Depth and length; the platform lies at [z ... z+length). */ num z; num length; - int height; + /* Platform height above the default height (cylinder quasiradius). This + can be compared with player->height. */ + num height; + /* Platform kind. */ platform_type_t type; + /* Whether the platform is currently falling. This is only used for red + platforms. */ + bool falling; }; struct Generator; diff --git a/src/main.cpp b/src/main.cpp index 3593a0c..fd0345a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -52,7 +52,7 @@ int play_level(int level_id) timer_start(timer); camera_track(camera, player); - log_printf("platform distance: %s\n", str(space_platform_distance())); + log_printf("cylinder quasiradius: %s\n",str(space_cylinder_quasiradius())); log_printf("player: at %s\n", str(player->pos())); log_printf("camera: at %s, screen distance %s, platform %d, " "angle vector %s\n", @@ -79,7 +79,7 @@ int play_level(int level_id) level_update(&game.level, player->z); camera_track(camera, player); - struct platform const *standing_on = game_platform_under_player(&game, + struct platform *standing_on = game_platform_under_player(&game, &game.player); //======= Rendering =======// @@ -271,6 +271,17 @@ int play_level(int level_id) if(standing_on && standing_on->type == PLATFORM_BLUE) { player->energy_percent += dt * vz * 5.5; } + if(standing_on && standing_on->type == PLATFORM_RED) { + standing_on->falling = true; + } + + for(auto &p: game.level.platform_buffer) { + if(p.type == PLATFORM_RED && p.falling) { + p.height -= PLATFORM_FALL_SPEED * dt; + if(standing_on == &p) + player->height = p.height; + } + } game_advance(&game); prof_leave_norec(perf_frame); diff --git a/src/settings.h b/src/settings.h index 4de78df..f953daa 100644 --- a/src/settings.h +++ b/src/settings.h @@ -7,21 +7,23 @@ using namespace libnum; /* Radius of the level cylinder, in world units. */ #define LEVEL_RADIUS num(4.0) /* Radius of the kill plane */ -#define KILL_PLANE_RADIUS num(10.0) -/* Section lengths, in world units. - TODO: Remove, we don't use sections anymore */ -#define SECTION_LENGTH num(3.0) +#define KILL_PLANE_RADIUS num(12.0) /* Number of platforms in the world cylinder. */ #define PLATFORM_COUNT 10 +/* Height of a single platform step. Most levels generate platforms whose + height is a integer multiple of this value above the default height. */ +#define PLATFORM_HEIGHT_STEP (LEVEL_RADIUS / 12) +/* Speed of red platforms falling once walked on (world units/s). */ +#define PLATFORM_FALL_SPEED num(1.5) /* Platforms len information, in word units */ #define PLATFORM_LEN_LONG num(3.0) #define PLATFORM_LEN_SHORT num(1) /* Magnitude of the gravity field, locally (world units/s^2), when holding the jump button and when releasing it. */ -#define HOVERING_GRAVITY num(-1.25) -#define FALLING_GRAVITY num(-8.0) +#define HOVERING_GRAVITY num(-1.75) +#define FALLING_GRAVITY num(-12.0) /* Vertical speed granted when a jump starts (world units/s). */ -#define JUMP_THRUST num(1.5) +#define JUMP_THRUST num(2.0) /* Maximum height of a step that can be crossed without dying. */ #define STEP_HEIGHT (LEVEL_RADIUS * num(0.09)) /* Player height, for collisions with platform fronts. */ @@ -41,7 +43,7 @@ using namespace libnum; /* Distance between the player and the camera */ #define RENDER_CAMERA_BACK_DISTANCE num(0.67) /* Depth at which we start rendering platforms */ -#define RENDER_DEPTH (num(8.0) * SECTION_LENGTH) +#define RENDER_DEPTH num(24.0) /* Set to 1 to enable logging by USB. */ #define LOG_USB_ENABLE 0