1 // Description:
2 //   Starfield with nebulas.
3 //
4 // Copyright (C) 2001 Frank Becker
5 //
6 // This program is free software; you can redistribute it and/or modify it under
7 // the terms of the GNU General Public License as published by the Free Software
8 // Foundation;  either version 2 of the License,  or (at your option) any  later
9 // version.
10 //
11 // This program is distributed in the hope that it will be useful,  but  WITHOUT
12 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 // FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details
14 //
15 #include "Starfield.hpp"
16 
17 #include <math.h>
18 #include <string>
19 
20 #include <Trace.hpp>
21 #include <GameState.hpp>
22 #include <Random.hpp>
23 #include <Constants.hpp>
24 #include <BitmapManager.hpp>
25 
26 using namespace std;
27 
Starfield(void)28 Starfield::Starfield( void)
29 {
30     XTRACE();
31 
32     _nebula = BitmapManagerS::instance()->getBitmap( "bitmaps/nebula");
33     if( !_nebula)
34     {
35 	LOG_ERROR << "Unable to load nebula" << endl;
36     }
37     _nebulaIndex = _nebula->getIndex( "Nebula");
38     _nebulaHalfWidth = (float)(_nebula->getWidth( _nebulaIndex))/2.0f;
39     _nebulaHalfHeight= (float)(_nebula->getHeight( _nebulaIndex))/2.0f;
40 }
41 
~Starfield()42 Starfield::~Starfield()
43 {
44     XTRACE();
45 }
46 
init(float z)47 void Starfield::init( float z)
48 {
49     XTRACE();
50     for( int i=0; i<NUM_STARS; i++)
51     {
52 	_starInfo[i].x = Random::rangef0_1()*200.0f - 100.0f;
53 	_starInfo[i].y = Random::rangef0_1()*200.0f - 100.0f;
54 	_starInfo[i].z = z;
55 	_starInfo[i].d = Random::rangef0_1()*1.0f+0.25f;
56 
57 	_starInfo[i].r = Random::rangef0_1()*0.5;
58 	_starInfo[i].g = Random::rangef0_1()*0.5;
59 	_starInfo[i].b = Random::rangef0_1()*0.5;
60     }
61     for( int i=0; i<NUM_NEBULAS; i++)
62     {
63 	pickSize( _nebulaInfo[i]);
64 	_nebulaInfo[i].rot = Random::rangef0_1() * 360.0f;
65 	findMax( _nebulaInfo[i]);
66 
67 	_nebulaInfo[i].x   =(Random::rangef0_1() - 0.5f)*200.0f;
68 	_nebulaInfo[i].y   =(Random::rangef0_1() - 0.5f)*200.0f;
69 	_nebulaInfo[i].d   = Random::rangef0_1() * 1.50f+0.25f;
70 
71 	_nebulaInfo[i].z = z + i;
72 	pickColor( _nebulaInfo[i]);
73     }
74 
75     updatePrevs();
76 }
77 
update(void)78 void Starfield::update( void)
79 {
80 //    XTRACE();
81     updatePrevs();
82 
83     for( int i=0; i<NUM_STARS; i++)
84     {
85 	_starInfo[i].y -= _starInfo[i].d;
86 	if( _starInfo[i].y < -100.0)
87 	{
88 	    _starInfo[i].y = 100.0;
89 	    _prevStarInfoY[ i] = _starInfo[ i].y;
90 	}
91     }
92     for( int i=0; i<NUM_NEBULAS; i++)
93     {
94 	_nebulaInfo[i].y -= _nebulaInfo[i].d;
95 	if( _nebulaInfo[i].y < (-50.0-_nebulaInfo[i].max))
96 	{
97 	    pickSize( _nebulaInfo[i]);
98 	    _nebulaInfo[i].rot = Random::rangef0_1() * 360.0f;
99 	    findMax( _nebulaInfo[i]);
100 
101 	    _nebulaInfo[i].x   =(Random::rangef0_1() - 0.5f)*200.0f;
102 	    _nebulaInfo[i].y   = 50.0f+_nebulaInfo[i].max;
103 	    _nebulaInfo[i].d   = Random::rangef0_1() * 1.50f+0.25f;
104 
105 	    _prevNebulaInfoY[ i] = _nebulaInfo[ i].y;
106 
107 	    pickColor( _nebulaInfo[i]);
108 	}
109     }
110 }
111 
updatePrevs(void)112 void Starfield::updatePrevs( void)
113 {
114 //    XTRACE();
115     for( int i=0; i<NUM_STARS; i++)
116     {
117 	_prevStarInfoY[ i] = _starInfo[ i].y;
118     }
119     for( int i=0; i<NUM_NEBULAS; i++)
120     {
121 	_prevNebulaInfoY[ i] = _nebulaInfo[ i].y;
122     }
123 }
124 
draw(bool showStars,bool showNebulas)125 void Starfield::draw( bool showStars, bool showNebulas)
126 {
127 //    XTRACE();
128 //	glDisable(GL_DEPTH_TEST);
129     glDisable(GL_LIGHTING);
130 
131     if( showStars)
132     {
133         GLfloat starVertices[NUM_STARS*3];
134         GLfloat starColors[NUM_STARS*4];
135 
136 	for( int i=0; i<NUM_STARS; i++)
137 	{
138 	    float vy = _prevStarInfoY[i] +
139                 (_starInfo[i].y - _prevStarInfoY[i])* GameState::frameFractionOther;
140 
141             starVertices[i*3+0] = _starInfo[i].x;
142             starVertices[i*3+1] = vy;
143             starVertices[i*3+2] = _starInfo[i].z;
144 
145             starColors[i*4+0] = _starInfo[i].r;
146             starColors[i*4+1] = _starInfo[i].g;
147             starColors[i*4+2] = _starInfo[i].b;
148             starColors[i*4+3] = 0.7;
149 	}
150 
151         glEnableClientState(GL_VERTEX_ARRAY);
152         glEnableClientState(GL_COLOR_ARRAY);
153 
154         glVertexPointer(3, GL_FLOAT, 0, starVertices);
155         glColorPointer(4, GL_FLOAT, 0, starColors);
156 
157         glDrawArrays(GL_POINTS, 0, NUM_STARS);
158 
159         glDisableClientState(GL_VERTEX_ARRAY);
160         glDisableClientState(GL_COLOR_ARRAY);
161     }
162 
163     if( showNebulas)
164     {
165 	glEnable(GL_TEXTURE_2D);
166 	bindTexture();
167 	for( int i=0; i<NUM_NEBULAS; i++)
168 	{
169 	    glPushMatrix();
170 
171 	    float vy = _prevNebulaInfoY[i] +
172 		(_nebulaInfo[i].y - _prevNebulaInfoY[i]) * GameState::frameFractionOther;
173 
174 	    glColor4f( _nebulaInfo[i].r, _nebulaInfo[i].g, _nebulaInfo[i].b, 0.3f);
175 	    glTranslatef( _nebulaInfo[i].x, vy, _nebulaInfo[i].z);
176 	    glRotatef( _nebulaInfo[i].rot, 0,0,1);
177 
178 	    _nebula->DrawC(
179 		_nebulaIndex, 0, 0, _nebulaInfo[i].sizeX, _nebulaInfo[i].sizeY);
180 
181 	    glPopMatrix();
182 	}
183 	glDisable(GL_TEXTURE_2D);
184     }
185 
186     glEnable(GL_LIGHTING);
187 //	glEnable(GL_DEPTH_TEST);
188 }
189 
pickSize(Nebula & n)190 void Starfield::pickSize( Nebula &n)
191 {
192     n.sizeX = Random::rangef0_1()*1.2f + 0.4f;
193     n.sizeY = Random::rangef0_1()*1.2f + 0.4f;
194 }
195 
findMax(Nebula & n)196 void Starfield::findMax( Nebula &n)
197 {
198     float sina = _nebulaHalfWidth *n.sizeX*sin( n.rot * ((float)M_PI/180.0f));
199     float cosa = _nebulaHalfHeight*n.sizeY*cos( n.rot * ((float)M_PI/180.0f));
200     float t1 = fabs(-sina + cosa);
201     float t2 = fabs(+sina + cosa);
202     n.max = max(t1,t2);
203 }
204 
pickColor(Nebula & n)205 void Starfield::pickColor( Nebula &n)
206 {
207     //only use 2 color components
208     float r1 = Random::rangef0_1()+0.1f;
209     float r2 = Random::rangef0_1()+0.1f;
210 
211     float d = 1.8f/(r1+r2);
212     r1 = r1*d;
213     r2 = r2*d;
214 
215     int r = Random::random() % 3;
216     switch( r)
217     {
218 	case 0:
219 	    n.r = r1;
220 	    n.g = r2;
221 	    n.b = 0.0;
222 	    break;
223 	case 1:
224 	    n.r = 0.0;
225 	    n.g = r1;
226 	    n.b = r2;
227 	    break;
228 	default:
229 	case 2:
230 	    n.r = r1;
231 	    n.g = 0.0;
232 	    n.b = r2;
233 	    break;
234     }
235 }
236