Switching to sfml

This commit is contained in:
noffie 2025-03-17 20:04:47 +01:00
parent 4536c62dad
commit de72aead56
40 changed files with 462 additions and 2385 deletions

1
.gitignore vendored
View file

@ -10,3 +10,4 @@ build
cmake-**/ cmake-**/
.kdev4 .kdev4
*.kdev4 *.kdev4
assets/

View file

@ -1,7 +1,7 @@
cmake_minimum_required(VERSION 3.20) cmake_minimum_required(VERSION 3.20)
project(colysis project(colysis
LANGUAGES C CXX LANGUAGES CXX
VERSION 0.0.1 VERSION 0.0.1
) )
@ -10,7 +10,7 @@ set(CMAKE_C_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED ON) set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_C_EXTENSIONS OFF) set(CMAKE_C_EXTENSIONS OFF)
set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF) set(CMAKE_CXX_EXTENSIONS OFF)
@ -22,24 +22,20 @@ set(BUILD_SHARED_LIBS OFF CACHE BOOL "" FORCE) # Build static libraries by
include(cmake/CPM.cmake) include(cmake/CPM.cmake)
# sfml
CPMAddPackage( CPMAddPackage(
NAME raylib NAME sfml
GITHUB_REPOSITORY raysan5/raylib GITHUB_REPOSITORY SFML/SFML
GIT_TAG 5.5 GIT_TAG 3.0.0
) )
CPMAddPackage( # # flecs
NAME flecs # CPMAddPackage(
GITHUB_REPOSITORY SanderMertens/flecs # NAME flecs
GIT_TAG v4.0.4 # GITHUB_REPOSITORY SanderMertens/flecs
) # GIT_TAG v4.0.4
# )
## alyson engine (needs flecs and raylib)
set(ASSETS_PATH "${CMAKE_CURRENT_SOURCE_DIR}/assets/")
add_subdirectory(alyson)
## Colysis .game
include(cmake/utils.cmake) include(cmake/utils.cmake)
@ -51,22 +47,17 @@ add_executable(colysis
) )
target_link_libraries(colysis target_link_libraries(colysis
raylib SFML::Audio
flecs::flecs_static SFML::Graphics
alyson SFML::Window
SFML::System
) )
target_include_directories(colysis PUBLIC include
#${ALYSON_INCLUDE_DIR}
)
# put the assets folder path as a C preprocessor define # put the assets folder path as a C preprocessor define
set(ASSETS_PATH "${CMAKE_CURRENT_SOURCE_DIR}/assets/")
target_compile_definitions(colysis PRIVATE ASSETS_PATH="${ASSETS_PATH}") target_compile_definitions(colysis PRIVATE ASSETS_PATH="${ASSETS_PATH}")
message(STATUS "Assets path : ${ASSETS_PATH}")
# if the os is windows, add the uninstall target to the vendor/raylib folder # put_targets_into_folder(FOLDER "vendor/flecs" TARGETS flecs::flecs flecs::flecs_static)
if(WIN32)
put_targets_into_folder(FOLDER "vendor/raylib" TARGETS uninstall)
endif()
put_targets_into_folder(FOLDER "vendor/raylib" TARGETS raylib)
put_targets_into_folder(FOLDER "vendor/flecs" TARGETS flecs::flecs flecs::flecs_static)

View file

