#include #include #include "game.h" #include "assets.h" #include "stdio.h" #include "player.h" #include "background.h" Game game; static inline bool EntityAllocated(const Entity* e) { return (e->flags & ENTITY_ALLOCATED); } static inline bool PhysicsEnabled(const Entity* e) { return EntityAllocated(e) && (e->flags & ENTITY_PHYSICS_ACTIVE); } 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) { return a->id == b->id; } 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->y) || (b->y <= a->y && b->y + b->height > a->y); return collisionX && collisionY; } static inline Rectangle GetPhysicsColliderGlobal(const Entity* e) { Rectangle physicsColliderGlobal = e->physicsCollider; physicsColliderGlobal.x += e->position.x; physicsColliderGlobal.y += e->position.y; 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); physicsCollider.x += e->velocity.x * deltaTime; for (int i = 0; i < MAX_ENTITY_COUNT; i++) { Entity* c = &game.entities[i]; if(!PhysicsEnabled(c) || SameEntity(c, e)) continue; Rectangle otherCollider = GetPhysicsColliderGlobal(c); if(IsColliding(&physicsCollider, &otherCollider)) { if (velocity.x > 0) { physicsCollider.x = otherCollider.x - physicsCollider.width; } else { physicsCollider.x = otherCollider.x + otherCollider.width; } } } physicsCollider.y += e->velocity.y * deltaTime; for (int i = 0; i < MAX_ENTITY_COUNT; i++) { Entity* c = &game.entities[i]; if(!PhysicsEnabled(c) || SameEntity(c, e)) continue; Rectangle otherCollider = GetPhysicsColliderGlobal(c); if(IsColliding(&physicsCollider, &otherCollider)) { if (velocity.y > 0) { physicsCollider.y = otherCollider.y - physicsCollider.height; } else { physicsCollider.y = otherCollider.y + otherCollider.height; } } } e->position.x = physicsCollider.x; e->position.y = physicsCollider.y; } void AddEntity(Entity* e) { static int nextId = 0; e->id = nextId++; e->flags |= ENTITY_ALLOCATED; for(int i = 0; i < MAX_ENTITY_COUNT; i++) { if (!EntityAllocated(&game.entities[i])) { game.entities[i] = *e; break; } } } void InitGame() { game.paused = false; LoadAssets(); memset(game.entities, 0, sizeof(game.entities)); } void UpdateEntity(Entity* e, float deltaTime) { switch (e->type) { case Player_Entity: UpdatePlayer(e, deltaTime); break; case Background_Entity: UpdateBackground(e, deltaTime); break; default: break; } } void UpdateGame(float 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]; if (EntityAllocated(e)) UpdateEntity(e, 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 (DrawLayer layer = Background_Layer; layer <= Foreground_Layer; layer++) { for (int j = 0; j < MAX_ENTITY_COUNT; j++) { Entity* currentEntity = &game.entities[j]; if (ShouldDrawEntity(currentEntity, layer)) DrawEntity(currentEntity); } } #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 = {0}; wall.type = Wall_Entity; wall.flags |= ENTITY_PHYSICS_ACTIVE; wall.position = (Vector2) {xpos, ypos}; wall.physicsCollider = (Rectangle) {0, 0, width, height}; #ifdef BEATEMUP_DEBUG wall.physicsColliderColor = BLUE; #endif AddEntity(&wall); }