diff --git a/Makefile b/Makefile
index b5795df..0d1490c 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
-CXX = clang++
+CXX = clang
EMCC = emcc
-FLAGS = -Wall -std=c++17 $(shell pkg-config --libs --cflags raylib)
-SRC = scripts/main.cpp
+FLAGS = -std=c99 -g -Wall -Werror -Wpedantic -Wconversion -Wshadow -Wstrict-prototypes -fsanitize=address,undefined -O0 $(shell pkg-config --libs --cflags raylib)
+SRC = scripts/main.c
# ARM Build
ARM_TARGET = bin/game
diff --git a/assets/flower.aseprite b/assets/flower.aseprite
new file mode 100644
index 0000000..fc137e9
Binary files /dev/null and b/assets/flower.aseprite differ
diff --git a/assets/flower.png b/assets/flower.png
new file mode 100644
index 0000000..1944bc4
Binary files /dev/null and b/assets/flower.png differ
diff --git a/grass.aseprite b/assets/grass.aseprite
similarity index 100%
rename from grass.aseprite
rename to assets/grass.aseprite
diff --git a/bin/game b/bin/game
index c91affa..e384799 100755
Binary files a/bin/game and b/bin/game differ
diff --git a/bin/game.dSYM/Contents/Info.plist b/bin/game.dSYM/Contents/Info.plist
new file mode 100644
index 0000000..4e06fe6
--- /dev/null
+++ b/bin/game.dSYM/Contents/Info.plist
@@ -0,0 +1,20 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ English
+ CFBundleIdentifier
+ com.apple.xcode.dsym.game
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundlePackageType
+ dSYM
+ CFBundleSignature
+ ????
+ CFBundleShortVersionString
+ 1.0
+ CFBundleVersion
+ 1
+
+
diff --git a/bin/game.dSYM/Contents/Resources/DWARF/game b/bin/game.dSYM/Contents/Resources/DWARF/game
new file mode 100644
index 0000000..7a7edf6
Binary files /dev/null and b/bin/game.dSYM/Contents/Resources/DWARF/game differ
diff --git a/bin/game.dSYM/Contents/Resources/Relocations/aarch64/game.yml b/bin/game.dSYM/Contents/Resources/Relocations/aarch64/game.yml
new file mode 100644
index 0000000..0e63948
--- /dev/null
+++ b/bin/game.dSYM/Contents/Resources/Relocations/aarch64/game.yml
@@ -0,0 +1,5 @@
+---
+triple: 'arm64-apple-darwin'
+binary-path: 'bin/game'
+relocations: []
+...
diff --git a/scripts/main.c b/scripts/main.c
new file mode 100644
index 0000000..0b0f8e1
--- /dev/null
+++ b/scripts/main.c
@@ -0,0 +1,361 @@
+#include
+// WHITE, Color,
+// KEY_RIGHT, KEY_LEFT, KEY_DOWN, KEY_UP, IsKeyDown(),
+// InitWindow(), SetTargetFPS(), WindowShouldClose(), GetFrameTime(), CloseWindow()
+// Music, InitAudioDevice(), LoadMusicStream(), PlayMusicStream(), UpdateMusicStream(), UnloadMusicStream(), CloseAudioDevice(),
+// Texture2D, Rectangle, Vector2, LoadTexture(), DrawTexturePro(), UnloadTexture(),
+// BeginDrawing(), EndDrawing(), ClearBackground(),
+// Camera2D, BeginMode2D(), EndMode2D()
+#include // Vector2Length(), Vector2Normalize(), Vector2Add(), Vector2Scale(), Lerp()
+#include // rand(), srand()
+#include // time()
+#include // memcpy()
+#include
+
+// Structs
+
+typedef struct {
+ Vector2 *data;
+ size_t count;
+} Vector2Array;
+
+typedef struct {
+ Texture2D texture; // Texture for the sprite
+ Rectangle sourceRec; // Source rectangle for the texture
+ Rectangle destRec; // Destination rectangle for the texture
+ Vector2 frameSize; // Size of the frame in the texture
+ Vector2 origin; // Origin point for rotation and positioning
+ float rotation; // Rotation angle
+ Color color;
+} Sprite;
+
+typedef struct {
+ Sprite sprite;
+ Rectangle bounds;
+} TileSprite;
+
+typedef struct {
+ Sprite sprite; // Base sprite for rendering
+ int currentFrame; // Current animation frame
+ int maxFrame; // Total number of frames
+ int framesCounter; // Counter to control frame speed
+ int framesSpeed; // Speed of the animation (frames per second)
+ float animTimer;
+ bool isVertical; // Whether the animation frames are arranged vertically
+} AnimSprite;
+
+typedef struct {
+ Sprite sprite;
+ Vector2 position;
+} Object;
+
+typedef struct {
+ Object *data;
+ const Object *prototype;
+ size_t count;
+} ObjectArray;
+
+typedef struct {
+ AnimSprite animSprite;
+ Vector2 position;
+ Vector2 direction;
+ float velocity;
+} Entity;
+
+// Pure functions
+
+float GetRandomFloat(const float min, const float max){
+ return min + (float)rand() / (float)(RAND_MAX / (max - min));
+}
+
+Vector2 GetRandomVector(const Rectangle bounds){
+ return (Vector2){
+ GetRandomFloat(bounds.x, bounds.x + bounds.width),
+ GetRandomFloat(bounds.y, bounds.y + bounds.height)
+ };
+}
+
+ObjectArray CreateObjectArray(const Object *prototype, const size_t count) {
+ ObjectArray objects = {0};
+
+ if (count <= 0) {
+ printf("Objects size must be greater than 0.\n");
+ return objects;
+ }
+
+ objects.count = count;
+ objects.data = malloc(count * sizeof(Object));
+
+ if (!objects.data) {
+ printf("Memory allocation of objects failed.\n");
+ return objects;
+ }
+
+ objects.prototype = prototype;
+
+ for (int i = 0; i < count; i++) {
+ objects.data[i].position = prototype->position;
+ objects.data[i].sprite = prototype->sprite;
+ }
+ return objects;
+}
+
+// Mutator Functions
+
+void GetDirectionFromInput(Vector2 *direction){
+ *direction = (Vector2){0.0f, 0.0f};
+ if (IsKeyDown(KEY_RIGHT) || IsKeyDown(KEY_D)){ direction->x += 1.0f; }
+ if (IsKeyDown(KEY_LEFT) || IsKeyDown(KEY_A)){ direction->x -= 1.0f; }
+ if (IsKeyDown(KEY_DOWN) || IsKeyDown(KEY_S)){ direction->y += 1.0f; }
+ if (IsKeyDown(KEY_UP) || IsKeyDown(KEY_W)){ direction->y -= 1.0f; }
+ if (Vector2Length(*direction) > 0.0f) { *direction = Vector2Normalize(*direction); }
+}
+
+void SetPositionOnDirectionAndVelocity(const Vector2 *direction, const float *velocity, Vector2 *position) {
+ *position = Vector2Add(*position, Vector2Scale(*direction, *velocity * GetFrameTime()));
+}
+
+void SetDestRecOnPosition(const Vector2 *position, Sprite *sprite){
+ Rectangle newDestRec = {
+ position->x,
+ position->y,
+ sprite->frameSize.x,
+ sprite->frameSize.y
+ };
+ sprite->destRec = newDestRec;
+}
+
+void SetAnimSpriteOnFrameTime(AnimSprite *animSprite) {
+ animSprite->animTimer += GetFrameTime();
+ float frameTime = 1.0f / animSprite->framesSpeed;
+
+ if (animSprite->animTimer < frameTime) {
+ return;
+ }
+
+ animSprite->animTimer -= frameTime;
+ animSprite->currentFrame++;
+
+ if (animSprite->currentFrame >= animSprite->maxFrame) {
+ animSprite->currentFrame = 0;
+ }
+
+ if (animSprite->isVertical) {
+ animSprite->sprite.sourceRec.y = animSprite->currentFrame * animSprite->sprite.frameSize.y;
+ } else {
+ animSprite->sprite.sourceRec.x = animSprite->currentFrame * animSprite->sprite.frameSize.x;
+ }
+}
+
+void SetRotationOnDirection(const Vector2 *direction, float *rotationDegree){
+ if(Vector2Length(*direction) <= 0.0f){
+ return;
+ }
+ float targetRotationDegree = (float)atan2(direction->y, direction->x) * (180.0f / PI) + 90.0f;
+ *rotationDegree = Lerp(*rotationDegree, targetRotationDegree, 0.1f);
+}
+
+void SetPositionForObjectArray(ObjectArray *objects, const Vector2Array *positions) {
+ if (positions->count != objects->count) {
+ printf("Warning: Position array size (%zu) does not match ObjectArray size (%zu)\n", positions->count, objects->count);
+ return;
+ }
+
+ for (size_t i = 0; i < objects->count; i++) {
+ objects->data[i].position = positions->data[i];
+ objects->data[i].sprite.destRec.x = positions->data[i].x;
+ objects->data[i].sprite.destRec.y = positions->data[i].y;
+ }
+}
+
+void SetRandomPositionForObjectArray(ObjectArray *objects, const Rectangle bounds){
+ srand((unsigned int)time(NULL));
+ for (int i = 0; i < objects->count; i++) {
+ Vector2 position = GetRandomVector(bounds);
+ objects->data[i].position = position;
+ objects->data[i].sprite.destRec.x = position.x;
+ objects->data[i].sprite.destRec.y = position.y;
+ }
+}
+
+void UpdateEntity(Entity *entity) {
+ GetDirectionFromInput(&entity->direction);
+ SetRotationOnDirection(&entity->direction, &entity->animSprite.sprite.rotation);
+ SetPositionOnDirectionAndVelocity(&entity->direction, &entity->velocity, &entity->position);
+ SetDestRecOnPosition(&entity->position, &entity->animSprite.sprite);
+ SetAnimSpriteOnFrameTime(&entity->animSprite);
+}
+
+void UpdateTileSprite(TileSprite *tileSprite, const Camera2D *camera){
+ tileSprite->bounds.x = (int)((camera->target.x - (GetScreenWidth() / 2.0f / camera->zoom)) / tileSprite->sprite.frameSize.x) - 1;
+ tileSprite->bounds.width = (int)((camera->target.x + (GetScreenWidth() / 2.0f / camera->zoom)) / tileSprite->sprite.frameSize.x) + 1;
+ tileSprite->bounds.y = (int)((camera->target.y - (GetScreenHeight() / 2.0f / camera->zoom)) / tileSprite->sprite.frameSize.y) - 1;
+ tileSprite->bounds.height = (int)((camera->target.y + (GetScreenHeight() / 2.0f / camera->zoom)) / tileSprite->sprite.frameSize.y) + 1;
+}
+
+void UpdateCamera2D(Camera2D *camera, const Entity *player, const float smoothness){
+ camera->target = Vector2Lerp(camera->target, player->position, smoothness * GetFrameTime());
+}
+
+void SwapAndPopObjectsArrayOnCollision(ObjectArray *objects, const Rectangle rec){
+ for (int i = 0; i < objects->count; i++){
+
+ if (CheckCollisionRecs(rec, objects->data[i].sprite.destRec)){
+ if (objects->count == 1) {
+ objects->count = 0;
+ break;
+ }
+ objects->data[i] = objects->data[objects->count - 1];
+ objects->count--;
+ i--;
+ }
+ }
+}
+
+void RenderSprite(const Sprite *sprite){
+ DrawTexturePro(
+ sprite->texture,
+ sprite->sourceRec,
+ sprite->destRec,
+ sprite->origin,
+ sprite->rotation,
+ sprite->color
+ );
+}
+
+void RenderTileSprite(TileSprite *tileSprite){
+ for (float y = tileSprite->bounds.y; y <= tileSprite->bounds.height; y++)
+ {
+ for (float x = tileSprite->bounds.x; x <= tileSprite->bounds.width; x++)
+ {
+ Vector2 tilePosition = {x * tileSprite->sprite.frameSize.x, y * tileSprite->sprite.frameSize.y};
+ SetDestRecOnPosition(&tilePosition, &tileSprite->sprite);
+ RenderSprite(&tileSprite->sprite);
+ }
+ }
+}
+
+void RenderObjectArray(const ObjectArray *objects){
+ for (int i = 0; i < objects->count; i++){
+ RenderSprite(&objects->data[i].sprite);
+ }
+}
+
+// Main
+
+int main(void)
+{
+ // Load
+ // SetConfigFlags(FLAG_VSYNC_HINT);
+ InitWindow(1280, 720, "Lazy Bee");
+ InitAudioDevice();
+ Music music = LoadMusicStream("assets/beez.mp3");
+ PlayMusicStream(music);
+ TileSprite floor = {
+ .sprite = {
+ .texture = LoadTexture("assets/grass.png"),
+ .frameSize = {16.0f,16.0f},
+ .sourceRec = { 0.0f, 0.0f, 16.0f, 16.0f},
+ .destRec = {0.0f, 0.0f, 16.0f, 16.0f},
+ .origin = {8.0f, 8.0f},
+ .rotation = 0.0f,
+ .color = WHITE
+ },
+ .bounds = {0.0f,0.0f,0.0f,0.0f}
+ };
+ Object hive = {
+ .sprite = {
+ .texture = LoadTexture("assets/hive.png"),
+ .frameSize = {32.0f,32.0f},
+ .sourceRec = {0.0f, 0.0f, 32.0f, 32.0f},
+ .destRec = {0.0f, 0.0f, 32.0f, 32.0f},
+ .origin = {16.0f, 16.0f},
+ .rotation = 0.0f,
+ .color = WHITE
+ },
+ .position = (Vector2){0.0f,0.0f}
+ };
+ Texture2D flower = LoadTexture("assets/flower.png");
+ ObjectArray flowers = CreateObjectArray(&(Object){
+ .sprite = {
+ .texture = flower,
+ .frameSize = {16.0f, 16.0f},
+ .sourceRec = {0.0f, 0.0f, 16.0f, 16.0f},
+ .destRec = {0.0f, 0.0f, 16.0f, 16.0f},
+ .origin = {8.0f, 8.0f},
+ .rotation = 45.0f,
+ .color = WHITE
+ },
+ .position = {0.0f, 0.0f}
+ }, 10);
+ if (!flowers.data) {
+ printf("Memory allocation failed.\n");
+ exit(1);
+ }
+ Rectangle flowerField = {-50.0f, -50.0f, 100.0f, 100.0f};
+ SetRandomPositionForObjectArray(&flowers, flowerField);
+ Entity player = {
+ .animSprite = {
+ .sprite = {
+ .texture = LoadTexture("assets/character_bee.png"),
+ .frameSize = {16.0f, 16.0f},
+ .sourceRec = {0.0f, 0.0f, 16.0f, 16.0f},
+ .destRec = {0.0f, 0.0f, 16.0f, 16.0f},
+ .origin = {8.0f, 8.0f},
+ .rotation = 0.0f,
+ .color = WHITE
+ },
+ .currentFrame = 0,
+ .maxFrame = 4,
+ .framesCounter = 0,
+ .framesSpeed = 10,
+ .isVertical = true,
+ .animTimer = 0.0f
+ },
+ .position = hive.position,
+ .direction = (Vector2){0.0f,0.0f},
+ .velocity = 50.0f
+ };
+ Camera2D camera = {
+ .offset = (Vector2){GetScreenWidth() / 2.0f, GetScreenHeight() / 2.0f},
+ .target = player.position,
+ .rotation = 0.0f,
+ .zoom = 10.0f
+ };
+ float followSmoothness = 5.0f;
+ Vector2 mousePoint = { 0.0f, 0.0f};
+
+ // Update & Render
+ while (!WindowShouldClose())
+ {
+ // Update
+ mousePoint = GetMousePosition();
+ UpdateMusicStream(music);
+ UpdateTileSprite(&floor, &camera);
+ UpdateEntity(&player);
+ UpdateCamera2D(&camera, &player, followSmoothness);
+ SwapAndPopObjectsArrayOnCollision(&flowers, player.animSprite.sprite.destRec);
+ // Render
+ BeginDrawing();
+ ClearBackground(BLACK);
+ BeginMode2D(camera);
+ RenderTileSprite(&floor);
+ RenderSprite(&hive.sprite);
+ RenderObjectArray(&flowers);
+ RenderSprite(&player.animSprite.sprite);
+ EndMode2D();
+ DrawFPS(10,10);
+ EndDrawing();
+ }
+ // Unload
+ UnloadTexture(floor.sprite.texture);
+ UnloadTexture(hive.sprite.texture);
+ UnloadTexture(flower);
+ UnloadTexture(player.animSprite.sprite.texture);
+ UnloadMusicStream(music);
+ free(flowers.data);
+ // Close
+ CloseAudioDevice();
+ CloseWindow();
+ return 0;
+}
diff --git a/scripts/main.cpp b/scripts/main.cpp
deleted file mode 100644
index 3a84c63..0000000
--- a/scripts/main.cpp
+++ /dev/null
@@ -1,136 +0,0 @@
-#include
-#include
-
-Vector2 getDirection(){
- Vector2 direction = {0.0f, 0.0f};
- if (IsKeyDown(KEY_RIGHT) || IsKeyDown(KEY_D)){ direction = Vector2Add(direction, {1.0f , 0.0f}); }
- if (IsKeyDown(KEY_LEFT) || IsKeyDown(KEY_A)){ direction = Vector2Add(direction, {-1.0f, 0.0f}); }
- if (IsKeyDown(KEY_DOWN) || IsKeyDown(KEY_S)){ direction = Vector2Add(direction, {0.0f, 1.0f}); }
- if (IsKeyDown(KEY_UP) || IsKeyDown(KEY_W)){ direction = Vector2Add(direction, {0.0f, -1.0f}); }
- if (Vector2Length(direction) > 0.0f) { direction = Vector2Normalize(direction); }
- return direction;
-}
-
-int main()
-{
- int screenWidth = 1280;
- int screenHeight = 720;
- InitWindow(screenWidth, screenHeight, "Lazy Bee");
- SetTargetFPS(60);
-
- // Init Audio
- InitAudioDevice();
- Music music = LoadMusicStream("assets/beez.mp3");
- PlayMusicStream(music);
-
- // Init Tiles
- Texture2D tileTexture = LoadTexture("assets/grass.png");
- Vector2 tileFrameSize = {16.0f, 16.0f};
- Rectangle tileSourceRec = { tileFrameSize.x, tileFrameSize.y, tileFrameSize.x, tileFrameSize.y};
-
- // Init Character
- Texture2D characterTexture = LoadTexture("assets/character_bee.png");
- Vector2 charFrameSize = {16.0f, 16.0f};
- Rectangle charSourceRec = {0.0f, 0.0f, charFrameSize.x, charFrameSize.y};
- Vector2 charPosition = {0.0f, 0.0f};
- Vector2 charOrigin = {charFrameSize.x / 2.0f, charFrameSize.y / 2.0f};
- float charRotation = 0.0f;
-
- // Init Character Animation
- int currentFrame = 0;
- int framesCounter = 0;
- int framesSpeed = 10;
-
- // Init Camera
- Camera2D camera = { 0 };
- camera.target = charPosition;
- camera.offset = (Vector2){screenWidth / 2.0f, screenHeight / 2.0f};
- camera.rotation = 0.0f;
- camera.zoom = 10.0f;
-
- // Init hive
- Texture2D hiveTexture = LoadTexture("assets/hive.png");
- Vector2 hiveFrameSize = {32.0f,32.0f};
- Rectangle hiveSourceRec = {0.0f, 0.0f, hiveFrameSize.x, hiveFrameSize.y};
- Vector2 hivePosition = {0.0f,0.0f};
- Rectangle hiveDestRec = {hivePosition.x, hivePosition.y, hiveFrameSize.x, hiveFrameSize.y};
- Vector2 hiveOrigin = {hiveFrameSize.x / 2.0f, hiveFrameSize.y / 2.0f};
-
- while (!WindowShouldClose())
- {
- UpdateMusicStream(music);
-
-
- // Update Char Movement
- Vector2 direction = getDirection();
- Vector2 targetPosition = Vector2Add(charPosition, Vector2Scale(direction, 100.0f * GetFrameTime()));
- charPosition = {Lerp(charPosition.x, targetPosition.x, 0.3f),Lerp(charPosition.y, targetPosition.y, 0.3f)};
-
- // Update Char Rotation
- if (Vector2Length(direction) > 0.0f) {
- float targetRotation = atan2(direction.y, direction.x) * (180.0f / PI) + 90.0f;
- charRotation = Lerp(charRotation, targetRotation, 0.1f);
- }
-
- // Update Char Animation
- framesCounter++;
-
- if (framesCounter >= (60 / framesSpeed))
- {
- framesCounter = 0;
- currentFrame++;
- if (currentFrame >= 4)
- currentFrame = 0;
- charSourceRec.y = currentFrame * charFrameSize.y;
- }
-
- // Update Char Camera
- camera.target = charPosition;
-
- // Render
- BeginDrawing();
- ClearBackground(BLACK);
- BeginMode2D(camera);
-
- // Render Tiles
- float left = camera.target.x - (screenWidth / 2.0f / camera.zoom);
- float right = camera.target.x + (screenWidth / 2.0f / camera.zoom);
- float top = camera.target.y - (screenHeight / 2.0f / camera.zoom);
- float bottom = camera.target.y + (screenHeight / 2.0f / camera.zoom);
-
- int startX = (int)(left / tileFrameSize.x) - 1;
- int endX = (int)(right / tileFrameSize.x) + 1;
- int startY = (int)(top / tileFrameSize.y) - 1;
- int endY = (int)(bottom / tileFrameSize.y) + 1;
-
- for (int y = startY; y <= endY; y++)
- {
- for (int x = startX; x <= endX; x++)
- {
- Vector2 tilePosition = {x * tileFrameSize.x, y * tileFrameSize.y};
- Rectangle tileDestRec = {tilePosition.x, tilePosition.y, tileFrameSize.x, tileFrameSize.y};
- DrawTexturePro(tileTexture, tileSourceRec, tileDestRec, (Vector2){0.0f, 0.0f}, 0.0f, WHITE);
- }
- }
-
- // Render Hive
- DrawTexturePro(hiveTexture, hiveSourceRec, hiveDestRec, hiveOrigin, 0.0f, WHITE);
-
- // Render Character
- Rectangle charDestRec = {charPosition.x, charPosition.y, charFrameSize.x, charFrameSize.y};
- DrawTexturePro(characterTexture, charSourceRec, charDestRec, charOrigin, charRotation, WHITE);
-
- EndMode2D();
- EndDrawing();
- }
-
- // Unload Character
- UnloadTexture(characterTexture);
- UnloadTexture(tileTexture);
- UnloadMusicStream(music);
-
- CloseAudioDevice();
- CloseWindow();
-
- return 0;
-}
\ No newline at end of file
diff --git a/scripts/main_crossplattform.cpp b/scripts/main_crossplattform.cpp
new file mode 100644
index 0000000..20d73ac
--- /dev/null
+++ b/scripts/main_crossplattform.cpp
@@ -0,0 +1,26 @@
+#include "raylib.h"
+#include "Game.h"
+
+#ifdef PLATFORM_WEB
+ #include
+#endif
+
+Game game;
+
+void UpdateDrawFrame() {
+ game.update();
+ game.render();
+}
+
+int main() {
+ InitWindow(1280, 720, "Lazy Bee");
+ SetTargetFPS(60);
+ game.init();
+#ifdef PLATFORM_WEB
+ emscripten_set_main_loop(UpdateDrawFrame, 0, 1);
+#else
+ while (!WindowShouldClose()) { game.update(); game.render(); }
+#endif
+ game.close();
+ return 0;
+}
diff --git a/scripts/object.c b/scripts/object.c
new file mode 100644
index 0000000..e69de29