diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..25d2feb --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,46 @@ +# Configure with [fxsdk build-fx] or [fxsdk build-cg], which provide the +# toolchain file and module path of the fxSDK + +cmake_minimum_required(VERSION 3.15) +project(MyAddin) + +include(GenerateG1A) +include(Fxconv) +find_package(Gint 2.1 REQUIRED) + +set(SOURCES + src/core.c + src/init.c + src/tools.c + src/main.c + # ... +) +# Shared assets, fx-9860G-only assets and fx-CG-50-only assets +set(ASSETS + # ... +) +set(ASSETS_fx + assets-fx/maps/map1.png + assets-fx/title.png + assets-fx/game_over.png + assets-fx/you_won.png + assets-fx/menu/play.png + assets-fx/menu/play_s.png + assets-fx/menu/quit.png + assets-fx/menu/quit_s.png + assets-fx/timer/3.png + assets-fx/timer/2.png + assets-fx/timer/1.png + # ... +) + +fxconv_declare_assets(${ASSETS} ${ASSETS_fx} WITH_METADATA) + +add_executable(myaddin ${SOURCES} ${ASSETS} ${ASSETS_${FXSDK_PLATFORM}}) +target_compile_options(myaddin PRIVATE -Wall -Wextra -Os) +target_link_libraries(myaddin Gint::Gint) + +if("${FXSDK_PLATFORM_LONG}" STREQUAL fx9860G) + generate_g1a(TARGET myaddin OUTPUT "METROSI4.G1A" + NAME "Metro Siberia 4" ICON assets-fx/icon.png) +endif() diff --git a/assets-fx/fxconv-metadata.txt b/assets-fx/fxconv-metadata.txt new file mode 100644 index 0000000..4834fea --- /dev/null +++ b/assets-fx/fxconv-metadata.txt @@ -0,0 +1,9 @@ +title.png: + type: bopti-image + name: title +game_over.png: + type: bopti-image + name: game_over +you_won.png: + type: bopti-image + name: you_won diff --git a/assets-fx/game_over.png b/assets-fx/game_over.png new file mode 100644 index 0000000..a5a0748 Binary files /dev/null and b/assets-fx/game_over.png differ diff --git a/assets-fx/icon.png b/assets-fx/icon.png new file mode 100644 index 0000000..07d1f73 Binary files /dev/null and b/assets-fx/icon.png differ diff --git a/assets-fx/maps/fxconv-metadata.txt b/assets-fx/maps/fxconv-metadata.txt new file mode 100644 index 0000000..c4ddb5c --- /dev/null +++ b/assets-fx/maps/fxconv-metadata.txt @@ -0,0 +1,3 @@ +map1.png: + type: bopti-image + name: map_1 diff --git a/assets-fx/maps/map1.png b/assets-fx/maps/map1.png new file mode 100644 index 0000000..2aecda4 Binary files /dev/null and b/assets-fx/maps/map1.png differ diff --git a/assets-fx/menu/fxconv-metadata.txt b/assets-fx/menu/fxconv-metadata.txt new file mode 100644 index 0000000..09de0da --- /dev/null +++ b/assets-fx/menu/fxconv-metadata.txt @@ -0,0 +1,12 @@ +play.png: + type: bopti-image + name: menu_play +play_s.png: + type: bopti-image + name: menu_play_inv +quit.png: + type: bopti-image + name: menu_quit +quit_s.png: + type: bopti-image + name: menu_quit_inv diff --git a/assets-fx/menu/play.png b/assets-fx/menu/play.png new file mode 100644 index 0000000..b2d4f78 Binary files /dev/null and b/assets-fx/menu/play.png differ diff --git a/assets-fx/menu/play_s.png b/assets-fx/menu/play_s.png new file mode 100644 index 0000000..44a54ab Binary files /dev/null and b/assets-fx/menu/play_s.png differ diff --git a/assets-fx/menu/quit.png b/assets-fx/menu/quit.png new file mode 100644 index 0000000..b90e940 Binary files /dev/null and b/assets-fx/menu/quit.png differ diff --git a/assets-fx/menu/quit_s.png b/assets-fx/menu/quit_s.png new file mode 100644 index 0000000..2940f6a Binary files /dev/null and b/assets-fx/menu/quit_s.png differ diff --git a/assets-fx/timer/1.png b/assets-fx/timer/1.png new file mode 100644 index 0000000..a5127df Binary files /dev/null and b/assets-fx/timer/1.png differ diff --git a/assets-fx/timer/2.png b/assets-fx/timer/2.png new file mode 100644 index 0000000..e49a41e Binary files /dev/null and b/assets-fx/timer/2.png differ diff --git a/assets-fx/timer/3.png b/assets-fx/timer/3.png new file mode 100644 index 0000000..c4add70 Binary files /dev/null and b/assets-fx/timer/3.png differ diff --git a/assets-fx/timer/fxconv-metadata.txt b/assets-fx/timer/fxconv-metadata.txt new file mode 100644 index 0000000..f785e15 --- /dev/null +++ b/assets-fx/timer/fxconv-metadata.txt @@ -0,0 +1,9 @@ +3.png: + type: bopti-image + name: timer_3 +2.png: + type: bopti-image + name: timer_2 +1.png: + type: bopti-image + name: timer_1 diff --git a/assets-fx/title.png b/assets-fx/title.png new file mode 100644 index 0000000..51cc391 Binary files /dev/null and b/assets-fx/title.png differ diff --git a/assets-fx/you_won.png b/assets-fx/you_won.png new file mode 100644 index 0000000..e862f57 Binary files /dev/null and b/assets-fx/you_won.png differ diff --git a/src/core.c b/src/core.c new file mode 100644 index 0000000..733107b --- /dev/null +++ b/src/core.c @@ -0,0 +1,146 @@ +/* + * Metro Siberia 4 - A sequel to Dark Storm's Metro Siberia 3 for CASIO calculators. + * Copyright (C) 2015 Dark Storm + * Copyright (C) 2022 Mibi88 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see https://www.gnu.org/licenses/. + */ + +#include "includes.h" + +Ship ship; +extern bopti_image_t map_1; +extern bopti_image_t timer_3; +extern bopti_image_t timer_2; +extern bopti_image_t timer_1; + +int dgetpixel(int x, int y) // Thanks to Lephenixnoir +{ + int offset = (y << 2) + (x >> 5); + return (int)(gint_vram[offset] << (x & 31)) < 0 ? C_BLACK : C_WHITE; +} + +int play_game(void) +{ + int collision = 0, ticks = 0, timer = 3; + init_ship(); + ship.scrolling.x = 0; + ship.scrolling.y = 0; + while(timer != 0){ + dclear(C_WHITE); + int i; + dimage(-ship.scrolling.x, 0, &map_1); + calculate_tops(); + for(i = 0; i != 3; i++) + dline(ship.tops[i].x, ship.tops[i].y, ship.tops[(i + 1) % 3].x, ship.tops[(i + 1) % 3].y, C_BLACK); + if(timer == 3){ + dimage(59, 25, &timer_3); + }else if(timer == 2){ + dimage(59, 25, &timer_2); + }else if(timer == 1){ + dimage(59, 25, &timer_1); + } + dupdate(); + sleep_ms(1000); + timer--; + } + + while(1) + { + clearevents(); + if(keydown(KEY_SHIFT) || keydown(KEY_EXE)){ // Go up + ship.thrust = false; + } + if(keydown(KEY_EXIT)){ + return 2; + } + sleep_ms(20); + calculate_tops(); + dclear(C_WHITE); + collision = move(); + draw(); + ship.thrust = true; + clearevents(); + if(ship.scrolling.x >= 3328){ + return 1; + } + if(collision == 1){ + return 0; + } + } + +} + +void draw(void) +{ + static Vector smoke_cubes[5]; + int i; + + for(i = 0; i != 3; i++) + dline(ship.tops[i].x, ship.tops[i].y, ship.tops[(i + 1) % 3].x, ship.tops[(i + 1) % 3].y, C_BLACK); + + dupdate(); +} + +int move(void) +{ + int i; + ship.acceleration.y = - GRAVITY * (float)(TIMER_PHYSIC) / 1000; + if(ship.thrust) ship.acceleration.y += THRUST * (float)(TIMER_PHYSIC) / 1000; + + ship.speed.x += ship.acceleration.x; + ship.speed.y += ship.acceleration.y; + + ship.position.x += ship.speed.x; + ship.position.y += ship.speed.y; + + ship.scrolling.x = ship.position.x; + + dimage(-ship.scrolling.x, 0, &map_1); + + // collision + for(i=0;i!=3;i++){ + if(dgetpixel(ship.tops[i].x, ship.tops[i].y) == C_BLACK){ + return 1; + } + if(ship.tops[i].y<0 || ship.tops[i].y>64){ + return 1; + } + } + return 0; +} + + +void calculate_tops(void) +{ + Vector tmp; + float angle = 15.0; + int i; + + angle = _atan(ship.speed.y / ship.speed.x); + + init_tops(); + + for(i = 0; i != 3; i++) + { + tmp.x = ship.tops[i].x; + tmp.y = ship.tops[i].y; + + ship.tops[i].x = tmp.x * cos(angle) + tmp.y * sin(angle); + ship.tops[i].y = tmp.y * cos(angle) - tmp.x * sin(angle); + + ship.tops[i].x += MARGIN; + ship.tops[i].y += ship.position.y; + } +} diff --git a/src/core.h b/src/core.h new file mode 100644 index 0000000..3f1e72e --- /dev/null +++ b/src/core.h @@ -0,0 +1,91 @@ +/* + * Metro Siberia 4 - A sequel to Dark Storm's Metro Siberia 3 for CASIO calculators. + * Copyright (C) 2015 Dark Storm + * Copyright (C) 2022 Mibi88 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see https://www.gnu.org/licenses/. + */ + +#ifndef _ENGINE_H +#define _ENGINE_H + +/* Global defines */ + +#ifndef NULL + #define NULL (void*)(0) +#endif + +// Timers delays +#define TIMER_PHYSIC 25 + +// Physic constants +#define GRAVITY 0.981 // px . s^{-2} +#define THRUST 2.0 * GRAVITY // px . s^{-2} +#define HORIZONTAL_SPEED 20.0 // px . s^{-1} + +// Margin before the ship +#define MARGIN 32 + +// Relative position of tops of the ship +/*#define SHIP_TOP_1_X 10 +#define SHIP_TOP_1_Y 0 +#define SHIP_TOP_2_X -5 +#define SHIP_TOP_2_Y 5 +#define SHIP_TOP_3_X -5 +#define SHIP_TOP_3_Y -5*/ +#define SHIP_TOP_1_X 9 +#define SHIP_TOP_1_Y 0 +#define SHIP_TOP_2_X 0 +#define SHIP_TOP_2_Y 3 +#define SHIP_TOP_3_X 0 +#define SHIP_TOP_3_Y -3 + +#define MENU_MAX 1 + +/* Enumerations */ + +// Menu entries + +#define PLAY 0 +#define QUIT 1 + +/* Structures */ +typedef struct { float x, y; } Vector; + +typedef struct +{ + Vector position; + Vector speed; + Vector acceleration; + Vector scrolling; + bool thrust; + + Vector tops[3]; +} Ship; + +typedef struct +{ + int x, y; +} Camera; + + +/* Functions */ + +int play_game(void); +void draw(void); +int move(void); + +void calculate_tops(void); + +#endif // _ENGINE_H diff --git a/src/includes.h b/src/includes.h new file mode 100644 index 0000000..1a940c7 --- /dev/null +++ b/src/includes.h @@ -0,0 +1,32 @@ +/* + * Metro Siberia 4 - A sequel to Dark Storm's Metro Siberia 3 for CASIO calculators. + * Copyright (C) 2015 Dark Storm + * Copyright (C) 2022 Mibi88 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see https://www.gnu.org/licenses/. + */ + +#define DEBUG + +#include +#include +#include +#include +#include + +#include "tools.h" + +#include "core.h" +#include "main.h" +#include "init.h" diff --git a/src/init.c b/src/init.c new file mode 100644 index 0000000..45b416d --- /dev/null +++ b/src/init.c @@ -0,0 +1,46 @@ +/* + * Metro Siberia 4 - A sequel to Dark Storm's Metro Siberia 3 for CASIO calculators. + * Copyright (C) 2015 Dark Storm + * Copyright (C) 2022 Mibi88 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see https://www.gnu.org/licenses/. + */ + +#include "includes.h" + +extern Ship ship; + +void init_ship(void) +{ + ship.position.x = 0; + ship.position.y = 32; + + ship.speed.x = HORIZONTAL_SPEED / TIMER_PHYSIC; + ship.speed.y = 0; + + ship.acceleration.x = 0; + ship.acceleration.y = 0; + + ship.thrust = false; +} + +void init_tops(void) +{ + ship.tops[0].x = SHIP_TOP_1_X; + ship.tops[0].y = SHIP_TOP_1_Y; + ship.tops[1].x = SHIP_TOP_2_X; + ship.tops[1].y = SHIP_TOP_2_Y; + ship.tops[2].x = SHIP_TOP_3_X; + ship.tops[2].y = SHIP_TOP_3_Y; +} diff --git a/src/init.h b/src/init.h new file mode 100644 index 0000000..1c25e24 --- /dev/null +++ b/src/init.h @@ -0,0 +1,26 @@ +/* + * Metro Siberia 4 - A sequel to Dark Storm's Metro Siberia 3 for CASIO calculators. + * Copyright (C) 2015 Dark Storm + * Copyright (C) 2022 Mibi88 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see https://www.gnu.org/licenses/. + */ + +#ifndef _INIT_H +#define _INIT_H + +void init_ship(void); +void init_tops(void); + +#endif // _INIT_H diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..0fc9ae0 --- /dev/null +++ b/src/main.c @@ -0,0 +1,113 @@ +/* + * Metro Siberia 4 - A sequel to Dark Storm's Metro Siberia 3 for CASIO calculators. + * Copyright (C) 2015 Dark Storm + * Copyright (C) 2022 Mibi88 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see https://www.gnu.org/licenses/. + */ + +#include "includes.h" + +int selection, stat; + +extern bopti_image_t title; +extern bopti_image_t game_over; +extern bopti_image_t you_won; +extern bopti_image_t menu_play; +extern bopti_image_t menu_play_inv; +extern bopti_image_t menu_quit; +extern bopti_image_t menu_quit_inv; + +void waitkey(int key){ + clearevents(); + while(keydown(key)){ + clearevents(); + } +} + +void end(){ + dclear(C_WHITE); + if(stat == 0){ + dimage(0, 0, &game_over); + }else if(stat == 1){ + dimage(0, 0, &you_won); + } + if(stat == 0 || stat == 1){ + dupdate(); + stat = 0; + clearevents(); + while(!keydown(KEY_EXIT)){ + clearevents(); + if(keydown(KEY_SHIFT)) + break; + clearevents(); + if(keydown(KEY_EXE)) + break; + clearevents(); + } + }else{ + return; + } +} + +int main(void) +{ + selection = PLAY; + stat = 0; + while(1){ + dclear(C_WHITE); + if(selection != PLAY){ + dimage(70, 22, &menu_play); + }else{ + dimage(70, 22, &menu_play_inv); + } + if(selection != QUIT){ + dimage(70, 32, &menu_quit); + }else{ + dimage(70, 32, &menu_quit_inv); + } + clearevents(); + if(keydown(KEY_SHIFT) || keydown(KEY_EXE)){ + if(selection == PLAY){ + play_game(); + end(); + waitkey(KEY_SHIFT); + waitkey(KEY_EXE); + selection = PLAY; + stat = 0; + }else if(selection == QUIT){ + return 1; + } + waitkey(KEY_SHIFT); + waitkey(KEY_EXE); + }else if(keydown(KEY_UP)){ + if(selection != 0){ + selection--; + }else{ + selection = MENU_MAX; + } + waitkey(KEY_UP); + }else if(keydown(KEY_DOWN)){ + if(selection != MENU_MAX){ + selection++; + }else{ + selection = 0; + } + waitkey(KEY_DOWN); + } + dimage(0, 0, &title); + dupdate(); + } + return 1; +} diff --git a/src/main.h b/src/main.h new file mode 100644 index 0000000..fba955b --- /dev/null +++ b/src/main.h @@ -0,0 +1,30 @@ +/* + * Metro Siberia 4 - A sequel to Dark Storm's Metro Siberia 3 for CASIO calculators. + * Copyright (C) 2015 Dark Storm + * Copyright (C) 2022 Mibi88 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see https://www.gnu.org/licenses/. + */ + +#ifndef _MAIN_H + +#define _MAIN_H + +/* Functions */ + +int main(void); +void waitkey(int key); +void end(void); + +#endif diff --git a/src/tools.c b/src/tools.c new file mode 100644 index 0000000..38b917f --- /dev/null +++ b/src/tools.c @@ -0,0 +1,51 @@ +/* + * Metro Siberia 4 - A sequel to Dark Storm's Metro Siberia 3 for CASIO calculators. + * Copyright (C) 2015 Dark Storm + * Copyright (C) 2022 Mibi88 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see https://www.gnu.org/licenses/. + */ + +#include "includes.h" + +char* _itoa(int i, char b[]) +{ + char const digit[] = "0123456789"; + char* p = b; + if(i<0){ + *p++ = '-'; + i *= -1; + } + int shifter = i; + do{ //Move to where representation ends + ++p; + shifter = shifter/10; + }while(shifter); + *p = '\0'; + do{ //Move back, inserting digits as u go + *--p = digit[i%10]; + i = i/10; + }while(i); + return b; +} + + +#define PI 3.14159 +#define M_PI_4 0.78539 +#define FABS(x) ((x<0)?-x:x) + +float _atan(float x) +{ + return (x * (M_PI_4 - ((FABS(x) - 1) * (0.2447 + 0.0663 * FABS(x))))); +} diff --git a/src/tools.h b/src/tools.h new file mode 100644 index 0000000..9a44e9c --- /dev/null +++ b/src/tools.h @@ -0,0 +1,28 @@ +/* + * Metro Siberia 4 - A sequel to Dark Storm's Metro Siberia 3 for CASIO calculators. + * Copyright (C) 2015 Dark Storm + * Copyright (C) 2022 Mibi88 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see https://www.gnu.org/licenses/. + */ + +#ifndef _TOOLS_H +#define _TOOLS_H +#include + +/* Functions */ +char* _itoa(int i, char str[]); +float _atan(float x); + +#endif