make red platforms fall + clarify lots of space-related stuff
This commit is contained in:
parent
cde90744cf
commit
5e44eb2e3c
41
src/game.cpp
41
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;
|
||||
|
|
17
src/game.h
17
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__ */
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#include <num/num.h>
|
||||
#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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
10
src/level.h
10
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;
|
||||
|
|
15
src/main.cpp
15
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);
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue