This commit is contained in:
2026-03-21 15:45:24 +01:00
commit 048575c14c
22 changed files with 589 additions and 0 deletions

9
.clang-format Normal file
View File

@@ -0,0 +1,9 @@
---
BasedOnStyle: Google
IndentWidth: 4
BreakBeforeBraces: Linux
AllowShortEnumsOnASingleLine: false
AllowShortFunctionsOnASingleLine: None
BinPackArguments: false
BinPackParameters: false

4
.editorconfig Normal file
View File

@@ -0,0 +1,4 @@
[*]
root = true
indent_style = space
indent_size = 4

10
.gitignore vendored Normal file
View File

@@ -0,0 +1,10 @@
# Xmake cache
.xmake/
build/
.cache
# MacOS Cache
.DS_Store

BIN
assets/ball.aseprite Normal file

Binary file not shown.

BIN
assets/ball.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 484 B

BIN
assets/block.aseprite Normal file

Binary file not shown.

BIN
assets/block.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 147 B

31
compile_commands.json Normal file
View File

@@ -0,0 +1,31 @@
[
{
"directory": "/home/jens/Development/cex/colossus_march",
"arguments": ["/usr/bin/gcc", "-c", "-m64", "-g", "-O0", "-std=c23", "-Isrc", "-Isrc/screens", "-I", "/home/jens/.xmake/packages/r/raylib/5.5/efaf75c5cc7042868d9f9fc4196a080a/include", "-I", "/home/jens/.xmake/packages/b/box2d/v3.1.1/2aecaa50772341c7b9eb7c79ee9859aa/include", "-o", "build/.objs/colossus_march/linux/x86_64/debug/src/screens/intro.c.o", "src/screens/intro.c"],
"file": "src/screens/intro.c"
},
{
"directory": "/home/jens/Development/cex/colossus_march",
"arguments": ["/usr/bin/gcc", "-c", "-m64", "-g", "-O0", "-std=c23", "-Isrc", "-Isrc/screens", "-I", "/home/jens/.xmake/packages/r/raylib/5.5/efaf75c5cc7042868d9f9fc4196a080a/include", "-I", "/home/jens/.xmake/packages/b/box2d/v3.1.1/2aecaa50772341c7b9eb7c79ee9859aa/include", "-o", "build/.objs/colossus_march/linux/x86_64/debug/src/screens/menu.c.o", "src/screens/menu.c"],
"file": "src/screens/menu.c"
},
{
"directory": "/home/jens/Development/cex/colossus_march",
"arguments": ["/usr/bin/gcc", "-c", "-m64", "-g", "-O0", "-std=c23", "-Isrc", "-Isrc/screens", "-I", "/home/jens/.xmake/packages/r/raylib/5.5/efaf75c5cc7042868d9f9fc4196a080a/include", "-I", "/home/jens/.xmake/packages/b/box2d/v3.1.1/2aecaa50772341c7b9eb7c79ee9859aa/include", "-o", "build/.objs/colossus_march/linux/x86_64/debug/src/screens/game.c.o", "src/screens/game.c"],
"file": "src/screens/game.c"
},
{
"directory": "/home/jens/Development/cex/colossus_march",
"arguments": ["/usr/bin/gcc", "-c", "-m64", "-g", "-O0", "-std=c23", "-Isrc", "-Isrc/screens", "-I", "/home/jens/.xmake/packages/r/raylib/5.5/efaf75c5cc7042868d9f9fc4196a080a/include", "-I", "/home/jens/.xmake/packages/b/box2d/v3.1.1/2aecaa50772341c7b9eb7c79ee9859aa/include", "-o", "build/.objs/colossus_march/linux/x86_64/debug/src/sprite.c.o", "src/sprite.c"],
"file": "src/sprite.c"
},
{
"directory": "/home/jens/Development/cex/colossus_march",
"arguments": ["/usr/bin/gcc", "-c", "-m64", "-g", "-O0", "-std=c23", "-Isrc", "-Isrc/screens", "-I", "/home/jens/.xmake/packages/r/raylib/5.5/efaf75c5cc7042868d9f9fc4196a080a/include", "-I", "/home/jens/.xmake/packages/b/box2d/v3.1.1/2aecaa50772341c7b9eb7c79ee9859aa/include", "-o", "build/.objs/colossus_march/linux/x86_64/debug/src/main.c.o", "src/main.c"],
"file": "src/main.c"
},
{
"directory": "/home/jens/Development/cex/colossus_march",
"arguments": ["/usr/bin/gcc", "-c", "-m64", "-g", "-O0", "-std=c23", "-Isrc", "-Isrc/screens", "-I", "/home/jens/.xmake/packages/r/raylib/5.5/efaf75c5cc7042868d9f9fc4196a080a/include", "-I", "/home/jens/.xmake/packages/b/box2d/v3.1.1/2aecaa50772341c7b9eb7c79ee9859aa/include", "-o", "build/.objs/colossus_march/linux/x86_64/debug/src/screens.c.o", "src/screens.c"],
"file": "src/screens.c"
}]

