Compare commits
17 commits
0f887ea419
...
311b7f27df
Author | SHA1 | Date | |
---|---|---|---|
|
311b7f27df | ||
|
d555c5be6f | ||
|
4d2eb2e8de | ||
|
04d4c9e31e | ||
|
771d844bc4 | ||
|
ad902217ea | ||
|
cce7209221 | ||
|
b3b31bcfcd | ||
|
4b636bb428 | ||
|
a8ff55c1cf | ||
|
755ed1a1a8 | ||
|
6f16556fb4 | ||
|
5cc9216155 | ||
|
322610d723 | ||
|
a86462fdb2 | ||
|
6c5641e5e9 | ||
|
a8294d3542 |
|
@ -10,3 +10,4 @@ IndentCaseBlocks: true
|
||||||
IncludeBlocks: Regroup
|
IncludeBlocks: Regroup
|
||||||
AllowShortBlocksOnASingleLine: Empty
|
AllowShortBlocksOnASingleLine: Empty
|
||||||
ColumnLimit: 80
|
ColumnLimit: 80
|
||||||
|
AllowShortEnumsOnASingleLine: false
|
||||||
|
|
|
@ -33,6 +33,8 @@ set(SOURCES
|
||||||
src/dialogs.c
|
src/dialogs.c
|
||||||
src/npc.c
|
src/npc.c
|
||||||
src/events.c
|
src/events.c
|
||||||
|
src/animation.c
|
||||||
|
src/inventory.c
|
||||||
# ...
|
# ...
|
||||||
)
|
)
|
||||||
# Shared assets, fx-9860G-only assets and fx-CG-50-only assets
|
# Shared assets, fx-9860G-only assets and fx-CG-50-only assets
|
||||||
|
@ -55,6 +57,8 @@ set(ASSETS
|
||||||
set(ASSETS_cg
|
set(ASSETS_cg
|
||||||
assets-cg/player_male.png
|
assets-cg/player_male.png
|
||||||
assets-cg/player_female.png
|
assets-cg/player_female.png
|
||||||
|
assets-cg/player_male_inv.png
|
||||||
|
assets-cg/player_female_inv.png
|
||||||
assets-cg/npc/char/npc_male.png
|
assets-cg/npc/char/npc_male.png
|
||||||
assets-cg/npc/char/npc_female.png
|
assets-cg/npc/char/npc_female.png
|
||||||
assets-cg/npc/char/npc_milkman.png
|
assets-cg/npc/char/npc_milkman.png
|
||||||
|
@ -68,6 +72,8 @@ set(ASSETS_cg
|
||||||
assets-cg/INFO_Icon.png
|
assets-cg/INFO_Icon.png
|
||||||
assets-cg/player_face.png
|
assets-cg/player_face.png
|
||||||
assets-cg/font.png
|
assets-cg/font.png
|
||||||
|
assets-cg/inventory.png
|
||||||
|
assets-cg/items.png
|
||||||
)
|
)
|
||||||
|
|
||||||
set(ASSETS_cg_EGA64
|
set(ASSETS_cg_EGA64
|
||||||
|
@ -97,6 +103,8 @@ set(ASSETS_fx_1b
|
||||||
assets-fx/1b/npc/face/npc_milkman.png
|
assets-fx/1b/npc/face/npc_milkman.png
|
||||||
assets-fx/1b/npc/face/npc_police.png
|
assets-fx/1b/npc/face/npc_police.png
|
||||||
assets-fx/1b/INFO_Icon.png
|
assets-fx/1b/INFO_Icon.png
|
||||||
|
assets-fx/1b/inventory.png
|
||||||
|
assets-fx/1b/items.png
|
||||||
# ...
|
# ...
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -111,7 +119,9 @@ set(ASSETS_fx_2b
|
||||||
assets-fx/2b/npc/face/npc_female.png
|
assets-fx/2b/npc/face/npc_female.png
|
||||||
assets-fx/2b/npc/face/npc_milkman.png
|
assets-fx/2b/npc/face/npc_milkman.png
|
||||||
assets-fx/2b/npc/face/npc_police.png
|
assets-fx/2b/npc/face/npc_police.png
|
||||||
assets-fx/1b/INFO_Icon.png
|
assets-fx/2b/INFO_Icon.png
|
||||||
|
assets-fx/2b/inventory.png
|
||||||
|
assets-fx/2b/items.png
|
||||||
# ...
|
# ...
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -122,7 +132,7 @@ if("${FXSDK_PLATFORM_LONG}" STREQUAL fx9860G)
|
||||||
elseif("${FXSDK_PLATFORM_LONG}" STREQUAL fxCG50)
|
elseif("${FXSDK_PLATFORM_LONG}" STREQUAL fxCG50)
|
||||||
add_executable(myaddin ${SOURCES} ${ASSETS} ${ASSETS_${FXSDK_PLATFORM}} ${ASSETS_${FXSDK_PLATFORM}_${COLORMODE_cg}} )
|
add_executable(myaddin ${SOURCES} ${ASSETS} ${ASSETS_${FXSDK_PLATFORM}} ${ASSETS_${FXSDK_PLATFORM}_${COLORMODE_cg}} )
|
||||||
elseif("${FXSDK_PLATFORM_LONG}" STREQUAL fx9860G_G3A)
|
elseif("${FXSDK_PLATFORM_LONG}" STREQUAL fx9860G_G3A)
|
||||||
add_executable(myaddin ${SOURCES} ${ASSETS} ${ASSETS_${FXSDK_PLATFORM}} ${ASSETS_${FXSDK_PLATFORM}_${COLORMODE_fx}} )
|
add_executable(myaddin ${SOURCES} ${ASSETS} ${ASSETS_${FXSDK_PLATFORM}} ${ASSETS_${FXSDK_PLATFORM}_${COLORMODE_fx}} )
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
target_link_options(myaddin PRIVATE -Wl,-Map=Build_Addin.map -Wl,--print-memory-usage)
|
target_link_options(myaddin PRIVATE -Wl,-Map=Build_Addin.map -Wl,--print-memory-usage)
|
||||||
|
|
BIN
assets-cg/base_slot.png
Normal file
After Width: | Height: | Size: 223 B |
Before Width: | Height: | Size: 6.3 KiB After Width: | Height: | Size: 28 KiB |
BIN
assets-cg/inventory.ase
Normal file
BIN
assets-cg/inventory.png
Normal file
After Width: | Height: | Size: 2.8 KiB |
BIN
assets-cg/items.png
Normal file
After Width: | Height: | Size: 666 B |
Before Width: | Height: | Size: 221 B After Width: | Height: | Size: 382 B |
Before Width: | Height: | Size: 206 B After Width: | Height: | Size: 327 B |
Before Width: | Height: | Size: 222 B After Width: | Height: | Size: 343 B |
Before Width: | Height: | Size: 220 B After Width: | Height: | Size: 344 B |
Before Width: | Height: | Size: 238 B After Width: | Height: | Size: 380 B |
BIN
assets-cg/player_female_inv.png
Normal file
After Width: | Height: | Size: 536 B |
Before Width: | Height: | Size: 208 B After Width: | Height: | Size: 324 B |
BIN
assets-cg/player_male_inv.png
Normal file
After Width: | Height: | Size: 421 B |
BIN
assets-cg/selected.png
Normal file
After Width: | Height: | Size: 206 B |
BIN
assets-cg/selection.png
Normal file
After Width: | Height: | Size: 211 B |
|
@ -1,3 +1,11 @@
|
||||||
INFO_Icon.png:
|
INFO_Icon.png:
|
||||||
type: bopti-image
|
type: bopti-image
|
||||||
name: INFO_Icon_img
|
name: INFO_Icon_img
|
||||||
|
|
||||||
|
inventory.png:
|
||||||
|
type: bopti-image
|
||||||
|
name: inventory_img
|
||||||
|
|
||||||
|
items.png:
|
||||||
|
type: bopti-image
|
||||||
|
name: items_img
|
||||||
|
|
BIN
assets-fx/1b/inventory.png
Normal file
After Width: | Height: | Size: 608 B |
BIN
assets-fx/1b/items.png
Normal file
After Width: | Height: | Size: 181 B |
Before Width: | Height: | Size: 110 B After Width: | Height: | Size: 133 B |
Before Width: | Height: | Size: 109 B After Width: | Height: | Size: 128 B |
Before Width: | Height: | Size: 109 B After Width: | Height: | Size: 128 B |
Before Width: | Height: | Size: 109 B After Width: | Height: | Size: 128 B |
|
@ -1,3 +1,11 @@
|
||||||
INFO_Icon.png:
|
INFO_Icon.png:
|
||||||
type: bopti-image
|
type: bopti-image
|
||||||
name: INFO_Icon_img
|
name: INFO_Icon_img
|
||||||
|
|
||||||
|
inventory.png:
|
||||||
|
type: bopti-image
|
||||||
|
name: inventory_img
|
||||||
|
|
||||||
|
items.png:
|
||||||
|
type: bopti-image
|
||||||
|
name: items_img
|
||||||
|
|
BIN
assets-fx/2b/inventory.png
Normal file
After Width: | Height: | Size: 608 B |
BIN
assets-fx/2b/items.png
Normal file
After Width: | Height: | Size: 181 B |
Before Width: | Height: | Size: 115 B After Width: | Height: | Size: 148 B |
Before Width: | Height: | Size: 118 B After Width: | Height: | Size: 144 B |
Before Width: | Height: | Size: 118 B After Width: | Height: | Size: 144 B |
Before Width: | Height: | Size: 118 B After Width: | Height: | Size: 144 B |
Before Width: | Height: | Size: 110 B After Width: | Height: | Size: 134 B |
Before Width: | Height: | Size: 107 B After Width: | Height: | Size: 126 B |
BIN
assets-fx/selected.png
Normal file
After Width: | Height: | Size: 93 B |
BIN
assets-fx/selection.png
Normal file
After Width: | Height: | Size: 90 B |
31
src/animation.c
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
#include "animation.h"
|
||||||
|
|
||||||
|
#include <gint/display.h>
|
||||||
|
|
||||||
|
void animation_new(Animation *animation, bopti_image_t *image,
|
||||||
|
unsigned char len, unsigned short frame_ms) {
|
||||||
|
animation->image = image;
|
||||||
|
animation->frame = 0;
|
||||||
|
animation->len = len;
|
||||||
|
animation->frame_ms = frame_ms;
|
||||||
|
animation->current_ms = 0;
|
||||||
|
animation->width = image->width / len;
|
||||||
|
animation->height = image->height;
|
||||||
|
animation->wrap_dest = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void animation_draw(Animation *animation, int x, int y) {
|
||||||
|
dsubimage(x, y, animation->image, animation->frame * animation->width, 0,
|
||||||
|
animation->width, animation->height, DIMAGE_NONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void animation_update(Animation *animation, unsigned short frame_ms) {
|
||||||
|
animation->current_ms += frame_ms;
|
||||||
|
while(animation->current_ms > animation->frame_ms) {
|
||||||
|
animation->frame++;
|
||||||
|
if(animation->frame >= animation->len) {
|
||||||
|
animation->frame = animation->wrap_dest;
|
||||||
|
}
|
||||||
|
animation->current_ms -= animation->frame_ms;
|
||||||
|
}
|
||||||
|
}
|
27
src/animation.h
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
#ifndef ANIMATION_H
|
||||||
|
#define ANIMATION_H
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
unsigned char frame;
|
||||||
|
bopti_image_t *image;
|
||||||
|
unsigned char len;
|
||||||
|
unsigned short frame_ms;
|
||||||
|
int current_ms;
|
||||||
|
unsigned short width;
|
||||||
|
unsigned short height;
|
||||||
|
unsigned char wrap_dest;
|
||||||
|
} Animation;
|
||||||
|
|
||||||
|
/* TODO: Doc! */
|
||||||
|
void animation_new(Animation *animation, bopti_image_t *image,
|
||||||
|
unsigned char len, unsigned short frame_ms);
|
||||||
|
|
||||||
|
/* TODO: Doc! */
|
||||||
|
void animation_draw(Animation *animation, int x, int y);
|
||||||
|
|
||||||
|
/* TODO: Doc! */
|
||||||
|
void animation_update(Animation *animation, unsigned short frame_ms);
|
||||||
|
|
||||||
|
#endif
|
|
@ -12,6 +12,9 @@
|
||||||
#define GRAYMODEOK 1
|
#define GRAYMODEOK 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define SLOT_NUM 9
|
||||||
|
#define SLOT_COLUMNS 3
|
||||||
|
|
||||||
#if GINT_RENDER_RGB
|
#if GINT_RENDER_RGB
|
||||||
/* The tile size */
|
/* The tile size */
|
||||||
#define T_HEIGHT 16
|
#define T_HEIGHT 16
|
||||||
|
@ -22,6 +25,9 @@
|
||||||
/* The size of the player */
|
/* The size of the player */
|
||||||
#define P_WIDTH 16
|
#define P_WIDTH 16
|
||||||
#define P_HEIGHT 16
|
#define P_HEIGHT 16
|
||||||
|
/*Max number of dynamic NPCs.*/
|
||||||
|
#define NPC_STACK_SIZE 256
|
||||||
|
|
||||||
#else
|
#else
|
||||||
/* The tile size */
|
/* The tile size */
|
||||||
#define T_HEIGHT 8
|
#define T_HEIGHT 8
|
||||||
|
@ -32,6 +38,9 @@
|
||||||
/* The player size */
|
/* The player size */
|
||||||
#define P_WIDTH 8
|
#define P_WIDTH 8
|
||||||
#define P_HEIGHT 8
|
#define P_HEIGHT 8
|
||||||
|
/*Max number of "dynamic" NPCs. We are starved for static ram on fx !*/
|
||||||
|
#define NPC_STACK_SIZE 32
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* SPEED should NOT be 8 or bigger: it may cause bugs when handling
|
/* SPEED should NOT be 8 or bigger: it may cause bugs when handling
|
||||||
|
|
|
@ -48,7 +48,7 @@ int (*_operations[OP_AMOUNT])(int, int) = {_op_null, _op_set, _op_add, _op_sub,
|
||||||
|
|
||||||
#define MIN(a, b) a < b ? a : b
|
#define MIN(a, b) a < b ? a : b
|
||||||
|
|
||||||
char _message_buffer[MESSAGE_BUFFER_SZ];
|
char *_message_buffer;
|
||||||
char *events_parse_string(EventHandler *handler, char *message) {
|
char *events_parse_string(EventHandler *handler, char *message) {
|
||||||
size_t message_pos = 0;
|
size_t message_pos = 0;
|
||||||
char in_token = 0;
|
char in_token = 0;
|
||||||
|
|
|
@ -15,7 +15,11 @@ typedef struct {
|
||||||
unsigned int vars;
|
unsigned int vars;
|
||||||
} EventHandler;
|
} EventHandler;
|
||||||
|
|
||||||
typedef enum { T_NULL, T_VAR_EDIT, T_AMOUNT } Token;
|
typedef enum {
|
||||||
|
T_NULL,
|
||||||
|
T_VAR_EDIT,
|
||||||
|
T_AMOUNT
|
||||||
|
} Token;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
OP_NULL,
|
OP_NULL,
|
||||||
|
|
169
src/game.c
|
@ -1,7 +1,9 @@
|
||||||
#include "game.h"
|
#include "game.h"
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include "inventory.h"
|
||||||
#include "map.h"
|
#include "map.h"
|
||||||
|
#include "mapdata.h"
|
||||||
#include "npc.h"
|
#include "npc.h"
|
||||||
|
|
||||||
#include <gint/cpu.h>
|
#include <gint/cpu.h>
|
||||||
|
@ -11,6 +13,8 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
extern bopti_image_t SignAction_img;
|
extern bopti_image_t SignAction_img;
|
||||||
|
extern bopti_image_t player_male_img;
|
||||||
|
extern bopti_image_t tiny_npc_male;
|
||||||
|
|
||||||
extern Dialog *dialogRPG;
|
extern Dialog *dialogRPG;
|
||||||
// extern NPC *npcRPG;
|
// extern NPC *npcRPG;
|
||||||
|
@ -18,6 +22,24 @@ extern Dialog *dialogRPG;
|
||||||
|
|
||||||
#define MAX_INTERACTION_DISTANCE 12
|
#define MAX_INTERACTION_DISTANCE 12
|
||||||
|
|
||||||
|
void game_init(Game *game) {
|
||||||
|
game->map_level = worldRPG[0];
|
||||||
|
/* NPC animation */
|
||||||
|
animation_new(&game->npc_animation, &tiny_npc_male, 3, 250);
|
||||||
|
/* Wrapping back to 0 to skip the idle frame. */
|
||||||
|
game->npc_animation.wrap_dest = 1;
|
||||||
|
/* Player animation */
|
||||||
|
animation_new(&game->player.animation, &player_male_img, 3, 250);
|
||||||
|
/* Wrapping back to 1 to skip the idle frame. */
|
||||||
|
game->player.animation.wrap_dest = 1;
|
||||||
|
/* Add some event handlers (for testing only) */
|
||||||
|
events_init_handler(&game->handler);
|
||||||
|
events_bind_variable(&game->handler, (int *)&game->player.life, "life");
|
||||||
|
events_bind_variable(&game->handler, &game->mana, "mana");
|
||||||
|
|
||||||
|
// reload_npc(&game);
|
||||||
|
}
|
||||||
|
|
||||||
void interaction_available(Game *game) {
|
void interaction_available(Game *game) {
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
|
|
||||||
|
@ -114,6 +136,7 @@ void game_draw(Game *game) {
|
||||||
dprint(8, 8, C_BLACK, "npc_count: %d", npc_count);
|
dprint(8, 8, C_BLACK, "npc_count: %d", npc_count);
|
||||||
dprint(8, 16, C_BLACK, "Mana: %d", game->mana);
|
dprint(8, 16, C_BLACK, "Mana: %d", game->mana);
|
||||||
dprint(8, 24, C_BLACK, "X: %d Y: %d", game->player.x, game->player.y);
|
dprint(8, 24, C_BLACK, "X: %d Y: %d", game->player.x, game->player.y);
|
||||||
|
inventory_draw(game, &game->inventory);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Key management */
|
/* Key management */
|
||||||
|
@ -128,86 +151,102 @@ void game_get_inputs(Game *game) {
|
||||||
if(keydown(KEY_EXIT))
|
if(keydown(KEY_EXIT))
|
||||||
game->exittoOS = true;
|
game->exittoOS = true;
|
||||||
|
|
||||||
/* Player actions - Prototypes in player.h and implementation in player.c */
|
/* Inventory */
|
||||||
if(keydown(KEY_LEFT))
|
if(keydown(KEY_ALPHA)) {
|
||||||
player_move(game, D_LEFT);
|
game->inventory.open = !game->inventory.open;
|
||||||
if(keydown(KEY_RIGHT))
|
|
||||||
player_move(game, D_RIGHT);
|
|
||||||
if(keydown(KEY_UP))
|
|
||||||
player_move(game, D_UP);
|
|
||||||
if(keydown(KEY_DOWN))
|
|
||||||
player_move(game, D_DOWN);
|
|
||||||
if(keydown(KEY_SHIFT))
|
|
||||||
player_action(game);
|
|
||||||
if(keydown(KEY_OPTN)) {
|
|
||||||
game->player.is_male = !game->player.is_male;
|
|
||||||
/* TODO: Make something cleaner */
|
/* TODO: Make something cleaner */
|
||||||
while(keydown(KEY_OPTN)) {
|
while(keydown(KEY_ALPHA)) {
|
||||||
clearevents();
|
clearevents();
|
||||||
sleep();
|
sleep();
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
Player *player = &game->player;
|
/* Player actions - Prototypes in player.h and implementation in
|
||||||
if(keydown(KEY_SHIFT)) {
|
* player.c */
|
||||||
uint32_t i;
|
if(keydown(KEY_LEFT))
|
||||||
for(i = 0; i < game->map_level->nbPortal; i++) {
|
player_move(game, D_LEFT);
|
||||||
Portal *portal = &game->map_level->portals[i];
|
if(keydown(KEY_RIGHT))
|
||||||
if(player->x >= (int)portal->collider.x1 * PXSIZE &&
|
player_move(game, D_RIGHT);
|
||||||
player->x < (int)portal->collider.x2 * PXSIZE &&
|
if(keydown(KEY_UP))
|
||||||
player->y >= (int)portal->collider.y1 * PXSIZE &&
|
player_move(game, D_UP);
|
||||||
player->y < (int)portal->collider.y2 * PXSIZE) {
|
if(keydown(KEY_DOWN))
|
||||||
Portal *dest_portal = (Portal *)portal->portal;
|
player_move(game, D_DOWN);
|
||||||
Collider dest_collider = dest_portal->collider;
|
if(keydown(KEY_SHIFT))
|
||||||
Map *dest_map = (Map *)portal->map;
|
player_action(game);
|
||||||
player->x = (dest_collider.x1 + dest_collider.x2) / 2 * PXSIZE;
|
if(keydown(KEY_OPTN)) {
|
||||||
player->y = (dest_collider.y1 + dest_collider.y2) / 2 * PXSIZE;
|
game->player.is_male = !game->player.is_male;
|
||||||
game->map_level = dest_map;
|
/* TODO: Make something cleaner */
|
||||||
/* TODO: Make something cleaner */
|
while(keydown(KEY_OPTN)) {
|
||||||
while(keydown(KEY_SHIFT)) {
|
clearevents();
|
||||||
clearevents();
|
sleep();
|
||||||
sleep();
|
}
|
||||||
|
}
|
||||||
|
Player *player = &game->player;
|
||||||
|
if(keydown(KEY_SHIFT)) {
|
||||||
|
uint32_t i;
|
||||||
|
for(i = 0; i < game->map_level->nbPortal; i++) {
|
||||||
|
Portal *portal = &game->map_level->portals[i];
|
||||||
|
if(player->x >= (int)portal->collider.x1 * PXSIZE &&
|
||||||
|
player->x < (int)portal->collider.x2 * PXSIZE &&
|
||||||
|
player->y >= (int)portal->collider.y1 * PXSIZE &&
|
||||||
|
player->y < (int)portal->collider.y2 * PXSIZE) {
|
||||||
|
Portal *dest_portal = (Portal *)portal->portal;
|
||||||
|
Collider dest_collider = dest_portal->collider;
|
||||||
|
Map *dest_map = (Map *)portal->map;
|
||||||
|
player->x =
|
||||||
|
(dest_collider.x1 + dest_collider.x2) / 2 * PXSIZE;
|
||||||
|
player->y =
|
||||||
|
(dest_collider.y1 + dest_collider.y2) / 2 * PXSIZE;
|
||||||
|
game->map_level = dest_map;
|
||||||
|
/* TODO: Make something cleaner */
|
||||||
|
while(keydown(KEY_SHIFT)) {
|
||||||
|
clearevents();
|
||||||
|
sleep();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/*Temp debug*/
|
/*Temp debug*/
|
||||||
if(keydown(KEY_F1)) {
|
if(keydown(KEY_F1)) {
|
||||||
NPC *mynpc = npc_create();
|
NPC *mynpc = npc_create();
|
||||||
if(mynpc) {
|
if(mynpc) {
|
||||||
mynpc->curx = player->x;
|
mynpc->curx = (player->x << PRECISION) / PXSIZE;
|
||||||
mynpc->cury = player->y;
|
mynpc->cury = (player->y << PRECISION) / PXSIZE;
|
||||||
mynpc->x = 0;
|
mynpc->x = player->x;
|
||||||
mynpc->y = 0;
|
mynpc->y = player->x;
|
||||||
mynpc->hasPath = 0;
|
mynpc->hasPath = 0;
|
||||||
mynpc->face = 0;
|
mynpc->face = 0;
|
||||||
mynpc->paused = 0;
|
mynpc->paused = 0;
|
||||||
mynpc->has_dialog = 0;
|
mynpc->has_dialog = 0;
|
||||||
dprint(0, 50, 0, "succes");
|
}
|
||||||
dupdate();
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* Display Debug Information on screen */
|
/* Display Debug Information on screen */
|
||||||
#if DEBUGMODE
|
#if DEBUGMODE
|
||||||
if(keydown(KEY_F1)) {
|
if(keydown(KEY_F1)) {
|
||||||
game->debug_map = !game->debug_map;
|
game->debug_map = !game->debug_map;
|
||||||
}
|
}
|
||||||
if(keydown(KEY_F2)) {
|
if(keydown(KEY_F2)) {
|
||||||
game->debug_player = !game->debug_player;
|
game->debug_player = !game->debug_player;
|
||||||
}
|
}
|
||||||
if(keydown(KEY_F3)) {
|
if(keydown(KEY_F3)) {
|
||||||
game->debug_extra = !game->debug_extra;
|
game->debug_extra = !game->debug_extra;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* if USB is enabled - keybinding for screencapture */
|
/* if USB is enabled - keybinding for screencapture */
|
||||||
#if USB_FEATURE
|
#if USB_FEATURE
|
||||||
|
|
||||||
if(keydown(KEY_7))
|
if(keydown(KEY_7))
|
||||||
game->screenshot = true;
|
game->screenshot = true;
|
||||||
if(keydown(KEY_8))
|
if(keydown(KEY_8))
|
||||||
game->record = !game->record;
|
game->record = !game->record;
|
||||||
|
|
||||||
#endif // USB_FEATURE
|
#endif // USB_FEATURE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void game_update_animations(Game *game, unsigned char ms) {
|
||||||
|
animation_update(&game->npc_animation, ms);
|
||||||
|
animation_update(&game->player.animation, ms);
|
||||||
}
|
}
|
||||||
|
|
53
src/game.h
|
@ -1,20 +1,53 @@
|
||||||
#ifndef GAME_H
|
#ifndef GAME_H
|
||||||
#define GAME_H
|
#define GAME_H
|
||||||
|
|
||||||
|
#include "animation.h"
|
||||||
#include "events.h"
|
#include "events.h"
|
||||||
|
|
||||||
#include <gint/display.h>
|
#include <gint/display.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
/* The direction where the player is going to. */
|
/* The direction where the player is going to. */
|
||||||
typedef enum { D_UP, D_DOWN, D_LEFT, D_RIGHT } Direction;
|
typedef enum {
|
||||||
|
D_UP,
|
||||||
|
D_DOWN,
|
||||||
|
D_LEFT,
|
||||||
|
D_RIGHT
|
||||||
|
} Direction;
|
||||||
|
|
||||||
typedef enum { P_LEFTUP = -1, P_CENTER = 0, P_RIGHTDOWN = 1 } Checkpos;
|
typedef enum {
|
||||||
|
P_LEFTUP = -1,
|
||||||
|
P_CENTER = 0,
|
||||||
|
P_RIGHTDOWN = 1
|
||||||
|
} Checkpos;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
I_NONE,
|
||||||
|
I_ARMOR,
|
||||||
|
I_GLOVE,
|
||||||
|
I_SWORD,
|
||||||
|
I_BEER,
|
||||||
|
I_MILK,
|
||||||
|
I_TALISMAN,
|
||||||
|
I_AMOUNT
|
||||||
|
} Item;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
Item i;
|
||||||
|
unsigned char durability;
|
||||||
|
} Slot;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
Slot slots[SLOT_NUM];
|
||||||
|
Slot talisman;
|
||||||
|
Slot armor;
|
||||||
|
Slot weapon;
|
||||||
|
char open : 1;
|
||||||
|
} Inventory;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t x1, y1;
|
uint32_t x1, y1;
|
||||||
uint32_t x2, y2;
|
uint32_t x2, y2;
|
||||||
|
|
||||||
} Collider;
|
} Collider;
|
||||||
|
|
||||||
/* Struct that define player parameters */
|
/* Struct that define player parameters */
|
||||||
|
@ -34,6 +67,8 @@ typedef struct {
|
||||||
/* the player is interacting with a NPC */
|
/* the player is interacting with a NPC */
|
||||||
bool isInteractingWithNPC;
|
bool isInteractingWithNPC;
|
||||||
bool is_male;
|
bool is_male;
|
||||||
|
|
||||||
|
Animation animation;
|
||||||
} Player;
|
} Player;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -70,7 +105,8 @@ typedef struct {
|
||||||
} Sign;
|
} Sign;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
/* current coordinates of the NPC */
|
/* current coordinates of the NPC
|
||||||
|
* In 24:8 fixed point */
|
||||||
uint32_t curx;
|
uint32_t curx;
|
||||||
uint32_t cury;
|
uint32_t cury;
|
||||||
|
|
||||||
|
@ -172,9 +208,15 @@ typedef struct {
|
||||||
bool debug_player;
|
bool debug_player;
|
||||||
bool debug_extra;
|
bool debug_extra;
|
||||||
|
|
||||||
|
Animation npc_animation;
|
||||||
|
Inventory inventory;
|
||||||
|
|
||||||
int mana; /* Only for testing events TODO: Remove this! */
|
int mana; /* Only for testing events TODO: Remove this! */
|
||||||
} Game;
|
} Game;
|
||||||
|
|
||||||
|
/* TODO: Doc! */
|
||||||
|
void game_init(Game *game);
|
||||||
|
|
||||||
/* (Mibi88) TODO: Describe what this function is doing. */
|
/* (Mibi88) TODO: Describe what this function is doing. */
|
||||||
void game_logic(Game *game);
|
void game_logic(Game *game);
|
||||||
|
|
||||||
|
@ -200,4 +242,7 @@ void game_render_indicator(Game *game);
|
||||||
*/
|
*/
|
||||||
void game_get_inputs(Game *game);
|
void game_get_inputs(Game *game);
|
||||||
|
|
||||||
|
/* TODO: Doc! */
|
||||||
|
void game_update_animations(Game *game, unsigned char ms);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
51
src/inventory.c
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
#include "inventory.h"
|
||||||
|
|
||||||
|
#include <gint/display.h>
|
||||||
|
|
||||||
|
extern bopti_image_t inventory_img;
|
||||||
|
extern bopti_image_t items_img;
|
||||||
|
extern bopti_image_t player_male_inv_img;
|
||||||
|
extern bopti_image_t player_female_inv_img;
|
||||||
|
|
||||||
|
void inventory_draw(Game *game, Inventory *inventory) {
|
||||||
|
size_t i;
|
||||||
|
/* TODO: Cleanup! */
|
||||||
|
inventory->slots[5].i = I_GLOVE;
|
||||||
|
inventory->armor.i = I_ARMOR;
|
||||||
|
inventory->talisman.i = I_TALISMAN;
|
||||||
|
inventory->weapon.i = I_SWORD;
|
||||||
|
if(inventory->open) {
|
||||||
|
dimage(0, 0, &inventory_img);
|
||||||
|
for(i = 0; i < SLOT_NUM; i++) {
|
||||||
|
#if GINT_RENDER_RGB
|
||||||
|
dsubimage(272 + (i % SLOT_COLUMNS) * 32,
|
||||||
|
87 + (i / SLOT_COLUMNS) * 32, &items_img,
|
||||||
|
inventory->slots[i].i * 28, 0, 28, 27, DIMAGE_NONE);
|
||||||
|
#else
|
||||||
|
dsubimage(88 + (i % SLOT_COLUMNS) * 12,
|
||||||
|
24 + (i / SLOT_COLUMNS) * 12, &items_img,
|
||||||
|
inventory->slots[i].i * 8, 0, 8, 8, DIMAGE_NONE);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#if GINT_RENDER_RGB
|
||||||
|
dsubimage(222, 87, &items_img, inventory->talisman.i * 28, 0, 28, 27,
|
||||||
|
DIMAGE_NONE);
|
||||||
|
dsubimage(222, 87 + 32, &items_img, inventory->armor.i * 28, 0, 28, 27,
|
||||||
|
DIMAGE_NONE);
|
||||||
|
dsubimage(222, 87 + 64, &items_img, inventory->weapon.i * 28, 0, 28, 27,
|
||||||
|
DIMAGE_NONE);
|
||||||
|
#else
|
||||||
|
dsubimage(72, 24, &items_img, inventory->talisman.i * 8, 0, 8, 8,
|
||||||
|
DIMAGE_NONE);
|
||||||
|
dsubimage(72, 24 + 12, &items_img, inventory->armor.i * 8, 0, 8, 8,
|
||||||
|
DIMAGE_NONE);
|
||||||
|
dsubimage(72, 24 + 24, &items_img, inventory->weapon.i * 8, 0, 8, 8,
|
||||||
|
DIMAGE_NONE);
|
||||||
|
#endif
|
||||||
|
#if GINT_RENDER_RGB
|
||||||
|
dimage(183, 20,
|
||||||
|
game->player.is_male ? &player_male_inv_img
|
||||||
|
: &player_female_inv_img);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
9
src/inventory.h
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
#ifndef INVENTORY_H
|
||||||
|
#define INVENTORY_H
|
||||||
|
|
||||||
|
/* The structs related to the inventory are defined in game.h */
|
||||||
|
#include "game.h"
|
||||||
|
|
||||||
|
void inventory_draw(Game *game, Inventory *inventory);
|
||||||
|
|
||||||
|
#endif
|
42
src/main.c
|
@ -27,14 +27,25 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
extern bopti_image_t player_face_img;
|
/* extern bopti_image_t player_face_img; */
|
||||||
|
|
||||||
extern Map *worldRPG[];
|
extern Map *worldRPG[];
|
||||||
|
|
||||||
/* Game data (defined in "game.h")*/
|
/* Game data (defined in "game.h")*/
|
||||||
Game game = {
|
Game game = {
|
||||||
NULL,
|
NULL,
|
||||||
{12 * PXSIZE, 36 * PXSIZE, 0, 0, 100, SPEED, false, 0, false, false, true},
|
{12 * PXSIZE,
|
||||||
|
36 * PXSIZE,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
100,
|
||||||
|
SPEED,
|
||||||
|
false,
|
||||||
|
0,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
{}},
|
||||||
{{}, {}, 0},
|
{{}, {}, 0},
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
|
@ -45,7 +56,10 @@ Game game = {
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
100};
|
{},
|
||||||
|
{},
|
||||||
|
100,
|
||||||
|
};
|
||||||
|
|
||||||
/* screen capture management code. TODO: Clean this up! */
|
/* screen capture management code. TODO: Clean this up! */
|
||||||
|
|
||||||
|
@ -106,12 +120,18 @@ int main(void) {
|
||||||
}
|
}
|
||||||
timer_start(timer);
|
timer_start(timer);
|
||||||
|
|
||||||
game.map_level = worldRPG[0];
|
extern char *_message_buffer;
|
||||||
events_init_handler(&game.handler);
|
_message_buffer = NULL;
|
||||||
events_bind_variable(&game.handler, (int *)&game.player.life, "life");
|
_message_buffer = malloc(MESSAGE_BUFFER_SZ);
|
||||||
events_bind_variable(&game.handler, &game.mana, "mana");
|
if(!_message_buffer) {
|
||||||
|
dtext(64, 64, C_BLACK,
|
||||||
// reload_npc(&game);
|
"Failed to allocate the message buffer: not "
|
||||||
|
"enough RAM available. Press any key to quit.");
|
||||||
|
dupdate();
|
||||||
|
getkey();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
game_init(&game);
|
||||||
|
|
||||||
#if USB_FEATURE
|
#if USB_FEATURE
|
||||||
usb_interface_t const *interfaces[] = {&usb_ff_bulk, NULL};
|
usb_interface_t const *interfaces[] = {&usb_ff_bulk, NULL};
|
||||||
|
@ -189,6 +209,9 @@ int main(void) {
|
||||||
/* Run the game at max. 50fps */
|
/* Run the game at max. 50fps */
|
||||||
while(game.frame_duration < 20)
|
while(game.frame_duration < 20)
|
||||||
sleep();
|
sleep();
|
||||||
|
/* Calling it here to get the real frame duration (there is a lot of lag
|
||||||
|
on cg) */
|
||||||
|
game_update_animations(&game, (unsigned char)game.frame_duration);
|
||||||
/* Reset frame_duration for the next frame */
|
/* Reset frame_duration for the next frame */
|
||||||
game.frame_duration = 0;
|
game.frame_duration = 0;
|
||||||
} while(!game.exittoOS); // want to exit ?
|
} while(!game.exittoOS); // want to exit ?
|
||||||
|
@ -204,5 +227,6 @@ int main(void) {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
timer_stop(timer);
|
timer_stop(timer);
|
||||||
|
free(_message_buffer);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -180,8 +180,8 @@ void map_render_by_layer(Game *game, int layer) {
|
||||||
for(x = 0; x < dw; x++) {
|
for(x = 0; x < dw; x++) {
|
||||||
/* I get the tile number if his position is inside the map. Then
|
/* I get the tile number if his position is inside the map. Then
|
||||||
* I draw it. */
|
* I draw it. */
|
||||||
if(tx + x >= 0 && tx + x < map_level->w && ty + y >= 0 &&
|
if((tx + x >= 0) && (tx + x < (int)map_level->w) && (ty + y >= 0) &&
|
||||||
ty + y < map_level->h) {
|
(ty + y < (int)map_level->h)) {
|
||||||
/* index of the current tile */
|
/* index of the current tile */
|
||||||
int currentIndex = (y + ty) * map_level->w + tx + x;
|
int currentIndex = (y + ty) * map_level->w + tx + x;
|
||||||
/* we get the ID of the tile in the current drawable layers
|
/* we get the ID of the tile in the current drawable layers
|
||||||
|
|
35
src/npc.c
|
@ -16,13 +16,11 @@ extern bopti_image_t tiny_npc_female;
|
||||||
extern bopti_image_t tiny_npc_milkman;
|
extern bopti_image_t tiny_npc_milkman;
|
||||||
extern bopti_image_t tiny_npc_police;
|
extern bopti_image_t tiny_npc_police;
|
||||||
|
|
||||||
#define NPC_STACK_SIZE 256
|
|
||||||
|
|
||||||
NPC npc_stack[NPC_STACK_SIZE];
|
NPC npc_stack[NPC_STACK_SIZE];
|
||||||
uint32_t npc_count;
|
uint32_t npc_count;
|
||||||
|
|
||||||
NPC *npc_create() {
|
NPC *npc_create() {
|
||||||
if(npc_count == 256)
|
if(npc_count == NPC_STACK_SIZE)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
return &npc_stack[npc_count++];
|
return &npc_stack[npc_count++];
|
||||||
|
@ -60,9 +58,9 @@ int npc_append_path(uint16_t x, uint16_t y, NPC *npc) {
|
||||||
npc->ypath = realloc(npc->ypath, npc->path_length * 2 + 2);
|
npc->ypath = realloc(npc->ypath, npc->path_length * 2 + 2);
|
||||||
if(npc->xpath == NULL || npc->ypath == NULL)
|
if(npc->xpath == NULL || npc->ypath == NULL)
|
||||||
return 1;
|
return 1;
|
||||||
|
npc->xpath[npc->path_length] = x - npc->x;
|
||||||
|
npc->ypath[npc->path_length] = y - npc->y;
|
||||||
npc->path_length++;
|
npc->path_length++;
|
||||||
npc->xpath[npc->path_length - 1] = x - npc->x;
|
|
||||||
npc->ypath[npc->path_length - 1] = y - npc->y;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -260,8 +258,9 @@ void update_npc(NPC *npc) {
|
||||||
bopti_image_t *npc_sprites[FACES] = {&tiny_npc_male, &tiny_npc_female,
|
bopti_image_t *npc_sprites[FACES] = {&tiny_npc_male, &tiny_npc_female,
|
||||||
&tiny_npc_milkman, &tiny_npc_police};
|
&tiny_npc_milkman, &tiny_npc_police};
|
||||||
|
|
||||||
void npc_draw_single(NPC *npc, Player *pl) {
|
void npc_draw_single(NPC *npc, Game *game) {
|
||||||
|
|
||||||
|
Player *pl = &game->player;
|
||||||
/* Render the path if in debug and it has one*/
|
/* Render the path if in debug and it has one*/
|
||||||
#if DEBUGMODE
|
#if DEBUGMODE
|
||||||
if(npc->hasPath) {
|
if(npc->hasPath) {
|
||||||
|
@ -270,16 +269,16 @@ void npc_draw_single(NPC *npc, Player *pl) {
|
||||||
|
|
||||||
int16_t deltaX1 =
|
int16_t deltaX1 =
|
||||||
((int16_t)(npc->x + npc->xpath[v % NbPoints]) * PXSIZE) -
|
((int16_t)(npc->x + npc->xpath[v % NbPoints]) * PXSIZE) -
|
||||||
(int16_t)pl->wx;
|
(int16_t)pl->x;
|
||||||
int16_t deltaY1 =
|
int16_t deltaY1 =
|
||||||
((int16_t)(npc->y + npc->ypath[v % NbPoints]) * PXSIZE) -
|
((int16_t)(npc->y + npc->ypath[v % NbPoints]) * PXSIZE) -
|
||||||
(int16_t)pl->wy;
|
(int16_t)pl->y;
|
||||||
int16_t deltaX2 =
|
int16_t deltaX2 =
|
||||||
((int16_t)(npc->x + npc->xpath[(v + 1) % NbPoints]) * PXSIZE) -
|
((int16_t)(npc->x + npc->xpath[(v + 1) % NbPoints]) * PXSIZE) -
|
||||||
(int16_t)pl->wx;
|
(int16_t)pl->x;
|
||||||
int16_t deltaY2 =
|
int16_t deltaY2 =
|
||||||
((int16_t)(npc->y + npc->ypath[(v + 1) % NbPoints]) * PXSIZE) -
|
((int16_t)(npc->y + npc->ypath[(v + 1) % NbPoints]) * PXSIZE) -
|
||||||
(int16_t)pl->wy;
|
(int16_t)pl->y;
|
||||||
|
|
||||||
dline(pl->px + deltaX1, pl->py + deltaY1, pl->px + deltaX2,
|
dline(pl->px + deltaX1, pl->py + deltaY1, pl->px + deltaX2,
|
||||||
pl->py + deltaY2, PATH_COLOR);
|
pl->py + deltaY2, PATH_COLOR);
|
||||||
|
@ -289,19 +288,23 @@ void npc_draw_single(NPC *npc, Player *pl) {
|
||||||
|
|
||||||
int16_t delX = ((npc->curx * PXSIZE) >> PRECISION) - (int16_t)pl->x;
|
int16_t delX = ((npc->curx * PXSIZE) >> PRECISION) - (int16_t)pl->x;
|
||||||
int16_t delY = ((npc->cury * PXSIZE) >> PRECISION) - (int16_t)pl->y;
|
int16_t delY = ((npc->cury * PXSIZE) >> PRECISION) - (int16_t)pl->y;
|
||||||
bopti_image_t *face = npc_sprites[npc->face];
|
game->npc_animation.image = npc_sprites[npc->face];
|
||||||
dimage(pl->px - P_WIDTH / 2 + delX, pl->py - P_HEIGHT / 2 + delY, face);
|
unsigned char frame = game->npc_animation.frame;
|
||||||
|
if(npc->paused || !npc->hasPath)
|
||||||
|
game->npc_animation.frame = 0;
|
||||||
|
animation_draw(&game->npc_animation, pl->px - P_WIDTH / 2 + delX,
|
||||||
|
pl->py - P_HEIGHT / 2 + delY);
|
||||||
|
game->npc_animation.frame = frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
void npc_draw(Game *game) {
|
void npc_draw(Game *game) {
|
||||||
Player *pl = &game->player;
|
|
||||||
|
|
||||||
uint32_t u;
|
uint32_t u;
|
||||||
|
|
||||||
for(u = 0; u < game->map_level->nbNPC; u++) {
|
for(u = 0; u < game->map_level->nbNPC; u++) {
|
||||||
npc_draw_single(&game->map_level->npcs[u], pl);
|
npc_draw_single(&game->map_level->npcs[u], game);
|
||||||
}
|
}
|
||||||
for(u = 0; u < npc_count; u++) {
|
for(u = 0; u < npc_count; u++) {
|
||||||
npc_draw_single(&npc_stack[u], pl);
|
npc_draw_single(&npc_stack[u], game);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,6 @@ enum {
|
||||||
NPC_FRIENDLY = 1, // The player's team
|
NPC_FRIENDLY = 1, // The player's team
|
||||||
NPC_HOSTILE = 2, // to the player
|
NPC_HOSTILE = 2, // to the player
|
||||||
NPC_ALL = 3
|
NPC_ALL = 3
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* /!\ Warning /!\
|
/* /!\ Warning /!\
|
||||||
|
|
12
src/player.c
|
@ -7,6 +7,7 @@
|
||||||
#include "npc.h"
|
#include "npc.h"
|
||||||
|
|
||||||
#include <gint/display.h>
|
#include <gint/display.h>
|
||||||
|
#include <gint/keyboard.h>
|
||||||
|
|
||||||
extern bopti_image_t player_male_img;
|
extern bopti_image_t player_male_img;
|
||||||
extern bopti_image_t player_female_img;
|
extern bopti_image_t player_female_img;
|
||||||
|
@ -44,8 +45,15 @@ extern uint32_t nbNPC;
|
||||||
|
|
||||||
void player_draw(Game *game) {
|
void player_draw(Game *game) {
|
||||||
Player *player = &game->player;
|
Player *player = &game->player;
|
||||||
dimage(player->px - P_WIDTH / 2, player->py - P_HEIGHT / 2,
|
clearevents();
|
||||||
player->is_male ? &player_male_img : &player_female_img);
|
if(!keydown(KEY_LEFT) && !keydown(KEY_RIGHT) && !keydown(KEY_UP) &&
|
||||||
|
!keydown(KEY_DOWN)) {
|
||||||
|
game->player.animation.frame = 0;
|
||||||
|
}
|
||||||
|
player->animation.image =
|
||||||
|
player->is_male ? &player_male_img : &player_female_img;
|
||||||
|
animation_draw(&player->animation, player->px - P_WIDTH / 2,
|
||||||
|
player->py - P_HEIGHT / 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
void player_move(Game *game, Direction direction) {
|
void player_move(Game *game, Direction direction) {
|
||||||
|
|