1 /*
2  * fireball.c - fire ball
3  * Copyright (C) 2010  Alexandre Martins <alemartf(at)gmail(dot)com>
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 along
16  * with this program; if not, write to the Free Software Foundation, Inc.,
17  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18  */
19 
20 #include "fireball.h"
21 #include "../../core/util.h"
22 #include "../../core/soundfactory.h"
23 #include "../../scenes/level.h"
24 
25 /* fireball class */
26 typedef struct fireball_t fireball_t;
27 struct fireball_t {
28     item_t item; /* base class */
29     void (*run)(item_t*,brick_list_t*);
30 };
31 
32 static void fireball_init(item_t *item);
33 static void fireball_release(item_t* item);
34 static void fireball_update(item_t* item, player_t** team, int team_size, brick_list_t* brick_list, item_list_t* item_list, enemy_list_t* enemy_list);
35 static void fireball_render(item_t* item, v2d_t camera_position);
36 
37 static void fireball_set_behavior(item_t *fireball, void (*behavior)(item_t*,brick_list_t*));
38 
39 static void falling_behavior(item_t *fireball, brick_list_t *brick_list);
40 static void disappearing_behavior(item_t *fireball, brick_list_t *brick_list);
41 static void smallfire_behavior(item_t *fireball, brick_list_t *brick_list);
42 
43 
44 
45 /* public methods */
fireball_create()46 item_t* fireball_create()
47 {
48     item_t *item = mallocx(sizeof(fireball_t));
49 
50     item->init = fireball_init;
51     item->release = fireball_release;
52     item->update = fireball_update;
53     item->render = fireball_render;
54 
55     return item;
56 }
57 
58 
59 /* private methods */
fireball_set_behavior(item_t * fireball,void (* behavior)(item_t *,brick_list_t *))60 void fireball_set_behavior(item_t *fireball, void (*behavior)(item_t*,brick_list_t*))
61 {
62     fireball_t *me = (fireball_t*)fireball;
63     me->run = behavior;
64 }
65 
fireball_init(item_t * item)66 void fireball_init(item_t *item)
67 {
68     item->obstacle = FALSE;
69     item->bring_to_back = FALSE;
70     item->preserve = FALSE;
71     item->actor = actor_create();
72 
73     fireball_set_behavior(item, falling_behavior);
74     actor_change_animation(item->actor, sprite_get_animation("SD_FIREBALL", 0));
75 }
76 
77 
78 
fireball_release(item_t * item)79 void fireball_release(item_t* item)
80 {
81     actor_destroy(item->actor);
82 }
83 
84 
85 
fireball_update(item_t * item,player_t ** team,int team_size,brick_list_t * brick_list,item_list_t * item_list,enemy_list_t * enemy_list)86 void fireball_update(item_t* item, player_t** team, int team_size, brick_list_t* brick_list, item_list_t* item_list, enemy_list_t* enemy_list)
87 {
88     int i;
89     actor_t *act = item->actor;
90     fireball_t *me = (fireball_t*)item;
91 
92     /* hit the player */
93     for(i=0; i<team_size; i++) {
94         player_t *player = team[i];
95         if(!player->dying && actor_collision(act, player->actor)) {
96             item->state = IS_DEAD;
97             if(player->shield_type != SH_FIRESHIELD)
98                 player_hit(player);
99         }
100     }
101 
102     /* my behavior */
103     me->run(item, brick_list);
104 }
105 
106 
fireball_render(item_t * item,v2d_t camera_position)107 void fireball_render(item_t* item, v2d_t camera_position)
108 {
109     actor_render(item->actor, camera_position);
110 }
111 
112 
113 /* private behaviors */
falling_behavior(item_t * fireball,brick_list_t * brick_list)114 void falling_behavior(item_t *fireball, brick_list_t *brick_list)
115 {
116     int i, n;
117     float sqrsize = 2, diff = -2;
118     actor_t *act = fireball->actor;
119     brick_t *down;
120 
121     /* movement & animation */
122     act->speed.x = 0.0f;
123     act->mirror = (act->speed.y < 0.0f) ? IF_VFLIP : IF_NONE;
124     actor_move(act, actor_particle_movement(act, level_gravity()));
125     actor_change_animation(act, sprite_get_animation("SD_FIREBALL", 0));
126 
127     /* collision detection */
128     actor_corners(act, sqrsize, diff, brick_list, NULL, NULL, NULL, NULL, &down, NULL, NULL, NULL);
129     actor_handle_clouds(act, diff, NULL, NULL, NULL, NULL, &down, NULL, NULL, NULL);
130     if(down) {
131         /* I have just touched the ground */
132         fireball_set_behavior(fireball, disappearing_behavior);
133         sound_play( soundfactory_get("fire2") );
134 
135         /* create small fire balls */
136         n = 2 + random(3);
137         for(i=0; i<n; i++) {
138             item_t *obj = level_create_item(IT_FIREBALL, act->position);
139             fireball_set_behavior(obj, smallfire_behavior);
140             obj->actor->speed = v2d_new(((float)i/(float)n)*400.0f-200.0f, -120.0f-random(240.0f));
141         }
142     }
143 }
144 
disappearing_behavior(item_t * fireball,brick_list_t * brick_list)145 void disappearing_behavior(item_t *fireball, brick_list_t *brick_list)
146 {
147     actor_t *act = fireball->actor;
148 
149     actor_change_animation(act, sprite_get_animation("SD_FIREBALL", 1));
150     if(actor_animation_finished(act))
151         fireball->state = IS_DEAD;
152 }
153 
smallfire_behavior(item_t * fireball,brick_list_t * brick_list)154 void smallfire_behavior(item_t *fireball, brick_list_t *brick_list)
155 {
156     float sqrsize = 2, diff = -2;
157     actor_t *act = fireball->actor;
158     brick_t *down;
159 
160     /* movement & animation */
161     actor_move(act, actor_particle_movement(act, level_gravity()));
162     actor_change_animation(act, sprite_get_animation("SD_FIREBALL", 2));
163 
164     /* collision detection */
165     actor_corners(act, sqrsize, diff, brick_list, NULL, NULL, NULL, NULL, &down, NULL, NULL, NULL);
166     actor_handle_clouds(act, diff, NULL, NULL, NULL, NULL, &down, NULL, NULL, NULL);
167     if(down && act->speed.y > 0.0f)
168         fireball->state = IS_DEAD;
169 }
170 
171