Some more progress

This commit is contained in:
2025-05-30 22:31:59 +02:00
parent d01bdbe819
commit 0c9698879b
13 changed files with 290 additions and 72 deletions

View File

@@ -21,9 +21,9 @@ add_executable(factorygame
tiles/tile.h
tiles/belt.c
tiles/belt.h
main.c
player/player.c
player/player.h) # Ensure the target is defined before linking
player/player.h # Ensure the target is defined before linking
main.c)
# Define the path to the assets folder
set(ASSETS_SOURCE_DIR "${CMAKE_SOURCE_DIR}/assets")

BIN
assets/player.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 398 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 215 B

After

Width:  |  Height:  |  Size: 202 B

View File

@@ -3,8 +3,6 @@
//
#include "item.h"
#include "../tiles/tile.h"
#include "../util/util.h"
#include "../player/player.h"
#include "../util/font.h"
#include <dirent.h>
@@ -257,18 +255,18 @@ void renderItem(ItemOnBelt item, SDL_Renderer *renderer, int lane) {
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};
// 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_RenderCopy(renderer, ItemRegistry[item.type].textureOnBelt[ORIENT_LEFT], NULL, &rect);
renderText(renderer, fonts[3], tempStr, rectA.x, rectA.y);
// renderText(renderer, fonts[3], tempStr, rectA.x, rectA.y);
}
void renderBeltItems(SDL_Renderer *renderer) {

View File

@@ -4,10 +4,20 @@
#include <SDL2/SDL.h>
#include "../util/util.h"
#include "../tiles/belt.h"
#ifndef FACTORYGAME_ITEM_H
#define FACTORYGAME_ITEM_H
#define ITEMREGISTRY_SIZE 20
typedef struct {
float offset;
int tileX, tileY;
bool active;
uint16_t type;
} ItemOnBelt;
typedef struct {
uint16_t type;
char name[20];
@@ -15,17 +25,9 @@ typedef struct {
SDL_Texture * textureOnBelt[ORIENT_DIRECTION_COUNT];
} Item;
#define ITEMREGISTRY_SIZE 512
extern Item ItemRegistry[ITEMREGISTRY_SIZE];
typedef struct {
float offset;
int tileX, tileY;
bool active;
uint16_t type;
} ItemOnBelt;
void updateItems();
void loadItems(SDL_Renderer *renderer);

93
main.c
View File

@@ -160,9 +160,6 @@ int processEvent(SDL_Event e) {
int keyMod = e.key.keysym.mod;
cursor = true;
switch (keySym) {
case SDLK_q:
laneTarget = laneTarget == 1 ? 0 : 1;
break;
case SDLK_p:
speed = speed == 0 ? 0.004f : 0;
break;
@@ -187,17 +184,18 @@ int processEvent(SDL_Event e) {
}
const Uint8 *keyboardState = SDL_GetKeyboardState(NULL);
if (keyboardState[SDL_SCANCODE_LCTRL] || keyboardState[SDL_SCANCODE_RCTRL]) {
currentScale += dAmount / 10.0f;
if (currentScale > 4) {
currentScale = 4;
} else if (currentScale < 0.5f) {
currentScale = 0.5f;
}
// currentScale += dAmount / 10.0f;
// if (currentScale > 4) {
// currentScale = 4;
// } else if (currentScale < 0.5f) {
// currentScale = 0.5f;
// }
//setZoom(currentScale);
} else {
setActivePlayerSlot(&player, player.inventory.activeSlotIndex + dAmount);
moveActivePlayerSlot(&player, dAmount == -1,
!(keyboardState[SDL_SCANCODE_LSHIFT] || keyboardState[SDL_SCANCODE_RSHIFT]));
}
}
return 1;
@@ -209,41 +207,64 @@ void processMousePosition() {
uint32_t mouseButtons = SDL_GetMouseState(&player.cursor.windowX, &player.cursor.windowY);
if (mouseButtons & SDL_BUTTON_LMASK) {
if(player.cursor.targetTile->type == TYPE_AIR && player.inventory.activeSlotIndex < tileTypeIndex) {
if (player.cursor.canReach && player.cursor.targetTile->type == TYPE_AIR &&
player.inventory.activeSlotIndex < tileTypeIndex) {
if (player.inventory.slotCounts[player.inventory.activeSlotIndex] > 0) {
player.inventory.slotCounts[player.inventory.activeSlotIndex]--;
player.cursor.targetTile->type = player.inventory.activeSlotIndex + 1;
player.cursor.targetTile->type = player.inventory.activeSlotIndex;
player.cursor.targetTile->direction = player.cursor.direction;
}
} else if (player.cursor.targetTile->type == player.inventory.activeSlotIndex) {
player.cursor.targetTile->direction = player.cursor.direction;
}
} else if (mouseButtons & SDL_BUTTON_RMASK) {
if (player.cursor.targetTile != player.cursor.prevTargetTile) {
player.cursor.breakingProgress = 0;
}
int tileIndex = player.cursor.targetTile->type - 1;
}
if (player.cursor.canReach && mouseButtons & SDL_BUTTON_RMASK) {
int tileIndex = player.cursor.targetTile->type;
uint16_t targetBreakTime = TileRegistry[tileIndex].breakTime;
if (targetBreakTime) {
if (player.cursor.breakingProgress >= targetBreakTime) {
if (player.cursor.targetTile->type - 1 < tileTypeIndex) {
player.inventory.slotCounts[player.cursor.targetTile->type - 1]++;
if (player.cursor.targetTile->type < tileTypeIndex) {
player.inventory.slotCounts[player.cursor.targetTile->type]++;
}
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 (itemType < itemRegistryIndex) {
player.inventory.slotCounts[itemType]++;
}
player.cursor.targetTile->items[lane][slot].active = false;
}
}
}
}
player.cursor.targetTile->type = TYPE_AIR;
player.cursor.breakingProgress = 0;
} else {
player.cursor.breakingProgress++;
}
printf("Player breaking %d\n", player.cursor.breakingProgress);
//printf("Player breaking %d\n", player.cursor.breakingProgress);
}
} else if (mouseButtons & SDL_BUTTON_MMASK) {
} else {
player.cursor.breakingProgress = 0;
}
if (player.cursor.targetTile != player.cursor.prevTargetTile) {
player.cursor.breakingProgress = 0;
}
if (mouseButtons & SDL_BUTTON_MMASK) {
if (player.cursor.targetTile->type > 0) {
setActivePlayerSlot(&player, player.cursor.targetTile->type);
}
}
// 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 / TILE_SIZE + (playerX / TILE_SIZE) - (SCREEN_WIDTH / TILE_SIZE / 2);
player.cursor.tileY = player.cursor.windowY / TILE_SIZE + (playerY / TILE_SIZE) - (SCREEN_HEIGHT / TILE_SIZE / 2);
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.prevTargetTile = player.cursor.targetTile;
player.cursor.targetTile = &tileMap[player.cursor.tileY][player.cursor.tileX];
}
@@ -285,6 +306,31 @@ void processKeyboardHeld() {
playerX = (MAP_WIDTH * TILE_SIZE) - (SCREEN_WIDTH / 2);
}
}
if (keyboardState[SDL_SCANCODE_Q]) {
if (player.cursor.targetTile->type > 0) {
setActivePlayerSlot(&player, player.cursor.targetTile->type);
}
}
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);
player.inventory.slotCounts[player.inventory.activeSlotIndex]--;
done = true;
break;
}
}
if (done) {
break;
}
}
}
}
}
int main(__attribute__((unused)) int argc, __attribute__((unused)) char *args[]) {
@@ -316,6 +362,7 @@ int main(__attribute__((unused)) int argc, __attribute__((unused)) char *args[])
}
updateItems();
updatePlayer(&player);
status = render();
if (status) {
return status;

View File

@@ -6,18 +6,52 @@
#include "player.h"
#include "../tiles/tile.h"
#define HEALTH_MARGIN 4
int playerSpeed = 4;
int playerReach = 4;
SDL_Texture *PlayerTexture;
SDL_Rect PlayerRect;
void setActivePlayerSlot(Player *plr, uint16_t activeSlotIndex) {
activeSlotIndex = activeSlotIndex % ITEMREGISTRY_SIZE;
if (activeSlotIndex < 0) {
activeSlotIndex = 0;
activeSlotIndex = activeSlotIndex % itemRegistryIndex;
if (activeSlotIndex <= 0) {
activeSlotIndex = 1;
}
plr->inventory.activeSlotIndex = activeSlotIndex;
}
void moveActivePlayerSlot(Player *plr, bool up, bool seek) {
if (seek) {
uint16_t prevSlot = plr->inventory.activeSlotIndex;
uint16_t newSlot = prevSlot;
do {
newSlot = (newSlot + (up ? 1 : ITEMREGISTRY_SIZE - 1)) % ITEMREGISTRY_SIZE;
// Stop if we've looped all the way around
if (newSlot == prevSlot) break;
// Stop if we found a slot with count > 0
if (plr->inventory.slotCounts[newSlot] > 0) break;
} while (true);
plr->inventory.activeSlotIndex = newSlot;
} else {
if (plr->inventory.activeSlotIndex == 1 && !up) {
plr->inventory.activeSlotIndex = itemRegistryIndex - 1;
} else if (plr->inventory.activeSlotIndex == itemRegistryIndex - 1 && up) {
plr->inventory.activeSlotIndex = 1;
} else {
plr->inventory.activeSlotIndex =
(plr->inventory.activeSlotIndex + (up ? 1 : ITEMREGISTRY_SIZE - 1)) % ITEMREGISTRY_SIZE;
}
}
}
int playerX = (MAP_WIDTH / 2) * 16;
int playerY = (MAP_HEIGHT / 2) * 16;
@@ -63,7 +97,23 @@ bool isInboundsRect(SDL_Rect rect) {
void initPlayer(Player *plr) {
plr->cursor.direction = ORIENT_UP;
setActivePlayerSlot(plr, 0);
setActivePlayerSlot(plr, 1);
PlayerTexture = IMG_LoadTexture(renderer, "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;
}
void updatePlayer(Player *plr) {
if (plr->health == plr->prevHealth && plr->healthIdle < neededHealthIdle) {
plr->healthIdle++;
}
if (plr->health < playerMaxHealth && plr->healthIdle >= neededHealthIdle) {
plr->health++;
}
plr->prevHealth = plr->health;
}
void renderPlayer(Player *plr) {
@@ -75,7 +125,7 @@ void renderPlayer(Player *plr) {
SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND);
plr->cursor.tileDiffX = plr->cursor.tileX - playerTileX;
plr->cursor.tileDiffY = plr->cursor.tileY - playerTileY;
if (plr->cursor.tileDiffX > plr->cursor.tileDiffY) {
if (abs(plr->cursor.tileDiffX) > abs(plr->cursor.tileDiffY)) {
plr->cursor.tileDiff = plr->cursor.tileDiffX;
} else {
plr->cursor.tileDiff = plr->cursor.tileDiffY;
@@ -87,21 +137,75 @@ void renderPlayer(Player *plr) {
uint16_t itemIndex = plr->inventory.activeSlotIndex;
if (itemIndex < itemRegistryIndex) {
if (plr->inventory.slotCounts[itemIndex] > 0) {
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];
if (itemTex == NULL) {
itemTex = ItemRegistry[itemIndex].textureOnBelt[ORIENT_LEFT];
}
if (itemTex != NULL) {
SDL_RenderCopy(renderer, ItemRegistry[itemIndex].textureOnBelt[plr->cursor.direction], NULL,
&heldItemRect);
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];
if (itemTex == NULL) {
itemTex = ItemRegistry[itemIndex].textureOnBelt[ORIENT_LEFT];
}
if (itemTex != NULL) {
if (plr->inventory.slotCounts[itemIndex] <= 0) {
// Set a red tint (255, 0, 0)
SDL_SetTextureColorMod(itemTex, 128, 128, 255);
SDL_SetTextureAlphaMod(itemTex, 192);
} else {
SDL_SetTextureColorMod(itemTex, 255, 255, 255);
SDL_SetTextureAlphaMod(itemTex, 255);
}
SDL_RenderCopy(renderer, itemTex, NULL,
&heldItemRect);
}
}
//printf("Player inventory index: %d\n", plr->inventory.activeSlotIndex);
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);
SDL_Color breakingBarColor = {128, 128, 0, 255};
renderBar(renderer, (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;
targetItemRect.x = TILE_SIZE / 4;
for (uint16_t i = 1; i < ITEMREGISTRY_SIZE; i++) {
SDL_Texture *itemTex = ItemRegistry[i].textureOnBelt[plr->cursor.direction];
if (itemTex == NULL) {
itemTex = ItemRegistry[i].textureOnBelt[ORIENT_LEFT];
}
if (itemTex != NULL) {
if (plr->inventory.slotCounts[i] <= 0) {
// Set a red tint (255, 0, 0)
SDL_SetTextureColorMod(itemTex, 128, 128, 255);
}
SDL_RenderCopy(renderer, 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,
plr->inventory.slotCounts[i] > 0 ? 32 : 128, 255);
DrawThickRect(renderer, targetItemRect, 4);
}
targetItemRect.x += (TILE_SIZE / 2) + (TILE_SIZE / 4);
}
}

View File

@@ -6,6 +6,7 @@
#define FACTORYGAME_PLAYER_H
#include "../tiles/tile.h"
#include "../items/item.h"
extern int playerReach;
extern int playerX;
@@ -22,6 +23,10 @@ bool isInboundsTile(int x, int y);
void adjustRect(SDL_Rect *rect);
#define neededHealthIdle 120
#define playerMaxHealth 255
typedef struct {
uint16_t slotCounts[ITEMREGISTRY_SIZE];
uint16_t activeSlotIndex;
@@ -47,12 +52,19 @@ typedef struct {
PlayerCursor cursor;
PlayerInventory inventory;
SDL_Renderer *renderer;
uint8_t health;
uint8_t prevHealth;
uint8_t healthIdle;
} Player;
void setActivePlayerSlot(Player * plr, uint16_t activeSlotIndex);
void moveActivePlayerSlot(Player *plr, bool up, bool seek);
void renderPlayer(Player * plr);
void initPlayer(Player * plr);
void updatePlayer(Player *plr);
#endif //FACTORYGAME_PLAYER_H

View File

@@ -7,6 +7,7 @@
#include "../util/util.h"
#include "tile.h"
#include "../player/player.h"
#include "../items/item.h"
static int scrollFrame = 0;
unsigned long beltFrames = 0;
@@ -17,7 +18,7 @@ void renderBelt(int x, int y, int w, int h, OrientDirection dir, SDL_Renderer *r
int px = x * TILE_SIZE;
int py = y * TILE_SIZE;
uint16_t tileType = tileMap[y][x].type - 1;
uint16_t tileType = tileMap[y][x].type;
SDL_Rect src1, src2, dst1, dst2;

View File

@@ -4,12 +4,10 @@
#include <dirent.h>
#include "tile.h"
#include "../player/player.h"
#include "../util/util.h"
Tile tileMap[MAP_HEIGHT][MAP_WIDTH];
uint16_t tileTypeIndex = 0;
uint16_t tileTypeIndex = 1;
TileType TileRegistry[TILEREGISTRY_SIZE];
@@ -47,7 +45,7 @@ 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 = 60;
TileRegistry[tileTypeIndex].breakTime = 30;
tileTypeIndex++;
}
@@ -64,4 +62,11 @@ void loadTiles(SDL_Renderer *renderer) {
registerTile(entry->d_name, renderer);
}
}
}
uint16_t getBreakTime(int type) {
if (type >= tileTypeIndex) {
return 0;
}
return TileRegistry[type].breakTime;
}

View File

@@ -6,8 +6,8 @@
#define FACTORYGAME_TILE_H
#include "belt.h"
#include "../items/item.h"
#include "../util/util.h"
#include "../items/item.h"
#define MAP_WIDTH 600
#define MAP_HEIGHT 340
@@ -50,4 +50,6 @@ void loadTiles(SDL_Renderer *renderer);
extern uint16_t tileTypeIndex;
uint16_t getBreakTime(int type);
#endif //FACTORYGAME_TILE_H

View File

@@ -3,7 +3,7 @@
//
#include "util.h"
#include "../tiles/tile.h"
//#include "font.h"
//The window we'll be rendering to
SDL_Window *window = NULL;
@@ -72,3 +72,45 @@ void DrawThickRect(SDL_Renderer* renderer, SDL_Rect rect, int thickness) {
SDL_RenderDrawRect(renderer, &r);
}
}
void renderBar(SDL_Renderer *renderer,
int x, int y, int width, int height,
int maxValue, int currentValue,
SDL_Color barColor, int margin)
{
if (maxValue <= 0) return; // Avoid division by zero
// Clamp value
if (currentValue < 0) currentValue = 0;
if (currentValue == 0) {
return;
}
if (currentValue > maxValue) currentValue = maxValue;
// Calculate filled width based on currentValue
int filledWidth = (width * currentValue) / maxValue;
// Bar rectangle
SDL_Rect barRect = { x, y, filledWidth, height };
// Background rectangle with margin
SDL_Rect bgRect = {
x - margin,
y - margin,
width + margin * 2,
height + margin * 2
};
// Draw background (black)
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
SDL_RenderFillRect(renderer, &bgRect);
// Draw bar with provided color
SDL_SetRenderDrawColor(renderer, barColor.r, barColor.g, barColor.b, barColor.a);
SDL_RenderFillRect(renderer, &barRect);
char barString[20];
sprintf(barString, "%d/%d", currentValue, maxValue);
//renderText(renderer, fonts[3], barString, width / 2, margin);
}

View File

@@ -33,4 +33,9 @@ SDL_Texture* ScaleTexture(SDL_Renderer* renderer, SDL_Texture* src, int newWidth
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);
#endif //FACTORYGAME_UTIL_H