add level conversion, loading, basic mechanics
This commit is contained in:
parent
4f72a8f401
commit
96247fbcfa
|
@ -5,7 +5,7 @@
|
|||
/*.g3a
|
||||
|
||||
# Python bytecode
|
||||
__pycache__/
|
||||
__pycache__/
|
||||
|
||||
# Common IDE files
|
||||
*.sublime-project
|
||||
|
|
|
@ -15,10 +15,16 @@ set(SOURCES
|
|||
src/physics.c
|
||||
)
|
||||
set(ASSETS
|
||||
assets-cg/example.png
|
||||
# ...
|
||||
assets-cg/level/level1.txt
|
||||
assets-cg/level/level2.txt
|
||||
assets-cg/level/level3.txt
|
||||
assets-cg/level/level4.txt
|
||||
assets-cg/level/level5.txt
|
||||
assets-cg/level/level6.txt
|
||||
assets-cg/level/level7.txt
|
||||
)
|
||||
|
||||
fxconv_declare_converters(converters.py)
|
||||
fxconv_declare_assets(${ASSETS} WITH_METADATA)
|
||||
|
||||
add_executable(addin ${SOURCES} ${ASSETS})
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 3.7 KiB |
|
@ -0,0 +1,3 @@
|
|||
level*.txt:
|
||||
custom-type: level
|
||||
name_regex: level(.*)\.txt level\1
|
|
@ -1,5 +1,5 @@
|
|||
#it's good to see you.\nStay close to me and don't touch anything.
|
||||
long middle vertical
|
||||
long_vertical middle
|
||||
|
||||
left
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ square right
|
|||
|
||||
middle
|
||||
|
||||
righet
|
||||
right
|
||||
|
||||
left
|
||||
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
import fxconv
|
||||
|
||||
def convert(input, output, params, target):
|
||||
if params["custom-type"] == "level":
|
||||
convert_level(input, output, params, target)
|
||||
return 0
|
||||
else:
|
||||
return 1
|
||||
|
||||
def convert_level(input, output, params, target):
|
||||
with open(input, "r") as fp:
|
||||
lines = fp.read().split("\n")
|
||||
lines = [tempo.split(",") for tempo in lines if not tempo.startswith("#")]
|
||||
|
||||
blocks = bytes()
|
||||
block_count = 0
|
||||
|
||||
for (tempo, rects) in enumerate(lines):
|
||||
for r in [r for r in rects if r]:
|
||||
r = r.strip().split()
|
||||
print(tempo, r)
|
||||
shape, action, position = -1, 0, -1
|
||||
|
||||
# Shape
|
||||
if "square" in r:
|
||||
shape = 0
|
||||
if "small" in r:
|
||||
shape = 2
|
||||
if "medium" in r:
|
||||
shape = 3
|
||||
if "normal" in r:
|
||||
shape = 4
|
||||
if "long" in r:
|
||||
shape = 5
|
||||
if "huge" in r:
|
||||
shape = 6
|
||||
if "long_vertical" in r:
|
||||
shape = 7
|
||||
|
||||
# Action
|
||||
|
||||
# Position
|
||||
if "left" in r:
|
||||
position = 0
|
||||
if "right" in r:
|
||||
position = 1
|
||||
if "middle" in r:
|
||||
position = 2
|
||||
|
||||
# Implicit rules
|
||||
if shape < 0 and action == 0:
|
||||
shape = 4
|
||||
|
||||
if shape < 0 or action < 0 or position < 0:
|
||||
raise fxconv.FxconvError("Incomplete in '" + " ".join(r) + "'")
|
||||
|
||||
blocks += fxconv.u32(tempo)
|
||||
blocks += fxconv.u32(shape)
|
||||
blocks += fxconv.u32(position)
|
||||
blocks += fxconv.u32(action)
|
||||
block_count += 1
|
||||
|
||||
o = fxconv.ObjectData()
|
||||
o += fxconv.u32(0x40000000) # 2.0 as a float
|
||||
o += fxconv.u32(block_count)
|
||||
o += fxconv.ref(blocks)
|
||||
|
||||
fxconv.elf(o, output, "_" + params["name"], **target)
|
44
src/duet.h
44
src/duet.h
|
@ -14,12 +14,13 @@
|
|||
//---
|
||||
|
||||
typedef enum {
|
||||
Shape_Square = 0,
|
||||
Shape_SmallBar = 2,
|
||||
Shape_MediumBar = 3,
|
||||
Shape_NormalBar = 4,
|
||||
Shape_LongBar = 5,
|
||||
Shape_HugeBar = 6,
|
||||
Shape_Square = 0,
|
||||
Shape_SmallBar = 2,
|
||||
Shape_MediumBar = 3,
|
||||
Shape_NormalBar = 4,
|
||||
Shape_LongBar = 5,
|
||||
Shape_HugeBar = 6,
|
||||
Shape_LongVertical = 7,
|
||||
} shape_t;
|
||||
|
||||
typedef enum {
|
||||
|
@ -48,6 +49,7 @@ typedef struct {
|
|||
|
||||
typedef struct {
|
||||
float tempo;
|
||||
int block_count;
|
||||
rectmeta_t *blocks;
|
||||
} level_t;
|
||||
|
||||
|
@ -55,16 +57,18 @@ typedef struct {
|
|||
// Game
|
||||
//---
|
||||
|
||||
#define PLAYER_X 55
|
||||
#define PLAYER_R 35
|
||||
#define PLAYER_SIZE 6
|
||||
#define PLAYER_X 60
|
||||
#define PLAYER_R 40
|
||||
#define PLAYER_SIZE 8
|
||||
#define CORRIDOR_SIZE 120
|
||||
|
||||
#define RECT_SPEED 60 /* px/tempo */
|
||||
|
||||
typedef struct {
|
||||
float w, h; /* px */
|
||||
float x, y; /* px */
|
||||
float vx, vy; /* px/s */
|
||||
float r; /* rad */
|
||||
float vr; /* rad/s */
|
||||
rectmeta_t const *meta;
|
||||
} rect_t;
|
||||
|
||||
#define RECT_TABLE_SIZE 20
|
||||
|
@ -73,6 +77,7 @@ typedef struct game {
|
|||
int dead;
|
||||
float time;
|
||||
level_t *level;
|
||||
rectmeta_t const *current;
|
||||
|
||||
rect_t table[RECT_TABLE_SIZE];
|
||||
int cursor;
|
||||
|
@ -99,4 +104,21 @@ void player_position(float angle,
|
|||
float *x1, float *y1, float *x2, float *y2);
|
||||
|
||||
bool player_collision(game_t const *game);
|
||||
|
||||
bool rect_circle_collide(rect_t const *r, int cx, int cy, int cr);
|
||||
|
||||
void rect_load(rect_t *r, rectmeta_t const *meta);
|
||||
|
||||
void rect_physics(rect_t *r, rectmeta_t const *meta, float time);
|
||||
|
||||
//---
|
||||
// Levels
|
||||
//---
|
||||
|
||||
extern level_t level1;
|
||||
extern level_t level2;
|
||||
extern level_t level3;
|
||||
extern level_t level4;
|
||||
extern level_t level5;
|
||||
extern level_t level6;
|
||||
extern level_t level7;
|
||||
|
|
51
src/main.c
51
src/main.c
|
@ -44,13 +44,9 @@ int main(void)
|
|||
__printf_enable_fp();
|
||||
|
||||
memset(&game, 0x00, sizeof game);
|
||||
game.level = &level0;
|
||||
|
||||
/* Temporary level */
|
||||
game.table[0] = (rect_t){
|
||||
.w=80, .h=20, .x=440, .y=50, .vx=-100, .vy=0, .r=0, .vr=0.5
|
||||
};
|
||||
game.cursor = 1;
|
||||
game.level = &level3;
|
||||
game.current = game.level->blocks;
|
||||
game.time = -5.0;
|
||||
|
||||
timer = timer_configure(TIMER_ANY, 33000, GINT_CALL_SET(&need_frame));
|
||||
timer_start(timer);
|
||||
|
@ -61,8 +57,8 @@ int main(void)
|
|||
while (need_frame == 0) sleep();
|
||||
need_frame = 0;
|
||||
|
||||
dt = (1.0 / 30) * level0.tempo;
|
||||
game.time += 1.0 / 30;
|
||||
dt = (1.0 / 30) * game.level->tempo;
|
||||
game.time += dt;
|
||||
|
||||
/* Input analysis */
|
||||
|
||||
|
@ -81,7 +77,31 @@ int main(void)
|
|||
}
|
||||
|
||||
/* Level generation */
|
||||
/* TODO */
|
||||
|
||||
// Remove rectangles that have passed their lifetime by 2 seconds
|
||||
for(int i = 0; i < game.cursor;) {
|
||||
if(game.time > game.table[i].meta->time + 2)
|
||||
game.table[i] = game.table[--game.cursor];
|
||||
else
|
||||
i++;
|
||||
}
|
||||
|
||||
// Find rectangles that need to be loaded
|
||||
rectmeta_t const *meta = game.current;
|
||||
while(meta < game.level->blocks + game.level->block_count) {
|
||||
if(meta - game.current > RECT_TABLE_SIZE - game.cursor)
|
||||
break; /* oops, not enough array space left */
|
||||
if(meta->time - 10 > game.time)
|
||||
break;
|
||||
meta++;
|
||||
}
|
||||
|
||||
// Load everything up to meta
|
||||
while(game.current < meta) {
|
||||
rect_t *r = &game.table[game.cursor++];
|
||||
r->meta = game.current++;
|
||||
rect_load(r, r->meta);
|
||||
}
|
||||
|
||||
/* Physics */
|
||||
|
||||
|
@ -89,22 +109,19 @@ int main(void)
|
|||
// break;
|
||||
|
||||
for(int i = 0; i < game.cursor; i++) {
|
||||
rect_t *r = &game.table[i];
|
||||
r->x += r->vx * dt;
|
||||
r->y += r->vy * dt;
|
||||
r->r += r->vr * dt;
|
||||
rect_physics(&game.table[i], game.table[i].meta, game.time);
|
||||
}
|
||||
|
||||
if(rotate_left)
|
||||
game.player_rota += M_PI * dt;
|
||||
game.player_rota += 2.1 * dt;
|
||||
if(rotate_right)
|
||||
game.player_rota -= M_PI * dt;
|
||||
game.player_rota -= 2.1 * dt;
|
||||
|
||||
/* Rendering */
|
||||
|
||||
dclear(player_collision(&game) ? C_RED : C_BLACK);
|
||||
dprint(0, 0, C_WHITE, "game time: %.2fs", game.time);
|
||||
dprint(0, 11, C_WHITE, "player rota: %.2f rad", game.player_rota);
|
||||
dprint(0, 11, C_WHITE, "rectangles loaded: %d", game.cursor);
|
||||
|
||||
for(int i = 0; i < game.cursor; i++)
|
||||
drectoid(&game.table[i], C_WHITE);
|
||||
|
|
|
@ -50,5 +50,67 @@ bool rect_circle_collide(rect_t const *r, int cx0, int cy0, int cr)
|
|||
if(cly > r->h/2) cly = r->h/2;
|
||||
|
||||
/* Determine whether that point is in the circle */
|
||||
|
||||
return (clx - cx) * (clx - cx) + (cly - cy) * (cly - cy) <= cr * cr;
|
||||
}
|
||||
|
||||
void rect_load(rect_t *r, rectmeta_t const *meta)
|
||||
{
|
||||
r->w = 0;
|
||||
r->h = 0;
|
||||
|
||||
switch(meta->shape) {
|
||||
case Shape_Square:
|
||||
r->w = 0.4;
|
||||
r->h = 0.5;
|
||||
break;
|
||||
case Shape_SmallBar:
|
||||
r->w = 0.2;
|
||||
r->h = 0.5;
|
||||
break;
|
||||
case Shape_MediumBar:
|
||||
r->w = 0.2;
|
||||
r->h = 0.65;
|
||||
break;
|
||||
case Shape_NormalBar:
|
||||
r->w = 0.2;
|
||||
r->h = 1.0;
|
||||
break;
|
||||
case Shape_LongBar:
|
||||
r->w = 0.2;
|
||||
r->h = 1.15;
|
||||
break;
|
||||
case Shape_HugeBar:
|
||||
r->w = 0.2;
|
||||
r->h = 1.5;
|
||||
break;
|
||||
case Shape_LongVertical:
|
||||
r->w = 0.8;
|
||||
r->h = 0.2;
|
||||
break;
|
||||
}
|
||||
|
||||
r->w *= 2 * PLAYER_R;
|
||||
r->h *= 2 * PLAYER_R;
|
||||
|
||||
switch(meta->position) {
|
||||
case Position_Left:
|
||||
r->y = DHEIGHT/2 - CORRIDOR_SIZE/2 + r->w/2;
|
||||
break;
|
||||
case Position_Right:
|
||||
r->y = DHEIGHT/2 + CORRIDOR_SIZE/2 - r->w/2;
|
||||
break;
|
||||
case Position_Middle:
|
||||
r->y = DHEIGHT/2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void rect_physics(rect_t *r, rectmeta_t const *meta, float absolute_time)
|
||||
{
|
||||
// TODO: Use position and actions
|
||||
float time = absolute_time - meta->time; /* <= 0 most of the time */
|
||||
|
||||
r->x = PLAYER_X - RECT_SPEED * time;
|
||||
r->r = 0;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue