gravity is out of their mind
Implements: https://todo.sr.ht/~kikoodx/jtmm2/6
This commit is contained in:
parent
0509f62e2f
commit
7a708c28f9
|
@ -25,6 +25,7 @@ set(ASSETS
|
|||
res/burn.kble
|
||||
res/bounce.kble
|
||||
res/worm.kble
|
||||
res/shake.kble
|
||||
res/fonts/dina.png
|
||||
)
|
||||
|
||||
|
|
|
@ -18,3 +18,4 @@
|
|||
#define BURN_DEATH 3
|
||||
#define BOUNCE_SPEED -2.0f
|
||||
#define DRAW_OFF_X -2
|
||||
#define GRAVS_MARGIN 0
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
enum AirState { AS_NEUTRAL, AS_RISING, AS_BREAKING };
|
||||
|
||||
struct Player {
|
||||
struct Vec pos;
|
||||
struct Vec pos, gravity;
|
||||
struct VecF spd, rem;
|
||||
enum AirState air_state;
|
||||
int jump_buffer, jump_grace, burn, bouncing;
|
||||
|
|
|
@ -9,5 +9,9 @@ enum Tile {
|
|||
TILE_EXIT,
|
||||
TILE_BURN,
|
||||
TILE_BOUNCER,
|
||||
TILE_GRAV_D,
|
||||
TILE_GRAV_U,
|
||||
TILE_GRAV_R,
|
||||
TILE_GRAV_L,
|
||||
TILE_OOB,
|
||||
};
|
||||
|
|
Binary file not shown.
BIN
res/tileset.png
BIN
res/tileset.png
Binary file not shown.
Before Width: | Height: | Size: 7.0 KiB After Width: | Height: | Size: 8.4 KiB |
10
src/level.c
10
src/level.c
|
@ -11,13 +11,11 @@
|
|||
static struct Level level;
|
||||
extern bopti_image_t bimg_tileset;
|
||||
|
||||
extern struct LevelBin kble_test, kble_burn, kble_bounce, kble_worm;
|
||||
extern struct LevelBin kble_test, kble_burn, kble_bounce, kble_worm, kble_shake;
|
||||
static const struct LevelBinNamed levels[] = {
|
||||
{&kble_test, "gentle introduction"},
|
||||
{&kble_burn, "these are rare"},
|
||||
{&kble_bounce, "deceptive road"},
|
||||
{&kble_worm, "under your skin"},
|
||||
{NULL, NULL}};
|
||||
{&kble_test, "gentle introduction"}, {&kble_burn, "these are rare"},
|
||||
{&kble_bounce, "deceptive road"}, {&kble_worm, "under your skin"},
|
||||
{&kble_shake, "breaking into reality"}, {NULL, NULL}};
|
||||
|
||||
static void level_free(void);
|
||||
|
||||
|
|
68
src/player.c
68
src/player.c
|
@ -19,6 +19,8 @@ player_spawn(struct Player *p)
|
|||
struct Vec pos = level_find(TILE_SPAWN);
|
||||
p->pos.x = pos.x * TILE_SIZE + (TILE_SIZE - PLAYER_WIDTH) / 2;
|
||||
p->pos.y = pos.y * TILE_SIZE + TILE_SIZE - PLAYER_HEIGHT;
|
||||
p->gravity.x = 0;
|
||||
p->gravity.y = 1;
|
||||
reset_speed(p, 1, 1);
|
||||
p->air_state = AS_NEUTRAL;
|
||||
p->jump_buffer = 0;
|
||||
|
@ -29,7 +31,8 @@ player_spawn(struct Player *p)
|
|||
void
|
||||
player_update(struct Player *p)
|
||||
{
|
||||
const int on_ground = collide_solid(p->pos.x, p->pos.y + 1);
|
||||
const int on_ground =
|
||||
collide_solid(p->pos.x + p->gravity.x, p->pos.y + p->gravity.y);
|
||||
const int k_left = input_down(K_LEFT);
|
||||
const int k_right = input_down(K_RIGHT);
|
||||
// const int k_up = input_down(K_UP);
|
||||
|
@ -38,18 +41,27 @@ player_update(struct Player *p)
|
|||
const int kp_jump = input_pressed(K_JUMP);
|
||||
const int kp_polarity = input_pressed(K_POLARITY);
|
||||
const int dir_x = k_right - k_left;
|
||||
const struct Vec rem_gravity = p->gravity;
|
||||
float spd_x, spd_y;
|
||||
|
||||
/* speed transformation */
|
||||
spd_x = p->spd.x;
|
||||
spd_y = p->spd.y * p->gravity.y;
|
||||
if (p->gravity.x) {
|
||||
spd_x = p->spd.y;
|
||||
spd_y = p->spd.x * p->gravity.x;
|
||||
}
|
||||
|
||||
/* polarity swap */
|
||||
if (kp_polarity) polarity_invert();
|
||||
|
||||
/* horizontal friction & acceleration */
|
||||
p->spd.x *= on_ground ? (1 - GROUND_FRICTION) : (1 - AIR_FRICTION);
|
||||
p->spd.x +=
|
||||
dir_x * (on_ground ? GROUND_ACCELERATION : AIR_ACCELERATION);
|
||||
spd_x *= on_ground ? (1 - GROUND_FRICTION) : (1 - AIR_FRICTION);
|
||||
spd_x += dir_x * (on_ground ? GROUND_ACCELERATION : AIR_ACCELERATION);
|
||||
|
||||
/* air resistance & gravity */
|
||||
p->spd.y *= (1 - AIR_RESISTANCE);
|
||||
p->spd.y +=
|
||||
spd_y *= (1 - AIR_RESISTANCE);
|
||||
spd_y +=
|
||||
(p->air_state == AS_BREAKING) ? (GRAVITY * JUMP_BREAK) : (GRAVITY);
|
||||
|
||||
/* air state machine */
|
||||
|
@ -59,7 +71,7 @@ player_update(struct Player *p)
|
|||
if (!k_jump) p->air_state = AS_BREAKING;
|
||||
/* fallthrough */
|
||||
case AS_BREAKING:
|
||||
if (p->spd.y > 0) p->air_state = AS_NEUTRAL;
|
||||
if (spd_y > 0) p->air_state = AS_NEUTRAL;
|
||||
break;
|
||||
case AS_NEUTRAL:
|
||||
default:
|
||||
|
@ -78,7 +90,7 @@ player_update(struct Player *p)
|
|||
p->jump_grace--;
|
||||
/* jump */
|
||||
if (p->jump_grace && p->jump_buffer && k_jump) {
|
||||
p->spd.y = JUMP_SPEED;
|
||||
spd_y = JUMP_SPEED;
|
||||
p->air_state = AS_RISING;
|
||||
p->jump_buffer = 0;
|
||||
p->jump_grace = 0;
|
||||
|
@ -87,7 +99,7 @@ player_update(struct Player *p)
|
|||
/* bounce */
|
||||
if (collide(p->pos.x, p->pos.y, TILE_BOUNCER)) {
|
||||
if (!p->bouncing) {
|
||||
p->spd.y = -absf(p->spd.y) + BOUNCE_SPEED;
|
||||
spd_y = -absf(spd_y) + BOUNCE_SPEED;
|
||||
p->bouncing = 1;
|
||||
}
|
||||
} else {
|
||||
|
@ -96,15 +108,49 @@ player_update(struct Player *p)
|
|||
|
||||
/* burn and death */
|
||||
if (collide(p->pos.x, p->pos.y, TILE_BURN)) {
|
||||
if (++p->burn >= BURN_DEATH) level_reload();
|
||||
if (++p->burn >= BURN_DEATH) {
|
||||
level_reload();
|
||||
return;
|
||||
}
|
||||
} else if (p->burn) {
|
||||
p->burn--;
|
||||
}
|
||||
|
||||
/* next level */
|
||||
if (collide(p->pos.x, p->pos.y, TILE_EXIT)) level_next();
|
||||
if (collide(p->pos.x, p->pos.y, TILE_EXIT)) {
|
||||
level_next();
|
||||
return;
|
||||
}
|
||||
|
||||
/* speed transformation */
|
||||
if (rem_gravity.y) {
|
||||
p->spd.x = spd_x;
|
||||
p->spd.y = spd_y * p->gravity.y;
|
||||
}
|
||||
if (rem_gravity.x) {
|
||||
p->spd.y = spd_x;
|
||||
p->spd.x = spd_y * p->gravity.x;
|
||||
}
|
||||
|
||||
player_move(p, update_rem(p));
|
||||
|
||||
/* gravity modifiers */
|
||||
if (collide_margin(p->pos.x, p->pos.y, TILE_GRAV_D, GRAVS_MARGIN)) {
|
||||
p->gravity.x = 0;
|
||||
p->gravity.y = 1;
|
||||
}
|
||||
if (collide_margin(p->pos.x, p->pos.y, TILE_GRAV_U, GRAVS_MARGIN)) {
|
||||
p->gravity.x = 0;
|
||||
p->gravity.y = -1;
|
||||
}
|
||||
if (collide_margin(p->pos.x, p->pos.y, TILE_GRAV_R, GRAVS_MARGIN)) {
|
||||
p->gravity.x = 1;
|
||||
p->gravity.y = 0;
|
||||
}
|
||||
if (collide_margin(p->pos.x, p->pos.y, TILE_GRAV_L, GRAVS_MARGIN)) {
|
||||
p->gravity.x = -1;
|
||||
p->gravity.y = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
|
Loading…
Reference in New Issue