From 8152651c990d5fab26db695a2b99d3e31bafe42f Mon Sep 17 00:00:00 2001 From: JanEhehalt Date: Fri, 2 Dec 2022 12:26:50 +0100 Subject: [PATCH] Keine Ahnung, achtung, Memory leak --- .vscode/settings.json | 3 +- DepthSorting/bucket.c | 27 ++++++++++++ DepthSorting/bucket.h | 17 ++++++++ DepthSorting/mergeSort.c | 43 +++++++++++++++++++ DepthSorting/mergeSort.h | 9 ++++ IsometricMap/isometricMap.c | 82 +++++++++++++++++++++++++++++++++++++ IsometricMap/isometricMap.h | 3 ++ Makefile | 10 ++++- README.md | 8 +++- main.c | 37 +++++++++++++++-- 10 files changed, 230 insertions(+), 9 deletions(-) create mode 100644 DepthSorting/bucket.c create mode 100644 DepthSorting/bucket.h create mode 100644 DepthSorting/mergeSort.c create mode 100644 DepthSorting/mergeSort.h diff --git a/.vscode/settings.json b/.vscode/settings.json index ab0fa52..7fb8f0c 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -6,6 +6,7 @@ "map": "c", "isometricmap.h": "c", "animationhandler.h": "c", - "textureids.h": "c" + "textureids.h": "c", + "tile.h": "c" } } \ No newline at end of file diff --git a/DepthSorting/bucket.c b/DepthSorting/bucket.c new file mode 100644 index 0000000..479b13c --- /dev/null +++ b/DepthSorting/bucket.c @@ -0,0 +1,27 @@ +#include "bucket.h" +#include "stdio.h" +#include "stdlib.h" + + +#define TEXTUREWIDTH 32; +#define TEXTUREHEIGHT 32; + +Bucket * BucketInit(Sprite *sprite, Tile *tile){ + Bucket *bucket = (Bucket *) malloc(sizeof(Bucket)); + if(sprite != 0){ + bucket->type = 0; + bucket->sprite = sprite; + bucket->tile = 0; + bucket->depth = sprite->x + sprite->y + 0.001 * sprite->z; + return bucket; + } + else if(tile != 0){ + bucket->type = 1; + bucket->sprite = 0; + bucket->tile = tile; + bucket->depth = tile->x * TEXTUREWIDTH + tile->y * TEXTUREHEIGHT + 0.001 * tile->z; + return bucket; + } + return 0; + +} \ No newline at end of file diff --git a/DepthSorting/bucket.h b/DepthSorting/bucket.h new file mode 100644 index 0000000..8b0e771 --- /dev/null +++ b/DepthSorting/bucket.h @@ -0,0 +1,17 @@ +#ifndef BUCKET_H_ +#define BUCKET_H_ +#include "raylib.h" +#include "../sprite.h" +#include "../IsometricMap/tile.h" + +typedef struct Bucket{ + int type; // 0: Sprite, 1: Tile + Sprite *sprite; + Tile *tile; + float depth; +} Bucket; + +Bucket * BucketInit(Sprite *sprite, Tile *tile); + + +#endif \ No newline at end of file diff --git a/DepthSorting/mergeSort.c b/DepthSorting/mergeSort.c new file mode 100644 index 0000000..8cc9887 --- /dev/null +++ b/DepthSorting/mergeSort.c @@ -0,0 +1,43 @@ +#include "bucket.h" + +void MergeSort(Bucket *liste[], int groesse){ + + if(groesse > 1){ + + Bucket *haelfte1[groesse/2]; + Bucket *haelfte2[(groesse + 1)/2]; + int i; + for(i = 0; i < groesse/2; ++i) + haelfte1[i] = liste[i]; + for(i = groesse/2; i < groesse; ++i) + haelfte2[i - groesse/2] = liste[i]; + + MergeSort(haelfte1,groesse/2); + MergeSort(haelfte2,(groesse + 1)/2); + + Bucket **pos1 = &haelfte1[0]; + Bucket **pos2 = &haelfte2[0]; + for(i = 0; i < groesse; ++i){ + if((*pos1)->depth <= (*pos2)->depth){ + liste[i] = *pos1; + if (pos1 != &haelfte2[(groesse+1)/2 - 1]) { // pos1 nicht verändern, wenn der größte Wert mehrmals vorkommt + if(pos1 == &haelfte1[groesse/2 - 1]){ + pos1 = &haelfte2[(groesse+1)/2 - 1]; + } + else{ + ++pos1; + } + } + } + else{ + liste[i] = *pos2; + if(pos2 == &haelfte2[(groesse + 1)/2 - 1]){ + pos2 = &haelfte1[groesse/2 - 1]; + } + else{ + ++pos2; + } + } + } + } + } \ No newline at end of file diff --git a/DepthSorting/mergeSort.h b/DepthSorting/mergeSort.h new file mode 100644 index 0000000..fb3d744 --- /dev/null +++ b/DepthSorting/mergeSort.h @@ -0,0 +1,9 @@ +#ifndef MERGESORT_H_ +#define MERGESORT_H_ +#include "raylib.h" +#include "bucket.h" + +void MergeSort(Bucket *liste[], int groesse); + + +#endif \ No newline at end of file diff --git a/IsometricMap/isometricMap.c b/IsometricMap/isometricMap.c index 59dda45..7284d68 100644 --- a/IsometricMap/isometricMap.c +++ b/IsometricMap/isometricMap.c @@ -4,6 +4,10 @@ #include "tile.h" #include "raymath.h" #include "raylib.h" +#include "../DepthSorting/bucket.h" +#include "../game.h" +#include "../List/list.h" +#include "../DepthSorting/mergeSort.h" // returns pointer to IsometricMap Instance IsometricMap * IsometricMapInit(int layer){ @@ -168,3 +172,81 @@ void IsometricMapChangeTextureIdOfTile(IsometricMap **map, int x, int y, int lay } } +void IsometricMapDraw(Game *game){ + // TODO: Implement as List + Bucket *buckets[100000]; + int counter = 0; + + int windowWidth = GetScreenWidth(); + int windowHeight = GetScreenHeight(); + Vector2 topleft = {0, 0}; + IsometricMapProject(game->layers[0], game->camera, topleft.x, topleft.y, &topleft); + Vector2 topright = {windowWidth, 0}; + IsometricMapProject(game->layers[0], game->camera, topright.x, topright.y, &topright); + Vector2 botleft = {0, windowHeight}; + IsometricMapProject(game->layers[0], game->camera, botleft.x, botleft.y, &botleft); + Vector2 botright = {windowWidth, windowHeight}; + IsometricMapProject(game->layers[0], game->camera, botright.x, botright.y, &botright); + int extraTiles = 1; + int n = 0; + int itmp = (int)(topleft.x / game->layers[0]->textureWidth) - extraTiles; + int jtmp = (int)(topright.y / game->layers[0]->textureHeight) - extraTiles; + int maxI = (int)(botright.x / game->layers[0]->textureWidth) + extraTiles; + int maxJ = (int)(botleft.y / game->layers[0]->textureHeight) + extraTiles; + if (itmp < 0){ itmp = 0; } + if (jtmp < 0){ jtmp = 0; } + if (maxI > game->layers[0]->width){ maxI = game->layers[0]->width; } + if (maxJ > game->layers[0]->height){ maxJ = game->layers[0]->height; } + int i, j = 0; + for (n = 0; n < 10; n++){ + for (j = jtmp; j < maxJ; j++){ + for (i = itmp; i < maxI; i++){ + if (game->layers[n]->tiles[i][j]->textureId == -1){ + } + else{ + buckets[counter] = BucketInit(0, game->layers[n]->tiles[i][j]); + ++counter; + } + } + } + } + + Node *current = game->sprites->head; + int extraPixels = 0; + while(current != 0){ + // drawing some extra corner pixels + // if extraPixels == 0 you can see flickering in the corners + itmp = (int)(topleft.x) - extraPixels; + jtmp = (int)(topright.y) - extraPixels; + maxI = (int)(botright.x) + extraPixels; + maxJ = (int)(botleft.y) + extraPixels; + // Only drawing the Sprites which are within Camera view + if( current->data.x > itmp && + current->data.y > jtmp && + current->data.x < maxI && + current->data.y < maxJ){ + buckets[counter] = BucketInit(¤t->data, 0); + ++counter; + } + current = current->next; + } + + MergeSort(buckets, counter); + + int k = 0; + for(k = 0; k < counter; k++){ + if(buckets[k]->type == 1){ + DrawTexture( + game->layers[0]->tileTextures[buckets[k]->tile->textureId], + buckets[k]->tile->offsetX, + buckets[k]->tile->offsetY, + WHITE); + } + else if(buckets[k]->type == 0){ + DrawSpriteToWorld(buckets[k]->sprite, game->layers, game->camera); + } + //free(buckets[k]); + } + + +} \ No newline at end of file diff --git a/IsometricMap/isometricMap.h b/IsometricMap/isometricMap.h index 10327ca..0d5a019 100644 --- a/IsometricMap/isometricMap.h +++ b/IsometricMap/isometricMap.h @@ -2,6 +2,7 @@ #define ISOMETRICMAP_H_ #include "raylib.h" #include "tile.c" +#include "../game.h" typedef struct IsometricMap{ // Array with all the needed textures for this layer @@ -60,5 +61,7 @@ void IsometricMapChangeTextureIdOfTile(IsometricMap **map, int x, int y, int lay // returns Tile * -> tile at coordinates x y z=layer Tile * IsometricMapGetTileFromWorldCoordinates(IsometricMap **isometricMap, float x, float y, float layer); +// Draws Isometric Map and Sprites in between :) +void IsometricMapDraw(Game *game); #endif diff --git a/Makefile b/Makefile index 05a12fa..0d6c92a 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,8 @@ CC = gcc FLAGS = -lraylib -lGL -lm -lpthread -ldl -lrt -lX11 -spiel: main.o sprite.o inputHandler.o isometricRenderer.o isometricMap.o tile.o list.o game.o textureatlas.o animation.o animationHandler.o - $(CC) -o spiel main.o sprite.o inputHandler.o isometricRenderer.o isometricMap.o tile.o list.o game.o textureatlas.o animation.o animationHandler.o $(FLAGS) +spiel: main.o sprite.o inputHandler.o isometricRenderer.o isometricMap.o tile.o list.o game.o textureatlas.o animation.o animationHandler.o bucket.o mergeSort.o + $(CC) -o spiel main.o sprite.o inputHandler.o isometricRenderer.o isometricMap.o tile.o list.o game.o textureatlas.o animation.o animationHandler.o bucket.o mergeSort.o $(FLAGS) main.o: main.c $(CC) -c main.c $(FLAGS) @@ -37,5 +37,11 @@ animation.o: Textures/animation.c animationHandler.o: Textures/animationHandler.c $(CC) -c Textures/animationHandler.c $(FLAGS) +bucket.o: DepthSorting/bucket.c + $(CC) -c DepthSorting/bucket.c $(FLAGS) + +mergeSort.o: DepthSorting/mergeSort.c + $(CC) -c DepthSorting/mergeSort.c $(FLAGS) + clean: rm *.o spiel diff --git a/README.md b/README.md index 68010f0..b00e4f1 100644 --- a/README.md +++ b/README.md @@ -27,8 +27,12 @@ Fantasy Welt oder Realistisch? + MapEditor * Rendering Reihenfolge: layer 0, Sprites auf layer 0, layer 1, Sprites auf layer 1; Theoretisch müssen die einzelnen Layer Reihenweise gedrawed werden mit den Sprites zwischendrin + IsometricMap struct erstellen, das den IsometricMap(+Layer) Array speichert ? -+ TODO: Das rendern der IsometricMap wird bei größeren Maps sehr ineffizient; -+ Add offset x and y to each tile to be calculated ONCE, not every frame + ++ Beim rendern müssen die map tiles und die sprites nach ihrer depth (d = x + y + ~0.05*z) sortiert werden, dafür sollten wir ein bucket sorting system implementieren. Buckets sollten erstmal nur tiles und sprites unterstützen. ++ Wir können auch die Sprites in der Liste nach d sortieren, dann geht das gut mit "nur in der Kamera sichtbare Sprites rendern". d ist nicht optimal, vielleicht auch einfach über die ganze Liste gehen und nur die sprites mit $ x y \subset camBounds $ in das Bucket sorting system einfügen. Buckets können auch mit MergeSort oder so sortiert werden +[Vererbung in C, drawable superStruct?](https://de.wikibooks.org/wiki/C%2B%2B-Programmierung:_Vererbung) + ++ Mit der Map geht das schon recht einfach, weil wir wissen welche tiles in der Kamera sind. d ### WiP diff --git a/main.c b/main.c index b81157c..2f79b34 100644 --- a/main.c +++ b/main.c @@ -8,6 +8,8 @@ #include "IsometricMap/isometricRenderer.h" #include "IsometricMap/isometricMap.h" #include "game.h" +#include "DepthSorting/bucket.h" +#include "DepthSorting/mergeSort.h" int main(){ @@ -20,9 +22,27 @@ int main(){ HideCursor(); //SetTargetFPS(60); - + + /* + Bucket *buckets[10]; + int i = 0; + for(i = 9; i >= 0; i--){ + buckets[9-i] = (BucketInit(0, game->layers[0]->tiles[i][i])); + } + printf("\n"); + for(i = 0; i < 10; i++){ + printf("%f\n", buckets[i]->depth); + } + printf("\n"); + MergeSort(buckets, 10); + printf("\n"); + for(i = 0; i < 10; i++){ + printf("%f\n", buckets[i]->depth); + } + printf("\n"); + */ + // GAME MAIN ROUTINE - int c = 0; while(!WindowShouldClose()){ ListActAllSprites(game); @@ -32,8 +52,9 @@ int main(){ BeginMode2D(*(game->camera)); - IsometricRendererRenderIsometricMap(game); - ListDrawAllSprites(game->sprites, game->layers, game->camera); + //IsometricRendererRenderIsometricMap(game); + //ListDrawAllSprites(game->sprites, game->layers, game->camera); + IsometricMapDraw(game); EndMode2D(); @@ -49,6 +70,11 @@ int main(){ DrawFPS(GetScreenWidth() - 95, 10); EndDrawing(); + + + + + } CloseWindow(); @@ -56,3 +82,6 @@ int main(){ return 0; } + + + \ No newline at end of file