@ -1,6 +1,5 @@
# Colysis # Colysis
A little video game with a custom engine written in C/C++. A simple game engine written in C++ and using SFML.
It uses [Flecs](https://github.com/SanderMertens/flecs) as an ECS framework and [Raylib](https://www.raylib.com/) as a 2D graphics library.
## Building ## Building
To build the project, you need to have [CMake](https://cmake.org/) installed. To build the project, you need to have [CMake](https://cmake.org/) installed.

View file

@ -1,61 +0,0 @@
project(alyson
VERSION 0.0.1
LANGUAGES C CXX
)
cmake_minimum_required(VERSION 3.20)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
include(cmake/utils.cmake)
add_library(alyson)
target_include_directories(alyson PUBLIC includes)
CPMAddPackage(
NAME raylib
GITHUB_REPOSITORY raysan5/raylib
GIT_TAG 5.5
)
CPMAddPackage(
NAME flecs
GITHUB_REPOSITORY SanderMertens/flecs
GIT_TAG v4.0.4
)
target_link_libraries(alyson PUBLIC raylib)
target_link_libraries(alyson PUBLIC flecs::flecs_static)
target_compile_definitions(alyson PRIVATE ASSETS_PATH="${ASSETS_PATH}")
# Add alyson files
find_files(alyson_src src cpp hpp cxx hxx c h)
target_sources(alyson PRIVATE ${alyson_src})
# set(ALYSON_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/alyson/include)
# google tests
find_package(GTest QUIET)
if(NOT GTest_FOUND)
FetchContent_Declare(
googletest
GIT_REPOSITORY https://github.com/google/googletest.git
GIT_TAG release-1.12.1
)
FetchContent_MakeAvailable(googletest)
endif()
find_files(alyson_test_src tests cpp hpp cxx hxx c h)
add_executable(alyson_test ${alyson_test_src})
target_link_libraries(alyson_test PRIVATE alyson)
target_link_libraries(alyson_test PRIVATE GTest::gtest)
target_link_libraries(alyson_test PRIVATE GTest::gtest_main)
target_include_directories(alyson_test PRIVATE ${GTEST_INCLUDE_DIRS})

View file

@ -1,21 +0,0 @@
The MIT License (MIT)
Copyright (c) 2025 n0ffie (noffie.github@icloud.com)
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.

File diff suppressed because it is too large Load diff

View file

@ -1,33 +0,0 @@
function(put_targets_into_folder)
set(oneValueArgs FOLDER)
set(multiValueArgs TARGETS)
cmake_parse_arguments(ARGS "" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
foreach(target ${ARGS_TARGETS})
# Check if target exists
if (NOT TARGET ${target})
message(FATAL_ERROR "${target} target not found")
endif()
# Get the actual target (if it is aliased)
get_target_property(actual_target ${target} ALIASED_TARGET)
if (NOT actual_target)
set(actual_target ${target})
endif()
# Set the folder property for the target
set_target_properties(${actual_target} PROPERTIES FOLDER ${ARGS_FOLDER})
endforeach()
endfunction()
function(find_files var_name path)
set(sources)
foreach(ext ${ARGN})
file(GLOB_RECURSE files "${path}/*.${ext}")
list(APPEND sources ${files})
endforeach()
set(${var_name} ${${var_name}} ${sources} PARENT_SCOPE)
endfunction()

View file

@ -1,22 +0,0 @@
#ifndef ALARGS_H_INCLUDED
#define ALARGS_H_INCLUDED
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
int argc;
char** argv;
} alyson_args_t, *ALArgs;
ALArgs al_args_create(int argc, char** argv);
void al_args_destroy(ALArgs args);
#ifdef __cplusplus
}
#endif
#endif // ALARGS_H_INCLUDED

View file

@ -1,29 +0,0 @@
#ifdef __cplusplus
extern "C" {
#endif
#include <raylib.h>
#include "types.h"
typedef struct {
Texture2D texture;
uveci2 texture_dimentions;
uveci2 rows_and_collumns;
uveci2 tile_dimentions;
} al_tilemap_t, *ALTilemap;
typedef struct {
ALTilemap map;
umat2 source;
} al_tile_t, *ALTile;
#ifdef __cplusplus
}
#endif

View file

@ -1,90 +0,0 @@
#pragma once
#ifndef ALYSON_HPP
#define ALYSON_HPP
#ifndef ASSETS_PATH
#define ASSETS_PATH "./assets/"
#endif
#ifdef __cplusplus
extern "C" {
#endif
#include <stddef.h>
#include "types.h"
#define ALYSIS_ENGINE_WINDOW_TITLE "Alyson Engine"
#include "alargs.h"
#include "resources/alpath.h"
#include "resources/alresource.h"
#if defined(RAYLIB_BACKEND)
#include <raylib.h>
#include <raymath.h>
#include <rlyson.h>
#endif
/* TODO : implement
typedef struct {
ALResource* resources;
usx count;
usx capacity;
} alyson_resource_manager_t, *ALResourceManager;
ALResourceManager al_resource_manager_create();
void al_resource_manager_destroy(ALResourceManager manager);
void al_resource_manager_add(ALResourceManager manager, ALResource resource);
void al_resource_manager_remove(ALResourceManager manager, usx id);
void al_resource_manager_clear(ALResourceManager manager);
typedef struct {
ALResourceManager resources_manager;
usx id;
char* name;
usx width;
usx height;
} alyson_window_t, *ALWindow;
ALWindow al_window_create(char* name, int width, int height);
void al_window_destroy(ALWindow window);
#include <flecs.h>
typedef struct {
ALWindow wnd;
ecs_world_t* engine;
ecs_world_t* ui;
} alyson_engine_t, *ALEngine;
ALEngine al_engine_create(ALArgs args, ALWindow wnd = NULL);
void al_engine_destroy(ALEngine engine);
void al_engine_run(ALEngine engine);
void al_engine_stop(ALEngine engine);
bool al_engine_is_running(ALEngine engine);
bool al_engine_is_stopped(ALEngine engine);
void al_engine_update(ALEngine engine);
void al_engine_draw(ALEngine engine);
void al_engine_draw_ui(ALEngine engine);
void al_engine_set_window(ALEngine engine, ALWindow wnd);
ALWindow al_engine_get_window(ALEngine engine);
*/
#ifdef __cplusplus
}
#endif
#endif // ALYSON_HPP

View file

@ -1,38 +0,0 @@
#ifndef ANIMATION_SPRITE_H
#define ANIMATION_SPRITE_H
#include <raylib.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
Texture2D texture;
Vector2 dimentions;
Rectangle sourceRect;
Vector2 size;
float rotation;
float scale;
int frameCount;
int currentFrame;
float speed;
float time;
} sprite_animation_t, *SpriteAnimation;
SpriteAnimation CreateSpriteAnimation(Texture2D texture, Vector2 sprite_texture_dimentions, Vector2 sprite_size, float rotation, float scale, int frameCount, float speed);
void UpdateSpriteAnimation(SpriteAnimation spriteAnimation, float dt);
void DrawSpriteAnimation(SpriteAnimation spriteAnimation, Vector2 position);
void DestroySpriteAnimation(SpriteAnimation spriteAnimation);
#ifdef __cplusplus
}
#endif
#endif // ANIMATION_SPRITE_H

View file

@ -1,36 +0,0 @@
#ifndef ALPATH_H_INCLUDED
#define ALPATH_H_INCLUDED
#ifdef __cplusplus
extern "C" {
#endif
#include "../types.h"
typedef struct {
char type[4 + 1];
char group[26 + 1];
char* name;
char* path;
} alyson_path_t, *ALPath;
/*
* @function: demangle_path
* @description: Demangles a path
* @param path: path to resource
* @return: ALPath
*/
ALPath al_demangle_path(const char* path);
char* al_mangle_path(const ALPath path);
ALPath al_create_path(
const char* type,
const char* path,
const char* name,
const char* group
);
void al_destroy_path(ALPath path);
#ifdef __cplusplus
}
#endif
#endif // ALPATH_H_INCLUDED

