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