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