18 |
* $Id$ |
* $Id$ |
19 |
*/ |
*/ |
20 |
|
|
21 |
|
#include "common.hh" |
22 |
#include "config.h" |
#include "config.h" |
23 |
#include "options.hh" |
#include "options.hh" |
|
#include "enigma.hh" |
|
|
#include "display.hh" |
|
24 |
#include "editor.hh" |
#include "editor.hh" |
25 |
#include "world.hh" |
#include "world.hh" |
26 |
#include "player.hh" |
#include "player.hh" |
28 |
#include "sound.hh" |
#include "sound.hh" |
29 |
#include "system.hh" |
#include "system.hh" |
30 |
#include "gui.hh" |
#include "gui.hh" |
|
#include "video.hh" |
|
31 |
#include "menus.hh" |
#include "menus.hh" |
32 |
|
|
33 |
#include "px/px.hh" |
#include "game.hh" |
|
#include "px/cache.hh" |
|
34 |
|
|
35 |
#include "SDL.h" |
#include "px/sdl.hh" |
|
#ifndef __APPLE__ |
|
|
#include "getopt.h" |
|
|
#endif |
|
36 |
|
|
|
#include <cstdio> |
|
|
#include <cstring> |
|
|
#include <cstdlib> |
|
|
#include <string> |
|
|
#include <cassert> |
|
37 |
#include <algorithm> |
#include <algorithm> |
38 |
#include <fstream> |
#include <fstream> |
39 |
|
|
40 |
|
#ifndef __APPLE__ |
41 |
|
#include "getopt.h" |
42 |
|
#endif |
43 |
|
|
44 |
using namespace std; |
using namespace std; |
45 |
using namespace px; |
using namespace px; |
46 |
using namespace enigma; |
using namespace enigma; |
47 |
|
|
|
namespace |
|
|
{ |
|
|
void flush_events() |
|
|
{ |
|
|
SDL_Event e; |
|
|
while (SDL_PollEvent(&e)) |
|
|
; |
|
|
} |
|
|
inline px::Screen *get_screen() { return video::GetScreen(); } |
|
|
} |
|
|
|
|
48 |
Direction |
Direction |
49 |
enigma::reverse(Direction d) |
enigma::reverse(Direction d) |
50 |
{ |
{ |
132 |
void release(Surface *s) { delete s; } |
void release(Surface *s) { delete s; } |
133 |
}; |
}; |
134 |
|
|
135 |
typedef cache::Cache<Surface*, ImageAlloc> ImageCache; |
typedef Cache<Surface*, ImageAlloc> ImageCache; |
136 |
} |
} |
137 |
|
|
138 |
|
|
139 |
//====================================================================== |
//====================================================================== |
140 |
// MAIN PROGRAM |
// APPLICATION DATA |
141 |
//====================================================================== |
//====================================================================== |
142 |
|
namespace enigma |
|
namespace |
|
143 |
{ |
{ |
144 |
vector<string> args; // List of command line arguments. |
struct Flags { |
145 |
|
bool nosound; |
146 |
|
}; |
147 |
|
|
148 |
|
class Application { |
149 |
|
public: |
150 |
|
|
151 |
|
void init(int argc, char **argv) { |
152 |
|
copy(argv+1, argv+argc, back_inserter(args)); |
153 |
|
} |
154 |
|
|
155 |
|
// Variables. |
156 |
|
|
157 |
|
vector<string> args; // List of command line arguments. |
158 |
|
|
159 |
|
Flags flags; |
160 |
|
Cache<Font *, FontAlloc> font_cache; |
161 |
|
Cache<Surface*, ImageAlloc> image_cache; |
162 |
|
}; |
163 |
|
|
164 |
|
vector<LevelPack *> LevelPacks; |
165 |
|
|
166 |
|
Application app; |
167 |
} |
} |
168 |
|
|
169 |
vector<LevelPack *> enigma::LevelPacks; |
|
170 |
|
//====================================================================== |
171 |
|
// MAIN PROGRAM |
172 |
|
//====================================================================== |
173 |
|
|
174 |
//---------------------------------------------------------------------- |
//---------------------------------------------------------------------- |
175 |
// Level management |
// Level management |
211 |
//---------------------------------------------------------------------- |
//---------------------------------------------------------------------- |
212 |
// GAME |
// GAME |
213 |
//---------------------------------------------------------------------- |
//---------------------------------------------------------------------- |
|
namespace |
|
|
{ |
|
|
class Game { |
|
|
public: |
|
|
Game(); |
|
|
void run(LevelPack *lp, int ilevel); |
|
|
void quit() { change_state(ABORT); } |
|
|
void finish_level() { change_state(LEVELFINISHED); } |
|
|
void restart_level() { change_state(RELOADLEVEL); } |
|
|
private: |
|
|
// Private types. |
|
|
enum State |
|
|
{ |
|
|
/* The game is currently running. */ |
|
|
INGAME, |
|
|
|
|
|
/* This level has been completed, proceed to the next |
|
|
one. */ |
|
|
LEVELFINISHED, |
|
|
|
|
|
/* Player's marble is dead. Wait a little, then restart |
|
|
the level. */ |
|
|
PLAYERDEAD, |
|
|
|
|
|
/* Restart the game. */ |
|
|
RESTARTGAME, |
|
|
|
|
|
/* Reload the current level (this automatically resets |
|
|
every object in the landscape). */ |
|
|
RELOADLEVEL, |
|
|
|
|
|
/* The level info screen before entering a new level. */ |
|
|
LEVELINFO, |
|
|
|
|
|
/* Leave the game immediately. */ |
|
|
ABORT |
|
|
}; |
|
|
|
|
|
|
|
|
// Private methods. |
|
|
void handle_events(); |
|
|
void on_keydown(SDL_Event &e); |
|
|
void on_mousebutton(SDL_Event &e); |
|
|
void update_mouse_button_state(); |
|
|
void change_state(State newstate); |
|
|
void tick(double dtime); |
|
|
void show_menu(); |
|
|
bool load_level(int ilevel); |
|
|
|
|
|
// Private variables. |
|
|
State state; |
|
|
enum InputState { |
|
|
I_NORMAL, I_MESSAGE, I_COMMAND |
|
|
} input_state; |
|
|
|
|
|
LevelPack *level_pack; |
|
|
unsigned icurrent_level; |
|
|
Uint32 last_tick_time; |
|
|
double level_finished_dtime; |
|
|
double actor_dead_dtime; |
|
|
}; |
|
|
} |
|
214 |
|
|
215 |
Game::Game() |
Game::Game() |
216 |
: state(INGAME), |
: state(INGAME), |
217 |
input_state(I_NORMAL), |
input_state(I_NORMAL), |
218 |
icurrent_level(0), |
icurrent_level(0), |
219 |
last_tick_time(0) |
last_tick_time(0), |
220 |
|
screen (0) |
221 |
{ |
{ |
222 |
} |
} |
223 |
|
|
263 |
if (actor_dead_dtime <= 0.5) { |
if (actor_dead_dtime <= 0.5) { |
264 |
world::Tick(dtime); |
world::Tick(dtime); |
265 |
display::Tick(dtime); |
display::Tick(dtime); |
266 |
display::Redraw(get_screen()); |
display::Redraw(screen); |
267 |
handle_events(); |
handle_events(); |
268 |
} else { |
} else { |
269 |
change_state (RESTARTGAME); |
change_state (RESTARTGAME); |
286 |
handle_events(); |
handle_events(); |
287 |
world::Tick(dtime); |
world::Tick(dtime); |
288 |
display::Tick(dtime); |
display::Tick(dtime); |
289 |
display::Redraw(get_screen()); |
display::Redraw(screen); |
290 |
} else { |
} else { |
291 |
unsigned next_level = 1+icurrent_level; |
unsigned next_level = 1+icurrent_level; |
292 |
if (next_level == level_pack->levels.size()) |
if (next_level == level_pack->levels.size()) |
310 |
handle_events(); |
handle_events(); |
311 |
world::Tick(dtime); |
world::Tick(dtime); |
312 |
display::Tick(dtime); |
display::Tick(dtime); |
313 |
display::Redraw(get_screen()); |
display::Redraw(screen); |
314 |
break; |
break; |
315 |
|
|
316 |
default: |
default: |
332 |
display::DrawAll(gc); |
display::DrawAll(gc); |
333 |
ShowScreen(video::TM_PUSH_RANDOM, video::BackBuffer()); |
ShowScreen(video::TM_PUSH_RANDOM, video::BackBuffer()); |
334 |
// FX_Fade(video::FADEIN); |
// FX_Fade(video::FADEIN); |
335 |
flush_events(); |
sdl::FlushEvents(); |
336 |
update_mouse_button_state(); |
update_mouse_button_state(); |
337 |
last_tick_time = SDL_GetTicks(); |
last_tick_time = SDL_GetTicks(); |
338 |
return true; |
return true; |
341 |
void |
void |
342 |
Game::run (LevelPack *lp, int ilevel) |
Game::run (LevelPack *lp, int ilevel) |
343 |
{ |
{ |
344 |
|
screen = video::GetScreen(); |
345 |
class Avg { |
class Avg { |
346 |
enum {N=20}; |
enum {N=20}; |
347 |
double dtimes[N]; |
double dtimes[N]; |
364 |
|
|
365 |
icurrent_level = ilevel; |
icurrent_level = ilevel; |
366 |
|
|
367 |
video::TempInputGrab grab(SDL_GRAB_ON); |
sdl::TempInputGrab grab(options::Nograb ? SDL_GRAB_OFF : SDL_GRAB_ON); |
368 |
video::HideMouse(); |
video::HideMouse(); |
369 |
// sound::PlayMusic("/sound/Emilie.xm"); |
// sound::PlayMusic("/sound/Emilie.xm"); |
370 |
sound::FadeoutMusic(); |
sound::FadeoutMusic(); |
550 |
break; |
break; |
551 |
case SDLK_t: |
case SDLK_t: |
552 |
// Darken the current screen; useful for debugging screen updates |
// Darken the current screen; useful for debugging screen updates |
553 |
TintRect(get_screen(), get_screen()->size(), |
TintRect(screen, screen->size(), 0,0,0, 200); |
554 |
0,0,0, 200); |
screen->update_all(); |
555 |
get_screen()->update_all(); |
screen->flush_updates(); |
|
get_screen()->flush_updates(); |
|
556 |
break; |
break; |
557 |
case SDLK_g: |
case SDLK_g: |
558 |
if (e.key.keysym.mod & KMOD_ALT) { |
if (e.key.keysym.mod & KMOD_ALT) { |
574 |
void |
void |
575 |
Game::show_menu() |
Game::show_menu() |
576 |
{ |
{ |
577 |
Screen *scr = get_screen(); |
sdl::TempInputGrab grab(SDL_GRAB_OFF); |
|
// TintRect(scr, scr->size(), 0,0,0, 150); |
|
|
// scr->update_all(); |
|
|
|
|
|
video::TempInputGrab grab(SDL_GRAB_OFF); |
|
578 |
|
|
579 |
video::ShowMouse(); |
video::ShowMouse(); |
580 |
GameMenu m; |
GameMenu m; |
581 |
m.manage(scr); |
m.manage(screen); |
582 |
video::HideMouse(); |
video::HideMouse(); |
583 |
update_mouse_button_state(); |
update_mouse_button_state(); |
584 |
last_tick_time = SDL_GetTicks(); |
last_tick_time = SDL_GetTicks(); |
585 |
if (state != ABORT) |
if (state != ABORT) |
586 |
display::RedrawAll(get_screen()); |
display::RedrawAll(screen); |
587 |
} |
} |
588 |
|
|
589 |
namespace |
namespace |
683 |
// Resource management |
// Resource management |
684 |
//---------------------------------------------------------------------- |
//---------------------------------------------------------------------- |
685 |
|
|
|
namespace |
|
|
{ |
|
|
cache::Cache<Font *, FontAlloc> font_cache; |
|
|
cache::Cache<Surface*, ImageAlloc> image_cache; |
|
|
} |
|
|
|
|
686 |
px::Font * |
px::Font * |
687 |
enigma::LoadFont(const char *name) |
enigma::LoadFont (const char *name) |
688 |
{ |
{ |
689 |
string png = string("fonts/") + name + ".png"; |
string png = string("fonts/") + name + ".png"; |
690 |
string bmf = string("fonts/") + name + ".bmf"; |
string bmf = string("fonts/") + name + ".bmf"; |
695 |
px::Font * |
px::Font * |
696 |
enigma::GetFont(const char *name) |
enigma::GetFont(const char *name) |
697 |
{ |
{ |
698 |
return font_cache.get(name); |
return app.font_cache.get(name); |
699 |
} |
} |
700 |
|
|
701 |
px::Surface * |
px::Surface * |
709 |
enigma::GetImage(const char *name) |
enigma::GetImage(const char *name) |
710 |
{ |
{ |
711 |
string filename = FindDataFile(string("gfx/") + name + ".png"); |
string filename = FindDataFile(string("gfx/") + name + ".png"); |
712 |
Surface *s = image_cache.get(filename); |
Surface *s = app.image_cache.get(filename); |
713 |
assert(s); |
assert(s); |
714 |
return s; |
return s; |
715 |
} |
} |
716 |
|
|
|
|
|
|
|
|
717 |
//---------------------------------------------------------------------- |
//---------------------------------------------------------------------- |
718 |
// Startup |
// Startup |
719 |
//---------------------------------------------------------------------- |
//---------------------------------------------------------------------- |
727 |
" --help -h Show this help\n" |
" --help -h Show this help\n" |
728 |
" --version Print the executable's version number\n" |
" --version Print the executable's version number\n" |
729 |
" --8bpp Use 256 color mode\n" |
" --8bpp Use 256 color mode\n" |
730 |
|
" --nograb Do not use exclusive mouse/keyboard access\n" |
731 |
"\n"); |
"\n"); |
732 |
} |
} |
733 |
|
|
751 |
bool nomusic_flag = false; |
bool nomusic_flag = false; |
752 |
bool show_help = false; |
bool show_help = false; |
753 |
bool show_version = false; |
bool show_version = false; |
754 |
for (unsigned i=0; i < ::args.size(); ++i) |
for (unsigned i=0; i < app.args.size(); ++i) |
755 |
{ |
{ |
756 |
string& arg = ::args[i]; |
string& arg = app.args[i]; |
757 |
|
|
758 |
if (arg == "--help" || arg == "-h") |
if (arg == "--help" || arg == "-h") |
759 |
show_help = true; |
show_help = true; |
769 |
options::WizardMode = true; |
options::WizardMode = true; |
770 |
else if (arg == "--8bpp") |
else if (arg == "--8bpp") |
771 |
options::BitsPerPixel = 8; |
options::BitsPerPixel = 8; |
772 |
|
else if (arg == "--nograb") |
773 |
|
options::Nograb = true; |
774 |
else |
else |
775 |
show_help = true; // unknown argument |
show_help = true; // unknown argument |
776 |
} |
} |
844 |
chdir (parentdir); /* chdir to the binary app's parent */ |
chdir (parentdir); /* chdir to the binary app's parent */ |
845 |
chdir ("../Resources/"); /* chdir to the .app's parent */ |
chdir ("../Resources/"); /* chdir to the .app's parent */ |
846 |
#endif //MACOSX |
#endif //MACOSX |
847 |
|
|
848 |
copy(argv+1, argv+argc, back_inserter(::args)); |
app.init(argc,argv); |
849 |
|
|
850 |
init(); |
init(); |
851 |
|
|
852 |
GUI_MainMenu(LevelPacks[0], 0); |
GUI_MainMenu(LevelPacks[0], 0); |