1 /* This file is part of Alienwave, a game by Alessandro Pira */
2
3 #include <stdlib.h>
4 #include <curses.h>
5 #include <unistd.h>
6 #include <time.h>
7 #include <sys/time.h>
8 #include "defs.h"
9 #include "blit.h"
10 #include "aliens.h"
11 #include "xzarna.h"
12 #include "levels.h"
13 #include "fire.h"
14 #include "shield.h"
15
16 int score = 0;
17 int end_x;
18 int game_ended = 0;
19 int x_ofs = 0;
20 int y_ofs = 0;
21 int term_x = 0;
22 int term_y = 0;
23
24 const bitmask bitmask_ship={0x38,0x7C,0xFE,0x7C,0x00};
25
26 WINDOW *term; /* our terminal */
27
28 int exploding=0; /* this will be >0 if the player's ship is exploding */
29
init_screen()30 void init_screen()
31 {
32 term = initscr(); /* Initialize terminal */
33
34 start_color(); /* Initialize colors */
35 init_pair(PC_WHITE,COLOR_WHITE,COLOR_BLACK);
36 init_pair(PC_RED,COLOR_RED,COLOR_BLACK);
37 init_pair(PC_GREEN,COLOR_GREEN,COLOR_BLACK);
38 init_pair(PC_YELLOW,COLOR_YELLOW,COLOR_BLACK);
39 init_pair(PC_BLUE,COLOR_BLUE,COLOR_BLACK);
40 init_pair(PC_MAGENTA,COLOR_MAGENTA,COLOR_BLACK);
41 init_pair(PC_CYAN,COLOR_CYAN,COLOR_BLACK);
42 SET_COLOR(COL_BKG);
43
44 cbreak(); /* Disable line buffering and erase/kill characters */
45 noecho(); /* Don't echo characters */
46 nodelay(term,TRUE); /* Don't block while waiting for input */
47
48 nonl(); /* Don't translate return into newline, only CR */
49 intrflush(term,FALSE); /* Do not flush input at ^C */
50 keypad(term,TRUE); /* Enable keypad */
51
52 wrefresh(term);
53 }
54
55 // Returns true if terminal is 80x25
right_size()56 int right_size()
57 {
58 getmaxyx(term,term_y,term_x);
59
60 x_ofs = (term_x-80)/2;
61 y_ofs = (term_y-25)/2;
62
63 return ((term_x>=80)&&(term_y>=25));
64 }
65
presentation()66 void presentation()
67 {
68 blit_borders(COL_BLUE);
69
70 SET_COLOR(COL_GREEN);
71 mvwprintw(term,8+y_ofs,25+x_ofs,"-- -= A-L-I-E-N-W-A-V-E =- --");
72 mvwprintw(term,11+y_ofs,27+x_ofs, "a game by Alessandro Pira");
73 SET_COLOR(COL_WHITE);
74 mvwprintw(term,22+y_ofs,29+x_ofs, "Press any key to start");
75 SET_COLOR(COL_BKG);
76
77 while (wgetch(term) == ERR)
78 ;
79
80 wclear(term);
81 }
82
pause()83 int pause()
84 {
85 int overwritten[16];
86 int ch,i;
87
88 for (i=0;i<16;i++)
89 overwritten[i] = (int)mvwinch(term,10,31+i);
90
91 SET_COLOR(COL_RED);
92 mvwprintw(term,10,31," *** PAUSED *** ");
93 SET_COLOR(COL_BKG);
94
95 wmove(term,0,0);
96
97 while ((ch=wgetch(term)) == ERR)
98 ;
99
100 for (i=0;i<16;i++)
101 mvwaddch(term,10,31+i,(chtype)overwritten[i]);
102
103 if ((ch==KEY_ESC) || (ch=='Q'))
104 {
105 return -1;
106 }
107 return 0;
108 }
109
collide_ship(int x)110 int collide_ship(int x)
111 {
112 /* This collision algorithm is probably faster but must be completed */
113 /* int i;
114 int rel_x,rel_y;
115 for (i=0;i<NUMALIENS;i++)
116 {
117 if (all_aliens[i].type!=AT_NONE)
118 {
119 rel_x=x-all_aliens[i].x;
120 rel_y=21-all_aliens[i].y;
121 // ......
122 }
123 }
124 return 0; */
125
126 /* For now I will use this... it can be good anyway */
127 int check_x,check_y;
128 for (check_y=0; check_y<MAX_HEIGHT; check_y++)
129 {
130 for (check_x=0; check_x<8; check_x++)
131 {
132 if ( (bitmask_ship[check_y] & (0x80 >> check_x)) != 0 )
133 {
134 if (collide_aliens(x+check_x,21+check_y)>=0)
135 return 1;
136 if (collide_queen(x+check_x,21+check_y,COL_SHIP)>=0)
137 return 1;
138 }
139 }
140 }
141 return 0;
142 }
143
move_ship()144 int move_ship()
145 {
146 int c=0; /* character readen */
147 static int last_c=-1;
148 static int x=37; /* ship position */
149 static int xs=0; /* ship speed */
150
151 if (game_ended)
152 {
153 end_x=x; // Publish ship x position
154 return 0;
155 }
156
157 if (exploding == 0)
158 {
159 c = wgetch(term);
160 if (c != last_c)
161 {
162 switch(c)
163 {
164 case ERR:
165 /* No key pressed */
166 break;
167 case KEY_LEFT:
168 xs--;
169 break;
170 case KEY_RIGHT:
171 xs++;
172 break;
173 case KEY_DOWN:
174 xs=0;
175 break;
176 case ' ':
177 case KEY_ENTER_:
178 new_fire(x+3,21);
179 break;
180 case 's':
181 case KEY_BACKSPACE:
182 case KEY_UP:
183 open_shields(x-1,20);
184 break;
185 case 'p':
186 case 'P':
187 if (pause()<0)
188 {
189 c='Q';
190 }
191 break;
192 case KEY_ESC:
193 c='Q';
194 }
195 }
196 last_c = c;
197
198 /* Check limits */
199 if (xs>MAXSPEED) xs=MAXSPEED;
200 if (xs<-MAXSPEED) xs=-MAXSPEED;
201
202 clear_ship(x+x_ofs,21+y_ofs);
203
204 x+=xs;
205
206 if ( (x<0) || (x>73) )
207 {
208 xs = 0;
209 (x>0)?(x=73):(x=0);
210 }
211
212 blit_ship(x+x_ofs,21+y_ofs);
213
214 /* Check for collision with aliens */
215 if (collide_ship(x))
216 {
217 exploding=1;
218 }
219 }
220 else
221 {
222 switch (exploding++)
223 {
224 case 1:
225 clear_ship(x+x_ofs,21+y_ofs);
226 blit_explosion(x+3+x_ofs,22+y_ofs,3);
227 break;
228 case 2:
229 clear_explosion(x+3+x_ofs,22+y_ofs,3);
230 blit_explosion(x+3+x_ofs,22+y_ofs,3);
231 break;
232 case 3:
233 clear_explosion(x+3+x_ofs,22+y_ofs,3);
234 blit_explosion(x+3+x_ofs,22+y_ofs,4);
235 break;
236 case 4:
237 clear_explosion(x+3+x_ofs,22+y_ofs,4);
238 blit_explosion(x+3+x_ofs,22+y_ofs,4);
239 break;
240 case 5:
241 clear_explosion(x+3+x_ofs,22+y_ofs,4);
242 blit_explosion(x+3+x_ofs,22+y_ofs,3);
243 break;
244 case 6:
245 clear_explosion(x+3+x_ofs,22+y_ofs,3);
246 blit_explosion(x+3+x_ofs,22+y_ofs,3);
247 break;
248 case 7:
249 clear_explosion(x+3+x_ofs,22+y_ofs,3);
250 blit_explosion(x+3+x_ofs,22+y_ofs,2);
251 break;
252 case 8:
253 clear_explosion(x+3+x_ofs,22+y_ofs,2);
254 blit_explosion(x+3+x_ofs,22+y_ofs,2);
255 break;
256 case 9:
257 clear_explosion(x+3+x_ofs,22+y_ofs,2);
258 blit_explosion(x+3+x_ofs,22+y_ofs,1);
259 break;
260 case 10:
261 clear_explosion(x+3+x_ofs,22+y_ofs,1);
262 blit_explosion(x+3+x_ofs,22+y_ofs,1);
263 break;
264 case 11:
265 clear_explosion(x+3+x_ofs,22+y_ofs,1);
266 c='Q';
267 break;
268 }
269 }
270
271 wmove(term,0,0);
272 wrefresh(term);
273
274 return (c!='Q');
275 }
276
m_wait(long delay)277 void m_wait(long delay)
278 {
279 /*
280 // This is an algorithm I've tested to uniform speed on every CPU, but
281 // gettimeofday resolution isn't very high and I got also very strange
282 // and not uniform results...
283
284 static struct timeval last={0,0};
285 struct timeval now;
286 long diff;
287
288 if (gettimeofday(&now,NULL)<0)
289 {
290 // Error in gettimeofday... using old algorithm
291 diff=0;
292 }
293 else
294 {
295 fprintf(stderr,"%lu . %lu - ",now.tv_sec,now.tv_usec);
296 if (last.tv_sec==0) last=now;
297 diff=(now.tv_sec-last.tv_sec)*1000000 + (now.tv_usec-last.tv_usec);
298 last=now;
299 }
300
301 fprintf(stderr,"diff: %d, waiting %lu\n",diff,(delay-diff>0)?delay-diff:0);
302 if (delay-diff>0)
303 usleep(delay-diff);
304
305 return;
306 */
307 usleep(delay);
308 }
309
end_game()310 void end_game()
311 {
312 int y;
313 for (y=21;y>-7;y--)
314 {
315 clear_ship(end_x+x_ofs,y+y_ofs);
316 blit_ship(end_x+x_ofs,y-1+y_ofs);
317
318 wmove(term,0,0);
319 wrefresh(term);
320
321 m_wait(DELAY);
322
323 delete_aliens();
324 delete_queen();
325 delete_fires();
326 clear_shields();
327
328 move_fires();
329 move_aliens();
330 move_queen();
331 move_shields();
332
333 blit_queen();
334 blit_aliens();
335 blit_fires();
336 blit_shields();
337 blit_score(74+x_ofs,y_ofs,score);
338 blit_borders(COL_RED);
339 }
340 }
341
final()342 void final()
343 {
344 printf("\n Congratulations!\n");
345 printf(" You have defeated Xzarna, the Queen of the Zorxians!\n\n");
346
347 printf(" With their queen gone all the zorxian space ships fled, desperately\n");
348 printf(" seeking to save themselves, and the earth attack failed.\n");
349 printf(" 2 years later the zorxian race was completely defeated, and the\n");
350 printf(" human race completed its expansion in all the solar system.\n");
351 printf(" The starpilot who killed Xzarna was decorated, and his bravery is\n");
352 printf(" recorded in every history book.\n");
353 printf("\n *** THE END ***\n");
354 }
355
main()356 int main()
357 {
358 srand(time(NULL));
359 init_screen();
360
361 if (!right_size())
362 {
363 endwin();
364 fprintf(stderr,"Alienwave must be run in an 80x25 terminal!\n");
365 return -1;
366 }
367
368 presentation();
369
370 init_aliens();
371 init_queen();
372 init_levels();
373 init_fires();
374 init_shields();
375
376 while (move_ship())
377 {
378 m_wait(DELAY);
379
380 delete_aliens();
381 delete_queen();
382 delete_fires();
383 clear_shields();
384
385 // move functions also performs collision check
386 move_fires();
387 move_aliens();
388 move_queen();
389 move_shields();
390
391 blit_queen();
392 blit_aliens();
393 blit_fires();
394 blit_shields();
395 blit_score(74+x_ofs,y_ofs,score);
396 blit_borders(COL_GREEN);
397 }
398
399 if (game_ended)
400 {
401 end_game();
402 }
403
404 /* Flush input */
405 while (wgetch(term) != ERR)
406 ;
407
408 endwin();
409
410 if (game_ended) final();
411
412 printf("\nYou have made %d points!\n",score);
413 printf("-= A-L-I-E-N-W-A-V-E =- by Alessandro Pira\n");
414
415 return 0;
416 }
417
418