BosonX/src/generator.h

165 lines
4.4 KiB
C++

#ifndef GENERATOR_H
#define GENERATOR_H
#include <num/num.h>
#include "settings.h"
#include "level.h"
using namespace libnum;
//======= Generation utilities =======//
/* A utility structure holding data for path carver - a generator tool that
produces a random traversable path. */
struct path_carver
{
/* Start a path on the provided face. */
path_carver(int initial_face);
/* Advance by one platform of the specified length and generate the
associated platform data. A platform might not be generated if the path
decides to skip for a jump! Returns true if a platform was generated in
*p, false otherwise (in that case don't use *p). If force is set, always
generates a platform. */
bool next(num length, struct platform *p, bool force=false);
/* Teleport to the specified z. */
void teleport(num z);
private:
/* Face where the next platform will be generated */
int m_face;
/* Current z position */
num m_z;
/* Whether last face was skipped */
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);
~MultiPathCarver();
/* Set initial positions. */
void set_faces(int const *faces /* size N */);
/* Get current positions. */
void get_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, num height=0.0);
private:
struct Path {
/* Current face */
int face;
/* Whether last platform was skipped */
bool last_skipped;
};
/* Number of parallel paths */
int m_N;
/* Information specific to each path */
Path *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;
return (f < 0) ? f + PLATFORM_COUNT : f;
}
static inline int next_face(int face)
{
return add_to_face(face, 1);
}
static inline int prev_face(int face)
{
return add_to_face(face, -1);
}
//======= Level generator API =======//
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 GeonGenerator: public Generator
{
GeonGenerator();
void generate(struct level *) override;
~GeonGenerator() override = default;
num generate_tunnel_block(struct level *level, num z, int sections);
num generate_blue_transition(struct level *level, num z);
num generate_blue_funnel(struct level *level, num z);
num generate_random_tunnel(struct level *level, num z, int sections);
void change_phase(void);
num m_z;
bool m_initial;
int m_phase;
MultiPathCarver m_multi_carver;
};
struct AcceleronGenerator: public Generator
{
AcceleronGenerator();
void generate(struct level *) override;
~AcceleronGenerator() override = default;
num generate_ascending_funnel(struct level *level, num z);
num generate_tunnel_block(struct level *level, num z, int sections);
num generate_fractured_tunnel(struct level *level, num z, int sections);
void change_phase(void);
num m_z;
bool m_initial;
int m_phase;
MultiPathCarver m_checkerboard_carver;
};
struct RadionGenerator: public Generator
{
RadionGenerator();
void generate(struct level *) override;
~RadionGenerator() override = default;
num generate_blue_spiral(struct level *level, num z);
num generate_ascending_grid(struct level *level, num z);
void change_phase(void);
num m_z;
bool m_initial;
int m_phase;
MultiPathCarver m_multi_carver;
};
#endif /* GENERATOR_H */