View file

@ -1,26 +0,0 @@
#ifndef ALRESOURCE_H_INCLUDED
#define ALRESOURCE_H_INCLUDED
#ifdef __cplusplus
extern "C" {
#endif
#include "../types.h"
#include "alpath.h"
typedef struct {
usx id;
alyson_path_t path;
} alyson_resource_t, *ALResource;
ALResource al_resource_create(ALPath path);
ALResource al_resource_create_from_file(char* name, char* path);
void al_resource_destroy(ALResource resource);
#ifdef __cplusplus
}
#endif
#endif // ALRESOURCE_H_INCLUDED

View file

@ -1,47 +0,0 @@
#ifndef RLYSON_HPP
#define RLYSON_HPP
#ifdef __cplusplus
extern "C" {
#endif
#include <raylib.h>
/*
the following functions are not part of the raylib API,
but are used by alyson and can be used by other projects using alyson
*/
typedef enum {
TEXT_ORIENTATION_LEFT,
TEXT_ORIENTATION_RIGHT,
TEXT_ORIENTATION_CENTER
} text_orientation_t;
void DrawTextFull(
Font font,
const char* text,
Vector2 origin,
text_orientation_t orientation,
float rotation,
float fontSize,
float spacing,
float lineSpacing,
Color tint
);
#ifndef RLAYSON_NO_ANIMATION
#include <animation/sprite.h>
// other animation types
#endif
#ifdef __cplusplus
}
#endif
#endif // RLYSON_HPP

View file

@ -1,100 +0,0 @@
//
// Created by n0ffie on 07/02/25.
//
#ifndef TYPES_H
#define TYPES_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
/*
* Basic types
*
* u8 - unsigned 8-bit integer
* u16 - unsigned 16-bit integer
* u32 - unsigned 32-bit integer
* u64 - unsigned 64-bit integer
*
* i8 - signed 8-bit integer
* i16 - signed 16-bit integer
* i32 - signed 32-bit integer
* i64 - signed 64-bit integer
*
* f32 - 32-bit floating point number
* f64 - 64-bit floating point number
*
* usx - unsigned size_t
* isx - signed size_t
*/
typedef uint64_t u64;
typedef uint32_t u32;
typedef uint16_t u16;
typedef uint8_t u8;
typedef int64_t i64;
typedef int32_t i32;
typedef int16_t i16;
typedef int8_t i8;
typedef float f32;
typedef double f64;
typedef size_t usx;
typedef ptrdiff_t isx;
typedef bool boolean;
/*
* Vectors and Matrices
*/
#define ALYSON_DEFINE_VECTOR2_TYPE(type, ...) typedef struct { type x; type y; } __VA_ARGS__
#define ALYSON_DEFINE_VECTOR3_TYPE(type, ...) typedef struct { type x; type y; type z; } __VA_ARGS__
#define ALYSON_DEFINE_VECTOR4_TYPE(type, ...) typedef struct { type x; type y; type z; type w; } __VA_ARGS__
ALYSON_DEFINE_VECTOR2_TYPE(f32, vec2, vec2f);
ALYSON_DEFINE_VECTOR3_TYPE(f32, vec3, vec3f);
ALYSON_DEFINE_VECTOR4_TYPE(f32, vec4, vec4f);
ALYSON_DEFINE_VECTOR2_TYPE(f64, vecd2);
ALYSON_DEFINE_VECTOR3_TYPE(f64, vecd3);
ALYSON_DEFINE_VECTOR4_TYPE(f64, vecd4);
ALYSON_DEFINE_VECTOR2_TYPE(i32, veci2);
ALYSON_DEFINE_VECTOR3_TYPE(i32, veci3);
ALYSON_DEFINE_VECTOR4_TYPE(i32, veci4);
ALYSON_DEFINE_VECTOR2_TYPE(u32, uveci2);
ALYSON_DEFINE_VECTOR3_TYPE(u32, uveci3);
ALYSON_DEFINE_VECTOR4_TYPE(u32, uveci4);
#define ALYSON_DEFINE_MATRIX_2x2_TYPE(type, ...) typedef struct { type m00; type m01; type m10; type m11; } __VA_ARGS__
#define ALYSON_DEFINE_MATRIX_3x3_TYPE(type, ...) typedef struct { type m00; type m01; type m02; type m10; type m11; type m12; type m20; type m21; type m22; } __VA_ARGS__
#define ALYSON_DEFINE_MATRIX_4x4_TYPE(type, ...) typedef struct { type m00; type m01; type m02; type m03; type m10; type m11; type m12; type m13; type m20; type m21; type m22; type m23; type m30; type m31; type m32; type m33; } __VA_ARGS__
ALYSON_DEFINE_MATRIX_2x2_TYPE(f32, mat2, fmat2);
ALYSON_DEFINE_MATRIX_3x3_TYPE(f32, mat3, fmat3);
ALYSON_DEFINE_MATRIX_4x4_TYPE(f32, mat4, fmat4);
ALYSON_DEFINE_MATRIX_2x2_TYPE(f64, dmat2);
ALYSON_DEFINE_MATRIX_3x3_TYPE(f64, dmat3);
ALYSON_DEFINE_MATRIX_4x4_TYPE(f64, dmat4);
ALYSON_DEFINE_MATRIX_2x2_TYPE(i32, imat2);
ALYSON_DEFINE_MATRIX_3x3_TYPE(i32, imat3);
ALYSON_DEFINE_MATRIX_4x4_TYPE(i32, imat4);
ALYSON_DEFINE_MATRIX_2x2_TYPE(u32, umat2);
ALYSON_DEFINE_MATRIX_3x3_TYPE(u32, umat3);
ALYSON_DEFINE_MATRIX_4x4_TYPE(u32, umat4);
#ifdef __cplusplus
}
#endif
#endif //TYPES_H

