From 91deaf34b212f3560f284c50100d794d13feb353 Mon Sep 17 00:00:00 2001 From: "Valeriano A.R." Date: Mon, 7 Oct 2024 02:46:16 +0200 Subject: [PATCH] =?UTF-8?q?Implement=20na=C3=AFve=20buckets=20of=20bboxes.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Allows faster spatial querying entities for collisions and overlapping. Fixes #3 --- CMakeLists.txt | 2 + src/Bucket.c | 185 +++++++++++++++++++++++++++++++++++++++++++++++ src/Bucket.h | 68 ++++++++++++++++++ src/Entity.c | 24 +++---- src/Entity.h | 4 +- src/GameLib.c | 189 +++++++++++++++++++++++++++++++++---------------- src/GameLib.h | 14 +++- 7 files changed, 409 insertions(+), 77 deletions(-) create mode 100644 src/Bucket.c create mode 100644 src/Bucket.h diff --git a/CMakeLists.txt b/CMakeLists.txt index f9214c4..bf2ae42 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -31,6 +31,7 @@ set(GAMELIB_HEADERS src/Audio.h src/Anim.h src/Entity.h + src/Bucket.h src/GameLib.h) set(GAMELIB_SOURCE @@ -42,6 +43,7 @@ set(GAMELIB_SOURCE src/Audio.c src/Anim.c src/Entity.c + src/Bucket.c src/GameLib.c) add_library(GameLib STATIC diff --git a/src/Bucket.c b/src/Bucket.c new file mode 100644 index 0000000..3bd44df --- /dev/null +++ b/src/Bucket.c @@ -0,0 +1,185 @@ +// Copyright (C) 2024 Valeriano Alfonso Rodriguez (Kableado) + +#include "Bucket.h" + +#include "Util.h" + +#include +#include + +//////////////////////////////////////////////// +// BBox +// + +int BBox_Intersect(BBox bbox1, BBox bbox2) { + if (bbox1->x2 >= bbox2->x1 && bbox1->x1 <= bbox2->x2 && bbox1->y2 >= bbox2->y1 && bbox1->y1 <= bbox2->y2) { + return (1); + } + return (0); +} + +//////////////////////////////////////////////// +// Bucket +// + +void Bucket_Init(Bucket bucket) { bucket->count = 0; } + +void Bucket_AddItem(Bucket bucket, BBox item) { + if (bucket->count >= Max_ItemsPerBucket) { + Print("Bucket Overflow\n"); + return; + } + bucket->bbox[bucket->count] = item; + bucket->count++; +} + +void Bucket_AddItemUnique(Bucket bucket, BBox item) { + for (int i = 0; i < bucket->count; i++) { + if (bucket->bbox[i]->parent == item->parent) { + return; + } + } + Bucket_AddItem(bucket, item); +} + +int Bucket_SearchItem(Bucket bucket, BBox item) { + for (int i = 0; i < bucket->count; i++) { + if (bucket->bbox[i]->parent == item->parent) { + return i; + } + } + return -1; +} + +void Bucket_RemoveIndex(Bucket bucket, int index) { + bucket->bbox[index] = bucket->bbox[bucket->count - 1]; + bucket->count--; + bucket->bbox[bucket->count] = NULL; +} + +void Bucket_RemoveItem(Bucket bucket, BBox item) { + int index = Bucket_SearchItem(bucket, item); + if (index < 0) { + return; + } + Bucket_RemoveIndex(bucket, index); +} + +//////////////////////////////////////////////// +// BucketGrid +// + +void BucketGrid_Init(BucketGrid bucketGrid, int width, int height, float bucketSize, float offsetX, float offsetY) { + bucketGrid->width = width; + bucketGrid->height = height; + bucketGrid->bucketSize = bucketSize; + bucketGrid->offsetX = offsetX; + bucketGrid->offsetY = offsetY; + bucketGrid->bucket = (TBucket *)malloc(sizeof(TBucket) * bucketGrid->width * bucketGrid->height); + for (int y = 0; y < bucketGrid->height; y++) { + for (int x = 0; x < bucketGrid->width; x++) { + Bucket_Init(&bucketGrid->bucket[x + y * width]); + } + } +} + +void BucketGrid_DeInit(BucketGrid bucketGrid) { free(bucketGrid->bucket); } + +int BucketGrid_AddItem(BucketGrid bucketGrid, BBox item) { + const int x1Bucket = (int)floorf((item->x1 + bucketGrid->offsetX) / bucketGrid->bucketSize); + const int x2Bucket = (int)ceilf((item->x2 + bucketGrid->offsetX) / bucketGrid->bucketSize); + const int y1Bucket = (int)floorf((item->y1 + bucketGrid->offsetY) / bucketGrid->bucketSize); + const int y2Bucket = (int)ceilf((item->y2 + bucketGrid->offsetY) / bucketGrid->bucketSize); + + int inserted = 0; + for (int y = y1Bucket; y <= y2Bucket; y++) { + for (int x = x1Bucket; x <= x2Bucket; x++) { + if (y < 0 || y >= bucketGrid->height || x < 0 || x >= bucketGrid->width) { + continue; + } + Bucket bucket = &bucketGrid->bucket[x + y * bucketGrid->width]; + Bucket_AddItem(bucket, item); + inserted = 1; + } + } + if (inserted) { + item->changed = 0; + } + return inserted; +} + +void BucketGrid_RemoveItem(BucketGrid bucketGrid, BBox item) { + const int x1Bucket = (int)floorf((item->x1 + bucketGrid->offsetX) / bucketGrid->bucketSize); + const int x2Bucket = (int)ceilf((item->x2 + bucketGrid->offsetX) / bucketGrid->bucketSize); + const int y1Bucket = (int)floorf((item->y1 + bucketGrid->offsetY) / bucketGrid->bucketSize); + const int y2Bucket = (int)ceilf((item->y2 + bucketGrid->offsetY) / bucketGrid->bucketSize); + + for (int y = y1Bucket; y <= y2Bucket; y++) { + for (int x = x1Bucket; x <= x2Bucket; x++) { + if (y < 0 || y >= bucketGrid->height || x < 0 || x >= bucketGrid->width) { + continue; + } + Bucket bucket = &bucketGrid->bucket[x + y * bucketGrid->width]; + Bucket_RemoveItem(bucket, item); + } + } +} + +void BucketGrid_Query(BucketGrid bucketGrid, BBox item, Bucket resultBucket) { + const int x1Bucket = (int)floorf((item->x1 + bucketGrid->offsetX) / bucketGrid->bucketSize); + const int x2Bucket = (int)ceilf((item->x2 + bucketGrid->offsetX) / bucketGrid->bucketSize); + const int y1Bucket = (int)floorf((item->y1 + bucketGrid->offsetY) / bucketGrid->bucketSize); + const int y2Bucket = (int)ceilf((item->y2 + bucketGrid->offsetY) / bucketGrid->bucketSize); + + Bucket_Init(resultBucket); + + for (int y = y1Bucket; y <= y2Bucket; y++) { + for (int x = x1Bucket; x <= x2Bucket; x++) { + if (y < 0 || y >= bucketGrid->height || x < 0 || x >= bucketGrid->width) { + continue; + } + Bucket bucket = &bucketGrid->bucket[x + y * bucketGrid->width]; + for (int i = 0; i < bucket->count; i++) { + if (BBox_Intersect(bucket->bbox[i], item)) { + Bucket_AddItemUnique(resultBucket, bucket->bbox[i]); + } + } + } + } +} + +int BucketGrid_ProcessChanged(BucketGrid bucketGrid) { + TBucket bucketChanged; + Bucket_Init(&bucketChanged); + + for (int y = 0; y < bucketGrid->height; y++) { + for (int x = 0; x <= bucketGrid->width; x++) { + Bucket bucket = &bucketGrid->bucket[x + y * bucketGrid->width]; + int i = 0; + while (i < bucket->count) { + if (bucket->bbox[i]->changed) { + if (bucketChanged.count == Max_ItemsPerBucket) { + return 0; + } + Bucket_AddItemUnique(&bucketChanged, bucket->bbox[i]); + Bucket_RemoveIndex(bucket, i); + } else { + i++; + } + } + } + } + for (int i = 0; i < bucketChanged.count; i++) { + BucketGrid_AddItem(bucketGrid, bucketChanged.bbox[i]); + } + return 1; +} + +void BucketGrid_Clean(BucketGrid bucketGrid) { + for (int y = 0; y < bucketGrid->height; y++) { + for (int x = 0; x <= bucketGrid->width; x++) { + Bucket bucket = &bucketGrid->bucket[x + y * bucketGrid->width]; + Bucket_Init(bucket); + } + } +} diff --git a/src/Bucket.h b/src/Bucket.h new file mode 100644 index 0000000..85858cf --- /dev/null +++ b/src/Bucket.h @@ -0,0 +1,68 @@ +// Copyright (C) 2024 Valeriano Alfonso Rodriguez (Kableado) + +#ifndef Bucket_H +#define Bucket_H + +//////////////////////////////////////////////// +// BBox +// +typedef struct TBBox TBBox, *BBox; +struct TBBox { + float x1, x2; + float y1, y2; + void *parent; + int changed; +}; + +int BBox_Intersect(BBox bbox1, BBox bbox2); + +//////////////////////////////////////////////// +// Bucket +// +#define Max_ItemsPerBucket 200 +typedef struct TBucket TBucket, *Bucket; +struct TBucket { + BBox bbox[Max_ItemsPerBucket]; + int count; +}; + +void Bucket_Init(Bucket bucket); + +void Bucket_AddItem(Bucket bucket, BBox item); + +void Bucket_AddItemUnique(Bucket bucket, BBox item); + +int Bucket_SearchItem(Bucket bucket, BBox item); + +void Bucket_RemoveIndex(Bucket bucket, int index); + +void Bucket_RemoveItem(Bucket bucket, BBox item); + +//////////////////////////////////////////////// +// BucketGrid +// +typedef struct TBucketGrid TBucketGrid, *BucketGrid; +struct TBucketGrid { + TBucket *bucket; + int width; + int height; + float bucketSize; + float offsetX; + float offsetY; +}; + +void BucketGrid_Init(BucketGrid bucketGrid, int width, int height, float bucketSize, float offsetX, float offsetY); + +void BucketGrid_DeInit(BucketGrid bucketGrid); + +int BucketGrid_AddItem(BucketGrid bucketGrid, BBox item); + +void BucketGrid_RemoveItem(BucketGrid bucketGrid, BBox item); + +void BucketGrid_Query(BucketGrid bucketGrid, BBox item, Bucket resultBucket); + +int BucketGrid_ProcessChanged(BucketGrid bucketGrid); + +void BucketGrid_Clean(BucketGrid bucketGrid); + +#endif diff --git a/src/Entity.c b/src/Entity.c index 9e7e0db..d458eb9 100644 --- a/src/Entity.c +++ b/src/Entity.c @@ -8,6 +8,7 @@ #include "Draw.h" #include "Util.h" +#include "Bucket.h" #include "Entity.h" #define EntityIntFlag_UpdateLight 1 @@ -195,6 +196,7 @@ Entity Entity_Copy(Entity e) { n->E = e->E; n->child = e->child; + n->bbox.parent = n; Entity_CalcBBox(n); // Call the copy event @@ -215,19 +217,20 @@ void Entity_CalcBBox(Entity e) { float hHeight = (max(e->height, e->radius) / 2) + BBox_ExtraMargin; float hWidth = (max(e->width, e->radius) / 2) + BBox_ExtraMargin; if (e->vel[0] > 0) { - e->maxX = e->pos[0] + e->vel[0] + hWidth; - e->minX = e->pos[0] - hWidth; + e->bbox.x2 = e->pos[0] + e->vel[0] + hWidth; + e->bbox.x1 = e->pos[0] - hWidth; } else { - e->minX = (e->pos[0] + e->vel[0]) - hWidth; - e->maxX = e->pos[0] + hWidth; + e->bbox.x1 = (e->pos[0] + e->vel[0]) - hWidth; + e->bbox.x2 = e->pos[0] + hWidth; } if (e->vel[1] > 0) { - e->maxY = e->pos[1] + e->vel[1] + hHeight; - e->minY = e->pos[1] - hHeight; + e->bbox.y2 = e->pos[1] + e->vel[1] + hHeight; + e->bbox.y1 = e->pos[1] - hHeight; } else { - e->minY = (e->pos[1] + e->vel[1]) - hHeight; - e->maxY = e->pos[1] + hHeight; + e->bbox.y1 = (e->pos[1] + e->vel[1]) - hHeight; + e->bbox.y2 = e->pos[1] + hHeight; } + e->bbox.changed = 1; } ///////////////////////////// @@ -235,10 +238,7 @@ void Entity_CalcBBox(Entity e) { // // int Entity_BBoxIntersect(Entity ent1, Entity ent2) { - if (ent1->maxX >= ent2->minX && ent1->minX <= ent2->maxX && ent1->maxY >= ent2->minY && ent1->minY <= ent2->maxY) { - return (1); - } - return (0); + return BBox_Intersect(&ent1->bbox, &ent2->bbox); } ///////////////////////////// diff --git a/src/Entity.h b/src/Entity.h index 85f53fa..2079c9c 100644 --- a/src/Entity.h +++ b/src/Entity.h @@ -4,6 +4,7 @@ #define Entity_H #include "Anim.h" +#include "Bucket.h" #include "Draw.h" #include "Util.h" @@ -76,8 +77,7 @@ struct TEntity { vec2 VecB; Entity child; - float maxX, minX; - float maxY, minY; + TBBox bbox; Entity next; }; diff --git a/src/GameLib.c b/src/GameLib.c index 211cd97..4521c15 100644 --- a/src/GameLib.c +++ b/src/GameLib.c @@ -8,6 +8,8 @@ #include "GameLib.h" +#include + // Globals Entity *g_Entity = NULL; int *g_EntityFlag = NULL; @@ -44,6 +46,8 @@ struct TParallaxBackground { TParallaxBackground g_ParallaxBackground[MaxParallaxBackgrounds]; int g_NumParallaxBackgrounds = 0; +TBucketGrid g_BucketGrid; + ///////////////////////////// // GameLib_Init // @@ -66,9 +70,52 @@ int GameLib_Init(int w, int h, char *title, int pFps, int fps) { g_ProcFt = 1000 / pFps; + BucketGrid_Init(&g_BucketGrid, 1, 1, 64, 32, 32); + return (1); } +///////////////////////////// +// GameLib_PrepareSize +// +// +void GameLib_PrepareSize(const float x1, const float y1, const float x2, const float y2) { + const float bucketSize = 64; + + const float width = x2 - x1; + const float height = y2 - y1; + const int widthBuckets = (int)ceilf(width / bucketSize); + const int heightBuckets = (int)ceilf(height / bucketSize); + + BucketGrid_DeInit(&g_BucketGrid); + BucketGrid_Init(&g_BucketGrid, widthBuckets, heightBuckets, bucketSize, -x1, -y1); + for (int i = 0; i < g_NumEntities; i++) { + BucketGrid_AddItem(&g_BucketGrid, &g_Entity[i]->bbox); + } +} + +///////////////////////////// +// GameLib_CheckSize +// +// +void GameLib_CheckSize() { + float xMin = FLT_MAX; + float yMin = FLT_MAX; + float xMax = FLT_MIN; + float yMax = FLT_MIN; + for (int i = 0; i < g_NumEntities; i++) { + if (g_Entity[i]->bbox.x1 < xMin) + xMin = g_Entity[i]->bbox.x1; + if (g_Entity[i]->bbox.x2 > xMax) + xMax = g_Entity[i]->bbox.x2; + if (g_Entity[i]->bbox.y1 < yMin) + yMin = g_Entity[i]->bbox.y1; + if (g_Entity[i]->bbox.y2 > yMax) + yMax = g_Entity[i]->bbox.y2; + } + GameLib_PrepareSize(xMin, yMin, xMax, yMax); +} + ///////////////////////////// // GameLib_AddEntity // @@ -108,6 +155,9 @@ void GameLib_AddEntity(Entity e) { Entity_MarkUpdateLight(e, g_Entity, g_NumEntities); Entity_CalcBBox(e); + if (BucketGrid_AddItem(&g_BucketGrid, &e->bbox) == 0) { + GameLib_CheckSize(); + } Entity_Init(e); } @@ -152,6 +202,7 @@ int GameLib_DelEntity(Entity e) { g_EntityFlag[i] = -1; } else { // Delete now + BucketGrid_RemoveItem(&g_BucketGrid, &g_Entity[i]->bbox); Entity_Destroy(e); } return (1); @@ -172,6 +223,7 @@ void GameLib_Compactate() { continue; } if (g_EntityFlag[i] == -1) { + BucketGrid_RemoveItem(&g_BucketGrid, &g_Entity[i]->bbox); Entity_Destroy(g_Entity[i]); continue; } @@ -191,7 +243,7 @@ void GameLib_Compactate() { // Process the loop. void GameLib_ProcLoop(void *data) { int i, j; - int repeat, count; + int repeat; long long time; // Step the gamePosition @@ -212,30 +264,42 @@ void GameLib_ProcLoop(void *data) { } GameLib_Compactate(); g_EntitiesLock = 0; + + if (BucketGrid_ProcessChanged(&g_BucketGrid) == 0) { + Print("Rebuild BucketGrid"); + BucketGrid_Clean(&g_BucketGrid); + for (int i = 0; i < g_NumEntities; i++) { + BucketGrid_AddItem(&g_BucketGrid, &g_Entity[i]->bbox); + } + } + t_proc += Time_GetTime() - time; // Collisions between entities time = Time_GetTime(); g_EntitiesLock = 1; - count = 0; + int count = 0; + int maxCount = 50; do { repeat = 0; CollisionInfo collInfo = NULL; for (i = 0; i < g_NumEntities; i++) { - if (!(g_Entity[i]->flags & EntityFlag_Collision) || g_Entity[i]->mass < 0.0f) { + Entity ent = g_Entity[i]; + if (!(ent->flags & EntityFlag_Collision) || ent->mass < 0.0f) { continue; } - if (g_Entity[i]->vel[0] <= 0.0f && g_Entity[i]->vel[0] >= -0.0f && g_Entity[i]->vel[1] <= 0.0f && - g_Entity[i]->vel[1] >= -0.0f) { + if (ent->vel[0] <= 0.0f && ent->vel[0] >= -0.0f && ent->vel[1] <= 0.0f && ent->vel[1] >= -0.0f) { continue; } - for (j = 0; j < g_NumEntities; j++) { - if (i == j || !(g_Entity[j]->flags & EntityFlag_Collision) || - CollisionInfo_CheckRepetition(collInfo, g_Entity[i], g_Entity[j]) || - !Entity_BBoxIntersect(g_Entity[i], g_Entity[j])) { + TBucket bucket; + BucketGrid_Query(&g_BucketGrid, &ent->bbox, &bucket); + for (j = 0; j < bucket.count; j++) { + Entity entCollision = bucket.bbox[j]->parent; + if (ent == entCollision || !(entCollision->flags & EntityFlag_Collision) || + CollisionInfo_CheckRepetition(collInfo, ent, entCollision)) { continue; } - Entity_CheckCollision(g_Entity[i], g_Entity[j], &collInfo); + Entity_CheckCollision(ent, entCollision, &collInfo); } } if (Entity_CollisionInfoResponse(collInfo)) { @@ -243,24 +307,27 @@ void GameLib_ProcLoop(void *data) { } CollisionInfo_Destroy(&collInfo); count++; - } while (repeat && count < 50); + } while (repeat && count < maxCount); // Stop remaining collisions - if (count == 10) { + if (count >= maxCount) { for (i = 0; i < g_NumEntities; i++) { - if (!(g_Entity[i]->flags & EntityFlag_Collision) || g_Entity[i]->mass < 0.0f) { + Entity ent = g_Entity[i]; + if (!(ent->flags & EntityFlag_Collision) || ent->mass < 0.0f) { continue; } - for (j = 0; j < g_NumEntities; j++) { - if (i == j || !(g_Entity[j]->flags & EntityFlag_Collision) || - !Entity_BBoxIntersect(g_Entity[i], g_Entity[j])) { + TBucket bucket; + BucketGrid_Query(&g_BucketGrid, &ent->bbox, &bucket); + for (j = 0; j < bucket.count; j++) { + Entity entCollision = bucket.bbox[j]->parent; + if (ent == entCollision || !(entCollision->flags & EntityFlag_Collision)) { continue; } - if (Entity_CheckCollision(g_Entity[i], g_Entity[j], NULL)) { - vec2_set(g_Entity[i]->vel, 0, 0); - Entity_CalcBBox(g_Entity[i]); - vec2_set(g_Entity[j]->vel, 0, 0); - Entity_CalcBBox(g_Entity[j]); + if (Entity_CheckCollision(ent, entCollision, NULL)) { + vec2_set(ent->vel, 0, 0); + Entity_CalcBBox(ent); + vec2_set(entCollision->vel, 0, 0); + Entity_CalcBBox(entCollision); } } } @@ -273,14 +340,18 @@ void GameLib_ProcLoop(void *data) { time = Time_GetTime(); g_EntitiesLock = 1; for (i = 0; i < g_NumEntities; i++) { - if (!(g_Entity[i]->flags & EntityFlag_Overlap) || g_Entity[i]->mass < 0.0f) { + Entity ent = g_Entity[i]; + if (!(ent->flags & EntityFlag_Overlap) || ent->mass < 0.0f) { continue; } - for (j = 0; j < g_NumEntities; j++) { - if (!(g_Entity[j]->flags & EntityFlag_Overlap) || i == j) { + TBucket bucket; + BucketGrid_Query(&g_BucketGrid, &ent->bbox, &bucket); + for (j = 0; j < bucket.count; j++) { + Entity entCollision = bucket.bbox[j]->parent; + if (!(entCollision->flags & EntityFlag_Overlap) || ent == entCollision) { continue; } - Entity_Overlaps(g_Entity[i], g_Entity[j]); + Entity_Overlaps(ent, entCollision); } } GameLib_Compactate(); @@ -288,14 +359,13 @@ void GameLib_ProcLoop(void *data) { t_over += Time_GetTime() - time; // Sort - int n, n2, swap; - n = g_NumEntities; + int n = g_NumEntities; do { - n2 = 0; + int n2 = 0; for (i = 1; i < n; i++) { Entity ent1 = g_Entity[i - 1]; Entity ent2 = g_Entity[i]; - swap = 0; + int swap = 0; if (ent1->zorder > ent2->zorder) { // Lower level swap = 1; @@ -303,8 +373,8 @@ void GameLib_ProcLoop(void *data) { // Upper level } else { // Same level - float y1 = ent1->pos[1] + ent1->sortYOffset; - float y2 = ent2->pos[1] + ent2->sortYOffset; + const float y1 = ent1->pos[1] + ent1->sortYOffset; + const float y2 = ent2->pos[1] + ent2->sortYOffset; if (y1 == y2) { if (ent1->pos[0] < ent2->pos[0]) { swap = 1; @@ -314,8 +384,7 @@ void GameLib_ProcLoop(void *data) { } } if (swap) { - Entity ent; - ent = g_Entity[i]; + Entity ent = g_Entity[i]; g_Entity[i] = g_Entity[i - 1]; g_Entity[i - 1] = ent; n2 = i; @@ -442,11 +511,11 @@ void GameLib_DrawLoop(void *data, float f) { // GameLib_Loop // // Loops the game. -void GameLib_Loop(void (*gameproc)(), void (*gamepostproc)(), void (*gamepredraw)(float f), void (*gamedraw)(float f)) { - g_GameProcFunc = gameproc; - g_GamePostProcFunc = gamepostproc; - g_GamePreDrawFunc = gamepredraw; - g_GameDrawFunc = gamedraw; +void GameLib_Loop(void (*gameProc)(), void (*gamePostProc)(), void (*gamePreDraw)(float f), void (*gameDraw)(float f)) { + g_GameProcFunc = gameProc; + g_GamePostProcFunc = gamePostProc; + g_GamePreDrawFunc = gamePreDraw; + g_GameDrawFunc = gameDraw; t_proc = 0; t_col = 0; t_over = 0; @@ -503,10 +572,10 @@ void GameLib_MoveToPos(vec2 pos, float f) { GameLib_MoveToPosH(pos, f); GameLib_MoveToPosV(pos, f); } -void GameLib_MoveToPosH(const vec2 pos, float f) { +void GameLib_MoveToPosH(const vec2 pos, const float f) { g_GamePos1[0] = g_GamePos1[0] + (pos[0] - (g_GamePos1[0] + (g_GameSize[0] / 2.0f))) * f; } -void GameLib_MoveToPosV(const vec2 pos, float f) { +void GameLib_MoveToPosV(const vec2 pos, const float f) { g_GamePos1[1] = g_GamePos1[1] + (pos[1] - (g_GamePos1[1] + (g_GameSize[1] / 2.0f))) * f; } @@ -515,15 +584,15 @@ void GameLib_MoveToPosV(const vec2 pos, float f) { // // Deletes every entity. void GameLib_DelEnts() { - int i; - - for (i = 0; i < g_NumEntities; i++) { + for (int i = 0; i < g_NumEntities; i++) { if (!g_Entity[i]) { continue; } Entity_Destroy(g_Entity[i]); } g_NumEntities = 0; + BucketGrid_DeInit(&g_BucketGrid); + BucketGrid_Init(&g_BucketGrid, 1, 1, 100, 50, 50); } ///////////////////////////// @@ -531,8 +600,7 @@ void GameLib_DelEnts() { // // Iterates every entity. void GameLib_ForEachEnt(int (*func)(Entity ent)) { - int i; - for (i = 0; i < g_NumEntities; i++) { + for (int i = 0; i < g_NumEntities; i++) { if (!g_Entity[i]) { continue; } @@ -547,9 +615,8 @@ void GameLib_ForEachEnt(int (*func)(Entity ent)) { // // Searches throught the entities. Entity GameLib_SearchEnt(int (*func)(Entity ent, void *d), void *d) { - int i; Entity ent = NULL; - for (i = 0; i < g_NumEntities; i++) { + for (int i = 0; i < g_NumEntities; i++) { if (!g_Entity[i]) { continue; } @@ -569,13 +636,12 @@ int GameLib_EntityCustomCheckCollision(Entity ent, vec2 vel) { int collision = 0; CollisionInfo collInfo = NULL; vec2 originalVel; - int j; vec2_copy(originalVel, ent->vel); vec2_copy(ent->vel, vel); Entity_CalcBBox(ent); - for (j = 0; j < g_NumEntities; j++) { + for (int j = 0; j < g_NumEntities; j++) { if (!(g_Entity[j]->flags & EntityFlag_Collision) || !Entity_BBoxIntersect(ent, g_Entity[j])) { continue; } @@ -598,27 +664,26 @@ int GameLib_EntityCustomCheckCollision(Entity ent, vec2 vel) { // // void GameLib_PlaySound(AudioSnd snd, int x, int y) { - float vLeft, vRight, dx, dy; - int r, cx, cy, off; + int r; // Get the screen context - cx = g_GamePos1[0] + g_GameSize[0] / 2; - cy = g_GamePos1[1] + g_GameSize[1] / 2; + int cx = g_GamePos1[0] + g_GameSize[0] / 2; + int cy = g_GamePos1[1] + g_GameSize[1] / 2; if (g_GameSize[0] > g_GameSize[1]) { r = g_GameSize[0] / 2; } else { r = g_GameSize[1] / 2; } - r = r * 1.2f; - off = r / 10.0f; + r = r * 1.2f; + int off = r / 10.0f; // Calculate volumes - dx = x - (cx + off); - dy = y - (cy); - vRight = 1.0f - (sqrtf(dx * dx + dy * dy) / (float)r); - dx = x - (cx - off); - dy = y - (cy); - vLeft = 1.0f - (sqrtf(dx * dx + dy * dy) / (float)r); + float dx = x - (cx + off); + float dy = y - (cy); + float vRight = 1.0f - (sqrtf(dx * dx + dy * dy) / (float)r); + dx = x - (cx - off); + dy = y - (cy); + float vLeft = 1.0f - (sqrtf(dx * dx + dy * dy) / (float)r); // Clamp to 0 if (vLeft < 0.0f) { @@ -677,7 +742,7 @@ void GameLib_ConvertScreenPositionToGamePosition(vec2 screenPos, vec2 gamePos, f // // void GameLib_AddParallaxBackground(DrawImg img, int imgSize[2], int imgOffset[2], float parallaxFactor[2]) { - int idx = g_NumParallaxBackgrounds; + const int idx = g_NumParallaxBackgrounds; if ((idx + 1) >= MaxParallaxBackgrounds) { Print("GameLib: Can't add parallaxBackground, limit reached."); return; diff --git a/src/GameLib.h b/src/GameLib.h index 1a7d745..40bed56 100644 --- a/src/GameLib.h +++ b/src/GameLib.h @@ -17,6 +17,18 @@ // Initializes the game. int GameLib_Init(int w, int h, char *title, int pFps, int fps); +///////////////////////////// +// GameLib_PrepareSize +// +// +void GameLib_PrepareSize(float x1, float y1, float x2, float y2); + +///////////////////////////// +// GameLib_CheckSize +// +// +void GameLib_CheckSize(); + ///////////////////////////// // GameLib_AddEntity // @@ -39,7 +51,7 @@ int GameLib_DelEntity(Entity e); // GameLib_Loop // // Loops the game. -void GameLib_Loop(void (*gameproc)(), void (*gamepostproc)(), void (*gamepredraw)(float f), void (*gamedraw)(float f)); +void GameLib_Loop(void (*gameProc)(), void (*gamePostProc)(), void (*gamePreDraw)(float f), void (*gameDraw)(float f)); ///////////////////////////// // GameLib_GetPos