1 /*
2   Copyright (C) 2009 Facundo Domínguez
3 
4   This file is part of Spacejunk.
5 
6   Spacejunk is free software: you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation, either version 3 of the License, or
9   (at your option) any later version.
10 
11   Foobar is distributed in the hope that it will be useful,
12   but WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   GNU General Public License for more details.
15 
16   You should have received a copy of the GNU General Public License
17   along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
18 */
19 
20 #include "starship.h"
21 #include <math.h>
22 #include "runtimeopts.h"
23 #include "soundcollection.h"
24 
25 #include <iostream>
26 #include <iomanip>
27 
28 using namespace std;
29 
30 extern SoundCollection * sounds;
31 
32 // This is an interesting velocity (-sqrt(G*2.5e14),0)
Starship(const string & graphicid,Vector2d pos,Vector2d vel,real m,real w)33 Starship::Starship(const string & graphicid,Vector2d pos,Vector2d vel,real m,real w)
34         :GameBody(graphicid,pos,vel,m,w),GraphicSeq(&flame), power(false), flame("flame") {
35     maxFuel=timeToFuel(1000);
36     fuel=maxFuel*0.8;
37     shipMass=mass;
38     mass+=fuel;
39     setAngle(getAngle());
40     flame.setFrame(flame.getImageCount());
41     initcount=0;
42 };
43 
turn_on_engine()44 void Starship::turn_on_engine() {
45     if (power || fuel<=0)
46         return;
47     power=true;
48     hold=true;
49     setFrameSequence(0,flame.getImageCount()-1,false,true);
50     if (sounds) {
51         sounds->engineinit.play();
52         initcount=150;
53     }
54 }
55 
turn_off_engine()56 void Starship::turn_off_engine() {
57     if (!power)
58         return;
59     power=false;
60     hold=false;
61     setFrameSequence(flame.getImageCount()-1,0,false,false);
62     if (sounds) {
63         /*if (initcount)*/
64         sounds->engineinit.stop();
65         /*else*/
66         sounds->engine.stop();
67         sounds->engineend.play();
68     }
69 }
70 
71 
72 //#define ANGLE_ACC 0.00005
73 #define ANGLE_VEL 0.5
74 
75 // Velocity at which the fuel is fired
76 #define FUEL_VEL 3
77 
78 // Rate of mass of fuel burned
79 #define MASS_PER_MILLISECOND 0.025
80 
turn_left()81 void Starship::turn_left() {
82     w=-ANGLE_VEL;
83 }
84 
turn_right()85 void Starship::turn_right() {
86     w=ANGLE_VEL;
87 }
88 
stop_turning()89 void Starship::stop_turning() {
90     w=0;
91 }
92 
setAngle(real a)93 void Starship::setAngle(real a) {
94     real x,y;
95     sincos((a-90)*M_PI/180,&y,&x);
96     dir.x=x;
97     dir.y=y;
98     GameBody::setAngle(a);
99 };
100 
timeToFuel(real delta)101 real Starship::timeToFuel(real delta) {
102     return MASS_PER_MILLISECOND*delta;
103 };
104 
fuelToTime(real fuel)105 real Starship::fuelToTime(real fuel) {
106     return fuel/MASS_PER_MILLISECOND;
107 };
108 
stepShip(int delta)109 void Starship::stepShip(int delta) {
110     stepSeq(delta);
111     if (power) {
112         real tempfuel=timeToFuel(delta);
113         real oldfuel=fuel/maxFuel;
114         if (fuel<=tempfuel) {
115             setFuel(0);
116             turn_off_engine();
117         } else
118             setFuel(getFuel()-tempfuel);
119         if (sounds && oldfuel>=0.25 && 0.25>fuel/maxFuel)
120             sounds->lowFuel.play(1);
121         if (initcount>0 && sounds) {
122             if (initcount<=int(delta)) {
123                 initcount=0;
124                 sounds->engine.play(-1);
125             } else
126                 initcount-=delta;
127         }
128     }
129 }
130 
getDirection()131 Vector2d Starship::getDirection() {
132     return dir;
133 }
134 
getAcceleration(real delta)135 Vector2d Starship::getAcceleration(real delta) {
136     if (power) {
137         if (fuel>0) {
138             real tempfuel=timeToFuel(delta);
139             if (fuel<tempfuel) {
140                 tempfuel=fuel;
141                 delta=fuelToTime(fuel);
142             }
143             real temp=MASS_PER_MILLISECOND/(mass-delta*MASS_PER_MILLISECOND)*FUEL_VEL;
144             return dir*temp;
145         };
146     }
147     return Vector2d();
148 }
149 
saveState()150 void Starship::saveState() {
151     GameBody::saveState();
152 }
153 
clone()154 PhysicBody * Starship::clone() {
155     Starship *s=new Starship(*this);
156     s->seqg=&s->flame;
157     return s;
158 };
159 
copy(PhysicBody * pb) const160 void Starship::copy(PhysicBody * pb) const {
161     Starship *s=dynamic_cast<Starship*>(pb);
162     *s=*this;
163     s->seqg=&s->flame;
164 };
165 
collectTrash(GameBody * t)166 void Starship::collectTrash(GameBody* t) {
167     collected.push_front(TrashData(t->mass));
168     mass+=t->mass;
169 };
170 
popTrash()171 TrashData Starship::popTrash() {
172     TrashData temp=collected.front();
173     collected.pop_front();
174     mass-=temp.mass;
175     return temp;
176 };
177 
getTrashCount()178 int Starship::getTrashCount() {
179     return collected.size();
180 };
181 
draw(int x,int y,real zoom,real angle)182 void Starship::draw(int x,int y,real zoom,real angle) {
183     flame.draw(int(x-dir.x*(getWidth()+7)*zoom),int(y-dir.y*(getWidth()+7)*zoom),zoom,angle);
184     GameBody::draw(x,y,zoom,angle);
185 }
186 
setFuel(real fuel)187 void Starship::setFuel(real fuel) {
188     mass -= this->fuel;
189     this->fuel = fuel;
190     mass += fuel;
191 }
192 
setFuelNoMass(real fuel)193 void Starship::setFuelNoMass(real fuel) {
194     this->fuel = fuel;
195 }
196 
getFuel()197 real Starship::getFuel() {
198     return fuel;
199 }
200 
201