BIN
screenshot000.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

38
src/defs.h Normal file
View File

@@ -0,0 +1,38 @@
#pragma once
#include <stddef.h>
#include <stdint.h>
#include "raylib.h"
#define GAME_NAME "Colossus March"
#define BG CLITERAL(Color){243, 223, 162, 255}
#define BALL CLITERAL(Color){126, 189, 194, 255}
#define BLOCK CLITERAL(Color){187, 68, 48, 255}
#define length(a) (sizeof(a) / sizeof(*a))
#define append(a, i) \
{ \
a.data[a.len] = i; \
a.len++; \
}
typedef size_t size;
typedef int8_t i8;
typedef int16_t i16;
typedef int32_t i32;
typedef int64_t i64;
typedef uint8_t u8;
typedef uint16_t u16;
typedef uint32_t u32;
typedef uint64_t u64;
typedef struct GameContext {
bool exit;
} GameContext;
extern GameContext g_ctx;

30
src/main.c Normal file
View File

@@ -0,0 +1,30 @@
#include <stdint.h>
#include "defs.h"
#include "raylib.h"
#include "screens.h"
GameContext g_ctx = {0};
int main(void)
{
SetConfigFlags(FLAG_WINDOW_RESIZABLE);
InitWindow(800, 600, "flappu");
SetTargetFPS(144);
SetExitKey(KEY_F12);
while (!WindowShouldClose() && !g_ctx.exit) {
screen_update();
BeginDrawing();
ClearBackground(BG);
screen_draw();
EndDrawing();
}
CloseWindow();
return 0;
}

65
src/screens.c Normal file
View File

@@ -0,0 +1,65 @@
#include "screens.h"
#include "game.h"
#include "intro.h"
#include "menu.h"
static Screen active_screen = Intro;
void screen_switch_to(Screen screen)
{
if (screen != active_screen) {
switch (active_screen) {
case Intro:
intro_screen_cleanup();
break;
case Menu:
menu_screen_cleanup();
break;
case Game:
game_screen_cleanup();
break;
}
active_screen = screen;
switch (active_screen) {
case Intro:
case Menu:
break;
case Game:
game_screen_init();
break;
}
}
}
void screen_update()
{
switch (active_screen) {
case Intro: {
intro_screen_update();
} break;
case Menu: {
menu_screen_update();
} break;
case Game: {
game_screen_update();
} break;
}
}
void screen_draw()
{
switch (active_screen) {
case Intro: {
intro_screen_draw();
} break;
case Menu: {
menu_screen_draw();
} break;
case Game: {
game_screen_draw();
} break;
}
}

11
src/screens.h Normal file
View File

@@ -0,0 +1,11 @@
#pragma once
typedef enum Screen {
Intro,
Menu,
Game
} Screen;
void screen_switch_to(Screen screen);
void screen_update();
void screen_draw();

89
src/screens/game.c Normal file
View File

