start turret
This commit is contained in:
@@ -49,6 +49,8 @@ set(SOURCE_FILES
|
|||||||
util/pathfinding.h
|
util/pathfinding.h
|
||||||
entity/entity.c
|
entity/entity.c
|
||||||
entity/entity.h
|
entity/entity.h
|
||||||
|
tiles/turret.c
|
||||||
|
tiles/turret.h
|
||||||
)
|
)
|
||||||
|
|
||||||
add_executable(factorygame ${SOURCE_FILES})
|
add_executable(factorygame ${SOURCE_FILES})
|
||||||
|
BIN
assets/tiles/05_turret_00.png
Normal file
BIN
assets/tiles/05_turret_00.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 239 B |
BIN
assets/tiles/05_turret_01.png
Normal file
BIN
assets/tiles/05_turret_01.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 261 B |
BIN
assets/tiles/05_turret_02.png
Normal file
BIN
assets/tiles/05_turret_02.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 256 B |
BIN
assets/tiles/05_turret_03.png
Normal file
BIN
assets/tiles/05_turret_03.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 265 B |
BIN
assets/tiles/05_turret_04.png
Normal file
BIN
assets/tiles/05_turret_04.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 252 B |
@@ -7,6 +7,7 @@
|
|||||||
#include "entity.h"
|
#include "entity.h"
|
||||||
#include "../player/player.h"
|
#include "../player/player.h"
|
||||||
#include "../util/pathfinding.h"
|
#include "../util/pathfinding.h"
|
||||||
|
#include "../util/font.h"
|
||||||
|
|
||||||
EntityArray entities;
|
EntityArray entities;
|
||||||
|
|
||||||
@@ -26,40 +27,52 @@ void renderEntities(SDL_Renderer *renderer, SDL_Rect playerRect) {
|
|||||||
EntityTypeReg entType = EntityRegistry[ent->type];
|
EntityTypeReg entType = EntityRegistry[ent->type];
|
||||||
char animationFrame = (animationStep / entType.animation.divisor) % entType.animation.frameCount;
|
char animationFrame = (animationStep / entType.animation.divisor) % entType.animation.frameCount;
|
||||||
SDL_RenderCopy(renderer, atlasTexture, &entType.animation.atlasRects[animationFrame], &renderRect);
|
SDL_RenderCopy(renderer, atlasTexture, &entType.animation.atlasRects[animationFrame], &renderRect);
|
||||||
|
char healthStr[12];
|
||||||
|
snprintf(healthStr, 12, "%d/%d", ent->health, entType.maxHealth);
|
||||||
|
renderText(renderer, fonts[2], healthStr, renderRect.x, renderRect.y);
|
||||||
}
|
}
|
||||||
SDL_SetRenderTarget(renderer, oldTarget);
|
SDL_SetRenderTarget(renderer, oldTarget);
|
||||||
}
|
}
|
||||||
|
|
||||||
void updateEntities() {
|
void updateEntities() {
|
||||||
for (int i = 0; i < entities.activeCount; i++) {
|
for (int i = 0; i < entities.activeCount; i++) {
|
||||||
Entity *ent = &entities.entities[i];
|
Entity *ent = &entities.entities[i];
|
||||||
EntityTypeReg entT = EntityRegistry[ent->type];
|
EntityTypeReg entT = EntityRegistry[ent->type];
|
||||||
|
|
||||||
// Step 1: If no path, or we're at the end of a path, check for re-path
|
if (ent->health > entT.maxHealth || ent->health <= 0) {
|
||||||
|
remove_entity(&entities, i);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
bool atTargetSnapshot = ent->tileRect.x == ent->targetSnapshot.x &&
|
bool atTargetSnapshot = ent->tileRect.x == ent->targetSnapshot.x &&
|
||||||
ent->tileRect.y == ent->targetSnapshot.y;
|
ent->tileRect.y == ent->targetSnapshot.y;
|
||||||
|
|
||||||
bool needsPath = ent->path.length == 0 || ent->path.stepIndex >= ent->path.length;
|
bool atTarget = ent->tileRect.x == ent->target.x &&
|
||||||
|
ent->tileRect.y == ent->target.y;
|
||||||
|
|
||||||
if (needsPath && (atTargetSnapshot || ent->path.length == 0)) {
|
// Retry pathfinding every 10 ticks if we don't have a path and aren't at the target
|
||||||
if (ent->tileRect.x != ent->target.x || ent->tileRect.y != ent->target.y) {
|
bool shouldRetryPathfinding = (
|
||||||
if (isWalkable(ent->target) && find_path(ent->tileRect, ent->target)) {
|
ent->path.length == 0 &&
|
||||||
ent->path = reconstruct_path(ent->target);
|
!atTarget &&
|
||||||
ent->path.stepIndex = 0;
|
(animationStep % 10 == 0)
|
||||||
ent->targetSnapshot = ent->target; // snapshot the current target
|
);
|
||||||
ent->fromTile = ent->tileRect;
|
|
||||||
ent->toTile = ent->path.steps[0];
|
// Also try pathfinding if we reached the snapshot (end of path)
|
||||||
ent->interpolateTick = 0;
|
if (atTargetSnapshot || shouldRetryPathfinding) {
|
||||||
ent->entityNextTick = animationStep + entT.entityTickRate;
|
if (isWalkable(ent->target) && find_path(ent->tileRect, ent->target)) {
|
||||||
} else {
|
ent->path = reconstruct_path(ent->target);
|
||||||
// No path found — freeze
|
ent->path.stepIndex = 0;
|
||||||
ent->path.length = 0;
|
ent->targetSnapshot = ent->target; // snapshot the current target
|
||||||
continue;
|
ent->fromTile = ent->tileRect;
|
||||||
}
|
ent->toTile = ent->path.steps[0];
|
||||||
|
ent->interpolateTick = 0;
|
||||||
|
ent->entityNextTick = animationStep + entT.entityTickRate;
|
||||||
|
} else if (atTargetSnapshot) {
|
||||||
|
// No path found and we finished current one — freeze
|
||||||
|
ent->path.length = 0;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 2: If it's time to move to the next tile
|
// Step 2: Movement
|
||||||
if (ent->path.length > 0 && ent->path.stepIndex < ent->path.length &&
|
if (ent->path.length > 0 && ent->path.stepIndex < ent->path.length &&
|
||||||
animationStep >= ent->entityNextTick) {
|
animationStep >= ent->entityNextTick) {
|
||||||
ent->fromTile = ent->tileRect;
|
ent->fromTile = ent->tileRect;
|
||||||
@@ -70,7 +83,7 @@ void updateEntities() {
|
|||||||
ent->path.stepIndex++;
|
ent->path.stepIndex++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 3: Interpolate renderRect between fromTile and toTile
|
// Step 3: Interpolation
|
||||||
MiniRect from = {
|
MiniRect from = {
|
||||||
.x = ent->fromTile.x * TILE_SIZE,
|
.x = ent->fromTile.x * TILE_SIZE,
|
||||||
.y = ent->fromTile.y * TILE_SIZE
|
.y = ent->fromTile.y * TILE_SIZE
|
||||||
@@ -93,6 +106,7 @@ void updateEntities() {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void registerEntity(char fname[20], SDL_Renderer *renderer) {
|
void registerEntity(char fname[20], SDL_Renderer *renderer) {
|
||||||
char name[21];
|
char name[21];
|
||||||
|
|
||||||
@@ -117,7 +131,7 @@ void registerEntity(char fname[20], SDL_Renderer *renderer) {
|
|||||||
|
|
||||||
SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_NONE);
|
SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_NONE);
|
||||||
|
|
||||||
printf("Ent %s to %d\n", fname, indexEntity);
|
//printf("Ent %s to %d\n", fname, indexEntity);
|
||||||
|
|
||||||
EntityRegistry[indexEntity].animation.textures[frame] = texture;
|
EntityRegistry[indexEntity].animation.textures[frame] = texture;
|
||||||
EntityRegistry[indexEntity].animation.atlasRects[frame] = allocate_32x32(texture, renderer);
|
EntityRegistry[indexEntity].animation.atlasRects[frame] = allocate_32x32(texture, renderer);
|
||||||
@@ -126,6 +140,7 @@ void registerEntity(char fname[20], SDL_Renderer *renderer) {
|
|||||||
EntityRegistry[indexEntity].animation.frameCount = frame + 1;
|
EntityRegistry[indexEntity].animation.frameCount = frame + 1;
|
||||||
EntityRegistry[indexEntity].animation.divisor = 1;
|
EntityRegistry[indexEntity].animation.divisor = 1;
|
||||||
EntityRegistry[indexEntity].entityTickRate = 8;
|
EntityRegistry[indexEntity].entityTickRate = 8;
|
||||||
|
EntityRegistry[indexEntity].maxHealth = 100;
|
||||||
|
|
||||||
if (indexEntity + 1 > backgroundTileTypeIndex) {
|
if (indexEntity + 1 > backgroundTileTypeIndex) {
|
||||||
backgroundTileTypeIndex = indexEntity + 1;
|
backgroundTileTypeIndex = indexEntity + 1;
|
||||||
|
@@ -20,13 +20,14 @@ typedef struct EntityTypeReg {
|
|||||||
char name[20];
|
char name[20];
|
||||||
int speed;
|
int speed;
|
||||||
int entityTickRate;
|
int entityTickRate;
|
||||||
|
uint16_t maxHealth;
|
||||||
} EntityTypeReg;
|
} EntityTypeReg;
|
||||||
|
|
||||||
typedef struct Entity {
|
typedef struct Entity {
|
||||||
MiniRect tileRect;
|
MiniRect tileRect;
|
||||||
SDL_Rect renderRect;
|
SDL_Rect renderRect;
|
||||||
EntityType type;
|
EntityType type;
|
||||||
uint16_t health;
|
int16_t health;
|
||||||
MiniRect target;
|
MiniRect target;
|
||||||
Path path;
|
Path path;
|
||||||
int entityNextTick;
|
int entityNextTick;
|
||||||
|
44
items/item.c
44
items/item.c
@@ -20,6 +20,28 @@ const int dirDx[8] = {-1, -1, -1, 0, 1, 1, 1, 0};
|
|||||||
const int dirDy[8] = {1, 0, -1, -1, -1, 0, 1, 1};
|
const int dirDy[8] = {1, 0, -1, -1, -1, 0, 1, 1};
|
||||||
|
|
||||||
const float epsilon = 0.999f; // if we can't move, back it off just below 1
|
const float epsilon = 0.999f; // if we can't move, back it off just below 1
|
||||||
|
|
||||||
|
bool putOntoNext(ItemOnBelt *itm, int nx, int ny, Tile *next, TileTypeReg *ntt, int newLane) {
|
||||||
|
if (next->items[newLane].type == 0 && (*ntt).allowedInItems[newLane][itm->type]) {
|
||||||
|
// MOVE it
|
||||||
|
ItemOnBelt moved = *itm;
|
||||||
|
moved.tileX = nx;
|
||||||
|
moved.tileY = ny;
|
||||||
|
if (!(*ntt).itemMoves) {
|
||||||
|
moved.offset = 0.5f;
|
||||||
|
}
|
||||||
|
next->items[newLane] = moved;
|
||||||
|
|
||||||
|
// clear this one
|
||||||
|
itm->type = 0;
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
// both slots full → wait at end
|
||||||
|
itm->offset = epsilon;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void updateItems() {
|
void updateItems() {
|
||||||
|
|
||||||
for (int i = 0; i < neededUpdates.activeCount; i++) {
|
for (int i = 0; i < neededUpdates.activeCount; i++) {
|
||||||
@@ -89,25 +111,13 @@ void updateItems() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (next->items[newLane].type == 0 && ntt.allowedInItems[newLane][itm->type]) {
|
if (!putOntoNext(itm, nx, ny, next, &ntt, newLane) && next->type != TYPE_BELT) {
|
||||||
// MOVE it
|
for (uint8_t nLane = 0; nLane < ItemSlotCount; nLane++) {
|
||||||
ItemOnBelt moved = *itm;
|
if (putOntoNext(itm, nx, ny, next, &ntt, nLane)) {
|
||||||
moved.tileX = nx;
|
break;
|
||||||
moved.tileY = ny;
|
}
|
||||||
if (!ntt.itemMoves) {
|
|
||||||
moved.offset = 0.5f;
|
|
||||||
}
|
}
|
||||||
next->items[newLane] = moved;
|
|
||||||
|
|
||||||
// clear this one
|
|
||||||
itm->type = 0;
|
|
||||||
} else {
|
|
||||||
// both slots full → wait at end
|
|
||||||
itm->offset = epsilon;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const UpdateTileCallback cb = ItemTileCallbacks[t->type];
|
const UpdateTileCallback cb = ItemTileCallbacks[t->type];
|
||||||
|
@@ -19,6 +19,7 @@ typedef enum ItemType {
|
|||||||
TYPE_BELT,
|
TYPE_BELT,
|
||||||
TYPE_FURNACE,
|
TYPE_FURNACE,
|
||||||
TYPE_MINER,
|
TYPE_MINER,
|
||||||
|
TYPE_TURRET,
|
||||||
IRON_ORE = ITEMREGISTRY_SIZE / 2,
|
IRON_ORE = ITEMREGISTRY_SIZE / 2,
|
||||||
SILVER_ORE,
|
SILVER_ORE,
|
||||||
GOLD_ORE,
|
GOLD_ORE,
|
||||||
|
64
main.c
64
main.c
@@ -24,7 +24,6 @@ typedef struct GameState {
|
|||||||
GameState gameState;
|
GameState gameState;
|
||||||
|
|
||||||
int loadGameState(char *filename, Player *plr) {
|
int loadGameState(char *filename, Player *plr) {
|
||||||
printf("hello from load\n");
|
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
FILE *gameSave = fopen(filename, "rb");
|
FILE *gameSave = fopen(filename, "rb");
|
||||||
if (gameSave) {
|
if (gameSave) {
|
||||||
@@ -154,18 +153,6 @@ int init() {
|
|||||||
loadItems(mainRenderer);
|
loadItems(mainRenderer);
|
||||||
loadEntities(mainRenderer);
|
loadEntities(mainRenderer);
|
||||||
|
|
||||||
Entity entTest;
|
|
||||||
memset(&entTest, 0, sizeof(Entity));
|
|
||||||
entTest.tileRect.x = 4;
|
|
||||||
entTest.tileRect.y = 5;
|
|
||||||
entTest.renderRect.w = TILE_SIZE;
|
|
||||||
entTest.renderRect.h = TILE_SIZE;
|
|
||||||
entTest.target.x = 0;
|
|
||||||
entTest.target.y = 0;
|
|
||||||
entTest.health = 100;
|
|
||||||
entTest.type = GHOST;
|
|
||||||
add_entity(&entities, entTest);
|
|
||||||
|
|
||||||
setupTiles();
|
setupTiles();
|
||||||
|
|
||||||
// for (ItemType i = 0; i < ITEMREGISTRY_SIZE; i++) {
|
// for (ItemType i = 0; i < ITEMREGISTRY_SIZE; i++) {
|
||||||
@@ -312,6 +299,25 @@ int processEvent(SDL_Event e) {
|
|||||||
case SDLK_F10:
|
case SDLK_F10:
|
||||||
renderAtlas = !renderAtlas;
|
renderAtlas = !renderAtlas;
|
||||||
break;
|
break;
|
||||||
|
case SDLK_F11:
|
||||||
|
printf("Enemy is at tile X:%d, Y:%d\n", entities.entities[0].tileRect.x,
|
||||||
|
entities.entities[0].tileRect.y);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SDLK_F2:
|
||||||
|
Entity entTest;
|
||||||
|
memset(&entTest, 0, sizeof(Entity));
|
||||||
|
entTest.tileRect = player.tileRect;
|
||||||
|
entTest.renderRect.w = TILE_SIZE;
|
||||||
|
entTest.renderRect.h = TILE_SIZE;
|
||||||
|
entTest.target.x = -1;
|
||||||
|
entTest.target.y = -1;
|
||||||
|
entTest.health = 100;
|
||||||
|
entTest.type = GHOST;
|
||||||
|
entTest.health = 100;
|
||||||
|
add_entity(&entities, entTest);
|
||||||
|
break;
|
||||||
|
|
||||||
case SDLK_F4:
|
case SDLK_F4:
|
||||||
Tile *tile = &tileMap[playerTileY][playerTileX];
|
Tile *tile = &tileMap[playerTileY][playerTileX];
|
||||||
break;
|
break;
|
||||||
@@ -620,8 +626,28 @@ int main(__attribute__((unused)) int argc, __attribute__((unused)) char *args[])
|
|||||||
running = processEvent(e);
|
running = processEvent(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
entities.entities[0].target = player.tileRect;
|
if (animationStep % 60 == 0) {
|
||||||
|
for (int i = 0; i < entities.activeCount; i++) {
|
||||||
|
int x = player.tileRect.x;
|
||||||
|
int y = player.tileRect.y;
|
||||||
|
x += (rand() % 10) - 5;
|
||||||
|
y += (rand() % 10) - 5;
|
||||||
|
if (x < 0) {
|
||||||
|
x = 0;
|
||||||
|
}
|
||||||
|
if (y < 0) {
|
||||||
|
y = 0;
|
||||||
|
}
|
||||||
|
if (x >= MAP_WIDTH) {
|
||||||
|
x = MAP_WIDTH - 1;
|
||||||
|
}
|
||||||
|
if (y >= MAP_HEIGHT) {
|
||||||
|
y = MAP_HEIGHT - 1;
|
||||||
|
}
|
||||||
|
entities.entities[i].target.x = x;
|
||||||
|
entities.entities[i].target.y = y;
|
||||||
|
}
|
||||||
|
}
|
||||||
updateItems();
|
updateItems();
|
||||||
updateEntities();
|
updateEntities();
|
||||||
updatePlayer(&player);
|
updatePlayer(&player);
|
||||||
@@ -723,10 +749,10 @@ void genInitMap() {
|
|||||||
if (baseType != BGType_WATER_SHALLOW && baseType != BGType_WATER_DEEP) {
|
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_IRON_ORE;
|
||||||
else if (sub < 0.50) finalType = BGType_GOLD_ORE;
|
else if (sub < 0.50) finalType = BGType_SILVER_ORE;
|
||||||
else if (sub < 0.80) finalType = BGType_SILVER_ORE;
|
else if (sub < 0.80) finalType = BGType_GOLD_ORE;
|
||||||
else finalType = BGType_IRON_ORE;
|
else finalType = BGType_PLATINUM_ORE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -30,7 +30,9 @@ SDL_Color breakingBarColor = {128, 128, 0, 255};
|
|||||||
|
|
||||||
void setActivePlayerSlot(Player *plr, ItemType activeSlotIndex) {
|
void setActivePlayerSlot(Player *plr, ItemType activeSlotIndex) {
|
||||||
activeSlotIndex = activeSlotIndex % itemRegistryIndex;
|
activeSlotIndex = activeSlotIndex % itemRegistryIndex;
|
||||||
|
if((activeSlotIndex < tileTypeIndex || (activeSlotIndex < itemRegistryIndex && activeSlotIndex >= ITEMREGISTRY_SIZE / 2)) && activeSlotIndex > 0) {
|
||||||
plr->inventory.activeSlotIndex = activeSlotIndex;
|
plr->inventory.activeSlotIndex = activeSlotIndex;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void moveActivePlayerSlot(Player *plr, bool up, bool seek) {
|
void moveActivePlayerSlot(Player *plr, bool up, bool seek) {
|
||||||
@@ -174,7 +176,7 @@ void renderPlayer(Player *plr) {
|
|||||||
ItemType itemIndex = plr->inventory.activeSlotIndex;
|
ItemType itemIndex = plr->inventory.activeSlotIndex;
|
||||||
//SDL_Texture *itemTex;
|
//SDL_Texture *itemTex;
|
||||||
char itemStringCount[6];
|
char itemStringCount[6];
|
||||||
if (itemIndex < itemRegistryIndex && itemIndex > 0) {
|
if ((itemIndex < tileTypeIndex || (itemIndex < itemRegistryIndex && itemIndex >= ITEMREGISTRY_SIZE / 2)) && itemIndex > 0) {
|
||||||
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];
|
||||||
|
18
tiles/tile.c
18
tiles/tile.c
@@ -9,6 +9,7 @@
|
|||||||
#include "../util/atlas.h"
|
#include "../util/atlas.h"
|
||||||
#include "../util/font.h"
|
#include "../util/font.h"
|
||||||
#include "miner.h"
|
#include "miner.h"
|
||||||
|
#include "turret.h"
|
||||||
|
|
||||||
int scrollFrame = 0;
|
int scrollFrame = 0;
|
||||||
unsigned long beltFrames = 0;
|
unsigned long beltFrames = 0;
|
||||||
@@ -80,7 +81,7 @@ void registerTile(char fname[20], SDL_Renderer *renderer) {
|
|||||||
|
|
||||||
// Load animation frames
|
// Load animation frames
|
||||||
int frame = 0;
|
int frame = 0;
|
||||||
int indexTile = 0;
|
ItemType indexTile = 0;
|
||||||
char texturePath[80];
|
char texturePath[80];
|
||||||
|
|
||||||
if (sscanf(fname, "%d_%20[^_]_%d.png", &indexTile, name, &frame) == 3) {
|
if (sscanf(fname, "%d_%20[^_]_%d.png", &indexTile, name, &frame) == 3) {
|
||||||
@@ -111,12 +112,13 @@ void registerTile(char fname[20], SDL_Renderer *renderer) {
|
|||||||
createRotatedTexture(renderer, texture, 270)
|
createRotatedTexture(renderer, texture, 270)
|
||||||
};
|
};
|
||||||
|
|
||||||
printf("Bound %s to %d orient %s\n", fname, indexTile, OrientStrings[o]);
|
// printf("Bound %s to %d orient %s\n", fname, indexTile, OrientStrings[o]);
|
||||||
TileRegistry[indexTile].animation.textures[o][frame] = textures[o];
|
TileRegistry[indexTile].animation.textures[o][frame] = textures[o];
|
||||||
SDL_SetTextureBlendMode(textures[o], SDL_BLENDMODE_BLEND);
|
SDL_SetTextureBlendMode(textures[o], SDL_BLENDMODE_BLEND);
|
||||||
TileRegistry[indexTile].animation.atlasRects[o][frame] = allocate_32x32(textures[o], renderer);
|
TileRegistry[indexTile].animation.atlasRects[o][frame] = allocate_32x32(textures[o], renderer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
printf("Bound %s to %d\n", fname, indexTile);
|
||||||
TileRegistry[indexTile].type = indexTile;
|
TileRegistry[indexTile].type = indexTile;
|
||||||
TileRegistry[indexTile].maxHealth = 200;
|
TileRegistry[indexTile].maxHealth = 200;
|
||||||
TileRegistry[indexTile].animation.frameCount = frame + 1;
|
TileRegistry[indexTile].animation.frameCount = frame + 1;
|
||||||
@@ -155,7 +157,7 @@ void registerBackgroundTile(char fname[20], SDL_Renderer *renderer) {
|
|||||||
|
|
||||||
SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_NONE);
|
SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_NONE);
|
||||||
|
|
||||||
printf("Bound %s to %d\n", fname, indexBgTile);
|
//printf("Bound %s to %d\n", fname, indexBgTile);
|
||||||
|
|
||||||
BackgroundTileRegistry[indexBgTile].animation.textures[frame] = texture;
|
BackgroundTileRegistry[indexBgTile].animation.textures[frame] = texture;
|
||||||
BackgroundTileRegistry[indexBgTile].animation.atlasRects[frame] = allocate_32x32(texture, renderer);
|
BackgroundTileRegistry[indexBgTile].animation.atlasRects[frame] = allocate_32x32(texture, renderer);
|
||||||
@@ -261,7 +263,7 @@ void setupTiles() {
|
|||||||
for (uint16_t i = 0; i < ItemSlotCount; i++) {
|
for (uint16_t i = 0; i < ItemSlotCount; i++) {
|
||||||
TileRegistry[TYPE_BELT].outputLane[i] = true;
|
TileRegistry[TYPE_BELT].outputLane[i] = true;
|
||||||
}
|
}
|
||||||
for (uint16_t l = 0; l < ItemSlotCount; l++) {
|
for (uint16_t l = 0; l < 2; l++) {
|
||||||
for (ItemType i = 0; i < itemRegistryIndex; i++) {
|
for (ItemType i = 0; i < itemRegistryIndex; i++) {
|
||||||
TileRegistry[TYPE_BELT].allowedInItems[l][i] = true;
|
TileRegistry[TYPE_BELT].allowedInItems[l][i] = true;
|
||||||
}
|
}
|
||||||
@@ -272,7 +274,7 @@ void setupTiles() {
|
|||||||
TileRegistry[TYPE_FURNACE].allowedInItems[FURNACE_INPUT_SLOT][i] = true;
|
TileRegistry[TYPE_FURNACE].allowedInItems[FURNACE_INPUT_SLOT][i] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TileRegistry[TYPE_FURNACE].outputLane[FURNACE_OUTPUT_SLOT] = 1;
|
; TileRegistry[TYPE_FURNACE].outputLane[FURNACE_OUTPUT_SLOT] = 1;
|
||||||
TileRegistry[TYPE_FURNACE].startFrame = 1;
|
TileRegistry[TYPE_FURNACE].startFrame = 1;
|
||||||
TileRegistry[TYPE_FURNACE].needsTicks = true;
|
TileRegistry[TYPE_FURNACE].needsTicks = true;
|
||||||
TileRegistry[TYPE_FURNACE].animation.divisor = 8;
|
TileRegistry[TYPE_FURNACE].animation.divisor = 8;
|
||||||
@@ -283,6 +285,9 @@ void setupTiles() {
|
|||||||
TileRegistry[TYPE_MINER].startFrame = 1;
|
TileRegistry[TYPE_MINER].startFrame = 1;
|
||||||
TileRegistry[TYPE_AIR].walkable = true;
|
TileRegistry[TYPE_AIR].walkable = true;
|
||||||
|
|
||||||
|
TileRegistry[TYPE_TURRET].needsTicks = true;
|
||||||
|
TileRegistry[TYPE_TURRET].allowedInItems[TURRET_AMMO_INPUT_SLOT][IRON_INGOT] = true;
|
||||||
|
|
||||||
BackgroundTileRegistry[BGType_WATER_DEEP].animation.divisor = 16;
|
BackgroundTileRegistry[BGType_WATER_DEEP].animation.divisor = 16;
|
||||||
BackgroundTileRegistry[BGType_WATER_SHALLOW].animation.divisor = 12;
|
BackgroundTileRegistry[BGType_WATER_SHALLOW].animation.divisor = 12;
|
||||||
BackgroundTileRegistry[BGType_GRASS_FLOWER0].animation.divisor = 16;
|
BackgroundTileRegistry[BGType_GRASS_FLOWER0].animation.divisor = 16;
|
||||||
@@ -450,6 +455,9 @@ void renderAllTiles(SDL_Renderer *renderer, SDL_Rect playerRect) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool isWalkable(MiniRect tileCoords) {
|
bool isWalkable(MiniRect tileCoords) {
|
||||||
|
if (tileCoords.x < 0 || tileCoords.x >= MAP_WIDTH || tileCoords.y < 0 || tileCoords.y >= MAP_HEIGHT) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
BackgroundTileType bgt = BackgroundTileRegistry[backgroundMap[tileCoords.y][tileCoords.x].type];
|
BackgroundTileType bgt = BackgroundTileRegistry[backgroundMap[tileCoords.y][tileCoords.x].type];
|
||||||
TileTypeReg fgt = TileRegistry[tileMap[tileCoords.y][tileCoords.x].type];
|
TileTypeReg fgt = TileRegistry[tileMap[tileCoords.y][tileCoords.x].type];
|
||||||
|
|
||||||
|
@@ -73,10 +73,10 @@ typedef enum BackgroundType {
|
|||||||
BGType_COBBLE1,
|
BGType_COBBLE1,
|
||||||
BGType_COBBLE2,
|
BGType_COBBLE2,
|
||||||
BGType_COBBLE3,
|
BGType_COBBLE3,
|
||||||
BGType_PLATINUM_ORE,
|
|
||||||
BGType_GOLD_ORE,
|
|
||||||
BGType_SILVER_ORE,
|
|
||||||
BGType_IRON_ORE,
|
BGType_IRON_ORE,
|
||||||
|
BGType_SILVER_ORE,
|
||||||
|
BGType_GOLD_ORE,
|
||||||
|
BGType_PLATINUM_ORE,
|
||||||
BGType_END
|
BGType_END
|
||||||
} BackgroundType;
|
} BackgroundType;
|
||||||
|
|
||||||
|
@@ -5,11 +5,13 @@
|
|||||||
#include "tilecallbacks.h"
|
#include "tilecallbacks.h"
|
||||||
#include "furnace.h"
|
#include "furnace.h"
|
||||||
#include "miner.h"
|
#include "miner.h"
|
||||||
|
#include "turret.h"
|
||||||
|
|
||||||
const UpdateTileCallback ItemTileCallbacks[TILEREGISTRY_SIZE] = {
|
const UpdateTileCallback ItemTileCallbacks[TILEREGISTRY_SIZE] = {
|
||||||
[TYPE_AIR] = NULL,
|
[TYPE_AIR] = NULL,
|
||||||
[TYPE_BLOCK] = NULL,
|
[TYPE_BLOCK] = NULL,
|
||||||
[TYPE_BELT] = NULL,
|
[TYPE_BELT] = NULL,
|
||||||
[TYPE_FURNACE] = updateFurnace,
|
[TYPE_FURNACE] = updateFurnace,
|
||||||
[TYPE_MINER] = updateMiner
|
[TYPE_MINER] = updateMiner,
|
||||||
|
[TYPE_TURRET] = updateTurret,
|
||||||
};
|
};
|
61
tiles/turret.c
Normal file
61
tiles/turret.c
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
//
|
||||||
|
// Created by bruno on 6.9.2025.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "turret.h"
|
||||||
|
#include "tile.h"
|
||||||
|
#include "../util/audio.h"
|
||||||
|
#include "../entity/entity.h"
|
||||||
|
|
||||||
|
const uint16_t AmmoDamages[ITEMREGISTRY_SIZE] = {
|
||||||
|
[IRON_INGOT] = 1
|
||||||
|
};
|
||||||
|
|
||||||
|
void updateTurret(Tile *tile) {
|
||||||
|
ItemOnBelt *inItem = &tile->items[TURRET_AMMO_INPUT_SLOT];
|
||||||
|
Item inItemType = ItemRegistry[inItem->type];
|
||||||
|
|
||||||
|
uint16_t damage = AmmoDamages[inItem->type];
|
||||||
|
|
||||||
|
if (damage > 0) {
|
||||||
|
bool foundEnt = false;
|
||||||
|
|
||||||
|
for (int i = 0; i < entities.activeCount; i++) {
|
||||||
|
Entity *ent = &entities.entities[i];
|
||||||
|
int dx = abs(ent->renderRect.x - (tile->rect.x * TILE_SIZE));
|
||||||
|
int dy = abs(ent->renderRect.y - (tile->rect.y * TILE_SIZE));
|
||||||
|
int d = sqrt(pow(dx, 2) + pow(dy, 2));
|
||||||
|
if (d <= (TILE_SIZE * 8)) {
|
||||||
|
ent->health -= damage;
|
||||||
|
inItem->type = 0;
|
||||||
|
tile->audioCh = getAvailableChannel();
|
||||||
|
if (tile->audioCh < NUM_SYNTH_VOICES) {
|
||||||
|
audioData.synthVoices[tile->audioCh].volume = 255;
|
||||||
|
audioData.synthVoices[tile->audioCh].phase = 0;
|
||||||
|
audioData.synthVoices[tile->audioCh].sourceRect.x = TILE_SIZE * tile->rect.x;
|
||||||
|
audioData.synthVoices[tile->audioCh].sourceRect.y = TILE_SIZE * tile->rect.y;
|
||||||
|
audioData.synthVoices[tile->audioCh].waveform = WAVE_TRIANGLE;
|
||||||
|
audioData.synthVoices[tile->audioCh].frequency = 400;
|
||||||
|
}
|
||||||
|
tile->fixedFrame = 0;
|
||||||
|
foundEnt = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!foundEnt) {
|
||||||
|
audioData.synthVoices[tile->audioCh].volume = 0;
|
||||||
|
tile->fixedFrame = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if (tile->audioCh < NUM_SYNTH_VOICES) {
|
||||||
|
audioData.synthVoices[tile->audioCh].volume = 0;
|
||||||
|
}
|
||||||
|
tile->fixedFrame = 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (audioData.synthVoices[tile->audioCh].frequency > 80) {
|
||||||
|
audioData.synthVoices[tile->audioCh].frequency--;
|
||||||
|
}
|
||||||
|
}
|
17
tiles/turret.h
Normal file
17
tiles/turret.h
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
//
|
||||||
|
// Created by bruno on 6/9/25.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef FACTORYGAME_TURRET_H
|
||||||
|
#define FACTORYGAME_TURRET_H
|
||||||
|
|
||||||
|
#include "../items/item.h"
|
||||||
|
#include "stdint.h"
|
||||||
|
|
||||||
|
extern const uint16_t AmmoDamages[];
|
||||||
|
|
||||||
|
#define TURRET_AMMO_INPUT_SLOT 0
|
||||||
|
|
||||||
|
void updateTurret(Tile * tile);
|
||||||
|
|
||||||
|
#endif //FACTORYGAME_TURRET_H
|
Reference in New Issue
Block a user