Player controller
This commit is contained in:
parent
ab5c442433
commit
5f522abcb5
Binary file not shown.
Binary file not shown.
Before Width: | Height: | Size: 634 B After Width: | Height: | Size: 601 B |
35
game/game.c
35
game/game.c
@ -8,16 +8,6 @@
|
||||
|
||||
uint32_t game_frame;
|
||||
|
||||
game_bbox game_player_bbox = {
|
||||
.x=0x9000,
|
||||
// .y=0x5800,
|
||||
.y=0x0000,
|
||||
.w=0x1000,
|
||||
.h=0x1000,
|
||||
};
|
||||
sys_i32 game_player_dx = 0;
|
||||
sys_i32 game_player_dy = 0;
|
||||
|
||||
const char* game_title() {
|
||||
return "Croc Party!";
|
||||
}
|
||||
@ -26,6 +16,7 @@ void game_init() {
|
||||
sys_init();
|
||||
|
||||
game_palette_init();
|
||||
game_player_init();
|
||||
}
|
||||
|
||||
void game_destroy() {
|
||||
@ -33,32 +24,16 @@ void game_destroy() {
|
||||
}
|
||||
|
||||
void game_update() {
|
||||
sys_update();
|
||||
|
||||
game_frame += 1;
|
||||
game_player_update();
|
||||
|
||||
game_player_dy += 1;
|
||||
|
||||
if (device_buttons[0]) { game_player_dx -= 16; }
|
||||
if (device_buttons[1]) { game_player_dx += 16; }
|
||||
|
||||
game_collision collision = game_collision_move_to_contact(
|
||||
&game_player_bbox,
|
||||
game_player_dx,
|
||||
game_player_dy
|
||||
);
|
||||
if (collision.collided_x) { game_player_dx = 0; }
|
||||
if (collision.collided_y) { game_player_dy = 0; }
|
||||
}
|
||||
|
||||
void game_draw() {
|
||||
sys_cls(9);
|
||||
|
||||
sys_map_draw(map_game_map, spr_game_tiles, 0, 0, 0, 0, 32, 18);
|
||||
sys_sprite_draw_ext(
|
||||
spr_game_player,
|
||||
(game_frame / 8) % 4 * 2,
|
||||
game_player_bbox.x / 0x100,
|
||||
game_player_bbox.y / 0x100,
|
||||
2, 2,
|
||||
false, false
|
||||
);
|
||||
game_player_draw();
|
||||
}
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
#include "game_collision.h"
|
||||
#include "game_palette.h"
|
||||
#include "game_player.h"
|
||||
|
||||
const char* game_title();
|
||||
void game_init();
|
||||
|
159
game/game_player.c
Normal file
159
game/game_player.c
Normal file
@ -0,0 +1,159 @@
|
||||
#include "art/game_player.h"
|
||||
#include "art/game_tiles.h"
|
||||
#include "device/device.h"
|
||||
#include "map/game_map.h"
|
||||
#include "game.h"
|
||||
#include "sys/sys.h"
|
||||
|
||||
game_bbox game_player_bbox = {
|
||||
.x=0x9000,
|
||||
// .y=0x5800,
|
||||
.y=0x0000,
|
||||
.w=0x1000,
|
||||
.h=0x1000,
|
||||
};
|
||||
bool game_player_grounded = false;
|
||||
sys_i32 game_player_jump_frames = 0;
|
||||
sys_i32 game_player_coyote_frames = 0;
|
||||
sys_i32 game_player_dx = 0;
|
||||
sys_i32 game_player_dy = 0;
|
||||
bool game_player_faceleft = false;
|
||||
|
||||
typedef enum {
|
||||
GAME_PLAYER_ANIM_STANDING,
|
||||
GAME_PLAYER_ANIM_WALKING,
|
||||
GAME_PLAYER_ANIM_FLOATING,
|
||||
} game_player_anim;
|
||||
|
||||
game_player_anim game_player_anim_state = GAME_PLAYER_ANIM_STANDING;
|
||||
uint8_t game_player_anim_progress = 0;
|
||||
|
||||
void game_player_anim_transition(game_player_anim anim);
|
||||
void game_player_anim_add_progress(uint8_t amt);
|
||||
|
||||
void game_player_init() {
|
||||
}
|
||||
|
||||
void game_player_update() {
|
||||
game_collision collision = game_collision_move_to_contact(
|
||||
&game_player_bbox,
|
||||
game_player_dx,
|
||||
game_player_dy
|
||||
);
|
||||
|
||||
if (collision.collided_x) { game_player_dx = 0; }
|
||||
if (collision.collided_y) { game_player_dy = 0; }
|
||||
|
||||
game_player_grounded = !game_collision_can_move(game_player_bbox, 0, 1);
|
||||
|
||||
{
|
||||
sys_i32 fric_numerator = game_player_grounded ? 0x70 : 0x7f;
|
||||
game_player_dx = (
|
||||
game_player_dx * fric_numerator +
|
||||
// round up
|
||||
0x7f * sys_sgn_i32(game_player_dx)
|
||||
) / 0x80;
|
||||
if (sys_abs_i32(game_player_dx) > 0x200) {
|
||||
game_player_dx = sys_sgn_i32(game_player_dx) * 0x200;
|
||||
}
|
||||
|
||||
int wanted_dx = game_player_dx;
|
||||
if (sys_btn(DEVICE_BUTTON_L)) { wanted_dx -= 0x50; }
|
||||
if (sys_btn(DEVICE_BUTTON_R)) { wanted_dx += 0x50; }
|
||||
|
||||
// allow this if grounded or if it's not a change of direction
|
||||
if (
|
||||
game_player_grounded ||
|
||||
(sys_sgn_i32(wanted_dx) == sys_sgn_i32(game_player_dx))
|
||||
) {
|
||||
game_player_dx = wanted_dx;
|
||||
} else {
|
||||
// the smallest possible amount of movement without changing sign
|
||||
game_player_dx = sys_sgn_i32(game_player_dx);
|
||||
}
|
||||
}
|
||||
|
||||
if (game_player_grounded || game_player_coyote_frames > 0) {
|
||||
if (sys_btn(DEVICE_BUTTON_U)) {
|
||||
game_player_dy = -0x300;
|
||||
game_player_jump_frames = 15;
|
||||
game_player_grounded = false;
|
||||
}
|
||||
}
|
||||
|
||||
bool wants_to_go_higher = false;
|
||||
if (game_player_grounded) {
|
||||
game_player_coyote_frames = 5;
|
||||
if (game_player_dy > 0) { game_player_dy = 0; }
|
||||
if (game_player_dx < 0) { game_player_faceleft = true; }
|
||||
if (game_player_dx > 0) { game_player_faceleft = false; }
|
||||
if (sys_abs_i32(game_player_dx) < 0x20) { game_player_dx = 0; }
|
||||
}
|
||||
else {
|
||||
game_player_coyote_frames =
|
||||
sys_max_i32(0, game_player_coyote_frames - 1);
|
||||
wants_to_go_higher = sys_btn(DEVICE_BUTTON_U);
|
||||
bool is_going_higher = wants_to_go_higher && game_player_jump_frames > 0;
|
||||
if (game_player_dy >= 0 || !is_going_higher) {
|
||||
game_player_dy += 48;
|
||||
} else {
|
||||
game_player_jump_frames -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
// deduce animation state
|
||||
if (game_player_grounded) {
|
||||
if (game_player_dx == 0) {
|
||||
game_player_anim_transition(GAME_PLAYER_ANIM_STANDING);
|
||||
} else {
|
||||
game_player_anim_transition(GAME_PLAYER_ANIM_WALKING);
|
||||
game_player_anim_add_progress(
|
||||
sys_min_i32(sys_abs_i32(game_player_dx) / 0x10, 0x8)
|
||||
);
|
||||
}
|
||||
} else {
|
||||
if (wants_to_go_higher) {
|
||||
game_player_anim_transition(GAME_PLAYER_ANIM_FLOATING);
|
||||
} else {
|
||||
game_player_anim_transition(GAME_PLAYER_ANIM_STANDING);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void game_player_draw() {
|
||||
int game_player_image;
|
||||
switch (game_player_anim_state) {
|
||||
case GAME_PLAYER_ANIM_WALKING:
|
||||
game_player_image = 2 + (game_player_anim_progress / 0x80) * 2;
|
||||
break;
|
||||
case GAME_PLAYER_ANIM_FLOATING:
|
||||
game_player_image = 6;
|
||||
break;
|
||||
default:
|
||||
case GAME_PLAYER_ANIM_STANDING:
|
||||
game_player_image = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
sys_sprite_draw_ext(
|
||||
spr_game_player,
|
||||
game_player_image,
|
||||
game_player_bbox.x / 0x100,
|
||||
game_player_bbox.y / 0x100,
|
||||
2, 2,
|
||||
game_player_faceleft, false
|
||||
);
|
||||
}
|
||||
|
||||
void game_player_anim_transition(game_player_anim anim) {
|
||||
if (game_player_anim_state == anim) { return ;}
|
||||
game_player_anim_state = anim;
|
||||
game_player_anim_progress = 0;
|
||||
}
|
||||
|
||||
void game_player_anim_add_progress(uint8_t amt) {
|
||||
game_player_anim_progress = (
|
||||
(uint32_t) game_player_anim_progress +
|
||||
(uint32_t) amt
|
||||
) & 0xff;
|
||||
}
|
8
game/game_player.h
Normal file
8
game/game_player.h
Normal file
@ -0,0 +1,8 @@
|
||||
#ifndef GAME_PLAYER_H
|
||||
#define GAME_PLAYER_H
|
||||
|
||||
void game_player_init();
|
||||
void game_player_update();
|
||||
void game_player_draw();
|
||||
|
||||
#endif // GAME_PLAYER_H
|
@ -65,16 +65,16 @@ int main(int argc, char** argv) {
|
||||
|
||||
sdl_host_loop();
|
||||
|
||||
// renderer_cleanup:
|
||||
SDL_DestroyRenderer(sdl_host_renderer);
|
||||
sdl_host_renderer = NULL;
|
||||
renderer_done: ;
|
||||
|
||||
// target_cleanup:
|
||||
SDL_DestroyTexture(sdl_host_target);
|
||||
sdl_host_target = NULL;
|
||||
target_done: ;
|
||||
|
||||
// renderer_cleanup:
|
||||
SDL_DestroyRenderer(sdl_host_renderer);
|
||||
sdl_host_renderer = NULL;
|
||||
renderer_done: ;
|
||||
|
||||
// window_cleanup:
|
||||
SDL_DestroyWindow(sdl_host_window);
|
||||
sdl_host_window = NULL;
|
||||
|
@ -15,6 +15,10 @@ void sys_init() {
|
||||
sys_dpal_reset();
|
||||
}
|
||||
|
||||
void sys_update() {
|
||||
sys_input_update();
|
||||
}
|
||||
|
||||
bool sys_get_initialized() {
|
||||
return sys_initialized;
|
||||
}
|
||||
|
@ -10,6 +10,11 @@
|
||||
*/
|
||||
void sys_init();
|
||||
|
||||
/**
|
||||
* Update sys -- usually for input state.
|
||||
*/
|
||||
void sys_update();
|
||||
|
||||
/**
|
||||
* Return whether sys was initialized.
|
||||
*/
|
||||
|
36
sys/sys_input.c
Normal file
36
sys/sys_input.c
Normal file
@ -0,0 +1,36 @@
|
||||
#include "device/device.h"
|
||||
#include "sys/sys.h"
|
||||
#include "sys_input.h"
|
||||
|
||||
sys_i32 sys_input_down_frames[DEVICE_BUTTON_N];
|
||||
|
||||
void sys_input_update() {
|
||||
for (DeviceButton db = 0; db < DEVICE_BUTTON_N; db++) {
|
||||
if (device_buttons[db]) {
|
||||
sys_input_down_frames[db] += 1;
|
||||
} else {
|
||||
sys_input_down_frames[db] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void sys_input_reset() {
|
||||
for (DeviceButton db = 0; db < DEVICE_BUTTON_N; db++) {
|
||||
sys_input_down_frames[db] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool sys_btn(DeviceButton button) {
|
||||
if (button >= DEVICE_BUTTON_N) { return false; }
|
||||
return sys_input_down_frames[button] >= 1;
|
||||
}
|
||||
|
||||
bool sys_btnp(DeviceButton button) {
|
||||
if (button >= DEVICE_BUTTON_N) { return false; }
|
||||
if (sys_input_down_frames[button] == 1) { return true; }
|
||||
// 31 and every 8 frames after that
|
||||
if (sys_input_down_frames[button] >= 31 && (sys_input_down_frames[button] - 31) % 8 == 0) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
33
sys/sys_input.h
Normal file
33
sys/sys_input.h
Normal file
@ -0,0 +1,33 @@
|
||||
#ifndef SYS_INPUT_H
|
||||
#define SYS_INPUT_H
|
||||
|
||||
/**
|
||||
* Update the state of every button. Each button's btnp state depends
|
||||
* on how long it's been down, and calling this function adds one frame.
|
||||
*
|
||||
* Usually this is called by sys_update(), at the start of frame.
|
||||
*/
|
||||
void sys_input_update();
|
||||
|
||||
/**
|
||||
* Resets the input state -- all buttons have been held for 0 frames.
|
||||
*
|
||||
* If the buttons are held next frame, this will lead to a btnp().
|
||||
*
|
||||
* There's rarely any reason for user code to call this.
|
||||
*/
|
||||
void sys_input_reset();
|
||||
|
||||
/**
|
||||
* Return whether a button is down.
|
||||
*/
|
||||
bool sys_btn(DeviceButton button);
|
||||
|
||||
/**
|
||||
* Return whether a button was just pressed.
|
||||
*
|
||||
* Repeats after 30 frames, returning true every 8 frames after that.
|
||||
*/
|
||||
bool sys_btnp(DeviceButton button);
|
||||
|
||||
#endif // SYS_INPUT_H
|
Loading…
Reference in New Issue
Block a user