1 /* xsoldier, a shoot 'em up game with "not shooting" bonus
2  * Copyright (C) 1997 Yuusuke HASHIMOTO <s945750@educ.info.kanagawa-u.ac.jp>
3  * Copyright (C) 2002 Oohara Yuuma  <oohara@libra.interq.or.jp>
4  *
5  * This is a copyleft program.  See the file LICENSE for details.
6  */
7 /* $Id: enemyshot.c,v 1.7 2002/04/29 16:54:59 oohara Exp $ */
8 
9 #include <stdio.h>
10 #include <stdlib.h>
11 
12 /*
13 #include <X11/Xlib.h>
14 #include <X11/xpm.h>
15 */
16 
17 #include <stdlib.h>
18 #include "image.h"
19 #include "xsoldier.h"
20 #include "manage.h"
21 #include "common.h"
22 #include "enemyshot.h"
23 #include "callback.h"
24 #include "extern.h"
25 #include "sin.h"
26 
27 /* enemy shot */
ShotToAngle(int x,int y,int angle,int speed)28 void ShotToAngle(int x, int y, int angle, int speed)
29 {
30     int i;
31 
32     if (manage->EnemyNum >= manage->EnemyMax)
33         return;
34 
35     if (speed <= 0)
36       speed = 1;
37 
38     for (i=1; i<manage->EnemyMax; i++)
39     {
40         if (manage->enemy[i]->Data.used == False)
41 	{
42 	    manage->EnemyShot.Data.X = x;
43 	    manage->EnemyShot.Data.Y = y;
44 	    manage->EnemyShot.Data.Angle = angle;
45 	    manage->EnemyShot.Data.Speed = speed;
46 	    manage->EnemyShot.Data.Cnt[0] = x << 8;
47 	    manage->EnemyShot.Data.Cnt[1] = y << 8;
48 	    manage->EnemyShot.Data.Cnt[2] = icos(angle);
49 	    manage->EnemyShot.Data.Cnt[3] = isin(angle);
50 
51 	    manage->enemy[i]->Data    = manage->EnemyShot.Data;
52 	    manage->enemy[i]->Grp     = manage->EnemyShot.Grp;
53             manage->enemy[i]->Action  = EnemyShotAct;
54             manage->enemy[i]->Realize = DrawImage;
55             manage->enemy[i]->Hit     = NullDelHit;
56 
57 	    manage->EnemyNum++;
58 	    return;
59 	}
60     }
61 }
62 
ShotToPoint(int x1,int y1,int x2,int y2,int speed)63 void ShotToPoint(int x1, int y1, int x2, int y2, int speed)
64 {
65     int i;
66     int diffx = x2 - x1;
67     int diffy = y2 - y1;
68     int absx = abs(diffx);
69     int absy = abs(diffy);
70 
71     if (manage->EnemyNum >= manage->EnemyMax)
72         return;
73 
74     if (speed <= 0)
75       speed = 1;
76 
77     for (i=1; i<manage->EnemyMax; i++)
78     {
79         if (manage->enemy[i]->Data.used == False)
80 	{
81 	    manage->EnemyShot.Data.X = x1;
82 	    manage->EnemyShot.Data.Y = y1;
83 	    manage->EnemyShot.Data.Speed = speed;
84 	    manage->EnemyShot.Data.Cnt[0] = x1 << 8;
85 	    manage->EnemyShot.Data.Cnt[1] = y1 << 8;
86 	    if (absx >= absy)
87 	    {
88 		manage->EnemyShot.Data.Cnt[2] = 1 << 8;
89 		manage->EnemyShot.Data.Cnt[3] = (absy/(double)absx) * 256;
90 	    }
91 	    else
92 	    {
93 		manage->EnemyShot.Data.Cnt[2] = (absx/(double)absy) * 256;
94 		manage->EnemyShot.Data.Cnt[3] = 1 << 8;
95 	    }
96 	    if (diffx < 0)
97 		manage->EnemyShot.Data.Cnt[2] *= -1;
98 	    if (diffy < 0)
99 		manage->EnemyShot.Data.Cnt[3] *= -1;
100 
101 	    manage->enemy[i]->Data    = manage->EnemyShot.Data;
102 	    manage->enemy[i]->Grp     = manage->EnemyShot.Grp;
103             manage->enemy[i]->Action  = EnemyShotAct;
104             manage->enemy[i]->Realize = DrawImage;
105             manage->enemy[i]->Hit     = NullDelHit;
106 
107 	    manage->EnemyNum++;
108 	    return;
109 	}
110     }
111 }
112 
EnemyShotAct(ObjData * my)113 DelAtt EnemyShotAct(ObjData *my)
114 {
115   /* 2^8 = 256 */
116     my->Cnt[0] += my->Cnt[2]*my->Speed;
117     my->X = my->Cnt[0] / 256;
118     my->Cnt[1] += my->Cnt[3]*my->Speed;
119     my->Y = my->Cnt[1] / 256;
120 
121     my->Cnt[4]++;
122     if (my->Cnt[4] >= 3)
123     {
124 	my->Cnt[4] = 0;
125 	my->image++;
126 	if (my->image > 3)
127 	    my->image = 0;
128     }
129 
130     if ((my->X < 0 - my->Width/2) || (my->X > FieldW + my->Width/2))
131 	return NullDel;
132     if ((my->Y < 0 - my->Height/2) || (my->Y > FieldH + my->Height/2))
133 	return NullDel;
134 
135     return NoneDel;
136 }
137 
RingToAngle(int x,int y,int angle,int speed)138 int RingToAngle(int x, int y, int angle, int speed)
139 {
140   if (speed <= 0)
141     speed = 1;
142 
143     manage->New.Data.hitAtt = MEnemy;
144     manage->New.Data.hitMask = MPlayer | MPShot;
145 
146     manage->New.Data.X = x;
147     manage->New.Data.Y = y;
148     manage->New.Data.HP = 1;
149     manage->New.Data.Point = 0;
150     manage->New.Data.Angle = angle;
151     manage->New.Data.Speed = speed;
152     manage->New.Data.Cnt[0] = x << 8;
153     manage->New.Data.Cnt[1] = y << 8;
154     manage->New.Data.Cnt[2] = icos(angle);
155     manage->New.Data.Cnt[3] = isin(angle);
156     manage->New.Data.Cnt[4] = 0;
157     manage->New.Data.EnemyAtt = NullDel;
158     manage->New.Data.Width = 28;
159     manage->New.Data.Height = 28;
160 
161     manage->New.Grp.image = ERingImage;
162 
163     return NewObj(MEnemy,EnemyShotAct,DeleteHit,DrawImage);
164 }
165 
RingToPoint(int x1,int y1,int x2,int y2,int speed)166 int RingToPoint(int x1, int y1, int x2, int y2, int speed)
167 {
168     int diffx = x2 - x1;
169     int diffy = y2 - y1;
170     int absx = abs(diffx);
171     int absy = abs(diffy);
172 
173     if (speed <= 0)
174       speed = 1;
175 
176     manage->New.Data.hitAtt = MEnemy;
177     manage->New.Data.hitMask = MPlayer | MPShot;
178 
179     manage->New.Data.X = x1;
180     manage->New.Data.Y = y1;
181     manage->New.Data.HP = 1;
182     manage->New.Data.Point = 0;
183     manage->New.Data.Speed = speed;
184     manage->New.Data.Cnt[0] = x1 << 8;
185     manage->New.Data.Cnt[1] = y1 << 8;
186 
187     if (absx >= absy)
188     {
189 	manage->New.Data.Cnt[2] = 1 << 8;
190 	manage->New.Data.Cnt[3] = (absy/(double)absx) * 256;
191     }
192     else
193     {
194 	manage->New.Data.Cnt[2] = (absx/(double)absy) * 256;
195 	manage->New.Data.Cnt[3] = 1 << 8;
196     }
197     if (diffx < 0)
198 	manage->New.Data.Cnt[2] *= -1;
199     if (diffy < 0)
200 	manage->New.Data.Cnt[3] *= -1;
201 
202     manage->New.Data.Cnt[4] = 0;
203     manage->New.Data.EnemyAtt = NullDel;
204     manage->New.Data.Width = 28;
205     manage->New.Data.Height = 28;
206 
207     manage->New.Grp.image = ERingImage;
208 
209     return NewObj(MEnemy,EnemyShotAct,DeleteHit,DrawImage);
210 }
211 
HomingShot(int x,int y,int ix,int iy)212 int HomingShot(int x, int y, int ix, int iy)
213 {
214     manage->New.Data.hitAtt = MEnemy;
215     manage->New.Data.hitMask = MPlayer | MPShot;
216 
217     manage->New.Data.X = x;
218     manage->New.Data.Y = y;
219     manage->New.Data.HP = 1;
220     manage->New.Data.Point = 0;
221     manage->New.Data.EnemyAtt = NullDel;
222     manage->New.Data.Width = 16;
223     manage->New.Data.Height = 16;
224     manage->New.Data.inertX = ix;
225     manage->New.Data.inertY = iy;
226 
227     manage->New.Grp.image = EMissileImage;
228 
229     return NewObj(MEnemy,HomingAct,DeleteHit,DrawImage);
230 }
231 
HomingAct(ObjData * my)232 DelAtt HomingAct(ObjData *my)
233 {
234     if (my->X < manage->player[0]->Data.X)
235     {
236 	if (my->inertX < 15)
237             my->inertX += 1;
238     }
239     else
240     {
241 	if (my->inertX > -15)
242             my->inertX -= 1;
243     }
244 
245     if (my->Y < manage->player[0]->Data.Y)
246 	my->inertY++;
247     else
248 	my->inertY--;
249 
250     my->X += my->inertX;
251     my->Y += my->inertY;
252 
253     my->image = GetDirection(0,0,my->inertX,my->inertY);
254 
255     if ((my->X < 0 - my->Width/2) || (my->X > FieldW + my->Width/2))
256 	return NullDel;
257     if ((my->Y < 0 - my->Height/2) || (my->Y > FieldH + my->Height/2))
258 	return NullDel;
259 
260     return NoneDel;
261 }
262 
LaserShot(int x,int y,int speed)263 int LaserShot(int x, int y, int speed)
264 {
265   if (speed <= 0)
266     speed = 1;
267 
268     manage->New.Data.hitAtt = MEShot;
269     manage->New.Data.hitMask = MPlayer;
270 
271     manage->New.Data.X = x;
272     manage->New.Data.Y = y;
273     manage->New.Data.EnemyAtt = NullDel;
274     manage->New.Data.Width = 7;
275     manage->New.Data.Height = 50;
276     manage->New.Data.Speed = speed;
277 
278     manage->New.Grp.image = ELaserImage;
279 
280     return NewObj(MEShot,EnemyLaserAct,NullHit,DrawImage);
281 }
282 
EnemyLaserAct(ObjData * my)283 DelAtt EnemyLaserAct(ObjData *my)
284 {
285     my->Y += my->Speed;
286 
287     if ((my->X < 0 - my->Width/2) || (my->X > FieldW + my->Width/2))
288 	return NullDel;
289     if ((my->Y < 0 - my->Height/2) || (my->Y > FieldH + my->Height/2))
290 	return NullDel;
291 
292     return NoneDel;
293 }
294 
BoundShot(int x,int y,int ix,int iy,int bound)295 int BoundShot(int x, int y, int ix, int iy, int bound)
296 {
297   if ((ix == 0) && (iy == 0))
298     ix = 1;
299 
300     manage->New.Data.hitAtt = MEnemy;
301     manage->New.Data.hitMask = MPlayer | MPShot;
302 
303     manage->New.Data.X = x;
304     manage->New.Data.Y = y;
305     manage->New.Data.EnemyAtt = NullDel;
306     manage->New.Data.Width = 28;
307     manage->New.Data.Height = 28;
308     manage->New.Data.inertX = ix;
309     manage->New.Data.inertY = iy;
310 
311     manage->New.Data.Cnt[0] = 0;
312     manage->New.Data.Cnt[1] = bound;
313 
314     manage->New.Grp.image = EBoundImage;
315 
316     return NewObj(MEShot,BoundShotAct,NullHit,DrawImage);
317 }
318 
BoundShotAct(ObjData * my)319 DelAtt BoundShotAct(ObjData *my)
320 {
321   if (my->Cnt[0] <= my->Cnt[1])
322   {
323     if ((my->X+my->inertX>FieldW) || (my->X+my->inertX<0))
324     {
325       my->inertX = my->inertX*(-1);
326       my->Cnt[0]++;
327     }
328     if ((my->Y+my->inertY>FieldH) || (my->Y+my->inertY<0))
329     {
330       my->inertY = my->inertY*(-1);
331       my->Cnt[0]++;
332     }
333   }
334 
335     my->image++;
336     if (my->image >= 8)
337 	my->image = 0;
338 
339     my->X += my->inertX;
340     my->Y += my->inertY;
341 
342     if ((my->X < 0 - my->Width/2) || (my->X > FieldW + my->Width/2))
343 	return NullDel;
344     if ((my->Y < 0 - my->Height/2) || (my->Y > FieldH + my->Height/2))
345 	return NullDel;
346 
347     return NoneDel;
348 }
349