View file

@ -1,20 +0,0 @@
#include <alargs.h>
#include <stdlib.h>
/*
* ALArgs
*/
ALArgs al_args_create(int argc, char** argv)
{
ALArgs args = malloc(sizeof(alyson_args_t));
args->argc = argc;
args->argv = argv;
return args;
}
void al_args_destroy(ALArgs args)
{
free(args);
}

View file

@ -1,8 +0,0 @@
#include <alyson.h>
#include <stdio.h>
#include <assert.h>
#include <string.h>
#include <stdlib.h>

View file

@ -1,76 +0,0 @@
#include <animation/sprite.h>
#include <stdlib.h>
#include "raylib.h"
#include "raymath.h"
#ifdef _DEBUG
#include <stdio.h>
#endif
SpriteAnimation CreateSpriteAnimation(Texture2D texture, Vector2 sprite_texture_dimentions, Vector2 sprite_size, float rotation, float scale, int frameCount, float speed)
{
SpriteAnimation spriteAnimation = malloc(sizeof(sprite_animation_t));
spriteAnimation->texture = texture;
spriteAnimation->dimentions = sprite_texture_dimentions;
spriteAnimation->sourceRect = (Rectangle){0, 0, sprite_size.x, sprite_size.y};
spriteAnimation->size = sprite_size;
spriteAnimation->rotation = rotation;
spriteAnimation->scale = scale;
spriteAnimation->frameCount = frameCount;
spriteAnimation->currentFrame = 0;
spriteAnimation->time = 0.f;
spriteAnimation->speed = speed;
return spriteAnimation;
}
void UpdateSpriteAnimation(SpriteAnimation self, float dt) {
self->time += dt;
if (self->time >= self->speed) {
self->time = 0.f;
self->currentFrame++;
}
if(self->currentFrame >= self->frameCount) {
self->currentFrame = 0;
}
self->sourceRect.x = (self->currentFrame * (int)self->size.x) % (int)self->dimentions.x;
self->sourceRect.y = (self->currentFrame * (int)self->size.y) % (int)self->dimentions.y;
}
void DrawSpriteAnimation(SpriteAnimation spriteAnimation, Vector2 position) {
position = Vector2Scale(position, .5f);
float yscale = (spriteAnimation->size.y * spriteAnimation->scale) / 2;
float xscale = (spriteAnimation->size.x * spriteAnimation->scale) / 2;
Rectangle destination = (Rectangle) {
xscale - position.x,
yscale - position.y,
xscale + position.x,
yscale + position.y
};
DrawTexturePro(
spriteAnimation->texture,
spriteAnimation->sourceRect,
destination,
(Vector2){0,0},
spriteAnimation->rotation,
WHITE
);
#ifdef _DEBUG
DrawCircleV(position, 5, DARKGREEN);
DrawRectangleLinesEx(destination, 2, BLACK);
#endif
}
void DestroySpriteAnimation(SpriteAnimation spriteAnimation)
{
free(spriteAnimation);
}

View file

