Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
9566 turbocat 1
#include "heads.h"
2
#include "../enemy.h"
3
#include "../game.h"
4
#include "../PHL.h"
5
#include "../hero.h"
6
#include 
7
#include 
8
 
9
void headStep(Head* h);
10
void headDraw(Head* h);
11
 
12
void bulletStep(Bullet* b);
13
void bulletDraw(Bullet* b);
14
 
15
void fireballStep(Fireball* f);
16
void fireballDraw(Fireball* f);
17
 
18
void laserStep(Laser* l);
19
void laserDraw(Laser* l);
20
 
21
void flameStep(Flame* f);
22
void flameDraw(Flame* f);
23
 
24
void rockStep(Rock* r);
25
void rockDraw(Rock* r);
26
 
27
void airStep(Air* a);
28
void airDraw(Air* a);
29
 
30
void createHead(int type, int x, int y, int dir, int offset, int cooloff)
31
{
32
	int i;
33
	for (i = 0; i < MAX_ENEMIES; i++) {
34
		if (enemies[i] == NULL) {
35
			Enemy* e = malloc(sizeof *e);
36
			Head* h = malloc(sizeof *h);
37
 
38
			h->id = i;
39
			h->type = type;
40
 
41
			h->x = x;
42
			h->y = y;
43
 
44
			h->state = 0;
45
 
46
			h->hp = 5;
47
			h->invincible = 0;
48
			h->counter = 0;
49
 
50
			h->dir = 1;
51
			if (dir == 1) {
52
				h->dir = -1;
53
			}
54
 
55
			h->timer = 30 * offset;
56
			h->cooloff = 60;
57
			if (cooloff != 0) {
58
				h->cooloff = 30 * cooloff;
59
			}
60
 
61
			e->type = -1;
62
			if (h->type == 0) {
63
				e->type = 4;
64
				h->cooloff = 120;
65
			}
66
			else if (h->type == 1) {
67
				e->type = 6;
68
			}
69
			else if (h->type == 2) {
70
				e->type = 5;
71
			}
72
			else if (h->type == 3) {
73
				e->type = 7;
74
				h->cooloff = 120;
75
			}
76
			else if (h->type == 4) {
77
				e->type = 10;
78
				h->dir = 0;
79
			}
80
			else if (h->type == 5) {
81
				e->type = 25;
82
				h->dir = 0;
83
			}
84
			e->data = h;
85
			e->enemyStep = headStep;
86
			e->enemyDraw = headDraw;
87
 
88
			enemies[i] = e;
89
			i = MAX_ENEMIES;
90
		}
91
	}
92
}
93
 
