summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordavidovski <david@davidovski.xyz>2023-07-23 23:45:47 +0200
committerdavidovski <david@davidovski.xyz>2023-07-23 23:45:47 +0200
commit661f470cc8197f643a2ab36c35fb0630f31023aa (patch)
tree8b0ad0754d0b7e0b000276c6b2cfcc9e4a330cd5 /src
parent0f1d7ba48387faaced30d35e64cf346d368f4a23 (diff)
optimise chunk loading and redrawing
Diffstat (limited to 'src')
-rw-r--r--src/tiled.c40
-rw-r--r--src/tiled.h8
-rw-r--r--src/tiledmap.c90
-rw-r--r--src/tiledmap.h4
4 files changed, 52 insertions, 90 deletions
diff --git a/src/tiled.c b/src/tiled.c
index b90aea7..436029b 100644
--- a/src/tiled.c
+++ b/src/tiled.c
@@ -14,15 +14,19 @@ void updateCamera(Tiled * tiled) {
if (IsKeyDown(KEY_W)) tiled->zoom += tiled->zoom * 0.01f;
if (IsKeyDown(KEY_S)) tiled->zoom -= tiled->zoom * 0.01f;
+ tiled->chunkOffset[2] = tiled->chunkOffset[0];
+ tiled->chunkOffset[3] = tiled->chunkOffset[1];
+
tiled->chunkOffset[0] = tiled->offset.x / tiled->tiledMap.chunkWidth;
tiled->chunkOffset[1] = tiled->offset.y / tiled->tiledMap.chunkHeight;
tiled->renderOffset.x = tiled->offset.x - tiled->chunkOffset[0]*tiled->tiledMap.chunkWidth;
tiled->renderOffset.y = tiled->offset.y - tiled->chunkOffset[1]*tiled->tiledMap.chunkHeight;
- // TODO only do this when chunk offset has changed
// TODO unload chunks when they are no longer visible
- redrawTiledMap(*tiled);
+ if (tiled->chunkOffset[0] != tiled->chunkOffset[2]
+ || tiled->chunkOffset[1] != tiled->chunkOffset[3])
+ redrawTiledMap(*tiled);
}
void updateTiledCamera(Tiled *tiled) {
@@ -52,29 +56,35 @@ Vector2 translateTiledPosition(Tiled tiled, Vector2 screenPos) {
Vector2 translateTiledScreenPosition(Tiled tiled, Vector2 tiledPos) {
return (Vector2) {
- (tiledPos.x + tiled.renderOffset.x + tiled.chunkOffset[0]*tiled.tiledMap.chunkWidth) * tiled.zoom,
- (tiledPos.y + tiled.renderOffset.y + tiled.chunkOffset[1]*tiled.tiledMap.chunkHeight) * tiled.zoom
+ (tiledPos.x + tiled.offset.x) * tiled.zoom,
+ (tiledPos.y + tiled.offset.y) * tiled.zoom
};
}
-Tile getOffsetTile(TiledMap * tiledMap, int chunkOffset[2], int x, int y) {
- return getChunkedTile(tiledMap,
- x - chunkOffset[0]*tiledMap->chunkWidth,
- y - chunkOffset[1]*tiledMap->chunkHeight);
-}
-
void redrawTile(Tiled tiled, int x, int y) {
+ int areaX = x + tiled.chunkOffset[0]*tiled.tiledMap.chunkWidth;
+ int areaY = tiled.renderArea[1] - y - tiled.chunkOffset[1]*tiled.tiledMap.chunkHeight - 1;
+
+ Tile v = getChunkedTile(&tiled.tiledMap, x, y);
+
BeginTextureMode(tiled.tilemapTexture);
- Tile v = getOffsetTile(&tiled.tiledMap, tiled.chunkOffset, x, y);
- DrawPixel(x, tiled.renderArea[1] - y - 1, (Color){ v, 0, 0, 255 });
+ DrawPixel(areaX, areaY, (Color){ v, 0, 0, 255 });
EndTextureMode();
}
void redrawTiledMap(Tiled tiled) {
+ // TODO since we have to do this every time a chunk is loaded, maybe there is a better way
+ int realX, realY;
+ Tile v;
+
BeginTextureMode(tiled.tilemapTexture);
for (int y = 0; y < tiled.renderArea[1]; y++) {
for (int x = 0; x < tiled.renderArea[0]; x++) {
- Tile v = getOffsetTile(&tiled.tiledMap, tiled.chunkOffset, x, y);
+ realX = x - tiled.chunkOffset[0]*tiled.tiledMap.chunkWidth;
+ realY = y - tiled.chunkOffset[1]*tiled.tiledMap.chunkHeight;
+
+ v = getChunkedTile(&tiled.tiledMap, realX, realY);
+
DrawPixel(x, tiled.renderArea[1] - y - 1, (Color){ v, 0, 0, 255 });
}
}
@@ -88,9 +98,11 @@ Tiled initTiled(TiledMap tiledMap) {
tiled.offset = (Vector2) {0, 0};
tiled.zoom = 64;
- // TODO renderArea is obsolete, should be visible map size
tiled.renderArea[0] = tiledMap.chunkWidth * RENDER_DISTANCE;
tiled.renderArea[1] = tiledMap.chunkHeight * RENDER_DISTANCE;
+
+ printf("Render area %dx%d\n", tiled.renderArea[0], tiled.renderArea[1]);
+
tiled.targetTexture = LoadRenderTexture(1, 1);
tiled.tilemapTexture = LoadRenderTexture(tiled.renderArea[0], tiled.renderArea[1]);
diff --git a/src/tiled.h b/src/tiled.h
index de469be..ae8fcc5 100644
--- a/src/tiled.h
+++ b/src/tiled.h
@@ -5,19 +5,19 @@
#define SCREEN_W 1280
#define SCREEN_H 720
-#define RENDER_DISTANCE 16
+#define RENDER_DISTANCE 4
-typedef struct Tiled {
+typedef struct {
TiledMap tiledMap;
float zoom;
-
+
// main viewport offset
Vector2 offset;
// offset passed to shader for rendering
Vector2 renderOffset;
// offset used to calculate which chunks to render
- int chunkOffset[2];
+ int chunkOffset[4];
int atlasSize[2];
int renderArea[2];
diff --git a/src/tiledmap.c b/src/tiledmap.c
index ea587cc..bb5a1fd 100644
--- a/src/tiledmap.c
+++ b/src/tiledmap.c
@@ -4,56 +4,7 @@
#include <unistd.h>
#include "tiledmap.h"
-
-const int endian = 1;
-#define is_bigendian() ( (*(char*)&endian) == 0 )
-
-void textureFromPixels(Texture2D *texOut, Color *pixels, int width, int height) {
- Image checkedIm = {
- .data = pixels,
- .width = width,
- .height = height,
- .format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8,
- .mipmaps = 1
- };
-
- *texOut = LoadTextureFromImage(checkedIm);
-}
-
-
-//! read a big endian bytes from file
-int readb(char * out, size_t noBytes, FILE * file) {
- if (!fread(out, (size_t)1, (size_t) noBytes, file))
- return 1;
-
- if (is_bigendian())
- return 0;
-
- int tmp;
- // reverse byte order
- for(int i = 0; i < noBytes/2; i++) {
- tmp = out[i];
- out[i] = out[noBytes-i-1];
- out[noBytes-i-1] = tmp;
- }
-
- return 0;
-}
-
-int writeb(char * in, size_t noBytes, FILE * file) {
- if (!is_bigendian()) {
- int tmp;
- // reverse byte order
- for(int i = 0; i < noBytes/2; i++) {
- tmp = in[i];
- in[i] = in[noBytes-i-1];
- in[noBytes-i-1] = tmp;
- }
-
- }
-
- return fwrite(in, (size_t)1, (size_t) noBytes, file);
-}
+#include "tiledio.h"
void buildChunkTree(TiledMap *tiledMap) {
// initialise chunk tree
@@ -143,7 +94,6 @@ void unloadChunk(TiledMap * tiledMap, CachedChunk * cached) {
//! load a chunk into the cache and return it
CachedChunk * loadChunk(TiledMap * tiledMap, int x, int y) {
- // TODO add caching for this
size_t chunkSizeBytes = tiledMap->chunkWidth * tiledMap->chunkHeight;
@@ -157,7 +107,6 @@ CachedChunk * loadChunk(TiledMap * tiledMap, int x, int y) {
cached->chunk = malloc(chunkSizeBytes);
fseek(tiledMap->file, cached->filePos, SEEK_SET);
fread(cached->chunk, 1, chunkSizeBytes, tiledMap->file);
- printf("loading chunk %d,%d, from %ld\n", x, y, cached->filePos);
}
return cached;
@@ -184,46 +133,49 @@ CachedChunk * createChunk(TiledMap *tiledMap, int x, int y, Chunk chunk) {
return cached;
}
-CachedChunk * createEmptyChunk(TiledMap * tiledMap, int x, int y) {
+CachedChunk * createEmptyChunkAt(TiledMap * tiledMap, int x, int y) {
Chunk chunk = calloc(tiledMap->chunkWidth*tiledMap->chunkHeight, 1);
- return createChunk(tiledMap, x, y, chunk);
+ return createChunk(tiledMap, x / tiledMap->chunkWidth, y / tiledMap->chunkHeight, chunk);
}
-Tile getChunkedTile(TiledMap *tiledMap, int x, int y) {
- // TODO put this calculation in function
+CachedChunk * loadChunkPosition(TiledMap *tiledMap, int x, int y, int * index) {
int inChunkX = x % tiledMap->chunkWidth;
int inChunkY = y % tiledMap->chunkHeight;
int chunkX = (x - inChunkX) / tiledMap->chunkWidth;
int chunkY = (y - inChunkY) / tiledMap->chunkHeight;
+ *index = inChunkY * tiledMap->chunkWidth + inChunkX;
+ return loadChunk(tiledMap, chunkX, chunkY);
+}
+
+Tile getChunkedTile(TiledMap *tiledMap, int x, int y) {
if (x < 0 || y < 0)
return 0;
- CachedChunk * cached = loadChunk(tiledMap, chunkX, chunkY);
+ int index;
+ CachedChunk * cached = loadChunkPosition(tiledMap, x, y, &index);
+
if (cached == NULL)
return 0;
if (cached->chunk == NULL)
return 0;
- Tile v = cached->chunk[inChunkY * tiledMap->chunkWidth + inChunkX];
- return v;
+ return cached->chunk[index];
}
Tile setChunkedTile(TiledMap * tiledMap, int x, int y, Tile value) {
- int inChunkX = x % tiledMap->chunkWidth;
- int inChunkY = y % tiledMap->chunkHeight;
- int chunkX = (x - inChunkX) / tiledMap->chunkWidth;
- int chunkY = (y - inChunkY) / tiledMap->chunkHeight;
+ if (x < 0 || y < 0)
+ return 0;
+
+ int index;
+ CachedChunk * cached = loadChunkPosition(tiledMap, x, y, &index);
- CachedChunk * cached = loadChunk(tiledMap, chunkX, chunkY);
if (cached == NULL)
- cached = createEmptyChunk(tiledMap, chunkX, chunkY);
+ cached = createEmptyChunkAt(tiledMap, x, y);
- cached->chunk[inChunkY * tiledMap->chunkWidth + inChunkX] = value;
+ cached->chunk[index] = value;
- // TODO do this when unloading
- //commitChunk(tiledMap, cached);
return value;
}
@@ -244,8 +196,6 @@ void writeTiledMapHeader(TiledMap tiledMap) {
writeb((char *) &tiledMap.atlasSize[1], 4, file);
fwrite(tiledMap.atlasData, 1, atlasSizeBytes, file);
- // since chunks are already directly written here, do not write anything else
- // TODO when caching, commit everything left in cache here
}
TiledMap openNewTiledMap(char * filename, Image atlas, int tileSize, int chunkWidth, int chunkHeight, int width, int height) {
diff --git a/src/tiledmap.h b/src/tiledmap.h
index 972a74d..7b819a2 100644
--- a/src/tiledmap.h
+++ b/src/tiledmap.h
@@ -6,12 +6,12 @@
typedef unsigned char Tile;
typedef Tile * Chunk;
-typedef struct CachedChunk {
+typedef struct {
long filePos;
Chunk chunk;
} CachedChunk;
-typedef struct ChunkedTiledMap {
+typedef struct {
FILE * file;
int chunkWidth;
int chunkHeight;