@ -1,210 +0,0 @@
#include <resources/alpath.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
/*
* mangled path format:
* <type>://(<group>/)<name>:<path>
*
* e.g. res://test:/tests/test.png
* type: "res"
* group: ""
* name: "test"
* path: "/tests/test.png"
*
*
* demangled path format:
* ./<type_path>/<demangled_path>
*
* e.g.
* type_path: res -> ./assets/
* demangled_path: tests/test.png
* -> ./assets/tests/test.png
*
* type max length: 4
*
* smallest possible path: ://:a (5 chars)
*
* groups max length: 26
* groups:
* e.g. res://image/test:/tests/test.png
* type: "res"
* group: "image"
* name: "test"
* path: "/tests/test.png"
* -> ./assets/tests/test.png
*/
// Path
ALPath al_demangle_path(const char* path)
{
const ALPath res = malloc(sizeof(alyson_path_t));
res->type[0] = '\0';
res->group[0] = '\0';
res->name = NULL;
res->path = NULL;
const usx len = strlen(path);
usx back_ptr = 0;
if (len < 5)
{
fprintf(stderr, "[ALResource] Invalid path: \"%s\"; too short\n", path);
al_destroy_path(res);
return NULL;
}
// type
for (usx i = 0; i < sizeof(res->type); i++)
{
if (path[i] == ':')
{
res->type[i] = '\0';
back_ptr = i + 1;
break;
}
res->type[i] = path[i];
}
if (back_ptr == 0)
{
fprintf(stderr, "[ALResource] Invalid path: \"%s\"; type not found\n", path);
al_destroy_path(res);
return NULL;
}
if (path[back_ptr] != '/' || path[back_ptr+1] != '/') {
fprintf(stderr, "[ALResource] Invalid path: \"%s\"; type not followed by '://'\n", path);
al_destroy_path(res);
return NULL;
}
back_ptr += 2;
// group + name
for (usx i = back_ptr; i < len; i++)
{
if (path[i] == '/')
{
if (res->group[0] != '\0')
{
fprintf(stderr, "[ALResource] Invalid path: \"%s\"; group already set\n", path);
al_destroy_path(res);
return NULL;
}
if (back_ptr == i) break;
strncpy(res->group, (char*)path + back_ptr, i - back_ptr);
res->group[i-back_ptr] = '\0';
back_ptr = i + 1;
}
if (path[i] == ':')
{
res->name = malloc(sizeof(char) * (i - back_ptr + 1));
strncpy(res->name, (char*)path + back_ptr, i - back_ptr);
res->name[i - back_ptr] = '\0';
back_ptr = i + 1;
break;
}
}
// path
if (back_ptr == len)
{
fprintf(stderr, "[ALResource] Invalid path: \"%s\"; path not found\n", path);
al_destroy_path(res);
return NULL;
}
res->path = malloc(sizeof(char) * (len - back_ptr + 1));
strncpy(res->path, (char*)path + back_ptr, len - back_ptr);
res->path[len - back_ptr] = '\0';
return res;
}
char* al_mangle_path(const ALPath path)
{
char* str = malloc(sizeof(char) * (
strlen(path->type) +
strlen(path->group) +
strlen(path->name) +
strlen(path->path) +
5 ));
if (path->group[0] != '\0')
{
sprintf(str, "%s://%s/%s:%s", path->type, path->group, path->name, path->path);
}
else
{
sprintf(str, "%s://%s:%s", path->type, path->name, path->path);
}
return str;
}
ALPath al_create_path(const char* type, const char* path, const char* name, const char* group)
{
const ALPath res = malloc(sizeof(alyson_path_t));
res->type[0] = '\0';
res->name = NULL;
res->path = NULL;
if (type != NULL)
{
if (strlen(type) > 4)
{
fprintf(stderr, "[ALResource] Type name too long: %s\n", type);
return NULL;
}
strncpy(res->type, type, strlen(type));
res->type[4] = '\0';
}
if (path != NULL)
{
usx len = strlen(path);
res->path = malloc(sizeof(char) * (len + 1));
strncpy(res->path, path, len);
res->path[len] = '\0';
}
if (name != NULL)
{
res->name = malloc(sizeof(char) * (strlen(name) + 1));
strncpy(res->name, name, strlen(name));
res->name[strlen(name)] = '\0';
}
if (group != NULL)
{
if (strlen(group) > 26)
{
fprintf(stderr, "[ALResource] Group name too long: %s\n", group);
al_destroy_path(res);
return NULL;
}
strncpy(res->group, group, strlen(group));
res->group[strlen(group)] = '\0';
}
return res;
}
void al_destroy_path(ALPath path)
{
if (path->name != NULL)
{
free(path->name);
path->name = NULL;
}
if (path->path != NULL)
{
free(path->path);
path->path = NULL;
}
free(path);
path = NULL;
}

View file

@ -1,54 +0,0 @@
#include <resources/alresource.h>
#include <stdlib.h>
#include <string.h>
ALResource al_resource_create(ALPath path)
{
ALResource resource = malloc(sizeof(alyson_resource_t));
resource->id = 0;
memcpy(&resource->path, path, sizeof(alyson_path_t));
return resource;
}
ALResource al_resource_create_from_file(char* name, char* path)
{
ALResource resource = malloc(sizeof(alyson_resource_t));
resource->id = 0;
usx len = strlen(path);
resource->path.path = malloc(sizeof(char) * (len + 1));
memcpy(resource->path.path, path, sizeof(char) * len);
resource->path.path[len] = '\0';
memcpy(&resource->path.type, "res", 4);
resource->path.type[4] = '\0';
len = strlen(name);
resource->path.name = malloc(sizeof(char) * len + 1);
memcpy(resource->path.name, name, sizeof(char) * len);
resource->path.name[len] = '\0';
memcpy(&resource->path.group, "runtime", 7);
resource->path.group[7] = '\0';
return resource;
}
void al_destroy_resource(ALResource resource)
{
if (resource->path.name != NULL)
{
free(resource->path.name);
resource->path.name = NULL;
}
if (resource->path.path != NULL)
{
free(resource->path.path);
resource->path.path = NULL;
}
free(resource);
resource = NULL;
}

View file

@ -1,41 +0,0 @@
#include <rlyson.h>
#include "raylib.h"
#include "raymath.h"
void DrawTextFull(
const Font font,
const char* text,
Vector2 origin,
const text_orientation_t orientation,
const float rotation,
const float fontSize,
const float spacing,
const float lineSpacing,
const Color tint
)
{
const Vector2 textSize = MeasureTextEx(font, text, fontSize, spacing);
const Vector2 pos = origin;
origin = (Vector2){0,0};
switch (orientation) {
case TEXT_ORIENTATION_LEFT:
origin.x += textSize.x;
break;
case TEXT_ORIENTATION_RIGHT:
break;
case TEXT_ORIENTATION_CENTER:
origin.x += (textSize.x / 2);
break;
default:
break;
}
origin.y += textSize.y / 2;
SetTextLineSpacing((int)lineSpacing);
DrawTextPro(font, text, pos, origin, rotation, fontSize, spacing, tint);
}

View file

View file

@ -1,65 +0,0 @@
//
// Created by n0ffie on 10/02/2025.
//
#include <alyson.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
// gtests
#include <gtest/gtest.h>
bool test_path(const char* path)
{
if (path == NULL)
return false;
ALPath al_path = al_demangle_path(path);
if (al_path == NULL)
return false;
if (al_path->path == NULL)
return false;
printf("Path: %s\n", al_path->path);
char* string = al_mangle_path(al_path);
if (strcmp(string, path) != 0) {
printf("%s : %s\n", path, string);
return false;
}
printf("\t%s\n", string);
free(string);
al_destroy_path(al_path);
return true;
}
void pathEQ_test(const char* string) {
ALPath al_path = al_demangle_path(string);
char* s2 = al_mangle_path(al_path);
EXPECT_STREQ(string, s2);
free(s2);
al_destroy_path(al_path);
}
TEST(PathEqual, normal) {
pathEQ_test("res://normal:path/this.is");
}
TEST(PathEqual, group_long_type) {
pathEQ_test("gays://i/love:gays/iam.one/kind.of");
}
TEST(PathEqual, group_type) {
pathEQ_test("g/es://this/is:shit");
}
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 697 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 870 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