94
void headStep(Head* h)
95
{
96
	int RHYNO = 0,
97
		MEDUSA = 1,
98
		DRAGON = 2,
99
		DEMON = 3,
100
		FIRE = 4,
101
		JAR = 5;
102
 
103
	//Setup Mask
104
	Mask mask;
105
	{
106
		mask.circle = mask.unused = 0;
107
		mask.x = h->x;
108
		mask.y = h->y + 1;
109
		mask.w = 40;
110
		mask.h = 39;
111
	}
112
 
113
	//Timers
114
	{
115
		if (h->invincible > 0) {
116
			h->invincible -= 1;
117
		}
118
 
119
		if (h->timer > 0) {
120
			h->timer -= 1;
121
		}
122
	}
123
 
124
	//Wait
125
	if (h->state == 0)
126
	{
127
		char endstate = 0;
128
 
129
		if (h->timer <= 0) {
130
			//Proximity
131
			if (h->type == RHYNO || h->type == DEMON) {
132
				Mask area;
133
				area.circle = area.unused = 0;
134
				area.h = 80;
135
				area.w = 400;
136
				area.y = h->y - 20;
137
				area.x = h->x;
138
				if (h->dir == -1) {
139
					area.x -= area.w - 40;
140
				}
141
 
142
				if (checkCollision(area, getHeroMask()) == 1) {
143
					endstate = 1;
144
				}
145
			}else{
146
				endstate = 1;
147
			}
148
		}
149
 
150
		//Move onto next state
151
		if (endstate == 1) {
152
			h->state = 1;
153
			h->timer = 30;
154
		}
155
	}
156
 
157
	//Blink
158
	else if (h->state == 1)
159
	{
160
		//Shoot projectile
161
		if (h->timer <= 0) {
162
			//Play Sound
163
			{
164
				int soundtoplay[6] = {sndShot03, sndShot04, sndFire01, sndHit06, sndShot03, sndShot06};
165
				PHL_PlaySound(sounds[soundtoplay[h->type]], CHN_ENEMIES);
166
			}
167
 
168
			//Set vars
169
			{
170
				h->state = 0;
171
				h->timer = h->cooloff;
172
			}
173
 
174
			//Create projectile
175
			{
176
				//Rhyno head
177
				if (h->type == RHYNO) {
178
					createBullet(mask.x + (mask.w / 2), h->y + 24, h->dir, h->id);
179
				}
180
				//Medusa head
181
				if (h->type == MEDUSA) {
182
					createLaser(h->x, h->y, h->dir);
183
				}
184
				//Dragon head
185
				if (h->type == DRAGON) {
186
					createFlame(h->x + 20 + (20 * h->dir), h->y - 10, h->dir);
187
				}
188
				//Demon head
189
				if (h->type == DEMON) {
190
					createRock(h->x + (20 * h->dir), h->y, h->dir);
191
				}
192
				//Fireball Statue
193
				if (h->type == FIRE) {
194
					createFireball(h->x + 20, h->y + 20, (atan2(heroy - h->y, h->x - (herox - 20)) * 180 / 3.14159) + 270, h->id);
195
				}
196
				//Air Jar
197
				if (h->type == JAR) {
198
					h->state = 3;
199
					h->timer = 12;
200
					h->counter = 0;
201
				}
202
			}
203
 
204
		}
205
	}
206
 
207
	//Air Jar
208
	else if (h->state == 3)
209
	{
210
		if (h->timer <= 0) {
211
			h->counter += 1;
212
			h->timer = 12;
213
			createAir(h->x, h->y - 20);
214
		}
215
 
216
		if (h->counter >= 6) {
217
			h->counter = 0;
218
			h->state = 0;
219
			h->timer = h->cooloff;
220
		}
221
	}
222
 
223
	//Hit player
224
	if (h->type != JAR) {
225
		if (checkCollision(getHeroMask(), mask)) {
226
			heroHit(10, mask.x + (mask.w / 2));
227
		}
228
	}
229
 
230
	//Weapon collision
231
	int i;
232
	for (i = 0; i < MAX_WEAPONS; i++) {
233
		if (weapons[i] != NULL) {
234
			if (weapons[i]->cooldown == 0) {
235
				if (checkCollision(mask, weapons[i]->weaponMask)) {
236
					h->hp -= 1;
237
					h->invincible = 15;
238
					weaponHit(weapons[i]);
239
					//Death
240
					if (h->hp <= 0) {
241
						createRockSmash(h->x + 20, h->y + 20);
242
						spawnCollectable(h->x + 20, h->y);
243
						enemyDestroy(h->id);
244
					}
245
 
246
					i = MAX_WEAPONS;
247
				}
248
			}
249
		}
250
	}
251
}
252
 
253
void headDraw(Head* h)
254
{
255
	if (h->invincible % 2 == 0)
256
	{
257
		int sheetX[6] = {0, 320, 160, 240, 560, 400};
258
		int sheetY[6] = {80, 80, 80, 120, 0, 120};
259
 
260
		int cropX = sheetX[h->type];
261
 
262
		int addx[6] = {6, 2, 0, 0, 0, 0};
263
		int frames = 2;
264
 
265
		//Change dir
266
		if (h->dir == 0) {
267
			frames = 1;
268
		}else{
269
			frames = 2;
270
			if (h->dir == -1) {
271
				cropX += 40;
272
			}
273
		}
274
 
275
		//White flash
276
		if (h->state == 1 && h->timer % 6 < 3) {
277
			cropX += 40 * frames;
278
		}
279
 
280
		PHL_DrawSurfacePart(h->x - (addx[h->type] * h->dir), h->y, cropX, sheetY[h->type], 40, 40, images[imgEnemies]);
281
	}
282
}
283
 
