Agora ele olha pra frente deitado
[Projeto-PCG.git] / shooter.cpp
blob3593f3d25e4c56291d7cc1fb79181c37bb30e5aa
1 #include <math.h>
2 #include "shooter.h"
3 #include "gravity.h"
4 #include "shot.h"
5 #include "shotmanager.h"
6 #include "usereventtype.h"
9 Shooter::Shooter(Game* agame, Ponto pos, Ponto speed) {
10 weapon = NULL;
11 setPosition(pos.x, pos.y);
12 setSpeed(speed.x, speed.y);
13 game = agame;
14 game->gravityManager->subscribe(this);
15 maxspeed.x = 3;
16 maxspeed.y = 20;
17 canfire = true;
18 realLeftfeet.x = -8;
19 realLeftfeet.y = 0;
20 realRightfeet.x = 8;
21 realRightfeet.y = 0;
22 bodyAngle = 0;
23 angleTime = 0;
24 feetTime = 0;
25 direction = 1;
26 addToAngle = 0;
27 crawl = false;
30 void Shooter::equip(Weapon* aweapon) {
31 //desequipar a anterior aqui mais tarde
32 weapon = aweapon;
35 static void allowFireFunc(void* param) {
36 ((Shooter*)param)->allowFire();
39 static Uint32 allowFireCallback(Uint32 interval, void *param) {
40 SDL_Event event;
41 SDL_UserEvent userevent;
42 userevent.type = SDL_USEREVENT;
43 userevent.code = FUNCTIONCALL;
44 userevent.data1 = (void*)allowFireFunc;
45 userevent.data2 = (void*)param;
47 event.type = SDL_USEREVENT;
48 event.user = userevent;
50 SDL_PushEvent(&event);
52 return 0;
55 void Shooter::allowFire() {
56 canfire = true;
59 void Shooter::fire() {
60 if (!canfire || weapon == NULL)
61 return;
62 SDL_AddTimer(weapon->fireRate*game->rate,allowFireCallback,this);
63 canfire = false;
64 Ponto tiplinha = weapon->getTip();
65 double angle = getAngle();
66 double cosAngle = cos(angle);
67 double sinAngle = sin(angle);
68 Ponto tip;
69 tip.x = (cosAngle*tiplinha.x+sinAngle*tiplinha.y);
70 tip.y = -(sinAngle*tiplinha.x-cosAngle*tiplinha.y);
71 Ponto leftfeet = leftFeet();
72 Ponto rightfeet = rightFeet();
73 weapon->position = pescoco();
74 weapon->position.x = direction*weapon->position.x;
75 weapon->position.y += + std::min(-rightfeet.y,-leftfeet.y);
76 weapon->position = weapon->position + getPosition();
77 weapon->fire(tip,angle,this);
81 Ponto Shooter::leftFeet() {
82 Ponto ret;
83 Ponto hips = cintura();
84 Ponto feetFromHips = realLeftfeet - hips;
85 double cosTheta = cos(bodyAngle);
86 double sinTheta = sin(bodyAngle);
87 ret.x = (cosTheta*feetFromHips.x-sinTheta*feetFromHips.y);
88 ret.y = (sinTheta*feetFromHips.x+cosTheta*feetFromHips.y);
89 return ret + hips;
92 Ponto Shooter::rightFeet() {
93 Ponto ret;
94 Ponto hips = cintura();
95 Ponto feetFromHips = realRightfeet - hips;
96 double cosTheta = cos(bodyAngle);
97 double sinTheta = sin(bodyAngle);
98 ret.x = (cosTheta*feetFromHips.x-sinTheta*feetFromHips.y);
99 ret.y = (sinTheta*feetFromHips.x+cosTheta*feetFromHips.y);
100 return ret + hips;
103 Ponto Shooter::imaginaryLeftfeet() {
104 int t = feetTime;
105 Ponto pe(0,0);
106 if (onGround && abs(getSpeedX()) < 0.05) {
107 pe.x = -8;
108 pe.y = 0;
110 else if (onGround) {
111 if (getSpeedX() < 0)
112 t = -t;
113 t *= 1.0+abs(getSpeedX());
114 pe.x = 6*cos(PI+t/30.0);
115 pe.y = 2.5*sin(PI+t/30.0)-2.5;
117 else if (bypass) {
118 pe.x = -4;
119 pe.y = -19;
121 else {
122 pe.x = -4;
123 pe.y = -19;
125 return pe;
128 Ponto Shooter::imaginaryRightfeet() {
129 int t = feetTime;
130 Ponto pe(0,0);
131 if (onGround && abs(getSpeedX()) < 0.05) {
132 pe.x = 8;
133 pe.y = 0;
135 else if (onGround) {
136 if (getSpeedX() < 0)
137 t = -t;
138 t *= 1.0+abs(getSpeedX());
139 pe.x = 6*cos(t/30.0);
140 pe.y = 2.5*sin(t/30.0)-2.5;
142 else if (bypass) {
143 pe.x = 4;
144 pe.y = -19;
146 else {
147 pe.x = 4;
148 pe.y = -19;
150 return pe;
153 double Shooter::imaginaryBodyAngle() {
154 int t = angleTime;
155 if (dead)
156 return 3*PI/2;
157 if ((bypass && !onGround) || bodyAngle > PI/2) {
158 return 2*PI*((t % 360) / 360.0) + addToAngle;
161 if (crawl)
162 return addToAngle + PI/2;
163 return addToAngle;
166 void Shooter::updateFeetTime() {
167 if (onGround && abs(getSpeedX()) >= 0.05)
168 feetTime++;
169 else
170 feetTime = 0;
173 void Shooter::updateAngleTime() {
174 if ((bypass && !onGround) || bodyAngle > PI/2)
175 angleTime+= 10;
176 else
177 angleTime = 0;
181 void Shooter::animate() {
182 updateFeetTime();
183 updateAngleTime();
184 Ponto il = imaginaryLeftfeet();
185 Ponto ir = imaginaryRightfeet();
187 realLeftfeet.x += closerToZero(sign(il.x - realLeftfeet.x)*0.5, il.x - realLeftfeet.x);
188 realLeftfeet.y += closerToZero(sign(il.y - realLeftfeet.y)*0.5,il.y - realLeftfeet.y);
190 realRightfeet.x += closerToZero(sign(ir.x - realRightfeet.x)*0.5,ir.x - realRightfeet.x);
191 realRightfeet.y += closerToZero(sign(ir.y - realRightfeet.y)*0.5,ir.y - realRightfeet.y);
193 double iangle = imaginaryBodyAngle();
194 double dif = iangle - bodyAngle;
195 if (dif > PI)
196 dif = dif - 2*PI;
197 if (dif < -PI)
198 dif = dif + 2*PI;
199 bodyAngle += closerToZero(sign(dif)*0.2,dif);
200 bodyAngle = fmod(bodyAngle,2*PI);
201 if (abs(addToAngle) > 0.2)
202 addToAngle += -sign(addToAngle)*0.2;
203 else
204 addToAngle = 0;
205 double dl = distance(il,realLeftfeet);
206 double dr = distance(ir,realRightfeet);
210 Ponto Shooter::leftArm(bool w) {
211 if (!w || (weapon == NULL)) {
212 Ponto braco(-10,-30);
213 return braco;
215 else
216 return weapon->getLeftHand();
219 Ponto Shooter::rightArm(bool w) {
220 if (!w || (weapon == NULL)) {
221 Ponto braco(10,-30);
222 return braco;
224 else
225 return weapon->getRightHand();
228 Ponto Shooter::cintura() {
229 Ponto c(0,-40);
230 return c;
233 Ponto Shooter::pescoco() {
234 Ponto hips = cintura();
235 Ponto neck (0,-30); //em relaçao a cintura
236 Ponto ret;
237 double cosTheta = cos(bodyAngle);
238 double sinTheta = sin(bodyAngle);
239 ret.x = (cosTheta*neck.x-sinTheta*neck.y);
240 ret.y = (sinTheta*neck.x+cosTheta*neck.y);
241 return ret + hips;
244 Ponto Shooter::cabeca() {
245 Ponto hips = cintura();
246 Ponto head(0,-11 -30); //-30 é pelo pescoco
247 Ponto ret;
248 double cosTheta = cos(bodyAngle);
249 double sinTheta = sin(bodyAngle);
250 ret.x = (cosTheta*head.x-sinTheta*head.y);
251 ret.y = (sinTheta*head.x+cosTheta*head.y);
252 return ret + hips;
255 double areaTriangle(double a, double b, double c) {
256 if (a < b) std::swap(a,b);
257 if (a < c) std::swap(a,c);
258 if (b < c) std::swap(b,c);
259 //a >= b >= c
261 return sqrt((a+(b+c))*(c-(a-b))*(c+(a-b))*(a+(b-c)))/4.0;
264 //retorna cotovelo em relacao ao ombro, usa matematica levemente pesada, cuidado ao mexer
265 Ponto Shooter::getJunta(Ponto superior, Ponto inferior,
266 double tamanhoSuperior, double tamanhoInferior) {
267 double a = tamanhoSuperior;
268 double b = tamanhoInferior;
269 double d = distance(superior,inferior);
270 double area = areaTriangle(a,b,d);
271 double ylinha = 2.0*area/d;
272 double xlinha = sqrt(a*a-ylinha*ylinha);
274 double sinTheta = (inferior.y-superior.y)/d;
275 double cosTheta = (inferior.x-superior.x)/d;
277 Ponto ret;
278 ret.x = (cosTheta*xlinha-sinTheta*ylinha);
279 ret.y = (sinTheta*xlinha+cosTheta*ylinha);
280 return ret;
283 //cuidado, distancia da arma nao pode exceder tamanhoBraco+tamanhoAntebraco
284 double Shooter::tamanhoBraco() {
285 return 23.0;
288 double Shooter::tamanhoAntebraco() {
289 return 16.0;
292 double Shooter::tamanhoCoxa() {
293 return 20.0;
296 double Shooter::tamanhoPerna() {
297 return 22.0;
300 double Shooter::getAngle() {
301 Ponto leftfeet = leftFeet();
302 Ponto rightfeet = rightFeet();
303 Ponto gameneck = pescoco() + getPosition();
304 gameneck.y += std::min(-rightfeet.y,-leftfeet.y);
305 double hyp = sqrt((aim.x-gameneck.x)*(aim.x-gameneck.x) +
306 (aim.y-gameneck.y)*(aim.y-gameneck.y));
307 if (aim.y <= gameneck.y)
308 return -acos((-aim.x+gameneck.x)/hyp);
309 else
310 return acos((-aim.x+gameneck.x)/hyp);
313 void Shooter::desenha() {
314 glPushMatrix();
315 glTranslatef(getX(),getY(),0);
316 glScalef(direction,1,1);
317 //getCollision().desenha();
318 Ponto leftfeet = leftFeet();
319 Ponto rightfeet = rightFeet();
320 glTranslatef(0,std::min(-rightfeet.y,-leftfeet.y),0);
321 Ponto hips = cintura();
322 Ponto leftarm = leftArm(true);
323 Ponto rightarm = rightArm(true);
324 Ponto neck = pescoco();
325 Ponto rightknee = getJunta(rightfeet,hips,tamanhoPerna(),tamanhoCoxa()) + rightfeet;
326 Ponto leftknee = getJunta(leftfeet,hips,tamanhoPerna(),tamanhoCoxa()) + leftfeet;
327 glBegin(GL_LINES);
328 glVertex3f(hips.x,hips.y,0);
329 glVertex3f(neck.x,neck.y,0);
331 glVertex3f(leftfeet.x,leftfeet.y,0);
332 glVertex3f(leftknee.x,leftknee.y,0);
334 glVertex3f(leftknee.x,leftknee.y,0);
335 glVertex3f(hips.x,hips.y,0);
337 glVertex3f(rightfeet.x,rightfeet.y,0);
338 glVertex3f(rightknee.x,rightknee.y,0);
340 glVertex3f(rightknee.x,rightknee.y,0);
341 glVertex3f(hips.x,hips.y,0);
342 glEnd();
343 Ponto rightelbow = getJunta(neck,rightarm+neck,tamanhoBraco(),tamanhoAntebraco());
344 Ponto leftelbow = getJunta(neck,leftarm+neck,tamanhoBraco(),tamanhoAntebraco());
345 glPushMatrix();
346 glTranslatef(neck.x,neck.y,0);
347 glScalef(direction,direction,1);
348 glRotatef(direction*getAngle()*180.0/PI,0,0,-1);
349 glBegin(GL_LINES);
350 glVertex3f(0,0,-1);
351 glVertex3f(leftelbow.x,leftelbow.y,-1);
352 glVertex3f(leftelbow.x,leftelbow.y,-1);
353 glVertex3f(leftarm.x,leftarm.y,-1);
355 glVertex3f(0,0,1);
356 glVertex3f(rightelbow.x,rightelbow.y,1);
357 glVertex3f(rightelbow.x,rightelbow.y,1);
358 glVertex3f(rightarm.x,rightarm.y,1);
359 glEnd();
360 if (weapon != NULL) weapon->desenha();
361 glPopMatrix();
362 Ponto head = cabeca();
363 glPushMatrix();
364 glTranslatef(head.x,head.y,0);
365 drawCircle(11,30);
366 glPopMatrix();
367 drawEquipment();
368 glPopMatrix();
372 Linha Shooter::getBaseLine() {
373 Ponto left(-8,0);
374 Ponto right(8,0);
375 return Linha(left, right);
378 Polygon Shooter::getCollision() {
379 Polygon poly;
380 Ponto leftfeet = leftFeet();
381 Ponto rightfeet = rightFeet();
382 double deslocy = std::min(-rightfeet.y,-leftfeet.y);
383 Ponto hips = cintura();
384 Ponto leftarm = leftArm(false);
385 Ponto rightarm = rightArm(false);
386 Ponto head = cabeca();
388 leftfeet.y += deslocy;
389 rightfeet.y += deslocy;
390 head.y += deslocy;
391 hips.y += deslocy;
392 leftarm.y += deslocy;
393 rightarm.y += deslocy;
395 Linha a(leftfeet,rightfeet);
396 Linha b(rightfeet,hips);
397 Linha c(hips,rightarm);
398 Linha d(rightarm,head);
399 Linha e(head,leftarm);
400 Linha f(leftarm,hips);
401 Linha g(hips,leftfeet);
402 poly.addLinha(a);
403 poly.addLinha(b);
404 poly.addLinha(c);
405 poly.addLinha(d);
406 poly.addLinha(e);
407 poly.addLinha(f);
408 poly.addLinha(g);
409 return poly;
412 void Shooter::setAim(double x, double y) {
413 aim.x = x;
414 aim.y = y;