summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoredGuy <osome3717@gmail.com>2025-07-29 11:50:57 +0300
committerBoredGuy <osome3717@gmail.com>2025-07-29 11:50:57 +0300
commit815aec62f8ae3a403e913559d5fe6138c8825007 (patch)
tree3041d4b8a843c05a4da02e66d5e2f63e1e713b72
parent9e1627c229d8d094c7b55751d82db9d3579a16e1 (diff)
Added background entity and asset system
-rw-r--r--CMakeLists.txt6
-rw-r--r--include/assets.h6
-rw-r--r--include/background.h7
-rw-r--r--include/game.h20
-rw-r--r--src/assets.c67
-rw-r--r--src/background.c30
-rw-r--r--src/game.c71
-rw-r--r--src/main.c7
-rw-r--r--src/player.c6
9 files changed, 200 insertions, 20 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index a1560e9..c8989c5 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -12,10 +12,14 @@ add_executable(game
"include/constants.h"
"include/physics.h"
"include/player.h"
+ "include/assets.h"
+ "include/background.h"
"src/game.c"
"src/main.c"
"src/player.c"
+ "src/assets.c"
+ "src/background.c"
)
target_include_directories(game PRIVATE "include")
@@ -31,4 +35,4 @@ endif()
if (MSVC)
target_link_libraries(game winmm)
-endif() \ No newline at end of file
+endif()
diff --git a/include/assets.h b/include/assets.h
new file mode 100644
index 0000000..e2d76b7
--- /dev/null
+++ b/include/assets.h
@@ -0,0 +1,6 @@
+#pragma once
+
+#include <raylib.h>
+
+void LoadAssets();
+Texture2D GetTexture(const char* name);
diff --git a/include/background.h b/include/background.h
new file mode 100644
index 0000000..104db7c
--- /dev/null
+++ b/include/background.h
@@ -0,0 +1,7 @@
+#pragma once
+
+#include "game.h"
+#include "assets.h"
+
+void AddBackground(const char* backgroundTexture);
+void UpdateBackground(Entity* background, float deltaTime);
diff --git a/include/game.h b/include/game.h
index 64da8e7..1039ad5 100644
--- a/include/game.h
+++ b/include/game.h
@@ -1,6 +1,7 @@
#pragma once
#include <raylib.h>
+#include <stdbool.h>
#include <stdint.h>
#include "constants.h"
@@ -11,9 +12,15 @@
typedef enum EntityType {
Player_Entity,
- Wall_Entity
+ Wall_Entity,
+ Background_Entity
} EntityType;
+typedef enum DrawLayer {
+ Background_Layer = 0,
+ Foreground_Layer = 1
+} DrawLayer;
+
typedef struct Entity {
int id;
EntityType type;
@@ -29,6 +36,11 @@ typedef struct Entity {
int numHurtBoxes;
Rectangle hurtBoxes[MAX_AREA_COUNT];
+ //Graphics Information
+ Texture2D texture;
+ DrawLayer drawLayer;
+ Rectangle destRect; //Relative to the players position
+
#ifdef BEATEMUP_DEBUG
//Debug information
Color physicsColliderColor;
@@ -42,6 +54,10 @@ typedef struct Game {
Texture2D background;
float backgroundPosition;
+ #ifdef BEATEMUP_DEBUG
+ //Debug information
+ bool enableDebugOverlay;
+ #endif
} Game;
void AddEntity(Entity* e);
@@ -49,4 +65,4 @@ void AddWall(float xpos, float ypos, float width, float height);
void InitGame();
void UpdateGame(float deltaTime);
-void DrawGame(); \ No newline at end of file
+void DrawGame();
diff --git a/src/assets.c b/src/assets.c
new file mode 100644
index 0000000..8edfde6
--- /dev/null
+++ b/src/assets.c
@@ -0,0 +1,67 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+#include "assets.h"
+
+typedef enum AssetType {
+ Texture_Asset
+} AssetType;
+
+typedef struct Asset {
+ AssetType type;
+ const char* name;
+ const char* filePath;
+
+ Texture2D texture;
+} Asset;
+
+Asset assets[] = {
+ {
+ .type = Texture_Asset,
+ .name = "bar-background",
+ .filePath = "assets/art/backgrounds/bar-background.png"
+ },
+ {
+ .type = Texture_Asset,
+ .name = "rails",
+ .filePath = "assets/art/backgrounds/rails.png"
+ },
+};
+
+#define ASSET_COUNT (sizeof(assets) / sizeof(Asset))
+
+void LoadAssets() {
+
+ for (size_t i = 0; i < ASSET_COUNT; i++) {
+ Asset* c = &assets[i];
+
+ switch (c->type) {
+ case Texture_Asset:
+ c->texture = LoadTexture(c->filePath);
+ break;
+ }
+ }
+}
+
+Asset* GetMatchingAssetWithType(const char* targetName, AssetType targetType) {
+ for (size_t i = 0; i < ASSET_COUNT; i++) {
+ Asset* c = &assets[i];
+
+ if (strcmp(targetName, c->name) == 0 && c->type == targetType)
+ return c;
+ }
+
+ return NULL;
+}
+
+Texture2D GetTexture(const char* name) {
+ Asset* textureAsset = GetMatchingAssetWithType(name, Texture_Asset);
+
+ if (textureAsset == NULL) {
+ fprintf(stderr, "Failed to load texture with name: %s, exitting!\n", name);
+ exit(EXIT_FAILURE);
+ }
+
+ return textureAsset->texture;
+}
diff --git a/src/background.c b/src/background.c
new file mode 100644
index 0000000..39e3c1e
--- /dev/null
+++ b/src/background.c
@@ -0,0 +1,30 @@
+#include "background.h"
+#include "constants.h"
+#include <raymath.h>
+
+void AddBackground(const char* backgroundTextureName) {
+ Entity e = {0};
+ e.type = Background_Entity;
+
+ e.flags |= ENTITY_VISIBLE;
+ e.drawLayer = Background_Layer;
+
+ e.position = (Vector2) {0.0f, 0.0f};
+ Texture2D backgroundTexture = GetTexture(backgroundTextureName);
+
+ const float backgroundSizeScale = (float)WINDOW_HEIGHT / backgroundTexture.height;
+ Vector2 backgroundBounds =
+ Vector2Scale((Vector2) {backgroundTexture.width, backgroundTexture.height}, backgroundSizeScale);
+
+ e.destRect = (Rectangle) {
+ .width = backgroundBounds.x,
+ .height = backgroundBounds.y
+ };
+ e.texture = backgroundTexture;
+
+ AddEntity(&e);
+}
+
+void UpdateBackground(Entity* background, float deltaTime) {
+ background->position.x -= 600 * deltaTime;
+}
diff --git a/src/game.c b/src/game.c
index 104effa..37eefe1 100644
--- a/src/game.c
+++ b/src/game.c
@@ -1,8 +1,11 @@
#include <raylib.h>
#include <string.h>
#include "game.h"
+#include "assets.h"
+#include "stdio.h"
#include "player.h"
+#include "background.h"
Game game;
@@ -14,8 +17,10 @@ static inline bool PhysicsEnabled(const Entity* e) {
return EntityAllocated(e) && (e->flags & ENTITY_PHYSICS_ACTIVE);
}
-static inline bool ShouldDrawEntity(const Entity* e) {
- return EntityAllocated(e) && (e->flags & ENTITY_VISIBLE);
+static inline bool ShouldDrawEntity(const Entity* e, DrawLayer layerDrawing) {
+ return EntityAllocated(e)
+ && (e->flags & ENTITY_VISIBLE)
+ && (layerDrawing == e->drawLayer);
}
static inline bool SameEntity(const Entity* a, const Entity* b) {
@@ -26,7 +31,7 @@ static inline bool IsColliding(const Rectangle* a, const Rectangle* b) {
bool collisionX = (a->x <= b->x && a->x + a->width > b->x)
|| (b->x <= a->x && b->x + b->width > a->x);
- bool collisionY = (a->y <= b->y && a->y + a->height > b->height)
+ bool collisionY = (a->y <= b->y && a->y + a->height > b->y)
|| (b->y <= a->y && b->y + b->height > a->y);
return collisionX && collisionY;
@@ -40,6 +45,15 @@ static inline Rectangle GetPhysicsColliderGlobal(const Entity* e) {
return physicsColliderGlobal;
}
+static inline Rectangle GetDrawDestinationRectGlobal(const Entity* e) {
+ Rectangle destRectGlobal = e->destRect;
+
+ destRectGlobal.x += e->position.x;
+ destRectGlobal.y += e->position.y;
+
+ return destRectGlobal;
+}
+
void MoveAndSlide(Entity* e, float deltaTime) {
Vector2 velocity = e->velocity;
Rectangle physicsCollider = GetPhysicsColliderGlobal(e);
@@ -97,6 +111,7 @@ void AddEntity(Entity* e) {
void InitGame() {
game.paused = false;
+ LoadAssets();
memset(game.entities, 0, sizeof(game.entities));
}
@@ -106,6 +121,10 @@ void UpdateEntity(Entity* e, float deltaTime) {
case Player_Entity:
UpdatePlayer(e, deltaTime);
break;
+
+ case Background_Entity:
+ UpdateBackground(e, deltaTime);
+ break;
default:
break;
@@ -113,7 +132,11 @@ void UpdateEntity(Entity* e, float deltaTime) {
}
void UpdateGame(float deltaTime) {
- (void)deltaTime;
+ #ifdef BEATEMUP_DEBUG
+ if (IsKeyPressed(KEY_D) && IsKeyDown(KEY_ENTER)) {
+ game.enableDebugOverlay = !game.enableDebugOverlay;
+ }
+ #endif
for (int i = 0; i < MAX_ENTITY_COUNT; i++) {
Entity* e = &game.entities[i];
@@ -125,34 +148,56 @@ void UpdateGame(float deltaTime) {
#ifdef BEATEMUP_DEBUG
void DebugHighlights(const Entity* e) {
+ if (!PhysicsEnabled(e))
+ return;
+
Rectangle dstRect = GetPhysicsColliderGlobal(e);
DrawRectangle(dstRect.x, dstRect.y, dstRect.width, dstRect.height, e->physicsColliderColor);
}
#endif
+void DefaultDrawEntity(const Entity* e) {
+ Rectangle srcRect = {0, 0, e->texture.width, e->texture.height};
+ Vector2 origin = {0.0f, 0.0f};
+ float rotation = 0.0f;
+ Rectangle destRect = GetDrawDestinationRectGlobal(e);
+
+ DrawTexturePro(e->texture, srcRect, destRect, origin, rotation, WHITE);
+}
+
void DrawEntity(const Entity* e) {
+ switch (e->type) {
+
+ default:
+ DefaultDrawEntity(e);
+ }
}
void DrawGame() {
BeginDrawing();
ClearBackground(RAYWHITE);
- for (int i = 0; i < MAX_ENTITY_COUNT; i++) {
- Entity* e = &game.entities[i];
+ for (DrawLayer layer = Background_Layer; layer <= Foreground_Layer; layer++) {
+ for (int j = 0; j < MAX_ENTITY_COUNT; j++) {
+ Entity* currentEntity = &game.entities[j];
- #ifdef BEATEMUP_DEBUG
- DebugHighlights(e);
- #endif
+ if (ShouldDrawEntity(currentEntity, layer))
+ DrawEntity(currentEntity);
+ }
+ }
- if (ShouldDrawEntity(e))
- DrawEntity(e);
+ #ifdef BEATEMUP_DEBUG
+ for (int i = 0; i < MAX_ENTITY_COUNT; i++) {
+ if (game.enableDebugOverlay)
+ DebugHighlights(&game.entities[i]);
}
+ #endif
EndDrawing();
}
void AddWall(float xpos, float ypos, float width, float height) {
- Entity wall;
+ Entity wall = {0};
wall.type = Wall_Entity;
wall.flags |= ENTITY_PHYSICS_ACTIVE;
@@ -165,4 +210,4 @@ void AddWall(float xpos, float ypos, float width, float height) {
#endif
AddEntity(&wall);
-} \ No newline at end of file
+}
diff --git a/src/main.c b/src/main.c
index 1bfbb61..661c615 100644
--- a/src/main.c
+++ b/src/main.c
@@ -3,6 +3,7 @@
#include "constants.h"
#include "game.h"
#include "player.h"
+#include "background.h"
int main() {
SetConfigFlags(FLAG_VSYNC_HINT); //Always better than fixed FPS imo
@@ -11,7 +12,11 @@ int main() {
InitGame();
AddPlayer(0.0, 0.0);
+
AddWall(200, 100, 10000, 100);
+ AddWall(200, 400, 10000, 100);
+
+ AddBackground("bar-background");
while(!WindowShouldClose()) {
UpdateGame(GetFrameTime());
@@ -21,4 +26,4 @@ int main() {
CloseWindow();
return 0;
-} \ No newline at end of file
+}
diff --git a/src/player.c b/src/player.c
index d65b873..c8e3f7d 100644
--- a/src/player.c
+++ b/src/player.c
@@ -27,11 +27,11 @@ void UpdatePlayer(Entity* player, float deltaTime) {
}
void AddPlayer(float xpos, float ypos) {
- Entity player;
+ Entity player = {0};
player.type = Player_Entity;
player.position = (Vector2) {xpos, ypos};
- player.flags |= (ENTITY_PHYSICS_ACTIVE | ENTITY_VISIBLE);
+ player.flags |= (ENTITY_PHYSICS_ACTIVE);
player.physicsCollider = (Rectangle) {0, 0, 100, 100};
@@ -40,4 +40,4 @@ void AddPlayer(float xpos, float ypos) {
#endif
AddEntity(&player);
-} \ No newline at end of file
+}