284
//Bullets
285
void createBullet(int x, int y, int dir, int minid)
286
{
287
	int i;
288
	for (i = minid; i < MAX_ENEMIES; i++) {
289
		if (enemies[i] == NULL) {
290
			Enemy* e = malloc(sizeof *e);
291
			Bullet* b = malloc(sizeof *b);
292
			b->id = i;
293
 
294
			b->x = x;
295
			b->y = y;
296
 
297
			b->hsp = dir * 4;
298
 
299
			b->imageIndex = 0;
300
 
301
			e->data = b;
302
			e->enemyStep = bulletStep;
303
			e->enemyDraw = bulletDraw;
304
			e->type = -1;
305
 
306
			enemies[i] = e;
307
			i = MAX_ENEMIES;
308
		}
309
	}
310
}
311
 
312
void bulletStep(Bullet* b)
313
{
314
	char dead = 0;
315
 
316
	//Movement
317
	{
318
		b->x += b->hsp;
319
	}
320
 
321
	//Create Mask
322
	Mask mask;
323
	{
324
		mask.unused = 0;
325
		mask.circle = 1;
326
		mask.w = mask.h = 10;
327
		mask.x = b->x;
328
		mask.y = b->y;
329
	}
330
 
331
	//Animation
332
	{
333
		if (b->hsp > 0) {
334
			b->imageIndex += 0.33;
335
		}else{
336
			b->imageIndex -= 0.33;
337
		}
338
 
339
		if (b->imageIndex < 0) {
340
			b->imageIndex += 4;
341
		}
342
		if (b->imageIndex >= 4) {
343
			b->imageIndex -= 4;
344
		}
345
	}
346
 
347
	//Collide with wall
348
	{
349
		if (checkTileCollision(1, mask) == 1) {
350
			createEffect(1, b->x - 20, b->y - 20);
351
			dead = 1;
352
		}
353
	}
354
 
355
	//Collide with hero
356
	{
357
		//Shield collision
358
		if (checkCollision(mask, shieldMask) == 1) {
359
			dead = 1;
360
			createEffect(1, b->x - 20, b->y - 20);
361
			PHL_PlaySound(sounds[sndHit07], CHN_EFFECTS);
362
		}
363
		//Collide with hero
364
		else{
365
			if (checkCollision(getHeroMask(), mask)) {
366
				heroHit(10, mask.x);
367
			}
368
		}
369
	}
370
 
371
	//Destroy if outside of view
372
	{
373
		if (b->x > 660 || b->x < -20 || b->y < -20 || b->y > 520) {
374
			dead = 1;
375
		}
376
	}
377
 
378
	//Destroy
379
	{
380
		if (dead == 1) {
381
			enemyDestroy(b->id);
382
		}
383
	}
384
}
385
 
386
void bulletDraw(Bullet* b)
387
{
388
	PHL_DrawSurfacePart(b->x - 20, b->y - 20, 160 + (40 * (int)b->imageIndex), 480, 40, 40, images[imgMisc20]);
389
}
390
 
391
//Fireball
392
void createFireball(int x, int y, int angle, int minid)
393
{
394
	//General idea: try to place fireball over spawner
395
	int i;
396
	for (i = minid; i < MAX_ENEMIES; i++) {
397
		if (enemies[i] == NULL) {
398
			Enemy* e = malloc(sizeof *e);
399
			Fireball* f = malloc(sizeof *f);
400
			f->id = i;
401
 
402
			f->x = x;
403
			f->y = y;
404
 
405
			f->spd = 3;
406
 
407
			f->imageIndex = 0;
408
			f->angle = angle;
409
 
410
			f->mask.circle = 1;
411
			f->mask.unused = 0;
412
			f->mask.x = x;
413
			f->mask.y = y;
414
			f->mask.w = f->mask.h = 14;
415
 
416
			e->data = f;
417
			e->enemyStep = fireballStep;
418
			e->enemyDraw = fireballDraw;
419
			e->type = -1;
420
 
421
			enemies[i] = e;
422
 
423
			i = MAX_ENEMIES;
424
		}
425
	}
426
}
427
 
