1 /*
2 Copyright (C) 2007, 2010 - Bit-Blot
3
4 This file is part of Aquaria.
5
6 Aquaria is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License
8 as published by the Free Software Foundation; either version 2
9 of the License, or (at your option) any later version.
10
11 This program 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.
14
15 See the GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21 #include "Shot.h"
22 #include "Game.h"
23 #include "Avatar.h"
24
25 #include "../BBGE/MathFunctions.h"
26
27 Beam::Beams Beam::beams;
28
Beam(Vector pos,float angle)29 Beam::Beam(Vector pos, float angle) : Quad()
30 {
31 addType(SCO_BEAM);
32 cull = false;
33 trace();
34 //rotation.z = angle;
35 this->angle = angle;
36 position = pos;
37
38 setTexture("beam");
39 beams.push_back(this);
40
41 setBlendType(BLEND_ADD);
42 alpha = 0;
43 alpha.interpolateTo(1, 0.1);
44 trace();
45 damageData.damageType = DT_ENEMY_BEAM;
46 damageData.damage = 0.5;
47
48 beamWidth = 16;
49 }
50
setBeamWidth(float w)51 void Beam::setBeamWidth(float w)
52 {
53 beamWidth = w;
54 }
55
setDamage(float dmg)56 void Beam::setDamage(float dmg)
57 {
58 damageData.damage = dmg;
59 }
60
setFirer(Entity * e)61 void Beam::setFirer(Entity *e)
62 {
63 damageData.attacker = e;
64 }
65
onEndOfLife()66 void Beam::onEndOfLife()
67 {
68 beams.remove(this);
69 }
70
killAllBeams()71 void Beam::killAllBeams()
72 {
73 std::queue<Beam*>beamDeleteQueue;
74 for (Beams::iterator i = beams.begin(); i != beams.end(); i++)
75 {
76 beamDeleteQueue.push(*i);
77 }
78 Beam *s = 0;
79 while (!beamDeleteQueue.empty())
80 {
81 s = beamDeleteQueue.front();
82 if (s)
83 {
84 s->safeKill();
85 }
86 beamDeleteQueue.pop();
87 }
88 beams.clear();
89 }
90
trace()91 void Beam::trace()
92 {
93 float angle = MathFunctions::toRadians(this->angle);
94 //(float(-this->angle)/180.0f)*PI;
95 //float angle = rotation.z;
96 Vector mov(sinf(angle), cosf(angle));
97 TileVector t(position);
98 Vector startTile(t.x, t.y);
99
100 /*
101 std::ostringstream os;
102 os << "rotation.z = " << rotation.z << " mov(" << mov.x << ", " << mov.y << ")";
103 debugLog(os.str());
104 */
105
106 int moves = 0;
107 while (!dsq->game->isObstructed(TileVector(startTile.x, startTile.y)))
108 {
109 startTile += mov;
110 moves++;
111 if (moves > 1000)
112 break;
113 }
114 t = TileVector(startTile.x, startTile.y);
115 endPos = t.worldVector();
116
117 /*
118 offset = endPos - position;
119 offset /= 2;
120 offset *= -1;
121 */
122
123
124 //width = (endPos - position).getLength2D();
125 }
126
render()127 void Beam::render()
128 {
129
130 /*
131 glLineWidth(4);
132 glColor4f(1,1,1,1);
133 glBegin(GL_LINES);
134 glVertex2f(position.x, position.y);
135 glVertex2f(endPos.x, endPos.y);
136 glEnd();
137 */
138
139 Quad::render();
140 }
141
onRender()142 void Beam::onRender()
143 {
144 #ifdef BBGE_BUILD_OPENGL
145 //glDisable(GL_CULL_FACE);
146 Vector diff = endPos - position;
147 Vector side = diff;
148 //side.normalize2D();
149 side.setLength2D(beamWidth*2);
150 Vector sideLeft = side.getPerpendicularLeft();
151 Vector sideRight = side.getPerpendicularRight();
152
153 glBegin(GL_QUADS);
154 glTexCoord2f(0, 0);
155 glVertex2f(sideLeft.x, sideLeft.y);
156 glTexCoord2f(1, 0);
157 glVertex2f(sideLeft.x+diff.x, sideLeft.y+diff.y);
158 glTexCoord2f(1, 1);
159 glVertex2f(sideRight.x+diff.x, sideRight.y+diff.y);
160 glTexCoord2f(0, 1);
161 glVertex2f(sideRight.x, sideRight.y);
162 glEnd();
163 #endif
164 }
165
onUpdate(float dt)166 void Beam::onUpdate(float dt)
167 {
168 if (dsq->game->isPaused()) return;
169
170 Quad::onUpdate(dt);
171
172 if (alpha.x > 0.5f)
173 {
174 FOR_ENTITIES(i)
175 {
176 Entity *e = *i;
177 if (e != damageData.attacker && e->isDamageTarget(damageData.damageType))
178 {
179 if (isTouchingLine(position, endPos, e->position, beamWidth + e->collideRadius))
180 {
181 e->damage(damageData);
182 }
183 }
184 }
185 }
186 }
187
188