Some more hopefully working progress

This commit is contained in:
2025-05-31 23:54:55 +02:00
parent 0c9698879b
commit 6b6e7df035
26 changed files with 659 additions and 393 deletions

View File

@@ -40,4 +40,4 @@ add_custom_target(copy_assets ALL
add_dependencies(factorygame copy_assets)
target_link_libraries(factorygame SDL2 SDL2_ttf SDL2_image SDL2_gfx SDL2_mixer SDL2_net m)
target_link_libraries(factorygame SDL2 SDL2_ttf SDL2_image m)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 517 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 566 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 516 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 513 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 592 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 492 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 526 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 530 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 546 B

View File

Before

Width:  |  Height:  |  Size: 120 B

After

Width:  |  Height:  |  Size: 120 B

View File

Before

Width:  |  Height:  |  Size: 202 B

After

Width:  |  Height:  |  Size: 202 B

View File

@@ -11,7 +11,7 @@ Item ItemRegistry[ITEMREGISTRY_SIZE];
uint16_t itemRegistryIndex = 0;
float speed = 0.002f; // fraction of tile per tick
double speed = 1.0f / TILE_SIZE; // fraction of tile per tick
void updateItems() {
const int dirDx[8] = {-1, -1, -1, 0, 1, 1, 1, 0};
@@ -29,9 +29,8 @@ void updateItems() {
bool vert = (dir == ORIENT_UP || dir == ORIENT_DOWN);
for (uint8_t lane = 0; lane < 2; lane++) {
for (uint8_t slot = 0; slot < 2; slot++) {
ItemOnBelt *itm = &t->items[lane][slot];
if (!itm->active) continue;
ItemOnBelt *itm = &t->items[lane];
if (itm->type == 0) continue;
// 1) Advance
itm->offset += speed;
@@ -46,12 +45,14 @@ void updateItems() {
// bounds & belt?
if (nx < 0 || nx >= MAP_WIDTH || ny < 0 || ny >= MAP_HEIGHT) {
itm->active = false;
//itm->type = 0;
itm->offset += 1.0f - speed;
continue;
}
Tile *next = &tileMap[ny][nx];
if (next->type != TYPE_BELT) {
itm->active = false;
//itm->type = 0;
itm->offset += 1.0f - speed;
continue;
}
@@ -65,30 +66,26 @@ void updateItems() {
// same axis → keep lane
} else if (horz && nV) {
// came off a horizontal: lane0=top→vertical.left, lane1=bottom→vertical.right
newLane = (dir == ORIENT_RIGHT ? 1 : 0);
newLane = (dir == ORIENT_RIGHT ^ newDir == ORIENT_UP ? 0 : 1);
itm->offset = 0.0f;
} else if (vert && nH) {
// came off vertical: lane0=left→horizontal.top, lane1=right→horizontal.bottom
newLane = (dir == ORIENT_UP ? 0 : 1);
newLane = (dir == ORIENT_UP ^ newDir == ORIENT_RIGHT ? 1 : 0);
itm->offset = 0.0f;
}
// (diagonals fall back to same-lane)
// Find a free slot in newLane
int destSlot = -1;
if (!next->items[newLane][0].active) destSlot = 0;
else if (!next->items[newLane][1].active) destSlot = 1;
// Find a free slot in
if (destSlot >= 0) {
if (next->items[newLane].type == 0) {
// MOVE it
ItemOnBelt moved = *itm;
moved.tileX = nx;
moved.tileY = ny;
next->items[newLane][destSlot] = moved;
next->items[newLane][destSlot].active = true;
next->items[newLane] = moved;
// clear this one
itm->active = false;
itm->type = 0;
} else {
// both slots full → wait at end
itm->offset = epsilon;
@@ -97,7 +94,6 @@ void updateItems() {
}
}
}
}
}
@@ -108,7 +104,8 @@ void registerItem(char name[20], SDL_Renderer *renderer) {
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],
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].type = itemRegistryIndex;
@@ -117,19 +114,28 @@ void registerItem(char name[20], SDL_Renderer *renderer) {
}
// easing function: cosine easeinout
//static float ease_in_out(float t) {
// if (t < -1.0f) t = -1.0f;
// if (t > 1.0f) t = 1.0f;
//
// // Even symmetric easing: reflected across t = 0
// return (t < 0.0f)
// ? -0.5f * (1.0f - cosf(M_PI * -t)) // negative side
// : 0.5f * (1.0f - cosf(M_PI * t)); // positive side
//}
static float ease_in_out(float t) {
// Clamp t to [-1.0, 1.0]
if (t < -1.0f) t = -1.0f;
if (t > 1.0f) t = 1.0f;
// Even symmetric easing: reflected across t = 0
return (t < 0.0f)
? -0.5f * (1.0f - cosf(M_PI * -t)) // negative side
: 0.5f * (1.0f - cosf(M_PI * t)); // positive side
return t; // Linear: no easing
}
uint8_t laneTarget = 0;
void renderItem(ItemOnBelt item, SDL_Renderer *renderer, int lane) {
void renderItem(ItemOnBelt item, SDL_Renderer *renderer, int lane, SDL_Rect playerRect) {
SDL_Rect rect = {0};
rect.x = item.tileX * TILE_SIZE;
rect.y = item.tileY * TILE_SIZE;
@@ -190,7 +196,7 @@ void renderItem(ItemOnBelt item, SDL_Renderer *renderer, int lane) {
yOffset += 0.0f * TILE_SIZE;
break;
case ORIENT_LEFT:
xOffset += 0.0f * TILE_SIZE;
xOffset += 0.0f * TILE_SIZE + (TILE_SIZE / 2);
yOffset += 0.26f * TILE_SIZE;
break;
case ORIENT_LEFT_UP:
@@ -199,7 +205,7 @@ void renderItem(ItemOnBelt item, SDL_Renderer *renderer, int lane) {
break;
case ORIENT_UP:
xOffset += 0.22f * TILE_SIZE; //GOTO HEHREHRHE
yOffset += 0.0f * TILE_SIZE;
yOffset += 0.0f * TILE_SIZE + (TILE_SIZE / 2);
break;
case ORIENT_RIGHT_UP:
xOffset += 0.0f * TILE_SIZE;
@@ -214,7 +220,7 @@ void renderItem(ItemOnBelt item, SDL_Renderer *renderer, int lane) {
yOffset += 0.0f * TILE_SIZE;
break;
case ORIENT_DOWN:
xOffset += 0.18f * TILE_SIZE;
xOffset += 0.18f * TILE_SIZE + (TILE_SIZE / 4);
yOffset += 0.0f * TILE_SIZE;
break;
default:
@@ -243,50 +249,45 @@ void renderItem(ItemOnBelt item, SDL_Renderer *renderer, int lane) {
rect.w = TILE_SIZE / 2;
rect.h = TILE_SIZE / 2;
adjustRect(&rect);
adjustRect(&rect, playerRect);
// (Optional debug overlay)
// SDL_Rect tileArea = {item.tileX * TILE_SIZE, item.tileY * TILE_SIZE,
// TILE_SIZE, TILE_SIZE};
// SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND);
// SDL_SetRenderDrawColor(renderer, 255, 0, 0, 32);
// adjustRect(&tileArea);
// SDL_RenderFillRect(renderer, &tileArea);
char tempStr[50];
// SDL_Rect rectA = {0};
// rectA.x = item.tileX * TILE_SIZE;
// rectA.y = item.tileY * TILE_SIZE;
// rectA.w = TILE_SIZE;
// rectA.h = TILE_SIZE;
// sprintf(tempStr, "L%d\n%f\n%f\n%f", lane, item.offset, xOffset, yOffset);
// SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND);
// SDL_SetRenderDrawColor(renderer, 255, 0, 0, 32);
// adjustRect(&rectA);
// SDL_RenderFillRect(renderer, &rectA);
SDL_Rect rectA = {0};
if (debugMode) {
SDL_Rect tileArea = {item.tileX * TILE_SIZE, item.tileY * TILE_SIZE,
TILE_SIZE, TILE_SIZE};
SDL_SetRenderDrawColor(renderer, 255, 0, 0, 32);
adjustRect(&tileArea, playerRect);
SDL_RenderFillRect(renderer, &tileArea);
rectA.x = item.tileX * TILE_SIZE;
rectA.y = item.tileY * TILE_SIZE;
rectA.w = TILE_SIZE;
rectA.h = TILE_SIZE;
sprintf(tempStr, "L%d\n%f\n%f\n%f", lane, item.offset, xOffset, yOffset);
SDL_SetRenderDrawColor(renderer, 255, 0, 0, 32);
adjustRect(&rectA, playerRect);
SDL_RenderFillRect(renderer, &rectA);
}
SDL_RenderCopy(renderer, ItemRegistry[item.type].textureOnBelt[ORIENT_LEFT], NULL, &rect);
// renderText(renderer, fonts[3], tempStr, rectA.x, rectA.y);
if (debugMode) {
renderText(renderer, fonts[3], tempStr, rectA.x, rectA.y);
}
}
void renderBeltItems(SDL_Renderer *renderer) {
}
void putItem(int x, int y, uint16_t itemType, uint8_t lane, uint8_t itemIndex) {
tileMap[y][x].items[lane][itemIndex].type = itemType;
tileMap[y][x].items[lane][itemIndex].offset = 0;
tileMap[y][x].items[lane][itemIndex].active = true;
tileMap[y][x].items[lane][itemIndex].tileX = x;
tileMap[y][x].items[lane][itemIndex].tileY = y;
void putItem(int x, int y, uint16_t itemType, uint8_t lane) {
tileMap[y][x].items[lane].type = itemType;
tileMap[y][x].items[lane].offset = 0;
tileMap[y][x].items[lane].tileX = x;
tileMap[y][x].items[lane].tileY = y;
}
void loadItems(SDL_Renderer *renderer) {
for(int i = 0; i < tileTypeIndex; i++) {
for (int i = 0; i < tileTypeIndex; i++) {
TileType tile = TileRegistry[i];
strcpy(ItemRegistry[itemRegistryIndex].name, tile.name);
memcpy(ItemRegistry[itemRegistryIndex].texture, tile.textures, sizeof (tile.textures));
memcpy(ItemRegistry[itemRegistryIndex].texture, tile.textures, sizeof(tile.textures));
for (int a = 0; a < ORIENT_DIRECTION_COUNT; a++) {
SDL_SetTextureBlendMode(ItemRegistry[itemRegistryIndex].texture[a], SDL_BLENDMODE_BLEND);
ItemRegistry[itemRegistryIndex].textureOnBelt[a] = ScaleTexture(renderer, tile.textures[a],
@@ -299,14 +300,16 @@ void loadItems(SDL_Renderer *renderer) {
}
DIR *dir = opendir("./assets/items");
if (dir) {
struct dirent *entry;
while ((entry = readdir(dir)) != NULL) {
if (entry->d_name[0] == '.') {
continue;
}
registerItem(entry->d_name, renderer);
}
}
iterateSortedDir("./assets/items", (DirEntryCallback) registerItem, renderer);
// DIR *dir = opendir("./assets/items");
// if (dir) {
// struct dirent *entry;
// while ((entry = readdir(dir)) != NULL) {
// if (entry->d_name[0] == '.') {
// continue;
// }
// registerItem(entry->d_name, mainRenderer);
// }
// }
}

View File

@@ -14,7 +14,6 @@
typedef struct {
float offset;
int tileX, tileY;
bool active;
uint16_t type;
} ItemOnBelt;
@@ -30,15 +29,15 @@ extern Item ItemRegistry[ITEMREGISTRY_SIZE];
void updateItems();
void loadItems(SDL_Renderer *renderer);
void loadItems(SDL_Renderer *mainRenderer);
void renderItem(ItemOnBelt item, SDL_Renderer *renderer, int lane);
void renderItem(ItemOnBelt item, SDL_Renderer *mainRenderer, int lane, SDL_Rect playerRect);
extern uint16_t itemRegistryIndex;
extern uint8_t laneTarget;
extern float speed;
extern double speed;
void putItem(int x, int y, uint16_t itemType, uint8_t lane, uint8_t itemIndex);
void putItem(int x, int y, uint16_t itemType, uint8_t lane);
#endif //FACTORYGAME_ITEM_H

240
main.c
View File

@@ -4,18 +4,45 @@
#include "util/font.h"
#include "util/audio.h"
#include "tiles/tile.h"
#include "tiles/belt.h"
#include "items/item.h"
#include "stdlib.h"
#include "player/player.h"
typedef struct {
Player player;
Tile tileMap[MAP_HEIGHT][MAP_WIDTH];
} GameState;
GameState gameState;
void loadGameState(char *filename, Player *plr) {
printf("hello from load\n");
fflush(stdout);
FILE *gameSave = fopen(filename, "rb");
if (gameSave) {
fread(&gameState, sizeof(gameState), 1, gameSave);
fclose(gameSave);
memcpy(tileMap, gameState.tileMap, sizeof(tileMap));
memcpy(plr, &gameState.player, sizeof(gameState.player));
}
}
void saveGameState(char *filename, Player *plr) {
memcpy(&gameState.player, plr, sizeof(gameState.player));
memcpy(gameState.tileMap, tileMap, sizeof(gameState.tileMap));
FILE *gameSave = fopen(filename, "wb");
if (!gameSave) {
perror("Failed to open file for saving");
return;
}
fwrite(&gameState, sizeof(gameState), 1, gameSave);
fclose(gameSave);
}
Player player;
float currentScale = 1;
//Screen dimension constants
#define SCREEN_WIDTH DISPLAY_WIDTH / currentScale
#define SCREEN_HEIGHT DISPLAY_HEIGHT/ currentScale
const int targetFPS = 60;
const int delayNeeded = 1000 / targetFPS;
@@ -24,6 +51,8 @@ const int delayNeeded = 1000 / targetFPS;
#define smallerFont fonts[2]
#define smallestFont fonts[3]
const char *autosaveName = "autosave.dat";
unsigned long frames = 0;
bool cursor = true;
@@ -35,11 +64,16 @@ void msleep(unsigned int milliseconds) {
nanosleep(&ts, NULL);
}
SDL_GLContext glContext;
int init() {
//Initialize SDL
screenRect.x = 0;
screenRect.y = 0;
screenRect.w = DISPLAY_WIDTH;
screenRect.h = DISPLAY_HEIGHT;
srand(0);
@@ -59,24 +93,24 @@ int init() {
}
//Create window
window = SDL_CreateWindow("Factory game", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, SCREEN_WIDTH,
SCREEN_HEIGHT, SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE);
window = SDL_CreateWindow("Factory game", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, DISPLAY_WIDTH,
DISPLAY_HEIGHT, SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE);
if (window == NULL) {
printf("Window could not be created! SDL_Error: %s\n", SDL_GetError());
return 1;
}
//Get window surface
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
if (renderer == NULL) {
mainRenderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
if (mainRenderer == NULL) {
printf("Renderer could not be created SDL_Error: %s\n", SDL_GetError());
return 1;
}
loadTiles(renderer);
loadItems(renderer);
loadTiles(mainRenderer);
loadItems(mainRenderer);
// Create OpenGL context
SDL_GLContext glContext = SDL_GL_CreateContext(window);
glContext = SDL_GL_CreateContext(window);
if (!glContext) {
fprintf(stderr, "SDL_GL_CreateContext failed: %s\n", SDL_GetError());
exit(1);
@@ -101,30 +135,32 @@ int init() {
SDL_PauseAudioDevice(dev, 0);
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
SDL_RenderClear(renderer);
SDL_SetRenderDrawColor(mainRenderer, 0, 0, 0, 255);
SDL_RenderClear(mainRenderer);
SDL_Rect viewport = {0, 0, SCREEN_WIDTH, SCREEN_HEIGHT};
SDL_RenderSetViewport(renderer, &viewport);
SDL_Rect viewport = {0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT};
SDL_RenderSetViewport(mainRenderer, &viewport);
SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND);
biggerFont = prepText(renderer, 16, "assets/PublicPixel.ttf", 255, 255, 255, 255);
smallFont = prepText(renderer, 12, "assets/PublicPixel.ttf", 255, 255, 255, 255);
smallerFont = prepText(renderer, 8, "assets/PublicPixel.ttf", 255, 255, 255, 255);
smallestFont = prepText(renderer, 4, "assets/PublicPixel.ttf", 255, 255, 255, 255);
SDL_RenderSetLogicalSize(renderer, SCREEN_WIDTH, SCREEN_HEIGHT);
SDL_SetRenderDrawBlendMode(mainRenderer, SDL_BLENDMODE_BLEND);
biggerFont = prepText(mainRenderer, 16, "assets/PublicPixel.ttf", 255, 255, 255, 255);
smallFont = prepText(mainRenderer, 12, "assets/PublicPixel.ttf", 255, 255, 255, 255);
smallerFont = prepText(mainRenderer, 8, "assets/PublicPixel.ttf", 255, 255, 255, 255);
smallestFont = prepText(mainRenderer, 4, "assets/PublicPixel.ttf", 255, 255, 255, 255);
SDL_RenderSetLogicalSize(mainRenderer, DISPLAY_WIDTH, DISPLAY_HEIGHT);
initPlayer(&player);
generateTestMap();
initTiles();
//generateTestMap();
return 0;
}
int render() {
SDL_SetRenderDrawColor(renderer, 32, 32, 32, 255);
SDL_RenderClear(renderer);
SDL_SetRenderDrawColor(mainRenderer, 32, 32, 32, 255);
SDL_RenderClear(mainRenderer);
SDL_Rect rect2;
rect2.x = 20;
@@ -132,12 +168,17 @@ int render() {
rect2.w = 0;
rect2.h = 0;
renderAllBelts(renderer);
renderAllTiles(mainRenderer, player.rect);
SDL_RenderCopy(mainRenderer, tilesTexture, &screenRect, &screenRect);
SDL_RenderCopy(mainRenderer, itemsTexture, &screenRect, &screenRect);
SDL_RenderCopy(mainRenderer, entityTexture, &screenRect, &screenRect);
SDL_RenderCopy(mainRenderer, hudTexture, &screenRect, &screenRect);
renderPlayer(&player);
SDL_RenderPresent(renderer);
SDL_RenderPresent(mainRenderer);
frames++;
if (!(frames % 60)) {
cursor = !cursor;
@@ -154,10 +195,11 @@ int processEvent(SDL_Event e) {
// Adjust the viewport to match the new window size;
SDL_Rect viewport = {0, 0, newWidth, newHeight};
SDL_RenderSetViewport(renderer, &viewport);
SDL_RenderSetViewport(mainRenderer, &viewport);
} else if (e.type == SDL_KEYDOWN) {
int keySym = e.key.keysym.sym;
int keyMod = e.key.keysym.mod;
SDL_KeyCode keySym = e.key.keysym.sym;
SDL_Scancode scanCode = e.key.keysym.scancode;
SDL_Keymod keyMod = e.key.keysym.mod;
cursor = true;
switch (keySym) {
case SDLK_p:
@@ -172,6 +214,12 @@ int processEvent(SDL_Event e) {
player.cursor.targetTile->direction = player.cursor.direction;
}
break;
case SDLK_u:
laneTarget = !laneTarget;
break;
case SDLK_F3:
debugMode = !debugMode;
break;
default:
break;
}
@@ -203,7 +251,7 @@ int processEvent(SDL_Event e) {
void processMousePosition() {
SDL_Rect viewport;
SDL_RenderGetViewport(renderer, &viewport);
SDL_RenderGetViewport(mainRenderer, &viewport);
uint32_t mouseButtons = SDL_GetMouseState(&player.cursor.windowX, &player.cursor.windowY);
if (mouseButtons & SDL_BUTTON_LMASK) {
@@ -228,14 +276,12 @@ void processMousePosition() {
}
if (player.cursor.targetTile->type == TYPE_BELT) {
for (int lane = 0; lane < 2; lane++) {
for (int slot = 0; slot < 2; slot++) {
if (player.cursor.targetTile->items[lane][slot].active) {
int itemType = player.cursor.targetTile->items[lane][slot].type;
if (player.cursor.targetTile->items[lane].type != 0) {
int itemType = player.cursor.targetTile->items[lane].type;
if (itemType < itemRegistryIndex) {
player.inventory.slotCounts[itemType]++;
}
player.cursor.targetTile->items[lane][slot].active = false;
}
player.cursor.targetTile->items[lane].type = 0;
}
}
}
@@ -261,12 +307,20 @@ void processMousePosition() {
}
// Translate mouseRect coordinates to viewport space
player.cursor.windowX = ((player.cursor.windowX - viewport.x) * SCREEN_WIDTH) / viewport.w;
player.cursor.windowY = (player.cursor.windowY - viewport.y) * SCREEN_HEIGHT / viewport.h;
player.cursor.tileX = (player.cursor.windowX + playerX) / TILE_SIZE - (SCREEN_WIDTH / TILE_SIZE / 2);
player.cursor.tileY = (player.cursor.windowY + playerY) / TILE_SIZE - (SCREEN_HEIGHT / TILE_SIZE / 2);
player.cursor.windowX = ((player.cursor.windowX - viewport.x) * DISPLAY_WIDTH) / viewport.w;
player.cursor.windowY = (player.cursor.windowY - viewport.y) * DISPLAY_HEIGHT / viewport.h;
player.cursor.tileX = (player.cursor.windowX + player.rect.x) / TILE_SIZE - (DISPLAY_WIDTH / TILE_SIZE / 2);
player.cursor.tileY = (player.cursor.windowY + player.rect.y) / TILE_SIZE - (DISPLAY_HEIGHT / TILE_SIZE / 2);
player.cursor.prevTargetTile = player.cursor.targetTile;
player.cursor.targetTile = &tileMap[player.cursor.tileY][player.cursor.tileX];
player.cursor.targetTileRect.x = player.cursor.tileX * TILE_SIZE;
player.cursor.targetTileRect.y = player.cursor.tileY * TILE_SIZE;
player.cursor.tileDiffX = player.cursor.tileX - playerTileX;
player.cursor.tileDiffY = player.cursor.tileY - playerTileY;
player.cursor.tileDiff = floorf(sqrtf(powf(player.cursor.tileDiffX, 2) + powf(player.cursor.tileDiffY, 2)));
player.cursor.canReach = player.cursor.tileDiff <= playerReach;
adjustRect(&player.cursor.targetTileRect, player.rect);
}
void processKeyboardHeld() {
@@ -281,29 +335,54 @@ void processKeyboardHeld() {
cameraSpeed /= 2;
}
if (player.cursor.breakingProgress == 0) {
if (keyboardState[SDL_SCANCODE_W]) {
// Example: move up
playerY -= cameraSpeed;
if (playerY < (SCREEN_HEIGHT / 2)) {
playerY = (SCREEN_HEIGHT / 2);
player.rect.y -= cameraSpeed;
if (player.rect.y < (DISPLAY_HEIGHT / 2)) {
player.rect.y = (DISPLAY_HEIGHT / 2);
}
}
if (keyboardState[SDL_SCANCODE_S]) {
playerY += cameraSpeed;
if (playerY > (MAP_HEIGHT * TILE_SIZE) - (SCREEN_HEIGHT / 2)) {
playerY = (MAP_HEIGHT * TILE_SIZE) - (SCREEN_HEIGHT / 2);
player.rect.y += cameraSpeed;
if (player.rect.y > (MAP_HEIGHT * TILE_SIZE) - (DISPLAY_HEIGHT / 2)) {
player.rect.y = (MAP_HEIGHT * TILE_SIZE) - (DISPLAY_HEIGHT / 2);
}
}
if (keyboardState[SDL_SCANCODE_A]) {
playerX -= cameraSpeed;
if (playerX < (SCREEN_WIDTH / 2)) {
playerX = (SCREEN_WIDTH / 2);
player.rect.x -= cameraSpeed;
if (player.rect.x < (DISPLAY_WIDTH / 2)) {
player.rect.x = (DISPLAY_WIDTH / 2);
}
}
if (keyboardState[SDL_SCANCODE_D]) {
playerX += cameraSpeed;
if (playerX > (MAP_WIDTH * TILE_SIZE) - (SCREEN_WIDTH / 2)) {
playerX = (MAP_WIDTH * TILE_SIZE) - (SCREEN_WIDTH / 2);
player.rect.x += cameraSpeed;
if (player.rect.x > (MAP_WIDTH * TILE_SIZE) - (DISPLAY_WIDTH / 2)) {
player.rect.x = (MAP_WIDTH * TILE_SIZE) - (DISPLAY_WIDTH / 2);
}
}
}
if (keyboardState[SDL_SCANCODE_F]) {
for (int x = player.rect.x - 1; x < player.rect.x + 1; player.rect.x++) {
if (x < 0) {
continue;
}
for (int y = player.rect.y - 1; y < player.rect.y + 1; player.rect.y++) {
if (y < 0) {
continue;
}
Tile *t = &tileMap[y][x];
if (t->type == TYPE_BELT) {
for (uint8_t lane = 0; lane < 2; lane++) {
ItemOnBelt *item = &t->items[lane];
if (item->type != 0) {
player.inventory.slotCounts[item->type]++;
item->type = 0;
}
}
}
}
}
}
@@ -315,22 +394,46 @@ void processKeyboardHeld() {
if (keyboardState[SDL_SCANCODE_Y]) {
if (player.cursor.canReach && player.cursor.targetTile->type == TYPE_BELT &&
player.inventory.slotCounts[player.inventory.activeSlotIndex] > 0) {
bool done = false;
for (uint8_t lane = 0; lane < 2; lane++) {
for (uint8_t slot = 0; slot < 2; slot++) {
if (!player.cursor.targetTile->items[lane][slot].active) {
putItem(player.cursor.tileX, player.cursor.tileY, player.inventory.activeSlotIndex, lane, slot);
for (uint8_t lane = 0; lane < 1; lane++) {
if (player.cursor.targetTile->items[lane].type == 0) {
putItem(player.cursor.tileX, player.cursor.tileY, player.inventory.activeSlotIndex, lane);
player.inventory.slotCounts[player.inventory.activeSlotIndex]--;
done = true;
break;
}
}
if (done) {
break;
}
}
}
}
unsigned int slot = 0;
if (keyboardState[SDL_SCANCODE_GRAVE]) {
slot = 1;
} else if (keyboardState[SDL_SCANCODE_1]) {
slot = 2;
} else if (keyboardState[SDL_SCANCODE_2]) {
slot = 3;
} else if (keyboardState[SDL_SCANCODE_3]) {
slot = 4;
} else if (keyboardState[SDL_SCANCODE_4]) {
slot = 5;
} else if (keyboardState[SDL_SCANCODE_5]) {
slot = 6;
} else if (keyboardState[SDL_SCANCODE_6]) {
slot = 7;
} else if (keyboardState[SDL_SCANCODE_7]) {
slot = 8;
} else if (keyboardState[SDL_SCANCODE_8]) {
slot = 9;
} else if (keyboardState[SDL_SCANCODE_9]) {
slot = 10;
} else if (keyboardState[SDL_SCANCODE_0]) {
slot = 11;
} else if (keyboardState[SDL_SCANCODE_MINUS]) {
slot = 12;
} else if (keyboardState[SDL_SCANCODE_EQUALS]) {
slot = 13;
}
if (slot > 0 && slot < itemRegistryIndex) {
setActivePlayerSlot(&player, slot);
}
}
int main(__attribute__((unused)) int argc, __attribute__((unused)) char *args[]) {
@@ -338,13 +441,7 @@ int main(__attribute__((unused)) int argc, __attribute__((unused)) char *args[])
if (status) {
return status;
}
uint8_t type = 0;
for (int x = 142; x < 154; x += 3) {
for (int y = 80; y < 94; y += 3) {
putItem(x, y, type++ % ITEMREGISTRY_SIZE, 0, 0);
}
}
loadGameState(autosaveName, &player);
//Hack to get window to stay up
@@ -375,12 +472,15 @@ int main(__attribute__((unused)) int argc, __attribute__((unused)) char *args[])
}
}
saveGameState(autosaveName, &player);
for (uint8_t i = 0; i < fontCount; i++) {
destroyFont(&fonts[i]);
}
puts(SDL_GetError());
if (renderer) SDL_DestroyRenderer(renderer);
if (mainRenderer) SDL_DestroyRenderer(mainRenderer);
if (window) SDL_DestroyWindow(window);
if (glContext) SDL_GL_DeleteContext(glContext);
SDL_Quit();

View File

@@ -5,16 +5,27 @@
#include <SDL2/SDL_rect.h>
#include "player.h"
#include "../tiles/tile.h"
#include "../util/font.h"
#define HEALTH_MARGIN 4
int playerSpeed = 4;
int playerSpeed = 2;
int playerReach = 4;
int playerReach = DISPLAY_MAP_HEIGHT / 2 - 2;
SDL_Texture *entityTexture;
SDL_Texture *hudTexture;
SDL_Texture *PlayerTexture;
SDL_Rect PlayerRect;
SDL_Rect targetItemBGRect;
SDL_Rect targetItemRect;
SDL_Color healthBarColor = {0, 240, 0, 255};
SDL_Color breakingBarColor = {128, 128, 0, 255};
void setActivePlayerSlot(Player *plr, uint16_t activeSlotIndex) {
activeSlotIndex = activeSlotIndex % itemRegistryIndex;
if (activeSlotIndex <= 0) {
@@ -35,7 +46,7 @@ void moveActivePlayerSlot(Player *plr, bool up, bool seek) {
if (newSlot == prevSlot) break;
// Stop if we found a slot with count > 0
if (plr->inventory.slotCounts[newSlot] > 0) break;
if (plr->inventory.slotCounts[newSlot] > 0 && newSlot != 0) break;
} while (true);
plr->inventory.activeSlotIndex = newSlot;
} else {
@@ -52,58 +63,88 @@ void moveActivePlayerSlot(Player *plr, bool up, bool seek) {
}
int playerX = (MAP_WIDTH / 2) * 16;
int playerY = (MAP_HEIGHT / 2) * 16;
void adjustRect(SDL_Rect *rect) {
rect->x -= playerX;
rect->y -= playerY;
void adjustRect(SDL_Rect *rect, SDL_Rect playerRect) {
rect->x -= playerRect.x;
rect->y -= playerRect.y;
rect->x += DISPLAY_WIDTH / 2;
rect->y += DISPLAY_HEIGHT / 2;
}
bool isInboundsTile(int x, int y) {
return (playerX / TILE_SIZE) - (DISPLAY_MAP_WIDTH / 2) < x &&
(playerY / TILE_SIZE) - (DISPLAY_MAP_HEIGHT / 2) < y &&
(playerX / TILE_SIZE) + (DISPLAY_MAP_WIDTH / 2) > x && (playerX / TILE_SIZE) + (DISPLAY_MAP_WIDTH / 2) > y;
}
//bool isInboundsTile(int x, int y) {
// return (playerX / TILE_SIZE) - (DISPLAY_MAP_WIDTH / 2) < x &&
// (playerY / TILE_SIZE) - (DISPLAY_MAP_HEIGHT / 2) < y &&
// (playerX / TILE_SIZE) + (DISPLAY_MAP_WIDTH / 2) > x && (playerX / TILE_SIZE) + (DISPLAY_MAP_WIDTH / 2) > y;
//}
//
//bool isInbounds(int x, int y) {
// return x > 0 && y > 0 && x < DISPLAY_WIDTH && y < DISPLAY_HEIGHT;
//}
bool isInbounds(int x, int y) {
return x > 0 && y > 0 && x < DISPLAY_WIDTH && y < DISPLAY_HEIGHT;
}
bool isInboundsRect(SDL_Rect rect) {
if (isInbounds(rect.x, rect.y)) {
return true;
}
if (rect.x < 0) {
rect.x += rect.w;
}
if (rect.y < 0) {
rect.y += rect.h;
}
if (isInbounds(rect.x, rect.y)) {
return true;
}
if (rect.x > DISPLAY_WIDTH) {
rect.x -= rect.w;
}
if (rect.y > DISPLAY_HEIGHT) {
rect.y -= rect.h;
}
return isInbounds(rect.x, rect.y);
}
//bool isInboundsRect(SDL_Rect rect) {
// if (isInbounds(rect.x, rect.y)) {
// return true;
// }
// if (rect.x < 0) {
// rect.x += rect.w;
// }
// if (rect.y < 0) {
// rect.y += rect.h;
// }
// if (isInbounds(rect.x, rect.y)) {
// return true;
// }
// if (rect.x > DISPLAY_WIDTH) {
// rect.x -= rect.w;
// }
// if (rect.y > DISPLAY_HEIGHT) {
// rect.y -= rect.h;
// }
// return isInbounds(rect.x, rect.y);
//}
void initPlayer(Player *plr) {
plr->cursor.direction = ORIENT_UP;
setActivePlayerSlot(plr, 1);
PlayerTexture = IMG_LoadTexture(renderer, "assets/player.png");
PlayerTexture = IMG_LoadTexture(mainRenderer, "assets/player.png");
SDL_QueryTexture(PlayerTexture, NULL, NULL, &PlayerRect.w, &PlayerRect.h);
PlayerRect.x = (DISPLAY_WIDTH / 2) - (PlayerRect.w / 2);
PlayerRect.y = (DISPLAY_HEIGHT / 2) - (PlayerRect.h / 2);
plr->health = 64;
plr->healthIdle = 0;
plr->rect.x = DISPLAY_WIDTH / 2;
plr->rect.y = DISPLAY_HEIGHT / 2;
plr->rect.w = TILE_SIZE;
plr->rect.h = TILE_SIZE;
for (uint16_t ui = 0; ui < itemRegistryIndex; ui++) {
plr->inventory.slotCounts[ui] = 64;
}
hudTexture = SDL_CreateTexture(mainRenderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, screenRect.w,
screenRect.h);
entityTexture = SDL_CreateTexture(mainRenderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, screenRect.w,
screenRect.h);
SDL_SetTextureBlendMode(entityTexture, SDL_BLENDMODE_BLEND);
SDL_SetTextureBlendMode(hudTexture, SDL_BLENDMODE_BLEND);
plr->cursor.targetTileRect.w = TILE_SIZE;
plr->cursor.targetTileRect.h = TILE_SIZE;
plr->cursor.targetTileRect.w = TILE_SIZE;
plr->cursor.targetTileRect.h = TILE_SIZE;
targetItemBGRect.w = DISPLAY_WIDTH;
targetItemBGRect.h = TILE_SIZE;
targetItemBGRect.x = 0;
targetItemBGRect.y = DISPLAY_HEIGHT - 32;
targetItemRect.w = TILE_SIZE / 2;
targetItemRect.h = TILE_SIZE / 2;
plr->cursor.heldItemRect.w = TILE_SIZE;
plr->cursor.heldItemRect.h = TILE_SIZE;
}
void updatePlayer(Player *plr) {
@@ -118,31 +159,26 @@ void updatePlayer(Player *plr) {
void renderPlayer(Player *plr) {
plr->cursor.targetTileRect.x = plr->cursor.tileX * TILE_SIZE;
plr->cursor.targetTileRect.y = plr->cursor.tileY * TILE_SIZE;
plr->cursor.targetTileRect.w = TILE_SIZE;
plr->cursor.targetTileRect.h = TILE_SIZE;
SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND);
plr->cursor.tileDiffX = plr->cursor.tileX - playerTileX;
plr->cursor.tileDiffY = plr->cursor.tileY - playerTileY;
if (abs(plr->cursor.tileDiffX) > abs(plr->cursor.tileDiffY)) {
plr->cursor.tileDiff = plr->cursor.tileDiffX;
} else {
plr->cursor.tileDiff = plr->cursor.tileDiffY;
}
plr->cursor.canReach = abs(plr->cursor.tileDiff) <= playerReach;
SDL_SetRenderDrawColor(renderer, plr->cursor.canReach ? 0 : 255, plr->cursor.canReach ? 255 : 0, 0, 128);
adjustRect(&plr->cursor.targetTileRect);
DrawThickRect(renderer, plr->cursor.targetTileRect, 4);
SDL_Texture *originalTarget = SDL_GetRenderTarget(mainRenderer);
SDL_SetRenderDrawColor(mainRenderer, 0, 0, 0, 0);
SDL_SetRenderTarget(mainRenderer, entityTexture);
SDL_RenderClear(mainRenderer);
SDL_RenderCopy(mainRenderer, PlayerTexture, NULL, &PlayerRect);
SDL_SetRenderTarget(mainRenderer, hudTexture);
SDL_RenderClear(mainRenderer);
SDL_SetRenderDrawColor(mainRenderer, plr->cursor.canReach ? 0 : 255, plr->cursor.canReach ? 255 : 0, 0, 128);
DrawThickRect(mainRenderer, plr->cursor.targetTileRect, 4);
uint16_t itemIndex = plr->inventory.activeSlotIndex;
SDL_Texture *itemTex;
char itemStringCount[6];
if (itemIndex < itemRegistryIndex) {
SDL_Rect heldItemRect;
heldItemRect.x = plr->cursor.windowX;
heldItemRect.y = plr->cursor.windowY;
heldItemRect.w = TILE_SIZE;
heldItemRect.h = TILE_SIZE;
SDL_Texture *itemTex = ItemRegistry[itemIndex].textureOnBelt[plr->cursor.direction];
plr->cursor.heldItemRect.x = plr->cursor.windowX;
plr->cursor.heldItemRect.y = plr->cursor.windowY;
itemTex = ItemRegistry[itemIndex].textureOnBelt[plr->cursor.direction];
if (itemTex == NULL) {
itemTex = ItemRegistry[itemIndex].textureOnBelt[ORIENT_LEFT];
}
@@ -158,37 +194,29 @@ void renderPlayer(Player *plr) {
SDL_SetTextureAlphaMod(itemTex, 255);
}
SDL_RenderCopy(renderer, itemTex, NULL,
&heldItemRect);
SDL_RenderCopy(mainRenderer, itemTex, NULL,
&plr->cursor.heldItemRect);
renderText(mainRenderer, fonts[2], ItemRegistry[itemIndex].name, plr->cursor.heldItemRect.x,
plr->cursor.heldItemRect.y - (fonts[2].size * 3 / 2));
}
}
SDL_RenderCopy(renderer, PlayerTexture, NULL, &PlayerRect);
SDL_Color healthBarColor = {0, 240, 0, 255};
renderBar(renderer, (DISPLAY_WIDTH / 2) - 128, DISPLAY_HEIGHT - 50, 200, 8, playerMaxHealth, plr->health, healthBarColor, 4);
renderBar(mainRenderer, (DISPLAY_WIDTH / 2) - 128, DISPLAY_HEIGHT - 50, 200, 8, playerMaxHealth, plr->health,
healthBarColor, 4);
SDL_Color breakingBarColor = {128, 128, 0, 255};
renderBar(renderer, (DISPLAY_WIDTH / 2) - 128, DISPLAY_HEIGHT - 70, 200, 8,
renderBar(mainRenderer, (DISPLAY_WIDTH / 2) - 128, DISPLAY_HEIGHT - 70, 200, 8,
getBreakTime(plr->cursor.targetTile->type), plr->cursor.breakingProgress, breakingBarColor, 4);
SDL_Rect targetItemBGRect;
targetItemBGRect.w = DISPLAY_WIDTH;
targetItemBGRect.h = TILE_SIZE;
targetItemBGRect.x = 0;
targetItemBGRect.y = DISPLAY_HEIGHT - 30;
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
SDL_RenderFillRect(renderer, &targetItemBGRect);
SDL_Rect targetItemRect;
targetItemRect.w = TILE_SIZE / 2;
targetItemRect.h = TILE_SIZE / 2;
targetItemRect.y = DISPLAY_HEIGHT - 30 + TILE_SIZE / 4;
SDL_SetRenderDrawColor(mainRenderer, 0, 0, 0, 255);
SDL_RenderFillRect(mainRenderer, &targetItemBGRect);
targetItemRect.y = DISPLAY_HEIGHT - 30 + TILE_SIZE / 4 + 3;
targetItemRect.x = TILE_SIZE / 4;
for (uint16_t i = 1; i < ITEMREGISTRY_SIZE; i++) {
SDL_Texture *itemTex = ItemRegistry[i].textureOnBelt[plr->cursor.direction];
for (uint16_t i = 1; i < itemRegistryIndex; i++) {
itemTex = ItemRegistry[i].textureOnBelt[plr->cursor.direction];
if (itemTex == NULL) {
itemTex = ItemRegistry[i].textureOnBelt[ORIENT_LEFT];
}
@@ -197,15 +225,21 @@ void renderPlayer(Player *plr) {
// Set a red tint (255, 0, 0)
SDL_SetTextureColorMod(itemTex, 128, 128, 255);
}
SDL_RenderCopy(renderer, itemTex, NULL, &targetItemRect);
SDL_RenderCopy(mainRenderer, itemTex, NULL, &targetItemRect);
SDL_SetTextureColorMod(itemTex, 255, 255, 255);
}
if (plr->inventory.activeSlotIndex == i) {
SDL_SetRenderDrawColor(renderer, 16, plr->inventory.slotCounts[i] > 0 ? 128 : 16,
SDL_SetRenderDrawColor(mainRenderer, 16, plr->inventory.slotCounts[i] > 0 ? 128 : 16,
plr->inventory.slotCounts[i] > 0 ? 32 : 128, 255);
DrawThickRect(renderer, targetItemRect, 4);
DrawThickRect(mainRenderer, targetItemRect, 4);
}
targetItemRect.x += (TILE_SIZE / 2) + (TILE_SIZE / 4);
sprintf(itemStringCount, "%d", plr->inventory.slotCounts[i]);
renderText(mainRenderer, fonts[2], itemStringCount, targetItemRect.x - 3,
targetItemRect.y - (fonts[2].size * 3 / 2));
//targetItemRect.x += (TILE_SIZE / 2) + (TILE_SIZE / 4);
targetItemRect.x += TILE_SIZE;
}
SDL_SetRenderTarget(mainRenderer, originalTarget);
}

View File

@@ -9,19 +9,20 @@
#include "../items/item.h"
extern int playerReach;
extern int playerX;
extern int playerY;
#define playerTileX (playerX / TILE_SIZE)
#define playerTileY (playerY / TILE_SIZE)
#define playerTileX (player.rect.x / TILE_SIZE)
#define playerTileY (player.rect.y / TILE_SIZE)
extern int playerSpeed;
bool isInbounds(int x, int y);
extern SDL_Texture *entityTexture;
extern SDL_Texture *hudTexture;
bool isInboundsRect(SDL_Rect rect);
//bool isInbounds(int x, int y);
//
//bool isInboundsRect(SDL_Rect rect);
//
//bool isInboundsTile(int x, int y);
bool isInboundsTile(int x, int y);
void adjustRect(SDL_Rect *rect);
void adjustRect(SDL_Rect *rect, SDL_Rect playerRect);
#define neededHealthIdle 120
@@ -45,25 +46,26 @@ typedef struct {
SDL_Rect targetTileRect;
Tile *targetTile;
Tile *prevTargetTile;
SDL_Rect heldItemRect;
int breakingProgress;
} PlayerCursor;
typedef struct {
PlayerCursor cursor;
PlayerInventory inventory;
SDL_Renderer *renderer;
uint8_t health;
uint8_t prevHealth;
uint8_t healthIdle;
SDL_Rect rect;
} Player;
void setActivePlayerSlot(Player * plr, uint16_t activeSlotIndex);
void setActivePlayerSlot(Player *plr, uint16_t activeSlotIndex);
void moveActivePlayerSlot(Player *plr, bool up, bool seek);
void renderPlayer(Player * plr);
void renderPlayer(Player *plr);
void initPlayer(Player * plr);
void initPlayer(Player *plr);
void updatePlayer(Player *plr);

View File

@@ -9,16 +9,14 @@
#include "../player/player.h"
#include "../items/item.h"
static int scrollFrame = 0;
unsigned long beltFrames = 0;
void renderBelt(int x, int y, int w, int h, OrientDirection dir, 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 py = y * TILE_SIZE;
uint16_t tileType = tileMap[y][x].type;
Tile *t = &tileMap[y][x];
uint16_t tileType = t->type;
SDL_Rect src1, src2, dst1, dst2;
@@ -35,8 +33,8 @@ void renderBelt(int x, int y, int w, int h, OrientDirection dir, SDL_Renderer *r
src2 = (SDL_Rect) {0, 0, offset, TILE_SIZE};
dst2 = (SDL_Rect) {px + (w - offset), py, offset, h};
adjustRect(&dst1);
adjustRect(&dst2);
adjustRect(&dst1, playerRect);
adjustRect(&dst2, playerRect);
SDL_RenderCopy(renderer, TileRegistry[tileType].textures[dir], &src1, &dst1);
SDL_RenderCopy(renderer, TileRegistry[tileType].textures[dir], &src2, &dst2);
@@ -53,60 +51,19 @@ void renderBelt(int x, int y, int w, int h, OrientDirection dir, SDL_Renderer *r
src2 = (SDL_Rect) {0, 0, TILE_SIZE, offset};
dst2 = (SDL_Rect) {px, py + (h - offset), w, offset};
adjustRect(&dst1);
adjustRect(&dst2);
adjustRect(&dst1, playerRect);
adjustRect(&dst2, playerRect);
// Rotate to make the belt vertical
SDL_RenderCopy(renderer, TileRegistry[tileType].textures[dir], &src1, &dst1);
SDL_RenderCopy(renderer, TileRegistry[tileType].textures[dir], &src2, &dst2);
}
}
void renderAllBelts(SDL_Renderer *renderer) {
int scrollSpeed = 1; // pixels per step
int scrollDelay = 1; // frames between steps
if (beltFrames++ % scrollDelay == 0) {
scrollFrame += scrollSpeed;
}
int tileSize = TILE_SIZE;
for (int y = (playerY / TILE_SIZE) - (DISPLAY_MAP_HEIGHT / 2) - 1;
y < (playerY / TILE_SIZE) + (DISPLAY_MAP_HEIGHT / 2) + 1; y++) {
if (y < 0 || y >= MAP_HEIGHT) {
continue;
}
for (int x = (playerX / TILE_SIZE) - (DISPLAY_MAP_WIDTH / 2) - 1;
x < (playerX / TILE_SIZE) + (DISPLAY_MAP_WIDTH / 2) + 1; x++) {
if (x < 0 || x >= MAP_WIDTH) {
continue;
}
Tile t = tileMap[y][x];
if (t.type != TYPE_BELT) continue;
renderBelt(x, y, tileSize, tileSize, t.direction, renderer);
}
}
for (int y = (playerY / TILE_SIZE) - (DISPLAY_MAP_HEIGHT / 2) - 1;
y < (playerY / TILE_SIZE) + (DISPLAY_MAP_HEIGHT / 2) + 1; y++) {
if (y < 0 || y >= MAP_HEIGHT) {
continue;
}
for (int x = (playerX / TILE_SIZE) - (DISPLAY_MAP_WIDTH / 2) - 1;
x < (playerX / TILE_SIZE) + (DISPLAY_MAP_WIDTH / 2) + 1; x++) {
if (x < 0 || x >= MAP_WIDTH) {
continue;
}
Tile t = tileMap[y][x];
if (t.type != TYPE_BELT) continue;
SDL_SetRenderTarget(renderer, itemsTexture);
for (uint8_t lane = 0; lane < 2; lane++) {
for (uint8_t itemIndex = 0; itemIndex < 2; itemIndex++) {
if (t.items[lane][itemIndex].active) {
renderItem(t.items[lane][itemIndex], renderer, lane);
}
}
}
if (t->items[lane].type != 0) {
renderItem(t->items[lane], renderer, lane, playerRect);
}
}
}

View File

@@ -4,13 +4,12 @@
#ifndef FACTORYGAME_BELT_H
#define FACTORYGAME_BELT_H
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include "tile.h"
#include "../util/util.h"
void renderBelt(int px, int py, int w, int h, OrientDirection dir, SDL_Renderer * renderer);
void renderAllBelts(SDL_Renderer * renderer);
void renderBelt(int x, int y, int w, int h, OrientDirection dir, SDL_Rect playerRect, SDL_Renderer *renderer);
#endif //FACTORYGAME_BELT_H

14
tiles/furnace.c Normal file
View File

@@ -0,0 +1,14 @@
//
// Created by bruno on 31.5.2025.
//
#include "furnace.h"
#include "tile.h"
uint16_t getFurnaceNewItem(uint16_t sourceItem) {
uint16_t realItemIndex = sourceItem - tileTypeIndex - 1;
if (realItemIndex < 8) {
return sourceItem + 1;
}
return 0;
}

10
tiles/furnace.h Normal file
View File

@@ -0,0 +1,10 @@
//
// Created by bruno on 31.5.2025.
//
#ifndef FACTORYGAME_FURNACE_H
#define FACTORYGAME_FURNACE_H
#include "stdint.h"
#endif //FACTORYGAME_FURNACE_H

View File

@@ -4,10 +4,17 @@
#include <dirent.h>
#include "tile.h"
#include "../player/player.h"
int scrollFrame = 0;
unsigned long beltFrames = 0;
SDL_Texture *tilesTexture;
SDL_Texture *itemsTexture;
Tile tileMap[MAP_HEIGHT][MAP_WIDTH];
uint16_t tileTypeIndex = 1;
uint16_t tileTypeIndex = 0;
TileType TileRegistry[TILEREGISTRY_SIZE];
@@ -31,6 +38,13 @@ void generateTestMap() {
tileMap[y][x].direction = (rand() % 4 * 2) + 1;
}
}
uint8_t type = 0;
for (int x = 142; x < 154; x += 3) {
for (int y = 80; y < 94; y += 3) {
putItem(x, y, type++ % ITEMREGISTRY_SIZE, 0);
}
}
}
@@ -45,23 +59,25 @@ void registerTile(char name[20], SDL_Renderer *renderer) {
TileRegistry[tileTypeIndex].textures[ORIENT_UP] = createRotatedTexture(renderer, texture, 90);
TileRegistry[tileTypeIndex].textures[ORIENT_DOWN] = createRotatedTexture(renderer, texture, 270);
TileRegistry[tileTypeIndex].type = tileTypeIndex;
TileRegistry[tileTypeIndex].breakTime = 30;
TileRegistry[tileTypeIndex].breakTime = 15;
tileTypeIndex++;
}
void loadTiles(SDL_Renderer *renderer) {
DIR *dir = opendir("./assets/tiles");
if (dir) {
struct dirent *entry;
while ((entry = readdir(dir)) != NULL) {
if (entry->d_name[0] == '.') {
continue;
}
registerTile(entry->d_name, renderer);
}
}
iterateSortedDir("./assets/tiles", (DirEntryCallback) registerTile, renderer);
// DIR *dir = opendir("./assets/tiles");
// if (dir) {
// struct dirent *entry;
// while ((entry = readdir(dir)) != NULL) {
// if (entry->d_name[0] == '.') {
// continue;
// }
// registerTile(entry->d_name, mainRenderer);
// }
// }
TileRegistry[0].breakTime = 0;
}
uint16_t getBreakTime(int type) {
@@ -70,3 +86,66 @@ uint16_t getBreakTime(int type) {
}
return TileRegistry[type].breakTime;
}
void initTiles() {
itemsTexture = SDL_CreateTexture(mainRenderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, screenRect.w,
screenRect.h);
tilesTexture = SDL_CreateTexture(mainRenderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, screenRect.w,
screenRect.h);
SDL_SetTextureBlendMode(itemsTexture, SDL_BLENDMODE_BLEND);
SDL_SetTextureBlendMode(tilesTexture, SDL_BLENDMODE_BLEND);
}
void renderAllTiles(SDL_Renderer *renderer, SDL_Rect playerRect) {
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0);
SDL_Texture *oldTarget = SDL_GetRenderTarget(renderer);
SDL_SetRenderTarget(renderer, itemsTexture);
SDL_RenderClear(renderer);
SDL_SetRenderTarget(renderer, tilesTexture);
SDL_RenderClear(renderer);
int scrollSpeed = 1; // pixels per step
int scrollDelay = 1; // frames between steps
if (beltFrames++ % scrollDelay == 0) {
scrollFrame += scrollSpeed;
}
int tileSize = TILE_SIZE;
for (int y = (playerRect.y / TILE_SIZE) - (DISPLAY_MAP_HEIGHT / 2) - 1;
y < (playerRect.y / TILE_SIZE) + (DISPLAY_MAP_HEIGHT / 2) + 1; y++) {
if (y < 0 || y >= MAP_HEIGHT) {
continue;
}
for (int x = (playerRect.x / TILE_SIZE) - (DISPLAY_MAP_WIDTH / 2) - 1;
x < (playerRect.x / TILE_SIZE) + (DISPLAY_MAP_WIDTH / 2) + 1; x++) {
if (x < 0 || x >= MAP_WIDTH) {
continue;
}
Tile t = tileMap[y][x];
SDL_SetRenderTarget(renderer, tilesTexture);
switch (t.type) {
case TYPE_BELT:
renderBelt(x, y, tileSize, tileSize, t.direction, playerRect, renderer);
break;
default:
SDL_Rect dstRect;
dstRect.x = x * TILE_SIZE;
dstRect.y = y * TILE_SIZE;
dstRect.w = TILE_SIZE;
dstRect.h = TILE_SIZE;
adjustRect(&dstRect, playerRect);
SDL_Texture *tex = TileRegistry[t.type].textures[t.direction];
if (tex == NULL) {
tex = TileRegistry[t.type].textures[ORIENT_LEFT];
}
if (tex != NULL) {
SDL_RenderCopy(renderer, tex, NULL, &dstRect);
}
}
if (t.type == TYPE_BELT) {
}
}
}
SDL_SetRenderTarget(renderer, oldTarget);
}

View File

@@ -12,14 +12,20 @@
#define MAP_WIDTH 600
#define MAP_HEIGHT 340
#define DISPLAY_MAP_WIDTH 30
#define DISPLAY_MAP_HEIGHT 16
#define DISPLAY_MAP_WIDTH 44
#define DISPLAY_MAP_HEIGHT 22
#define TILE_SIZE 32
#define DISPLAY_WIDTH DISPLAY_MAP_WIDTH * TILE_SIZE
#define DISPLAY_HEIGHT DISPLAY_MAP_HEIGHT * TILE_SIZE
extern SDL_Texture *tilesTexture;
extern SDL_Texture *itemsTexture;
extern int scrollFrame;
extern unsigned long beltFrames;
typedef struct {
uint16_t type;
char name[20];
@@ -32,13 +38,15 @@ typedef struct {
extern TileType TileRegistry[TILEREGISTRY_SIZE];
#define TYPE_AIR 0
#define TYPE_BELT 1
#define TYPE_BELT 2
void renderAllTiles(SDL_Renderer * renderer, SDL_Rect playerRect);
typedef struct {
OrientDirection direction;
uint16_t type;
int frameOffset;
ItemOnBelt items[2][2];
ItemOnBelt items[2];
int x;
int y;
} Tile;
@@ -52,4 +60,6 @@ extern uint16_t tileTypeIndex;
uint16_t getBreakTime(int type);
void initTiles();
#endif //FACTORYGAME_TILE_H

View File

@@ -18,7 +18,7 @@ void audio_callback(void *userdata, Uint8 *stream, int len) {
SynthVoice *voice = &audio->synthVoices[v];
if (voice->volume == 0 || voice->frequency == 0) continue;
float sample = 0.0f;
float sample;
float t = (float) voice->phase / 255.0f * 2.0f - 1.0f;
switch (voice->waveform) {

View File

@@ -2,6 +2,7 @@
// Created by bruno on 4/24/25.
//
#include <dirent.h>
#include "util.h"
//#include "font.h"
@@ -9,16 +10,20 @@
SDL_Window *window = NULL;
volatile bool running = true;
//The surface contained by the window
SDL_Renderer *renderer = NULL;
bool debugMode = false;
SDL_Texture* createFlippedTexture(SDL_Renderer* renderer, SDL_Texture* src, SDL_RendererFlip flip) {
//The surface contained by the window
SDL_Renderer *mainRenderer = NULL;
SDL_Rect screenRect;
SDL_Texture *createFlippedTexture(SDL_Renderer *renderer, SDL_Texture *src, SDL_RendererFlip flip) {
int w, h;
SDL_QueryTexture(src, NULL, NULL, &w, &h);
SDL_Texture *renderTarget = SDL_GetRenderTarget(renderer);
SDL_Texture* target = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, w, h);
SDL_Texture *target = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, w, h);
SDL_SetRenderTarget(renderer, target);
SDL_RenderCopyEx(renderer, src, NULL, NULL, 0, NULL, flip);
SDL_SetRenderTarget(renderer, renderTarget);
@@ -26,12 +31,12 @@ SDL_Texture* createFlippedTexture(SDL_Renderer* renderer, SDL_Texture* src, SDL_
return target;
}
SDL_Texture* createRotatedTexture(SDL_Renderer* renderer, SDL_Texture* src, double angle) {
SDL_Texture *createRotatedTexture(SDL_Renderer *renderer, SDL_Texture *src, double angle) {
int w, h;
SDL_QueryTexture(src, NULL, NULL, &w, &h);
SDL_Texture *renderTarget = SDL_GetRenderTarget(renderer);
SDL_Texture* target = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, w, h);
SDL_Texture *target = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, w, h);
SDL_SetRenderTarget(renderer, target);
SDL_RenderCopyEx(renderer, src, NULL, NULL, angle, NULL, SDL_FLIP_NONE);
SDL_SetRenderTarget(renderer, renderTarget);
@@ -39,8 +44,8 @@ SDL_Texture* createRotatedTexture(SDL_Renderer* renderer, SDL_Texture* src, doub
return target;
}
SDL_Texture* ScaleTexture(SDL_Renderer* renderer, SDL_Texture* src, int newWidth, int newHeight) {
SDL_Texture* scaledTex = SDL_CreateTexture(renderer,
SDL_Texture *ScaleTexture(SDL_Renderer *renderer, SDL_Texture *src, int newWidth, int newHeight) {
SDL_Texture *scaledTex = SDL_CreateTexture(renderer,
SDL_PIXELFORMAT_RGBA8888,
SDL_TEXTUREACCESS_TARGET,
newWidth,
@@ -52,13 +57,13 @@ SDL_Texture* ScaleTexture(SDL_Renderer* renderer, SDL_Texture* src, int newWidth
}
// Save current render target
SDL_Texture* oldTarget = SDL_GetRenderTarget(renderer);
SDL_Texture *oldTarget = SDL_GetRenderTarget(renderer);
SDL_SetRenderTarget(renderer, scaledTex);
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0);
SDL_RenderClear(renderer);
SDL_Rect dst = { 0, 0, newWidth, newHeight };
SDL_Rect dst = {0, 0, newWidth, newHeight};
SDL_RenderCopy(renderer, src, NULL, &dst);
SDL_SetRenderTarget(renderer, oldTarget); // Restore
@@ -66,9 +71,9 @@ SDL_Texture* ScaleTexture(SDL_Renderer* renderer, SDL_Texture* src, int newWidth
return scaledTex;
}
void DrawThickRect(SDL_Renderer* renderer, SDL_Rect rect, int thickness) {
void DrawThickRect(SDL_Renderer *renderer, SDL_Rect rect, int thickness) {
for (int i = 0; i < thickness; i++) {
SDL_Rect r = { rect.x - i, rect.y - i, rect.w + i * 2, rect.h + i * 2 };
SDL_Rect r = {rect.x - i, rect.y - i, rect.w + i * 2, rect.h + i * 2};
SDL_RenderDrawRect(renderer, &r);
}
}
@@ -76,8 +81,7 @@ void DrawThickRect(SDL_Renderer* renderer, SDL_Rect rect, int thickness) {
void renderBar(SDL_Renderer *renderer,
int x, int y, int width, int height,
int maxValue, int currentValue,
SDL_Color barColor, int margin)
{
SDL_Color barColor, int margin) {
if (maxValue <= 0) return; // Avoid division by zero
// Clamp value
@@ -91,7 +95,7 @@ void renderBar(SDL_Renderer *renderer,
int filledWidth = (width * currentValue) / maxValue;
// Bar rectangle
SDL_Rect barRect = { x, y, filledWidth, height };
SDL_Rect barRect = {x, y, filledWidth, height};
// Background rectangle with margin
SDL_Rect bgRect = {
@@ -112,5 +116,50 @@ void renderBar(SDL_Renderer *renderer,
char barString[20];
sprintf(barString, "%d/%d", currentValue, maxValue);
//renderText(renderer, fonts[3], barString, width / 2, margin);
//renderText(mainRenderer, fonts[3], barString, width / 2, margin);
}
int cmpstringp(const void *p1, const void *p2) {
return strcmp(*(const char **)p1, *(const char **)p2);
}
// Helper function to iterate over sorted entries in a directory
void iterateSortedDir(const char *path, DirEntryCallback callback, SDL_Renderer *renderer) {
DIR *dir = opendir(path);
if (!dir) {
perror("opendir");
return;
}
struct dirent *entry;
char **names = NULL;
size_t count = 0;
// Collect file names
while ((entry = readdir(dir)) != NULL) {
if (entry->d_name[0] == '.') continue;
names = realloc(names, sizeof(char *) * (count + 1));
if (!names) {
perror("realloc");
closedir(dir);
return;
}
names[count++] = strdup(entry->d_name);
}
closedir(dir);
// Sort entries
qsort(names, count, sizeof(char *), cmpstringp);
// Call the user-provided function for each file
if (names != NULL) {
for (size_t i = 0; i < count; i++) {
if (names[i] != NULL) {
callback(names[i], renderer);
free(names[i]);
}
}
free(names);
}
}

View File

@@ -11,7 +11,9 @@ extern SDL_Window *window;
extern volatile bool running;
//The surface contained by the window
extern SDL_Renderer *renderer;
extern SDL_Renderer *mainRenderer;
extern SDL_Rect screenRect;
typedef enum {
ORIENT_LEFT_DOWN,
@@ -25,6 +27,8 @@ typedef enum {
ORIENT_DIRECTION_COUNT
} OrientDirection;
extern bool debugMode;
SDL_Texture *createRotatedTexture(SDL_Renderer *renderer, SDL_Texture *src, double angle);
SDL_Texture *createFlippedTexture(SDL_Renderer *renderer, SDL_Texture *src, SDL_RendererFlip flip);
@@ -33,6 +37,12 @@ SDL_Texture* ScaleTexture(SDL_Renderer* renderer, SDL_Texture* src, int newWidth
void DrawThickRect(SDL_Renderer* renderer, SDL_Rect rect, int thickness);
// Define a function pointer type for your callback
typedef void (*DirEntryCallback)(const char *filename, SDL_Renderer *renderer);
// Helper function to iterate over sorted entries in a directory
void iterateSortedDir(const char *path, DirEntryCallback callback, SDL_Renderer *renderer);
void renderBar(SDL_Renderer *renderer,
int x, int y, int width, int height,
int maxValue, int currentValue,