Starting on shaped tile hitboxes
This commit is contained in:
@ -33,6 +33,7 @@
|
|||||||
"overworld.tsx"
|
"overworld.tsx"
|
||||||
],
|
],
|
||||||
"project": "map project.tiled-project",
|
"project": "map project.tiled-project",
|
||||||
|
"property.type": "int",
|
||||||
"recentFiles": [
|
"recentFiles": [
|
||||||
"overworld.tsx",
|
"overworld.tsx",
|
||||||
"map.tmj",
|
"map.tmj",
|
||||||
|
24
data/map.tmj
24
data/map.tmj
@ -411,17 +411,11 @@
|
|||||||
"id":3,
|
"id":3,
|
||||||
"name":"Object Layer 1",
|
"name":"Object Layer 1",
|
||||||
"objects":[
|
"objects":[
|
||||||
{
|
|
||||||
"id":3,
|
|
||||||
"template":"templates\/NPC.tx",
|
|
||||||
"x":6551.3106060606,
|
|
||||||
"y":6829.13636363636
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"id":4,
|
"id":4,
|
||||||
"template":"templates\/NPC.tx",
|
"template":"templates\/NPC.tx",
|
||||||
"x":6649.66666666667,
|
"x":6650.41666666667,
|
||||||
"y":6741.58333333334
|
"y":6753.58333333334
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"gid":257,
|
"gid":257,
|
||||||
@ -438,14 +432,14 @@
|
|||||||
{
|
{
|
||||||
"id":7,
|
"id":7,
|
||||||
"template":"templates\/NPC.tx",
|
"template":"templates\/NPC.tx",
|
||||||
"x":6497,
|
"x":6700.25,
|
||||||
"y":6942
|
"y":6838.75
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id":8,
|
"id":8,
|
||||||
"template":"templates\/NPC.tx",
|
"template":"templates\/NPC.tx",
|
||||||
"x":6640,
|
"x":6559,
|
||||||
"y":6817
|
"y":6754.75
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id":9,
|
"id":9,
|
||||||
@ -456,8 +450,8 @@
|
|||||||
{
|
{
|
||||||
"id":10,
|
"id":10,
|
||||||
"template":"templates\/NPC.tx",
|
"template":"templates\/NPC.tx",
|
||||||
"x":6781,
|
"x":6697,
|
||||||
"y":6746.33333333333
|
"y":6769.08333333333
|
||||||
}],
|
}],
|
||||||
"opacity":1,
|
"opacity":1,
|
||||||
"type":"objectgroup",
|
"type":"objectgroup",
|
||||||
@ -466,7 +460,7 @@
|
|||||||
"y":0
|
"y":0
|
||||||
}],
|
}],
|
||||||
"nextlayerid":6,
|
"nextlayerid":6,
|
||||||
"nextobjectid":11,
|
"nextobjectid":13,
|
||||||
"orientation":"orthogonal",
|
"orientation":"orthogonal",
|
||||||
"renderorder":"right-down",
|
"renderorder":"right-down",
|
||||||
"tiledversion":"1.11.1",
|
"tiledversion":"1.11.1",
|
||||||
|
@ -1,6 +1,31 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<tileset version="1.10" tiledversion="1.11.1" name="overworld" tilewidth="16" tileheight="16" tilecount="256" columns="16">
|
<tileset version="1.10" tiledversion="1.11.1" name="overworld" tilewidth="16" tileheight="16" tilecount="256" columns="16">
|
||||||
<image source="tilemap.png" width="256" height="256"/>
|
<image source="tilemap.png" width="256" height="256"/>
|
||||||
|
<tile id="1">
|
||||||
|
<properties>
|
||||||
|
<property name="solid" type="int" value="4"/>
|
||||||
|
</properties>
|
||||||
|
</tile>
|
||||||
|
<tile id="3">
|
||||||
|
<properties>
|
||||||
|
<property name="solid" type="int" value="5"/>
|
||||||
|
</properties>
|
||||||
|
</tile>
|
||||||
|
<tile id="18">
|
||||||
|
<properties>
|
||||||
|
<property name="solid" type="int" value="1"/>
|
||||||
|
</properties>
|
||||||
|
</tile>
|
||||||
|
<tile id="33">
|
||||||
|
<properties>
|
||||||
|
<property name="solid" type="int" value="2"/>
|
||||||
|
</properties>
|
||||||
|
</tile>
|
||||||
|
<tile id="35">
|
||||||
|
<properties>
|
||||||
|
<property name="solid" type="int" value="3"/>
|
||||||
|
</properties>
|
||||||
|
</tile>
|
||||||
<tile id="54">
|
<tile id="54">
|
||||||
<objectgroup draworder="index" id="3">
|
<objectgroup draworder="index" id="3">
|
||||||
<object id="3" x="5.04743" y="5.92885" width="7.93676" height="6.0751"/>
|
<object id="3" x="5.04743" y="5.92885" width="7.93676" height="6.0751"/>
|
||||||
|
@ -55,33 +55,77 @@ void entityUpdate(entity_t *entity) {
|
|||||||
fixed248_t halfTileWH = FIXED248(TILE_WIDTH_HEIGHT / 2, 0);
|
fixed248_t halfTileWH = FIXED248(TILE_WIDTH_HEIGHT / 2, 0);
|
||||||
fixed248_t selfCircR = halfTileWH;
|
fixed248_t selfCircR = halfTileWH;
|
||||||
|
|
||||||
// Check for collisions with the world boundaries
|
// Check for collisions with tiles
|
||||||
|
uint8_t tileChecks = ENTITY_TILE_COLISSION_RESOLUTION_COUNT;
|
||||||
|
do {
|
||||||
|
// loop to resolve tile collisions multiple times to handle sliding
|
||||||
|
// correctly
|
||||||
|
bool tileResolved = false;
|
||||||
|
|
||||||
// Check for collisions with tile
|
// Compute affected tile range
|
||||||
fixed248_t tileStartX = fx248Floor(newX - halfTileWH);
|
fixed248_t tileStartX = fx248Floor(fx248Divfx248(
|
||||||
fixed248_t tileStartY = fx248Floor(newY - halfTileWH);
|
(newX - halfTileWH), FIXED248(TILE_WIDTH_HEIGHT, 0)
|
||||||
fixed248_t tileEndX = fx248Ceil(newX + halfTileWH);
|
));
|
||||||
fixed248_t tileEndY = fx248Ceil(newY + halfTileWH);
|
fixed248_t tileStartY = fx248Floor(fx248Divfx248(
|
||||||
|
(newY - halfTileWH), FIXED248(TILE_WIDTH_HEIGHT, 0)
|
||||||
|
));
|
||||||
|
fixed248_t tileEndX = fx248Ceil(fx248Divfx248(
|
||||||
|
(newX + halfTileWH), FIXED248(TILE_WIDTH_HEIGHT, 0)
|
||||||
|
));
|
||||||
|
fixed248_t tileEndY = fx248Ceil(fx248Divfx248(
|
||||||
|
(newY + halfTileWH), FIXED248(TILE_WIDTH_HEIGHT, 0)
|
||||||
|
));
|
||||||
|
|
||||||
for(fixed248_t y = tileStartY; y <= tileEndY; y+= FIXED248_ONE) {
|
// For each tile
|
||||||
for(fixed248_t x = tileStartX; x <= tileEndX; x+= FIXED248_ONE) {
|
for(fixed248_t y = tileStartY; y <= tileEndY; y += FIXED248_ONE) {
|
||||||
//
|
for(fixed248_t x = tileStartX; x <= tileEndX; x += FIXED248_ONE) {
|
||||||
|
uint16_t tileX = fx248Tou16(x);
|
||||||
|
uint16_t tileY = fx248Tou16(y);
|
||||||
|
uint16_t chunkX = tileX / CHUNK_WIDTH;
|
||||||
|
uint16_t chunkY = tileY / CHUNK_HEIGHT;
|
||||||
|
chunk_t *chunk = chunkGetChunkAt(chunkX, chunkY);
|
||||||
|
if(chunk == NULL) continue;
|
||||||
|
|
||||||
|
uint8_t chunkTileX = tileX % CHUNK_WIDTH;
|
||||||
|
uint8_t chunkTileY = tileY % CHUNK_HEIGHT;
|
||||||
|
tile_t tile = chunk->tilesBase[chunkTileY * CHUNK_WIDTH + chunkTileX];
|
||||||
|
|
||||||
|
tilesolidtype_t solidType = (
|
||||||
|
tile < TILE_META_DATA_COUNT ? TILE_META_DATA[tile].solidType :
|
||||||
|
TILE_SOLID_NONE
|
||||||
|
);
|
||||||
|
|
||||||
|
collisionresult_t collision;
|
||||||
|
switch(solidType) {
|
||||||
|
case TILE_SOLID_FULL:
|
||||||
|
collision = physicsCheckCircleAABB(
|
||||||
|
newX, newY, selfCircR,
|
||||||
|
fx248Mulfx248(x, FIXED248(TILE_WIDTH_HEIGHT, 0)),
|
||||||
|
fx248Mulfx248(y, FIXED248(TILE_WIDTH_HEIGHT, 0)),
|
||||||
|
FIXED248(TILE_WIDTH_HEIGHT, 0),
|
||||||
|
FIXED248(TILE_WIDTH_HEIGHT, 0)
|
||||||
|
);
|
||||||
|
|
||||||
|
default:
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if(collision.hit && collision.depth > FIXED248(0, 1)) {
|
||||||
|
fixed248_t slideX = fx248Mulfx248(
|
||||||
|
collision.normalX, collision.depth
|
||||||
|
);
|
||||||
|
fixed248_t slideY = fx248Mulfx248(
|
||||||
|
collision.normalY, collision.depth
|
||||||
|
);
|
||||||
|
newX -= slideX;
|
||||||
|
newY -= slideY;
|
||||||
|
tileResolved = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
if(!tileResolved) break; // no more overlaps
|
||||||
|
} while(--tileChecks > 0);
|
||||||
// uint16_t tileStartX = fx248Tou16(fx248Floor(newX - halfTileWH));
|
|
||||||
// uint16_t tileStartY = fx248Tou16(fx248Floor(newY - halfTileWH));
|
|
||||||
// uint16_t tileEndX = fx248Tou16(fx248Ceil(newX + halfTileWH)) + 1;
|
|
||||||
// uint16_t tileEndY = fx248Tou16(fx248Ceil(newY + halfTileWH)) + 1;
|
|
||||||
|
|
||||||
// printf("Checking tiles between (%u, %u) and (%u, %u)\n",
|
|
||||||
// tileStartX, tileStartY, tileEndX, tileEndY
|
|
||||||
// );
|
|
||||||
// for(uint16_t tileY = tileStartY; tileY <= tileEndY; tileY++) {
|
|
||||||
// for(uint16_t tileX = tileStartX; tileX <= tileEndX; tileX++) {
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
// Check for collisions with other entities
|
// Check for collisions with other entities
|
||||||
entity_t *otherEntity = ENTITIES;
|
entity_t *otherEntity = ENTITIES;
|
||||||
@ -98,8 +142,8 @@ void entityUpdate(entity_t *entity) {
|
|||||||
if(!collision.hit) continue;
|
if(!collision.hit) continue;
|
||||||
|
|
||||||
// Collision with entity detected. Slide out of collision.
|
// Collision with entity detected. Slide out of collision.
|
||||||
fixed248_t slideX = fx248Mulf32(collision.normalX, fx248Tof32(collision.depth));
|
fixed248_t slideX = fx248Mulfx248(collision.normalX, collision.depth);
|
||||||
fixed248_t slideY = fx248Mulf32(collision.normalY, fx248Tof32(collision.depth));
|
fixed248_t slideY = fx248Mulfx248(collision.normalY, collision.depth);
|
||||||
newX -= slideX;
|
newX -= slideX;
|
||||||
newY -= slideY;
|
newY -= slideY;
|
||||||
} while(++otherEntity < ENTITIES + ENTITY_COUNT_MAX);
|
} while(++otherEntity < ENTITIES + ENTITY_COUNT_MAX);
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
#include "util/fixed.h"
|
#include "util/fixed.h"
|
||||||
|
|
||||||
#define ENTITY_COUNT_MAX 32
|
#define ENTITY_COUNT_MAX 32
|
||||||
|
#define ENTITY_TILE_COLISSION_RESOLUTION_COUNT 4
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
ENTITY_DIR_SOUTH = 0,
|
ENTITY_DIR_SOUTH = 0,
|
||||||
|
@ -47,6 +47,54 @@ collisionresult_t physicsCheckCircleCircle(
|
|||||||
// Penetration depth = sum of radii - distance
|
// Penetration depth = sum of radii - distance
|
||||||
result.depth = fx248Subfx248(rSum, dist);
|
result.depth = fx248Subfx248(rSum, dist);
|
||||||
}
|
}
|
||||||
|
result.hit = true;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
collisionresult_t physicsCheckCircleAABB(
|
||||||
|
fixed248_t circleX, fixed248_t circleY, fixed248_t circleR,
|
||||||
|
fixed248_t aabbX, fixed248_t aabbY,
|
||||||
|
fixed248_t aabbWidth, fixed248_t aabbHeight
|
||||||
|
) {
|
||||||
|
collisionresult_t result;
|
||||||
|
|
||||||
|
// Find the closest point on the AABB to the circle center
|
||||||
|
fixed248_t closestX = fx248Max(
|
||||||
|
aabbX, fx248Min(circleX, fx248Addfx248(aabbX, aabbWidth))
|
||||||
|
);
|
||||||
|
fixed248_t closestY = fx248Max(
|
||||||
|
aabbY, fx248Min(circleY, fx248Addfx248(aabbY, aabbHeight))
|
||||||
|
);
|
||||||
|
|
||||||
|
// Vector from circle center to closest point
|
||||||
|
fixed248_t dx = fx248Subfx248(closestX, circleX);
|
||||||
|
fixed248_t dy = fx248Subfx248(closestY, circleY);
|
||||||
|
|
||||||
|
// Distance squared from circle center to closest point
|
||||||
|
fixed248_t distSq = fx248Addfx248(fx248Mulfx248(dx, dx), fx248Mulfx248(dy, dy));
|
||||||
|
|
||||||
|
// Check if distance is less than radius squared
|
||||||
|
if(distSq > fx248Mulfx248(circleR, circleR)) {
|
||||||
|
result.hit = false;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Collision: calculate normal and penetration depth
|
||||||
|
fixed248_t dist = fx248Sqrt(distSq);
|
||||||
|
|
||||||
|
if(dist <= FIXED248(0, 1)) {
|
||||||
|
// Circle center is at the AABB corner
|
||||||
|
result.normalX = FIXED248(1,0);
|
||||||
|
result.normalY = FIXED248(0,1);
|
||||||
|
result.depth = circleR;
|
||||||
|
} else {
|
||||||
|
// Normalized direction from circle center to closest point
|
||||||
|
result.normalX = fx248Divfx248(dx, dist);
|
||||||
|
result.normalY = fx248Divfx248(dy, dist);
|
||||||
|
// Penetration depth = radius - distance
|
||||||
|
result.depth = fx248Subfx248(circleR, dist);
|
||||||
|
}
|
||||||
|
|
||||||
result.hit = true;
|
result.hit = true;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
@ -28,4 +28,22 @@ typedef struct {
|
|||||||
collisionresult_t physicsCheckCircleCircle(
|
collisionresult_t physicsCheckCircleCircle(
|
||||||
fixed248_t circle0x, fixed248_t circle0y, fixed248_t circle0r,
|
fixed248_t circle0x, fixed248_t circle0y, fixed248_t circle0r,
|
||||||
fixed248_t circle1x, fixed248_t circle1y, fixed248_t circle1r
|
fixed248_t circle1x, fixed248_t circle1y, fixed248_t circle1r
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check for collision between a circle and an axis-aligned bounding box (AABB).
|
||||||
|
*
|
||||||
|
* @param circleX X coordinate of the circle's center.
|
||||||
|
* @param circleY Y coordinate of the circle's center.
|
||||||
|
* @param circleR Radius of the circle.
|
||||||
|
* @param aabb X coordinate of the AABB's top-left corner.
|
||||||
|
* @param aabbY Y coordinate of the AABB's top-left corner.
|
||||||
|
* @param aabbWidth Width of the AABB.
|
||||||
|
* @param aabbHeight Height of the AABB.
|
||||||
|
* @return A collisionresult_t structure containing collision information.
|
||||||
|
*/
|
||||||
|
collisionresult_t physicsCheckCircleAABB(
|
||||||
|
fixed248_t circleX, fixed248_t circleY, fixed248_t circleR,
|
||||||
|
fixed248_t aabb, fixed248_t aabbY,
|
||||||
|
fixed248_t aabbWidth, fixed248_t aabbHeight
|
||||||
);
|
);
|
@ -24,24 +24,34 @@ fixed248_t fx248Fromu16(const uint16_t b) {
|
|||||||
return (fixed248_t)((int32_t)b << FIXED248_FRACTION_BITS);
|
return (fixed248_t)((int32_t)b << FIXED248_FRACTION_BITS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fixed248_t fx248Fromu8(const uint8_t b) {
|
||||||
|
return (fixed248_t)((int32_t)b << FIXED248_FRACTION_BITS);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int32_t fx248Toi32(const fixed248_t a) {
|
int32_t fx248Toi32(const fixed248_t a) {
|
||||||
return (int32_t)(a >> FIXED248_FRACTION_BITS);
|
return a >> FIXED248_FRACTION_BITS;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t fx248Tou32(const fixed248_t a) {
|
uint32_t fx248Tou32(const fixed248_t a) {
|
||||||
return (uint32_t)((a >> FIXED248_FRACTION_BITS) & 0xFFFFFFFF);
|
return (uint32_t)(a >> FIXED248_FRACTION_BITS);
|
||||||
}
|
}
|
||||||
|
|
||||||
float_t fx248Tof32(const fixed248_t a) {
|
float_t fx248Tof32(const fixed248_t a) {
|
||||||
return (float_t)(a / (float_t)(1 << FIXED248_FRACTION_BITS));
|
return (float_t)a / (1 << FIXED248_FRACTION_BITS);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t fx248Tou16(const fixed248_t a) {
|
uint16_t fx248Tou16(const fixed248_t a) {
|
||||||
return (uint16_t)((a >> FIXED248_FRACTION_BITS) & 0xFFFF);
|
return (uint16_t)(a >> FIXED248_FRACTION_BITS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint8_t fx248Tou8(const fixed248_t a) {
|
||||||
|
return (uint8_t)(a >> FIXED248_FRACTION_BITS);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
fixed248_t fx248Addfx248(const fixed248_t a, const fixed248_t b) {
|
fixed248_t fx248Addfx248(const fixed248_t a, const fixed248_t b) {
|
||||||
return a + b;
|
return a + b;
|
||||||
}
|
}
|
||||||
@ -170,4 +180,14 @@ fixed248_t fx248Sqrt(const fixed248_t a) {
|
|||||||
y = (y + div) >> 1;
|
y = (y + div) >> 1;
|
||||||
}
|
}
|
||||||
return y;
|
return y;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
fixed248_t fx248Max(const fixed248_t a, const fixed248_t b) {
|
||||||
|
return (a > b) ? a : b;
|
||||||
|
}
|
||||||
|
|
||||||
|
fixed248_t fx248Min(const fixed248_t a, const fixed248_t b) {
|
||||||
|
return (a < b) ? a : b;
|
||||||
}
|
}
|
@ -52,6 +52,14 @@ fixed248_t fx248Fromf32(const float_t b);
|
|||||||
*/
|
*/
|
||||||
fixed248_t fx248Fromu16(const uint16_t b);
|
fixed248_t fx248Fromu16(const uint16_t b);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert a uint8_t value to a fixed248_t value.
|
||||||
|
*
|
||||||
|
* @param b The uint8_t value to convert.
|
||||||
|
* @return The converted fixed248_t value.
|
||||||
|
*/
|
||||||
|
fixed248_t fx248Fromu8(const uint8_t b);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -86,6 +94,14 @@ float_t fx248Tof32(const fixed248_t a);
|
|||||||
*/
|
*/
|
||||||
uint16_t fx248Tou16(const fixed248_t a);
|
uint16_t fx248Tou16(const fixed248_t a);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert a fixed248_t value to an uint8_t value.
|
||||||
|
*
|
||||||
|
* @param a The fixed248_t value to convert.
|
||||||
|
* @return The converted uint8_t value.
|
||||||
|
*/
|
||||||
|
uint8_t fx248Tou8(const fixed248_t a);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -299,4 +315,24 @@ uint32_t fx248Roundu32(const fixed248_t a);
|
|||||||
*
|
*
|
||||||
* @param a The fixed248_t value to calculate the square root of.
|
* @param a The fixed248_t value to calculate the square root of.
|
||||||
*/
|
*/
|
||||||
fixed248_t fx248Sqrt(const fixed248_t a);
|
fixed248_t fx248Sqrt(const fixed248_t a);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the maximum of two fixed248_t values.
|
||||||
|
*
|
||||||
|
* @param a First fixed248_t value.
|
||||||
|
* @param b Second fixed248_t value.
|
||||||
|
* @return The maximum of the two values.
|
||||||
|
*/
|
||||||
|
fixed248_t fx248Max(const fixed248_t a, const fixed248_t b);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the minimum of two fixed248_t values.
|
||||||
|
*
|
||||||
|
* @param a First fixed248_t value.
|
||||||
|
* @param b Second fixed248_t value.
|
||||||
|
* @return The minimum of the two values.
|
||||||
|
*/
|
||||||
|
fixed248_t fx248Min(const fixed248_t a, const fixed248_t b);
|
@ -8,4 +8,5 @@ target_sources(${DUSK_TARGET_NAME}
|
|||||||
PRIVATE
|
PRIVATE
|
||||||
chunk.c
|
chunk.c
|
||||||
overworld.c
|
overworld.c
|
||||||
|
tile.c
|
||||||
)
|
)
|
@ -169,6 +169,20 @@ void chunkMapSetPosition(const uint16_t x, const uint16_t y) {
|
|||||||
chunkMapShift(shiftX, shiftY);
|
chunkMapShift(shiftX, shiftY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
chunk_t * chunkGetChunkAt(const uint16_t chunkX, const uint16_t chunkY) {
|
||||||
|
assertTrue(
|
||||||
|
chunkX < WORLD_WIDTH && chunkY < WORLD_HEIGHT,
|
||||||
|
"Chunk coordinates out of bounds"
|
||||||
|
);
|
||||||
|
|
||||||
|
chunk_t *chunk = CHUNK_MAP.chunks;
|
||||||
|
do {
|
||||||
|
if(chunk->x == chunkX && chunk->y == chunkY) return chunk;
|
||||||
|
chunk++;
|
||||||
|
} while(chunk < CHUNK_MAP.chunks + CHUNK_MAP_COUNT);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
void chunkLoad(chunk_t *chunk, const uint16_t x, const uint16_t y) {
|
void chunkLoad(chunk_t *chunk, const uint16_t x, const uint16_t y) {
|
||||||
assertNotNull(chunk, "Chunk pointer is null");
|
assertNotNull(chunk, "Chunk pointer is null");
|
||||||
|
|
||||||
|
@ -56,6 +56,16 @@ void chunkMapShift(const int16_t x, const int16_t y);
|
|||||||
*/
|
*/
|
||||||
void chunkMapSetPosition(const uint16_t x, const uint16_t y);
|
void chunkMapSetPosition(const uint16_t x, const uint16_t y);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the chunk at the specified chunk coordinates.
|
||||||
|
*
|
||||||
|
* @param chunkX The x coordinate of the chunk.
|
||||||
|
* @param chunkY The y coordinate of the chunk.
|
||||||
|
* @return A pointer to the chunk at the specified chunk coordinates, or NULL if
|
||||||
|
* no chunk exists at those coordinates.
|
||||||
|
*/
|
||||||
|
chunk_t * chunkGetChunkAt(const uint16_t chunkX, const uint16_t chunkY);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads a chunk at the specified coordinates.
|
* Loads a chunk at the specified coordinates.
|
||||||
*
|
*
|
||||||
|
8
src/dusk/world/tile.c
Normal file
8
src/dusk/world/tile.c
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2025 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "tile.h"
|
@ -10,4 +10,43 @@
|
|||||||
|
|
||||||
#define TILE_WIDTH_HEIGHT 16
|
#define TILE_WIDTH_HEIGHT 16
|
||||||
|
|
||||||
typedef uint8_t tile_t;
|
typedef uint8_t tile_t;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
TILE_SOLID_NONE = 0,
|
||||||
|
TILE_SOLID_FULL = 1,
|
||||||
|
TILE_SOLID_TRIANGLE_TOP_RIGHT = 2,
|
||||||
|
TILE_SOLID_TRIANGLE_TOP_LEFT = 3,
|
||||||
|
TILE_SOLID_TRIANGLE_BOTTOM_RIGHT = 4,
|
||||||
|
TILE_SOLID_TRIANGLE_BOTTOM_LEFT = 5,
|
||||||
|
} tilesolidtype_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
tilesolidtype_t solidType;
|
||||||
|
} tilemeta_t;
|
||||||
|
|
||||||
|
static const tilemeta_t TILE_META_DATA[] = {
|
||||||
|
{TILE_SOLID_NONE}, // 0
|
||||||
|
{TILE_SOLID_NONE}, // 1
|
||||||
|
{TILE_SOLID_NONE}, // 2
|
||||||
|
{TILE_SOLID_NONE}, // 3
|
||||||
|
{TILE_SOLID_NONE}, // 4
|
||||||
|
{TILE_SOLID_NONE}, // 5
|
||||||
|
{TILE_SOLID_NONE}, // 6
|
||||||
|
{TILE_SOLID_NONE}, // 7
|
||||||
|
{TILE_SOLID_NONE}, // 8
|
||||||
|
{TILE_SOLID_NONE}, // 9
|
||||||
|
{TILE_SOLID_NONE}, // 10
|
||||||
|
{TILE_SOLID_NONE}, // 11
|
||||||
|
{TILE_SOLID_NONE}, // 12
|
||||||
|
{TILE_SOLID_NONE}, // 13
|
||||||
|
{TILE_SOLID_NONE}, // 14
|
||||||
|
{TILE_SOLID_NONE}, // 15
|
||||||
|
{TILE_SOLID_NONE}, // 16
|
||||||
|
{TILE_SOLID_NONE}, // 17
|
||||||
|
{TILE_SOLID_FULL}, // 18
|
||||||
|
{TILE_SOLID_FULL}, // 19
|
||||||
|
{TILE_SOLID_FULL}, // 19
|
||||||
|
};
|
||||||
|
|
||||||
|
#define TILE_META_DATA_COUNT (sizeof(TILE_META_DATA) / sizeof(tilemeta_t))
|
@ -422,7 +422,7 @@ with open(headerPath, 'w') as f:
|
|||||||
for i in range(worldHeight):
|
for i in range(worldHeight):
|
||||||
f.write(" ")
|
f.write(" ")
|
||||||
for j in range(worldWidth):
|
for j in range(worldWidth):
|
||||||
if (j, i) in chunksDone:
|
if(j, i) in chunksDone:
|
||||||
f.write(f"&CHUNK_{j}_{i}, ")
|
f.write(f"&CHUNK_{j}_{i}, ")
|
||||||
else:
|
else:
|
||||||
f.write("NULL, ")
|
f.write("NULL, ")
|
||||||
|
21
tools/tilecompile/CMakeLists.txt
Normal file
21
tools/tilecompile/CMakeLists.txt
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
# Copyright (c) 2025 Dominic Masters
|
||||||
|
#
|
||||||
|
# This software is released under the MIT License.
|
||||||
|
# https://opensource.org/licenses/MIT
|
||||||
|
|
||||||
|
find_package(Python3 COMPONENTS Interpreter REQUIRED)
|
||||||
|
|
||||||
|
# Custom command to generate all header files
|
||||||
|
add_custom_target(DUSK_CHUNKS
|
||||||
|
# OUTPUT ${DUSK_GENERATED_HEADERS_DIR}/world/world.h
|
||||||
|
COMMAND
|
||||||
|
${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/mapcompile.py
|
||||||
|
--output ${DUSK_GENERATED_HEADERS_DIR}
|
||||||
|
--input ${DUSK_DATA_DIR}/map.tmj
|
||||||
|
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/mapcompile.py
|
||||||
|
COMMENT "Generating chunk header files"
|
||||||
|
VERBATIM
|
||||||
|
)
|
||||||
|
|
||||||
|
# Ensure headers are generated before compiling main
|
||||||
|
add_dependencies(${DUSK_TARGET_NAME} DUSK_CHUNKS)
|
32
tools/tilecompile/tilecompile.py
Normal file
32
tools/tilecompile/tilecompile.py
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
import sys, os
|
||||||
|
import argparse
|
||||||
|
from datetime import datetime
|
||||||
|
import json
|
||||||
|
import math
|
||||||
|
|
||||||
|
# Check if the script is run with the correct arguments
|
||||||
|
parser = argparse.ArgumentParser(description="Generate chunk header files")
|
||||||
|
parser.add_argument('--output', required=True, help='Dir to output headers')
|
||||||
|
parser.add_argument('--input', required=True, help='Input JSON file from tiled')
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
# Ensure outdir exists
|
||||||
|
outputDir = args.output
|
||||||
|
os.makedirs(outputDir, exist_ok=True)
|
||||||
|
|
||||||
|
# Create world directory if it does not exist
|
||||||
|
worldDir = os.path.join(outputDir, "world")
|
||||||
|
os.makedirs(worldDir, exist_ok=True)
|
||||||
|
|
||||||
|
# Some vars used during printing
|
||||||
|
now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||||
|
|
||||||
|
# Read the input JSON file
|
||||||
|
inputFile = args.input
|
||||||
|
if not os.path.isfile(inputFile):
|
||||||
|
print(f"Error: Input file '{inputFile}' does not exist.")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
with open(inputFile, 'r') as f:
|
||||||
|
data = json.load(f)
|
||||||
|
|
Reference in New Issue
Block a user