428
void fireballStep(Fireball* f)
429
{
430
	f->x += (f->spd) * sin(f->angle * 3.14159 / 180);
431
	f->y += (f->spd) * cos(f->angle * 3.14159 / 180);
432
 
433
	f->mask.x = f->x;
434
	f->mask.y = f->y;
435
 
436
	f->imageIndex += 0.5;
437
	if (f->imageIndex >= 8) {
438
		f->imageIndex -= 8;
439
	}
440
 
441
	//Collide with shield
442
	if (checkCollision(f->mask, shieldMask)) {
443
		createEffect(1, f->x - 20, f->y - 20);
444
		PHL_PlaySound(sounds[sndHit07], CHN_EFFECTS);
445
		enemyDestroy(f->id);
446
	}else{
447
		//Hit player
448
		if (checkCollision(getHeroMask(), f->mask)) {
449
			heroHit(10, f->mask.x);
450
		}
451
		//Destroy if outside of view
452
		if (f->x > 660 || f->x < -20 || f->y < -20 || f->y > 520) {
453
			enemyDestroy(f->id);
454
		}
455
	}
456
}
457
 
458
void fireballDraw(Fireball* f)
459
{
460
	PHL_DrawSurfacePart(f->x - 20, f->y - 20, 320 + (40 * (int)f->imageIndex), 440, 40, 40, images[imgMisc20]);
461
}
462
 
463
//Laser
464
void createLaser(int x, int y, int dir)
465
{
466
	int i;
467
	for (i = 0; i < MAX_ENEMIES; i++) {
468
		if (enemies[i] == NULL) {
469
			Enemy* e = malloc(sizeof *e);
470
			Laser* l = malloc(sizeof *l);
471
			l->id = i;
472
 
473
			l->x = x;
474
			l->y = y;
475
 
476
			l->dir = dir;
477
			l->imageIndex = 0;
478
 
479
			l->mask.circle = l->mask.unused = 0;
480
			l->mask.x = x;
481
			l->mask.y = y + 17;
482
			l->mask.w = 40;
483
			l->mask.h = 6;
484
 
485
			e->data = l;
486
			e->enemyStep = laserStep;
487
			e->enemyDraw = laserDraw;
488
			e->type = -1;
489
 
490
			enemies[i] = e;
491
			i = MAX_ENEMIES;
492
		}
493
	}
494
}
495
 
496
void laserStep(Laser* l)
497
{
498
	char dead = 0;
499
 
500
	l->x += l->dir * 10;
501
	l->mask.x = l->x;
502
 
503
	l->imageIndex += 0.34;
504
	if (l->imageIndex >= 2) {
505
		l->imageIndex -= 2;
506
	}
507
 
508
	if (checkCollision(shieldMask, l->mask)) { //Hit shield
509
		PHL_PlaySound(sounds[sndHit07], CHN_EFFECTS);
510
		createEffect(1, l->x + (20 * l->dir), l->y);
511
		enemyDestroy(l->id);
512
		dead = 1;
513
	}else if (checkCollision(getHeroMask(), l->mask)) {
514
		heroStone();
515
		heroHit(15, l->x + 20);
516
	}
517
 
518
	if (dead == 0) {
519
		if (checkTileCollision(1, l->mask)) {
520
			createEffect(1, l->x + (20 * l->dir), l->y);
521
			enemyDestroy(l->id);
522
			dead = 1;
523
		}
524
 
525
		if (dead == 0) {
526
			if (l->mask.x > 640 || l->mask.x + l->mask.w <= 0) {
527
				enemyDestroy(l->id);
528
			}
529
		}
530
	}
531
}
532
 
533
void laserDraw(Laser* l)
534
{
535
	int dx = 0,
536
		dy = 480;
537
	if (l->dir == -1) {
538
		dx += 80;
539
	}
540
 
541
	PHL_DrawSurfacePart(l->x, l->y, dx + (((int)l->imageIndex) * 40), dy, 40, 40, images[imgMisc20]);
542
}
543
 
