lv2: add a random checkerboard path phase
This commit is contained in:
parent
f8a0544b87
commit
08411fc90c
|
@ -31,6 +31,45 @@ private:
|
|||
bool m_last_skipped;
|
||||
};
|
||||
|
||||
/* A path carver that generates multiple simultaneous paths following a
|
||||
grid-like structure (platforms all of the same length, minus some random
|
||||
variation). */
|
||||
struct MultiPathCarver
|
||||
{
|
||||
/* Create a carver with a set number of parallel paths. */
|
||||
MultiPathCarver(int N);
|
||||
|
||||
/* Set initial positions. */
|
||||
void set_faces(int *faces /* size N */);
|
||||
|
||||
/* Force the carver to generate all platforms and never skip. */
|
||||
void set_noskip(bool noskip);
|
||||
|
||||
/* Force the carver to generate paths along a checkerboard. */
|
||||
void set_checkerboard(bool checkerboard);
|
||||
|
||||
/* Rotate the current state to force one platform to be at `face`. */
|
||||
void force_to_match(int face);
|
||||
|
||||
/* Add the next set of platforms (all at z) to the level. */
|
||||
void next(struct level *level, num z, num length);
|
||||
|
||||
private:
|
||||
/* Number of parallel paths */
|
||||
int m_N;
|
||||
/* Information specific to each path */
|
||||
struct {
|
||||
/* Current face */
|
||||
int face;
|
||||
/* Whether last platform was skipped */
|
||||
bool last_skipped;
|
||||
} *m_paths;
|
||||
/* Force all platforms to be generated */
|
||||
bool m_noskip;
|
||||
/* Force a checkerboard pattern */
|
||||
bool m_checkerboard;
|
||||
};
|
||||
|
||||
static inline int add_to_face(int face, int how_much)
|
||||
{
|
||||
int f = (face + how_much) % PLATFORM_COUNT;
|
||||
|
@ -75,7 +114,8 @@ struct AcceleronGenerator: public Generator
|
|||
|
||||
num m_z;
|
||||
bool m_initial;
|
||||
path_carver m_path_carver;
|
||||
int m_phase;
|
||||
MultiPathCarver m_checkerboard_carver;
|
||||
};
|
||||
|
||||
struct gen3: public Generator
|
||||
|
|
|
@ -10,11 +10,18 @@
|
|||
/* Probabilities */
|
||||
#define P_ASCF_RED num(0.2)
|
||||
|
||||
AcceleronGenerator::AcceleronGenerator(): m_path_carver{0}
|
||||
AcceleronGenerator::AcceleronGenerator():
|
||||
m_checkerboard_carver{3}
|
||||
{
|
||||
srand(123456);
|
||||
m_initial = true;
|
||||
m_z = 0.0;
|
||||
m_phase = 0;
|
||||
|
||||
int faces[3] = { 0, 4, 8 };
|
||||
m_checkerboard_carver.set_faces(faces);
|
||||
m_checkerboard_carver.set_noskip(true);
|
||||
m_checkerboard_carver.set_checkerboard(true);
|
||||
}
|
||||
|
||||
/* Generates an ascending funnel up to a long red platform on face #4, in the
|
||||
|
@ -128,7 +135,21 @@ void AcceleronGenerator::generate(struct level *level)
|
|||
m_initial = false;
|
||||
}
|
||||
|
||||
m_z = generate_ascending_funnel(level, m_z);
|
||||
/* Phase #0: Ascending funnel and long/tight red platform */
|
||||
if(m_phase == 0) {
|
||||
m_z = generate_ascending_funnel(level, m_z);
|
||||
m_checkerboard_carver.force_to_match(4);
|
||||
m_phase = 1;
|
||||
}
|
||||
/* Phase #1: Checkerboard random paths */
|
||||
else if(m_phase == 1) {
|
||||
int length = 4 + 2 * (rand() % 2);
|
||||
for(int i = 0; i < length; i++) {
|
||||
m_checkerboard_carver.next(level, m_z, G_PLATFORM_LEN);
|
||||
m_z += G_PLATFORM_LEN + G_PLATFORM_SPC;
|
||||
}
|
||||
m_phase = 0;
|
||||
}
|
||||
|
||||
/* Phase #1: Almost-full tunnel with random holes? */
|
||||
|
||||
|
@ -136,7 +157,6 @@ void AcceleronGenerator::generate(struct level *level)
|
|||
|
||||
/* Phase #3: Full + odd + even tunnel combination leading into #0 */
|
||||
|
||||
/* Phase #4: Checkerboard random paths */
|
||||
|
||||
/* Phase #5: Obstacles
|
||||
- ##.##.#.#.
|
||||
|
|
|
@ -36,3 +36,78 @@ void path_carver::teleport(num z)
|
|||
{
|
||||
m_z = z;
|
||||
}
|
||||
|
||||
//~
|
||||
|
||||
MultiPathCarver::MultiPathCarver(int N)
|
||||
{
|
||||
m_N = N;
|
||||
m_paths = static_cast<decltype(m_paths)>(malloc(N * sizeof *m_paths));
|
||||
m_noskip = false;
|
||||
m_checkerboard = false;
|
||||
|
||||
for(int i = 0; i < N; i++)
|
||||
m_paths[i].last_skipped = false;
|
||||
}
|
||||
|
||||
void MultiPathCarver::set_faces(int *faces)
|
||||
{
|
||||
for(int i = 0; i < m_N; i++)
|
||||
m_paths[i].face = faces[i];
|
||||
}
|
||||
|
||||
void MultiPathCarver::set_noskip(bool noskip)
|
||||
{
|
||||
m_noskip = noskip;
|
||||
}
|
||||
|
||||
void MultiPathCarver::set_checkerboard(bool checkerboard)
|
||||
{
|
||||
m_checkerboard = checkerboard;
|
||||
}
|
||||
|
||||
void MultiPathCarver::force_to_match(int face)
|
||||
{
|
||||
if(m_N <= 0)
|
||||
return;
|
||||
|
||||
int diff = face - m_paths[0].face;
|
||||
for(int i = 0; i < m_N; i++) {
|
||||
m_paths[i].face = add_to_face(m_paths[i].face, diff);
|
||||
}
|
||||
}
|
||||
|
||||
void MultiPathCarver::next(struct level *level, num z, num length)
|
||||
{
|
||||
/* Decide whether to skip */
|
||||
for(int i = 0; i < m_N; i++) {
|
||||
bool skip = !m_noskip && !m_paths[i].last_skipped && (rand() % 4 == 0);
|
||||
m_paths[i].last_skipped = skip;
|
||||
}
|
||||
|
||||
/* Generate platforms for the current positions */
|
||||
for(int face = 0; face < PLATFORM_COUNT; face++) {
|
||||
bool is_hit = false;
|
||||
for(int i = 0; i < m_N; i++)
|
||||
is_hit |= (!m_paths[i].last_skipped && m_paths[i].face == face);
|
||||
|
||||
if(is_hit) {
|
||||
struct platform p;
|
||||
p.face = face;
|
||||
p.z = z;
|
||||
p.length = length;
|
||||
p.height = 0;
|
||||
p.type = PLATFORM_WHITE;
|
||||
level->platform_buffer.push_back(p);
|
||||
}
|
||||
}
|
||||
|
||||
/* Advance positions */
|
||||
for(int i = 0; i < m_N; i++) {
|
||||
/* In checkerboard mode, only allow diff -1/+1 instead of -1/0/+1 */
|
||||
int diff = m_checkerboard
|
||||
? 2 * (rand() % 2) - 1
|
||||
: rand() % 3 - 1;
|
||||
m_paths[i].face = add_to_face(m_paths[i].face, diff);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -111,18 +111,11 @@ int play_level(int level_id)
|
|||
|
||||
if(game.debug.footer) {
|
||||
drect(0, DHEIGHT-20, DWIDTH-1, DHEIGHT-1, C_WHITE);
|
||||
#if 0
|
||||
dprint(4, 209, C_BLACK, "render:%4d+%4dus comp:%4dus FPS:%02d",
|
||||
prof_time(azrp_perf_render) - prof_time(azrp_perf_r61524),
|
||||
prof_time(azrp_perf_r61524),
|
||||
prof_time(perf_comp),
|
||||
last_frame_us ? 1000000 / last_frame_us : 0);
|
||||
#else
|
||||
dprint(4, 209, C_BLACK, "floor:%f h:%f vh:%f",
|
||||
(double)floor,
|
||||
(double)game.player.height,
|
||||
(double)game.player.vheight);
|
||||
#endif
|
||||
r61524_display(gint_vram, DHEIGHT-20, 20, R61524_DMA_WAIT);
|
||||
}
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ struct camera
|
|||
|
||||
/* Distance to the near plane, for clipping.
|
||||
TODO: Figure out a better choice of a near plane. */
|
||||
num near_plane() const { return this->screen_distance() * num(0.75); }
|
||||
num near_plane() const { return this->screen_distance() * num(0.25); }
|
||||
|
||||
//======= World data =======//
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ using namespace libnum;
|
|||
/* Vertical speed granted when a jump starts (world units/s). */
|
||||
#define JUMP_THRUST num(1.5)
|
||||
/* Maximum height of a step that can be crossed without dying. */
|
||||
#define STEP_HEIGHT (LEVEL_RADIUS * num(0.12))
|
||||
#define STEP_HEIGHT (LEVEL_RADIUS * num(0.09))
|
||||
/* Player height, for collisions with platform fronts. */
|
||||
#define PLAYER_HEIGHT num(0.8)
|
||||
|
||||
|
|
Loading…
Reference in New Issue