597a74ff79d24b11a7bf54d7dc91e5dfc6758ed1
[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 <boost/bind.hpp>
34
35 #include <Moof/Exception.hh>
36 #include <Moof/Log.hh>
37 #include <Moof/Math.hh>
38 #include <Moof/OpenGL.hh>
39 #include <Moof/Settings.hh>
40 #include <Moof/Timer.hh>
41 #include <Moof/Video.hh>
42
43 #include "YoinkApp.hh"
44
45 #if HAVE_CONFIG_H
46 #include "config.h"
47 #endif
48
49
50 static std::string configFiles()
51 {
52 std::string files;
53
54 char* configFile = getenv("YOINKRC");
55 char* dataDir = getenv("YOINK_DATADIR");
56
57 if (configFile)
58 {
59 // if a config file from the environment variable is specified, we want
60 // to load it first so it has precedence
61 files += configFile;
62 files += ":";
63 }
64
65 // add the colon-delimited paths from configure
66 files += YOINK_CONFIGFILES;
67
68 if (dataDir)
69 {
70 // if another data directory is set in the environment, look for a
71 // config file there
72 files += ":";
73 files += dataDir;
74 files += "/yoinkrc";
75 }
76
77 // look in the configured data directory last of all
78 files += ":";
79 files += (dataDir ? dataDir : YOINK_DATADIR);
80 files += "/yoinkrc";
81
82 return files;
83 }
84
85 static std::string iconFile()
86 {
87 char* dataDir = getenv("YOINK_DATADIR");
88
89 // first set up the search paths so we can find the icon and other resources
90 if (dataDir)
91 {
92 // look first in the data directory specified by the environment
93 Mf::Resource::addSearchPath(dataDir);
94 }
95
96 // then look in the configured data directory
97 Mf::Resource::addSearchPath(YOINK_DATADIR);
98
99 return Mf::Resource::getPath("yoink.png");
100 }
101
102
103 YoinkApp::YoinkApp(int argc, char* argv[]) :
104 Mf::Engine(argc, argv, configFiles(), PACKAGE_STRING, iconFile()),
105 music("BeatTheCube"),
106 punchSound("RobotPunch")
107 {
108 Mf::dispatcher::addHandler("video.context_recreated",
109 boost::bind(&YoinkApp::contextRecreated, this, _1), this);
110 setupGL();
111
112 music.setLooping(true);
113 music.enqueue("NightFusionLoop");
114 music.stream();
115
116 heroine = Character::alloc("RobotTrooper");
117 heroine->getAnimation().startSequence("Run");
118
119 Mf::Scalar a[6] = {0.0, 1.5, -0.5, 3.0, -1.5, 1.0};
120 interp.init(a, 2.0, Mf::Interpolator::OSCILLATE);
121
122 Mf::Scalar b[2] = {1.0, 0.0};
123 fadeIn.init(b, 1.0);
124
125 octree = Mf::loadScene("Test");
126 heroine->treeNode = octree->insert(heroine);
127 }
128
129 YoinkApp::~YoinkApp()
130 {
131 Mf::dispatcher::removeHandler(this);
132 }
133
134
135 void YoinkApp::setupGL()
136 {
137 glEnable(GL_TEXTURE_2D);
138
139 //glEnable(GL_CULL_FACE);
140 glEnable(GL_DEPTH_TEST);
141
142 glShadeModel(GL_SMOOTH);
143 //glEnable(GL_POLYGON_SMOOTH);
144
145 //int texSize;
146 //glGetIntegerv(GL_MAX_TEXTURE_SIZE, &texSize);
147 //std::cout << "texture size: " << texSize << std::endl;
148
149 //glEnable(GL_BLEND);
150 //glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
151 glEnable(GL_ALPHA_TEST);
152 glAlphaFunc(GL_GREATER, 0.0);
153
154 glClearColor(1.0, 0.0, 0.0, 1.0);
155
156 //glMatrixMode(GL_PROJECTION);
157 //glLoadIdentity();
158 //gluPerspective(60.0, 1.33333, 1.0, 2500.0);
159 camera.setProjection(cml::rad(60.0), 1.33333, 32.0, 2500.0);
160 camera.uploadProjectionToGL();
161
162 //glMatrixMode(GL_MODELVIEW);
163
164 //glLineWidth(10.0f);
165 }
166
167 void YoinkApp::contextRecreated(const Mf::Notification* note)
168 {
169 // Whenever the context is destroyed and a new one created, it probably
170 // won't contain our state so we need to set that up again.
171 setupGL();
172 }
173
174
175 void YoinkApp::update(Mf::Scalar t, Mf::Scalar dt)
176 {
177 dt *= 0.7;
178
179 music.update(t, dt);
180 fadeIn.update(dt);
181 camera.update(t, dt);
182 heroine->update(t, dt);
183
184 // reinsert heroine
185 heroine->treeNode = octree->reinsert(heroine, heroine->treeNode);
186 octree->print(heroine->treeNode);
187
188 //camera.lookAt(heroine->getSphere().point);
189 camera.setPosition(Mf::Vector3(-heroine->current.position[0], -heroine->current.position[1], -256));
190
191 interp.update(dt);
192 hud.setBar1Progress(interp.getState(dt));
193 hud.setBar2Progress(1.0 - interp.getState(dt));
194 }
195
196
197 void YoinkApp::draw(Mf::Scalar alpha)
198 {
199 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
200
201 glMatrixMode(GL_MODELVIEW);
202 glLoadMatrix(camera.getModelviewMatrix().data());
203
204 // DRAW THE SCENE
205 Mf::Texture::resetBind();
206
207 glEnableClientState(GL_VERTEX_ARRAY);
208 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
209
210 octree->drawIfVisible(alpha, camera.getFrustum());
211
212 //heroine->draw(alpha);
213 heroine->getAabb().draw();
214
215 hud.draw();
216
217 // DRAW FADE
218 glEnable(GL_BLEND);
219 glMatrixMode(GL_PROJECTION);
220 glPushMatrix();
221 glLoadIdentity();
222 glMatrixMode(GL_MODELVIEW);
223 glPushMatrix();
224 glLoadIdentity();
225 glColor4f(0.0f, 0.0f, 0.0f, fadeIn.getState(alpha));
226 Mf::Texture::resetBind();
227
228 //glRectf(-1.0f, -1.0f, 1.0f, 1.0f);
229 glBegin(GL_QUADS);
230 glVertex3f(-1.0, -1.0, -0.1);
231 glVertex3f(1.0, -1.0, -0.1);
232 glVertex3f(1.0, 1.0, -0.1);
233 glVertex3f(-1.0, 1.0, -0.1);
234 glEnd();
235
236 glDisable(GL_BLEND);
237
238 glMatrixMode(GL_PROJECTION);
239 glPopMatrix();
240 glMatrixMode(GL_MODELVIEW);
241 glPopMatrix();
242 }
243
244 void YoinkApp::handleEvent(const Mf::Event& event)
245 {
246 switch (event.type)
247 {
248 case SDL_KEYDOWN:
249 if (event.key.keysym.sym == SDLK_ESCAPE)
250 {
251 stop();
252 break;
253 }
254 else if (event.key.keysym.sym == SDLK_f)
255 {
256 getVideo().toggleFull();
257 break;
258 }
259 else if (event.key.keysym.sym == SDLK_SPACE)
260 {
261 heroine->getAnimation().startSequence("Punch");
262 punchSound.play();
263 break;
264 }
265 else if (event.key.keysym.sym == SDLK_t)
266 {
267 Mf::dispatcher::dispatch("video.context_recreated");
268 break;
269 }
270 else if (event.key.keysym.sym == SDLK_p)
271 {
272 music.toggle();
273 break;
274 }
275 else if (event.key.keysym.sym == SDLK_l)
276 {
277 getVideo().toggleCursorGrab();
278 getVideo().toggleCursorVisible();
279 break;
280 }
281
282 case SDL_KEYUP:
283 heroine->handleEvent(event);
284
285 case SDL_MOUSEMOTION:
286 case SDL_MOUSEBUTTONDOWN:
287 camera.handleEvent(event);
288 break;
289
290 case SDL_QUIT:
291 stop();
292 break;
293
294 case SDL_VIDEORESIZE:
295 glViewport(0, 0, event.resize.w, event.resize.h);
296 hud.resize(event.resize.w, event.resize.h);
297 camera.setProjection(cml::rad(60.0), double(event.resize.w / event.resize.h), 32.0, 2500.0);
298 camera.uploadProjectionToGL();
299 break;
300 }
301 }
302
303
304
305 int main(int argc, char* argv[])
306 {
307 std::cout << std::endl << PACKAGE_STRING << std::endl
308 << "Compiled " << __TIME__ " " __DATE__ << std::endl
309 << "Send patches and bug reports to <"
310 PACKAGE_BUGREPORT << ">." << std::endl << std::endl;
311
312 #if YOINK_LOGLEVEL >= 4
313 Mf::setLogLevel(Mf::LOG_DEBUG);
314 #elif YOINK_LOGLEVEL >= 3
315 Mf::setLogLevel(Mf::LOG_INFO);
316 #elif YOINK_LOGLEVEL >= 2
317 Mf::setLogLevel(Mf::LOG_WARNING);
318 #elif YOINK_LOGLEVEL >= 1
319 Mf::setLogLevel(Mf::LOG_ERROR);
320 #elif YOINK_LOGLEVEL
321 Mf::setLogLevel(Mf::LOG_NONE);
322 #endif
323
324 int status = 0;
325
326 try
327 {
328 YoinkApp app(argc, argv);
329 status = app.run();
330 }
331 catch (Mf::Exception e)
332 {
333 Mf::logError("unhandled exception: <<%s>>", e.what());
334 Mf::logInfo("it's time to crash now :-(");
335 //status = 1;
336 throw e;
337 }
338
339 std::cout << std::endl << "Goodbye..." << std::endl << std::endl;
340 return status;
341 }
342
343
344 /** vim: set ts=4 sw=4 tw=80: *************************************************/
345
This page took 0.041624 seconds and 3 git commands to generate.