docs
[mirrors/Programs.git] / c / ninvaders-0.1.1 / aliens.c
1 /**
2 * nInvaders - a space invaders clone for ncurses
3 * Copyright (C) 2002-2003 Dettus
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 *
19 * homepage: http://ninvaders.sourceforge.net
20 * mailto: ninvaders-devel@lists.sourceforge.net
21 *
22 */
23
24
25 #include "aliens.h"
26 #include "player.h"
27 #include "nInvaders.h"
28
29 /**
30 * initialize aliens attributes
31 */
32 void aliensReset()
33 {
34 int i,j;
35
36 // three different types of aliens [5], [10]
37 int level[ALIENS_MAX_NUMBER_Y][ALIENS_MAX_NUMBER_X]={
38 {1,1,1,1,1,1,1,1,1,1},
39 {2,2,2,2,2,2,2,2,2,2},
40 {2,2,2,2,2,2,2,2,2,2},
41 {3,3,3,3,3,3,3,3,3,3},
42 {3,3,3,3,3,3,3,3,3,3}
43 };
44
45 aliensClear(aliens.posX, aliens.posY, aliens.right, aliens.bottom); // clear old position of aliens
46
47 // reset alien position
48 aliens.posX = 0;
49 aliens.posY = 0;
50 aliens.right = 0;
51 aliens.bottom = 0;
52 aliens.left = 0;
53 aliens.speed = 1;
54
55 // copy level-array to enemy-array
56 for (i=0;i<ALIENS_MAX_NUMBER_X;i++) {
57 for (j=0;j<ALIENS_MAX_NUMBER_Y;j++) {
58 alienBlock[j][i]=level[j][i];
59 }
60 }
61
62 // reset missiles
63 for (i = 0; i < ALIENS_MAX_MISSILES; i++) {
64 if (alienshotx[i] != 0) {
65 aliensMissileClear(alienshotx[i],alienshoty[i]); // clear old position
66 }
67 alienshotx[i] = 0; // start with zero values
68 alienshoty[i] = 0; // start with zero values
69 }
70 alienshotnum = 1; // one missile at the same time
71 alienshotx[0] = 5; // x position of first alienshot
72 alienshoty[0] = 1; // y position of first alienshot
73
74 }
75
76 /**
77 * initialize bunkers attributes
78 */
79 void bunkersReset()
80 {
81 int a, b;
82
83 // set position of bunker sprites. user graphical char bunkerd for better visual overview
84 // and set according to this the bunker-array
85 char bunkerd[BUNKERHEIGHT][BUNKERWIDTH+1] = {
86 " ### ### ### ### ",
87 " ##### ##### ##### ##### ",
88 " ####### ####### ####### ####### ",
89 " ## ## ## ## ## ## ## ## "
90 };
91 // 12345678901234567890123456789012345678901234567890123456789012345678901234567890
92 // 80 characters wide
93
94 // copy graphical "bunkerd" to binary "bunker"
95 for (a = 0; a < BUNKERWIDTH; a++) {
96 for (b = 0; b < BUNKERHEIGHT; b++) {
97 if (bunkerd[b][a] == '#')
98 bunker[b][a] = 1;
99 else
100 bunker[b][a] = 0;
101 }
102 }
103
104 // display bunkers sprite
105 bunkersDisplay(&bunker[0][0]);
106 }
107
108 /**
109 * move aliens and test if they've reached the
110 * bottom of the windows or the bunkers.
111 */
112 int aliensMove()
113 {
114
115 int cx,cy;
116 int fReachedPlayer=0; // return value
117
118 render();
119 aliensClear(aliens.posX, aliens.posY, aliens.right, aliens.bottom); // clear old position of aliens
120
121 aliens.posX = aliens.posX + aliens.speed; // move aliens left/ right
122
123 // when aliens reached left or right screen-border
124 if (aliens.posX == (BUNKERWIDTH + BUNKERX - 5 - aliens.right) || aliens.posX == (BUNKERX + aliens.left)) {
125
126 aliens.posY++; // move aliens downwards
127
128 // aliens reached player
129 if (aliens.posY == SCREENHEIGHT - 2 - aliens.bottom) {
130 fReachedPlayer = 1; // set return value
131 }
132
133 // aliens reached bunkers //funzt nicht ganz: todo
134 if (aliens.posY == BUNKERY - aliens.bottom) {
135 // clear bunkers
136 for(cx=0;cx<BUNKERWIDTH;cx++) {
137 for(cy=0;cy<BUNKERHEIGHT;cy++) {
138 bunker[cy][cx]=0;
139 }
140 }
141 bunkersClear(); // clear bunkers sprites
142 }
143
144 aliens.speed = aliens.speed * (-1); // change direction of aliens' movements
145 }
146
147 aliensDisplay(aliens.posX, aliens.posY, aliens.right, aliens.bottom); // display aliens at new position
148
149 return fReachedPlayer; // return if aliens reached player
150 }
151
152
153 /**
154 * display alien animation, display remaining parts of aliens and bunker
155 */
156 void render()
157 {
158 int k,row;
159 int c=0;
160
161 // calculate left, right, bottom, lowest_ship
162 aliens.left=1;
163 aliens.right=-1;
164 aliens.bottom=-1;
165 shipnum=0;
166 for (k=0;k<11;k++) {
167 lowest_ship[k]=-1;
168 }
169
170 for (row=0;row<ALIENS_MAX_NUMBER_Y*2;row++) {
171 if ((row%2)==0){
172 for (k=0;k<ALIENS_MAX_NUMBER_X;k++) {
173 if (alienBlock[c][k] != 0) {
174 lowest_ship[k]=row;
175 shipnum++;
176 if (aliens.left==1 || -k>aliens.left) {aliens.left=-k;}
177 if (aliens.right==-1 || k>aliens.right) {aliens.right=k;}
178 if (aliens.bottom==-1 || c>aliens.bottom) {aliens.bottom=c;}
179 }
180 }
181 } else {
182 c++;
183 }
184 }
185 aliens.bottom=aliens.bottom*2; // every 2nd row is an empty row
186 aliens.left=aliens.left*3; // alien sprite is 3 chars wide
187 aliens.right=aliens.right*3; // alien sprite is 3 chars wide
188
189 // display remaining aliens with animation
190 aliensRefresh(level, &alienBlock[0][0]);
191
192 }
193
194
195 /**
196 * move aliens' missiles and do player/bunker hit testing
197 * a zero value in alienshotx indicates that the appropriate missile is loaded, but not fired
198 */
199 int aliensMissileMove()
200 {
201 int i, tmp;
202 int fPlayerWasHit = 0;
203 int shootThreshold;
204 static int alienshot_counter = 0;
205
206
207 // calculate threshold when next missile should be fired
208 // it is done here to save calculation time in for-instruction
209 shootThreshold = (skill_level * 8) * (shipnum + 2);
210 alienshot_counter = alienshot_counter + 10 ;
211
212 // loop all possible missiles
213 for (i = 0; i < ALIENS_MAX_MISSILES; i++) {
214
215 // if the current missile is flying we should do movements
216 if (alienshotx[i] != 0) {
217
218 aliensMissileClear(alienshotx[i],alienshoty[i]); // clear old position
219
220 // if missile hit the bunkers
221 if (bunkersHitCheck(alienshotx[i], alienshoty[i]) == 1) {
222 alienshotx[i] = 0; // value of zero reloads missile
223 }
224
225 alienshoty[i]++; // move missile downwards
226
227 // check if player was hit by an alien missile
228 if (playerHitCheck(alienshotx[i], alienshoty[i]) == 1) {
229 alienshotx[i] = 0; // value of zero reloads missile
230 fPlayerWasHit = 1;
231 }
232
233
234 } else { // missile not launched yet
235
236 // start new missile if counter says so
237 if (alienshot_counter > shootThreshold && shipnum > 0) {// only shot if there's an alien left
238 alienshot_counter = 0; // reset counter
239 tmp = random() % ALIENS_MAX_NUMBER_X; // randomly select one of the ...
240 while (lowest_ship[tmp] == -1) { // ...aliens at the bottom of ...
241 tmp = random() % ALIENS_MAX_NUMBER_X; // ...a column to launch missile
242 }
243 alienshoty[i]=aliens.posY+lowest_ship[tmp]; // set y position of missile
244 alienshotx[i]=aliens.posX+tmp*3; // set x position of missile
245 }
246 } // if
247
248 // display missiles if still running or just launched; could have been modified in the above code
249 if (alienshotx[i] != 0) {
250 // if missile is out of battlefield
251 if (alienshoty[i] == SCREENHEIGHT - 1) {
252 alienshotx[i] = 0; // reload missile
253 } else {
254 aliensMissileDisplay(alienshotx[i], alienshoty[i]); // display Missile at new position
255 }
256 }
257
258 } // for
259
260
261 return fPlayerWasHit;
262 }
263
264
265
266 /**
267 * check if missile hit an alien
268 */
269 int aliensHitCheck(int shotx, int shoty)
270 {
271 int alienType = 0;
272 int shipx, shipy;
273 // if missile is within alien-rectangle
274 if (shotx >= aliens.posX && shotx <= aliens.posX + ALIENS_MAX_NUMBER_X * 3 - 1
275 && shoty >= aliens.posY && shoty <= aliens.posY + (ALIENS_MAX_NUMBER_Y - 1) * 2) {
276 // calculate the ship that was hit
277 shipx = (shotx - aliens.posX) / 3;
278 shipy = (shoty - aliens.posY) / 2;
279 // if there is still a ship at this position
280 alienType = alienBlock[shipy][shipx];
281 if (alienType != 0) {
282 alienBlock[shipy][shipx] = 0; // delete alien ship
283 }
284 }
285 return alienType; // returns 0 if no alien was hit, else returns type-code of alien
286 }
287
288 /**
289 * check if missile hit an element of bunker
290 */
291 int bunkersHitCheck(int shotx, int shoty)
292 {
293 int adjx, adjy;
294 int fBunkerWasHit = 0;
295 // if missile is within bunker-rectangle
296 if (shotx >= BUNKERX && shotx < BUNKERX + BUNKERWIDTH
297 && shoty >= BUNKERY && shoty < BUNKERY + BUNKERHEIGHT) {
298 // calculate the element of the bunker that was hit
299 adjy = shoty - BUNKERY;
300 adjx = shotx - BUNKERX;
301 // if there is still an element
302 if(bunker[adjy][adjx] == 1){
303 bunker[adjy][adjx] = 0; // delete element
304 fBunkerWasHit = 1; // bunker was hit!
305 }
306 }
307 return fBunkerWasHit;
308 }
This page took 0.426897 seconds and 4 git commands to generate.