Decently small and minimalistic working base.

This commit is contained in:
KikooDX 2021-03-02 00:21:01 +01:00
commit f3f6677386
25 changed files with 396 additions and 0 deletions

19
.gitignore vendored Normal file
View File

@ -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

48
CMakeLists.txt Normal file
View File

@ -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()

View File

@ -0,0 +1 @@

BIN
assets-cg/icon-sel.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

BIN
assets-cg/icon-uns.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

BIN
assets/levels/chaos.kble Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
assets/levels/dome.kble Normal file

Binary file not shown.

BIN
assets/levels/end.kble Normal file

Binary file not shown.

Binary file not shown.

BIN
assets/levels/key_101.kble Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

8
include/conf.h Normal file
View File

@ -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)

35
include/input.h Normal file
View File

@ -0,0 +1,35 @@
#pragma once
#include <stdint.h>
#include <stdbool.h>
#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);

10
include/level.h Normal file
View File

@ -0,0 +1,10 @@
#pragma once
#include <stdint.h>
#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;

16
include/player.h Normal file
View File

@ -0,0 +1,16 @@
#pragma once
#include <stdint.h>
#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();

13
include/tiles.h Normal file
View File

@ -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

8
include/vec2.h Normal file
View File

@ -0,0 +1,8 @@
#pragma once
#include <stdbool.h>
typedef int16_t vec2_int_t;
typedef struct Vec2{
vec2_int_t x;
vec2_int_t y;
} Vec2;

109
kble.py Normal file
View File

@ -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("};")

55
src/input.c Normal file
View File

@ -0,0 +1,55 @@
#include <gint/keyboard.h>
#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);
}

59
src/main.c Normal file
View File

@ -0,0 +1,59 @@
#include <gint/display.h>
#include <gint/timer.h>
#include <gint/clock.h>
#include <gint/std/string.h>
#include <stdint.h>
#include <stdbool.h>
#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;
}

15
src/player.c Normal file
View File

@ -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,
};
}