Cleaned tile map stuff.

This commit is contained in:
Kapendev 2024-10-11 06:38:59 +03:00
parent aea2b5b72e
commit 66b07f3684
2 changed files with 49 additions and 48 deletions

View file

@ -3,7 +3,10 @@ import parin;
// The game variables.
auto atlas = TextureId();
auto tileMap = TileMap();
auto map = TileMap();
auto playerTile = Tile(145, 16, 16);
auto playerPosition = Vec2();
auto playerSpeed = Vec2(120);
void ready() {
lockResolution(320, 180);
@ -11,12 +14,15 @@ void ready() {
// Load the `atlas.png` file from the assets folder.
atlas = loadTexture("atlas.png");
// Parse the tile map CSV file.
tileMap.parse("145,0,65\n21,22,23\n37,38,39\n53,54,55", 16, 16);
map.parse("-1,-1,-1\n21,22,23\n37,38,39\n53,54,55", 16, 16);
}
bool update(float dt) {
playerPosition += wasd * playerSpeed * Vec2(dt);
// Draw the tile map.
drawTileMap(atlas, tileMap, Vec2(), Camera(), DrawOptions(Vec2(2)));
auto options = DrawOptions(Vec2(2));
drawTileMap(atlas, map, Vec2(), Camera(), options);
drawTile(atlas, playerTile, playerPosition, options);
return false;
}

View file

@ -7,9 +7,8 @@
// ---
// TODO: Think about gaps in an atlas texture.
// TODO: Think about how to get the position of a tile.
// TODO: Think about maybe adding a texture id to things like sprites and tile maps.
// TODO: Add simple collision check in the tile map example.
// TODO: Think about the tile struct a bit.
// TODO: Update all the doc comments here.
/// The `tilemap` module provides a simple and fast tile map.
@ -25,9 +24,23 @@ public import joka.types;
@safe:
struct Tile {
int id;
Sz id;
int width;
int height;
@safe @nogc nothrow:
Sz row(Sz colCount) {
return id / colCount;
}
Sz col(Sz colCount) {
return id % colCount;
}
Rect area(Sz colCount) {
return Rect(col(colCount) * width, row(colCount) * height, width, height);
}
}
struct TileMap {
@ -38,18 +51,13 @@ struct TileMap {
int tileHeight;
alias data this;
@safe:
@safe @nogc nothrow:
/// Returns true if the tile map has not been loaded.
bool isEmpty() {
return data.length == 0;
}
/// Returns the tile size of the tile map.
Vec2 tileSize() {
return Vec2(tileWidth, tileHeight);
}
int width() {
return cast(int) (estimatedMaxColCount * tileWidth);
}
@ -63,6 +71,11 @@ struct TileMap {
return Vec2(width, height);
}
/// Returns the tile size of the tile map.
Vec2 tileSize() {
return Vec2(tileWidth, tileHeight);
}
Fault parse(IStr csv, int tileWidth, int tileHeight) {
if (csv.length == 0) return Fault.invalid;
this.tileWidth = tileWidth;
@ -88,6 +101,10 @@ struct TileMap {
}
}
Vec2 findTilePosition(TileMap map, Vec2 position, Sz row, Sz col, DrawOptions options = DrawOptions()) {
return Vec2(position.x + col * map.tileWidth * options.scale.x, position.y + row * map.tileHeight * options.scale.y);
}
Result!TileMap toTileMap(IStr csv, int tileWidth, int tileHeight) {
auto value = TileMap();
auto fault = value.parse(csv, tileWidth, tileHeight);
@ -106,59 +123,37 @@ Result!TileMap loadRawTileMap(IStr path, int tileWidth, int tileHeight) {
}
void drawTile(Texture texture, Tile tile, Vec2 position, DrawOptions options = DrawOptions()) {
auto gridWidth = texture.width / tile.width;
auto gridHeight = texture.height / tile.height;
if (gridWidth == 0 || gridHeight == 0) {
return;
}
auto row = tile.id / gridWidth;
auto col = tile.id % gridWidth;
auto area = Rect(col * tile.width, row * tile.height, tile.width, tile.height);
drawTextureArea(texture, area, position, options);
drawTextureArea(texture, tile.area(texture.width / tile.width), position, options);
}
void drawTile(TextureId texture, Tile tile, Vec2 position, DrawOptions options = DrawOptions()) {
drawTile(texture.getOr(), tile, position, options);
}
void drawTileMap(Texture texture, TileMap tileMap, Vec2 position, Camera camera, DrawOptions options = DrawOptions()) {
void drawTileMap(Texture texture, TileMap map, Vec2 position, Camera camera, DrawOptions options = DrawOptions()) {
auto area = camera.area;
auto topLeft = area.topLeftPoint;
auto bottomRight = area.bottomRightPoint;
auto targetTileWidth = cast(int) (tileMap.tileWidth * options.scale.x);
auto targetTileHeight = cast(int) (tileMap.tileHeight * options.scale.y);
auto targetTileSize = Vec2(targetTileWidth, targetTileHeight);
auto row1 = 0;
auto col1 = 0;
auto row2 = 0;
auto col2 = 0;
if (camera.isAttached) {
row1 = cast(int) floor(clamp((topLeft.y - position.y) / targetTileHeight, 0, tileMap.rowCount));
col1 = cast(int) floor(clamp((topLeft.x - position.x) / targetTileWidth, 0, tileMap.colCount));
row2 = cast(int) floor(clamp((bottomRight.y - position.y) / targetTileHeight + 1, 0, tileMap.rowCount));
col2 = cast(int) floor(clamp((bottomRight.x - position.x) / targetTileWidth + 1, 0, tileMap.colCount));
} else {
row1 = cast(int) 0;
col1 = cast(int) 0;
row2 = cast(int) tileMap.rowCount;
col2 = cast(int) tileMap.colCount;
}
auto targetTileWidth = cast(int) (map.tileWidth * options.scale.x);
auto targetTileHeight = cast(int) (map.tileHeight * options.scale.y);
if (row1 == row2 || col1 == col2) {
return;
}
auto row1 = cast(int) floor(clamp((topLeft.y - position.y) / targetTileHeight, 0, map.rowCount));
auto col1 = cast(int) floor(clamp((topLeft.x - position.x) / targetTileWidth, 0, map.colCount));
auto row2 = cast(int) floor(clamp((bottomRight.y - position.y) / targetTileHeight + 1, 0, map.rowCount));
auto col2 = cast(int) floor(clamp((bottomRight.x - position.x) / targetTileWidth + 1, 0, map.colCount));
if (row1 == row2 || col1 == col2) return;
foreach (row; row1 .. row2) {
foreach (col; col1 .. col2) {
if (tileMap[row, col] == -1) continue;
auto tile = Tile(tileMap[row, col], tileMap.tileWidth, tileMap.tileHeight);
auto tilePosition = position + Vec2(col, row) * targetTileSize;
if (map[row, col] == -1) continue;
auto tile = Tile(map[row, col], map.tileWidth, map.tileHeight);
auto tilePosition = position + Vec2(col * targetTileWidth, row * targetTileHeight);
drawTile(texture, tile, tilePosition, options);
}
}
}
void drawTileMap(TextureId texture, TileMap tileMap, Vec2 position, Camera camera, DrawOptions options = DrawOptions()) {
drawTileMap(texture.getOr(), tileMap, position, camera, options);
void drawTileMap(TextureId texture, TileMap map, Vec2 position, Camera camera, DrawOptions options = DrawOptions()) {
drawTileMap(texture.getOr(), map, position, camera, options);
}