View file

@ -1,17 +0,0 @@
#ifndef COLYSIS_H
#define COLYSIS_H
#include <alyson.h>
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif

21
src/Enemy/Enemy.cpp Normal file
View file

@ -0,0 +1,21 @@
#include "Enemy.hpp"
Enemy::Enemy(sf::Vector2f position) : rectangle(sf::Vector2f{100, 100})
{
rectangle.move(position);
rectangle.setFillColor(sf::Color::Red);
}
void Enemy::look_at(sf::Vector2f target)
{
float dx = target.x - rectangle.getPosition().x;
float dy = target.y - rectangle.getPosition().y;
float angle = atan2(dy, dx);
rectangle.setRotation(sf::degrees(angle));
}
void Enemy::draw(sf::RenderTarget& target, const sf::RenderStates states) const
{
target.draw(rectangle, states);
}

13
src/Enemy/Enemy.hpp Normal file
View file

@ -0,0 +1,13 @@
#pragma once
#include <SFML/Graphics.hpp>
class Enemy : public sf::Drawable
{
sf::RectangleShape rectangle;
public:
explicit Enemy(sf::Vector2f position);
void look_at(sf::Vector2f target);
void draw(sf::RenderTarget& target, sf::RenderStates states) const override;
};

46
src/Game.cpp Normal file
View file

@ -0,0 +1,46 @@
#include "Game.hpp"
Game::Game(sf::RenderWindow& window) : window(window)
{
enemies.emplace_back(sf::Vector2f{100, 100});
enemies.emplace_back(sf::Vector2f{200, 200});
}
#include <iostream>
void Game::run()
{
std::cout << "Loading map... Version: " MAP_VERSION_STRING << std::endl;
auto start = std::chrono::system_clock::now();
auto err = map.load(ASSETS_PATH "/test.cymf");
auto end = std::chrono::system_clock::now();
auto milliseconds = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
std::cout << "Loading took: " << milliseconds << std::endl;
if (err.code != 0)
{
std::cout << err.message << std::endl;
return;
}
map.debug();
while (window.isOpen())
{
while (const auto event = window.pollEvent())
{
if (event->is<sf::Event::Closed>())
{
window.close();
}
}
// Render game
window.clear({0x20, 0x20, 0x20,0xff});
for (auto& enemy : enemies)
{
window.draw(enemy);
}
window.draw(map);
window.display();
}
}

20
src/Game.hpp Normal file
View file

@ -0,0 +1,20 @@
#pragma once
#include <SFML/Graphics.hpp>
#include "Enemy/Enemy.hpp"
#include "Map/Map.hpp"
#include <vector>
class Game
{
std::vector<Enemy> enemies;
Map map;
public:
explicit Game(sf::RenderWindow& window);
void run();
private:
sf::RenderWindow& window;
};

162
src/Map/Map.cpp Normal file
View file

