From f3f667738640a5da6cf3b42b07583eff9457d8b3 Mon Sep 17 00:00:00 2001 From: KikooDX Date: Tue, 2 Mar 2021 00:21:01 +0100 Subject: [PATCH] Decently small and minimalistic working base. --- .gitignore | 19 +++++ CMakeLists.txt | 48 +++++++++++ assets-cg/fxconv-metadata.txt | 1 + assets-cg/icon-sel.png | Bin 0 -> 8388 bytes assets-cg/icon-uns.png | Bin 0 -> 4629 bytes assets/levels/chaos.kble | Bin 0 -> 518 bytes assets/levels/damage_boosting_101.kble | Bin 0 -> 518 bytes assets/levels/die_and_retry.kble | Bin 0 -> 518 bytes assets/levels/dome.kble | Bin 0 -> 518 bytes assets/levels/end.kble | Bin 0 -> 518 bytes assets/levels/hello_world.kble | Bin 0 -> 518 bytes assets/levels/key_101.kble | Bin 0 -> 518 bytes assets/levels/so_far_but_so_close.kble | Bin 0 -> 518 bytes assets/levels/two_for_one.kble | Bin 0 -> 518 bytes assets/levels/up_and_down.kble | Bin 0 -> 518 bytes include/conf.h | 8 ++ include/input.h | 35 ++++++++ include/level.h | 10 +++ include/player.h | 16 ++++ include/tiles.h | 13 +++ include/vec2.h | 8 ++ kble.py | 109 +++++++++++++++++++++++++ src/input.c | 55 +++++++++++++ src/main.c | 59 +++++++++++++ src/player.c | 15 ++++ 25 files changed, 396 insertions(+) create mode 100644 .gitignore create mode 100644 CMakeLists.txt create mode 100644 assets-cg/fxconv-metadata.txt create mode 100644 assets-cg/icon-sel.png create mode 100644 assets-cg/icon-uns.png create mode 100644 assets/levels/chaos.kble create mode 100644 assets/levels/damage_boosting_101.kble create mode 100644 assets/levels/die_and_retry.kble create mode 100644 assets/levels/dome.kble create mode 100644 assets/levels/end.kble create mode 100644 assets/levels/hello_world.kble create mode 100644 assets/levels/key_101.kble create mode 100644 assets/levels/so_far_but_so_close.kble create mode 100644 assets/levels/two_for_one.kble create mode 100644 assets/levels/up_and_down.kble create mode 100644 include/conf.h create mode 100644 include/input.h create mode 100644 include/level.h create mode 100644 include/player.h create mode 100644 include/tiles.h create mode 100644 include/vec2.h create mode 100644 kble.py create mode 100644 src/input.c create mode 100644 src/main.c create mode 100644 src/player.c diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3f21bab --- /dev/null +++ b/.gitignore @@ -0,0 +1,19 @@ +# Build files +/build-fx +/build-cg +/*.g1a +/*.g3a + +# Python bytecode + __pycache__/ + +# Common IDE files +*.sublime-project +*.sublime-workspace +.vscode + +# KBLE backup files +backup_*.kble + +# Generated C files. +gen_*.c diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..37d27d8 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,48 @@ +# 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.18) +project(MyAddin) + +execute_process(COMMAND python3 kble.py + WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}) + +include(GenerateG1A) +include(GenerateG3A) +include(Fxconv) +include_directories(include) +find_package(Gint 2.1 REQUIRED) + +set(SOURCES + src/main.c + src/player.c + src/input.c + src/gen_levels.c + # ... +) +# Shared assets, fx-9860G-only assets and fx-CG-50-only assets +set(ASSETS + # ... +) +#set(ASSETS_fx +# assets-fx/example.png +# # ... +#) +#set(ASSETS_cg +# assets-cg/example.png +# # ... +#) + +fxconv_declare_assets(${ASSETS} ${ASSETS_fx} ${ASSETS_cg} 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 "MyAddin.g1a" +# NAME "Painful" ICON assets-fx/icon.png) +if("${FXSDK_PLATFORM_LONG}" STREQUAL fxCG50) + generate_g3a(TARGET myaddin OUTPUT "Painfull.g3a" + NAME "Painful" ICONS assets-cg/icon-uns.png assets-cg/icon-sel.png) +endif() diff --git a/assets-cg/fxconv-metadata.txt b/assets-cg/fxconv-metadata.txt new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/assets-cg/fxconv-metadata.txt @@ -0,0 +1 @@ + diff --git a/assets-cg/icon-sel.png b/assets-cg/icon-sel.png new file mode 100644 index 0000000000000000000000000000000000000000..7137b504cfd44f62f3105ce7a203b9100a557d0f GIT binary patch literal 8388 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 ag#Q8hHNm}t`+-sb0000 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 LNkvXXu0mjfMjhGA literal 0 HcmV?d00001 diff --git a/assets/levels/chaos.kble b/assets/levels/chaos.kble new file mode 100644 index 0000000000000000000000000000000000000000..25339116581ae14e575145550d3e24a456663aec GIT binary patch literal 518 zcmb7<(Gh?!2tz44fcsCYf#!_J)e}BS^9Z!&c3e3=(-r~uDmt#3)|lh-HJn*Fbk(%3 u9-q^2I^hpLEOkEas%g#s5&Lpu&(WEo9Caq?bN`!?Z(+Fk9(VqqdV8L+y#Sy9 literal 0 HcmV?d00001 diff --git a/assets/levels/damage_boosting_101.kble b/assets/levels/damage_boosting_101.kble new file mode 100644 index 0000000000000000000000000000000000000000..7e4eaffd07113c4ee0597b047e90d26b38247ab8 GIT binary patch literal 518 zcmb79Q3^mI2wV0J(EU%F;xi`*k^YQLH-%tnk86W!5XQgBl``^IFw>bYsz`~fSD)4OKIWYtC8ybHep$z%Yn literal 0 HcmV?d00001 diff --git a/assets/levels/die_and_retry.kble b/assets/levels/die_and_retry.kble new file mode 100644 index 0000000000000000000000000000000000000000..83693656d545ff184e45f791729423df675a6456 GIT binary patch literal 518 zcmaivOA>%E2txrsYwv$r36z2k)@IQTkA^@(mx_Nx<#fHkhlyIJo(s9SxYz$;by3H& zDCdh#B=tZgJHid#etJHjUMr3XZyveU{ygS? ICaIbK1`1dK@c;k- literal 0 HcmV?d00001 diff --git a/assets/levels/dome.kble b/assets/levels/dome.kble new file mode 100644 index 0000000000000000000000000000000000000000..9a94f3645f2e0e587ba3b065d509cfad37f2a4ec GIT binary patch literal 518 zcmb_YNe+NO2P?`WR?9TE?+<<9dNfRqbL4LAR@rS>G>``Fn nZF1&!_Q~kH+s`7PAIrh{Hza2UzOnDY-L4Ab@- zg5hlCAH8SZ`MCAo_a}|5*a*)j&W=Hn=6q}HPqKA>mB~+#6-j|>jJ-~ B0Gj{+ literal 0 HcmV?d00001 diff --git a/assets/levels/hello_world.kble b/assets/levels/hello_world.kble new file mode 100644 index 0000000000000000000000000000000000000000..e53f7d87a4f5e48a8ee0a88706e0f5bfb7b7965a GIT binary patch literal 518 zcmZQzVh{jAMuLz54*==L2O#n+IF%r5$F77JdF(nNqUi3Ul#gx~x_JnBVq6YUgV2M? WLNy;|CPE!Vo*62DT^=Til?DKtZ2*1% literal 0 HcmV?d00001 diff --git a/assets/levels/key_101.kble b/assets/levels/key_101.kble new file mode 100644 index 0000000000000000000000000000000000000000..9f25fb92198ca50af37ba6374a70f271990bf0e0 GIT binary patch literal 518 pcmZQzVh{jA#vuS1Z~&OwaY(~`MtgZ?pcO1|YgnNynEM7X4FCqU0OtSz literal 0 HcmV?d00001 diff --git a/assets/levels/so_far_but_so_close.kble b/assets/levels/so_far_but_so_close.kble new file mode 100644 index 0000000000000000000000000000000000000000..22910b7956d00606e0224b51c8f5cfc935896f5a GIT binary patch literal 518 zcmbV_0S1rK`1W^{);Ao4Aqg8n=OcvF%HRkn}jCp!~;k`-$R2Mky m$+5)gwY5$C&Pz-&gkC8=#WU0I?kim0`e~hevVYt@S3d!-ApoEN literal 0 HcmV?d00001 diff --git a/assets/levels/two_for_one.kble b/assets/levels/two_for_one.kble new file mode 100644 index 0000000000000000000000000000000000000000..70983be57f8b92bce59e58597a0e24572103d1c1 GIT binary patch literal 518 zcma)2NfN*y2&1&U_y4bz7&}BfD2z@>0xstEMP7$#J>X81z2M$h)Pab9M<)iS_(XR@ wGB_WYY}VA%S^cc*Ui)|YZhoDYwNL-Nz6VatdVke`RllQH^=Gj2$?6NG0q7L~#sB~S literal 0 HcmV?d00001 diff --git a/assets/levels/up_and_down.kble b/assets/levels/up_and_down.kble new file mode 100644 index 0000000000000000000000000000000000000000..44b5590ade78cec9a40cd3170aa188d9c93f84b5 GIT binary patch literal 518 zcmb7A!4`lZ2wPO1`~R;EL|mr4UUCo_8xsgFjqNi8j1$m)9%D;?dN$*G>kt&p96xH! z`K8v;lxBVm$n=R*-)r<|Gv0iuf6x8T_^2QFU;ms)f95y#v%;VLS9t7TyiGq3^?w65 ClK~3= literal 0 HcmV?d00001 diff --git a/include/conf.h b/include/conf.h new file mode 100644 index 0000000..455717d --- /dev/null +++ b/include/conf.h @@ -0,0 +1,8 @@ +#pragma once + +#define TARGET_UPS 60 +#define TARGET_FPS 30 +#define TILE_SIZE 16 +#define LEVEL_WIDTH 16 +#define LEVEL_HEIGHT 16 +#define LEVEL_SIZE (LEVEL_WIDTH * LEVEL_HEIGHT) diff --git a/include/input.h b/include/input.h new file mode 100644 index 0000000..acd0228 --- /dev/null +++ b/include/input.h @@ -0,0 +1,35 @@ +#pragma once +#include +#include + +#define KEYS_COUNT 6 +enum { + K_LEFT, + K_RIGHT, + K_DOWN, + K_JUMP, + K_RESTART, + K_EXIT +}; + +#define S_PRESSED 0 +#define S_DOWN 1 +#define S_RELEASED 2 +#define S_UP 3 + +typedef struct Input { + uint8_t keys[KEYS_COUNT]; + uint8_t states[KEYS_COUNT]; +} Input; + +/* Check for new key inputs and update accordingly. */ +void input_update(Input *input); + +/* Initialize values. */ +void input_init(Input *input); + +/* Get state of keys. */ +bool input_is_pressed(Input *input, uint8_t key); +bool input_is_down(Input *input, uint8_t key); +bool input_is_released(Input *input, uint8_t key); +bool input_is_up(Input *input, uint8_t key); diff --git a/include/level.h b/include/level.h new file mode 100644 index 0000000..9cad609 --- /dev/null +++ b/include/level.h @@ -0,0 +1,10 @@ +#pragma once +#include +#include "conf.h" +#include "vec2.h" + +typedef uint8_t tile_t; +typedef struct Level{ + tile_t content[LEVEL_WIDTH * LEVEL_HEIGHT]; + Vec2 start_pos; +} Level; diff --git a/include/player.h b/include/player.h new file mode 100644 index 0000000..87b5396 --- /dev/null +++ b/include/player.h @@ -0,0 +1,16 @@ +#pragma once +#include +#include "vec2.h" + +typedef struct Player{ + Vec2 pos; + Vec2 spd; + int8_t facing; + bool stun; + bool knocked; + uint8_t keys_left; + uint8_t jump_buffer; + uint8_t coyot; +} Player; + +Player player_init(); diff --git a/include/tiles.h b/include/tiles.h new file mode 100644 index 0000000..e4b1a43 --- /dev/null +++ b/include/tiles.h @@ -0,0 +1,13 @@ +#pragma once + +enum { + AIR_TILE, + SOLID_TILE, + PAIN_TILE, + SPAWN_TILE, + EXIT_TILE, + KEY_TILE, + SEMI_SOLID, + CHECKY_TILE, +}; +#define OUT_OF_BOUNDS AIR_TILE diff --git a/include/vec2.h b/include/vec2.h new file mode 100644 index 0000000..c7cac25 --- /dev/null +++ b/include/vec2.h @@ -0,0 +1,8 @@ +#pragma once +#include + +typedef int16_t vec2_int_t; +typedef struct Vec2{ + vec2_int_t x; + vec2_int_t y; +} Vec2; diff --git a/kble.py b/kble.py new file mode 100644 index 0000000..05b9c88 --- /dev/null +++ b/kble.py @@ -0,0 +1,109 @@ +""" +The MIT License (MIT) + +Copyright © 2021 KikooDX + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +“Software”), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +""" + +def info(*args) -> None: + #print("info:", *args) + pass + +def merge_bytes(_bytes: bytes) -> int: + """ + Get a bytes slice and merge them into an integer. + """ + mul = 256 ** len(_bytes) + sum = 0 + for byte in _bytes: + mul //= 256 + sum += byte * mul + return sum + +def kble_parse(_bytes: bytes) -> list: + """ + Read content of binary file using the KBLE format and output a two + dimensional int grid. + """ + # Read whole file at once. + # Check version byte. + assert(_bytes[0] == 0) + # Get byte length of cells. + cell_size: int = _bytes[1] + info("Cell size:", cell_size) + # Get level dimensions. + width = merge_bytes(_bytes[2:4]) + height = merge_bytes(_bytes[4:6]) + info("Level width:", width) + info("Level height:", height) + # Check than the number of bytes matches the obtained informations. + assert(len(_bytes) == width * height * cell_size + 6) + info("Correct format.") + # Process remaining bytes and add them to a list. + grid: list = [[0 for _ in range(width)] for _ in range(height)] + i: int = 6 + x: int = 0 + y: int = 0 + while (i < len(_bytes)): + SLICE = _bytes[i:i + cell_size] + grid[y][x] = merge_bytes(SLICE) + i += cell_size + x += 1 + if x == width: + x = 0 + y += 1 + info("Parsing ended successfully.") + return grid + +if __name__ == "__main__": + LEVELS_PATHS = ( + "assets/levels/hello_world.kble", + "assets/levels/damage_boosting_101.kble", + "assets/levels/chaos.kble", + "assets/levels/so_far_but_so_close.kble", + "assets/levels/key_101.kble", + "assets/levels/two_for_one.kble", + "assets/levels/up_and_down.kble", + "assets/levels/dome.kble", + "assets/levels/die_and_retry.kble", + "assets/levels/end.kble") + with open("src/gen_levels.c", "w") as c_file: + c_file.write("#include \"level.h\"\n#include \"vec2.h\"\n") + c_file.write("const Level levels[] = {\n") + for level_path in LEVELS_PATHS: + c_file.write("\t{\n\t\t.content = {") + with open(level_path, "rb") as file: + BYTES = file.read() + data = kble_parse(BYTES) + start_x = 0 + start_y = 0 + for y, line in enumerate(data): + for x, tile in enumerate(line): + c_file.write(str(tile)) + c_file.write(", ") + if tile == 3: # spawn tile + start_x, start_y = x, y + c_file.write("},\n") + c_file.write("\t\t.start_pos = (Vec2){") + c_file.write(f"{start_x}, {start_y}") + c_file.write("}\n\t},\n") + c_file.write("};") + diff --git a/src/input.c b/src/input.c new file mode 100644 index 0000000..d5c12eb --- /dev/null +++ b/src/input.c @@ -0,0 +1,55 @@ +#include +#include "input.h" + +void input_update(Input *input) { + /* Read full input stream. */ + clearevents(); + /* For each key, update state. */ + for (int i = 0; i < KEYS_COUNT; ++i) { + uint8_t *state = &input->states[i]; + const uint8_t key = input->keys[i]; + /* See if the key is pressed. */ + const bool pressed = keydown(key); + /* Update input status. */ + if (pressed) { + if (*state == S_RELEASED || *state == S_UP) + *state = S_PRESSED; + else + *state = S_DOWN; + } + else { + if (*state == S_PRESSED || *state == S_DOWN) + *state = S_RELEASED; + else + *state = S_UP; + } + } +} + +void input_init(Input *input) { + /* initialize all values to S_UP, avoid random bugs */ + input->keys[K_LEFT] = KEY_LEFT; + input->keys[K_RIGHT] = KEY_RIGHT; + input->keys[K_DOWN] = KEY_DOWN; + input->keys[K_JUMP] = KEY_SHIFT; + input->keys[K_RESTART] = KEY_6; + input->keys[K_EXIT] = KEY_EXIT; + for (int i = 0; i < KEYS_COUNT; ++i) + input->states[i] = S_UP; +} + +bool input_is_pressed(Input *input, uint8_t key) { + return input->states[key] == S_PRESSED; +} + +bool input_is_down(Input *input, uint8_t key) { + return (input->states[key] == S_DOWN) || (input->states[key] == S_PRESSED); +} + +bool input_is_released(Input *input, uint8_t key) { + return input->states[key] == S_RELEASED; +} + +bool input_is_up(Input *input, uint8_t key) { + return (input->states[key] == S_UP) || (input->states[key] == S_RELEASED); +} diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..f90dcce --- /dev/null +++ b/src/main.c @@ -0,0 +1,59 @@ +#include +#include +#include +#include +#include +#include +#include "conf.h" +#include "input.h" +#include "level.h" +#include "player.h" + +void load_level(Level *level, Player *player, uint8_t id) { + extern Level levels[LEVEL_SIZE]; + memcpy(level->content, levels[id].content, LEVEL_SIZE); + level->start_pos = levels[id].start_pos; + player->pos = levels[id].start_pos; +} + +int callback(volatile void *arg) { + volatile bool *has_ticked = arg; + *has_ticked = true; + return 0; +} + +int main(void) { + /* Initialize player. */ + Player player = player_init(); + /* Initialize level. */ + Level level = (Level){}; + uint8_t level_id = 0; + load_level(&level, &player, level_id); + /* Initialize input. */ + Input input = (Input){}; + input_init(&input); + + /* UPS control. */ + volatile bool has_ticked = true; + int timer = timer_setup(TIMER_ANY, 1000000/TARGET_UPS, callback, &has_ticked); + timer_start(timer); + + /* Core loop. */ + while (!input_is_down(&input, K_EXIT)) { + /* Repeat step event so the UPS is constant. */ + for (uint8_t i = 0; i < TARGET_UPS / TARGET_FPS; i += 1) { + /* UPS control. */ + while (!has_ticked) sleep(); + has_ticked = false; + /* Update. */ + input_update(&input); + /* player_update(&player, &level, &level_id); */ + } + /* Draw. */ + dclear(C_BLACK); + /* player_draw(player); */ + dupdate(); + } + + return 1; +} diff --git a/src/player.c b/src/player.c new file mode 100644 index 0000000..7a71554 --- /dev/null +++ b/src/player.c @@ -0,0 +1,15 @@ +#include "player.h" +#include "vec2.h" + +Player player_init() { + return (Player){ + .pos = (Vec2){}, + .spd = (Vec2){}, + .facing = 1, + .stun = false, + .knocked = false, + .keys_left = 0, + .jump_buffer = 0, + .coyot = 0, + }; +}