a9b8f1328068029f42442cfa16630234db76f3a3
[chaz/yoink] / src / YoinkApp.cc
1
2 /*******************************************************************************
3
4 Copyright (c) 2009, Charles McGarvey
5 All rights reserved.
6
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions are met:
9
10 * Redistributions of source code must retain the above copyright notice,
11 this list of conditions and the following disclaimer.
12 * Redistributions in binary form must reproduce the above copyright notice,
13 this list of conditions and the following disclaimer in the documentation
14 and/or other materials provided with the distribution.
15
16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
20 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
27 *******************************************************************************/
28
29 #include <cstdlib> // getenv
30 #include <iostream>
31 #include <string>
32
33 #include <Moof/Exception.hh>
34 #include <Moof/Log.hh>
35 #include <Moof/Math.hh>
36 #include <Moof/OpenGL.hh>
37 #include <Moof/Settings.hh>
38 #include <Moof/Thread.hh>
39 #include <Moof/Timer.hh>
40 #include <Moof/Video.hh>
41
42 #include "YoinkApp.hh"
43
44 #if HAVE_CONFIG_H
45 #include "config.h"
46 #endif
47
48
49 static std::string configFiles()
50 {
51 std::string files;
52
53 char* configFile = getenv("YOINKRC");
54 char* dataDir = getenv("YOINK_DATADIR");
55
56 if (configFile)
57 {
58 // if a config file from the environment variable is specified, we want
59 // to load it first so it has precedence
60 files += configFile;
61 files += ":";
62 }
63
64 // add the colon-delimited paths from configure
65 files += YOINK_CONFIGFILES;
66
67 if (dataDir)
68 {
69 // if another data directory is set in the environment, look for a
70 // config file there
71 files += ":";
72 files += dataDir;
73 files += "/yoinkrc";
74 }
75
76 // look in the configured data directory last of all
77 files += ":";
78 files += (dataDir ? dataDir : YOINK_DATADIR);
79 files += "/yoinkrc";
80
81 return files;
82 }
83
84 static std::string iconFile()
85 {
86 char* dataDir = getenv("YOINK_DATADIR");
87
88 // first set up the search paths so we can find the icon and other resources
89 if (dataDir)
90 {
91 // look first in the data directory specified by the environment
92 Mf::Resource::addSearchPath(dataDir);
93 }
94
95 // then look in the configured data directory
96 Mf::Resource::addSearchPath(YOINK_DATADIR);
97
98 return Mf::Resource::getPath("yoink.png");
99 }
100
101
102 void YoinkApp::myFunc(Mf::Timer& timer, Mf::Scalar t)
103 {
104 std::cout << "timer: " << t << std::endl;
105
106 //timer.invalidate();
107 }
108
109 int YoinkApp::myThread()
110 {
111 Mf::Scalar timer = Mf::Timer::getTicks();
112
113 for (;;)
114 {
115 std::cout << "thread awake: " << Mf::Timer::getTicks() << std::endl;
116
117 timer += 3.0;
118 Mf::Timer::sleep(timer, true);
119 }
120 return 0;
121 }
122
123
124 YoinkApp::YoinkApp(int argc, char* argv[]) :
125 Mf::Engine(argc, argv, configFiles(), PACKAGE_STRING, iconFile()),
126 music("NightFusionIntro"),
127 punchSound("RobotPunch")
128 {
129 Mf::dispatcher::addHandler("video.context_recreated",
130 boost::bind(&YoinkApp::contextRecreated, this, _1), this);
131 setupGL();
132
133 music.setLooping(true);
134 music.enqueue("NightFusionLoop");
135 music.stream();
136
137 heroine = Character::alloc("RobotTrooper");
138 heroine->getAnimation().startSequence("Run");
139
140 Mf::Scalar a[6] = {0.0, 1.5, -0.5, 3.0, -1.5, 1.0};
141 interp.init(a, 2.0, Mf::Interpolator::OSCILLATE);
142
143 Mf::Scalar b[2] = {1.0, 0.0};
144 fadeIn.init(b, 1.0);
145
146 octree = Mf::loadScene("Test");
147 heroine->treeNode = octree->insert(heroine);
148
149 //myTimer.init(boost::bind(&YoinkApp::myFunc, this, _1, _2),
150 //0.0, Mf::Timer::REPEAT);
151 //Mf::Thread thread = Mf::detachFunction(boost::bind(&YoinkApp::myThread, this));
152 //std::cout << "thread " << thread << " detached." << std::endl;
153 }
154
155 YoinkApp::~YoinkApp()
156 {
157 Mf::dispatcher::removeHandler(this);
158 }
159
160
161 void YoinkApp::setupGL()
162 {
163 glEnable(GL_TEXTURE_2D);
164
165 //glEnable(GL_CULL_FACE);
166 glEnable(GL_DEPTH_TEST);
167
168 glShadeModel(GL_SMOOTH);
169 //glEnable(GL_POLYGON_SMOOTH);
170
171 //int texSize;
172 //glGetIntegerv(GL_MAX_TEXTURE_SIZE, &texSize);
173 //std::cout << "texture size: " << texSize << std::endl;
174
175 //glEnable(GL_BLEND);
176 //glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
177 glEnable(GL_ALPHA_TEST);
178 glAlphaFunc(GL_GREATER, 0.0);
179
180 glClearColor(1.0, 0.0, 0.0, 1.0);
181
182 //glMatrixMode(GL_PROJECTION);
183 //glLoadIdentity();
184 //gluPerspective(60.0, 1.33333, 1.0, 2500.0);
185 camera.setProjection(cml::rad(60.0), 1.33333, 32.0, 2500.0);
186 camera.uploadProjectionToGL();
187
188 //glMatrixMode(GL_MODELVIEW);
189
190 //glLineWidth(10.0f);
191 }
192
193 void YoinkApp::contextRecreated(const Mf::Notification* note)
194 {
195 // Whenever the context is destroyed and a new one created, it probably
196 // won't contain our state so we need to set that up again.
197 setupGL();
198 }
199
200
201 void YoinkApp::update(Mf::Scalar t, Mf::Scalar dt)
202 {
203 //dt *= 0.7;
204
205 fadeIn.update(dt);
206 camera.update(t, dt);
207 heroine->update(t, dt);
208
209 // reinsert heroine
210 heroine->treeNode = octree->reinsert(heroine, heroine->treeNode);
211 octree->print(heroine->treeNode);
212
213 //camera.lookAt(heroine->getSphere().point);
214 camera.setPosition(Mf::Vector3(-heroine->current.position[0],
215 -heroine->current.position[1], -256));
216
217 interp.update(dt);
218 hud.setBar1Progress(interp.getState(dt));
219 hud.setBar2Progress(1.0 - interp.getState(dt));
220 }
221
222
223 void YoinkApp::draw(Mf::Scalar alpha)
224 {
225 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
226
227 glMatrixMode(GL_MODELVIEW);
228 glLoadMatrix(camera.getModelviewMatrix().data());
229
230 // DRAW THE SCENE
231 Mf::Texture::resetBind();
232
233 glEnableClientState(GL_VERTEX_ARRAY);
234 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
235
236 octree->drawIfVisible(alpha, camera.getFrustum());
237
238 //heroine->draw(alpha);
239 heroine->getAabb().draw();
240
241 hud.draw();
242
243 // DRAW FADE
244 glEnable(GL_BLEND);
245 glMatrixMode(GL_PROJECTION);
246 glPushMatrix();
247 glLoadIdentity();
248 glMatrixMode(GL_MODELVIEW);
249 glPushMatrix();
250 glLoadIdentity();
251 glColor4f(0.0f, 0.0f, 0.0f, fadeIn.getState(alpha));
252 Mf::Texture::resetBind();
253
254 //glRectf(-1.0f, -1.0f, 1.0f, 1.0f);
255 glBegin(GL_QUADS);
256 glVertex3f(-1.0, -1.0, -0.1);
257 glVertex3f(1.0, -1.0, -0.1);
258 glVertex3f(1.0, 1.0, -0.1);
259 glVertex3f(-1.0, 1.0, -0.1);
260 glEnd();
261
262 glDisable(GL_BLEND);
263
264 glMatrixMode(GL_PROJECTION);
265 glPopMatrix();
266 glMatrixMode(GL_MODELVIEW);
267 glPopMatrix();
268 }
269
270 void YoinkApp::handleEvent(const Mf::Event& event)
271 {
272 switch (event.type)
273 {
274 case SDL_KEYDOWN:
275 if (event.key.keysym.sym == SDLK_ESCAPE)
276 {
277 stop();
278 break;
279 }
280 else if (event.key.keysym.sym == SDLK_f)
281 {
282 getVideo().toggleFull();
283 break;
284 }
285 else if (event.key.keysym.sym == SDLK_SPACE)
286 {
287 heroine->getAnimation().startSequence("Punch");
288 punchSound.play();
289 break;
290 }
291 else if (event.key.keysym.sym == SDLK_t)
292 {
293 Mf::dispatcher::dispatch("video.context_recreated");
294 break;
295 }
296 else if (event.key.keysym.sym == SDLK_p)
297 {
298 music.toggle();
299 break;
300 }
301 else if (event.key.keysym.sym == SDLK_l)
302 {
303 getVideo().toggleCursorGrab();
304 getVideo().toggleCursorVisible();
305 break;
306 }
307
308 case SDL_KEYUP:
309 heroine->handleEvent(event);
310
311 case SDL_MOUSEMOTION:
312 case SDL_MOUSEBUTTONDOWN:
313 camera.handleEvent(event);
314 break;
315
316 case SDL_QUIT:
317 stop();
318 break;
319
320 case SDL_VIDEORESIZE:
321 glViewport(0, 0, event.resize.w, event.resize.h);
322 hud.resize(event.resize.w, event.resize.h);
323 camera.setProjection(cml::rad(60.0),
324 double(event.resize.w) / double(event.resize.h), 32.0, 2500.0);
325 camera.uploadProjectionToGL();
326 break;
327 }
328 }
329
330
331
332 int main(int argc, char* argv[])
333 {
334 std::cout << std::endl << PACKAGE_STRING << std::endl
335 << "Compiled " << __TIME__ " " __DATE__ << std::endl
336 << "Send patches and bug reports to <"
337 PACKAGE_BUGREPORT << ">." << std::endl << std::endl;
338
339 #if YOINK_LOGLEVEL >= 4
340 Mf::setLogLevel(Mf::LOG_DEBUG);
341 #elif YOINK_LOGLEVEL >= 3
342 Mf::setLogLevel(Mf::LOG_INFO);
343 #elif YOINK_LOGLEVEL >= 2
344 Mf::setLogLevel(Mf::LOG_WARNING);
345 #elif YOINK_LOGLEVEL >= 1
346 Mf::setLogLevel(Mf::LOG_ERROR);
347 #elif YOINK_LOGLEVEL
348 Mf::setLogLevel(Mf::LOG_NONE);
349 #endif
350
351 int status = 0;
352
353 try
354 {
355 YoinkApp app(argc, argv);
356 status = app.run();
357 }
358 catch (Mf::Exception e)
359 {
360 Mf::logError("unhandled exception: <<%s>>", e.what());
361 Mf::logInfo("it's time to crash now :-(");
362 //status = 1;
363 throw e;
364 }
365
366 std::cout << std::endl << "Goodbye..." << std::endl << std::endl;
367 return status;
368 }
369
370
371 /** vim: set ts=4 sw=4 tw=80: *************************************************/
372
This page took 0.046829 seconds and 3 git commands to generate.