@@ -0,0 +1,89 @@
#include "game.h"
#include <stddef.h>
#include <stdlib.h>
#include "raylib.h"
#include "raymath.h"
#include "screens.h"
#include "sprite.h"
static Player player;
static Camera2D cam;
static bool paused = false;
static bool game_over = false;
void process_input()
{
if (IsKeyPressed(KEY_P)) {
paused = true;
}
if (IsKeyPressed(KEY_F10)) {
screen_switch_to(Menu);
}
}
void game_screen_init()
{
paused = 0;
game_over = 0;
Sprite* player_sprite = sprite_new("assets/ball.png",
&(Vector2){100, 400},
NULL,
&(Rectangle){0, 0, 32, 32},
&BALL);
Animation* anim = malloc(sizeof(Animation));
if (!anim) abort();
*anim = (Animation){
.current_frame = 0, .frame_count = 3, .current_time = 0, .fps = 4};
player_sprite->animation = anim;
player = (Player){player_sprite};
cam = (Camera2D){{200, GetScreenHeight() / 2.0f}, player.sprite->pos, 0, 2};
}
void game_screen_update()
{
if (game_over) {
if (IsKeyPressed(KEY_SPACE)) {
game_over = false;
game_screen_cleanup();
game_screen_init();
}
return;
}
if (paused) return;
float dt = GetFrameTime();
process_input();
// Update Camera
cam.target = Vector2Lerp(cam.target, player.sprite->pos, 0.1);
// Update Animation
// TODO: make it scalable
animation_update(player.sprite->animation);
};
void game_screen_draw()
{
BeginMode2D(cam);
// Draw Stuff
sprite_draw(player.sprite);
EndMode2D();
}
void game_screen_cleanup()
{
// free player
sprite_free(player.sprite);
};

12
src/screens/game.h Normal file
View File

@@ -0,0 +1,12 @@
#pragma once
#include "sprite.h"
typedef struct Player {
Sprite* sprite;
} Player;
void game_screen_init();
void game_screen_update();
void game_screen_draw();
void game_screen_cleanup();

21
src/screens/intro.c Normal file
View File

@@ -0,0 +1,21 @@
#include "intro.h"
#include "defs.h"
#include "raylib.h"
#include "screens.h"
void intro_screen_update()
{
if (IsKeyPressed(KEY_ENTER)) {
screen_switch_to(Menu);
}
}
void intro_screen_draw()
{
DrawText(GAME_NAME, 120, 100, 120, WHITE);
}
void intro_screen_cleanup()
{
}

5
src/screens/intro.h Normal file
View File

@@ -0,0 +1,5 @@
#pragma once
void intro_screen_update();
void intro_screen_draw();
void intro_screen_cleanup();

63
src/screens/menu.c Normal file
View File

@@ -0,0 +1,63 @@
#include "menu.h"
#include <stddef.h>
#include <stdint.h>
#include "defs.h"
#include "raylib.h"
#include "screens.h"
typedef enum Option {
Start,
Settings,
Quit
} Option;
static const Option menu_options[] = {Start, Settings, Quit};
size_t selected = Start;
void menu_screen_update()
{
if (IsKeyPressed(KEY_ENTER)) {
switch (menu_options[selected]) {
case Start:
screen_switch_to(Game);
break;
case Settings:
break;
case Quit:
g_ctx.exit = true;
break;
}
}
if (IsKeyPressed(KEY_DOWN)) {
selected += 1;
}
if (IsKeyPressed(KEY_UP)) {
selected -= 1;
}
if (selected <= 0) selected = 0;
if (selected >= length(menu_options)) selected = length(menu_options) - 1;
};
void menu_screen_draw()
{
for (size_t i = 0; i < length(menu_options); i++) {
Color color = selected == i ? GREEN : WHITE;
switch ((Option)menu_options[i]) {
case Start:
DrawText("Start", 20, 100 * i + 100, 64, color);
break;
case Settings:
DrawText("Settings", 20, 100 * i + 100, 64, color);
break;
case Quit:
DrawText("Quit", 20, 100 * i + 100, 64, color);
break;
}
}
}
void menu_screen_cleanup() {};

5
src/screens/menu.h Normal file
View File

@@ -0,0 +1,5 @@
#pragma once
void menu_screen_update();
void menu_screen_draw();
void menu_screen_cleanup();

84
src/sprite.c Normal file
View File