544
//Dragon Flame
545
void createFlame(int x, int y, int dir)
546
{
547
	int i;
548
	for (i = 0; i < MAX_ENEMIES; i++) {
549
		if (enemies[i] == NULL) {
550
			Enemy* e = malloc(sizeof *e);
551
			Flame* f = malloc(sizeof *f);
552
			f->id = i;
553
 
554
			f->x = x;
555
			f->y = y;
556
 
557
			f->dir = dir;
558
			f->timer = 60;
559
 
560
			f->imageIndex = 0;
561
 
562
			e->data = f;
563
			e->enemyStep = flameStep;
564
			e->enemyDraw = flameDraw;
565
			e->type = -1;
566
 
567
			enemies[i] = e;
568
			i = MAX_ENEMIES;
569
		}
570
	}
571
}
572
 
573
void flameStep(Flame* f)
574
{
575
	f->imageIndex += 0.25;
576
 
577
	if (f->timer > 0) {
578
		if (f->imageIndex >= 3) {
579
			f->imageIndex -= 3;
580
		}
581
	}
582
 
583
	f->timer -= 1;
584
 
585
	if (f->timer == 0) {
586
		f->imageIndex = 3;
587
	}
588
 
589
	//Hero Collision
590
	{
591
		Mask mask;
592
		mask.circle = mask.unused = 0;
593
		mask.x = f->x;
594
		mask.y = f->y + 16;
595
		mask.w = 120;
596
		mask.h = 18;
597
		if (f->dir == -1) {
598
			mask.x -= 120;
599
		}
600
 
601
		if (checkCollision(mask, getHeroMask()) == 1) {
602
			int centerX = mask.x + 60 - (60 * f->dir);
603
 
604
			//Hero is on ladder
605
			if (getHeroState() == 3) {
606
				centerX = herox;
607
			}
608
 
609
			heroHit(30, centerX);
610
		}
611
	}
612
 
613
	if (f->timer < 0 && f->imageIndex >= 6) {
614
		enemyDestroy(f->id);
615
	}
616
}
617
 
618
void flameDraw(Flame* f)
619
{
620
	int drawX = f->x,
621
		drawY = f->y;
622
 
623
	int cropX = 0,
624
		cropY = 0;
625
 
626
	if (f->dir == -1) {
627
		cropX += 720;
628
		drawX -= 120;
629
	}
630
 
631
	cropX += 120 * (int)f->imageIndex;
632
 
633
	while (cropX >= 600) {
634
		cropX -= 600;
635
		cropY += 40;
636
	}
637
 
638
	PHL_DrawSurfacePart(drawX, drawY, cropX, cropY, 120, 40, images[imgMisc6020]);
639
}
640
 
641
//Demon Rock
642
void createRock(int x, int y, int dir)
643
{
644
	int i;
645
	for (i = 0; i < MAX_ENEMIES; i++) {
646
		if (enemies[i] == NULL) {
647
			Enemy* e = malloc(sizeof *e);
648
			Rock* r = malloc(sizeof *r);
649
			r->id = i;
650
 
651
			r->x = x;
652
			r->y = y;
653
 
654
			r->vsp = -3;
655
			r->dir = dir;
656
 
657
			r->imageIndex = 0;
658
 
659
			e->data = r;
660
			e->enemyStep = rockStep;
661
			e->enemyDraw = rockDraw;
662
			e->type = -1;
663
 
664
			enemies[i] = e;
665
			i = MAX_ENEMIES;
666
		}
667
	}
668
}
669
 
