5 |
* modify it under the terms of the GNU General Public License |
* modify it under the terms of the GNU General Public License |
6 |
* as published by the Free Software Foundation; either version 2 |
* as published by the Free Software Foundation; either version 2 |
7 |
* of the License, or (at your option) any later version. |
* of the License, or (at your option) any later version. |
8 |
* |
* |
9 |
* This program is distributed in the hope that it will be useful, |
* This program is distributed in the hope that it will be useful, |
10 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
36 |
//---------------------------------------- |
//---------------------------------------- |
37 |
// Data types |
// Data types |
38 |
//---------------------------------------- |
//---------------------------------------- |
39 |
namespace |
namespace |
40 |
{ |
{ |
41 |
|
|
42 |
class LevelPack_Enigma : public LevelPack { |
class LevelPack_Enigma : public LevelPack { |
48 |
|
|
49 |
string name() const { return m_name; } |
string name() const { return m_name; } |
50 |
size_t size() const { return m_levels.size(); } |
size_t size() const { return m_levels.size(); } |
51 |
|
|
52 |
bool load_level (size_t index) |
bool load_level (size_t index) |
53 |
{ |
{ |
54 |
LevelInfo *levelinfo = get_info(index); |
LevelInfo *levelinfo = get_info(index); |
55 |
return world::Load(levelinfo->filename); |
return world::Load(levelinfo->filename); |
56 |
} |
} |
57 |
|
|
58 |
LevelInfo *get_info (size_t index) { |
LevelInfo *get_info (size_t index) { |
59 |
return &m_levels[index]; |
return &m_levels[index]; |
60 |
}; |
}; |
94 |
void finish_level(); |
void finish_level(); |
95 |
void restart_level(); |
void restart_level(); |
96 |
void restart_game(); |
void restart_game(); |
97 |
|
int get_current_level() const { return icurrent_level; } |
98 |
private: |
private: |
99 |
// Private types. |
// Private types. |
100 |
enum State { |
enum State { |
101 |
INGAME, // game is currently running |
INGAME, // game is currently running |
102 |
LEVELFINISHED, // level finished; proceed to next one |
LEVELFINISHED, // level finished; proceed to next one |
103 |
PLAYERDEAD, // player is dead; restart level shortly |
PLAYERDEAD, // player is dead; restart level shortly |
136 |
// GameMenu impl |
// GameMenu impl |
137 |
//---------------------------------------- |
//---------------------------------------- |
138 |
|
|
139 |
GameMenu::GameMenu() |
GameMenu::GameMenu() |
140 |
: resume(new gui::TextButton("Resume Level", this)), |
: resume(new gui::TextButton("Resume Level", this)), |
141 |
restart(new gui::TextButton("Restart Level", this)), |
restart(new gui::TextButton("Restart Level", this)), |
142 |
options(new gui::TextButton("Options", this)), |
options(new gui::TextButton("Options", this)), |
143 |
abort(new gui::TextButton("Abort Level", this)) |
abort(new gui::TextButton("Abort Level", this)) |
144 |
{ |
{ |
145 |
add(resume, Rect(0,0,150,40)); |
add(resume, Rect(0,0,150,40)); |
146 |
add(restart, Rect(0,45,150,40)); |
add(restart, Rect(0,45,150,40)); |
147 |
add(options, Rect(0,90,150,40)); |
add(options, Rect(0,90,150,40)); |
148 |
add(abort, Rect(0,135,150,40)); |
add(abort, Rect(0,135,150,40)); |
149 |
center(video::GetScreen()); |
center(video::GetScreen()); |
150 |
} |
} |
151 |
|
|
152 |
bool |
bool |
153 |
GameMenu::on_event (const SDL_Event &e) { |
GameMenu::on_event (const SDL_Event &e) { |
154 |
if (e.type == SDL_MOUSEBUTTONDOWN |
if (e.type == SDL_MOUSEBUTTONDOWN |
155 |
&& e.button.button == SDL_BUTTON_RIGHT) |
&& e.button.button == SDL_BUTTON_RIGHT) |
160 |
return false; |
return false; |
161 |
} |
} |
162 |
|
|
163 |
void |
void |
164 |
GameMenu::on_action(gui::Widget *w) { |
GameMenu::on_action(gui::Widget *w) { |
165 |
if (w == resume) { |
if (w == resume) { |
166 |
Menu::quit(); |
Menu::quit(); |
187 |
HelpMenu::HelpMenu() |
HelpMenu::HelpMenu() |
188 |
: ok(new gui::TextButton("Ok", this)) |
: ok(new gui::TextButton("Ok", this)) |
189 |
{ |
{ |
190 |
add(ok, Rect(640-170,480-60,150,40)); |
add(ok, Rect(640-170,480-60,150,40)); |
191 |
} |
} |
192 |
|
|
193 |
bool |
bool |
194 |
HelpMenu::on_event (const SDL_Event &e) |
HelpMenu::on_event (const SDL_Event &e) |
195 |
{ |
{ |
196 |
if (e.type == SDL_MOUSEBUTTONDOWN |
if (e.type == SDL_MOUSEBUTTONDOWN |
197 |
&& e.button.button == SDL_BUTTON_RIGHT) |
&& e.button.button == SDL_BUTTON_RIGHT) |
202 |
return false; |
return false; |
203 |
} |
} |
204 |
|
|
205 |
void |
void |
206 |
HelpMenu::on_action(gui::Widget *w) |
HelpMenu::on_action(gui::Widget *w) |
207 |
{ |
{ |
208 |
if (w == ok) |
if (w == ok) |
209 |
Menu::quit(); |
Menu::quit(); |
210 |
} |
} |
211 |
|
|
212 |
void |
void |
213 |
HelpMenu::draw_background(px::GC &gc) |
HelpMenu::draw_background(px::GC &gc) |
214 |
{ |
{ |
215 |
blit(gc, 0,0, enigma::GetImage("menu_bg")); |
blit(gc, 0,0, enigma::GetImage("menu_bg")); |
223 |
f->render(gc,x,y, "Left mouse button:"); |
f->render(gc,x,y, "Left mouse button:"); |
224 |
f->render(gc,x2,y, "Activate/drop leftmost inventory item"); |
f->render(gc,x2,y, "Activate/drop leftmost inventory item"); |
225 |
y += yskip; |
y += yskip; |
226 |
|
|
227 |
f->render (gc,x,y, "Right mouse button:"); |
f->render (gc,x,y, "Right mouse button:"); |
228 |
f->render (gc,x2,y,"Rotate inventory items"); |
f->render (gc,x2,y,"Rotate inventory items"); |
229 |
y += yskip; |
y += yskip; |
322 |
//---------------------------------------------------------------------- |
//---------------------------------------------------------------------- |
323 |
|
|
324 |
Game::Game() |
Game::Game() |
325 |
: state(INGAME), |
: state(INGAME), |
326 |
icurrent_level(0), |
icurrent_level(0), |
327 |
last_tick_time(0), |
last_tick_time(0), |
328 |
screen (0) |
screen (0) |
329 |
{ |
{ |
330 |
} |
} |
331 |
|
|
332 |
void |
void |
333 |
Game::quit() |
Game::quit() |
334 |
{ |
{ |
335 |
change_state(ABORT); |
change_state(ABORT); |
336 |
} |
} |
337 |
|
|
338 |
void |
void |
339 |
Game::finish_level() |
Game::finish_level() |
340 |
{ |
{ |
341 |
change_state(LEVELFINISHED); |
change_state(LEVELFINISHED); |
342 |
} |
} |
343 |
|
|
344 |
void Game::restart_level() |
void Game::restart_level() |
345 |
{ |
{ |
346 |
change_state(RELOADLEVEL); |
change_state(RELOADLEVEL); |
347 |
} |
} |
348 |
|
|
349 |
void Game::restart_game() |
void Game::restart_game() |
352 |
} |
} |
353 |
|
|
354 |
|
|
355 |
void |
void |
356 |
Game::change_state(State newstate) |
Game::change_state(State newstate) |
357 |
{ |
{ |
358 |
if (state == newstate) return; |
if (state == newstate) return; |
366 |
sound::PlaySound("finished"); |
sound::PlaySound("finished"); |
367 |
display::GetStatusBar()->show_text("Level finished!", display::TEXT_STATIC); |
display::GetStatusBar()->show_text("Level finished!", display::TEXT_STATIC); |
368 |
player::LevelFinished(); // remove player-controlled actors |
player::LevelFinished(); // remove player-controlled actors |
369 |
|
|
370 |
options::SetLevelFinished |
options::SetLevelFinished |
371 |
(level_pack->name(), |
(level_pack->name(), |
372 |
level_pack->get_info(icurrent_level)->filename, |
level_pack->get_info(icurrent_level)->filename, |
393 |
|
|
394 |
try_next: |
try_next: |
395 |
next_level++; |
next_level++; |
396 |
|
|
397 |
if (next_level >= level_pack->size()) { |
if (next_level >= level_pack->size()) { |
398 |
change_state(ABORT); // no next level in level pack |
change_state(ABORT); // no next level in level pack |
399 |
} |
} |
400 |
else { |
else { |
401 |
LevelInfo *info = level_pack->get_info(next_level); |
LevelInfo *info = level_pack->get_info(next_level); |
402 |
options::LevelStatus *ls = |
options::LevelStatus *ls = |
403 |
options::GetLevelStatus(level_pack->name(), |
options::GetLevelStatus(level_pack->name(), |
404 |
info->filename); |
info->filename); |
405 |
|
|
406 |
if (info->filename == "todo") |
if (info->filename == "todo") |
407 |
goto try_next; // Skip todo levels |
goto try_next; // Skip todo levels |
408 |
|
|
409 |
if (options::SkipSolvedLevels && ls && ls->finished) |
if (options::SkipSolvedLevels && ls && ls->finished) |
410 |
goto try_next; // Skip solved level |
goto try_next; // Skip solved level |
411 |
|
|
412 |
// this level is ok. |
// this level is ok. |
413 |
load_level(next_level); |
load_level(next_level); |
414 |
change_state(LEVELINFO); |
change_state(LEVELINFO); |
424 |
player::NewGame(2); // two virtual players |
player::NewGame(2); // two virtual players |
425 |
if( ! load_level(icurrent_level)) { |
if( ! load_level(icurrent_level)) { |
426 |
change_state(ABORT); |
change_state(ABORT); |
427 |
} else |
} else |
428 |
change_state(INGAME); |
change_state(INGAME); |
429 |
break; |
break; |
430 |
|
|
491 |
} |
} |
492 |
|
|
493 |
bool |
bool |
494 |
Game::load_level(int ilevel) |
Game::load_level(int ilevel) |
495 |
{ |
{ |
496 |
if (level_pack->load_level (ilevel)) |
if (level_pack->load_level (ilevel)) |
497 |
{ |
{ |
551 |
double dtime=0; |
double dtime=0; |
552 |
|
|
553 |
state = RESTARTGAME; |
state = RESTARTGAME; |
554 |
while (state != ABORT) |
while (state != ABORT) |
555 |
{ |
{ |
556 |
last_tick_time=SDL_GetTicks(); |
last_tick_time=SDL_GetTicks(); |
557 |
|
|
568 |
if (abs(adtime-dtime)/adtime < 0.1) { |
if (abs(adtime-dtime)/adtime < 0.1) { |
569 |
// less than 10% deviation from average frame time? |
// less than 10% deviation from average frame time? |
570 |
dtime = adtime; |
dtime = adtime; |
571 |
} |
} |
572 |
|
|
573 |
if (dtime > 500.0) /* Time has done something strange, perhaps |
if (dtime > 500.0) /* Time has done something strange, perhaps |
574 |
run backwards */ |
run backwards */ |
584 |
{ |
{ |
585 |
px::V2 force(xrel, yrel); |
px::V2 force(xrel, yrel); |
586 |
double f = length(force); |
double f = length(force); |
587 |
if (f > 0) |
if (f > 0) |
588 |
{ |
{ |
589 |
force *= options::MouseSpeed; |
force *= options::MouseSpeed; |
590 |
world::SetMouseForce(force); |
world::SetMouseForce(force); |
595 |
Game::handle_events() |
Game::handle_events() |
596 |
{ |
{ |
597 |
SDL_Event e; |
SDL_Event e; |
598 |
while (SDL_PollEvent(&e)) |
while (SDL_PollEvent(&e)) |
599 |
{ |
{ |
600 |
switch (e.type) { |
switch (e.type) { |
601 |
case SDL_KEYDOWN: |
case SDL_KEYDOWN: |
633 |
display::GetStatusBar()->hide_text(); |
display::GetStatusBar()->hide_text(); |
634 |
player::RotateInventory(); |
player::RotateInventory(); |
635 |
} |
} |
636 |
} |
} |
637 |
update_mouse_button_state(); |
update_mouse_button_state(); |
638 |
} |
} |
639 |
|
|
680 |
|
|
681 |
case SDLK_F10: |
case SDLK_F10: |
682 |
{ |
{ |
683 |
string fname = level_pack->get_info(icurrent_level)->filename + ".bmp"; |
string fname = level_pack->get_info(icurrent_level)->filename + ".bmp"; |
684 |
video::Screenshot(fname.c_str()); |
video::Screenshot(fname.c_str()); |
685 |
} |
} |
686 |
break; |
break; |
724 |
} |
} |
725 |
} |
} |
726 |
|
|
727 |
void |
void |
728 |
Game::show_help() |
Game::show_help() |
729 |
{ |
{ |
730 |
sdl::TempInputGrab grab(SDL_GRAB_OFF); |
sdl::TempInputGrab grab(SDL_GRAB_OFF); |
737 |
display::RedrawAll(screen); |
display::RedrawAll(screen); |
738 |
} |
} |
739 |
|
|
740 |
void |
void |
741 |
Game::show_menu() |
Game::show_menu() |
742 |
{ |
{ |
743 |
sdl::TempInputGrab grab(SDL_GRAB_OFF); |
sdl::TempInputGrab grab(SDL_GRAB_OFF); |
753 |
|
|
754 |
|
|
755 |
//---------------------------------------------------------------------- |
//---------------------------------------------------------------------- |
756 |
// VARIABLES / FUNCTIONS |
// VARIABLES / FUNCTIONS |
757 |
//---------------------------------------------------------------------- |
//---------------------------------------------------------------------- |
758 |
|
|
759 |
namespace |
namespace |
764 |
bool enigma::ConserveLevel = false; |
bool enigma::ConserveLevel = false; |
765 |
int enigma::Difficulty = 1; |
int enigma::Difficulty = 1; |
766 |
|
|
767 |
void |
unsigned |
768 |
enigma::StartGame (LevelPack *lp, unsigned levelidx) |
enigma::StartGame (LevelPack *lp, unsigned levelidx) |
769 |
{ |
{ |
770 |
if (lp->get_info(levelidx)->filename != "todo") |
if (lp->get_info(levelidx)->filename != "todo") { |
771 |
game_inst.run (lp, levelidx); |
game_inst.run (lp, levelidx); |
772 |
|
levelidx = game_inst.get_current_level(); |
773 |
|
} |
774 |
|
return levelidx; |
775 |
} |
} |
776 |
|
|
777 |
|
|