@@ -0,0 +1,84 @@
#include "sprite.h"
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include "raylib.h"
#include "raymath.h"
void* xmalloc(size_t size)
{
void* p = malloc(size);
if (!p) abort();
return p;
}
Sprite* sprite_new(const char* path,
Vector2* pos,
Vector2* anchor,
Rectangle* source,
Color* color)
{
assert(path && "path must not be empty");
Sprite* sprite = xmalloc(sizeof(Sprite));
if (!sprite) abort();
sprite->tex = LoadTexture(path);
sprite->pos = pos != NULL ? *pos : (Vector2){0, 0};
sprite->source =
source != NULL
? *source
: (Rectangle){0, 0, sprite->tex.width, sprite->tex.height};
sprite->anchor = anchor != NULL ? *anchor
: (Vector2){sprite->source.width / 2.0f,
sprite->source.height / 2.0f};
sprite->color = color != NULL ? *color : (Color){26, 164, 98, 255};
sprite->animation = NULL;
return sprite;
}
void sprite_draw(Sprite* s)
{
Rectangle source = s->source;
// update source rect if sprite has animation
if (s->animation) {
source.x = source.width * (float)s->animation->current_frame;
}
DrawTextureRec(
s->tex, source, Vector2Subtract(s->pos, s->anchor), s->color);
}
void sprite_free(Sprite* s)
{
if (s->animation) free(s->animation);
UnloadTexture(s->tex);
free(s);
}
//
// Animation System
//
void animation_update(Animation* a)
{
float dt = GetFrameTime();
a->current_time += dt;
if (a->current_time >= 1.0f / a->fps) {
a->current_time = 0;
a->current_frame++;
if (a->current_frame >= a->frame_count) {
a->current_frame = 0;
}
}
}

32
src/sprite.h Normal file
View File

@@ -0,0 +1,32 @@
#pragma once
#include "defs.h"
#include "raylib.h"
typedef struct Animation {
u8 frame_count;
u8 current_frame;
u8 fps;
float current_time;
} Animation;
typedef struct Sprite {
Texture2D tex;
Vector2 pos;
Vector2 anchor;
Rectangle source;
Color color;
Animation* animation;
} Sprite;
Sprite* sprite_new(const char* path,
Vector2* pos,
Vector2* anchor,
Rectangle* source,
Color* color);
void sprite_draw(Sprite* sprite);
void sprite_free(Sprite* sprite);
void animation_update(Animation* a);

80
xmake.lua Normal file
View File

@@ -0,0 +1,80 @@
add_rules("mode.debug", "mode.release")
add_requires("raylib", "box2d")
target("colossus_march")
set_languages("c23")
set_kind("binary")
add_files("src/**.c")
add_packages("raylib", "box2d")
add_includedirs("src", os.dirs("src/**"))
set_rundir("$(projectdir)")
--
-- If you want to known more usage about xmake, please see https://xmake.io
--
-- ## FAQ
--
-- You can enter the project directory firstly before building project.
--
-- $ cd projectdir
--
-- 1. How to build project?
--
-- $ xmake
--
-- 2. How to configure project?
--
-- $ xmake f -p [macosx|linux|iphoneos ..] -a [x86_64|i386|arm64 ..] -m [debug|release]
--
-- 3. Where is the build output directory?
--
-- The default output directory is `./build` and you can configure the output directory.
--
-- $ xmake f -o outputdir
-- $ xmake
--
-- 4. How to run and debug target after building project?
--
-- $ xmake run [targetname]
-- $ xmake run -d [targetname]
--
-- 5. How to install target to the system directory or other output directory?
--
-- $ xmake install
-- $ xmake install -o installdir
--
-- 6. Add some frequently-used compilation flags in xmake.lua
--
-- @code
-- -- add debug and release modes
-- add_rules("mode.debug", "mode.release")
--
-- -- add macro definition
-- add_defines("NDEBUG", "_GNU_SOURCE=1")
--
-- -- set warning all as error
-- set_warnings("all", "error")
--
-- -- set language: c99, c++11
-- set_languages("c99", "c++11")
--
-- -- set optimization: none, faster, fastest, smallest
-- set_optimize("fastest")
--
-- -- add include search directories
-- add_includedirs("/usr/include", "/usr/local/include")
--
-- -- add link libraries and search directories
-- add_links("tbox")
-- add_linkdirs("/usr/local/lib", "/usr/lib")
--
-- -- add system link libraries
-- add_syslinks("z", "pthread")
--
-- -- add compilation and link flags
-- add_cxflags("-stdnolib", "-fno-strict-aliasing")
-- add_ldflags("-L/usr/local/lib", "-lpthread", {force = true})
--
-- @endcode
--