1/*
2 Copyright (C) 1998-2001 Andreas Zehender <az@azweb.de>
3 Copyright (C) 2006-2008 Dirk Rathlev <dirkrathlev@gmx.de>
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
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18*/
19
20#include "sprites.h"
21
22#include <math.h>
23
24#include <QGraphicsScene>
25
26#include <kdebug.h>
27
28#include "mathroutines.h"
29
30SunSprite::SunSprite(QSvgRenderer* svg, const QString& element)
31 :SimpleSprite(svg, element)
32{
33 setZValue(0);
34}
35
36
37PowerupSprite::PowerupSprite(QSvgRenderer* svg, const QString& element, int t,
38 double lifetime)
39 :SimpleSprite(svg, element)
40{
41 time=lifetime;
42 mtype=t;
43}
44
45ShipSprite::ShipSprite(QSvgRenderer* svg, const QString& element, int pn)
46 :MobileSprite(svg, element,pn)
47{
48 hitpoints=MAX_HP;
49 energy=MAX_ENERGY;
50 explosion=-1;
51 setZValue(-20);
52 rotation=0;
53 bulletPowerups=0;
54 minePowerups=0;
55 angle = 0;
56}
57
58void ShipSprite::setRotation(double r)
59{
60 rotation=r;
61 if(rotation<0)
62 rotation-=((int)(rotation/(2*M_PI))-1)*2*M_PI;
63 if(rotation>=2*M_PI)
64 rotation-=(int)(rotation/(2*M_PI))*2*M_PI;
65
66 translate(center().x(),center().y());
67 rotate(-(rotation-angle)*57.3);
68 translate(-center().x(),-center().y());
69 angle = rotation;
70}
71
72void ShipSprite::forward(double mult)
73{
74 MobileSprite::forward(mult);
75 if(explosion>0)
76 {
77 explosion--;
78 if(explosion==0)
79 hide();
80 }
81 if(reloadBulletTime>0)
82 reloadBulletTime-=mult;
83 if(reloadMineTime>0)
84 reloadMineTime-=mult;
85}
86
87void ShipSprite::forward(double mult,int fr)
88{
89 MobileSprite::forward(mult,fr);
90 rotation=fr/ROTNUM*M_PI*2;
91 if(explosion>0)
92 {
93 explosion--;
94 if(explosion==0)
95 hide();
96 }
97 if(reloadBulletTime>0)
98 reloadBulletTime-=mult;
99 if(reloadMineTime>0)
100 reloadMineTime-=mult;
101}
102
103void ShipSprite::calculateGravityAndEnergy(double gravity,double sunEnergy,
104 double mult)
105{
106 double nx,ny,ex,ey,abs_2,phi,sq,eg;
107
108 if(!stopped)
109 {
110 ex=x()+center().x()-scene()->width()/2.0;
111 ey=y()+center().y()-scene()->height()/2.0;
112
113 abs_2=ex*ex+ey*ey;
114 sq=sqrt(abs_2);
115
116 if ( explodes() && (sq<20) )
117 stopped = true;
118 else
119 {
120 nx=ex/sq;
121 ny=ey/sq;
122 eg=gravity*mult;
123 setVelocity(xVelocity()-eg*nx/abs_2,
124 yVelocity()-eg*ny/abs_2);
125 if(hitpoints!=0)
126 {
127 if(energy<99.8)
128 {
129 phi=rectToAngle(nx,ny);
130 energy+=fabs(sunEnergy*mult/(abs_2)*cos(phi+rotation));
131 }
132 }
133 }
134 }
135}
136
137void ShipSprite::rotateRight(double rotationEnergyNeed,double rotationSpeed)
138{
139 if(energy>rotationEnergyNeed)
140 {
141 energy-=rotationEnergyNeed;
142 setRotation(rotation-rotationSpeed);
143 }
144}
145
146void ShipSprite::rotateLeft(double rotationEnergyNeed,double rotationSpeed)
147{
148 if(energy>rotationEnergyNeed)
149 {
150 energy-=rotationEnergyNeed;
151 setRotation(rotation+rotationSpeed);
152 }
153}
154
155BulletSprite::BulletSprite(QSvgRenderer* svg, const QString& element, int pn,double lifetime)
156 :MobileSprite(svg,element,pn)
157{
158 setZValue(-10);
159 time=lifetime;
160}
161
162void BulletSprite::forward(double mult)
163{
164 MobileSprite::forward(mult);
165 time-=mult;
166}
167
168void BulletSprite::forward(double mult,int fr)
169{
170 MobileSprite::forward(mult,fr);
171 time-=mult;
172}
173
174MineSprite::MineSprite(QSvgRenderer* svg, const QList<QString>& animation, const QList<QString>& exploanimation, int pn,double atime,double f)
175 :AnimatedSprite(svg, animation,pn)
176{
177 exploframes = exploanimation;
178 activateTime=atime;
179 setZValue(-25);
180 fuel=f;
181 explosiontime=0;
182 timeToGo=0.0;
183 expl=false;
184 active=false;
185}
186
187void MineSprite::explode()
188{
189 setAnimation(exploframes);
190 timeToGo=frameCount();
191 expl=true;
192 explosiontime=0.0;
193 setZValue(-8);
194 setFuel(0.0);
195}
196
197void MineSprite::forward(double mult)
198{
199 if(active)
200 {
201 if(expl)
202 {
203 explosiontime+=mult;
204 if(explosiontime>(timeToGo-0.001))
205 explosiontime=timeToGo-0.01;
206 setFrame((int)explosiontime);
207 }
208 }
209 else
210 {
211 activateTime-=(double)mult;
212 if(activateTime<0.0)
213 {
214 active=true;
215 setFrame(1);
216 }
217 }
218 if(fuel<0.001)
219 MobileSprite::forward(mult);
220}
221
222void MineSprite::calculateGravity(double gravity,double mult)
223{
224 double abs_2,nx,ny,ex,ey,sq,eg;
225
226 if(!stopped)
227 {
228 ex=x()-scene()->width()/2.0;
229 ey=y()-scene()->height()/2.0;
230
231 abs_2=ex*ex+ey*ey;
232 sq=sqrt(abs_2);
233 nx=ex/sq;
234 ny=ey/sq;
235 eg=gravity*mult;
236 if(fuel<0.001)
237 setVelocity(xVelocity()-eg*nx/abs_2,
238 yVelocity()-eg*ny/abs_2);
239 else
240 fuel-=eg/abs_2;
241 }
242}
243
244ExplosionSprite::ExplosionSprite(QSvgRenderer* svg, const QList<QString>& animation, MobileSprite *sp)
245 :AnimatedSprite(svg, animation)
246{
247 over=false;
248 setZValue(5);
249 obj=sp;
250 timeToGo = frameCount();
251 time=0;
252
253 setPos(QPointF(sp->x(),sp->y()));
254}
255
256void ExplosionSprite::forward(double mult)
257{
258 int of=frame();
259 setPos(QPointF(obj->x(),obj->y()));
260 time+=mult;
261
262 if(time>=timeToGo)
263 {
264 over=true;
265 hide();
266 }
267 else
268 if((int)time!=of)
269 setFrame((int)time);
270}
271