1 /*
2  * bumper.c - bumper
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 "bumper.h"
21 #include "../../core/util.h"
22 #include "../../core/audio.h"
23 #include "../../core/soundfactory.h"
24 #include "../player.h"
25 #include "../item.h"
26 #include "../enemy.h"
27 #include "../brick.h"
28 
29 /* bumper class */
30 typedef struct bumper_t bumper_t;
31 struct bumper_t {
32     item_t item; /* base class */
33     int getting_hit;
34 };
35 
36 static void bumper_init(item_t *item);
37 static void bumper_release(item_t* item);
38 static void bumper_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);
39 static void bumper_render(item_t* item, v2d_t camera_position);
40 
41 static void bump(item_t *bumper, player_t *player);
42 
43 
44 /* public methods */
bumper_create()45 item_t* bumper_create()
46 {
47     item_t *item = mallocx(sizeof(bumper_t));
48 
49     item->init = bumper_init;
50     item->release = bumper_release;
51     item->update = bumper_update;
52     item->render = bumper_render;
53 
54     return item;
55 }
56 
57 
58 /* private methods */
bumper_init(item_t * item)59 void bumper_init(item_t *item)
60 {
61     bumper_t *me = (bumper_t*)item;
62 
63     item->obstacle = FALSE;
64     item->bring_to_back = TRUE;
65     item->preserve = TRUE;
66     item->actor = actor_create();
67 
68     me->getting_hit = FALSE;
69     actor_change_animation(item->actor, sprite_get_animation("SD_BUMPER", 0));
70 }
71 
72 
73 
bumper_release(item_t * item)74 void bumper_release(item_t* item)
75 {
76     actor_destroy(item->actor);
77 }
78 
79 
80 
bumper_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)81 void bumper_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)
82 {
83     bumper_t *me = (bumper_t*)item;
84     actor_t *act = item->actor;
85     int i;
86 
87     for(i=0; i<team_size; i++) {
88         player_t *player = team[i];
89         if(!player->dying && actor_pixelperfect_collision(player->actor, act)) {
90             if(!me->getting_hit) {
91                 me->getting_hit = TRUE;
92                 actor_change_animation(act, sprite_get_animation("SD_BUMPER", 1));
93                 sound_play( soundfactory_get("bumper") );
94                 bump(item, player);
95             }
96         }
97     }
98 
99     if(me->getting_hit) {
100         if(actor_animation_finished(act)) {
101             me->getting_hit = FALSE;
102             actor_change_animation(act, sprite_get_animation("SD_BUMPER", 0));
103         }
104     }
105 }
106 
107 
bumper_render(item_t * item,v2d_t camera_position)108 void bumper_render(item_t* item, v2d_t camera_position)
109 {
110     actor_render(item->actor, camera_position);
111 }
112 
113 /* misc */
bump(item_t * bumper,player_t * player)114 void bump(item_t *bumper, player_t *player)
115 {
116     /* law of conservation of linear momentum */
117     float ec = 1.0f; /* (coefficient of restitution == 1.0) => elastic collision */
118     float mass_player = 1.0f;
119     float mass_bumper = 10000.0f;
120     float mass_ratio = mass_bumper / mass_player;
121     v2d_t v0, approximation_speed, separation_speed;
122     actor_t *act = bumper->actor;
123 
124 
125 
126     v0 = player->actor->speed; /* initial speed of the player */
127     v0.x = (v0.x < 0) ? min(-300, v0.x) : max(300, v0.x);
128 
129 
130 
131     approximation_speed = v2d_multiply(
132         v2d_normalize(
133             v2d_subtract(act->position, player->actor->position)
134         ),
135         v2d_magnitude(v0)
136     );
137 
138     separation_speed = v2d_multiply(approximation_speed, ec);
139 
140 
141 
142     player->actor->speed = v2d_multiply(
143         v2d_add(
144             v0,
145             v2d_multiply(separation_speed, -mass_ratio)
146         ),
147         1.0f / (mass_ratio + 1.0f)
148     );
149 
150     act->speed = v2d_multiply(
151         v2d_add(v0, separation_speed),
152         1.0f / (mass_ratio + 1.0f)
153     );
154 
155 
156 
157     /* cute stuff */
158     player->flying = FALSE;
159     player->landing = FALSE;
160     player->climbing = FALSE;
161     player->spring = FALSE;
162 }
163 
164