Fixes
BIN
assets/backgrounds/00_water_00.png
Normal file
After Width: | Height: | Size: 2.4 KiB |
BIN
assets/backgrounds/00_water_01.png
Normal file
After Width: | Height: | Size: 2.4 KiB |
BIN
assets/backgrounds/00_water_02.png
Normal file
After Width: | Height: | Size: 2.4 KiB |
BIN
assets/backgrounds/00_water_03.png
Normal file
After Width: | Height: | Size: 2.5 KiB |
BIN
assets/backgrounds/00_water_04.png
Normal file
After Width: | Height: | Size: 2.5 KiB |
BIN
assets/backgrounds/00_water_05.png
Normal file
After Width: | Height: | Size: 2.5 KiB |
BIN
assets/backgrounds/00_water_06.png
Normal file
After Width: | Height: | Size: 2.5 KiB |
BIN
assets/backgrounds/00_water_07.png
Normal file
After Width: | Height: | Size: 2.5 KiB |
BIN
assets/backgrounds/00_water_08.png
Normal file
After Width: | Height: | Size: 2.5 KiB |
BIN
assets/backgrounds/00_water_09.png
Normal file
After Width: | Height: | Size: 2.6 KiB |
BIN
assets/backgrounds/00_water_10.png
Normal file
After Width: | Height: | Size: 2.6 KiB |
BIN
assets/backgrounds/00_water_11.png
Normal file
After Width: | Height: | Size: 2.6 KiB |
Before Width: | Height: | Size: 2.1 KiB |
BIN
assets/backgrounds/01_water_00.png
Normal file
After Width: | Height: | Size: 2.0 KiB |
BIN
assets/backgrounds/01_water_01.png
Normal file
After Width: | Height: | Size: 2.0 KiB |
BIN
assets/backgrounds/01_water_02.png
Normal file
After Width: | Height: | Size: 2.0 KiB |
BIN
assets/backgrounds/01_water_03.png
Normal file
After Width: | Height: | Size: 2.1 KiB |
BIN
assets/backgrounds/01_water_04.png
Normal file
After Width: | Height: | Size: 2.1 KiB |
BIN
assets/backgrounds/01_water_05.png
Normal file
After Width: | Height: | Size: 2.1 KiB |
BIN
assets/backgrounds/01_water_06.png
Normal file
After Width: | Height: | Size: 2.2 KiB |
BIN
assets/backgrounds/01_water_07.png
Normal file
After Width: | Height: | Size: 2.2 KiB |
BIN
assets/backgrounds/01_water_08.png
Normal file
After Width: | Height: | Size: 2.2 KiB |
BIN
assets/backgrounds/01_water_09.png
Normal file
After Width: | Height: | Size: 2.4 KiB |
BIN
assets/backgrounds/01_water_10.png
Normal file
After Width: | Height: | Size: 2.4 KiB |
BIN
assets/backgrounds/01_water_11.png
Normal file
After Width: | Height: | Size: 2.4 KiB |
Before Width: | Height: | Size: 2.1 KiB |
Before Width: | Height: | Size: 859 B After Width: | Height: | Size: 859 B |
Before Width: | Height: | Size: 858 B After Width: | Height: | Size: 858 B |
Before Width: | Height: | Size: 878 B After Width: | Height: | Size: 878 B |
Before Width: | Height: | Size: 855 B After Width: | Height: | Size: 855 B |
Before Width: | Height: | Size: 860 B After Width: | Height: | Size: 860 B |
Before Width: | Height: | Size: 862 B After Width: | Height: | Size: 862 B |
Before Width: | Height: | Size: 868 B After Width: | Height: | Size: 868 B |
Before Width: | Height: | Size: 869 B After Width: | Height: | Size: 869 B |
Before Width: | Height: | Size: 855 B After Width: | Height: | Size: 855 B |
Before Width: | Height: | Size: 849 B After Width: | Height: | Size: 849 B |
Before Width: | Height: | Size: 863 B After Width: | Height: | Size: 863 B |
Before Width: | Height: | Size: 854 B After Width: | Height: | Size: 854 B |
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.4 KiB |
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.5 KiB |
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.4 KiB |
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.4 KiB |
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.5 KiB |
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.5 KiB |
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.5 KiB |
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.5 KiB |
Before Width: | Height: | Size: 814 B After Width: | Height: | Size: 814 B |
Before Width: | Height: | Size: 802 B After Width: | Height: | Size: 802 B |
Before Width: | Height: | Size: 734 B After Width: | Height: | Size: 734 B |
Before Width: | Height: | Size: 739 B After Width: | Height: | Size: 739 B |
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
Before Width: | Height: | Size: 873 B After Width: | Height: | Size: 873 B |
Before Width: | Height: | Size: 990 B After Width: | Height: | Size: 990 B |
Before Width: | Height: | Size: 837 B After Width: | Height: | Size: 837 B |
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 513 B After Width: | Height: | Size: 513 B |
Before Width: | Height: | Size: 546 B After Width: | Height: | Size: 546 B |
Before Width: | Height: | Size: 566 B After Width: | Height: | Size: 566 B |
Before Width: | Height: | Size: 526 B After Width: | Height: | Size: 526 B |
Before Width: | Height: | Size: 516 B After Width: | Height: | Size: 516 B |
Before Width: | Height: | Size: 517 B After Width: | Height: | Size: 517 B |
Before Width: | Height: | Size: 492 B After Width: | Height: | Size: 492 B |
Before Width: | Height: | Size: 530 B After Width: | Height: | Size: 530 B |
Before Width: | Height: | Size: 592 B After Width: | Height: | Size: 592 B |
Before Width: | Height: | Size: 157 B After Width: | Height: | Size: 157 B |
Before Width: | Height: | Size: 120 B After Width: | Height: | Size: 120 B |
Before Width: | Height: | Size: 202 B After Width: | Height: | Size: 202 B |
BIN
assets/tiles/03_furnace_00.png
Normal file
After Width: | Height: | Size: 298 B |
Before Width: | Height: | Size: 557 B After Width: | Height: | Size: 557 B |
BIN
assets/tiles/03_furnace_02.png
Normal file
After Width: | Height: | Size: 513 B |
BIN
assets/tiles/03_furnace_03.png
Normal file
After Width: | Height: | Size: 483 B |
BIN
assets/tiles/03_furnace_04.png
Normal file
After Width: | Height: | Size: 511 B |
BIN
assets/tiles/03_furnace_05.png
Normal file
After Width: | Height: | Size: 505 B |
BIN
assets/tiles/03_furnace_06.png
Normal file
After Width: | Height: | Size: 483 B |
Before Width: | Height: | Size: 489 B After Width: | Height: | Size: 489 B |
BIN
assets/tiles/04_miner_01.png
Normal file
After Width: | Height: | Size: 492 B |
BIN
assets/tiles/04_miner_02.png
Normal file
After Width: | Height: | Size: 486 B |
BIN
assets/tiles/04_miner_03.png
Normal file
After Width: | Height: | Size: 487 B |
BIN
assets/tiles/04_miner_04.png
Normal file
After Width: | Height: | Size: 485 B |
BIN
assets/tiles/04_miner_05.png
Normal file
After Width: | Height: | Size: 487 B |
BIN
assets/tiles/04_miner_06.png
Normal file
After Width: | Height: | Size: 483 B |
BIN
assets/tiles/04_miner_07.png
Normal file
After Width: | Height: | Size: 481 B |
128
items/item.c
@@ -117,29 +117,6 @@ void updateItems() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void registerItem(char name[20], SDL_Renderer *renderer) {
|
|
||||||
const char *dot = strchr(name, '.');
|
|
||||||
memcpy(ItemRegistry[itemRegistryIndex].name, name, dot - name);
|
|
||||||
char texturePath[80];
|
|
||||||
snprintf(texturePath, 80, "./assets/items/%s", name);
|
|
||||||
ItemRegistry[itemRegistryIndex].texture[ORIENT_LEFT] = IMG_LoadTexture(renderer, texturePath);
|
|
||||||
SDL_SetTextureBlendMode(ItemRegistry[itemRegistryIndex].texture[0], SDL_BLENDMODE_BLEND);
|
|
||||||
ItemRegistry[itemRegistryIndex].textureOnBelt[ORIENT_LEFT] = ScaleTexture(renderer,
|
|
||||||
ItemRegistry[itemRegistryIndex].texture[ORIENT_LEFT],
|
|
||||||
TILE_SIZE / 2, TILE_SIZE / 2);
|
|
||||||
SDL_SetTextureBlendMode(ItemRegistry[itemRegistryIndex].textureOnBelt[ORIENT_LEFT], SDL_BLENDMODE_BLEND);
|
|
||||||
ItemRegistry[itemRegistryIndex].atlasRects[ORIENT_LEFT] = allocate_32x32(
|
|
||||||
ItemRegistry[itemRegistryIndex].texture[ORIENT_LEFT], renderer);
|
|
||||||
ItemRegistry[itemRegistryIndex].atlasRectsOnBelt[ORIENT_LEFT] = allocate_16x16(
|
|
||||||
ItemRegistry[itemRegistryIndex].textureOnBelt[ORIENT_LEFT], renderer);
|
|
||||||
ItemRegistry[itemRegistryIndex].type = itemRegistryIndex;
|
|
||||||
ItemRegistry[itemRegistryIndex].isTile = false;
|
|
||||||
ItemRegistry[itemRegistryIndex].miscVal = 60;
|
|
||||||
|
|
||||||
itemRegistryIndex++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// easing function: cosine ease‐in‐out
|
// easing function: cosine ease‐in‐out
|
||||||
//static float ease_in_out(float t) {
|
//static float ease_in_out(float t) {
|
||||||
// if (t < -1.0f) t = -1.0f;
|
// if (t < -1.0f) t = -1.0f;
|
||||||
@@ -297,7 +274,11 @@ void renderItem(ItemOnBelt item, SDL_Renderer *renderer, int lane, SDL_Rect play
|
|||||||
SDL_RenderFillRect(renderer, &rectA);
|
SDL_RenderFillRect(renderer, &rectA);
|
||||||
}
|
}
|
||||||
//SDL_RenderCopyx(renderer, ItemRegistry[item.type].textureOnBelt[ORIENT_LEFT], NULL, &rect);
|
//SDL_RenderCopyx(renderer, ItemRegistry[item.type].textureOnBelt[ORIENT_LEFT], NULL, &rect);
|
||||||
SDL_RenderCopy(renderer, atlasTexture, &ItemRegistry[item.type].atlasRectsOnBelt[ORIENT_LEFT], &rect);
|
SDL_RenderCopy(renderer, atlasTexture,
|
||||||
|
&ItemRegistry[item.type].beltAnimation.atlasRects[ORIENT_LEFT][
|
||||||
|
(animationStep / ItemRegistry[item.type].beltAnimation.divisor) %
|
||||||
|
ItemRegistry[item.type].beltAnimation.frameCount],
|
||||||
|
&rect);
|
||||||
|
|
||||||
if (debugMode) {
|
if (debugMode) {
|
||||||
renderText(renderer, fonts[3], tempStr, rectA.x, rectA.y);
|
renderText(renderer, fonts[3], tempStr, rectA.x, rectA.y);
|
||||||
@@ -312,29 +293,102 @@ void putItem(int x, int y, ItemType itemType, uint8_t lane) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void loadItems(SDL_Renderer *renderer) {
|
void loadItems(SDL_Renderer *renderer) {
|
||||||
|
// Load tile-based items
|
||||||
for (int i = 0; i < tileTypeIndex; i++) {
|
for (int i = 0; i < tileTypeIndex; i++) {
|
||||||
TileTypeReg tile = TileRegistry[i];
|
TileTypeReg tile = TileRegistry[i];
|
||||||
|
|
||||||
strcpy(ItemRegistry[itemRegistryIndex].name, tile.name);
|
Item *item = &ItemRegistry[itemRegistryIndex];
|
||||||
memcpy(ItemRegistry[itemRegistryIndex].texture, tile.textures, sizeof(tile.textures));
|
strcpy(item->name, tile.name);
|
||||||
memcpy(ItemRegistry[itemRegistryIndex].atlasRects, tile.atlasRects, sizeof(tile.atlasRects));
|
memcpy(&item->animation, &tile.animation, sizeof(tile.animation));
|
||||||
|
|
||||||
|
for (int frame = 0; frame < item->animation.frameCount; frame++) {
|
||||||
for (int a = 0; a < ORIENT_DIRECTION_COUNT; a++) {
|
for (int a = 0; a < ORIENT_DIRECTION_COUNT; a++) {
|
||||||
SDL_SetTextureBlendMode(ItemRegistry[itemRegistryIndex].texture[a], SDL_BLENDMODE_BLEND);
|
SDL_SetTextureBlendMode(item->animation.textures[a][frame], SDL_BLENDMODE_BLEND);
|
||||||
ItemRegistry[itemRegistryIndex].textureOnBelt[a] = ScaleTexture(renderer, tile.textures[a],
|
item->beltAnimation.textures[a][frame] = ScaleTexture(renderer, tile.animation.textures[a][frame],
|
||||||
TILE_SIZE / 2, TILE_SIZE / 2);
|
TILE_SIZE / 2, TILE_SIZE / 2);
|
||||||
ItemRegistry[itemRegistryIndex].atlasRectsOnBelt[a] = allocate_16x16(
|
item->beltAnimation.atlasRects[a][frame] = allocate_16x16(item->beltAnimation.textures[a][frame],
|
||||||
ItemRegistry[itemRegistryIndex].textureOnBelt[a], renderer);
|
renderer);
|
||||||
SDL_SetTextureBlendMode(ItemRegistry[itemRegistryIndex].textureOnBelt[a], SDL_BLENDMODE_BLEND);
|
if (frame + 1 > item->beltAnimation.frameCount) {
|
||||||
|
item->beltAnimation.frameCount = frame + 1;
|
||||||
}
|
}
|
||||||
ItemRegistry[itemRegistryIndex].type = itemRegistryIndex;
|
SDL_SetTextureBlendMode(item->beltAnimation.textures[a][frame], SDL_BLENDMODE_BLEND);
|
||||||
ItemRegistry[itemRegistryIndex].isTile = true;
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
item->type = itemRegistryIndex;
|
||||||
|
item->isTile = true;
|
||||||
|
item->animation.divisor = 1;
|
||||||
|
item->beltAnimation.divisor = 1;
|
||||||
|
|
||||||
itemRegistryIndex++;
|
itemRegistryIndex++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Skip ahead to avoid overlap (tile items use lower indices)
|
||||||
itemRegistryIndex = ITEMREGISTRY_SIZE / 2;
|
itemRegistryIndex = ITEMREGISTRY_SIZE / 2;
|
||||||
iterateSortedDir("./assets/items", (DirEntryCallback) registerItem, renderer);
|
|
||||||
|
|
||||||
|
// Load sprite-based items with animations
|
||||||
|
DIR *dir = opendir("./assets/items");
|
||||||
|
if (!dir) {
|
||||||
|
perror("Failed to open item asset folder");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct dirent *entry;
|
||||||
|
while ((entry = readdir(dir)) != NULL) {
|
||||||
|
if (!strstr(entry->d_name, ".png")) continue;
|
||||||
|
|
||||||
|
int frame, indexItem;
|
||||||
|
char name[64];
|
||||||
|
|
||||||
|
if (sscanf(entry->d_name, "%d-%20[^-]-%d.png", &indexItem, name, &frame) == 3) {
|
||||||
|
// Success: you now have index, fname, and frame
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "Invalid format: %s\n", entry->d_name);
|
||||||
|
}
|
||||||
|
indexItem += ITEMREGISTRY_SIZE / 2;
|
||||||
|
|
||||||
|
Item *item;
|
||||||
|
item = &ItemRegistry[indexItem];
|
||||||
|
memset(item, 0, sizeof(Item));
|
||||||
|
strcpy(item->name, name);
|
||||||
|
item->type = indexItem;
|
||||||
|
item->isTile = false;
|
||||||
|
item->miscVal = 60;
|
||||||
|
item->animation.divisor = 1;
|
||||||
|
item->beltAnimation.divisor = 1;
|
||||||
|
|
||||||
|
// Load the texture
|
||||||
|
char path[128];
|
||||||
|
snprintf(path, sizeof(path), "./assets/items/%s", entry->d_name);
|
||||||
|
SDL_Texture *tex = IMG_LoadTexture(renderer, path);
|
||||||
|
if (!tex) {
|
||||||
|
fprintf(stderr, "Failed to load texture %s: %s\n", path, IMG_GetError());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_SetTextureBlendMode(tex, SDL_BLENDMODE_BLEND);
|
||||||
|
SDL_Texture *beltTex = ScaleTexture(renderer, tex, TILE_SIZE / 2, TILE_SIZE / 2);
|
||||||
|
SDL_SetTextureBlendMode(beltTex, SDL_BLENDMODE_BLEND);
|
||||||
|
|
||||||
|
SDL_Rect mainRect = allocate_32x32(tex, renderer);
|
||||||
|
SDL_Rect beltRect = allocate_16x16(beltTex, renderer);
|
||||||
|
// Assign to all orientations
|
||||||
|
for (int o = 0; o < ORIENT_DIRECTION_COUNT; o++) {
|
||||||
|
item->animation.textures[o][frame] = tex;
|
||||||
|
item->beltAnimation.textures[o][frame] = beltTex;
|
||||||
|
item->animation.atlasRects[o][frame] = mainRect;
|
||||||
|
item->beltAnimation.atlasRects[o][frame] = beltRect;
|
||||||
|
if (frame + 1 > item->animation.frameCount) {
|
||||||
|
item->animation.frameCount = frame + 1;
|
||||||
|
item->beltAnimation.frameCount = frame + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
item->animation.divisor = 1;
|
||||||
|
if (indexItem + 1 > itemRegistryIndex) {
|
||||||
|
itemRegistryIndex = indexItem + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
closedir(dir);
|
||||||
}
|
}
|
@@ -42,10 +42,8 @@ typedef struct Item {
|
|||||||
ItemType type;
|
ItemType type;
|
||||||
char name[20];
|
char name[20];
|
||||||
uint16_t miscVal;
|
uint16_t miscVal;
|
||||||
SDL_Texture * texture[ORIENT_DIRECTION_COUNT];
|
OrientedAnimation animation;
|
||||||
SDL_Texture * textureOnBelt[ORIENT_DIRECTION_COUNT];
|
OrientedAnimation beltAnimation;
|
||||||
SDL_Rect atlasRects[ORIENT_DIRECTION_COUNT];
|
|
||||||
SDL_Rect atlasRectsOnBelt[ORIENT_DIRECTION_COUNT];
|
|
||||||
} Item;
|
} Item;
|
||||||
|
|
||||||
|
|
||||||
|
13
main.c
@@ -139,6 +139,7 @@ int init() {
|
|||||||
|
|
||||||
initAtlas(mainRenderer);
|
initAtlas(mainRenderer);
|
||||||
|
|
||||||
|
loadBackgroundTiles(mainRenderer);
|
||||||
loadTiles(mainRenderer);
|
loadTiles(mainRenderer);
|
||||||
loadItems(mainRenderer);
|
loadItems(mainRenderer);
|
||||||
setupTiles();
|
setupTiles();
|
||||||
@@ -506,6 +507,9 @@ void processKeyboardHeld() {
|
|||||||
setActivePlayerSlot(&player, 0);
|
setActivePlayerSlot(&player, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (keyboardState[SDL_SCANCODE_F9]) {
|
||||||
|
player.inventory.slotCounts[player.inventory.activeSlotIndex]++;
|
||||||
|
}
|
||||||
if (keyboardState[SDL_SCANCODE_Y]) {
|
if (keyboardState[SDL_SCANCODE_Y]) {
|
||||||
if (player.cursor.canReach && player.cursor.targetTile->type == TYPE_BELT &&
|
if (player.cursor.canReach && player.cursor.targetTile->type == TYPE_BELT &&
|
||||||
player.inventory.slotCounts[player.inventory.activeSlotIndex] > 0) {
|
player.inventory.slotCounts[player.inventory.activeSlotIndex] > 0) {
|
||||||
@@ -586,6 +590,7 @@ int main(__attribute__((unused)) int argc, __attribute__((unused)) char *args[])
|
|||||||
updateItems();
|
updateItems();
|
||||||
updatePlayer(&player);
|
updatePlayer(&player);
|
||||||
updateTiles();
|
updateTiles();
|
||||||
|
animationStep++;
|
||||||
status = render();
|
status = render();
|
||||||
if (status) {
|
if (status) {
|
||||||
return status;
|
return status;
|
||||||
@@ -655,15 +660,15 @@ void genInitMap() {
|
|||||||
// [Same as your original terrain generation logic...]
|
// [Same as your original terrain generation logic...]
|
||||||
BackgroundType baseType;
|
BackgroundType baseType;
|
||||||
if (terrain < 0.30) {
|
if (terrain < 0.30) {
|
||||||
baseType = (humidity < 0.5) ? BGType_WATER0 : BGType_WATER1;
|
baseType = (humidity < 0.5) ? BGType_WATER_SHALLOW : BGType_WATER_DEEP;
|
||||||
} else if (terrain < 0.35) {
|
} else if (terrain < 0.35) {
|
||||||
if (humidity < 0.3) baseType = BGType_SAND4;
|
if (humidity < 0.3) baseType = BGType_SAND4;
|
||||||
else if (humidity < 0.6) baseType = BGType_SAND2;
|
else if (humidity < 0.6) baseType = BGType_SAND2;
|
||||||
else baseType = BGType_SAND7;
|
else baseType = BGType_SAND7;
|
||||||
} else if (terrain < 0.7) {
|
} else if (terrain < 0.7) {
|
||||||
double grassVal = (terrain - 0.35) / (0.70 - 0.35);
|
double grassVal = (terrain - 0.35) / (0.70 - 0.35);
|
||||||
int idx = (int) (grassVal * 8.0);
|
int idx = (int) (grassVal * 3.0);
|
||||||
if (idx >= 8) idx = 7;
|
if (idx >= 4) idx = 3;
|
||||||
if (humidity > 0.6 && ((rand() & 0xFF) < 10)) {
|
if (humidity > 0.6 && ((rand() & 0xFF) < 10)) {
|
||||||
int flowerIdx = rand() % 4;
|
int flowerIdx = rand() % 4;
|
||||||
baseType = (BackgroundType) (BGType_GRASS_FLOWER0 + flowerIdx);
|
baseType = (BackgroundType) (BGType_GRASS_FLOWER0 + flowerIdx);
|
||||||
@@ -679,7 +684,7 @@ void genInitMap() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
BackgroundType finalType = baseType;
|
BackgroundType finalType = baseType;
|
||||||
if (baseType != BGType_WATER0 && baseType != BGType_WATER1) {
|
if (baseType != BGType_WATER_SHALLOW && baseType != BGType_WATER_DEEP) {
|
||||||
if (oreNrm > 0.86) {
|
if (oreNrm > 0.86) {
|
||||||
double sub = (oreNrm - 0.86) / (1.0 - 0.86);
|
double sub = (oreNrm - 0.86) / (1.0 - 0.86);
|
||||||
if (sub < 0.25) finalType = BGType_PLATINUM_ORE;
|
if (sub < 0.25) finalType = BGType_PLATINUM_ORE;
|
||||||
|
@@ -179,9 +179,9 @@ void renderPlayer(Player *plr) {
|
|||||||
plr->cursor.heldItemRect.x = plr->cursor.windowX;
|
plr->cursor.heldItemRect.x = plr->cursor.windowX;
|
||||||
plr->cursor.heldItemRect.y = plr->cursor.windowY;
|
plr->cursor.heldItemRect.y = plr->cursor.windowY;
|
||||||
//itemTex = ItemRegistry[itemIndex].textureOnBelt[plr->cursor.direction];
|
//itemTex = ItemRegistry[itemIndex].textureOnBelt[plr->cursor.direction];
|
||||||
SDL_Rect itemAtlasRect = ItemRegistry[itemIndex].atlasRects[plr->cursor.direction];
|
SDL_Rect itemAtlasRect = ItemRegistry[itemIndex].animation.atlasRects[plr->cursor.direction][(animationStep / ItemRegistry[itemIndex].animation.divisor) % ItemRegistry[itemIndex].animation.frameCount];
|
||||||
if (itemAtlasRect.w == 0 || itemAtlasRect.h == 0) {
|
if (itemAtlasRect.w == 0 || itemAtlasRect.h == 0) {
|
||||||
itemAtlasRect = ItemRegistry[itemIndex].atlasRects[ORIENT_LEFT];
|
itemAtlasRect = ItemRegistry[itemIndex].animation.atlasRects[ORIENT_LEFT][(animationStep / ItemRegistry[itemIndex].animation.divisor) % ItemRegistry[itemIndex].animation.frameCount];
|
||||||
}
|
}
|
||||||
if (itemAtlasRect.w != 0 && itemAtlasRect.h != 0) {
|
if (itemAtlasRect.w != 0 && itemAtlasRect.h != 0) {
|
||||||
|
|
||||||
@@ -197,8 +197,10 @@ void renderPlayer(Player *plr) {
|
|||||||
// }
|
// }
|
||||||
// SDL_RenderCopy(mainRenderer, itemTex, NULL,
|
// SDL_RenderCopy(mainRenderer, itemTex, NULL,
|
||||||
// &plr->cursor.heldItemRect);
|
// &plr->cursor.heldItemRect);
|
||||||
|
char nameItem[80];
|
||||||
|
snprintf(nameItem, 80, "%s\n%s", ItemRegistry[itemIndex].name, OrientStrings[plr->cursor.direction]);
|
||||||
SDL_RenderCopy(mainRenderer, atlasTexture, &itemAtlasRect, &plr->cursor.heldItemRect);
|
SDL_RenderCopy(mainRenderer, atlasTexture, &itemAtlasRect, &plr->cursor.heldItemRect);
|
||||||
renderText(mainRenderer, fonts[2], ItemRegistry[itemIndex].name, plr->cursor.heldItemRect.x,
|
renderText(mainRenderer, fonts[2], nameItem, plr->cursor.heldItemRect.x,
|
||||||
plr->cursor.heldItemRect.y - (fonts[2].size * 3 / 2));
|
plr->cursor.heldItemRect.y - (fonts[2].size * 3 / 2));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -223,9 +225,12 @@ void renderPlayer(Player *plr) {
|
|||||||
|
|
||||||
SDL_SetTextureBlendMode(atlasTexture, SDL_BLENDMODE_ADD);
|
SDL_SetTextureBlendMode(atlasTexture, SDL_BLENDMODE_ADD);
|
||||||
for (ItemType i = 0; i < ITEMREGISTRY_SIZE; i++) {
|
for (ItemType i = 0; i < ITEMREGISTRY_SIZE; i++) {
|
||||||
SDL_Rect itemAtlasRectd = ItemRegistry[i].atlasRects[plr->cursor.direction];
|
if (ItemRegistry[i].name[0] == 0x00) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
SDL_Rect itemAtlasRectd = ItemRegistry[i].animation.atlasRects[plr->cursor.direction][(animationStep / ItemRegistry[i].animation.divisor) % ItemRegistry[i].animation.frameCount];
|
||||||
if (itemAtlasRectd.w == 0 || itemAtlasRectd.h == 0) {
|
if (itemAtlasRectd.w == 0 || itemAtlasRectd.h == 0) {
|
||||||
itemAtlasRectd = ItemRegistry[i].atlasRects[ORIENT_LEFT];
|
itemAtlasRectd = ItemRegistry[i].animation.atlasRects[ORIENT_LEFT][(animationStep / ItemRegistry[i].animation.divisor) % ItemRegistry[i].animation.frameCount];
|
||||||
}
|
}
|
||||||
if (itemAtlasRectd.w != 0 && itemAtlasRectd.h != 0) {
|
if (itemAtlasRectd.w != 0 && itemAtlasRectd.h != 0) {
|
||||||
// if (plr->inventory.slotCounts[i] <= 0) {
|
// if (plr->inventory.slotCounts[i] <= 0) {
|
||||||
|
140
tiles/belt.c
@@ -10,63 +10,97 @@
|
|||||||
#include "../items/item.h"
|
#include "../items/item.h"
|
||||||
#include "../util/atlas.h"
|
#include "../util/atlas.h"
|
||||||
|
|
||||||
|
void generateBeltFrames(SDL_Renderer *renderer) {
|
||||||
|
SDL_Texture *baseTexture = TileRegistry[TYPE_BELT].animation.textures[ORIENT_LEFT][0]; // Base belt tile
|
||||||
|
SDL_Texture *oldTarget = SDL_GetRenderTarget(renderer);
|
||||||
|
const int frameCount = TILE_SIZE; // 32 frames, 1px per frame = full seamless loop
|
||||||
|
|
||||||
|
for (OrientDirection dir = ORIENT_LEFT_DOWN; dir < ORIENT_DIRECTION_COUNT; dir++) {
|
||||||
|
double angle = 0.0;
|
||||||
|
bool isHorizontal = true;
|
||||||
|
bool reverse = false;
|
||||||
|
|
||||||
|
switch (dir) {
|
||||||
|
case ORIENT_LEFT:
|
||||||
|
angle = 0;
|
||||||
|
isHorizontal = true;
|
||||||
|
reverse = false;
|
||||||
|
break;
|
||||||
|
case ORIENT_UP:
|
||||||
|
angle = 90;
|
||||||
|
isHorizontal = false;
|
||||||
|
reverse = false;
|
||||||
|
break;
|
||||||
|
case ORIENT_RIGHT:
|
||||||
|
angle = 180;
|
||||||
|
isHorizontal = true;
|
||||||
|
reverse = true;
|
||||||
|
break;
|
||||||
|
case ORIENT_DOWN:
|
||||||
|
angle = 270;
|
||||||
|
isHorizontal = false;
|
||||||
|
reverse = true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
continue; // skip diagonals or unsupported directions
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 1: Rotate the tile once
|
||||||
|
SDL_Texture *rotated = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888,
|
||||||
|
SDL_TEXTUREACCESS_TARGET, TILE_SIZE, TILE_SIZE);
|
||||||
|
SDL_SetTextureBlendMode(rotated, SDL_BLENDMODE_BLEND);
|
||||||
|
SDL_SetRenderTarget(renderer, rotated);
|
||||||
|
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0);
|
||||||
|
SDL_RenderClear(renderer);
|
||||||
|
|
||||||
|
SDL_Rect full = {0, 0, TILE_SIZE, TILE_SIZE};
|
||||||
|
SDL_RenderCopyEx(renderer, baseTexture, NULL, &full, angle, NULL, SDL_FLIP_NONE);
|
||||||
|
|
||||||
|
// Step 2: For each frame, render 2 rotated tiles with wrapping offset
|
||||||
|
for (int f = 0; f < frameCount; f++) {
|
||||||
|
SDL_Texture *frame = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888,
|
||||||
|
SDL_TEXTUREACCESS_TARGET, TILE_SIZE, TILE_SIZE);
|
||||||
|
SDL_SetTextureBlendMode(frame, SDL_BLENDMODE_BLEND);
|
||||||
|
SDL_SetRenderTarget(renderer, frame);
|
||||||
|
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0);
|
||||||
|
SDL_RenderClear(renderer);
|
||||||
|
|
||||||
|
int offset = reverse ? (TILE_SIZE - f) % TILE_SIZE : f;
|
||||||
|
|
||||||
|
SDL_Rect dst1, dst2;
|
||||||
|
if (isHorizontal) {
|
||||||
|
dst1 = (SDL_Rect) {-offset, 0, TILE_SIZE, TILE_SIZE};
|
||||||
|
dst2 = (SDL_Rect) {TILE_SIZE - offset, 0, TILE_SIZE, TILE_SIZE};
|
||||||
|
} else {
|
||||||
|
dst1 = (SDL_Rect) {0, -offset, TILE_SIZE, TILE_SIZE};
|
||||||
|
dst2 = (SDL_Rect) {0, TILE_SIZE - offset, TILE_SIZE, TILE_SIZE};
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_RenderCopy(renderer, rotated, NULL, &dst1);
|
||||||
|
SDL_RenderCopy(renderer, rotated, NULL, &dst2);
|
||||||
|
|
||||||
|
TileRegistry[TYPE_BELT].animation.textures[dir][f] = frame;
|
||||||
|
TileRegistry[TYPE_BELT].animation.atlasRects[dir][f] = allocate_32x32(frame, renderer);
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_DestroyTexture(rotated);
|
||||||
|
TileRegistry[TYPE_BELT].animation.frameCount = frameCount;
|
||||||
|
TileRegistry[TYPE_BELT].animation.divisor = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_SetRenderTarget(renderer, oldTarget);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void renderBelt(int x, int y, int w, int h, OrientDirection dir, SDL_Rect playerRect, SDL_Renderer *renderer) {
|
void renderBelt(int x, int y, int w, int h, OrientDirection dir, SDL_Rect playerRect, SDL_Renderer *renderer) {
|
||||||
int px = x * TILE_SIZE;
|
int px = x * TILE_SIZE;
|
||||||
int py = y * TILE_SIZE;
|
int py = y * TILE_SIZE;
|
||||||
|
|
||||||
Tile *t = &tileMap[y][x];
|
SDL_Rect dst = {px, py, w, h};
|
||||||
|
adjustRect(&dst, playerRect);
|
||||||
ItemType tileType = t->type;
|
|
||||||
|
|
||||||
SDL_Rect src1, src2, dst1, dst2;
|
|
||||||
|
|
||||||
if (dir == ORIENT_LEFT || dir == ORIENT_RIGHT) {
|
|
||||||
int offset = scrollFrame % TILE_SIZE;
|
|
||||||
|
|
||||||
if (dir == ORIENT_RIGHT) {
|
|
||||||
offset = TILE_SIZE - offset; // reverse scroll
|
|
||||||
}
|
|
||||||
|
|
||||||
src1 = (SDL_Rect) {offset, 0, TILE_SIZE - offset, TILE_SIZE};
|
|
||||||
dst1 = (SDL_Rect) {px, py, (w - offset), h};
|
|
||||||
|
|
||||||
src2 = (SDL_Rect) {0, 0, offset, TILE_SIZE};
|
|
||||||
dst2 = (SDL_Rect) {px + (w - offset), py, offset, h};
|
|
||||||
|
|
||||||
adjustRect(&dst1, playerRect);
|
|
||||||
adjustRect(&dst2, playerRect);
|
|
||||||
|
|
||||||
SDL_RenderCopy(renderer, TileRegistry[tileType].textures[dir], &src1, &dst1); //TODO CONVERT TO ATLAS
|
|
||||||
SDL_RenderCopy(renderer, TileRegistry[tileType].textures[dir], &src2, &dst2); //TODO CONVERT TO ATLAS
|
|
||||||
// SDL_RenderCopyx(renderer, atlasTexture, &TileRegistry[tileType].atlasRects[dir], NULL);
|
|
||||||
// SDL_RenderCopyx(renderer, atlasTexture, &TileRegistry[tileType].atlasRects[dir], NULL);
|
|
||||||
} else {
|
|
||||||
int offset = scrollFrame % TILE_SIZE;
|
|
||||||
|
|
||||||
if (dir == ORIENT_DOWN) {
|
|
||||||
offset = TILE_SIZE - offset; // reverse scroll
|
|
||||||
}
|
|
||||||
|
|
||||||
src1 = (SDL_Rect) {0, offset, TILE_SIZE, TILE_SIZE - offset};
|
|
||||||
dst1 = (SDL_Rect) {px, py, w, h - offset};
|
|
||||||
|
|
||||||
src2 = (SDL_Rect) {0, 0, TILE_SIZE, offset};
|
|
||||||
dst2 = (SDL_Rect) {px, py + (h - offset), w, offset};
|
|
||||||
|
|
||||||
adjustRect(&dst1, playerRect);
|
|
||||||
adjustRect(&dst2, playerRect);
|
|
||||||
|
|
||||||
|
|
||||||
// Rotate to make the belt vertical
|
|
||||||
// SDL_RenderCopyx(renderer, atlasTexture, &ItemRegistry[item.type].atlasRectsOnBelt[ORIENT_LEFT], NULL);
|
|
||||||
// SDL_RenderCopyx(renderer, atlasTexture, &ItemRegistry[item.type].atlasRectsOnBelt[ORIENT_LEFT], NULL);
|
|
||||||
|
|
||||||
SDL_RenderCopy(renderer, TileRegistry[tileType].textures[dir], &src1, &dst1);
|
|
||||||
SDL_RenderCopy(renderer, TileRegistry[tileType].textures[dir], &src2, &dst2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void updateBelt(Tile * tile) {
|
|
||||||
|
|
||||||
|
SDL_RenderCopy(renderer, atlasTexture, &TileRegistry[TYPE_BELT].animation.atlasRects[dir][
|
||||||
|
(animationStep / TileRegistry[TYPE_BELT].animation.divisor) %
|
||||||
|
TileRegistry[TYPE_BELT].animation.frameCount],
|
||||||
|
&dst);
|
||||||
}
|
}
|
@@ -11,8 +11,7 @@
|
|||||||
|
|
||||||
struct Tile;
|
struct Tile;
|
||||||
|
|
||||||
void renderBelt(int x, int y, int w, int h, OrientDirection dir, SDL_Rect playerRect, SDL_Renderer *renderer);
|
void generateBeltFrames(SDL_Renderer *renderer);
|
||||||
|
|
||||||
void updateBelt(struct Tile * tile);
|
|
||||||
|
|
||||||
|
void renderBelt(int x, int y, int w, int h, OrientDirection dir, SDL_Rect playerRect, SDL_Renderer *renderer);
|
||||||
#endif //FACTORYGAME_BELT_H
|
#endif //FACTORYGAME_BELT_H
|
||||||
|
@@ -25,6 +25,13 @@ void updateFurnace(Tile *tile) {
|
|||||||
|
|
||||||
if (targetOutItemType != TYPE_AIR) {
|
if (targetOutItemType != TYPE_AIR) {
|
||||||
if (tile->miscVal == 0) {
|
if (tile->miscVal == 0) {
|
||||||
|
if (outItem->type != TYPE_AIR) {
|
||||||
|
if (tile->audioCh < NUM_SYNTH_VOICES) {
|
||||||
|
audioData.synthVoices[tile->audioCh].volume = 0;
|
||||||
|
}
|
||||||
|
tile->fixedFrame = 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
tile->audioCh = getAvailableChannel();
|
tile->audioCh = getAvailableChannel();
|
||||||
if (tile->audioCh < NUM_SYNTH_VOICES) {
|
if (tile->audioCh < NUM_SYNTH_VOICES) {
|
||||||
audioData.synthVoices[tile->audioCh].volume = 255;
|
audioData.synthVoices[tile->audioCh].volume = 255;
|
||||||
@@ -34,6 +41,7 @@ void updateFurnace(Tile *tile) {
|
|||||||
audioData.synthVoices[tile->audioCh].waveform = WAVE_SINE;
|
audioData.synthVoices[tile->audioCh].waveform = WAVE_SINE;
|
||||||
audioData.synthVoices[tile->audioCh].frequency = 200;
|
audioData.synthVoices[tile->audioCh].frequency = 200;
|
||||||
}
|
}
|
||||||
|
tile->fixedFrame = 0;
|
||||||
}
|
}
|
||||||
++audioData.synthVoices[tile->audioCh].frequency;
|
++audioData.synthVoices[tile->audioCh].frequency;
|
||||||
if (audioData.synthVoices[tile->audioCh].volume < 255) {
|
if (audioData.synthVoices[tile->audioCh].volume < 255) {
|
||||||
@@ -43,10 +51,13 @@ void updateFurnace(Tile *tile) {
|
|||||||
if (tile->audioCh < NUM_SYNTH_VOICES) {
|
if (tile->audioCh < NUM_SYNTH_VOICES) {
|
||||||
audioData.synthVoices[tile->audioCh].volume = 0;
|
audioData.synthVoices[tile->audioCh].volume = 0;
|
||||||
}
|
}
|
||||||
|
tile->fixedFrame = 1;
|
||||||
tile->miscVal = 0;
|
tile->miscVal = 0;
|
||||||
inItem->type = 0;
|
inItem->type = 0;
|
||||||
outItem->type = targetOutItemType;
|
outItem->type = targetOutItemType;
|
||||||
outItem->offset = -0.5f;
|
outItem->offset = -0.5f;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
tile->fixedFrame = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -23,6 +23,7 @@ void updateMiner(Tile *tile) {
|
|||||||
if (targetOutItemType != TYPE_AIR && outItem->type == 0) {
|
if (targetOutItemType != TYPE_AIR && outItem->type == 0) {
|
||||||
if (tile->miscVal == 0) {
|
if (tile->miscVal == 0) {
|
||||||
tile->audioCh = getAvailableChannel();
|
tile->audioCh = getAvailableChannel();
|
||||||
|
tile->fixedFrame = 0;
|
||||||
if (tile->audioCh < NUM_SYNTH_VOICES) {
|
if (tile->audioCh < NUM_SYNTH_VOICES) {
|
||||||
audioData.synthVoices[tile->audioCh].volume = 64;
|
audioData.synthVoices[tile->audioCh].volume = 64;
|
||||||
audioData.synthVoices[tile->audioCh].phase = 0;
|
audioData.synthVoices[tile->audioCh].phase = 0;
|
||||||
@@ -36,9 +37,12 @@ void updateMiner(Tile *tile) {
|
|||||||
if (tile->audioCh < NUM_SYNTH_VOICES) {
|
if (tile->audioCh < NUM_SYNTH_VOICES) {
|
||||||
audioData.synthVoices[tile->audioCh].volume = 0;
|
audioData.synthVoices[tile->audioCh].volume = 0;
|
||||||
}
|
}
|
||||||
|
tile->fixedFrame = 1;
|
||||||
tile->miscVal = 0;
|
tile->miscVal = 0;
|
||||||
outItem->type = targetOutItemType;
|
outItem->type = targetOutItemType;
|
||||||
outItem->offset = -0.5f;
|
outItem->offset = -0.5f;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
tile->fixedFrame = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
234
tiles/tile.c
@@ -2,6 +2,7 @@
|
|||||||
// Created by bruno on 4/24/25.
|
// Created by bruno on 4/24/25.
|
||||||
//
|
//
|
||||||
|
|
||||||
|
#include <dirent.h>
|
||||||
#include "tile.h"
|
#include "tile.h"
|
||||||
#include "../player/player.h"
|
#include "../player/player.h"
|
||||||
#include "furnace.h"
|
#include "furnace.h"
|
||||||
@@ -73,57 +74,189 @@ void generateTestMap() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void registerTile(char name[20], SDL_Renderer *renderer) {
|
void registerTile(char fname[20], SDL_Renderer *renderer) {
|
||||||
const char *dot = strchr(name, '.');
|
|
||||||
memcpy(TileRegistry[tileTypeIndex].name, name, dot - name);
|
char name[21];
|
||||||
|
|
||||||
|
// Load animation frames
|
||||||
|
int frame = 0;
|
||||||
|
int indexTile = 0;
|
||||||
char texturePath[80];
|
char texturePath[80];
|
||||||
snprintf(texturePath, 80, "./assets/tiles/%s", name);
|
|
||||||
|
if (sscanf(fname, "%d_%20[^_]_%d.png", &indexTile, name, &frame) == 3) {
|
||||||
|
// Success: you now have index, fname, and frame
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "Invalid format: %s\n", fname);
|
||||||
|
}
|
||||||
|
strcpy(TileRegistry[indexTile].name, name);
|
||||||
|
snprintf(texturePath, sizeof(texturePath), "./assets/tiles/%s", fname);
|
||||||
|
|
||||||
SDL_Texture *texture = IMG_LoadTexture(renderer, texturePath);
|
SDL_Texture *texture = IMG_LoadTexture(renderer, texturePath);
|
||||||
TileRegistry[tileTypeIndex].textures[ORIENT_LEFT] = texture;
|
if (!texture) {
|
||||||
TileRegistry[tileTypeIndex].textures[ORIENT_RIGHT] = createFlippedTexture(renderer, texture, SDL_FLIP_HORIZONTAL);
|
// Stop loading frames if the first one fails, or after all valid ones are added
|
||||||
TileRegistry[tileTypeIndex].textures[ORIENT_UP] = createRotatedTexture(renderer, texture, 90);
|
if (frame == 0) {
|
||||||
TileRegistry[tileTypeIndex].textures[ORIENT_DOWN] = createRotatedTexture(renderer, texture, 270);
|
fprintf(stderr, "Failed to load tile texture %s: %s\n", texturePath, IMG_GetError());
|
||||||
SDL_SetTextureBlendMode(TileRegistry[tileTypeIndex].textures[ORIENT_LEFT], SDL_BLENDMODE_BLEND);
|
}
|
||||||
SDL_SetTextureBlendMode(TileRegistry[tileTypeIndex].textures[ORIENT_RIGHT], SDL_BLENDMODE_BLEND);
|
}
|
||||||
SDL_SetTextureBlendMode(TileRegistry[tileTypeIndex].textures[ORIENT_UP], SDL_BLENDMODE_BLEND);
|
|
||||||
SDL_SetTextureBlendMode(TileRegistry[tileTypeIndex].textures[ORIENT_DOWN], SDL_BLENDMODE_BLEND);
|
|
||||||
|
|
||||||
TileRegistry[tileTypeIndex].atlasRects[ORIENT_LEFT] = allocate_32x32(
|
for (int o = 0; o < ORIENT_DIRECTION_COUNT; o++) {
|
||||||
TileRegistry[tileTypeIndex].textures[ORIENT_LEFT], renderer);
|
SDL_Texture *textures[ORIENT_DIRECTION_COUNT] = {
|
||||||
TileRegistry[tileTypeIndex].atlasRects[ORIENT_RIGHT] = allocate_32x32(
|
NULL,
|
||||||
TileRegistry[tileTypeIndex].textures[ORIENT_RIGHT], renderer);
|
texture,
|
||||||
TileRegistry[tileTypeIndex].atlasRects[ORIENT_UP] = allocate_32x32(TileRegistry[tileTypeIndex].textures[ORIENT_UP],
|
NULL,
|
||||||
renderer);
|
createFlippedTexture(renderer, texture, SDL_FLIP_HORIZONTAL),
|
||||||
TileRegistry[tileTypeIndex].atlasRects[ORIENT_DOWN] = allocate_32x32(
|
NULL,
|
||||||
TileRegistry[tileTypeIndex].textures[ORIENT_DOWN], renderer);
|
createRotatedTexture(renderer, texture, 90),
|
||||||
|
NULL,
|
||||||
|
createRotatedTexture(renderer, texture, 270)
|
||||||
|
};
|
||||||
|
|
||||||
TileRegistry[tileTypeIndex].type = tileTypeIndex;
|
printf("Bound %s to %d orient %s\n", fname, indexTile, OrientStrings[o]);
|
||||||
TileRegistry[tileTypeIndex].breakTime = 15;
|
TileRegistry[indexTile].animation.textures[o][frame] = textures[o];
|
||||||
|
SDL_SetTextureBlendMode(textures[o], SDL_BLENDMODE_BLEND);
|
||||||
|
TileRegistry[indexTile].animation.atlasRects[o][frame] = allocate_32x32(textures[o], renderer);
|
||||||
|
}
|
||||||
|
|
||||||
tileTypeIndex++;
|
TileRegistry[indexTile].type = indexTile;
|
||||||
|
TileRegistry[indexTile].animation.frameCount = frame + 1;
|
||||||
|
TileRegistry[indexTile].animation.divisor = 1;
|
||||||
|
|
||||||
|
TileRegistry[indexTile].type = tileTypeIndex;
|
||||||
|
TileRegistry[indexTile].breakTime = 15;
|
||||||
|
|
||||||
|
if (indexTile + 1 > tileTypeIndex) {
|
||||||
|
tileTypeIndex = indexTile + 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void registerBackgroundTile(char name[20], SDL_Renderer *renderer) {
|
|
||||||
const char *dot = strchr(name, '.');
|
void registerBackgroundTile(char fname[20], SDL_Renderer *renderer) {
|
||||||
memcpy(BackgroundTileRegistry[backgroundTileTypeIndex].name, name, dot - name);
|
char name[21];
|
||||||
|
|
||||||
|
// Load animation frames
|
||||||
|
int frame = 0;
|
||||||
|
int indexBgTile = 0;
|
||||||
char texturePath[80];
|
char texturePath[80];
|
||||||
snprintf(texturePath, 80, "./assets/backgrounds/%s", name);
|
|
||||||
|
if (sscanf(fname, "%d_%20[^_]_%d.png", &indexBgTile, name, &frame) == 3) {
|
||||||
|
// Success: you now have index, fname, and frame
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "Invalid format: %s\n", fname);
|
||||||
|
}
|
||||||
|
strcpy(BackgroundTileRegistry[indexBgTile].name, name);
|
||||||
|
snprintf(texturePath, sizeof(texturePath), "./assets/backgrounds/%s", fname);
|
||||||
SDL_Texture *texture = IMG_LoadTexture(renderer, texturePath);
|
SDL_Texture *texture = IMG_LoadTexture(renderer, texturePath);
|
||||||
BackgroundTileRegistry[backgroundTileTypeIndex].texture = texture;
|
if (!texture) {
|
||||||
SDL_SetTextureBlendMode(BackgroundTileRegistry[backgroundTileTypeIndex].texture, SDL_BLENDMODE_NONE);
|
if (frame == 0) {
|
||||||
BackgroundTileRegistry[backgroundTileTypeIndex].atlasRect = allocate_32x32(
|
fprintf(stderr, "Failed to load background texture %s: %s\n", texturePath, IMG_GetError());
|
||||||
BackgroundTileRegistry[backgroundTileTypeIndex].texture, renderer);
|
}
|
||||||
|
}
|
||||||
|
|
||||||
BackgroundTileRegistry[backgroundTileTypeIndex].type = backgroundTileTypeIndex;
|
SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_NONE);
|
||||||
|
|
||||||
backgroundTileTypeIndex++;
|
printf("Bound %s to %d\n", fname, indexBgTile);
|
||||||
|
|
||||||
|
BackgroundTileRegistry[indexBgTile].animation.textures[frame] = texture;
|
||||||
|
BackgroundTileRegistry[indexBgTile].animation.atlasRects[frame] = allocate_32x32(texture, renderer);
|
||||||
|
|
||||||
|
BackgroundTileRegistry[indexBgTile].type = indexBgTile;
|
||||||
|
BackgroundTileRegistry[indexBgTile].animation.frameCount = frame + 1;
|
||||||
|
BackgroundTileRegistry[indexBgTile].animation.divisor = 1;
|
||||||
|
|
||||||
|
if (indexBgTile + 1 > backgroundTileTypeIndex) {
|
||||||
|
backgroundTileTypeIndex = indexBgTile + 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int compareStrings(const void *a, const void *b) {
|
||||||
|
const char *strA = *(const char **) a;
|
||||||
|
const char *strB = *(const char **) b;
|
||||||
|
return strcmp(strA, strB);
|
||||||
|
}
|
||||||
|
|
||||||
void loadTiles(SDL_Renderer *renderer) {
|
void loadTiles(SDL_Renderer *renderer) {
|
||||||
iterateSortedDir("./assets/tiles", (DirEntryCallback) registerTile, renderer);
|
DIR *dir = opendir("./assets/tiles");
|
||||||
iterateSortedDir("./assets/backgrounds", (DirEntryCallback) registerBackgroundTile, renderer);
|
if (!dir) {
|
||||||
|
perror("Failed to open tiles directory");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *baseNames[MAX_BASE_NAMES];
|
||||||
|
int baseNameCount = 0;
|
||||||
|
|
||||||
|
struct dirent *entry;
|
||||||
|
while ((entry = readdir(dir))) {
|
||||||
|
char *dot = strrchr(entry->d_name, '.');
|
||||||
|
if (!dot || strcmp(dot, ".png") != 0) continue;
|
||||||
|
|
||||||
|
// Check if baseName already stored
|
||||||
|
int found = 0;
|
||||||
|
for (int i = 0; i < baseNameCount; ++i) {
|
||||||
|
if (strcmp(baseNames[i], entry->d_name) == 0) {
|
||||||
|
found = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found && baseNameCount < MAX_BASE_NAMES) {
|
||||||
|
baseNames[baseNameCount++] = strdup(entry->d_name); // Only store base, not full file name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
closedir(dir);
|
||||||
|
|
||||||
|
qsort(baseNames, baseNameCount, sizeof(char *), compareStrings);
|
||||||
|
|
||||||
|
// Call registerTile on each base name
|
||||||
|
for (int i = 0; i < baseNameCount; ++i) {
|
||||||
|
char fileName[64];
|
||||||
|
snprintf(fileName, sizeof(fileName), "%s", baseNames[i]);
|
||||||
|
registerTile(fileName, renderer);
|
||||||
|
free(baseNames[i]);
|
||||||
|
}
|
||||||
|
generateBeltFrames(renderer);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void loadBackgroundTiles(SDL_Renderer *renderer) {
|
||||||
|
DIR *dir = opendir("./assets/backgrounds");
|
||||||
|
if (!dir) {
|
||||||
|
perror("Failed to open backgrounds directory");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *baseNames[MAX_BASE_NAMES];
|
||||||
|
int baseNameCount = 0;
|
||||||
|
|
||||||
|
struct dirent *entry;
|
||||||
|
while ((entry = readdir(dir))) {
|
||||||
|
char *dot = strrchr(entry->d_name, '.');
|
||||||
|
if (!dot || strcmp(dot, ".png") != 0) continue;
|
||||||
|
|
||||||
|
// Check if baseName already stored
|
||||||
|
int found = 0;
|
||||||
|
for (int i = 0; i < baseNameCount; ++i) {
|
||||||
|
if (strcmp(baseNames[i], entry->d_name) == 0) {
|
||||||
|
found = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found && baseNameCount < MAX_BASE_NAMES) {
|
||||||
|
baseNames[baseNameCount++] = strdup(entry->d_name); // Only store base, not full file name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
closedir(dir);
|
||||||
|
|
||||||
|
qsort(baseNames, baseNameCount, sizeof(char *), compareStrings);
|
||||||
|
|
||||||
|
// Call registerBackgroundTile on each base name
|
||||||
|
for (int i = 0; i < baseNameCount; ++i) {
|
||||||
|
char fileName[64];
|
||||||
|
snprintf(fileName, sizeof(fileName), "%s", baseNames[i]);
|
||||||
|
registerBackgroundTile(fileName, renderer);
|
||||||
|
free(baseNames[i]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void setupTiles() {
|
void setupTiles() {
|
||||||
@@ -144,10 +277,19 @@ void setupTiles() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
TileRegistry[TYPE_FURNACE].outputLane[FURNACE_OUTPUT_SLOT] = 1;
|
TileRegistry[TYPE_FURNACE].outputLane[FURNACE_OUTPUT_SLOT] = 1;
|
||||||
|
TileRegistry[TYPE_FURNACE].startFrame = 1;
|
||||||
TileRegistry[TYPE_FURNACE].needsTicks = true;
|
TileRegistry[TYPE_FURNACE].needsTicks = true;
|
||||||
|
TileRegistry[TYPE_FURNACE].animation.divisor = 8;
|
||||||
TileRegistry[TYPE_BELT].needsTicks = true;
|
TileRegistry[TYPE_BELT].needsTicks = true;
|
||||||
TileRegistry[TYPE_MINER].needsTicks = true;
|
TileRegistry[TYPE_MINER].needsTicks = true;
|
||||||
TileRegistry[TYPE_MINER].outputLane[MINER_OUTPUT_SLOT] = 1;
|
TileRegistry[TYPE_MINER].outputLane[MINER_OUTPUT_SLOT] = 1;
|
||||||
|
TileRegistry[TYPE_MINER].startFrame = 1;
|
||||||
|
|
||||||
|
BackgroundTileRegistry[BGType_WATER_DEEP].animation.divisor = 16;
|
||||||
|
BackgroundTileRegistry[BGType_WATER_SHALLOW].animation.divisor = 12;
|
||||||
|
BackgroundTileRegistry[BGType_GRASS_FLOWER0].animation.divisor = 16;
|
||||||
|
BackgroundTileRegistry[BGType_GRASS_FLOWER1].animation.divisor = 16;
|
||||||
|
BackgroundTileRegistry[BGType_GRASS_FLOWER2].animation.divisor = 16;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t getBreakTime(int type) {
|
uint16_t getBreakTime(int type) {
|
||||||
@@ -205,8 +347,11 @@ void renderAllTiles(SDL_Renderer *renderer, SDL_Rect playerRect) {
|
|||||||
adjustRect(&dstRect, playerRect);
|
adjustRect(&dstRect, playerRect);
|
||||||
|
|
||||||
BackgroundTile bt = backgroundMap[y][x];
|
BackgroundTile bt = backgroundMap[y][x];
|
||||||
SDL_Texture *tex = BackgroundTileRegistry[bt.type].texture;
|
SDL_Texture *tex = BackgroundTileRegistry[bt.type].animation.textures[animationStep %
|
||||||
SDL_Rect atlRect = BackgroundTileRegistry[bt.type].atlasRect;
|
BackgroundTileRegistry[bt.type].animation.frameCount];
|
||||||
|
SDL_Rect atlRect = BackgroundTileRegistry[bt.type].animation.atlasRects[
|
||||||
|
(animationStep / BackgroundTileRegistry[bt.type].animation.divisor) %
|
||||||
|
BackgroundTileRegistry[bt.type].animation.frameCount];
|
||||||
if (atlRect.w != 0 && atlRect.h != 0) {
|
if (atlRect.w != 0 && atlRect.h != 0) {
|
||||||
SDL_RenderCopy(renderer, atlasTexture, &atlRect, &dstRect);
|
SDL_RenderCopy(renderer, atlasTexture, &atlRect, &dstRect);
|
||||||
//SDL_RenderCopy(renderer, tex, NULL, &dstRect);
|
//SDL_RenderCopy(renderer, tex, NULL, &dstRect);
|
||||||
@@ -237,11 +382,18 @@ void renderAllTiles(SDL_Renderer *renderer, SDL_Rect playerRect) {
|
|||||||
renderBelt(x, y, tileSize, tileSize, t.direction, playerRect, renderer);
|
renderBelt(x, y, tileSize, tileSize, t.direction, playerRect, renderer);
|
||||||
break;
|
break;
|
||||||
default: {
|
default: {
|
||||||
SDL_Rect atlRect = TileRegistry[t.type].atlasRects[t.direction];
|
char animationFrame = ((animationStep / TileRegistry[t.type].animation.divisor) %
|
||||||
SDL_Texture *tex = TileRegistry[t.type].textures[t.direction];
|
(TileRegistry[t.type].animation.frameCount -
|
||||||
|
TileRegistry[t.type].startFrame)) + TileRegistry[t.type].startFrame;
|
||||||
|
if (t.fixedFrame > 0) {
|
||||||
|
animationFrame = t.fixedFrame - 1;
|
||||||
|
}
|
||||||
|
SDL_Rect atlRect = TileRegistry[t.type].animation.atlasRects[t.direction][animationFrame];
|
||||||
|
SDL_Texture *tex = TileRegistry[t.type].animation.textures[t.direction][animationFrame];
|
||||||
if (atlRect.w == 0 || atlRect.h == 0) {
|
if (atlRect.w == 0 || atlRect.h == 0) {
|
||||||
tex = TileRegistry[t.type].textures[ORIENT_LEFT];
|
tex = TileRegistry[t.type].animation.textures[ORIENT_LEFT][animationFrame];
|
||||||
atlRect = TileRegistry[t.type].atlasRects[ORIENT_LEFT];
|
atlRect = TileRegistry[t.type].animation.atlasRects[ORIENT_LEFT][
|
||||||
|
animationFrame];
|
||||||
}
|
}
|
||||||
if (atlRect.w != 0 && atlRect.h != 0) {
|
if (atlRect.w != 0 && atlRect.h != 0) {
|
||||||
//SDL_RenderCopy(renderer, tex, NULL, &dstRect);
|
//SDL_RenderCopy(renderer, tex, NULL, &dstRect);
|
||||||
|
29
tiles/tile.h
@@ -49,20 +49,14 @@ extern unsigned long beltFrames;
|
|||||||
#define ItemSlotCount 4
|
#define ItemSlotCount 4
|
||||||
|
|
||||||
typedef enum BackgroundType {
|
typedef enum BackgroundType {
|
||||||
BGType_WATER0,
|
BGType_WATER_SHALLOW,
|
||||||
BGType_WATER1,
|
BGType_WATER_DEEP,
|
||||||
BGType_GRASS0,
|
|
||||||
BGType_GRASS1,
|
|
||||||
BGType_GRASS2,
|
|
||||||
BGType_GRASS3,
|
|
||||||
BGType_GRASS4,
|
|
||||||
BGType_GRASS5,
|
|
||||||
BGType_GRASS6,
|
|
||||||
BGType_GRASS7,
|
|
||||||
BGType_GRASS_FLOWER0,
|
BGType_GRASS_FLOWER0,
|
||||||
BGType_GRASS_FLOWER1,
|
BGType_GRASS_FLOWER1,
|
||||||
BGType_GRASS_FLOWER2,
|
BGType_GRASS_FLOWER2,
|
||||||
BGType_GRASS_FLOWER3,
|
BGType_GRASS0,
|
||||||
|
BGType_GRASS1,
|
||||||
|
BGType_GRASS2,
|
||||||
BGType_SAND0,
|
BGType_SAND0,
|
||||||
BGType_SAND1,
|
BGType_SAND1,
|
||||||
BGType_SAND2,
|
BGType_SAND2,
|
||||||
@@ -86,23 +80,25 @@ typedef enum BackgroundType {
|
|||||||
BGType_END
|
BGType_END
|
||||||
} BackgroundType;
|
} BackgroundType;
|
||||||
|
|
||||||
|
#define MAX_BASE_NAMES 512
|
||||||
|
#define MAX_ANIMATION_FRAMES 32
|
||||||
|
|
||||||
typedef struct TileTypeReg {
|
typedef struct TileTypeReg {
|
||||||
ItemType type;
|
ItemType type;
|
||||||
char name[20];
|
char name[20];
|
||||||
SDL_Texture *textures[ORIENT_DIRECTION_COUNT];
|
OrientedAnimation animation;
|
||||||
SDL_Rect atlasRects[ORIENT_DIRECTION_COUNT];
|
|
||||||
uint16_t breakTime;
|
uint16_t breakTime;
|
||||||
bool itemMoves;
|
bool itemMoves;
|
||||||
bool allowedInItems[ItemSlotCount][ITEMREGISTRY_SIZE];
|
bool allowedInItems[ItemSlotCount][ITEMREGISTRY_SIZE];
|
||||||
bool outputLane[ItemSlotCount];
|
bool outputLane[ItemSlotCount];
|
||||||
bool needsTicks;
|
bool needsTicks;
|
||||||
|
char startFrame;
|
||||||
} TileTypeReg;
|
} TileTypeReg;
|
||||||
|
|
||||||
typedef struct BackgroundTileType {
|
typedef struct BackgroundTileType {
|
||||||
ItemType type;
|
ItemType type;
|
||||||
char name[20];
|
char name[20];
|
||||||
SDL_Texture *texture;
|
Animation animation;
|
||||||
SDL_Rect atlasRect;
|
|
||||||
} BackgroundTileType;
|
} BackgroundTileType;
|
||||||
|
|
||||||
typedef struct BackgroundTile {
|
typedef struct BackgroundTile {
|
||||||
@@ -127,6 +123,7 @@ typedef struct Tile {
|
|||||||
uint16_t audioCh;
|
uint16_t audioCh;
|
||||||
MiniRect rect;
|
MiniRect rect;
|
||||||
int neededUpdateIndex;
|
int neededUpdateIndex;
|
||||||
|
char fixedFrame;
|
||||||
} Tile;
|
} Tile;
|
||||||
|
|
||||||
|
|
||||||
@@ -138,6 +135,8 @@ void setupTiles();
|
|||||||
|
|
||||||
void generateTestMap();
|
void generateTestMap();
|
||||||
|
|
||||||
|
void loadBackgroundTiles(SDL_Renderer *renderer);
|
||||||
|
|
||||||
void loadTiles(SDL_Renderer *renderer);
|
void loadTiles(SDL_Renderer *renderer);
|
||||||
|
|
||||||
extern uint16_t tileTypeIndex;
|
extern uint16_t tileTypeIndex;
|
||||||
|
@@ -9,7 +9,7 @@
|
|||||||
const UpdateTileCallback ItemTileCallbacks[TILEREGISTRY_SIZE] = {
|
const UpdateTileCallback ItemTileCallbacks[TILEREGISTRY_SIZE] = {
|
||||||
[TYPE_AIR] = NULL,
|
[TYPE_AIR] = NULL,
|
||||||
[TYPE_BLOCK] = NULL,
|
[TYPE_BLOCK] = NULL,
|
||||||
[TYPE_BELT] = updateBelt,
|
[TYPE_BELT] = NULL,
|
||||||
[TYPE_FURNACE] = updateFurnace,
|
[TYPE_FURNACE] = updateFurnace,
|
||||||
[TYPE_MINER] = updateMiner
|
[TYPE_MINER] = updateMiner
|
||||||
};
|
};
|
@@ -10,7 +10,6 @@ SDL_Texture *atlasTexture;
|
|||||||
int tileIndex16 = 0, quadrantIndex16 = 0;
|
int tileIndex16 = 0, quadrantIndex16 = 0;
|
||||||
int tileIndex32 = 0;
|
int tileIndex32 = 0;
|
||||||
|
|
||||||
#define MAX_RECTS 256
|
|
||||||
int allocatedRectCount = 0;
|
int allocatedRectCount = 0;
|
||||||
SDL_Rect allocatedRects[MAX_RECTS];
|
SDL_Rect allocatedRects[MAX_RECTS];
|
||||||
|
|
||||||
|
@@ -5,7 +5,8 @@
|
|||||||
#ifndef FACTORYGAME_ATLAS_H
|
#ifndef FACTORYGAME_ATLAS_H
|
||||||
#define FACTORYGAME_ATLAS_H
|
#define FACTORYGAME_ATLAS_H
|
||||||
|
|
||||||
#define ATLAS_SIZE 512
|
#define ATLAS_SIZE 1024
|
||||||
|
#define MAX_RECTS 2048
|
||||||
#define TILE_SIZE 32
|
#define TILE_SIZE 32
|
||||||
#define QUADRANT_SIZE 16
|
#define QUADRANT_SIZE 16
|
||||||
#define ATLAS_TILES_PER_ROW (ATLAS_SIZE / TILE_SIZE)
|
#define ATLAS_TILES_PER_ROW (ATLAS_SIZE / TILE_SIZE)
|
||||||
|
13
util/util.c
@@ -11,6 +11,19 @@
|
|||||||
SDL_Window *window = NULL;
|
SDL_Window *window = NULL;
|
||||||
volatile bool running = true;
|
volatile bool running = true;
|
||||||
|
|
||||||
|
const char OrientStrings[ORIENT_DIRECTION_COUNT][10] = {
|
||||||
|
"LEFT_DOWN",
|
||||||
|
"LEFT",
|
||||||
|
"LEFT_UP",
|
||||||
|
"UP",
|
||||||
|
"RIGHT_UP",
|
||||||
|
"RIGHT",
|
||||||
|
"RIGHT_DOWN",
|
||||||
|
"DOWN",
|
||||||
|
};
|
||||||
|
|
||||||
|
int animationStep = 0;
|
||||||
|
|
||||||
bool debugMode = false;
|
bool debugMode = false;
|
||||||
bool itemViewing = false;
|
bool itemViewing = false;
|
||||||
bool renderAtlas = false;
|
bool renderAtlas = false;
|
||||||
|
23
util/util.h
@@ -6,6 +6,9 @@
|
|||||||
#define FACTORYGAME_UTIL_H
|
#define FACTORYGAME_UTIL_H
|
||||||
|
|
||||||
#include <SDL2/SDL.h>
|
#include <SDL2/SDL.h>
|
||||||
|
#include "atlas.h"
|
||||||
|
|
||||||
|
extern int animationStep;
|
||||||
|
|
||||||
//The window we'll be rendering to
|
//The window we'll be rendering to
|
||||||
extern SDL_Window *window;
|
extern SDL_Window *window;
|
||||||
@@ -16,7 +19,7 @@ extern SDL_Renderer *mainRenderer;
|
|||||||
|
|
||||||
extern SDL_Rect screenRect;
|
extern SDL_Rect screenRect;
|
||||||
|
|
||||||
typedef enum OrientDirection{
|
typedef enum OrientDirection {
|
||||||
ORIENT_LEFT_DOWN,
|
ORIENT_LEFT_DOWN,
|
||||||
ORIENT_LEFT,
|
ORIENT_LEFT,
|
||||||
ORIENT_LEFT_UP,
|
ORIENT_LEFT_UP,
|
||||||
@@ -28,10 +31,28 @@ typedef enum OrientDirection{
|
|||||||
ORIENT_DIRECTION_COUNT
|
ORIENT_DIRECTION_COUNT
|
||||||
} OrientDirection;
|
} OrientDirection;
|
||||||
|
|
||||||
|
extern const char OrientStrings[ORIENT_DIRECTION_COUNT][10];
|
||||||
|
|
||||||
extern bool debugMode;
|
extern bool debugMode;
|
||||||
extern bool itemViewing;
|
extern bool itemViewing;
|
||||||
extern bool renderAtlas;
|
extern bool renderAtlas;
|
||||||
|
|
||||||
|
typedef struct Animation {
|
||||||
|
SDL_Texture *textures[TILE_SIZE];
|
||||||
|
SDL_Rect atlasRects[TILE_SIZE];
|
||||||
|
unsigned char frameCount;
|
||||||
|
unsigned char divisor;
|
||||||
|
} Animation;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct OrientedAnimation {
|
||||||
|
SDL_Texture *textures[ORIENT_DIRECTION_COUNT][TILE_SIZE * 2];
|
||||||
|
SDL_Rect atlasRects[ORIENT_DIRECTION_COUNT][TILE_SIZE * 2];
|
||||||
|
unsigned char frameCount;
|
||||||
|
unsigned char divisor;
|
||||||
|
} OrientedAnimation;
|
||||||
|
|
||||||
|
|
||||||
SDL_Texture *createRotatedTexture(SDL_Renderer *renderer, SDL_Texture *src, double angle);
|
SDL_Texture *createRotatedTexture(SDL_Renderer *renderer, SDL_Texture *src, double angle);
|
||||||
|
|
||||||
SDL_Texture *createFlippedTexture(SDL_Renderer *renderer, SDL_Texture *src, SDL_RendererFlip flip);
|
SDL_Texture *createFlippedTexture(SDL_Renderer *renderer, SDL_Texture *src, SDL_RendererFlip flip);
|
||||||
|