@ -0,0 +1,162 @@
#include "Map.hpp"
#include <fstream>
Map::Map() {}
bool operator&(uint8_t lhs, MapFlags rhs)
{
return lhs & static_cast<uint8_t>(rhs);
}
bool operator==(int lhs, TileType rhs)
{
return lhs == static_cast<int>(rhs);
}
auto operator<=>(int lhs, TileType rhs)
{
return lhs <=> static_cast<int>(rhs);
}
#include <iostream>
MapError Map::load(const std::filesystem::path& path)
{
// opening the file and checking the magic number
std::ifstream file(path, std::ios::binary | std::ios::in);
char magic[4];
file.read(magic, 4);
if (std::memcmp(magic, "CYMF", 4) != 0) {
return {"Map: [Loading] Invalid magic number", 1};
}
// reading the version
uint8_t version[3];
file.read(reinterpret_cast<char*>(version), 3);
if (version[0] != MAP_VERSION_MAJOR || version[1] > MAP_VERSION_MINOR)
{
return {"Map: [Loading] Invalid version; Current: " MAP_VERSION_STRING, 1};
}
// reading the flags
uint8_t flags;
file.read(reinterpret_cast<char*>(&flags), 1);
// flag CustomTilemap -> load the tilemap
if (flags & MapFlags::CustomTilemap)
{
uint32_t filepath_buffer_size;
file.read(reinterpret_cast<char*>(&filepath_buffer_size), 4);
char* filepath_buffer = new char[filepath_buffer_size];
file.read(filepath_buffer, filepath_buffer_size);
tileAtlas.load(std::filesystem::path(filepath_buffer));
delete[] filepath_buffer;
}
// load the map info
uint32_t map_info[3];
file.read(reinterpret_cast<char*>(map_info), 12);
map_size = sf::Vector3<size_t>(static_cast<size_t>(map_info[0])*map_info[1], map_info[0], map_info[1]);
// load the tiles
tiles = new int[map_info[0] * map_info[1] + map_info[2] * (sizeof(MapSpecial)/4)];
for (int i = 0; i < map_info[0] * map_info[1] + map_info[2] * (sizeof(MapSpecial)/4); i++)
{
// read the special if needed
file.read(reinterpret_cast<char*>(&tiles[i]), 4);
if (tiles[i] == TileType::Special)
{
MapSpecial special{};
file.read(reinterpret_cast<char*>(&special), sizeof(MapSpecial));
// get position
uint32_t tile_x = i % map_info[0];
uint32_t tile_y = i / map_info[0];
specials.emplace_back(std::pair<sf::Vector2u, MapSpecial>({tile_x, tile_y}, special));
}
}
// load the player spawn
uint32_t t_player_spawn[2];
file.read(reinterpret_cast<char*>(t_player_spawn), 8);
player_spawn = sf::Vector2u{t_player_spawn[0], t_player_spawn[1]};
if (player_spawn.x >= map_size.y || player_spawn.y >= map_size.z)
{
return {"Map: [Loading] Player: Spawn out of bounds", 2};
}
int player_tile = tiles[player_spawn.x + player_spawn.y * map_size.x];
if (player_tile <= TileType::Special)
{
return {"Map: [Loading] Player: Spawn is not a valid tile (invalid: wall, special; valid: Floor)", 2};
}
// load all the enemy spawns
uint32_t number_enemy_spawns;
file.read(reinterpret_cast<char*>(&number_enemy_spawns), 4);
if (number_enemy_spawns > map_size.x)
{
return {"Map: [Loading] Enemies: Too many enemy spawns (More than tile in the map)", 3};
}
for (int i = 0; i < number_enemy_spawns; i++)
{
uint32_t t_enemy_spawn[2];
file.read(reinterpret_cast<char*>(t_enemy_spawn), 8);
if (t_enemy_spawn[0] >= map_size.x || t_enemy_spawn[1] >= map_size.y)
{
return {"Map: [Loading] Enemy: Spawn out of bounds", 4};
}
if (tiles[t_enemy_spawn[0] + t_enemy_spawn[1] * map_size.y] <= TileType::Special)
{
return {"Map: [Loading] Enemy: Spawn is not a valid tile (invalid: wall, special; valid: Floor)", 4};
}
if (t_enemy_spawn[0] == player_spawn.x && t_enemy_spawn[1] == player_spawn.y)
{
return {"Map: [Loading] Enemy: Spawn is the same as the player spawn", 4};
}
enemy_spawns.emplace_back(t_enemy_spawn[0], t_enemy_spawn[1]);
}
// Everything went well
return {"Map: [Loading] Success", 0};
}
sf::Vector2u Map::getSize() const
{
return {static_cast<uint32_t>(map_size.y), static_cast<uint32_t>(map_size.z)};
}
void Map::draw(sf::RenderTarget& target, const sf::RenderStates states) const
{
if (!tiles) return;
for (uint32_t x = 0; x < map_size.y; x++) {
for (uint32_t y = 0; y < map_size.z; ++y)
{
target.draw(tileAtlas, states);
}
}
}
#include <iostream>
void Map::debug()
{
std::cout << "Map Debug" << std::endl;
std::cout << "\tSize : " << map_size.x << ", " << map_size.y << ", " << map_size.z << std::endl;
std::cout << "\tTiles : 0x" << tiles << std::endl;
for (auto& special : specials)
{
std::cout << "\t\tSpecial : " << special.first.x << ", " << special.first.y << std::endl;
std::cout << "\t\t\tType : " << special.second.type << std::endl;
std::cout << "\t\t\tPortal : " << special.second.portal_end[0] << ", " << special.second.portal_end[1] << std::endl;
}
std::cout << "\t\tEnemy Spawns : " << enemy_spawns.size() << std::endl;
for (auto& spawn : enemy_spawns)
{
std::cout << "\t\t\tSpawn : " << spawn.x << ", " << spawn.y << std::endl;
}
std::cout << "\t\tPlayer Spawn : " << player_spawn.x << ", " << player_spawn.y << std::endl;
}

101
src/Map/Map.hpp Normal file
View file

@ -0,0 +1,101 @@

/******************************************************************
* ==============================================================
* Map File Format
* ==============================================================
*
* int8_t magic[4] = 'CYMF' (Colysis Map File) : 4 bytes
* uint8_t version[3] : major, minor, patch
*
* uint8_t flags
* if (flags):
* case MapFlags::CustomTilemap:
* uint32_t filepath_buffer_size
* char filepath_buffer[filepath_buffer_size]
* uint32_t tile_size[2] : width, height
* uint32_t tile_count[2] : width, height
*
* uint32_t map_size[3] : x, y, specials
* int32_t tiles[x * y + specials * (sizeof(MapSpecial)/4)] : tilemap data
* // a special tile has a type and its tilemap data
* if tiles[i] == Special:
* uint8_t type
* MapSpecial data
* else:
* uint8_t tile
*
* uint32_t player_spawn[2] : x, y
* uint32_t number_enemy_spawns
* uint32_t enemy_spawns[number_enemy_spawns][2] : x, y
*
*******************************************************************/
#pragma once
#include <SFML/Graphics.hpp>
#define STR(name) #name
#define STR_VALUE(name) STR(name)
#define MAP_VERSION_MAJOR 0
#define MAP_VERSION_MINOR 1
#define MAP_VERSION_PATCH 0
#define MAP_VERSION (MAP_VERSION_MAJOR << 16 | MAP_VERSION_MINOR << 8 | MAP_VERSION_PATCH)
#define MAP_VERSION_STRING STR_VALUE(MAP_VERSION_MAJOR) "." STR_VALUE(MAP_VERSION_MINOR) "." STR_VALUE(MAP_VERSION_PATCH)
struct MapSpecial
{
int type;
uint32_t portal_end[2];
};
enum class MapFlags : uint8_t
{
None = 0,
CustomTilemap = 1 << 0,
UNDEFINED = 1 << 1,
};
enum class TileType : int
{
Wall = -1,
Special = 0,
Other = 1,
};
struct MapError
{
const char* message;
int code;
};
#include "TileAtlas.hpp"
class Map : public sf::Drawable
{
static_assert(sizeof(MapSpecial)%4 == 0);
TileAtlas tileAtlas = TileAtlas::defaultAtlas();
sf::Vector3<size_t> map_size; // width * height, width, height
int *tiles = nullptr;
std::vector<std::pair<sf::Vector2u, MapSpecial>> specials;
std::vector<sf::Vector2u> enemy_spawns;
sf::Vector2u player_spawn;
public:
Map();
MapError load(const std::filesystem::path& path);
sf::Vector2u getSize() const;
void draw(sf::RenderTarget& target, sf::RenderStates states) const override;
void debug();
};