670
void rockStep(Rock* r)
671
{
672
	char dead = 0;
673
 
674
	//Animate
675
	{
676
		r->imageIndex += 0.25 * r->dir;
677
		if (r->imageIndex >= 8) {
678
			r->imageIndex -= 8;
679
		}
680
		if (r->imageIndex < 0) {
681
			r->imageIndex += 8;
682
		}
683
	}
684
 
685
	//Setup Mask
686
	Mask mask;
687
	{
688
		mask.unused = mask.circle = 0;
689
		mask.x = r->x + 2;
690
		mask.y = r->y + 2;
691
		mask.w = 36;
692
		mask.h = 36;
693
	}
694
 
695
	int hsp = 3;
696
	double grav = 0.12;
697
 
698
	//Movement
699
	{
700
		r->y += r->vsp;
701
		r->vsp += grav;
702
 
703
		//Collide with floor
704
		{
705
			mask.y = r->y + 2;
706
 
707
			PHL_Rect collide = getTileCollision(1, mask);
708
			if (collide.x == -1) {
709
				collide = getTileCollision(3, mask);
710
			}
711
 
712
			if (collide.x != -1) {
713
				PHL_PlaySound(sounds[sndHit06], CHN_ENEMIES);
714
				r->y = collide.y - mask.h - 2;
715
				r->vsp = -3;
716
				mask.y = r->y + 2;
717
			}
718
		}
719
 
720
		r->x += hsp * r->dir;
721
 
722
		//Collide with wall
723
		{
724
			mask.x = r->x + 2;
725
 
726
			PHL_Rect collide = getTileCollision(1, mask);
727
 
728
			if (collide.x != -1) {
729
				dead = 1;
730
			}
731
		}
732
	}
733
 
734
	//Collision
735
	{
736
		//Hero collision
737
		if (checkCollision(mask, getHeroMask()) == 1) {
738
			heroHit(20, mask.x + (mask.w / 2));
739
		}
740
 
741
		//Weapon collision
742
		int i;
743
		for (i = 0; i < MAX_WEAPONS; i++) {
744
			if (weapons[i] != NULL) {
745
				if (weapons[i]->cooldown == 0) {
746
					if (checkCollision(mask, weapons[i]->weaponMask)) {
747
						weaponHit(weapons[i]);
748
						PHL_PlaySound(sounds[sndHit03], CHN_WEAPONS);
749
 
750
						i = MAX_WEAPONS;
751
					}
752
				}
753
			}
754
		}
755
	}
756
 
757
	//Destroy
758
	if (dead == 1) {
759
		createRockSmash(r->x + 20, r->y);
760
		enemyDestroy(r->id);
761
	}
762
}
763
 
764
void rockDraw(Rock* r)
765
{
766
	PHL_DrawSurfacePart(r->x, r->y, 320 + ((int)r->imageIndex * 40), 160, 40, 40, images[imgEnemies]);
767
}
768
 
769
//Air Stream
770
void createAir(int x, int y)
771
{
772
	int i;
773
	for (i = 0; i < MAX_ENEMIES; i++) {
774
		if (enemies[i] == NULL) {
775
			Enemy* e = malloc(sizeof *e);
776
			Air* a = malloc(sizeof *a);
777
			a->id = i;
778
 
779
			a->x = x;
780
			a->y = y;
781
 
782
			a->imageIndex = 0;
783
 
784
			e->data = a;
785
			e->enemyStep = airStep;
786
			e->enemyDraw = airDraw;
787
			e->type = -1;
788
 
789
			enemies[i] = e;
790
			i = MAX_ENEMIES;
791
		}
792
	}
793
}
794
 
795
//Air Puff
796
void airStep(Air* a)
797
{
798
	Mask mask;
799
	mask.circle = mask.unused = 0;
800
	mask.w = 36;
801
	mask.h = 30;
802
	mask.x = a->x + ((40 - mask.w) / 2);
803
 
804
	//Animate
805
	a->imageIndex += 0.5;
806
	if (a->imageIndex >= 2) {
807
		a->imageIndex -= 2;
808
	}
809
 
810
	//Movement
811
	a->y -= 6;
812
	mask.y = a->y + (40 - mask.h);
813
 
814
	//Collide with player
815
	if (getHeroState() != 2) {
816
		if (checkCollision(mask, getHeroMask())) {
817
			if (hasItem[27] == 0) {
818
				heroHit(10, mask.x + (mask.w / 2));
819
			}else{
820
				//Floating stuff
821
				if (getHeroVsp() > -5) {
822
					setHeroVsp(-5);
823
					setHeroOnground(0);
824
				}
825
			}
826
		}
827
	}
828
 
829
	//destroy if outside of room
830
	if (mask.y + mask.h < 0) {
831
		enemyDestroy(a->id);
832
	}
833
}
834
 
835
void airDraw(Air* a)
836
{
837
	PHL_DrawSurfacePart(a->x, a->y, (int)a->imageIndex * 40, 560, 40, 40, images[imgMisc20]);
838
}