From a988017110ad2e99c47011a4f84da6a2027013ee Mon Sep 17 00:00:00 2001 From: Carlo Date: Mon, 10 Nov 2025 11:02:50 +0100 Subject: [PATCH] MAJOR COMMIT. big refactor(did it with AI help). no changes in game logic, just moved things around. --- Makefile | 26 ++++ README.md | 2 +- build/game.o | Bin 0 -> 6096 bytes build/gui.o | Bin 0 -> 7400 bytes build/input.o | Bin 0 -> 1792 bytes build/logic.o | Bin 0 -> 3112 bytes build/main.o | Bin 0 -> 2104 bytes build/objects.o | Bin 0 -> 2008 bytes build/space_shooter | Bin 0 -> 22968 bytes build/utils.o | Bin 0 -> 936 bytes include/game.h | 9 ++ include/gui.h | 29 +++-- include/input.h | 18 +++ include/logic.h | 16 +++ include/objects.h | 31 +++++ include/utils.h | 18 +++ src/game.c | 127 +++++++++++++++++++ src/gui.c | 39 +++--- src/input.c | 41 ++++++ src/logic.c | 73 +++++++++++ src/main.c | 295 +------------------------------------------- src/objects.c | 33 +++++ src/utils.c | 2 + 23 files changed, 438 insertions(+), 321 deletions(-) create mode 100644 Makefile create mode 100644 build/game.o create mode 100644 build/gui.o create mode 100644 build/input.o create mode 100644 build/logic.o create mode 100644 build/main.o create mode 100644 build/objects.o create mode 100755 build/space_shooter create mode 100644 build/utils.o create mode 100644 include/game.h create mode 100644 include/input.h create mode 100644 include/logic.h create mode 100644 include/objects.h create mode 100644 include/utils.h create mode 100644 src/game.c create mode 100644 src/input.c create mode 100644 src/logic.c create mode 100644 src/objects.c create mode 100644 src/utils.c diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..5bef432 --- /dev/null +++ b/Makefile @@ -0,0 +1,26 @@ +CC = gcc +CFLAGS = -Wall -Wextra -Iinclude -std=c11 +LDFLAGS = -lncurses + +SRC = $(wildcard src/*.c) +OBJ = $(patsubst src/%.c, build/%.o, $(SRC)) +TARGET = build/space_shooter + +all: $(TARGET) + +build: + mkdir -p build + +build/%.o: src/%.c | build + $(CC) $(CFLAGS) -c $< -o $@ + +$(TARGET): $(OBJ) | build + $(CC) $(OBJ) -o $@ $(LDFLAGS) + +clean: + rm -rf build + +run: all + ./$(TARGET) + +.PHONY: all clean run diff --git a/README.md b/README.md index 249f3d1..b99741e 100644 --- a/README.md +++ b/README.md @@ -4,4 +4,4 @@ > cd space-shooter/ -> gcc -o /build/shooter src/main.c src/gui.c -lncurses \ No newline at end of file +> make \ No newline at end of file diff --git a/build/game.o b/build/game.o new file mode 100644 index 0000000000000000000000000000000000000000..8ee3cbfa44f33765cf3b7a156bbfb4e35af36bd8 GIT binary patch literal 6096 zcmbtYeQX@X6`!+Bl9G>eA*FoeX zUM@jVVz_L@b+xE!dlc~>AS4i#iYhq`m69B3)J-J>j#Q;c@JCd&Qe35K_>@Z{%zLvl zcQ4D0De$7bnfblnypNgLH|rc79lN(Dm10s->~7W>NtCfYt2_N+-W_JE*h=<6dfg`z zTH~ME}1o8hmTDfH&M;CkQ2`)h{pG$ME0CYv7!X z#4C&4KjP0R{At^%pUnvS5(=8QWI>4GXdyo;o!Lt^Iv5_XO4w%FhO(c|9d^!BG=RpRSKK3-8 zlz2zw(dp|Poq(4anSA3+z+c0`+0NS*iR0XUGykjwO{`7A=>3gZE&LYWrN;TjCt!-c zD*PmU-tXK<4`b=${9vX}oeP?)Vef*On{kulSVtP?v@qU$YBBQv3a-)H99j+dP|MG1 z5Jjq`rDnC)FZODwOWM}6sAhgEeeCCp6K6r4KF%-8I}O9stcVvfl3xT#L z(EA>kVDMVC5QA#NMShN?9(#zT4)&*RTd{Q6FW`W!0WCf#GfUxTbXEV)dUmf|()-(` zK;d||AG`|t*n9j9OzL~Pei30T{D!}Vjvj6xd>#W}--HMANy<$Cbi*-+ZukZT{(S|$ zMS*Wu;CCzVQ3XDxz$X;=BMRJ5;1vb#De%Jz{7D7gRN&7m@K+T$ei3%tuk#B0?+W~i z0>^{d&HgGlxZUtI3Vc9;Z&BcPC~*AP@8vu~qp@)|cK-vT^m10gtp_C;aOP9uWR=g8x#%f0po95dL!t{>y}qUwbm1 zR|y~E$NGs95&kL|Oa7aLPvgHp`1p6Jw|ZZ#5WTB27*6K@EZxf zpWxK*lLW`RS=#>%!STaU;x7;!??8$Ff#7tV|4Z<16aJw1Ai%tCCipIa<21T%KPLQJ z2>&q!{|UmsmGECA_-zC~uCVhK;p5#d^Zii4ze@OP34Z_+1;GaYyFuF7L2!EBiUg2jfU%5cx%f0f^>+yV1A$9BCD5VVL-^FrhYJ1@ zEIJ@)pYpd8oaXh8z>|LeP59K#tyqjelJO4-9PQ9^^&sJY7j$wR9wj(^Uo3)eB>bld zK0xr_5&U}u&p;mq)1uFJBH6%X=O z1@2JLnU-f{;oEyFzbeFduUXB)%?E!kc!yvPS~7~cDF<$`v(5{2>X5wkU`g9~BwDY<~z!*{8f;Cmji8lKT+g z7-};9XT0KYl03`4aEu8|PgS r#Fxaz;@yOPlJn7Ka_<3R&)@_QJF#GiA-|iu&3{|OkAL@2NzVTaP?~`W literal 0 HcmV?d00001 diff --git a/build/gui.o b/build/gui.o new file mode 100644 index 0000000000000000000000000000000000000000..1c5a1ef36ef92e5ddc8da511c8d9f2bbd9089b9b GIT binary patch literal 7400 zcmdT}U2Ggz6~1dHX(F1xlF~{AG;JD45t(e-2$=|qU2B?&m&Uf!U zyJsgmF@HkkC^Pq-?|$d!o_lBJuJeR9@L*RaqgXQPe$~<#Rci6}R=-zwd({TDUcJBm zvsXv_`0Yhtzr^hf%+KN`u$92N+A+=RZpT15yP_QfItWC27b|4$1*ZnP=uRv3G^u z0GJXwYqnW_A)VVNTUEm>spTXrlxh@ zn1(>S8RmX>4oPWwz#BZ^4UP;CxlS$&CW_ASTE0{*=Bq^~%2%U`GZ}==c(GE*hk@(5 zY}Rc3zCBLP+qb`EuPtiTLb0T7xfRbubDV62gnab$(7zttA_OTF%7%Q?ow;Z&hq=0CE4D!ko{VR*WTy7XJ`e`+ zg&<>t-8h~xA&xN@^UIP4)W!@*Uk2CXHYRhkh)Fgr-EavZ)Z!*Dnj!%v9+$V(()7hr z!j#AKbi|m!&Hkidw%n*VQa-fZv~nqUjHhJAOvzh*9Bof-OuD)Z=(A9t$0~q%OyiF6 zGX!&6LX5XAgToh>ijX1bFtIk2lJSE8=Atn@cj8eC0WNE0be@MEMqDy%#W!2h=&d`p zCfgC2Bxz@`?T6s2We4Bwc04C;!3GOvjG27YmZ}=qbHLlbYt5E1wZDI8pQn4nLpi6V zJuosb;0+s&iS#kO@9yv4nduFgJ8r&d^&FkVKTS9;NQ9fWZo{{``q!@NIz|ko z9D=?AoMaRycOKt;x_f3t_fUpd4#AJm1^MRnoa4;-mZ98`^Md8Pg_dJ=y`gilLmeB0 zU7`N=QK!M~j=yYB8&s=ZaDv{bRyDz_?csC2u~|)}82`TI_gbD~+uNuGzt`$_+V)o( zU)8LaWAQB-?^aJ*o%#6k-XikXYed*Cy0G3!d60lkc#d%RVSBxngguU&y7rNg&j2I=eluN+?*K@W#61IF zhkrc(BUW07>Zmr^gt7Tcg+G?^+ywHqyoX z^>&}Z54OtZK_I!);!tm)i}`&5|D?bl61dEBO!!|Z_$9%Y`8<`vKP_;X=kvmk%<~rl zmwCP-@J%A0zY6?Q0>3J7xn65fFcQ>9uGd`xmv#7>#nIrc%k|8q;0J{tS)Y@FFY9nx z@MRrd6u7LzZv-y${G;%XZv^N0y5P%v-b>+sAaI%IIw&N`eRa3MWu94q%k}!I!0`>@ zJSzg1>-dIF6T>WYr$*9ZUL=hFF_ce zG-~sk&v?V)x7(KS96BV9zPJ3$TYPH*x2oz*;8_%$#5YYdpJ|Kd68OBu4<_){c5;s- z@SMeuCh(^%&hzGZ@$)vF;9s$P$KpuCrlOJF1Rhy^EP?Ym>*)l}=cX4EIG>x8TRkxm z^2$A2ttvOH7)6hw>r&4x(O;fQ$}LnT=&VErjA!5yXRQ9t&`BdNIHDlZP6Tk zE;%7Pf>=^^kOEBZA&kFZ?GM@K9TNkgv z7zsb$s2@_|_*}n1!jONKE-62-@lhWsJb!KE$(E0&?Xo+ElnqB{|})-%*Ox# literal 0 HcmV?d00001 diff --git a/build/input.o b/build/input.o new file mode 100644 index 0000000000000000000000000000000000000000..146eea8118476b3a4e26940451bf51831bfc644c GIT binary patch literal 1792 zcmcIjO=uHQ5T4znKi29-DJoPXdhv($(LY5hNU%-&4y{xn;HA_wuB~W(%igwDeN(5~NsXcK0Rgl3FP^@b=C3&3tcW-tI0%$3|2| z0ci?cg*uWf?!mervE2x?!$J6=o%$K$;+t65=EB?dseo2^hwbGS zw!>QCjqO!cZRHhum|?e|6;>P+DnhQhqvb!>AWxLJD08L6l`{WO32^ZdRcl9Wk+I)|W^-_70mP*l@<8(VP~am$dg~LL#(z0b>uXwpGl7jj#AX zJY#iW)EQXju8UBO%fGhsX!IB8)y^#l2RWmgix~LZ6#sebRhoVB6O0ZG4TjIfrmd7| zg?sy1KkMnfWZAH9v2TF&44ijq`!fuostMQV^%$rCCHgc2xX3!34U|VWL759Fo$W2H z&#=r%MAL(PFJDyGf!BLB)*r*SSCwA zCYw&^hB0MhfH1|-s3lr8W5#^aj86kI%&fD|O3&2iOkj87W*peGVE{{{lSw^=Tq^(3#kKieOu1e= zjet1${$wow$7M*?$*m)Rvk2(z?N{H0TB_fJ%WJYe#l0r`m-|HwO5dCJ_8-b2y%f2otmQGLI@>=Kvv(BHy1{XY?3-edPdPq;jN*VL!1FZo8bNz&@-ZxcXk k!$p)|Pv`pI9a1pslE(>n%zxKMFxE)_(j{j+T5|pR-~JIZ$p8QV literal 0 HcmV?d00001 diff --git a/build/logic.o b/build/logic.o new file mode 100644 index 0000000000000000000000000000000000000000..840ee2a402b1317a483f4cfb1520f9132e9c5bf3 GIT binary patch literal 3112 zcmbtWPly{;7=M$*HfvLpl?8>0%|X-_J8Zi}++t;989S6#f)Y?^*(T|Ot%nWX& zyDMZPK8BP%34(%u@FEC8FaGIavmThwkypro6DT2__~5Ltqe2dn1o#@2n;t*TvULKm9w6>twVq54M}hltvDMJ<10xecjhe~yy1o1^raN<0EO9aw~J zIO^SMCq^5M?ZeV9x4X1KTc7;>4{g;oX=oKNT76;+@(EReBH-g0p)-N^*hvm5^8_2n zUv~{8&EE0m(R){?!)9wxkJZo_WO|v2>IS^6iO`EW+6cLlnr zVI^_YJ9W(s_ou+Lu1tmM3?{Mdkb1_2L2T31pxQqKCl991|NK$Ei7g^H!c79rarsE@ zycHVR`>u_n1B{GM03z=kMn4Xzc3ta$cbryxOJnSq?e(t~S^g3Y9P(onVjsbeWs7DK z@S!4SW@b*MpU>uP!?M%Ir{pPl^4N?2>W_*}GWLsv2Kr@Ko4Ky;74Xk&ms z?!#|!!zVc|c$OnzM>+l~en@~=Zm_=u3+o)D(*U6V^St0JSHRA3{3mP%5X%t{#q!np zf?Oc>!sVQ$&*tr7QMXJomoqLG_1QwXSe!TK%Z5qJh1`3_tZwL~dEF!xkP91u70NIt zeGllIkZ<|DG3-8AJ)CNwG@Ox8%vBh#u-^eL>TxN6i+X$zz(wAl2XK)$k4e zs(AaHI92pwPPX(#i^x!m9Fg;;N#sJgRMHK=jIyQ6Fw@6OD_3}z^H&X9UZ|88^on(j z$jpO2H+!X$E9v|O|8Gl!InEf?&QA(wbbM$&LR~){0tRcZ_(3>#_Im)%9nzz)&{q7r zCGclCF5WM&jJ^)U6?icI3m`zB|JD9D*rLx#Sbh@m(Z8QWe6gPbp*Z{XZvV^sp9Lc< zm48Oj&nCA|BjY1cKLO?8fboO&U2gxqP~>~i{vzOe^-nZvk=tSa&{o)s{_PbTO}^s; swTTSS0a)0hpgn%Cg1rNXe8lJH9b|kIto1m^_Of5(fr>s`JO=F_08#MmSpWb4 literal 0 HcmV?d00001 diff --git a/build/main.o b/build/main.o new file mode 100644 index 0000000000000000000000000000000000000000..7d1b69d8edbe4c1a25ece35843db8e85e7038049 GIT binary patch literal 2104 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 Mmk~XhY?H751$KNmM*si- literal 0 HcmV?d00001 diff --git a/include/game.h b/include/game.h new file mode 100644 index 0000000..0fe58ae --- /dev/null +++ b/include/game.h @@ -0,0 +1,9 @@ +#ifndef GAME_H +#define GAME_H + +#include "objects.h" + +/* Run the main game. Returns 0 on clean exit. */ +int game_run(void); + +#endif /* GAME_H */ diff --git a/include/gui.h b/include/gui.h index 26b7259..34426ed 100644 --- a/include/gui.h +++ b/include/gui.h @@ -2,23 +2,26 @@ #define GUI_H #include -#include -#include +#include "objects.h" +#include "utils.h" -// Aspect constatnts -#define TEXTLINES 4 -#define BORDERLINES 2 +/* color pair ids for gui.c */ +enum { + ENEMY_PAIR = 1, + TITLE_PAIR, + GMOVR_PAIR, + BONUS_PAIR, + WINSC_PAIR +}; -#define ENEMY_PAIR 1 -#define BONUS_PAIR 2 -#define TITLE_PAIR 3 -#define GMOVR_PAIR 4 -#define WINSC_PAIR 5 - -void init_colors(); +/* initialization and screens */ +void init_colors(void); void print_menu(WINDOW* win); void print_gameover(WINDOW* win); void print_win_screen(WINDOW* win); +/* status bar (draws into stdscr or another window) */ +void print_status_bar(WINDOW* main_win, int y, int x, struct status game_status); + +#endif /* GUI_H */ -#endif \ No newline at end of file diff --git a/include/input.h b/include/input.h new file mode 100644 index 0000000..3d35614 --- /dev/null +++ b/include/input.h @@ -0,0 +1,18 @@ +#ifndef INPUT_H +#define INPUT_H + +#include +#include "objects.h" +#include "utils.h" + +/* Process a single key code and apply to game state. + Returns 1 if game should continue, 0 if quit (player inactive). */ +int process_input(int input, + int *pause, + int *auto_shoot, + struct game_obj *player, + struct game_obj bullets[], + int bullet_attivi, + int *next_bullet); + +#endif /* INPUT_H */ diff --git a/include/logic.h b/include/logic.h new file mode 100644 index 0000000..6323722 --- /dev/null +++ b/include/logic.h @@ -0,0 +1,16 @@ +#ifndef LOGIC_H +#define LOGIC_H + +#include "objects.h" +#include "utils.h" +#include + +/* Logic functions used by the game loop */ +void update_bullets(struct game_obj bullets[]); +void handle_collisions(struct game_obj bullets[], struct game_obj enemies[], struct status *game_status, WINDOW *win); +void spawn_enemies(struct game_obj enemies[], int width); +void update_enemies(struct game_obj enemies[], struct status *game_status, int height, WINDOW *win); + +void count_bullets(const struct game_obj bullets[], int *bullet_attivi, int *next_bullet, struct status *game_status); + +#endif /* LOGIC_H */ diff --git a/include/objects.h b/include/objects.h new file mode 100644 index 0000000..44bceff --- /dev/null +++ b/include/objects.h @@ -0,0 +1,31 @@ +#ifndef OBJECTS_H +#define OBJECTS_H + +#include "utils.h" + +/* speed, game_obj, status definitions */ +struct speed { + int slowness; + int count; +}; + +struct game_obj { + char symbol; + int x, y; + int active; + struct speed y_speed; +}; + +struct status { + int lives; + int score; + int top_score; + int remaining_bullets; +}; + +/* constructors / initializers */ +void init_player(struct game_obj *player, int win_width, int win_height); +void init_bullets(struct game_obj bullets[]); +void init_enemies(struct game_obj enemies[]); + +#endif /* OBJECTS_H */ diff --git a/include/utils.h b/include/utils.h new file mode 100644 index 0000000..927fdac --- /dev/null +++ b/include/utils.h @@ -0,0 +1,18 @@ +#ifndef UTILS_H +#define UTILS_H + +/* Window/constants shared across modules */ +#define DELAY 30000 +#define ENEMY_N 5 +#define BULLET_N 3 +#define LIVES_N 5 +#define WIN_PTS 100 + +#define WIDTH 52 +#define HEIGHT 30 +#define MIN_COLS 110 + +#define TEXTLINES 4 +#define BORDERLINES 2 + +#endif /* UTILS_H */ diff --git a/src/game.c b/src/game.c new file mode 100644 index 0000000..d351a2e --- /dev/null +++ b/src/game.c @@ -0,0 +1,127 @@ +#include "../include/game.h" +#include "../include/gui.h" +#include "../include/input.h" +#include "../include/logic.h" +#include "../include/objects.h" +#include "../include/utils.h" + +#include +#include +#include +#include +#include +#include + +/* main game runner */ +int game_run(void) { + WINDOW *game_window = NULL; + int height, width, win_startx, win_starty; + char *pause_msg = "PAUSA: premi q per uscire dal gioco..."; + int pause = 0; + int auto_shoot = 0; + + struct game_obj player = {}; + int input = 0; + + struct status game_status = {}; + game_status.top_score = 0; + game_status.score = 0; + game_status.lives = LIVES_N; + game_status.remaining_bullets = BULLET_N; + + struct game_obj bullet[BULLET_N] = {}; + int bullet_attivi = 0; + int next_bullet = -1; + + struct game_obj enemy[ENEMY_N] = {}; + + /* seed */ + srand((unsigned)time(NULL)); + + /* Dimensioni finestra di gioco */ + height = HEIGHT; + width = WIDTH - (WIDTH%4); + win_startx = (COLS - width)/2; + win_starty = (LINES - height)/2; + + if(COLS < MIN_COLS || LINES < HEIGHT) { + printf("Gioco terminato.\nSchermo troppo piccolo\n"); + return 0; + } + + /* show menu */ + print_menu(stdscr); + getch(); + werase(stdscr); + mvprintw(1, 1, "p per pausa, q per uscire"); + refresh(); + + /* create windows */ + game_window = newwin(height, width, win_starty, win_startx); + nodelay(game_window, TRUE); + keypad(game_window, TRUE); + box(game_window, 0, 0); + wrefresh(game_window); + + /* setup objects */ + init_player(&player, width, height); + init_bullets(bullet); + init_enemies(enemy); + + while (player.active) { + input = wgetch(game_window); + + if (!process_input(input, &pause, &auto_shoot, &player, bullet, bullet_attivi, &next_bullet)) { + player.active = 0; + break; + } + + if (!pause) update_bullets(bullet); + if (!pause) handle_collisions(bullet, enemy, &game_status, stdscr); + if (!pause && game_status.score >= WIN_PTS) { + player.active = 0; + print_win_screen(stdscr); + break; + } + + if (!pause) spawn_enemies(enemy, width); + if (!pause) update_enemies(enemy, &game_status, height, stdscr); + if (!pause && game_status.lives <= 0) { + player.active = 0; + print_gameover(stdscr); + break; + } + + count_bullets(bullet, &bullet_attivi, &next_bullet, &game_status); + + /* draw */ + werase(game_window); + box(game_window, 0, 0); + + if (pause) { + wattron(game_window, A_REVERSE); + mvwprintw(game_window, height/2, (width - (int)strlen(pause_msg)) / 2, "%s", pause_msg); + wattroff(game_window, A_REVERSE); + } else { + mvwprintw(game_window, player.y, player.x, "%c", player.symbol); + + for(int i = 0; i < BULLET_N; i++) + if (bullet[i].active) mvwprintw(game_window, bullet[i].y, bullet[i].x, "%c", bullet[i].symbol); + + wattron(game_window, COLOR_PAIR(ENEMY_PAIR)); + for(int i = 0; i < ENEMY_N; i++) + if (enemy[i].active) mvwprintw(game_window, enemy[i].y, enemy[i].x, "%c", enemy[i].symbol); + wattroff(game_window, COLOR_PAIR(ENEMY_PAIR)); + + print_status_bar(stdscr, win_starty, (win_startx + width), game_status); + } + + wrefresh(game_window); + usleep(DELAY); + } + + if (game_window) delwin(game_window); + + /* note: no endwin(), no curs_set(1) here */ + return 0; +} diff --git a/src/gui.c b/src/gui.c index 6821549..009b69d 100644 --- a/src/gui.c +++ b/src/gui.c @@ -1,4 +1,5 @@ #include "../include/gui.h" +#include /************** FUNZIONI GUI ***************/ @@ -10,7 +11,7 @@ char* title[] = "# o888 88 888888 88 88 o888 88 88 88 888 88 888 88 88 88 88 #", "# 088880 88 88 88 888880 088888 088880 08 80 088880 088880 00 088888 88 88o #", "###########################################################################################################" -}; +}; char menu_desc[] = "BENVENUTO. Premi qualsiasi tasto per giocare..."; @@ -28,7 +29,7 @@ char gameover_desc[] = "HAI PERSO. Premi q per uscire..."; char* win_screen[] = { "o8 o8 o8888o o8 8o o8 8o o8888o o8 8o", -"88 o8 88 888 88 88 oo 88 88 88 888o88", +"88 o8 88 888 88 88 oo 88 88 88 888o88", "888 88 888 88 88 88/\\88 88 88 888", "888 088880 088880 8888 088880 88 88" }; @@ -45,76 +46,78 @@ void init_colors() { } void print_menu(WINDOW* win) { - // Ottieni parametri della finestra int height; int width; getmaxyx(win, height, width); - // Scritta colorata wattron(win, COLOR_PAIR(TITLE_PAIR)); for(int i = 0; i < (TEXTLINES+BORDERLINES); i++) { mvwprintw(win, i+1, (width-(strlen(title[0])))/2, "%s", title[i]); } wattroff(win, COLOR_PAIR(TITLE_PAIR)); - // Scritta che blinka wattron(win, A_BLINK); mvwprintw(win, (TEXTLINES+BORDERLINES)+1, (width-(strlen(menu_desc)))/2, "%s", menu_desc); wattroff(win, A_BLINK); - // stampa a video - refresh(); + wrefresh(win); return; } void print_gameover(WINDOW* win) { - // Parametri della finestra e pulisci tutto int height; int width; int ch; wclear(win); getmaxyx(win, height, width); - // Stampa della scritta colorata wattron(win, COLOR_PAIR(GMOVR_PAIR)); for(int i = 0; i < TEXTLINES; i++) { mvwprintw(win, i+1, (width-(strlen(gameover[0])))/2, "%s", gameover[i]); } wattroff(win, COLOR_PAIR(GMOVR_PAIR)); - // Stampa della scritta che blinka wattron(win, A_BLINK); mvwprintw(win, TEXTLINES+1, (width-(strlen(gameover_desc)))/2, "%s", gameover_desc); wattroff(win, A_BLINK); - // Stampa a video e attendi input - refresh(); + wrefresh(win); while((ch = wgetch(win)) != 'q'); return; } void print_win_screen(WINDOW* win) { - // Parametri della finestra e pulisci tutto int height; int width; int ch; wclear(win); getmaxyx(win, height, width); - // Stampa della scritta colorata wattron(win, COLOR_PAIR(WINSC_PAIR)); for(int i = 0; i < TEXTLINES; i++) { mvwprintw(win, i+1, (width-(strlen(win_screen[0])))/2, "%s", win_screen[i]); } wattroff(win, COLOR_PAIR(WINSC_PAIR)); - // Stampa della scritta che blinka wattron(win, A_BLINK); mvwprintw(win, TEXTLINES+1, (width-(strlen(win_desc)))/2, "%s", win_desc); wattroff(win, A_BLINK); - // Stampa a video e attendi input - refresh(); + wrefresh(win); while((ch = wgetch(win)) != 'q'); return; -} \ No newline at end of file +} + +void print_status_bar(WINDOW* main_win, int y, int x, struct status game_status) { + int status_x = x + 1; + int status_y = y; + status_x++; + + mvwprintw(main_win, status_y, status_x, "LIVES:\t%d", game_status.lives); + mvwprintw(main_win, status_y+1, status_x, "SCORE:\t%d", game_status.score); + mvwprintw(main_win, status_y+2, status_x, "TOP SCORE:\t%d", game_status.top_score); + mvwprintw(main_win, status_y+3, status_x, "BULLETS:\t%d", game_status.remaining_bullets); + + wrefresh(main_win); + return; +} diff --git a/src/input.c b/src/input.c new file mode 100644 index 0000000..6032560 --- /dev/null +++ b/src/input.c @@ -0,0 +1,41 @@ +#include "../include/input.h" +#include + +/* Returns 1 to continue, 0 if quit requested (player inactive). */ +int process_input(int input, + int *pause, + int *auto_shoot, + struct game_obj *player, + struct game_obj bullets[], + int bullet_attivi, + int *next_bullet) { + + if (input == KEY_RIGHT && !(*pause) && player->x < (WIDTH - 2)) { + player->x += 2; + } else if (input == KEY_LEFT && !(*pause) && player->x > 2) { + player->x -= 2; + } else if (!(*auto_shoot) && input == ' ' && bullet_attivi < BULLET_N && !(*pause)) { + if (*next_bullet != -1) { + bullets[*next_bullet].x = player->x; + bullets[*next_bullet].y = player->y - 1; + bullets[*next_bullet].active = 1; + } + } else if (input == 'p') { + *pause = !(*pause); + } else if (input == 'q') { + /* signal to caller to quit by marking player inactive */ + return 0; + } else if (input == 'g') { + *auto_shoot = !(*auto_shoot); + } + + if (*auto_shoot && bullet_attivi < BULLET_N && !(*pause)) { + if (*next_bullet != -1) { + bullets[*next_bullet].x = player->x; + bullets[*next_bullet].y = player->y - 1; + bullets[*next_bullet].active = 1; + } + } + + return 1; +} diff --git a/src/logic.c b/src/logic.c new file mode 100644 index 0000000..7ed7aa6 --- /dev/null +++ b/src/logic.c @@ -0,0 +1,73 @@ +#include "../include/logic.h" +#include + +void update_bullets(struct game_obj bullets[]) { + for(int i = 0; i< BULLET_N; i++) { + if (bullets[i].active) { + bullets[i].y--; + if (bullets[i].y < 1) { + bullets[i].active = 0; + } + } + } +} + +void handle_collisions(struct game_obj bullets[], struct game_obj enemies[], struct status *game_status, WINDOW *win) { + (void)win; /* kept parameter for parity with original code */ + for(int j = 0; j < BULLET_N; j++) { + if(bullets[j].active) { + for(int i = 0; i < ENEMY_N; i++) { + if(enemies[i].active && bullets[j].x == enemies[i].x && bullets[j].y == enemies[i].y) { + enemies[i].active = 0; + bullets[j].active = 0; + game_status->score++; + } + } + } + } +} + +void spawn_enemies(struct game_obj enemies[], int width) { + for(int i = 0; i < ENEMY_N; i++) { + if(!enemies[i].active) { + enemies[i].y = 2; + enemies[i].x = (rand()%((width-4)/2))*2 + 2; + enemies[i].active = 1; + enemies[i].y_speed.count = 0; + break; + } + } +} + +void update_enemies(struct game_obj enemies[], struct status *game_status, int height, WINDOW *win) { + (void)win; + for(int i = 0; i < ENEMY_N; i++) { + if(enemies[i].active) { + enemies[i].y_speed.count++; + if(enemies[i].y_speed.count > enemies[i].y_speed.slowness) { + enemies[i].y++; + enemies[i].y_speed.count = 0; + } + if(enemies[i].y > height - 2) { + enemies[i].active = 0; + game_status->lives--; + } + } + } +} + +/* Recomputes bullet_attivi and next_bullet, and updates remaining_bullets */ +void count_bullets(const struct game_obj bullets[], int *bullet_attivi, int *next_bullet, struct status *game_status) { + *bullet_attivi = 0; + *next_bullet = -1; + for (int i = 0; i < BULLET_N; i++) { + if (bullets[i].active) { + (*bullet_attivi)++; + } else { + if (*next_bullet == -1 || i < *next_bullet) { + *next_bullet = i; + } + } + } + game_status->remaining_bullets = BULLET_N - (*bullet_attivi); +} diff --git a/src/main.c b/src/main.c index 1f3025a..c87703e 100644 --- a/src/main.c +++ b/src/main.c @@ -1,308 +1,25 @@ #include #include -#include -#include #include -#include -#include -#include + +#include "../include/game.h" #include "../include/gui.h" -/************* STATIC DEFINITIONS ************/ -// Game constants -#define ENEMY_N 5 -#define BULLET_N 3 -#define LIVES_N 5 -#define WIN_PTS 100 - -// Window constants -#define DELAY 30000 -#define WIDTH 52 -#define HEIGHT 30 -#define MIN_COLS 110 - - -/************* GAME STRUCTURES **************/ -struct speed { - int slowness; - int count; -}; - -struct game_obj { - char symbol; - int x, y; - int active; - struct speed y_speed; -}; - -struct status { - int lives; - int score; - int top_score; - int remaining_bullets; -}; - - -void print_status_bar(WINDOW* main_win, int y, int x, struct status game_status) { - int status_x = x + 1; - int status_y = y; - status_x++; - - // lives - mvwprintw(main_win, status_y, status_x, "LIVES:\t%d", game_status.lives); - // score - mvwprintw(main_win, status_y+1, status_x, "SCORE:\t%d", game_status.score); - // top score - mvwprintw(main_win, status_y+2, status_x, "TOP SCORE:\t%d", game_status.top_score); - // bullets - mvwprintw(main_win, status_y+3, status_x, "BULLETS:\t%d", game_status.remaining_bullets); - - // refresh window - wrefresh(main_win); - return; -} - -int main() { - - /************ VARIABILI **************/ - WINDOW *game_window; - int height, width, win_startx, win_starty; - char *pause_msg = "PAUSA: premi q per uscire dal gioco..."; - int pause = 0; - int auto_shoot = 0; - - // Giocatore - struct game_obj player = {}; - int input; - - // Status - struct status game_status = {}; - game_status.top_score = 0; - game_status.score = 0; - game_status.lives = LIVES_N; - game_status.remaining_bullets = BULLET_N; - - // Proiettile - struct game_obj bullet[BULLET_N] = {}; - int bullet_attivi = 0; - int next_bullet = 0; - - // Nemici - struct game_obj enemy[ENEMY_N] = {}; - - /**************** INIZIALIZZAZIONE ***************/ +int main(void) { initscr(); cbreak(); noecho(); keypad(stdscr, TRUE); curs_set(0); - srand(time(NULL)); - // Colori init_colors(); - // Dimensioni finestra di gioco e controlli - // calcolo delle misure della finestra - height = HEIGHT; - width = WIDTH - (WIDTH%4); - win_startx = (COLS - width)/2; - win_starty = (LINES - height)/2; + game_run(); - // Schermo troppo piccolo ? - if(COLS < MIN_COLS || LINES < HEIGHT) { - curs_set(1); - endwin(); - printf("Gioco terminato.\n"); - printf("Schermo troppo piccolo \n"); - return 0; - } - - // MENU - print_menu(stdscr); - getch(); - werase(stdscr); - mvprintw(1, 1, "p per pausa, q per uscire"); - refresh(); - - // GAME WINDOW - game_window = newwin(height, width, win_starty, win_startx); - nodelay(game_window, TRUE); // input non bloccante - keypad(game_window, TRUE); - box(game_window, 0, 0); - wrefresh(game_window); - - // setup giocatore - player.symbol = 'A'; - player.x = width / 2; - player.y = height - 2; - player.active = 1; - - // setup proiettili - for(int i = 0; i < BULLET_N; i++) { - bullet[i].symbol = '*'; - bullet[i].active = 0; - } - - // setup dei nemici - for(int i = 0; i < ENEMY_N; i++) { - enemy[i].symbol = 'Q'; - enemy[i].active = 0; - enemy[i].y_speed.slowness = 7; - enemy[i].y_speed.count = 0; - } - - //********************* GAME LOOP ***********************/ - while (player.active) { - // TODO if pausa all'inizio e continue - input = wgetch(game_window); - - // Gestione input - if (input == KEY_RIGHT && !pause && player.x < width - 2) { - player.x += 2; - } else if (input == KEY_LEFT && !pause && player.x > 2) { - player.x -= 2; - } else if (!auto_shoot && input == ' ' && bullet_attivi < BULLET_N && !pause) { - bullet[next_bullet].x = player.x; - bullet[next_bullet].y = player.y - 1; - bullet[next_bullet].active = 1; - } else if (input == 'p') { - pause = !pause; - } else if (input == 'q') { - player.active = 0; - } else if (input == 'g') { - auto_shoot= !auto_shoot; - } - - if (auto_shoot && bullet_attivi < BULLET_N && !pause) { - bullet[next_bullet].x = player.x; - bullet[next_bullet].y = player.y - 1; - bullet[next_bullet].active = 1; - } - - // Aggiorna proiettile - for(int i = 0; i< BULLET_N; i++) { - if (bullet[i].active && !pause) { - bullet[i].y--; - } - if (bullet[i].y < 1) { - bullet[i].active = 0; - } - } - - // Collisioni 1 - for(int j = 0; j < BULLET_N; j++) { - if(bullet[j].active && !pause) { - for(int i = 0; i < ENEMY_N; i++) { - if(bullet[j].x == enemy[i].x && bullet[j].y == enemy[i].y) { - enemy[i].active = 0; - bullet[j].active = 0; - game_status.score++; - if(game_status.score == WIN_PTS) { - player.active = 0; - print_win_screen(stdscr); - } - } - } - } - } - - // Spawna nemici - for(int i = 0; !pause && i < ENEMY_N; i++) { - if(!enemy[i].active && !pause) { - enemy[i].y = 2; - enemy[i].x = (rand()%((width-4)/2))*2 + 2; - enemy[i].active = 1; - break; - } - } - - // Aggiorna posizione nemici - for(int i = 0; !pause && i < ENEMY_N; i++) { - if(enemy[i].active && !pause) { - enemy[i].y_speed.count++; - if(enemy[i].y_speed.count > enemy[i].y_speed.slowness) { - enemy[i].y++; - enemy[i].y_speed.count = 0; - } - if(enemy[i].y > height - 2) { - enemy[i].active = 0; - game_status.lives--; - if(game_status.lives == 0) { - player.active = 0; - print_gameover(stdscr); - } - } - } - } - - // Collisioni 2 - for(int j = 0; j < BULLET_N; j++) { - if(bullet[j].active && !pause) { - for(int i = 0; i < ENEMY_N; i++) { - if(bullet[j].x == enemy[i].x && bullet[j].y == enemy[i].y) { - enemy[i].active = 0; - bullet[j].active = 0; - game_status.score++; - if(game_status.score == WIN_PTS) { - player.active = 0; - print_win_screen(stdscr); - } - } - } - } - } - - // Conteggio proiettili - bullet_attivi = 0; - next_bullet = -1; - for (int i = 0; i < BULLET_N; i++) { - if (bullet[i].active) { - bullet_attivi++; - } else if (i < next_bullet || next_bullet == -1) { - next_bullet = i; - } - } - game_status.remaining_bullets = BULLET_N - bullet_attivi; - - // Disegna scena - werase(game_window); - box(game_window, 0, 0); - - if (pause) { - wattron(game_window, A_REVERSE); - mvwprintw(game_window, height/2, (width - strlen(pause_msg)) / 2, "%s", pause_msg); - wattroff(game_window, A_REVERSE); - } else { - // Giocatore - mvwprintw(game_window, player.y, player.x, "%c", player.symbol); - - // Proiettile - for(int i = 0; i < BULLET_N; i++) { - if (bullet[i].active) mvwprintw(game_window, bullet[i].y, bullet[i].x, "%c", bullet[i].symbol); - } - - // Nemici - for(int i = 0; i < ENEMY_N; i++) { - wattron(game_window, COLOR_PAIR(1)); - if (enemy[i].active) mvwprintw(game_window, enemy[i].y, enemy[i].x, "%c", enemy[i].symbol); - wattroff(game_window, COLOR_PAIR(1)); - } - - - // Status Bar - print_status_bar(stdscr, win_starty, (win_startx + width), game_status); - - } - - wrefresh(game_window); - usleep(DELAY); - } - - /***************** CHIUSURA *****************/ - delwin(game_window); + /* cleanup terminal */ curs_set(1); endwin(); + printf("Gioco terminato.\n"); return 0; } - diff --git a/src/objects.c b/src/objects.c new file mode 100644 index 0000000..e06504d --- /dev/null +++ b/src/objects.c @@ -0,0 +1,33 @@ +#include "objects.h" +#include + +void init_player(struct game_obj *player, int win_width, int win_height) { + player->symbol = 'A'; + player->x = win_width / 2; + player->y = win_height - 2; + player->active = 1; + player->y_speed.slowness = 0; + player->y_speed.count = 0; +} + +void init_bullets(struct game_obj bullets[]) { + for (int i = 0; i < BULLET_N; i++) { + bullets[i].symbol = '*'; + bullets[i].active = 0; + bullets[i].x = 0; + bullets[i].y = 0; + bullets[i].y_speed.slowness = 0; + bullets[i].y_speed.count = 0; + } +} + +void init_enemies(struct game_obj enemies[]) { + for (int i = 0; i < ENEMY_N; i++) { + enemies[i].symbol = 'Q'; + enemies[i].active = 0; + enemies[i].y_speed.slowness = 7; + enemies[i].y_speed.count = 0; + enemies[i].x = 0; + enemies[i].y = 0; + } +} diff --git a/src/utils.c b/src/utils.c new file mode 100644 index 0000000..abbb907 --- /dev/null +++ b/src/utils.c @@ -0,0 +1,2 @@ +#include "utils.h" +/* currently no utility functions needed; file exists for future helpers */