41
src/Map/TileAtlas.cpp Normal file
View file

@ -0,0 +1,41 @@
#include "TileAtlas.hpp"
TileAtlas TileAtlas::defaultAtlas()
{
TileAtlas atlas(sf::Vector2u{16, 16}, sf::Vector2u{16, 16}, ASSETS_PATH "/default_tilemap.png");
atlas.sprite.setTexture(atlas.texture);
atlas.sprite.setTextureRect(sf::IntRect({0, 0}, {static_cast<int>(atlas.tile_size.x), static_cast<int>(atlas.tile_size.y)}));
return atlas;
}
void TileAtlas::set(uint32_t x, uint32_t y)
{
if (x >= tile_count.x || y >= tile_count.y) return;
sprite.setTextureRect(sf::IntRect({static_cast<int>(x * tile_size.x), static_cast<int>(y * tile_size.y)}, sf::Vector2<int>(tile_size)));
}
TileAtlas::TileAtlas(const sf::Vector2u tile_size, const sf::Vector2u tile_count, const std::filesystem::path& path) :
tile_size(tile_size), tile_count(tile_count), sprite(texture) { load(path); }
TileAtlas::TileAtlas(sf::Vector2u tile_size, sf::Vector2u tile_count) : tile_size(tile_size), tile_count(tile_count), sprite(texture)
{
}
void TileAtlas::load(const std::filesystem::path& path)
{
if (!texture.loadFromFile(path))
{
throw std::runtime_error("TileAtlas: [Loading] Could not load tilemap -> Fatal");
}
sprite.setTexture(texture);
sprite.setTextureRect(sf::IntRect({0, 0}, {static_cast<int>(tile_size.x), static_cast<int>(tile_size.y)}));
}
void TileAtlas::draw(sf::RenderTarget& target, const sf::RenderStates states) const
{
if (texture.getSize().x == 0 || texture.getSize().y == 0)
{
return;
}
target.draw(sprite, states);
}

21
src/Map/TileAtlas.hpp Normal file
View file

@ -0,0 +1,21 @@
#pragma once
#include <SFML/Graphics.hpp>
class TileAtlas : public sf::Drawable
{
sf::Vector2u tile_size;
sf::Vector2u tile_count;
sf::Texture texture;
sf::Sprite sprite;
public:
explicit TileAtlas(sf::Vector2u tile_size, sf::Vector2u tile_count, const std::filesystem::path& path);
TileAtlas(sf::Vector2u tile_size, sf::Vector2u tile_count);
void load(const std::filesystem::path& path);
static TileAtlas defaultAtlas();
void set(uint32_t, uint32_t);
void draw(sf::RenderTarget& target, sf::RenderStates states) const override;
};

View file

@ -1,71 +0,0 @@
#include <colysis.h>
#define RAYLIB_BACKEND
#include <alyson.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <raylib.h>
#include <raymath.h>
#include <rlyson.h>
#include <animation/sprite.h>
int main(int argc, char** argv)
{
InitWindow(900, 600, "Colysis");
SetWindowState(FLAG_WINDOW_RESIZABLE | FLAG_WINDOW_MAXIMIZED);
Texture2D gery = LoadTexture(ASSETS_PATH "/karl-heinz_head.png");
SpriteAnimation geryanim = CreateSpriteAnimation(gery,
(Vector2){64*14,64}, (Vector2){64,64},
0.f, 4.f, 5, 0.15f);
Camera2D camera = { 0 };
camera.target = (Vector2){0,0};
camera.offset = (Vector2){GetScreenWidth()/2.f,GetScreenHeight()/2.f};
camera.rotation = 0.f;
camera.zoom = 1.f;
while (!WindowShouldClose()) {
ClearBackground((Color){ 0x00, 0x6d, 0xfb });
float dt = GetFrameTime();
camera.offset = (Vector2){GetScreenWidth()/2.f,GetScreenHeight()/2.f};
UpdateSpriteAnimation(geryanim, dt);
BeginDrawing();
{
BeginMode2D(camera);
{
DrawSpriteAnimation(geryanim, (Vector2){0,0});
}
EndMode2D();
{
DrawTextFull(GetFontDefault(), "Darling, I'm Home!",
(Vector2){20,20}, TEXT_ORIENTATION_RIGHT,
0, 24, 5, 5, RAYWHITE);
}
}
EndDrawing();
}
DestroySpriteAnimation(geryanim);
UnloadTexture(gery);
CloseWindow();
return 0;
}

15
src/main.cpp Normal file
View file

@ -0,0 +1,15 @@
#include <SFML/Graphics.hpp>
#include <SFML/Window.hpp>
#include "Game.hpp"
int main()
{
sf::RenderWindow window(sf::VideoMode({800, 450}), "Colysis", sf::Style::Close | sf::Style::Titlebar);
window.setMinimumSize(sf::Vector2u{800, 450});
Game game(window);
game.run();
return 0;
}