summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordavidovski <david@davidovski.xyz>2023-07-22 00:50:32 +0200
committerdavidovski <david@davidovski.xyz>2023-07-22 00:50:32 +0200
commit5ec62c0a2a0357a79f92b8bb37f67272e7f910ff (patch)
tree26e45f549e27999f9bc2d6f5d62461894223230d
parent2dcefdb4565f96b808ed01ce1d96a802b8f73931 (diff)
loading map data from chunks rather than tilelayout
-rw-r--r--makefile5
-rw-r--r--src/chunkedtiledmap.c114
-rw-r--r--src/chunkedtiledmap.h14
-rw-r--r--src/editor.c31
-rw-r--r--src/kdtree.c4
-rw-r--r--src/kdtree.h3
-rw-r--r--src/tiled.c47
-rw-r--r--src/tiled.h6
-rw-r--r--src/tiledmap.c2
9 files changed, 156 insertions, 70 deletions
diff --git a/makefile b/makefile
index 28fbdab..928632f 100644
--- a/makefile
+++ b/makefile
@@ -3,6 +3,7 @@ FLAGS=-lm -lraylib -ggdb
.DEFAULT_GOAL := editor
-editor: src/*.c src/editor.c
- ${CC} src/*.c -o editor ${FLAGS}
+EDITOR_SOURCE=src/chunkedtiledmap.c src/editor.c src/kdtree.c src/tiled.c
+editor: ${EDITOR_SOURCE}
+ ${CC} ${EDITOR_SOURCE} -o editor ${FLAGS}
diff --git a/src/chunkedtiledmap.c b/src/chunkedtiledmap.c
index ce6be57..a3019af 100644
--- a/src/chunkedtiledmap.c
+++ b/src/chunkedtiledmap.c
@@ -2,10 +2,26 @@
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
-#include <wchar.h>
#include "chunkedtiledmap.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))
@@ -41,17 +57,25 @@ int writeb(char * in, size_t noBytes, FILE * file) {
}
void buildChunkTree(ChunkedTiledMap *tiledMap) {
- int noChunks;
+ // initialise chunk tree
+ tiledMap->chunkTree = NULL;
- // 4 bytes for number of chunks
- readb((char *)&noChunks, 4, tiledMap->file);
size_t chunkSizeBytes = tiledMap->chunkWidth * tiledMap->chunkHeight;
- for (int n = 0; n < noChunks; n++) {
+ // calculate how much space there is until the end of the file
+ // TODO save the number of chunks total to avoid having to jump around to find referenceso
+ // or just keep reading chunks until eof or other descriptor
+ long chunksStart = ftell(tiledMap->file);
+ fseek(tiledMap->file, 0, SEEK_END);
+ long totalChunksSize = ftell(tiledMap->file) - chunksStart;
+
+ fseek(tiledMap->file, chunksStart, SEEK_SET);
+
+ for (int n = 0; n < totalChunksSize; n += chunkSizeBytes + 8) {
int x, y;
readb((char *)&x, 4, tiledMap->file);
readb((char *)&y, 4, tiledMap->file);
long pointer = ftell(tiledMap->file);
- // TODO casting to pointer here is maybe unsafe
+
kdtree_insert(&tiledMap->chunkTree, x, y, (char *) pointer);
fseek(tiledMap->file, chunkSizeBytes, SEEK_CUR);
}
@@ -85,22 +109,40 @@ ChunkedTiledMap openTiledMap(char * filename) {
tiledMap.atlasData = malloc(atlasSizeBytes);
fread(tiledMap.atlasData, atlasSizeBytes, (size_t) 1, file);
+ tiledMap.tileCount = tiledMap.atlasSize[0]*tiledMap.atlasSize[1] + 1;
+
buildChunkTree(&tiledMap);
return tiledMap;
}
+//! write a chunk to the file
+char* writeChunk(ChunkedTiledMap *tiledMap, int x, int y, char * chunk) {
+ size_t chunkSizeBytes = tiledMap->chunkWidth * tiledMap->chunkHeight;
+
+
+ long pos = (long) kdtree_search(tiledMap->chunkTree, x, y);
+
+ fseek(tiledMap->file, pos, SEEK_SET);
+ fwrite(chunk, 1, chunkSizeBytes, tiledMap->file);
+ return chunk;
+}
+
char* loadChunk(ChunkedTiledMap tiledMap, int x, int y) {
// TODO add caching for this
size_t chunkSizeBytes = tiledMap.chunkWidth * tiledMap.chunkHeight;
char * chunk = malloc(chunkSizeBytes);
long pos = (long) kdtree_search(tiledMap.chunkTree, x, y);
+ // if this chunk is not indexed, return NULL
+ if (pos == 0)
+ return NULL;
+
fseek(tiledMap.file, pos, SEEK_SET);
fread(chunk, 1, chunkSizeBytes, tiledMap.file);
return chunk;
}
-void appendChunk(ChunkedTiledMap *tiledMap, int x, int y, char * chunk) {
+char * appendChunk(ChunkedTiledMap *tiledMap, int x, int y, char * chunk) {
// TODO does this actually need tiledMap as a pointer
size_t chunkSizeBytes = tiledMap->chunkWidth * tiledMap->chunkHeight;
@@ -108,11 +150,51 @@ void appendChunk(ChunkedTiledMap *tiledMap, int x, int y, char * chunk) {
// calculate position before writing
long pos = ftell(tiledMap->file) + 8;
- kdtree_insert(&tiledMap->chunkTree, x, y, chunk);
+ kdtree_insert(&tiledMap->chunkTree, x, y, (char *)pos);
+ int chunkx, chunky;
writeb((char *) &x, 4, tiledMap->file);
writeb((char *) &y, 4, tiledMap->file);
fwrite(chunk, 1, chunkSizeBytes, tiledMap->file);
+
+ return chunk;
+}
+
+char * appendEmptyChunk(ChunkedTiledMap * tiledMap, int x, int y) {
+ char * chunk = calloc(tiledMap->chunkWidth*tiledMap->chunkHeight, 1);
+ return appendChunk(tiledMap, x, y, chunk);
+}
+
+char getChunkedTile(ChunkedTiledMap tiledMap, int x, int y) {
+ // TODO put this calculation in function
+ int inChunkX = x % tiledMap.chunkWidth;
+ int inChunkY = y % tiledMap.chunkHeight;
+ int chunkX = (x - inChunkX) / tiledMap.chunkWidth;
+ int chunkY = (y - inChunkY) / tiledMap.chunkHeight;
+
+ char * chunk = loadChunk(tiledMap, chunkX, chunkY);
+ if (chunk == NULL)
+ return 0;
+
+ char v = chunk[inChunkY * tiledMap.chunkWidth + inChunkX];
+ return v;
+}
+
+char setChunkedTile(ChunkedTiledMap * tiledMap, int x, int y, char value) {
+ int inChunkX = x % tiledMap->chunkWidth;
+ int inChunkY = y % tiledMap->chunkHeight;
+ int chunkX = (x - inChunkX) / tiledMap->chunkWidth;
+ int chunkY = (y - inChunkY) / tiledMap->chunkHeight;
+
+ char * chunk = loadChunk(*tiledMap, chunkX, chunkY);
+ if (chunk == NULL)
+ chunk = appendEmptyChunk(tiledMap, chunkX, chunkY);
+
+ chunk[inChunkY * tiledMap->chunkWidth + inChunkX] = value;
+
+ writeChunk(tiledMap, chunkX, chunkY, chunk);
+
+ return value;
}
@@ -136,7 +218,7 @@ void writeTiledMapHeader(ChunkedTiledMap tiledMap) {
// TODO when caching, commit everything left in cache here
}
-ChunkedTiledMap newTiledMap(char * filename, Image atlas, int tileSize, int chunkWidth, int chunkHeight, int width, int height) {
+ChunkedTiledMap openNewTiledMap(char * filename, Image atlas, int tileSize, int chunkWidth, int chunkHeight, int width, int height) {
ChunkedTiledMap tiledMap;
tiledMap.chunkWidth = chunkWidth;
tiledMap.chunkHeight = chunkHeight;
@@ -147,8 +229,11 @@ ChunkedTiledMap newTiledMap(char * filename, Image atlas, int tileSize, int chun
tiledMap.atlasSize[1] = atlas.height / tileSize;
tiledMap.atlasData = LoadImageColors(atlas);
+ tiledMap.tileCount = tiledMap.atlasSize[0]*tiledMap.atlasSize[1] + 1;
- if (!(tiledMap.file = fopen(filename, "r+b"))) {
+ tiledMap.chunkTree = NULL;
+
+ if (!(tiledMap.file = fopen(filename, "wb"))) {
fprintf(stderr, "Failed to load %s\n", filename);
}
@@ -159,6 +244,13 @@ ChunkedTiledMap newTiledMap(char * filename, Image atlas, int tileSize, int chun
appendChunk(&tiledMap, x, y, chunk);
}
}
+
+ // reopen the file in read+write mode
+ fclose(tiledMap.file);
+
+ if (!(tiledMap.file = fopen(filename, "r+b"))) {
+ fprintf(stderr, "Failed to load %s\n", filename);
+ }
return tiledMap;
}
@@ -169,5 +261,3 @@ void closeTiledMap(ChunkedTiledMap tiledMap) {
fclose(tiledMap.file);
}
-
-
diff --git a/src/chunkedtiledmap.h b/src/chunkedtiledmap.h
index 0d5c5d0..8bc2aaa 100644
--- a/src/chunkedtiledmap.h
+++ b/src/chunkedtiledmap.h
@@ -1,9 +1,6 @@
#include <raylib.h>
#include "kdtree.h"
-const int i = 1;
-#define is_bigendian() ( (*(char*)&i) == 0 )
-
typedef struct ChunkedTiledMap {
FILE * file;
int chunkWidth;
@@ -14,3 +11,14 @@ typedef struct ChunkedTiledMap {
Color * atlasData;
kdtree_t * chunkTree;
} ChunkedTiledMap;
+
+void textureFromPixels(Texture2D *texOut, Color *pixels, int width, int height);
+ChunkedTiledMap openTiledMap(char * filename);
+char * loadChunk(ChunkedTiledMap tiledMap, int x, int y);
+char getChunkedTile(ChunkedTiledMap tiledMap, int x, int y);
+char setChunkedTile(ChunkedTiledMap * tiledMap, int x, int y, char value);
+char * appendChunk(ChunkedTiledMap * tiledMap, int x, int y, char * chunk);
+void writeTiledMapHeader(ChunkedTiledMap tiledMap);
+ChunkedTiledMap openNewTiledMap(char * filename, Image atlas, int tileSize, int chunkWidth, int chunkHeight, int width, int height);
+void closeTiledMap(ChunkedTiledMap tiledMap);
+
diff --git a/src/editor.c b/src/editor.c
index eddd6ad..46afe37 100644
--- a/src/editor.c
+++ b/src/editor.c
@@ -22,7 +22,7 @@ void drawOverlay(Tiled tiled) {
}
void modifyTile(Tiled *tiled, int tile) {
- setTiledMapTile(tiled->tiledMap, selectedTile, tile);
+ setChunkedTile(&tiled->tiledMap, selectedTile[0], selectedTile[1], tile);
redrawTiledMap(*tiled);
}
@@ -34,10 +34,10 @@ void setDrawMode(Tiled *tiled, int tile) {
void handleInputs(Tiled *tiled) {
if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT))
- setDrawMode(tiled, getTiledMapTile(tiled->tiledMap, selectedTile) + 1);
+ setDrawMode(tiled, getChunkedTile(tiled->tiledMap, selectedTile[0], selectedTile[1]) + 1);
if (IsMouseButtonPressed(MOUSE_BUTTON_RIGHT))
- setDrawMode(tiled, getTiledMapTile(tiled->tiledMap, selectedTile) - 1);
+ setDrawMode(tiled, getChunkedTile(tiled->tiledMap, selectedTile[0], selectedTile[1]) - 1);
if (IsMouseButtonPressed(MOUSE_BUTTON_MIDDLE))
setDrawMode(tiled, 0);
@@ -59,8 +59,8 @@ void update(Tiled *tiled) {
updateTiledCamera(tiled);
Vector2 mousePos = GetMousePosition();
Vector2 mapPos = translateTiledPosition(*tiled, mousePos);
- if (mapPos.x >= 0 && mapPos.x < tiled->tiledMap.width
- && mapPos.y >= 0 && mapPos.y < tiled->tiledMap.height) {
+ if (mapPos.x >= 0 && mapPos.x < tiled->mapSize[0]
+ && mapPos.y >= 0 && mapPos.y < tiled->mapSize[1]) {
lastSelectedTile[0] = selectedTile[0];
lastSelectedTile[1] = selectedTile[1];
selectedTile[0] = mapPos.x;
@@ -69,7 +69,7 @@ void update(Tiled *tiled) {
handleInputs(tiled);
}
-TiledMap launchEditor(TiledMap tiledMap) {
+ChunkedTiledMap launchEditor(ChunkedTiledMap tiledMap) {
SetConfigFlags(FLAG_WINDOW_RESIZABLE);
InitWindow(SCREEN_W, SCREEN_H, "tiled");
@@ -92,7 +92,7 @@ TiledMap launchEditor(TiledMap tiledMap) {
unloadTiled(&tiled);
CloseWindow();
- return tiled.tiledMap;
+ return tiledMap;
}
void printUsage(char *progname) {
@@ -104,11 +104,14 @@ int main(int argc, char *argv[]) {
char * tiledFilePath;
const char * atlasFilePath = NULL;
int tileSize = 16;
- int mapSize = 16;
+ int mapSize = 2;
+ int chunkSize = 2;
int flags, opt;
- while ((opt = getopt(argc, argv, "s:a:h")) != -1) {
+ while ((opt = getopt(argc, argv, "c:s:a:h")) != -1) {
switch (opt) {
+ case 'c':
+ chunkSize = atoi(optarg);
case 's':
mapSize = atoi(optarg);
case 't':
@@ -123,7 +126,7 @@ int main(int argc, char *argv[]) {
tiledFilePath = argv[optind];
- TiledMap tiledMap;
+ ChunkedTiledMap tiledMap;
if (access(tiledFilePath, F_OK)) {
if (atlasFilePath == NULL) {
fprintf(stderr, "Atlas file must be specified!\n");
@@ -131,11 +134,11 @@ int main(int argc, char *argv[]) {
}
Image atlasImage = LoadImage(atlasFilePath);
- tiledMap = newTiledMap(atlasImage, tileSize, mapSize, mapSize);
+ tiledMap = openNewTiledMap(tiledFilePath, atlasImage, tileSize, chunkSize, chunkSize, mapSize, mapSize);
} else {
- tiledMap = loadTiledMap(tiledFilePath);
+ tiledMap = openTiledMap(tiledFilePath);
}
- TiledMap editedTiledMap = launchEditor(tiledMap);
- saveTiledMap(tiledFilePath, tiledMap);
+ launchEditor(tiledMap);
+ closeTiledMap(tiledMap);
}
diff --git a/src/kdtree.c b/src/kdtree.c
index ab5aa98..551bc5c 100644
--- a/src/kdtree.c
+++ b/src/kdtree.c
@@ -1,5 +1,9 @@
#include "kdtree.h"
+void print_node(kdtree_t *tree) {
+ printf("[%d,%d] %ld\n", tree->x, tree->y, (long)tree->value);
+}
+
kdtree_t * kdtree_create(int x, int y, char * value) {
kdtree_t * tree = malloc(sizeof(kdtree_t));
tree->x = x;
diff --git a/src/kdtree.h b/src/kdtree.h
index e121442..a5c178e 100644
--- a/src/kdtree.h
+++ b/src/kdtree.h
@@ -31,3 +31,6 @@ int kdtree_fwrite(kdtree_t *root, FILE *file);
//! read a tree from file
int kdtree_fread(kdtree_t **root, FILE *file);
+//! print a single node (debug purposes)
+void print_node(kdtree_t *tree);
+
diff --git a/src/tiled.c b/src/tiled.c
index 43afa7b..f490d6a 100644
--- a/src/tiled.c
+++ b/src/tiled.c
@@ -3,6 +3,8 @@
#include "tiled.h"
+int alpha =0;
+
void updateCamera(Vector2 *offset, float *zoom) {
if (IsKeyDown(KEY_UP)) offset->y += 16.0f / *zoom;
if (IsKeyDown(KEY_DOWN)) offset->y -= 16.0f/ *zoom;
@@ -15,6 +17,7 @@ void updateCamera(Vector2 *offset, float *zoom) {
void updateTiledCamera(Tiled *tiled) {
updateCamera(&tiled->offset, &tiled->zoom);
+ alpha++;
}
@@ -47,12 +50,11 @@ Vector2 translateTiledScreenPosition(Tiled tiled, Vector2 tiledPos) {
void redrawTiledMap(Tiled tiled) {
BeginTextureMode(tiled.tilemapTexture);
- for (int y = 0; y < tiled.tiledMap.height; y++) {
- for (int x = 0; x < tiled.tiledMap.width; x++) {
- int i = (tiled.tiledMap.height - y - 1)*tiled.tiledMap.width + x;
+ for (int y = 0; y < tiled.mapSize[1]; y++) {
+ for (int x = 0; x < tiled.mapSize[0]; x++) {
+ unsigned char v = getChunkedTile(tiled.tiledMap, x, tiled.mapSize[1] - y - 1);
Color c = (Color){
- tiled.tiledMap.tilelayout[i],
- 0, 0, 255
+ v, 0, 0, 255
};
DrawPixel(x, y, c);
}
@@ -62,17 +64,18 @@ void redrawTiledMap(Tiled tiled) {
}
-Tiled initTiled(TiledMap tiledMap) {
+Tiled initTiled(ChunkedTiledMap tiledMap) {
Tiled tiled;
tiled.tiledMap = tiledMap;
tiled.offset = (Vector2) {0, 0};
tiled.zoom = 64;
- tiled.mapSize[0] = tiledMap.width;
- tiled.mapSize[1] = tiledMap.height;
+ // TODO mapSize is obsolete, should be visible map size
+ tiled.mapSize[0] = tiledMap.chunkWidth * 20;
+ tiled.mapSize[1] = tiledMap.chunkHeight * 20;
tiled.targetTexture = LoadRenderTexture(1, 1);
- tiled.tilemapTexture = LoadRenderTexture(tiledMap.width, tiledMap.width);
+ tiled.tilemapTexture = LoadRenderTexture(tiled.mapSize[0], tiled.mapSize[1]);
tiled.atlasSize[0] = tiledMap.atlasSize[0];
tiled.atlasSize[1] = tiledMap.atlasSize[1];
@@ -120,29 +123,3 @@ void drawTiled(Tiled *tiled) {
//(Vector2){0, 0},
//WHITE);
}
-
-int launchTiledView() {
- SetConfigFlags(FLAG_WINDOW_RESIZABLE);
- InitWindow(SCREEN_W, SCREEN_H, "tiled");
-
- TiledMap tiledMap = loadTiledMap("map.tiles");
- Tiled tiled = initTiled(tiledMap);
-
- while (!WindowShouldClose()) {
- updateTiledCamera(&tiled);
-
- BeginDrawing();
-
- ClearBackground(LIGHTGRAY);
-
- drawTiled(&tiled);
- DrawFPS(16, 16);
-
- EndDrawing();
- }
-
- unloadTiled(&tiled);
-
- CloseWindow();
- return 0;
-}
diff --git a/src/tiled.h b/src/tiled.h
index 9890a72..11518e7 100644
--- a/src/tiled.h
+++ b/src/tiled.h
@@ -1,12 +1,12 @@
#include <raylib.h>
-#include "tiledmap.h"
+#include "chunkedtiledmap.h"
#define SCREEN_W 1280
#define SCREEN_H 720
typedef struct Tiled {
- TiledMap tiledMap;
+ ChunkedTiledMap tiledMap;
float zoom;
Vector2 offset;
@@ -33,7 +33,7 @@ typedef struct Tiled {
void updateTiledCamera(Tiled *tiled);
Vector2 translateTiledPosition(Tiled tiled, Vector2 screenPos);
Vector2 translateTiledScreenPosition(Tiled tiled, Vector2 tiledPos);
-Tiled initTiled(TiledMap tiledMap);
+Tiled initTiled(ChunkedTiledMap tiledMap);
void drawTiled(Tiled *tiled);
void unloadTiled(Tiled *tiled);
void redrawTiledMap(Tiled tiled);
diff --git a/src/tiledmap.c b/src/tiledmap.c
index 69dcdaa..e274a6e 100644
--- a/src/tiledmap.c
+++ b/src/tiledmap.c
@@ -111,7 +111,7 @@ TiledMap loadTiledMap(char * filename) {
return tiledMap;
}
-TiledMap newTiledMap(Image atlas, int tileSize, int width, int height) {
+TiledMap openNewTiledMap(Image atlas, int tileSize, int width, int height) {
TiledMap tiledMap;
tiledMap.width = width;
tiledMap.height = height;