Compare commits
No commits in common. "84043e31e7da7fe037b5351c65dcee93f0d4a651" and "7b3e3aaec81e2c3e2e114507cf18ae2d9e86c01b" have entirely different histories.
84043e31e7
...
7b3e3aaec8
|
@ -10,4 +10,3 @@ IndentCaseBlocks: true
|
|||
IncludeBlocks: Regroup
|
||||
AllowShortBlocksOnASingleLine: Empty
|
||||
ColumnLimit: 80
|
||||
AllowShortEnumsOnASingleLine: false
|
||||
|
|
|
@ -34,7 +34,6 @@ set(SOURCES
|
|||
src/npc.c
|
||||
src/events.c
|
||||
src/animation.c
|
||||
src/inventory.c
|
||||
# ...
|
||||
)
|
||||
# Shared assets, fx-9860G-only assets and fx-CG-50-only assets
|
||||
|
@ -57,8 +56,6 @@ set(ASSETS
|
|||
set(ASSETS_cg
|
||||
assets-cg/player_male.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_female.png
|
||||
assets-cg/npc/char/npc_milkman.png
|
||||
|
@ -72,10 +69,6 @@ set(ASSETS_cg
|
|||
assets-cg/INFO_Icon.png
|
||||
assets-cg/player_face.png
|
||||
assets-cg/font.png
|
||||
assets-cg/inventory.png
|
||||
assets-cg/items.png
|
||||
assets-cg/selection.png
|
||||
assets-cg/selected.png
|
||||
)
|
||||
|
||||
set(ASSETS_cg_EGA64
|
||||
|
@ -90,8 +83,6 @@ set(ASSETS_fx
|
|||
assets-fx/SGN_Icon.png
|
||||
assets-fx/player_face.png
|
||||
assets-fx/font.png
|
||||
assets-fx/selection.png
|
||||
assets-fx/selected.png
|
||||
# ...
|
||||
)
|
||||
|
||||
|
@ -107,8 +98,6 @@ set(ASSETS_fx_1b
|
|||
assets-fx/1b/npc/face/npc_milkman.png
|
||||
assets-fx/1b/npc/face/npc_police.png
|
||||
assets-fx/1b/INFO_Icon.png
|
||||
assets-fx/1b/inventory.png
|
||||
assets-fx/1b/items.png
|
||||
# ...
|
||||
)
|
||||
|
||||
|
@ -123,9 +112,7 @@ set(ASSETS_fx_2b
|
|||
assets-fx/2b/npc/face/npc_female.png
|
||||
assets-fx/2b/npc/face/npc_milkman.png
|
||||
assets-fx/2b/npc/face/npc_police.png
|
||||
assets-fx/2b/INFO_Icon.png
|
||||
assets-fx/2b/inventory.png
|
||||
assets-fx/2b/items.png
|
||||
assets-fx/1b/INFO_Icon.png
|
||||
# ...
|
||||
)
|
||||
|
||||
|
|
Before Width: | Height: | Size: 223 B |
Before Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 684 B |
Before Width: | Height: | Size: 536 B |
Before Width: | Height: | Size: 421 B |
Before Width: | Height: | Size: 206 B |
Before Width: | Height: | Size: 211 B |
|
@ -1,11 +1,3 @@
|
|||
INFO_Icon.png:
|
||||
type: bopti-image
|
||||
name: INFO_Icon_img
|
||||
|
||||
inventory.png:
|
||||
type: bopti-image
|
||||
name: inventory_img
|
||||
|
||||
items.png:
|
||||
type: bopti-image
|
||||
name: items_img
|
||||
|
|
Before Width: | Height: | Size: 608 B |
Before Width: | Height: | Size: 181 B |
|
@ -1,11 +1,3 @@
|
|||
INFO_Icon.png:
|
||||
type: bopti-image
|
||||
name: INFO_Icon_img
|
||||
|
||||
inventory.png:
|
||||
type: bopti-image
|
||||
name: inventory_img
|
||||
|
||||
items.png:
|
||||
type: bopti-image
|
||||
name: items_img
|
||||
|
|
Before Width: | Height: | Size: 608 B |
Before Width: | Height: | Size: 181 B |
|
@ -17,14 +17,6 @@ SGN_Icon.png:
|
|||
type: bopti-image
|
||||
name: SGN_Icon_img
|
||||
|
||||
selection.png:
|
||||
type: bopti-image
|
||||
name: selection_img
|
||||
|
||||
selected.png:
|
||||
type: bopti-image
|
||||
name: selected_img
|
||||
|
||||
font.png:
|
||||
name: fontRPG
|
||||
type: font
|
||||
|
|
Before Width: | Height: | Size: 93 B |
Before Width: | Height: | Size: 90 B |
|
@ -142,7 +142,7 @@ def convert_map(input: str, output: str, params: dict, target):
|
|||
indoor = int(input_map.get_property("indoor"))
|
||||
except Exception as e:
|
||||
# Show a warning
|
||||
print(f"WARNING: Indoor property not found.")
|
||||
print(f"WARNING: Indoor property not found.\n")
|
||||
|
||||
if indoor:
|
||||
# Get the indoor tileset
|
||||
|
|
23
src/config.h
|
@ -12,9 +12,6 @@
|
|||
#define GRAYMODEOK 1
|
||||
#endif
|
||||
|
||||
#define SLOT_NUM 9
|
||||
#define SLOT_COLUMNS 3
|
||||
|
||||
#if GINT_RENDER_RGB
|
||||
/* The tile size */
|
||||
#define T_HEIGHT 16
|
||||
|
@ -25,15 +22,9 @@
|
|||
/* The size of the player */
|
||||
#define P_WIDTH 16
|
||||
#define P_HEIGHT 16
|
||||
/* Max number of dynamic NPCs. */
|
||||
/*Max number of dynamic NPCs.*/
|
||||
#define NPC_STACK_SIZE 256
|
||||
/* The position of the slots in the inventory */
|
||||
#define SLOT_Y 87
|
||||
#define SLOT_X_EQUIPPED 222
|
||||
#define SLOT_X 272
|
||||
#define SLOT_W 28
|
||||
#define SLOT_H 27
|
||||
#define SLOT_SPACING 32
|
||||
|
||||
#else
|
||||
/* The tile size */
|
||||
#define T_HEIGHT 8
|
||||
|
@ -44,15 +35,9 @@
|
|||
/* The player size */
|
||||
#define P_WIDTH 8
|
||||
#define P_HEIGHT 8
|
||||
/* Max number of "dynamic" NPCs. We are starved for static ram on fx ! */
|
||||
/*Max number of "dynamic" NPCs. We are starved for static ram on fx !*/
|
||||
#define NPC_STACK_SIZE 32
|
||||
/* The position of the slots in the inventory */
|
||||
#define SLOT_Y 24
|
||||
#define SLOT_X_EQUIPPED 72
|
||||
#define SLOT_X 88
|
||||
#define SLOT_W 8
|
||||
#define SLOT_H 8
|
||||
#define SLOT_SPACING 12
|
||||
|
||||
#endif
|
||||
|
||||
/* 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
|
||||
|
||||
char *_message_buffer;
|
||||
char _message_buffer[MESSAGE_BUFFER_SZ];
|
||||
char *events_parse_string(EventHandler *handler, char *message) {
|
||||
size_t message_pos = 0;
|
||||
char in_token = 0;
|
||||
|
|
|
@ -15,11 +15,7 @@ typedef struct {
|
|||
unsigned int vars;
|
||||
} EventHandler;
|
||||
|
||||
typedef enum {
|
||||
T_NULL,
|
||||
T_VAR_EDIT,
|
||||
T_AMOUNT
|
||||
} Token;
|
||||
typedef enum { T_NULL, T_VAR_EDIT, T_AMOUNT } Token;
|
||||
|
||||
typedef enum {
|
||||
OP_NULL,
|
||||
|
|
220
src/game.c
|
@ -1,7 +1,6 @@
|
|||
#include "game.h"
|
||||
|
||||
#include "config.h"
|
||||
#include "inventory.h"
|
||||
#include "map.h"
|
||||
#include "mapdata.h"
|
||||
#include "npc.h"
|
||||
|
@ -36,11 +35,6 @@ void game_init(Game *game) {
|
|||
events_init_handler(&game->handler);
|
||||
events_bind_variable(&game->handler, (int *)&game->player.life, "life");
|
||||
events_bind_variable(&game->handler, &game->mana, "mana");
|
||||
inventory_init(&game->inventory);
|
||||
/* For debugging */
|
||||
game->inventory.slots[5].i = I_GLOVE;
|
||||
game->inventory.slots[1].i = I_ARMOR;
|
||||
game->inventory.slots[8].i = I_TALISMAN;
|
||||
|
||||
// reload_npc(&game);
|
||||
}
|
||||
|
@ -127,10 +121,8 @@ void game_render_indicator(Game *game) {
|
|||
|
||||
/* Draw everything. */
|
||||
void game_draw(Game *game) {
|
||||
/* Only clear if we are inside, the screen is guaranteed to be filled
|
||||
/*Only clear if we are inside, the screen is guaranteed to be filled
|
||||
* otherwise */
|
||||
/* (Mibi88) if we do so, we should only use opaque tiles in the background
|
||||
layer (it's currently not the case), to artefacts when rendering dialogs. */
|
||||
if(game->map_level->indoor)
|
||||
dclear(C_WHITE);
|
||||
map_render_by_layer(game, BACKGROUND);
|
||||
|
@ -143,7 +135,6 @@ void game_draw(Game *game) {
|
|||
dprint(8, 8, C_BLACK, "npc_count: %d", npc_count);
|
||||
dprint(8, 16, C_BLACK, "Mana: %d", game->mana);
|
||||
dprint(8, 24, C_BLACK, "X: %d Y: %d", game->player.x, game->player.y);
|
||||
inventory_draw(&game->inventory, &game->player);
|
||||
}
|
||||
|
||||
/* Key management */
|
||||
|
@ -158,161 +149,98 @@ void game_get_inputs(Game *game) {
|
|||
if(keydown(KEY_EXIT))
|
||||
game->exittoOS = true;
|
||||
|
||||
/* Inventory */
|
||||
if(keydown(KEY_ALPHA)) {
|
||||
game->inventory.open = !game->inventory.open;
|
||||
/* TODO: Make something cleaner */
|
||||
while(keydown(KEY_ALPHA)) {
|
||||
clearevents();
|
||||
sleep();
|
||||
}
|
||||
} else if(game->inventory.open) {
|
||||
if(keydown(KEY_LEFT))
|
||||
inventory_move_selection(&game->inventory, D_LEFT);
|
||||
/* TODO: Make something cleaner */
|
||||
while(keydown(KEY_LEFT)) {
|
||||
clearevents();
|
||||
sleep();
|
||||
}
|
||||
if(keydown(KEY_RIGHT))
|
||||
inventory_move_selection(&game->inventory, D_RIGHT);
|
||||
/* TODO: Make something cleaner */
|
||||
while(keydown(KEY_RIGHT)) {
|
||||
clearevents();
|
||||
sleep();
|
||||
}
|
||||
if(keydown(KEY_UP))
|
||||
inventory_move_selection(&game->inventory, D_UP);
|
||||
/* TODO: Make something cleaner */
|
||||
while(keydown(KEY_UP)) {
|
||||
clearevents();
|
||||
sleep();
|
||||
}
|
||||
if(keydown(KEY_DOWN))
|
||||
inventory_move_selection(&game->inventory, D_DOWN);
|
||||
/* TODO: Make something cleaner */
|
||||
while(keydown(KEY_DOWN)) {
|
||||
clearevents();
|
||||
sleep();
|
||||
}
|
||||
if(keydown(KEY_OPTN))
|
||||
inventory_move_from_selected(&game->inventory);
|
||||
/* Player actions - Prototypes in player.h and implementation in player.c */
|
||||
if(keydown(KEY_LEFT))
|
||||
player_move(game, D_LEFT);
|
||||
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 */
|
||||
while(keydown(KEY_OPTN)) {
|
||||
clearevents();
|
||||
sleep();
|
||||
}
|
||||
if(keydown(KEY_SQUARE)) {
|
||||
inventory_use(&game->inventory, &game->player);
|
||||
}
|
||||
if(keydown(KEY_F1)) {
|
||||
inventory_unequip(&game->inventory, IT_TALISMAN);
|
||||
}
|
||||
if(keydown(KEY_F2)) {
|
||||
inventory_unequip(&game->inventory, IT_ARMOR);
|
||||
}
|
||||
if(keydown(KEY_F3)) {
|
||||
inventory_unequip(&game->inventory, IT_WEAPON);
|
||||
}
|
||||
if(keydown(KEY_SHIFT))
|
||||
game->inventory.selected = game->inventory.selection;
|
||||
} else {
|
||||
/* Player actions - Prototypes in player.h and implementation in
|
||||
* player.c */
|
||||
if(keydown(KEY_LEFT))
|
||||
player_move(game, D_LEFT);
|
||||
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 */
|
||||
while(keydown(KEY_OPTN)) {
|
||||
clearevents();
|
||||
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();
|
||||
}
|
||||
}
|
||||
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*/
|
||||
if(keydown(KEY_F1)) {
|
||||
NPC *mynpc = npc_create();
|
||||
if(mynpc) {
|
||||
mynpc->curx = (player->x << PRECISION) / PXSIZE;
|
||||
mynpc->cury = (player->y << PRECISION) / PXSIZE;
|
||||
mynpc->x = player->x;
|
||||
mynpc->y = player->x;
|
||||
mynpc->hasPath = 0;
|
||||
mynpc->owns_path = false;
|
||||
mynpc->face = 0;
|
||||
mynpc->paused = 0;
|
||||
mynpc->has_dialog = 0;
|
||||
mynpc->xpath = NULL;
|
||||
mynpc->ypath = NULL;
|
||||
}
|
||||
while(keydown(KEY_F1)) {
|
||||
clearevents();
|
||||
}
|
||||
/*Temp debug*/
|
||||
if(keydown(KEY_F1)) {
|
||||
NPC *mynpc = npc_create();
|
||||
if(mynpc) {
|
||||
mynpc->curx = (player->x << PRECISION) / PXSIZE;
|
||||
mynpc->cury = (player->y << PRECISION) / PXSIZE;
|
||||
mynpc->x = player->x;
|
||||
mynpc->y = player->x;
|
||||
mynpc->hasPath = 0;
|
||||
mynpc->owns_path = false;
|
||||
mynpc->face = 1;
|
||||
mynpc->paused = 0;
|
||||
mynpc->has_dialog = 0;
|
||||
mynpc->xpath = NULL;
|
||||
mynpc->ypath = NULL;
|
||||
}
|
||||
if(keydown(KEY_F2)) {
|
||||
npc_remove_pos(0);
|
||||
while(keydown(KEY_F2)) {
|
||||
clearevents();
|
||||
}
|
||||
while(keydown(KEY_F1)) {
|
||||
clearevents();
|
||||
}
|
||||
}
|
||||
if(keydown(KEY_F2)) {
|
||||
npc_remove_pos(0);
|
||||
while(keydown(KEY_F2)) {
|
||||
clearevents();
|
||||
}
|
||||
}
|
||||
|
||||
/* Display Debug Information on screen */
|
||||
/* Display Debug Information on screen */
|
||||
#if DEBUGMODE
|
||||
if(keydown(KEY_F1)) {
|
||||
game->debug_map = !game->debug_map;
|
||||
}
|
||||
if(keydown(KEY_F2)) {
|
||||
game->debug_player = !game->debug_player;
|
||||
}
|
||||
if(keydown(KEY_F3)) {
|
||||
game->debug_extra = !game->debug_extra;
|
||||
}
|
||||
if(keydown(KEY_F1)) {
|
||||
game->debug_map = !game->debug_map;
|
||||
}
|
||||
if(keydown(KEY_F2)) {
|
||||
game->debug_player = !game->debug_player;
|
||||
}
|
||||
if(keydown(KEY_F3)) {
|
||||
game->debug_extra = !game->debug_extra;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* if USB is enabled - keybinding for screencapture */
|
||||
/* if USB is enabled - keybinding for screencapture */
|
||||
#if USB_FEATURE
|
||||
|
||||
if(keydown(KEY_7))
|
||||
game->screenshot = true;
|
||||
if(keydown(KEY_8))
|
||||
game->record = !game->record;
|
||||
if(keydown(KEY_7))
|
||||
game->screenshot = true;
|
||||
if(keydown(KEY_8))
|
||||
game->record = !game->record;
|
||||
|
||||
#endif // USB_FEATURE
|
||||
}
|
||||
}
|
||||
|
||||
void game_update_animations(Game *game, unsigned char ms) {
|
||||
|
|
53
src/game.h
|
@ -8,59 +8,14 @@
|
|||
#include <stdint.h>
|
||||
|
||||
/* 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 {
|
||||
I_NONE,
|
||||
I_ARMOR,
|
||||
I_GLOVE,
|
||||
I_SWORD,
|
||||
I_BEER,
|
||||
I_MILK,
|
||||
I_TALISMAN,
|
||||
I_AMOUNT
|
||||
} Item;
|
||||
|
||||
typedef enum {
|
||||
IT_NONE,
|
||||
IT_TALISMAN,
|
||||
IT_ARMOR,
|
||||
IT_WEAPON,
|
||||
IT_FOOD,
|
||||
IT_AMOUNT
|
||||
} ItemType;
|
||||
|
||||
typedef struct {
|
||||
Item i : 4;
|
||||
unsigned char durability;
|
||||
} Slot;
|
||||
|
||||
typedef struct {
|
||||
/* Backpack slots. */
|
||||
Slot slots[SLOT_NUM];
|
||||
/* Equipped items: first slot: talisman, second slot: armor, last slot:
|
||||
weapon. */
|
||||
Slot equipped[3];
|
||||
/* 1 if the inventory is open. */
|
||||
char open : 1;
|
||||
char selected;
|
||||
char selection;
|
||||
} Inventory;
|
||||
typedef enum { P_LEFTUP = -1, P_CENTER = 0, P_RIGHTDOWN = 1 } Checkpos;
|
||||
|
||||
typedef struct {
|
||||
uint32_t x1, y1;
|
||||
uint32_t x2, y2;
|
||||
|
||||
} Collider;
|
||||
|
||||
/* Struct that define player parameters */
|
||||
|
@ -154,7 +109,6 @@ typedef struct {
|
|||
uint8_t current_group;
|
||||
uint8_t hostile_to_group;
|
||||
|
||||
/* uint16_t to keep the struct aligned */
|
||||
uint16_t __padding;
|
||||
} NPC;
|
||||
|
||||
|
@ -224,7 +178,6 @@ typedef struct {
|
|||
bool debug_extra;
|
||||
|
||||
Animation npc_animation;
|
||||
Inventory inventory;
|
||||
|
||||
int mana; /* Only for testing events TODO: Remove this! */
|
||||
} Game;
|
||||
|
|
151
src/inventory.c
|
@ -1,151 +0,0 @@
|
|||
#include "inventory.h"
|
||||
|
||||
#include <gint/display.h>
|
||||
#include <string.h>
|
||||
|
||||
extern bopti_image_t inventory_img;
|
||||
extern bopti_image_t items_img;
|
||||
extern bopti_image_t selection_img;
|
||||
extern bopti_image_t selected_img;
|
||||
extern bopti_image_t player_male_inv_img;
|
||||
extern bopti_image_t player_female_inv_img;
|
||||
|
||||
char item_types[I_AMOUNT] = {IT_NONE, IT_ARMOR, IT_WEAPON, IT_WEAPON,
|
||||
IT_FOOD, IT_FOOD, IT_TALISMAN};
|
||||
|
||||
void inventory_init(Inventory *inventory) {
|
||||
inventory->open = 0;
|
||||
memset(inventory->slots, 0, sizeof(Slot) * SLOT_NUM);
|
||||
memset(inventory->equipped, 0, sizeof(Slot) * 3);
|
||||
inventory->selected = -1;
|
||||
inventory->selection = 0;
|
||||
}
|
||||
|
||||
void inventory_draw(Inventory *inventory, Player *player) {
|
||||
size_t i;
|
||||
if(inventory->open) {
|
||||
dimage(0, 0, &inventory_img);
|
||||
for(i = 0; i < SLOT_NUM; i++) {
|
||||
dsubimage(SLOT_X + (i % SLOT_COLUMNS) * SLOT_SPACING,
|
||||
SLOT_Y + (i / SLOT_COLUMNS) * SLOT_SPACING, &items_img,
|
||||
inventory->slots[i].i * SLOT_W, 0, SLOT_W, SLOT_H,
|
||||
DIMAGE_NONE);
|
||||
if(i == inventory->selection) {
|
||||
dimage(SLOT_X + (i % SLOT_COLUMNS) * SLOT_SPACING,
|
||||
SLOT_Y + (i / SLOT_COLUMNS) * SLOT_SPACING,
|
||||
&selection_img);
|
||||
}
|
||||
if(i == inventory->selected) {
|
||||
dimage(SLOT_X + (i % SLOT_COLUMNS) * SLOT_SPACING,
|
||||
SLOT_Y + (i / SLOT_COLUMNS) * SLOT_SPACING,
|
||||
&selected_img);
|
||||
}
|
||||
}
|
||||
for(i = 0; i < 3; i++) {
|
||||
dsubimage(SLOT_X_EQUIPPED, SLOT_Y + i * SLOT_SPACING, &items_img,
|
||||
inventory->equipped[i].i * SLOT_W, 0, SLOT_W, SLOT_H,
|
||||
DIMAGE_NONE);
|
||||
}
|
||||
#if GINT_RENDER_RGB
|
||||
/* Render the player between the two swords if we are on cg. */
|
||||
dimage(183, 20,
|
||||
player->is_male ? &player_male_inv_img : &player_female_inv_img);
|
||||
#endif
|
||||
}
|
||||
/* TODO: Stats. */
|
||||
}
|
||||
|
||||
char inventory_add(Inventory *inventory, Item item) {
|
||||
size_t i;
|
||||
for(i = 0; i < SLOT_NUM; i++) {
|
||||
if(!inventory->slots[i].i) {
|
||||
inventory->slots[i].i = item;
|
||||
inventory->slots[i].durability = 255;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void inventory_move_from_selected(Inventory *inventory) {
|
||||
if(inventory->selected < 0)
|
||||
return;
|
||||
Slot current = inventory->slots[inventory->selection];
|
||||
Slot new = inventory->slots[inventory->selected];
|
||||
inventory->slots[inventory->selection] = new;
|
||||
inventory->slots[inventory->selected] = current;
|
||||
}
|
||||
|
||||
void inventory_use(Inventory *inventory, Player *player) {
|
||||
Item item = inventory->slots[inventory->selection].i;
|
||||
switch(item_types[item]) {
|
||||
case IT_TALISMAN:
|
||||
inventory->equipped[0] = inventory->slots[inventory->selection];
|
||||
break;
|
||||
case IT_ARMOR:
|
||||
inventory->equipped[1] = inventory->slots[inventory->selection];
|
||||
break;
|
||||
case IT_WEAPON:
|
||||
inventory->equipped[2] = inventory->slots[inventory->selection];
|
||||
break;
|
||||
case IT_FOOD:
|
||||
/* TODO */
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
inventory->slots[inventory->selection].i = I_NONE;
|
||||
inventory->slots[inventory->selection].durability = 255;
|
||||
}
|
||||
|
||||
void inventory_unequip(Inventory *inventory, ItemType type) {
|
||||
if(inventory->slots[inventory->selection].i)
|
||||
return;
|
||||
switch(type) {
|
||||
case IT_TALISMAN:
|
||||
inventory->slots[inventory->selection] = inventory->equipped[0];
|
||||
inventory->equipped[0].i = I_NONE;
|
||||
inventory->equipped[0].durability = 255;
|
||||
break;
|
||||
case IT_ARMOR:
|
||||
inventory->slots[inventory->selection] = inventory->equipped[1];
|
||||
inventory->equipped[1].i = I_NONE;
|
||||
inventory->equipped[1].durability = 255;
|
||||
break;
|
||||
case IT_WEAPON:
|
||||
inventory->slots[inventory->selection] = inventory->equipped[2];
|
||||
inventory->equipped[2].i = I_NONE;
|
||||
inventory->equipped[2].durability = 255;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void inventory_move_selection(Inventory *inventory, Direction direction) {
|
||||
switch(direction) {
|
||||
case D_UP:
|
||||
inventory->selection -= SLOT_COLUMNS;
|
||||
if(inventory->selection < 0)
|
||||
inventory->selection = 0;
|
||||
break;
|
||||
case D_DOWN:
|
||||
inventory->selection += SLOT_COLUMNS;
|
||||
if(inventory->selection >= SLOT_NUM) {
|
||||
inventory->selection = SLOT_NUM - 1;
|
||||
}
|
||||
break;
|
||||
case D_LEFT:
|
||||
if(inventory->selection > 0) {
|
||||
inventory->selection--;
|
||||
}
|
||||
break;
|
||||
case D_RIGHT:
|
||||
if(inventory->selection < SLOT_NUM - 1) {
|
||||
inventory->selection++;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
#ifndef INVENTORY_H
|
||||
#define INVENTORY_H
|
||||
|
||||
/* The structs related to the inventory are defined in game.h */
|
||||
#include "game.h"
|
||||
|
||||
void inventory_init(Inventory *inventory);
|
||||
void inventory_draw(Inventory *inventory, Player *player);
|
||||
char inventory_add(Inventory *inventory, Item item);
|
||||
void inventory_move_from_selected(Inventory *inventory);
|
||||
void inventory_use(Inventory *inventory, Player *player);
|
||||
void inventory_unequip(Inventory *inventory, ItemType type);
|
||||
void inventory_move_selection(Inventory *inventory, Direction direction);
|
||||
|
||||
#endif
|
63
src/main.c
|
@ -32,34 +32,31 @@
|
|||
extern Map *worldRPG[];
|
||||
|
||||
/* Game data (defined in "game.h")*/
|
||||
Game game = {
|
||||
NULL,
|
||||
{12 * PXSIZE,
|
||||
36 * PXSIZE,
|
||||
0,
|
||||
0,
|
||||
100,
|
||||
SPEED,
|
||||
false,
|
||||
0,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
{}},
|
||||
{{}, {}, 0},
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
0,
|
||||
Game game = {NULL,
|
||||
{12 * PXSIZE,
|
||||
36 * PXSIZE,
|
||||
0,
|
||||
0,
|
||||
100,
|
||||
SPEED,
|
||||
false,
|
||||
0,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
{}},
|
||||
{{}, {}, 0},
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
0,
|
||||
|
||||
/* debug variables*/
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
{},
|
||||
{},
|
||||
100,
|
||||
};
|
||||
/* debug variables*/
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
{},
|
||||
100};
|
||||
|
||||
/* screen capture management code. TODO: Clean this up! */
|
||||
|
||||
|
@ -120,17 +117,6 @@ int main(void) {
|
|||
}
|
||||
timer_start(timer);
|
||||
|
||||
extern char *_message_buffer;
|
||||
_message_buffer = NULL;
|
||||
_message_buffer = malloc(MESSAGE_BUFFER_SZ);
|
||||
if(!_message_buffer) {
|
||||
dtext(64, 64, C_BLACK,
|
||||
"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
|
||||
|
@ -227,6 +213,5 @@ int main(void) {
|
|||
#endif
|
||||
|
||||
timer_stop(timer);
|
||||
free(_message_buffer);
|
||||
return 1;
|
||||
}
|
||||
|
|
65
src/npc.c
|
@ -91,49 +91,44 @@ void as_clean(uint8_t *visited, uint8_t *gscore, uint8_t *fscore) {
|
|||
free(fscore);
|
||||
}
|
||||
|
||||
int as_reconstruct_path(int16_t *came_from, int w, int h, int16_t start,
|
||||
int16_t dest, bool is_alloc, NPC *npc) {
|
||||
// TODO : Fix
|
||||
int as_reconstruct_path(int16_t *came_from, int w, int h, int16_t spos,
|
||||
int16_t dest, NPC *npc) {
|
||||
if(npc_clear_path(npc))
|
||||
goto as_recons_fail;
|
||||
|
||||
int16_t prev = came_from[dest];
|
||||
int16_t next = came_from[dest];
|
||||
|
||||
uint32_t i;
|
||||
int x, y;
|
||||
unsigned int i;
|
||||
|
||||
for(i = 0; i < PATHFIND_MAX_ITER; i++) {
|
||||
x = ((prev%w)*T_WIDTH + T_WIDTH/2) << PRECISION;
|
||||
y = ((prev/w)*T_HEIGHT + T_HEIGHT/2) << PRECISION;
|
||||
if(npc_append_path(x,y,npc)) {
|
||||
for(i = 0; i < 64; i++) {
|
||||
if(npc_append_path((next % w) * T_WIDTH, (next / h) * T_HEIGHT, npc)) {
|
||||
goto as_recons_fail;
|
||||
}
|
||||
prev = came_from[prev];
|
||||
if(prev == start){
|
||||
x = ((prev%w)*T_WIDTH + T_WIDTH/2) << PRECISION;
|
||||
y = ((prev/w)*T_HEIGHT + T_HEIGHT/2) << PRECISION;
|
||||
if(npc_append_path(x,y,npc))
|
||||
|
||||
next = came_from[next];
|
||||
if(next == spos) {
|
||||
if(npc_append_path((spos % w) * T_WIDTH, (spos / h) * T_HEIGHT,
|
||||
npc))
|
||||
goto as_recons_fail;
|
||||
break;
|
||||
}
|
||||
if(prev == -1)
|
||||
goto as_recons_fail;
|
||||
}
|
||||
|
||||
uint16_t tx, ty;
|
||||
|
||||
// Flip the path because it started from the end
|
||||
|
||||
/*for(i = 0; i < npc->path_length / 2; i++) {
|
||||
for(i = 0; i < npc->path_length / 2; i++) {
|
||||
tx = npc->xpath[i];
|
||||
ty = npc->ypath[i];
|
||||
npc->xpath[i] = npc->xpath[npc->path_length - i - 1];
|
||||
npc->ypath[i] = npc->ypath[npc->path_length - i - 1];
|
||||
npc->ypath[npc->path_length - i - 1] = tx;
|
||||
npc->ypath[npc->path_length - i - 1] = ty;
|
||||
}*/
|
||||
}
|
||||
|
||||
if(is_alloc)
|
||||
free(came_from);
|
||||
free(came_from);
|
||||
|
||||
npc->hasPath = true;
|
||||
|
||||
|
@ -141,8 +136,7 @@ int as_reconstruct_path(int16_t *came_from, int w, int h, int16_t start,
|
|||
|
||||
as_recons_fail:
|
||||
|
||||
if(is_alloc)
|
||||
free(came_from);
|
||||
free(came_from);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -154,8 +148,8 @@ uint32_t xyram = 0xe500e000 + 32;
|
|||
int npc_pathfind(int32_t dest_x, int32_t dest_y, Map *full_map, NPC *npc) {
|
||||
int32_t i, j;
|
||||
|
||||
int32_t w = full_map->w/T_WIDTH/PXSIZE;
|
||||
int32_t h = full_map->h/T_HEIGHT/PXSIZE;
|
||||
int32_t w = full_map->w;
|
||||
int32_t h = full_map->h;
|
||||
int32_t x = (npc->curx >> PRECISION) / T_WIDTH;
|
||||
int32_t y = (npc->cury >> PRECISION) / T_HEIGHT;
|
||||
dest_x /= T_WIDTH;
|
||||
|
@ -164,8 +158,8 @@ int npc_pathfind(int32_t dest_x, int32_t dest_y, Map *full_map, NPC *npc) {
|
|||
|
||||
uint8_t *map = full_map->walkable;
|
||||
|
||||
/*if(dest_x < 0 || dest_x > w || dest_y < 0 || dest_x > h)
|
||||
return 2;*/
|
||||
if(dest_x < 0 || dest_x > w || dest_y < 0 || dest_x > h)
|
||||
return 2;
|
||||
if(map[spos])
|
||||
return 2;
|
||||
if(map[dest_y * w + dest_x])
|
||||
|
@ -178,11 +172,7 @@ int npc_pathfind(int32_t dest_x, int32_t dest_y, Map *full_map, NPC *npc) {
|
|||
uint8_t *gscore;
|
||||
uint8_t *fscore;
|
||||
|
||||
bool is_alloc;
|
||||
|
||||
if(1 || isSH3() || w * h * 5 > 1024 * 15) {
|
||||
is_alloc = true;
|
||||
|
||||
if(isSH3() || w * h * 5 > 1024 * 15) {
|
||||
visited = malloc(w * h);
|
||||
came_from = malloc(w * h * 2);
|
||||
gscore = malloc(w * h * 2);
|
||||
|
@ -192,7 +182,6 @@ int npc_pathfind(int32_t dest_x, int32_t dest_y, Map *full_map, NPC *npc) {
|
|||
free(came_from);
|
||||
return 4;
|
||||
}
|
||||
|
||||
for(i = 0; i < w * h; i++)
|
||||
visited[i] = 1;
|
||||
for(i = 0; i < w * h; i++)
|
||||
|
@ -202,8 +191,6 @@ int npc_pathfind(int32_t dest_x, int32_t dest_y, Map *full_map, NPC *npc) {
|
|||
for(i = 0; i < w * h; i++)
|
||||
fscore[i] = 255;
|
||||
} else {
|
||||
is_alloc = false;
|
||||
|
||||
visited = (void *)xyram;
|
||||
gscore = (void *)(xyram + w * h);
|
||||
fscore = (void *)(xyram + w * h * 2);
|
||||
|
@ -226,7 +213,7 @@ int npc_pathfind(int32_t dest_x, int32_t dest_y, Map *full_map, NPC *npc) {
|
|||
int32_t bx = x;
|
||||
int32_t by = y;
|
||||
|
||||
for(int iter = 0; iter < PATHFIND_MAX_ITER; iter++) {
|
||||
for(int iter = 0; iter < 64; iter++) {
|
||||
bscore = 255;
|
||||
/* Cheapest known tile */
|
||||
/* Could be improved with a priority queue*/
|
||||
|
@ -243,8 +230,9 @@ int npc_pathfind(int32_t dest_x, int32_t dest_y, Map *full_map, NPC *npc) {
|
|||
}
|
||||
if(bx == dest_x && by == dest_y) {
|
||||
as_clean(visited, gscore, fscore);
|
||||
return 0; /*as_reconstruct_path(came_from, w, h, spos,
|
||||
return 1 /*as_reconstruct_path(came_from, w, h, spos,
|
||||
dest_y * w + dest_x, npc)*/
|
||||
;
|
||||
}
|
||||
|
||||
visited[by * w + bx] = 1;
|
||||
|
@ -288,9 +276,8 @@ void update_npcs(Game *game) {
|
|||
}
|
||||
for(i = 0; i < npc_count; i++) {
|
||||
update_npc(&npc_stack[i]);
|
||||
/*Temp debug*/
|
||||
game->mana = npc_pathfind(game->player.x, game->player.y, game->map_level,
|
||||
&npc_stack[i]);
|
||||
/*npc_pathfind(game->player.x, game->player.y, game->map_level,
|
||||
&npc_stack[i]);*/
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,16 +7,15 @@
|
|||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/*Maximum iterations before the pathfinding considers the target unreacheable*/
|
||||
#define PATHFIND_MAX_ITER 64
|
||||
|
||||
enum {
|
||||
|
||||
NPC_NONE = 0,
|
||||
NPC_FRIENDLY = 1, // The player's team
|
||||
NPC_HOSTILE = 2, // to the player
|
||||
NPC_ALL = 3
|
||||
|
||||
};
|
||||
|
||||
/* /!\ Warning /!\
|
||||
* Do not keep hard references to non-static NPCs, as they will likely move
|
||||
* in the stack */
|
||||
|
|