diff --git a/CMakeLists.txt b/CMakeLists.txt index 57490c6..725b16e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -37,20 +37,23 @@ set(SOURCES src/main.c src/map.c src/player.c + src/memory.c + src/game.c # ... ) # Shared assets, fx-9860G-only assets and fx-CG-50-only assets set(ASSETS assets/level0.json - assets/demo_player.png # ... ) set(ASSETS_cg assets-cg/tileset2b_CG.png + assets-cg/demo_player.png ) set(ASSETS_fx + assets-fx/demo_player.png # ... ) diff --git a/assets-cg/demo_player.png b/assets-cg/demo_player.png new file mode 100644 index 0000000..376ade9 Binary files /dev/null and b/assets-cg/demo_player.png differ diff --git a/assets-cg/fxconv-metadata.txt b/assets-cg/fxconv-metadata.txt index d110fdb..114c15f 100644 --- a/assets-cg/fxconv-metadata.txt +++ b/assets-cg/fxconv-metadata.txt @@ -1,5 +1,7 @@ - tileset2b_CG.png: type: bopti-image name: img_tilesetnpp +demo_player.png: + type: bopti-image + name: demo_player_img diff --git a/assets/demo_player.png b/assets-fx/demo_player.png similarity index 100% rename from assets/demo_player.png rename to assets-fx/demo_player.png diff --git a/assets-fx/fxconv-metadata.txt b/assets-fx/fxconv-metadata.txt new file mode 100644 index 0000000..db0f145 --- /dev/null +++ b/assets-fx/fxconv-metadata.txt @@ -0,0 +1,12 @@ +tileset1b.png: + type: bopti-image + name: img_tilesetnpp + + +tileset2b.png: + type: bopti-image + name: img_tilesetnpp + +demo_player.png: + type: bopti-image + name: demo_player_img diff --git a/assets/fxconv-metadata.txt b/assets/fxconv-metadata.txt index 77a8758..ddb88cb 100644 --- a/assets/fxconv-metadata.txt +++ b/assets/fxconv-metadata.txt @@ -1,7 +1,3 @@ *.json: custom-type: map name_regex: (.*)\.json map_\1 - -demo_player.png: - type: bopti-image - name: demo_player_img \ No newline at end of file diff --git a/src/config.h b/src/config.h new file mode 100644 index 0000000..87cd453 --- /dev/null +++ b/src/config.h @@ -0,0 +1,6 @@ +#ifndef CONFIG_H +#define CONFIG_H + +#define USB_FEATURE 1 + +#endif diff --git a/src/game.c b/src/game.c new file mode 100644 index 0000000..4bf871b --- /dev/null +++ b/src/game.c @@ -0,0 +1,49 @@ +#include "game.h" + +#include "map.h" + +#include "config.h" + +#include + +void game_logic(Game *game) { + // to be done +} + +void draw(Game *game) { + /* Draw everything. */ + render_map(&game->player, game->map_level); + player_draw(&game->player); +} + +/* Key management */ + +void get_inputs(Game *game) { + key_event_t ev; + while((ev = pollevent()).type != KEYEV_NONE){ + /**/ + } + + /* Key binding for the Player action */ + + /*************************************/ + + if(keydown(KEY_EXIT)) game->exittoOS = true; + + /* Player actions - Prototypes in player.h and implementation in player.c */ + if(keydown(KEY_LEFT)) player_move(game->map_level, &game->player, D_LEFT); + if(keydown(KEY_RIGHT)) player_move(game->map_level, &game->player, D_RIGHT); + if(keydown(KEY_UP)) player_move(game->map_level, &game->player, D_UP); + if(keydown(KEY_DOWN)) player_move(game->map_level, &game->player, D_DOWN); + if(keydown(KEY_SHIFT)) player_action(&game->player); + + /* if USB is enabled - keybinding for screencapture */ + +#if USB_FEATURE==1 + + if(keydown(KEY_7)) game->screenshot = true; + if(keydown(KEY_8)) game->record = !game->record; + +#endif //USB_FEATURE +} + diff --git a/src/game.h b/src/game.h new file mode 100644 index 0000000..0a487a2 --- /dev/null +++ b/src/game.h @@ -0,0 +1,34 @@ +#ifndef GAME_H +#define GAME_H + +#include "mapstruct.h" +#include "player.h" + +/* This struct will contain all the data of the game. It will make it possible + * to pass it to the NPCs to let them interact with the player and the rest of + * the world. */ +typedef struct { + Map *map_level; /* The level that the player is currently playing */ + Player player; /* The player data (see player.h). */ + /* Some global variables */ + /* Set to true when asked for exit */ + bool exittoOS; + /* Set to true when screenshot is required */ + bool screenshot; + /* Set to true when recording a video of the screen is required */ + bool record; + /* How many ms the frame already took. */ + long int frame_duration; +} Game; + +/* (Mibi88) TODO: Describe what this function is doing. */ +void game_logic(Game *game); + +/* Draws everything on screen. */ +void draw(Game *game); + +/* Handle key presses. */ +void get_inputs(Game *game); + +#endif + diff --git a/src/main.c b/src/main.c index d803bff..63273ae 100644 --- a/src/main.c +++ b/src/main.c @@ -1,10 +1,12 @@ #include #include +#include +#include -#define USB_FEATURE 1 +#include "config.h" -#if USB_FEATURE==1 +#if USB_FEATURE #include #include #endif //USB_FEATURE @@ -21,52 +23,15 @@ #include #include -#include "map.h" -#include "player.h" +#include "game.h" #include "mapdata.h" -/* Player data (defined in "player.h")*/ -Player MyPlayer = { 10, 5, 0, 0, 100 }; -Map *map_level = &map_level0; - -/* some global variables */ -bool exittoOS = false; // set to true when asked for exit - -bool screenshot = false; // set to true when screenshot is required -bool record = false; // set to true when - -/* Key management */ - -static void get_inputs( void ) -{ - key_event_t ev; - while((ev = pollevent()).type != KEYEV_NONE){ - - } - - /* Key binding for the Player action */ - - /*************************************/ - - if(keydown(KEY_EXIT)) exittoOS = true; - - /* Player actions - Prototypes in player.h and implementation in player.c */ - if(keydown(KEY_LEFT)) PlayerLeft(); - if(keydown(KEY_RIGHT)) PlayerRight(); - if(keydown(KEY_UP)) PlayerUp(); - if(keydown(KEY_DOWN)) PlayerDown(); - if(keydown(KEY_SHIFT)) PlayerAction(); - - /* if USB is enabled - keybinding for screencapture */ - -#if USB_FEATURE==1 - - if(keydown(KEY_7)) screenshot = true; - if(keydown(KEY_8)) record = !record; - -#endif //USB_FEATURE -} - +/* Game data (defined in "game.h")*/ +Game game = { + &map_level0, + {10, 5, 0, 0, 100}, + false, false, false, 0 +}; /* screen capture management code */ @@ -74,9 +39,9 @@ static void get_inputs( void ) void USB_feature( void ) { - if (screenshot && usb_is_open()) { + if (game.screenshot && usb_is_open()) { - #ifdef GRAYMODEOK // This is a trick, if GRAYMODEOK is defined then we make the code accessible + #ifdef GRAYMODEOK // This is a trick, if GRAYMODEOK is defined then we make the code accessible if (dgray_enabled()) usb_fxlink_screenshot_gray(false); @@ -84,12 +49,12 @@ static void get_inputs( void ) #endif - usb_fxlink_screenshot(false); // else we just let the usual screeshot function - screenshot = false; + usb_fxlink_screenshot(false); // else we just let the usual screeshot function + game.screenshot = false; } - if (record && usb_is_open()) { + if (game.record && usb_is_open()) { #ifdef GRAYMODEOK @@ -105,13 +70,20 @@ static void get_inputs( void ) #endif +/* Timer callback */ -void GameLogic(void) { - // to be done +int update_time(void) { + game.frame_duration++; + return TIMER_CONTINUE; } - int main(void) { + int timer; + timer = timer_configure(TIMER_TMU, 1000, GINT_CALL(update_time)); + if(timer < 0){ + return -1; + } + timer_start(timer); #if USB_FEATURE==1 usb_interface_t const *interfaces[] = {&usb_ff_bulk, NULL}; @@ -122,21 +94,19 @@ int main(void) { /* start grayscale engine */ #ifdef GRAYMODEOK - dgray( DGRAY_ON ); + dgray(DGRAY_ON); #endif - do - { + do{ /* clear screen */ dclear(C_WHITE); /* render the map */ - RenderMap(&MyPlayer, map_level); - PlayerDraw(); + draw(&game); /* start the logic of the game */ - GameLogic(); + game_logic(&game); /* Screen blit */ dupdate(); @@ -147,16 +117,18 @@ int main(void) { #endif /* Management of the inputs */ - get_inputs(); - - } - while (exittoOS == false); // want to exit ? + get_inputs(&game); + /* Run the game at max. 50fps */ + while(game.frame_duration < 20) sleep(); + /* Reset frame_duration for the next frame */ + game.frame_duration = 0; + }while(!game.exittoOS); // want to exit ? /* shutdown grayengine*/ #ifdef GRAYMODEOK - dgray( DGRAY_OFF ); + dgray(DGRAY_OFF); #endif @@ -165,6 +137,7 @@ int main(void) { usb_close(); #endif - + timer_stop(timer); return 1; } + diff --git a/src/map.c b/src/map.c index 749b6e7..0e86663 100644 --- a/src/map.c +++ b/src/map.c @@ -2,7 +2,7 @@ #include -void RenderMap(Player *player, Map *map_level) { +void render_map(Player *player, Map *map_level) { /* for all Layer (2 in the current configuration: Background is layer 0 and * foreground is layer 1 ) */ /* x and y will contain the position in the loop. */ @@ -15,7 +15,7 @@ void RenderMap(Player *player, Map *map_level) { unsigned char mx, my; /* dw and dh contain the amount of tiles that will be drawn on x and on * y. */ - unsigned char dw = DWIDTH/T_WIDTH+1, dh = DHEIGHT/T_HEIGHT+1; + unsigned char dw = DWIDTH/T_WIDTH+2, dh = DHEIGHT/T_HEIGHT+1; /* mw and mh will contain the height and the width of the map. */ unsigned short int mw = map_level->w*T_WIDTH, mh = map_level->h*T_HEIGHT; /* tile contains the tile to draw. */ @@ -87,3 +87,10 @@ void RenderMap(Player *player, Map *map_level) { } } +short int get_tile(Map *map_level, int x, int y, int l) { + /* Get the tile at (x, y) on layer l. Returns the tile ID or MAP_OUTSIDE if + * she's not found. */ + return x>=0 && x < map_level->w && y>=0 && y < map_level->h ? + map_level->layers[l][y * map_level->w + x] : MAP_OUTSIDE; +} + diff --git a/src/map.h b/src/map.h index 0d7fe0f..42293f1 100644 --- a/src/map.h +++ b/src/map.h @@ -10,25 +10,18 @@ #define T_WIDTH 8 #endif +#define MAP_OUTSIDE -2 /* Returned by get_tile_at_pos if the point is outside of + * the map. */ -#include - +#include "mapstruct.h" #include "player.h" -typedef struct { +/* Draws the map map on the entire screen to be viewed by the player player. */ +void render_map(Player *player, Map *map_level); - /*width, height and the number of layer of the map*/ - int w, h, nblayers; - - /*the tileset to use*/ - bopti_image_t *tileset; - int tileset_size; - - /*list of all the tiles*/ - short *layers[]; -} Map; - -void RenderMap(Player *player, Map *map_level); +/* Get the tile at (x, y) of the map map. If the tile is located outside of the + * screen, MAP_OUTSIDE is returned. */ +short int get_tile(Map *map_level, int x, int y, int l); #endif diff --git a/src/mapstruct.h b/src/mapstruct.h new file mode 100644 index 0000000..bcf1c77 --- /dev/null +++ b/src/mapstruct.h @@ -0,0 +1,18 @@ +#ifndef MAPSTRUCT_H +#define MAPSTRUCT_H + +#include + +typedef struct { + /* width, height and the number of layer of the map */ + int w, h, nblayers; + + /* the tileset to use */ + bopti_image_t *tileset; + int tileset_size; + + /* list of all the tiles */ + short *layers[]; +} Map; + +#endif diff --git a/src/memory.c b/src/memory.c new file mode 100644 index 0000000..9e3e58a --- /dev/null +++ b/src/memory.c @@ -0,0 +1,12 @@ +#include "memory.h" + +bool is_in(short int *array, short int array_length, short int item) { + short int i; + for(i=0;i + +bool is_in(short int *array, short int array_length, short int item); + +#endif + diff --git a/src/player.c b/src/player.c index 5d7c582..6d0627d 100644 --- a/src/player.c +++ b/src/player.c @@ -2,51 +2,85 @@ #include "map.h" #include - -#define P_WIDTH 8 -#define P_HEIGHT 8 - - #ifdef FXCG50 - #define SPEED 3 + #define P_WIDTH 16 + #define P_HEIGHT 16 +#else + #define P_WIDTH 8 + #define P_HEIGHT 8 +#endif + +/* SPEED should NOT be 8 or bigger: it this may cause bugs when handling + * collisions! */ +#ifdef FXCG50 + #define SPEED 2 #else #define SPEED 1 #endif +const char one_px_mov[8] = { + 0, -1, /* Up */ + 0, 1, /* Down */ + -1, 0, /* Left */ + 1, 0 /* Right */ +}; + +/* TODO: Search for all hard tiles in the tileset. hard_tiles is a list of their + * IDs */ +/* The tiles where the player can't go trough. */ +#define HARD_TILES_AMOUNT 5 +const short int hard_tiles[HARD_TILES_AMOUNT] = { + MAP_OUTSIDE, 124, 148, 125, 149 +}; -extern Player MyPlayer; -extern Map *map_level; extern bopti_image_t demo_player_img; - -void PlayerDraw(void) { - dimage(MyPlayer.px-P_WIDTH/2, MyPlayer.py-P_HEIGHT/2, &demo_player_img); +void player_draw(Player *player) { + dimage(player->px-P_WIDTH/2, player->py-P_HEIGHT/2, &demo_player_img); } -void PlayerLeft(void) { - if(MyPlayer.x >= SPEED){ - MyPlayer.x-=SPEED; +void player_move(Map *map_level, Player *player, Direction direction) { + /* How this player movement will modify the player x and y. */ + const char dx = one_px_mov[direction*2]*SPEED; + const char dy = one_px_mov[direction*2+1]*SPEED; + /* If the player will collide with a hard tile. */ + if(player_collision(map_level, player, direction)){ + /* I fix his position so he won't be partially in the tile. */ + player_fix_position(player, 1, 1); + }else{ + /* If he won't collide I just move him normally */ + player->x += dx; + player->y += dy; } } -void PlayerRight(void) { - if(MyPlayer.x <= map_level->w * T_WIDTH - SPEED){ - MyPlayer.x+=SPEED; +void player_action(Player *player) { + /**/ +} + +bool player_collision(Map *map_level, Player *player, Direction direction) { + /* What's the tile the player is going to. */ + short int i; + /* Where is the tile where he will go to from his position. */ + const char dx = one_px_mov[direction*2]; + const char dy = one_px_mov[direction*2+1]; + /* The tile he will go to. */ + int player_tile_x = player->x/T_WIDTH; + int player_tile_y = player->y/T_HEIGHT; + for(i=0;inblayers;i++){ + /* if he's on a hard tile */ + if(is_in((short int*)hard_tiles, HARD_TILES_AMOUNT, + get_tile(map_level, player_tile_x+dx, player_tile_y+dy, i))){ + return true; /* He will collide with it. */ + } } + return false; /* He won't collide with a hard tile. */ } -void PlayerUp(void) { - if(MyPlayer.y >= SPEED){ - MyPlayer.y-=SPEED; - } +void player_fix_position(Player *player, bool fix_x, bool fix_y) { + /* I fix his poition on x or/and on y if y need to, so that he won't be over + * the hard tile that he collided with. */ + if(fix_x) player->x = player->x/T_WIDTH*T_WIDTH+P_WIDTH/2; + if(fix_y) player->y = player->y/T_HEIGHT*T_HEIGHT+P_HEIGHT/2; } -void PlayerDown(void) { - if(MyPlayer.y <= map_level->h * T_HEIGHT - SPEED){ - MyPlayer.y+=SPEED; - } -} - -void PlayerAction(void) { - -} diff --git a/src/player.h b/src/player.h index 6277655..e4771a2 100644 --- a/src/player.h +++ b/src/player.h @@ -1,6 +1,19 @@ #ifndef PLAYER_H #define PLAYER_H +#include + +#include "mapstruct.h" +#include "memory.h" + +/* The direction where the player is going to. */ +typedef enum { + D_UP, + D_DOWN, + D_LEFT, + D_RIGHT +} Direction; + /* Struct that define player parameters */ typedef struct { unsigned short int x, y; /* The position of the player */ @@ -9,18 +22,22 @@ typedef struct { * and 100. */ } Player; -/* This function should be called after drawing the map ! */ -void PlayerDraw(void); +/* Draws the player player. This function should be called after drawing the + * map! */ +void player_draw(Player *player); -void PlayerLeft(void); +/* Move the player player in the direction direction. */ +void player_move(Map *map_level, Player *player, Direction direction); -void PlayerRight(void); +/* (Mibi88) TODO: Describe this function please, I've no idea what she's for! */ +void player_action(Player *player); -void PlayerUp(void); - -void PlayerDown(void); - -void PlayerAction(void); +/* Check if the player is in collision with the map or a NPC. */ +bool player_collision(Map *map_level, Player *player, Direction direction); +/* Fix the position of the player so that he's not a bit inside of a hard block + * after a collision. */ +void player_fix_position(Player *player, bool fix_x, bool fix_y); #endif +