From 451e80f7506e063c748252750c38485e27c425dd Mon Sep 17 00:00:00 2001 From: bruno Date: Thu, 24 Apr 2025 20:04:41 +0200 Subject: [PATCH] something --- CMakeLists.txt | 24 ++++- assets/dopravnik.png | Bin 187 -> 0 bytes assets/items/gold_ingot.png | Bin 0 -> 517 bytes assets/items/gold_ore.png | Bin 0 -> 566 bytes assets/items/iron_ingot.png | Bin 0 -> 516 bytes assets/items/iron_ore.png | Bin 0 -> 513 bytes assets/items/log.png | Bin 0 -> 592 bytes assets/items/platinum_ingot.png | Bin 0 -> 492 bytes assets/items/platinum_ore.png | Bin 0 -> 526 bytes assets/items/silver_ingot.png | Bin 0 -> 530 bytes assets/items/silver_ore.png | Bin 0 -> 546 bytes assets/tiles/dopravnik.png | Bin 0 -> 215 bytes items/item.c | 127 +++++++++++++++++++++++ items/item.h | 35 +++++++ main.c | 176 +++----------------------------- player/player.c | 48 +++++++++ player/player.h | 16 +++ tiles/belt.c | 85 +++++++++++++++ tiles/belt.h | 16 +++ tiles/tile.c | 67 ++++++++++++ tiles/tile.h | 49 +++++++++ util/util.c | 55 ++++++++++ util/util.h | 28 +++++ 23 files changed, 565 insertions(+), 161 deletions(-) delete mode 100644 assets/dopravnik.png create mode 100644 assets/items/gold_ingot.png create mode 100644 assets/items/gold_ore.png create mode 100644 assets/items/iron_ingot.png create mode 100644 assets/items/iron_ore.png create mode 100644 assets/items/log.png create mode 100644 assets/items/platinum_ingot.png create mode 100644 assets/items/platinum_ore.png create mode 100644 assets/items/silver_ingot.png create mode 100644 assets/items/silver_ore.png create mode 100644 assets/tiles/dopravnik.png create mode 100644 items/item.c create mode 100644 items/item.h create mode 100644 player/player.c create mode 100644 player/player.h create mode 100644 tiles/belt.c create mode 100644 tiles/belt.h create mode 100644 tiles/tile.c create mode 100644 tiles/tile.h create mode 100644 util/util.c create mode 100644 util/util.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 9519a38..5ea9c43 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,6 +13,28 @@ add_executable(factorygame util/font.h util/audio.c util/audio.h - main.c) # Ensure the target is defined before linking + util/util.c + util/util.h + items/item.c + items/item.h + tiles/tile.c + tiles/tile.h + tiles/belt.c + tiles/belt.h + main.c + player/player.c + player/player.h) # Ensure the target is defined before linking + +# Define the path to the assets folder +set(ASSETS_SOURCE_DIR "${CMAKE_SOURCE_DIR}/assets") +set(ASSETS_BINARY_DIR "${CMAKE_BINARY_DIR}/assets") + +# Copy assets directory after build +add_custom_command(TARGET factorygame POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_directory + "${ASSETS_SOURCE_DIR}" "${ASSETS_BINARY_DIR}" + COMMENT "Copying assets directory to build output..." +) + target_link_libraries(factorygame SDL2 SDL2_ttf SDL2_image SDL2_gfx SDL2_mixer SDL2_net m) \ No newline at end of file diff --git a/assets/dopravnik.png b/assets/dopravnik.png deleted file mode 100644 index f4d4b2029f66db3462200fea11e72b0cd6dd2185..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 187 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s77>k44ofy`glX=O&z)x)d2d0m1SgJZgQ4llCw4`A^WOjZhI-X$TtQtHCd p86H;~^x6bFmPj44c(7BDq3CsPU9R})-wX^444$rjF6*2Ung9zCK_&nI diff --git a/assets/items/gold_ingot.png b/assets/items/gold_ingot.png new file mode 100644 index 0000000000000000000000000000000000000000..e9bbb8df343d9e2192787ad67cbc4db4444bbe1b GIT binary patch literal 517 zcmeAS@N?(olHy`uVBq!ia0y~yU{C;I7G?$phQ^Te;~-A5N02WALzNl>LqiJ#!!HH~ zhK3gm45bDP46hOx7_4S6Fo+k-*%fHRz`!6E;1lA?00spSGDj9VJ=hib|9+pRwb0CR zt(#kd|NsAgpFL^{0|NtNNswPKgTu2MX&_FLx4R4H$D2#vFfcH%mw5WRvcKSv5t27! zw5!>`z`(HC)5S4F}&v@oR*}eDN=B>WfSj1c+n0EJ)i$i+g zRR+N|-Yo|6Wh;vO878SRdKf+E@NHBsJGFn#?Z<(9=88)c_CM$T$Es^S-KETrfq_A_ z#5JNMC9x#cD!C{%u_Tqj$iT=%*T6#8$Rfnh!phjt%Gg}nz`)ADfMxr`Z73RY^HVa@ uDsgKleH96cJPo)FC7HRY#U+Wk1(LqiJ#!!HH~ zhK3gm45bDP46hOx7_4S6Fo+k-*%fHRz`&p$;1lA?00y4cLQd9NGt0FSB5aQ=bn2{+ z*}l5@|NXv#2$@&6*Z=?j-{~{gH3kL-#*!evUYp2p3A$qWn(>?NMQ zuIw*3WQ63+80~5{FfcIO_H=O!(Kx?$f-Tn}2Z7eR(h`rPqB$)aB*hK}g*l$?J)HGg z|3+J?c(mhMU8Zdxm!IH0a(d;2UeEU>@00JHd3-giUUqrh)g$jiI5K&j%{5x^jOpzs zr{Wo3K0a5}dwlvezkt=;lt=-whO+s$MI<8}4ycqre*MV1+w+aAVwuhdl}#pmB~zk1 zZgJjd5vt`b*t+NE0*5CDtmjnTV&!=g_^a!>RglqH#+kP2o%a@R;``;{_UDMhjhMJ? zaXtN$8f_m+o$CooyvTnsCZi>&dEJj6-8b$}?Fjv{Jb(GB|91H=4;x?Q*=$(Mz`&qd z;u=wsl30>zm0XmXSdz+MWME{XYha;kWD#O$VP$M+Wo)i(U|?lnz_R_}HWUrH`6-!c umAEyOzKR6Jwg%jWlFZ!H;*!MN0!%%oCJ;-mR%D+C#i^&OpUXO@geCyC1I|DI literal 0 HcmV?d00001 diff --git a/assets/items/iron_ingot.png b/assets/items/iron_ingot.png new file mode 100644 index 0000000000000000000000000000000000000000..ea8eedafc1101d59e964825befed5b21c179def0 GIT binary patch literal 516 zcmeAS@N?(olHy`uVBq!ia0y~yU{C;I7G?$phQ^Te;~-A5N02WALzNl>LqiJ#!!HH~ zhK3gm45bDP46hOx7_4S6Fo+k-*%fHRz`!6K;1lA?00u>s?UQG&GBC2*y8GPq+iwGc z6aN4I|H{l?lYxPOu_VYZn8D%MjWiG^$=lt9qwU_*Dh37y_7YEDSN0biGD7lZjCM5} z7#J9~db&7-$n)_ZA16cah$2ZJ8BP z%!?T$mOf*6pk>V$w#kRFVREXLoXF!K2Bq_tmnU#95BX4S=T>eoqxgxrJp%)SYKdz^ zNlIc#s#S7PYGO$$gOP!eiLQZ#u8~EEp@o&Pp_Q?@wt<0_fdR|*hucszBQ;SOya|LqiJ#!!HH~ zhK3gm45bDP46hOx7_4S6Fo+k-*%fHRz`!68;1lA?00u>s?E%3F21ZtsXRf+_`|bb# z|G7_DJ!N2EU@Qsp3ubV5b|VeMN%D4gVHZp6c+J4Tz+U3%>&pIuLq%`*iapC;Mchg@B) z_{xa=?P(|DTTG1Gr*V9nTq_`Od~vPPKEacw3vP=&;%;1EGi%Bg-aontv!eYsca`L_ zZqH0Dyz+783-jfX6E=N6r*^c0V^L!L%2R&XpW44YW<4>_*78rxJX?<3%&>2-Cp>@f zZK*+bVV{~Y_ra3j*@_A7i#6v9o;fD+U6ASL{}Yey`k#5s+!-!+N0-OGo`HcuwZt`| zBqgyV)hf9tHL)a>!N|bKMAyJV*T^Eo(89{t(8}0c+rYrez<_1@!)+)Ua`RI%(<*Um rD18+PiZ~6p4JDbmsl_FUxdoVdOidt`T&>7H4~ia7S3j3^P6#1&54~ycwfi%?1VrhUcCxjv*GOw@$vj>5u}C>*}3M z$DjQFf2}3SpM9m>N$>QClSz{o-u||j^#iN2u2{cyw;idV?AL{>hRrkH0^q#Zih4>!#1=ky2oyXP@}^=a20Nrq6%b{+csDfIG#|&GsS#1A}UbYeY#(Vo9o1a#3nxNh*Vpfsu)> zfrYM-MTnt=m9e3fvAMQ^ft7&)%l3!cP&DM`r(~v8;?_|5DiV|qG~hOrWag$8mn7yE bVCpe7fmm|2BKtf80|SGntDnm{r-UW|yN%h& literal 0 HcmV?d00001 diff --git a/assets/items/platinum_ingot.png b/assets/items/platinum_ingot.png new file mode 100644 index 0000000000000000000000000000000000000000..975c49b57a59cadf91997c2b73e30a7534cf5f1f GIT binary patch literal 492 zcmeAS@N?(olHy`uVBq!ia0y~yU{C;I7G?$phQ^Te;~-A5N02WALzNl>LqiJ#!!HH~ zhK3gm45bDP46hOx7_4S6Fo+k-*%fHRz`!68;1lA?00s+o@6T=TaS4xp`uG2VyAS^V z|9?;}nTLUafw3gWFPOpM*^M+1C&}C0gy?B=QumTTj!i|PYybcfJ5*X{$I$YQs4*l*AxV-GdIn%EnUv8ey;`FER z$z!1xD=cp0JbG|La$?-ik2)S40!A$UjPF_=a5y9_UY;7dF?Mx9eU z3Mc{bOKYP%UwdC`m~yNwrEYN=+LqiJ#!!HH~ zhK3gm45bDP46hOx7_4S6Fo+k-*%fHRz`!6K;1lA?00s+o@6T=TIdJ!ZOL(-Vh3(V7 z|NsC0-w~Lh%D}+DSQ6wH%;50sMjD8dt@kZu^v# zm8Ca7=yyG&uVnRO1`~hnnw0Hw6S{sShU@zDEIPEb^~q(988Iu01p@9*T3xc}u562u z?RI%V!O)dE%&OGPCd}pbv9wy`uyk@5-)Ej_?>D;MoPBe;%Z$S0jfJxXmtD*_Iqf&c z*25QMpJr8hy)0`w=Ix=8cTLbGbzY^QOTZi(rE?43@15{y`l0TL5w9O^|Jtu#!*sw| zW&cX;pRXAh7*tDKBT7;dOH!?pi&7IyQW=a4j7)S5EOd=5LJTdej18@f&9w~-tPBiT zwm;m4q9HdwB{QuOw}#SJk)T-AfZI@#nVVW%l9*e7smIg=V#(Et?DL?w@^tlcS?83{ F1OR?ZxflQd literal 0 HcmV?d00001 diff --git a/assets/items/silver_ingot.png b/assets/items/silver_ingot.png new file mode 100644 index 0000000000000000000000000000000000000000..9bd8d331bed6006e67cfc0dfe1a212c3a15946e8 GIT binary patch literal 530 zcmeAS@N?(olHy`uVBq!ia0y~yU{C;I7G?$phQ^Te;~-A5N02WALzNl>LqiJ#!!HH~ zhK3gm45bDP46hOx7_4S6Fo+k-*%fHRz`!6K;1lA?00!Av>DR7a+P-bed0!83dmMVrZ?5`a)8VSu z^YwK#TmGzjbm{VK)r9^z7pl&1I$zOTC?pts=$8PGs}ZB2a(=^MA;+!Xg^x67Ci^UZ zE9CfiyPG4=jNc8$3%=JbVcKx~)}_{jYpZRyU8*$h;JfyfVb9l9^S8Esj@JZGSlF`%ha8TIQ^yffoZnw^YBE`y$>+@CW zuW&Dt(wpVVBpJZKz@S><8c~vxSdwa$T$GwvlFDFYU}U0eV4-Vd5n^azWo&3=Y_4r! zU}a#yvi;#U6b-rgDVb@NxHXi%iUh@^2Hb{{%-q!ClEmBsOg*M15KFFBWSLqiJ#!!HH~ zhK3gm45bDP46hOx7_4S6Fo+k-*%fHRz`!68;1lA?00!H)ZOP6`pFC;8`**K=ygmQ_ z|Gz`+{AUIR2F8*gzhDN3XE)M7oFs2|7k074j@Jwf4D2PIzOL*qIAnz6%^2-!HZU+S zT=R5s4AD5hH1OcW!wNhuvI{=*uqJ365OijY*vWJvuz|n-m;S>^4avv%&wjD}^rE}0 zOYJ0&2ybKj%Gmtf**cugeDiA3W;ag@uO!`40*vF4@I?+*0z}%DmMRn&#@Y zZo3;0GtJ~f|9RWWwD9!DIfc78YnBQ4@)mdV-4rWoG4lS*%9ZoJ{kzfL+g|7Fc;aGv zTHdDaT6^WkKh=zLxsI#r&&c=dXfEKXfA*7sfkCyzHKHUXu_VnC}Q!>*kacd}j6$y%24Y&;@nYpROC5gEO Zn0ic2AeLOM$UYB>KTlUbmvv4FO#n-}z}^4= literal 0 HcmV?d00001 diff --git a/assets/tiles/dopravnik.png b/assets/tiles/dopravnik.png new file mode 100644 index 0000000000000000000000000000000000000000..53c5deaa662dfeee586ee11df434a7970f52362c GIT binary patch literal 215 zcmeAS@N?(olHy`uVBq!ia0y~yU{C;I4mJh`hT^KKFANL}jKx9jP7LeL$-HD>V3_FX z;usRqntbNWsbA*}8X7VcbmdDKn3UpRLqu}bD(N2r3QHQo z?AljK?@@Hfo`3kj18&BupE7K0{u~!>KQ}OVpm^ZN@5wjo+1P&luDLL!Wieku4-faR z^9Kwj6*KCvBqSV}+9ILIz^uH??1&_jfx(+-7Zzs*wzk~Z0~WW;Wj^vTFkHD+`gC#W SOdAFU1_n=8KbLh*2~7aRsY@0B literal 0 HcmV?d00001 diff --git a/items/item.c b/items/item.c new file mode 100644 index 0000000..262b280 --- /dev/null +++ b/items/item.c @@ -0,0 +1,127 @@ +// +// Created by bruno on 4/24/25. +// + +#include "item.h" +#include "../tiles/tile.h" +#include "../util/util.h" +#include "../player/player.h" +#include + +Item ItemRegistry[ITEMREGISTRY_SIZE]; + +uint16_t itemRegistryIndex = 0; + +void updateItems() { + for (int y = 0; y < MAP_HEIGHT; y++) { + for (int x = 0; x < MAP_WIDTH; x++) { + Tile *t = &tileMap[y][x]; + if (t->type != TYPE_BELT || !t->item.active) continue; + + if ( + (t->item.x < 0 && t->direction == ORIENT_LEFT) || + (t->item.x > 0.75f && t->direction == ORIENT_RIGHT) || + (t->item.y < 0.25f && t->direction == ORIENT_UP) || + (t->item.y > 0.625f && t->direction == ORIENT_DOWN) + ) { + int nx = x, ny = y; + if (t->direction == ORIENT_LEFT) nx--; + if (t->direction == ORIENT_RIGHT) nx++; + if (t->direction == ORIENT_UP) ny--; + if (t->direction == ORIENT_DOWN) ny++; + if (nx >= 0 && nx < MAP_WIDTH && ny >= 0 && ny < MAP_HEIGHT) { + Tile *next = &tileMap[ny][nx]; + if (next->type == TYPE_BELT && !next->item.active) { + memcpy(&next->item, &t->item, sizeof(ItemOnBelt)); + printf("Moved to X=%d, Y=%d", nx, ny); + next->item.tileX = nx; + next->item.tileY = ny; + if (t->direction == ORIENT_LEFT) next->item.x = 0.5f; + if (t->direction == ORIENT_RIGHT) next->item.x = 0.25f; + if (t->direction == ORIENT_UP) next->item.y = 0.5f; + if (t->direction == ORIENT_DOWN) next->item.y = 0; + next->item.active = true; + t->item.active = false; + } else { + continue; + } + } else { + t->item.active = false; + } + } + + float speed = 0.02f; + switch (t->direction) { + case ORIENT_LEFT: + t->item.x -= speed; + break; + case ORIENT_RIGHT: + t->item.x += speed; + break; + case ORIENT_UP: + t->item.y -= speed; + break; + case ORIENT_DOWN: + t->item.y += speed; + break; + default: + break; + } + } + } +} + +void registerItem(char name[20], SDL_Renderer *renderer) { + const char *dot = strchr(name, '.'); + memcpy(ItemRegistry[itemRegistryIndex].name, name, dot - name); + char texturePath[80]; + snprintf(texturePath, 80, "./assets/items/%s", name); + ItemRegistry[itemRegistryIndex].texture = IMG_LoadTexture(renderer, texturePath); + SDL_SetTextureBlendMode(ItemRegistry[itemRegistryIndex].texture, SDL_BLENDMODE_BLEND); + ItemRegistry[itemRegistryIndex].textureOnBelt = ScaleTexture(renderer, ItemRegistry[itemRegistryIndex].texture, + TILE_SIZE / 2, TILE_SIZE / 2); + SDL_SetTextureBlendMode(ItemRegistry[itemRegistryIndex].textureOnBelt, SDL_BLENDMODE_BLEND); + ItemRegistry[itemRegistryIndex].type = itemRegistryIndex; + + itemRegistryIndex++; +} + +void renderItem(ItemOnBelt item, SDL_Renderer *renderer) { + SDL_Rect rect = {0}; + rect.x = (item.tileX * TILE_SIZE) + (item.x * TILE_SIZE); + rect.y = (item.tileY * TILE_SIZE) + (item.y * TILE_SIZE); + rect.w = TILE_SIZE / 2; + rect.h = TILE_SIZE / 2; + adjustRect(&rect); + SDL_RenderCopy(renderer, ItemRegistry[item.type].textureOnBelt, NULL, &rect); +} + +void renderBeltItems(SDL_Renderer *renderer) { + +} + +void putItem(int x, int y, uint16_t itemType) { + tileMap[y][x].item.type = itemType; + tileMap[y][x].item.x = 0.25f; + tileMap[y][x].item.y = 0.25f; + if (tileMap[y][x].direction == ORIENT_LEFT) tileMap[y][x].item.x = 0.5f; + if (tileMap[y][x].direction == ORIENT_RIGHT) tileMap[y][x].item.x = 0.25f; + if (tileMap[y][x].direction == ORIENT_UP) tileMap[y][x].item.y = 0.5f; + if (tileMap[y][x].direction == ORIENT_DOWN) tileMap[y][x].item.y = 0.25f; + tileMap[y][x].item.active = true; + tileMap[y][x].item.tileX = x; + tileMap[y][x].item.tileY = y; +} + +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); + } + } +} \ No newline at end of file diff --git a/items/item.h b/items/item.h new file mode 100644 index 0000000..7f36d01 --- /dev/null +++ b/items/item.h @@ -0,0 +1,35 @@ +// +// Created by bruno on 4/24/25. +// + +#include + +#ifndef FACTORYGAME_ITEM_H +#define FACTORYGAME_ITEM_H + +typedef struct { + uint16_t type; + char name[20]; + SDL_Texture * texture; + SDL_Texture * textureOnBelt; +} Item; + +#define ITEMREGISTRY_SIZE 512 + +extern Item ItemRegistry[ITEMREGISTRY_SIZE]; + +typedef struct { + float x, y; // local position in tile (0.0–1.0) + int tileX, tileY; + bool active; + uint16_t type; +} ItemOnBelt; + +void updateItems(); + +void loadItems(SDL_Renderer *renderer); + +void renderItem(ItemOnBelt item, SDL_Renderer *renderer); + +void putItem(int x, int y, uint16_t itemType); +#endif //FACTORYGAME_ITEM_H diff --git a/main.c b/main.c index 91c7f06..05f59b6 100644 --- a/main.c +++ b/main.c @@ -3,42 +3,10 @@ #include #include "util/font.h" #include "util/audio.h" -#include - -#define MAP_WIDTH 64 -#define MAP_HEIGHT 36 - -#define TILE_SIZE 16 - -#define DISPLAY_WIDTH MAP_WIDTH * TILE_SIZE -#define DISPLAY_HEIGHT MAP_HEIGHT * TILE_SIZE - -typedef enum { - BELT_LEFT_DOWN, - BELT_LEFT, - BELT_LEFT_UP, - BELT_UP, - BELT_RIGHT_UP, - BELT_RIGHT, - BELT_RIGHT_DOWN, - BELT_DOWN -} BeltDirection; - -typedef struct { - float x, y; // local position in tile (0.0–1.0) - bool active; -} Item; - - - -typedef struct { - bool hasBelt; - BeltDirection direction; - int frameOffset; - Item item; -} Tile; - -Tile tileMap[MAP_HEIGHT][MAP_WIDTH]; +#include "tiles/tile.h" +#include "tiles/belt.h" +#include "items/item.h" +#include "player/player.h" //Screen dimension constants const int SCREEN_WIDTH = DISPLAY_WIDTH; @@ -63,9 +31,6 @@ BitmapFont fonts[fontCount]; unsigned long frames = 0; bool cursor = true; - -SDL_Texture *beltTex; - void msleep(unsigned int milliseconds) { struct timespec ts; ts.tv_sec = milliseconds / 1000; @@ -73,28 +38,10 @@ void msleep(unsigned int milliseconds) { nanosleep(&ts, NULL); } -void generateTestMap() { - for (int y = 0; y < MAP_HEIGHT; y++) { - for (int x = 0; x < MAP_WIDTH; x++) { - tileMap[y][x] = (Tile){0}; - } - } - - for (int x = 5; x < 5 + (4*2); x+=2) { - tileMap[10][x].hasBelt = true; - tileMap[10][x].frameOffset = 0; - } - tileMap[10][5].direction = BELT_LEFT; - tileMap[10][7].direction = BELT_RIGHT; - tileMap[10][9].direction = BELT_UP; - tileMap[10][11].direction = BELT_DOWN; - - tileMap[10][5].item = (Item){.x = 0.5f, .y = 0.5f, .active = true}; -} - int init() { //Initialize SDL + SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, NULL); SDL_SetHint(SDL_HINT_VIDEO_HIGHDPI_DISABLED, "1"); SDL_SetHint(SDL_HINT_RENDER_DRIVER, "opengl"); @@ -123,6 +70,8 @@ int init() { return 1; } + loadItems(renderer); + loadTiles(renderer); // Create OpenGL context SDL_GLContext glContext = SDL_GL_CreateContext(window); if (!glContext) { @@ -162,112 +111,12 @@ int init() { smallerFont = prepText(renderer, 8, "PublicPixel.ttf", 255, 255, 255, 255); SDL_RenderSetLogicalSize(renderer, SCREEN_WIDTH, SCREEN_HEIGHT); - beltTex = IMG_LoadTexture(renderer, "../assets/dopravnik.png"); - generateTestMap(); return 0; } -void updateItems() { - for (int y = 0; y < MAP_HEIGHT; y++) { - for (int x = 0; x < MAP_WIDTH; x++) { - Tile *t = &tileMap[y][x]; - if (!t->hasBelt || !t->item.active) continue; - - float speed = 0.05f; - switch (t->direction) { - case BELT_LEFT: t->item.x -= speed; break; - case BELT_RIGHT: t->item.x += speed; break; - case BELT_UP: t->item.y -= speed; break; - case BELT_DOWN: t->item.y += speed; break; - default: break; - } - - if (t->item.x < 0 || t->item.x > 1 || t->item.y < 0 || t->item.y > 1) { - int nx = x, ny = y; - if (t->direction == BELT_LEFT) nx--; - if (t->direction == BELT_RIGHT) nx++; - if (t->direction == BELT_UP) ny--; - if (t->direction == BELT_DOWN) ny++; - if (nx >= 0 && nx < MAP_WIDTH && ny >= 0 && ny < MAP_HEIGHT) { - Tile *next = &tileMap[ny][nx]; - if (next->hasBelt && next->direction == t->direction && !next->item.active) { - next->item = (Item){ .x = 0.5f, .y = 0.5f, .active = true }; - t->item.active = false; - } - } else { - t->item.active = false; - } - } - } - } -} -void renderBelt(SDL_Texture *tex, int x, int y, int w, int h, BeltDirection dir) { - int texW, texH; - SDL_QueryTexture(tex, NULL, NULL, &texW, &texH); - - static int scrollFrame = 0; - int scrollSpeed = 1; // pixels per step - int scrollDelay = 15; // frames between steps - - if (frames % scrollDelay == 0) { - scrollFrame += scrollSpeed; - } - - SDL_Rect src1, src2, dst1, dst2; - - if (dir == BELT_LEFT || dir == BELT_RIGHT) { - int offset = scrollFrame % texW; - - if (dir == BELT_LEFT) { - offset = texW - offset; // reverse scroll - } - - src1 = (SDL_Rect){offset, 0, texW - offset, texH}; - dst1 = (SDL_Rect){x, y, w - offset, h}; - - src2 = (SDL_Rect){0, 0, offset, texH}; - dst2 = (SDL_Rect){x + (w - offset), y, offset, h}; - - SDL_RenderCopy(renderer, tex, &src1, &dst1); - SDL_RenderCopy(renderer, tex, &src2, &dst2); - } else { - int offset = scrollFrame % texH; - - if (dir == BELT_UP) { - offset = texH - offset; // reverse scroll - } - - src1 = (SDL_Rect){0, offset, texW, texH - offset}; - dst1 = (SDL_Rect){x, y, w, h - offset}; - - src2 = (SDL_Rect){0, 0, texW, offset}; - dst2 = (SDL_Rect){x, y + (h - offset), w, offset}; - - SDL_RenderCopy(renderer, tex, &src1, &dst1); - SDL_RenderCopy(renderer, tex, &src2, &dst2); - } -} - - - - -void renderAllBelts() { - int tileSize = TILE_SIZE; - for (int y = 0; y < MAP_HEIGHT; y++) { - for (int x = 0; x < MAP_WIDTH; x++) { - Tile t = tileMap[y][x]; - if (!t.hasBelt) continue; - int px = x * tileSize; - int py = y * tileSize; - renderBelt(beltTex, px, py, tileSize, tileSize, t.direction); - } - } -} - - int render() { SDL_SetRenderDrawColor(renderer, 32, 32, 32, 255); SDL_RenderClear(renderer); @@ -278,7 +127,7 @@ int render() { rect2.w = 0; rect2.h = 0; - renderAllBelts(); + renderAllBelts(renderer); SDL_RenderPresent(renderer); @@ -331,6 +180,14 @@ int main(__attribute__((unused)) int argc, __attribute__((unused)) char *args[]) return status; } + uint8_t type = 0; + for (int x = 149; x < 152; x++) { + for(int y = 87; y < 90; y++) { + putItem(x, y, type++); + } + } + + //Hack to get window to stay up SDL_Event e; Uint64 start; @@ -358,7 +215,6 @@ int main(__attribute__((unused)) int argc, __attribute__((unused)) char *args[]) for (uint8_t i = 0; i < fontCount; i++) { destroyFont(&fonts[i]); } - puts(SDL_GetError()); if (renderer) SDL_DestroyRenderer(renderer); if (window) SDL_DestroyWindow(window); diff --git a/player/player.c b/player/player.c new file mode 100644 index 0000000..c4e22c8 --- /dev/null +++ b/player/player.c @@ -0,0 +1,48 @@ +// +// Created by bruno on 4/24/25. +// + +#include +#include "player.h" +#include "../tiles/tile.h" + +int playerX = (MAP_WIDTH / 2) * 16; +int playerY = (MAP_HEIGHT / 2) * 16; + +void adjustRect(SDL_Rect * rect) { + rect->x -= playerX; + rect->y -= playerY; + 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 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); +} \ No newline at end of file diff --git a/player/player.h b/player/player.h new file mode 100644 index 0000000..fdee410 --- /dev/null +++ b/player/player.h @@ -0,0 +1,16 @@ +// +// Created by bruno on 4/24/25. +// + +#ifndef FACTORYGAME_PLAYER_H +#define FACTORYGAME_PLAYER_H + +extern int playerX; +extern int playerY; + +bool isInbounds(int x, int y); +bool isInboundsRect(SDL_Rect rect); +bool isInboundsTile(int x, int y); +void adjustRect(SDL_Rect * rect); + +#endif //FACTORYGAME_PLAYER_H diff --git a/tiles/belt.c b/tiles/belt.c new file mode 100644 index 0000000..7ce317f --- /dev/null +++ b/tiles/belt.c @@ -0,0 +1,85 @@ +// +// Created by bruno on 4/24/25. +// + +#include "belt.h" + +#include "../util/util.h" +#include "tile.h" +#include "../player/player.h" + +static int scrollFrame = 0; +unsigned long beltFrames = 0; + + +void renderBelt(int x, int y, int w, int h, OrientDirection dir, SDL_Renderer * renderer) { + + int px = x * TILE_SIZE; + int py = y * TILE_SIZE; + + uint16_t tileType = tileMap[y][x].type; + + SDL_Rect src1, src2, dst1, dst2; + + if (dir == ORIENT_LEFT || dir == ORIENT_RIGHT) { + int offset = scrollFrame % TILE_SIZE; + + if (dir == ORIENT_RIGHT) { + offset = TILE_SIZE - offset; // reverse scroll + } + + src1 = (SDL_Rect) {offset, 0, TILE_SIZE - offset, TILE_SIZE}; + dst1 = (SDL_Rect) {px, py, (w - offset), h}; + + src2 = (SDL_Rect) {0, 0, offset, TILE_SIZE}; + dst2 = (SDL_Rect) {px + (w - offset), py, offset, h}; + + adjustRect(&dst1); + adjustRect(&dst2); + + SDL_RenderCopy(renderer, TileRegistry[tileType].textures[dir], &src1, &dst1); + SDL_RenderCopy(renderer, TileRegistry[tileType].textures[dir], &src2, &dst2); + } else { + int offset = scrollFrame % TILE_SIZE; + + if (dir == ORIENT_DOWN) { + offset = TILE_SIZE - offset; // reverse scroll + } + + src1 = (SDL_Rect) {0, offset, TILE_SIZE, TILE_SIZE - offset}; + dst1 = (SDL_Rect) {px, py, w, h - offset}; + + src2 = (SDL_Rect) {0, 0, TILE_SIZE, offset}; + dst2 = (SDL_Rect) {px, py + (h - offset), w, offset}; + + adjustRect(&dst1); + adjustRect(&dst2); + + + // 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); y < (playerY / TILE_SIZE) + (DISPLAY_MAP_HEIGHT / 2); y++) { + for (int x = (playerX / TILE_SIZE) - (DISPLAY_MAP_WIDTH / 2); x < (playerX / TILE_SIZE) + (DISPLAY_MAP_WIDTH / 2); x++) { + Tile t = tileMap[y][x]; + if (t.type != TYPE_BELT) continue; + renderBelt(x, y, tileSize, tileSize, t.direction, renderer); + if (t.item.active) { + renderItem(t.item, renderer); + } + } + } +} \ No newline at end of file diff --git a/tiles/belt.h b/tiles/belt.h new file mode 100644 index 0000000..b0db68c --- /dev/null +++ b/tiles/belt.h @@ -0,0 +1,16 @@ +// +// Created by bruno on 4/24/25. +// + +#ifndef FACTORYGAME_BELT_H +#define FACTORYGAME_BELT_H +#include +#include +#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); + +#endif //FACTORYGAME_BELT_H diff --git a/tiles/tile.c b/tiles/tile.c new file mode 100644 index 0000000..d339e3e --- /dev/null +++ b/tiles/tile.c @@ -0,0 +1,67 @@ +// +// Created by bruno on 4/24/25. +// + +#include +#include "tile.h" +#include "../player/player.h" +#include "../util/util.h" + +Tile tileMap[MAP_HEIGHT][MAP_WIDTH]; + +uint16_t tileTypeIndex = 0; + +TileType TileRegistry[TILEREGISTRY_SIZE]; + +void generateTestMap() { + for (int y = 0; y < DISPLAY_MAP_HEIGHT; y++) { + for (int x = 0; x < DISPLAY_MAP_WIDTH; x++) { + Tile tile = {0}; + tile.x = x; + tile.y = y; + tileMap[y][x] = tile; + } + } + + for (int x = (playerX / TILE_SIZE) - (DISPLAY_MAP_WIDTH / 2); + x < (playerX / TILE_SIZE) + (DISPLAY_MAP_WIDTH / 2); x += 1) { + for (int y = (playerY / TILE_SIZE) - (DISPLAY_MAP_HEIGHT / 2); + y < (playerY / TILE_SIZE) + (DISPLAY_MAP_HEIGHT / 2); y += 1) { + + tileMap[y][x].type = TYPE_BELT; + tileMap[y][x].frameOffset = 0; + //tileMap[y][x].direction = ((x + y) % 4 * 2) + 1; + tileMap[y][x].direction = 5; + } + } +} + + +void registerTile(char name[20], SDL_Renderer *renderer) { + const char *dot = strchr(name, '.'); + memcpy(TileRegistry[tileTypeIndex].name, name, dot - name); + char texturePath[80]; + snprintf(texturePath, 80, "./assets/tiles/%s", name); + SDL_Texture * texture = IMG_LoadTexture(renderer, texturePath); + TileRegistry[tileTypeIndex].textures[ORIENT_LEFT] = texture; + TileRegistry[tileTypeIndex].textures[ORIENT_RIGHT] = createFlippedTexture(renderer, texture, SDL_FLIP_HORIZONTAL); + TileRegistry[tileTypeIndex].textures[ORIENT_UP] = createRotatedTexture(renderer, texture, 90); + TileRegistry[tileTypeIndex].textures[ORIENT_DOWN] = createRotatedTexture(renderer, texture, 270); + TileRegistry[tileTypeIndex].type = tileTypeIndex; + + 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); + } + } +} \ No newline at end of file diff --git a/tiles/tile.h b/tiles/tile.h new file mode 100644 index 0000000..dc50e5f --- /dev/null +++ b/tiles/tile.h @@ -0,0 +1,49 @@ +// +// Created by bruno on 4/24/25. +// + +#ifndef FACTORYGAME_TILE_H +#define FACTORYGAME_TILE_H + +#include "belt.h" +#include "../items/item.h" +#include "../util/util.h" + +#define MAP_WIDTH 600 +#define MAP_HEIGHT 340 + +#define DISPLAY_MAP_WIDTH 30 +#define DISPLAY_MAP_HEIGHT 16 + +#define TILE_SIZE 32 + +#define DISPLAY_WIDTH DISPLAY_MAP_WIDTH * TILE_SIZE +#define DISPLAY_HEIGHT DISPLAY_MAP_HEIGHT * TILE_SIZE + +typedef struct { + uint16_t type; + char name[20]; + SDL_Texture *textures[ORIENT_DIRECTION_COUNT]; +} TileType; + +#define TILEREGISTRY_SIZE 512 + +extern TileType TileRegistry[TILEREGISTRY_SIZE]; + +#define TYPE_BELT 0 + +typedef struct { + OrientDirection direction; + uint16_t type; + int frameOffset; + ItemOnBelt item; + int x; + int y; +} Tile; + +extern Tile tileMap[MAP_HEIGHT][MAP_WIDTH]; + +void generateTestMap(); +void loadTiles(SDL_Renderer *renderer); + +#endif //FACTORYGAME_TILE_H diff --git a/util/util.c b/util/util.c new file mode 100644 index 0000000..51234ed --- /dev/null +++ b/util/util.c @@ -0,0 +1,55 @@ +// +// Created by bruno on 4/24/25. +// + +#include "util.h" +SDL_Texture* createFlippedTexture(SDL_Renderer* renderer, SDL_Texture* src, SDL_RendererFlip flip) { + int w, h; + SDL_QueryTexture(src, NULL, NULL, &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, NULL); + + return target; +} + +SDL_Texture* createRotatedTexture(SDL_Renderer* renderer, SDL_Texture* src, double angle) { + int w, h; + SDL_QueryTexture(src, NULL, NULL, &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, NULL); + + return target; +} + +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, + newHeight); + + if (!scaledTex) { + SDL_Log("Failed to create target texture: %s", SDL_GetError()); + return nullptr; + } + + // Save current render target + 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_RenderCopy(renderer, src, NULL, &dst); + + SDL_SetRenderTarget(renderer, oldTarget); // Restore + + return scaledTex; +} diff --git a/util/util.h b/util/util.h new file mode 100644 index 0000000..7677579 --- /dev/null +++ b/util/util.h @@ -0,0 +1,28 @@ +// +// Created by bruno on 4/24/25. +// + +#ifndef FACTORYGAME_UTIL_H +#define FACTORYGAME_UTIL_H + +#include + +typedef enum { + ORIENT_LEFT_DOWN, + ORIENT_LEFT, + ORIENT_LEFT_UP, + ORIENT_UP, + ORIENT_RIGHT_UP, + ORIENT_RIGHT, + ORIENT_RIGHT_DOWN, + ORIENT_DOWN, + ORIENT_DIRECTION_COUNT +} OrientDirection; + +SDL_Texture *createRotatedTexture(SDL_Renderer *renderer, SDL_Texture *src, double angle); + +SDL_Texture *createFlippedTexture(SDL_Renderer *renderer, SDL_Texture *src, SDL_RendererFlip flip); + +SDL_Texture* ScaleTexture(SDL_Renderer* renderer, SDL_Texture* src, int newWidth, int newHeight); + +#endif //FACTORYGAME_UTIL_H