28 |
#include "system.hh" |
#include "system.hh" |
29 |
#include "gui.hh" |
#include "gui.hh" |
30 |
#include "video.hh" |
#include "video.hh" |
31 |
|
#include "menus.hh" |
32 |
|
|
33 |
#include "px/px.hh" |
#include "px/px.hh" |
34 |
#include "px/cache.hh" |
#include "px/cache.hh" |
42 |
#include <string> |
#include <string> |
43 |
#include <cassert> |
#include <cassert> |
44 |
#include <algorithm> |
#include <algorithm> |
45 |
|
#include <fstream> |
46 |
|
|
47 |
using namespace std; |
using namespace std; |
48 |
using namespace px; |
using namespace px; |
49 |
using namespace enigma; |
using namespace enigma; |
50 |
|
|
|
|
|
51 |
namespace |
namespace |
52 |
{ |
{ |
|
void optionsmenu(); |
|
|
void gamemenu(); |
|
|
|
|
53 |
void flush_events() |
void flush_events() |
54 |
{ |
{ |
55 |
SDL_Event e; |
SDL_Event e; |
56 |
while (SDL_PollEvent(&e)) ; |
while (SDL_PollEvent(&e)) |
57 |
|
; |
58 |
} |
} |
59 |
inline px::Screen *get_screen() { return video::GetScreen(); } |
inline px::Screen *get_screen() { return video::GetScreen(); } |
60 |
} |
} |
61 |
|
|
62 |
Direction |
Direction |
81 |
{ |
{ |
82 |
using gui::TextButton; |
using gui::TextButton; |
83 |
|
|
84 |
class GameMenu : public gui::Menu, gui::ActionListener { |
class GameMenu : public gui::Menu { |
85 |
public: |
public: |
86 |
GameMenu() |
GameMenu() |
87 |
: resume(new TextButton("Resume Level", this)), |
: resume(new TextButton("Resume Level", this)), |
117 |
gui::Widget *resume, *restart, *options, *abort; |
gui::Widget *resume, *restart, *options, *abort; |
118 |
}; |
}; |
119 |
|
|
120 |
|
class FontAlloc { |
121 |
|
public: |
122 |
|
Font *acquire(const std::string &name) { |
123 |
|
string fname = enigma::FindDataFile(string("fonts/") + name + ".png"); |
124 |
|
string dname = enigma::FindDataFile(string("fonts/") + name + ".bmf"); |
125 |
|
return px::LoadBitmapFont(fname.c_str(), dname.c_str()); |
126 |
|
} |
127 |
|
void release(Font *f) { delete f; } |
128 |
|
}; |
129 |
|
|
130 |
class ImageAlloc { |
class ImageAlloc { |
131 |
public: |
public: |
132 |
Surface *acquire(const std::string &name) { |
Surface *acquire(const std::string &name) { |
145 |
|
|
146 |
namespace |
namespace |
147 |
{ |
{ |
|
struct LevelInfo |
|
|
{ |
|
|
LevelInfo(const string &fn, const string &n, const string &a) |
|
|
: filename(fn), name(n), author(a) |
|
|
{ |
|
|
hidden=false; |
|
|
playable=true; |
|
|
completed=false; |
|
|
best_time = 99.59*60; // 99.59 minutes |
|
|
} |
|
|
|
|
|
string filename; |
|
|
string name; |
|
|
string author; |
|
|
bool hidden; |
|
|
bool playable; |
|
|
bool completed; |
|
|
double best_time; // Best time in seconds |
|
|
}; |
|
|
} |
|
|
|
|
|
|
|
|
namespace |
|
|
{ |
|
|
vector<LevelInfo> levels; |
|
|
|
|
148 |
vector<string> args; // List of command line arguments. |
vector<string> args; // List of command line arguments. |
|
bool quit_mainmenu; |
|
|
} |
|
|
|
|
|
|
|
|
//---------------------------------------- |
|
|
// LevelMenu implementation |
|
|
//---------------------------------------- |
|
|
namespace |
|
|
{ |
|
|
class LevelMenu { |
|
|
public: |
|
|
LevelMenu(); |
|
|
bool manage (); |
|
|
int current_level() const { return iselected; } |
|
|
|
|
|
void paint (Surface *scr); |
|
|
private: |
|
|
|
|
|
// Private functions. |
|
|
void redraw (); |
|
|
void set_selected (int newfirst, int newsel); |
|
|
|
|
|
void scroll_up(int lines); |
|
|
void scroll_down(int lines); |
|
|
|
|
|
// Event handling. |
|
|
void handle_event (SDL_Event *e); |
|
|
void handle_keydown (SDL_Event *e); |
|
|
void handle_mousedown (SDL_Event *e); |
|
|
|
|
|
|
|
|
// Variables. |
|
|
ImageCache cache; |
|
|
int ifirst; // Index of "upper left" level |
|
|
int iselected; // Index of selected level |
|
|
int width, height; |
|
|
Font *smallfnt; |
|
|
vector<Rect> areas; // Screen-areas occupied by level previews |
|
|
bool redraw_p; |
|
|
bool show_filenames_p; |
|
|
bool abort_menu_p; |
|
|
bool exit_menu_p; |
|
|
}; |
|
149 |
} |
} |
150 |
|
|
151 |
LevelMenu::LevelMenu() |
vector<LevelPack *> enigma::LevelPacks; |
|
: ifirst(0), iselected(0), |
|
|
width(3), height(3), |
|
|
smallfnt(enigma::GetFont("levelmenu")), |
|
|
areas(), |
|
|
redraw_p(true), |
|
|
show_filenames_p(false) |
|
|
{} |
|
|
|
|
|
void |
|
|
LevelMenu::scroll_up(int nlines) |
|
|
{ |
|
|
for (; nlines; --nlines) { |
|
|
if (ifirst+width*height > (int)levels.size()) |
|
|
break; |
|
|
ifirst += width; |
|
|
if (iselected < ifirst) |
|
|
iselected += width; |
|
|
redraw_p=true; |
|
|
} |
|
|
} |
|
152 |
|
|
153 |
void |
//---------------------------------------------------------------------- |
154 |
LevelMenu::scroll_down(int nlines) |
// Level management |
155 |
{ |
//---------------------------------------------------------------------- |
|
for (; nlines; --nlines) { |
|
|
if (ifirst < width) |
|
|
break; |
|
|
ifirst -= width; |
|
|
if (iselected >= ifirst+width*height) |
|
|
iselected -= width; |
|
|
redraw_p = true; |
|
|
} |
|
|
} |
|
|
|
|
|
void |
|
|
LevelMenu::paint (Surface *sfc) |
|
|
{ |
|
|
GC gc(sfc->get_drawable()); |
|
|
|
|
|
areas.clear(); |
|
|
|
|
|
blit(gc, 0,0, enigma::GetImage("menu_bg")); |
|
|
|
|
|
const int imgw = 160; |
|
|
const int imgh = 104; |
|
|
const int hgap = 20, vgap=40; |
|
|
|
|
|
const int x0 = (sfc->width() - width*(imgw+hgap)+hgap)/2; |
|
|
const int y0 = 30; |
|
|
|
|
|
unsigned i=ifirst; |
|
|
for (int y=0; y<height; y++) |
|
|
{ |
|
|
for (int x=0; x<width; x++, i++) |
|
|
{ |
|
|
if (i >= levels.size()) |
|
|
goto done_painting; |
|
|
|
|
|
int xpos = x0 + x*(imgw + hgap); |
|
|
int ypos = y0 + y*(imgh + vgap); |
|
|
areas.push_back(Rect(xpos-hgap/2, ypos-hgap/2, |
|
|
imgw+hgap, imgh+hgap+vgap/2)); |
|
|
|
|
|
string fname = string("levels/") + levels[i].filename + ".png"; |
|
|
if (Surface *img = cache.get(enigma::FindDataFile(fname))) |
|
|
blit (gc, xpos, ypos, img); |
|
|
|
|
|
if (levels[i].completed) { |
|
|
blit (gc, xpos, ypos, enigma::GetImage("completed")); |
|
|
} |
|
|
|
|
|
char str[10]; |
|
|
sprintf(str, "#%d ",i+1); |
|
|
|
|
|
string tstr(str); |
|
|
if (show_filenames_p) |
|
|
tstr += levels[i].filename; |
|
|
else |
|
|
tstr += levels[i].name; |
|
|
smallfnt->render (gc, |
|
|
xpos+(imgw-smallfnt->get_width(tstr.c_str()))/2, |
|
|
ypos+imgh+1, |
|
|
tstr.c_str()); |
|
|
} |
|
|
} |
|
|
done_painting: |
|
|
|
|
|
set_color(gc, 255,0,0); |
|
|
Rect a=areas[iselected-ifirst]; |
|
|
frame(gc, a); |
|
|
frame(gc, smaller(a,1)); |
|
|
frame(gc, smaller(a,2)); |
|
|
} |
|
|
|
|
|
void |
|
|
LevelMenu::redraw() |
|
|
{ |
|
|
Screen *screen = video::GetScreen(); |
|
|
|
|
|
if (redraw_p) { |
|
|
redraw_p=false; |
|
|
|
|
|
video::HideMouse(); |
|
|
paint (screen); |
|
|
video::ShowMouse(); |
|
|
|
|
|
screen->update_all(); |
|
|
} |
|
|
screen->flush_updates(); |
|
|
} |
|
|
|
|
|
|
|
|
void |
|
|
LevelMenu::set_selected (int newfirst, int newsel) |
|
|
{ |
|
|
if (newfirst!=ifirst && newfirst>=0 && newfirst<(int)levels.size()) |
|
|
{ |
|
|
sound::PlaySound("menumove"); |
|
|
ifirst = newfirst; |
|
|
iselected = Max(Min(newsel,(int)levels.size()-1), 0); |
|
|
redraw_p = true; |
|
|
} |
|
|
else if (newsel!=iselected && newsel>=0 && newsel<(int)levels.size()) |
|
|
{ |
|
|
sound::PlaySound("menumove"); |
|
|
while (newsel < ifirst) |
|
|
ifirst -= width; |
|
|
while (newsel >= ifirst+width*height) |
|
|
ifirst += width; |
|
|
iselected = newsel; |
|
|
redraw_p = true; |
|
|
} |
|
|
} |
|
|
|
|
|
void |
|
|
LevelMenu::handle_event (SDL_Event *e) |
|
|
{ |
|
|
switch (e->type) { |
|
|
case SDL_MOUSEBUTTONDOWN: |
|
|
handle_mousedown (e); |
|
|
break; |
|
|
case SDL_QUIT: |
|
|
abort_menu_p = true; |
|
|
quit_mainmenu = true; |
|
|
break; |
|
|
|
|
|
case SDL_KEYDOWN: |
|
|
handle_keydown (e); |
|
|
break; |
|
|
} |
|
|
} |
|
|
|
|
|
void |
|
|
LevelMenu::handle_mousedown (SDL_Event *e) |
|
|
{ |
|
|
switch (e->button.button) { |
|
|
case SDL_BUTTON_LEFT: |
|
|
for (unsigned i=0; i<areas.size(); ++i) |
|
|
if (areas[i].contains(e->button.x, e->button.y)) |
|
|
{ |
|
|
sound::PlaySound("menuok"); |
|
|
iselected = ifirst+i; |
|
|
exit_menu_p = true; |
|
|
} |
|
|
break; |
|
|
case SDL_BUTTON_RIGHT: |
|
|
abort_menu_p = true; |
|
|
break; |
|
|
case 4: scroll_down(1); break; |
|
|
case 5: scroll_up(1); break; |
|
|
} |
|
|
} |
|
156 |
|
|
157 |
|
// Run init_file to initialize the level list. |
158 |
void |
void |
159 |
LevelMenu::handle_keydown (SDL_Event *e) |
LevelPack::init() |
160 |
{ |
{ |
161 |
switch (e->key.keysym.sym) { |
levels.clear(); |
|
case SDLK_t: |
|
|
show_filenames_p = !show_filenames_p; |
|
|
redraw_p = true; |
|
|
break; |
|
|
case SDLK_LEFT: set_selected (ifirst, iselected-1); break; |
|
|
case SDLK_RIGHT: set_selected (ifirst, iselected+1); break; |
|
|
case SDLK_DOWN: set_selected (ifirst, iselected+width); break; |
|
|
case SDLK_UP: set_selected (ifirst, iselected-width); break; |
|
|
case SDLK_PAGEDOWN: |
|
|
set_selected (ifirst + width*height, iselected + width*height); |
|
|
break; |
|
|
case SDLK_PAGEUP: |
|
|
set_selected (ifirst - width*height, iselected - width*height); |
|
|
break; |
|
|
case SDLK_HOME: set_selected (0,0); break; |
|
|
case SDLK_END: set_selected (ifirst, levels.size()-1); break; |
|
162 |
|
|
163 |
case SDLK_RETURN: |
string filename = enigma::FindDataFile(init_file); |
164 |
exit_menu_p = true; |
ifstream is(filename.c_str()); |
|
break; |
|
165 |
|
|
166 |
case SDLK_ESCAPE: |
if (!is) { |
167 |
abort_menu_p = true; |
fprintf(stderr, "Couldn't load level pack %s.\n", filename.c_str()); |
168 |
break; |
return; |
|
default: |
|
|
break; |
|
169 |
} |
} |
|
|
|
|
} |
|
|
|
|
|
bool |
|
|
LevelMenu::manage () |
|
|
{ |
|
|
redraw_p = true; |
|
|
SDL_Event e; |
|
170 |
|
|
171 |
exit_menu_p = abort_menu_p = false; |
string line; |
172 |
while (!exit_menu_p && !abort_menu_p) |
vector<string> tokens; |
173 |
{ |
while (getline(is, line)) { |
174 |
redraw(); |
split_copy(line, ',', back_inserter(tokens)); |
175 |
SDL_Delay(10); |
transform(tokens.begin(), tokens.end(), |
176 |
|
tokens.begin(), trim<char>); |
177 |
if (SDL_PollEvent(&e)) |
if (tokens.size() == 2) |
178 |
handle_event(&e); |
levels.push_back(LevelInfo(tokens[0], tokens[1], "")); |
179 |
|
tokens.clear(); |
180 |
} |
} |
|
cache.clear(); |
|
|
return !abort_menu_p; |
|
181 |
} |
} |
182 |
|
|
183 |
|
void |
184 |
//---------------------------------------------------------------------- |
enigma::AddLevelPack (const char *init_file, const char *name) |
|
// Level list |
|
|
//---------------------------------------------------------------------- |
|
|
|
|
|
void |
|
|
enigma::ClearLevelList() |
|
|
{ |
|
|
levels.clear(); |
|
|
} |
|
|
|
|
|
void |
|
|
enigma::AddLevel (const char *filename, const char *name) |
|
185 |
{ |
{ |
186 |
if( strcmp( filename, "todo")) |
LevelPack *lp = new LevelPack(init_file, name); |
187 |
levels.push_back(LevelInfo(filename, name, "")); |
LevelPacks.push_back(lp); |
188 |
|
lp->init(); |
189 |
} |
} |
190 |
|
|
191 |
//---------------------------------------------------------------------- |
//---------------------------------------------------------------------- |
196 |
class Game { |
class Game { |
197 |
public: |
public: |
198 |
Game(); |
Game(); |
199 |
void run(int ilevel); |
void run(LevelPack *lp, int ilevel); |
200 |
void quit() { change_state(ABORT); } |
void quit() { change_state(ABORT); } |
201 |
void next_level() { change_state(NEXTLEVEL); } |
void next_level() { change_state(NEXTLEVEL); } |
202 |
void restart_level() { change_state(RESTARTLEVEL); } |
void restart_level() { change_state(RESTARTLEVEL); } |
237 |
I_NORMAL, I_MESSAGE, I_COMMAND |
I_NORMAL, I_MESSAGE, I_COMMAND |
238 |
} input_state; |
} input_state; |
239 |
|
|
240 |
|
LevelPack *level_pack; |
241 |
unsigned icurrent_level; |
unsigned icurrent_level; |
242 |
Uint32 last_tick_time; |
Uint32 last_tick_time; |
243 |
double level_finished_dtime; |
double level_finished_dtime; |
270 |
case NEXTLEVEL: |
case NEXTLEVEL: |
271 |
level_finished_dtime=0; |
level_finished_dtime=0; |
272 |
display::GetStatusBar()->show_text("Level finished!", display::TEXT_STATIC); |
display::GetStatusBar()->show_text("Level finished!", display::TEXT_STATIC); |
273 |
|
player::LevelFinished(); // remove player-controlled actors |
274 |
break; |
break; |
275 |
case PLAYERDEAD: |
case PLAYERDEAD: |
276 |
actor_dead_dtime=0; |
actor_dead_dtime=0; |
323 |
display::Tick(dtime); |
display::Tick(dtime); |
324 |
display::Redraw(get_screen()); |
display::Redraw(get_screen()); |
325 |
} else { |
} else { |
326 |
|
vector<LevelInfo> &levels = level_pack->levels; |
327 |
|
|
328 |
if (1+icurrent_level == levels.size()) |
if (1+icurrent_level == levels.size()) |
329 |
change_state(ABORT); |
change_state(ABORT); |
330 |
else { |
else { |
331 |
levels[icurrent_level].completed = true; |
options::SetLevelFinished(level_pack->name, |
332 |
|
levels[icurrent_level].filename, |
333 |
|
2); // difficulty |
334 |
|
// levels[icurrent_level].completed = true; |
335 |
load_level(1+icurrent_level); |
load_level(1+icurrent_level); |
336 |
change_state(LEVELINFO); |
change_state(LEVELINFO); |
337 |
} |
} |
361 |
Game::load_level(int ilevel) |
Game::load_level(int ilevel) |
362 |
{ |
{ |
363 |
// FX_Fade(video::FADEOUT); |
// FX_Fade(video::FADEOUT); |
364 |
|
vector<LevelInfo> &levels = level_pack->levels; |
365 |
|
|
366 |
icurrent_level=ilevel; |
icurrent_level=ilevel; |
367 |
world::Load(levels[icurrent_level].filename); |
world::Load(levels[icurrent_level].filename); |
375 |
} |
} |
376 |
|
|
377 |
void |
void |
378 |
Game::run(int ilevel) |
Game::run (LevelPack *lp, int ilevel) |
379 |
{ |
{ |
380 |
|
level_pack = lp; |
381 |
player::NewGame(2); // two virtual players |
player::NewGame(2); // two virtual players |
382 |
|
|
383 |
|
video::TempInputGrab grab(SDL_GRAB_ON); |
384 |
|
video::HideMouse(); |
385 |
// sound::PlayMusic("/sound/Emilie.xm"); |
// sound::PlayMusic("/sound/Emilie.xm"); |
386 |
sound::FadeoutMusic(); |
sound::FadeoutMusic(); |
387 |
sound::StopMusic(); |
sound::StopMusic(); |
407 |
else if (dtime > 0.5) |
else if (dtime > 0.5) |
408 |
dtime = 0.5; |
dtime = 0.5; |
409 |
} |
} |
410 |
|
video::ShowMouse(); |
411 |
} |
} |
412 |
|
|
413 |
void |
void |
474 |
break; |
break; |
475 |
case SDLK_F10: |
case SDLK_F10: |
476 |
{ |
{ |
477 |
string fname = levels[icurrent_level].filename + ".bmp"; |
string fname = level_pack->levels[icurrent_level].filename + ".bmp"; |
478 |
video::Screenshot(fname.c_str()); |
video::Screenshot(fname.c_str()); |
479 |
} |
} |
480 |
break; |
break; |
484 |
case SDLK_x: |
case SDLK_x: |
485 |
if (e.key.keysym.mod & KMOD_ALT) { |
if (e.key.keysym.mod & KMOD_ALT) { |
486 |
change_state(ABORT); |
change_state(ABORT); |
|
quit_mainmenu = true; |
|
487 |
} |
} |
488 |
break; |
break; |
489 |
default: |
default: |
531 |
// TintRect(scr, scr->size(), 0,0,0, 150); |
// TintRect(scr, scr->size(), 0,0,0, 150); |
532 |
// scr->update_all(); |
// scr->update_all(); |
533 |
|
|
534 |
|
video::TempInputGrab grab(SDL_GRAB_OFF); |
535 |
|
|
536 |
video::ShowMouse(); |
video::ShowMouse(); |
537 |
GameMenu m; |
GameMenu m; |
538 |
m.manage(scr); |
m.manage(scr); |
549 |
|
|
550 |
bool enigma::ConserveLevel = false; |
bool enigma::ConserveLevel = false; |
551 |
|
|
552 |
static void |
void enigma::StartGame (LevelPack *lp, unsigned levelidx) { |
553 |
game() |
game_inst.run (lp, levelidx); |
|
{ |
|
|
if (levels.empty()) |
|
|
lua::Dofile("levels/index.lua"); |
|
|
|
|
|
if (levels.empty()) { |
|
|
fprintf(stderr, "Error: No levels defined\n"); |
|
|
return; |
|
|
} |
|
|
|
|
|
LevelMenu lm; |
|
|
|
|
|
{ |
|
|
Surface *sfc = video::BackBuffer(); |
|
|
lm.paint (sfc); |
|
|
ShowScreen (video::TM_PUSH_RANDOM, sfc); |
|
|
} |
|
|
|
|
|
while (lm.manage()) |
|
|
{ |
|
|
video::HideMouse(); |
|
|
game_inst.run (lm.current_level()); |
|
|
video::ShowMouse(); |
|
|
} |
|
554 |
} |
} |
555 |
|
|
556 |
|
|
557 |
void enigma::FinishLevel() { |
void enigma::FinishLevel() { |
558 |
game_inst.next_level(); |
game_inst.next_level(); |
559 |
} |
} |
567 |
} |
} |
568 |
|
|
569 |
//---------------------------------------------------------------------- |
//---------------------------------------------------------------------- |
570 |
// Main menu |
// Data path |
571 |
//---------------------------------------------------------------------- |
//---------------------------------------------------------------------- |
572 |
namespace |
namespace |
573 |
{ |
{ |
|
class MainMenu : public gui::Menu, public gui::ActionListener { |
|
|
public: |
|
|
MainMenu() |
|
|
: newgame(new gui::TextButton("New Game", this)), |
|
|
leveled(new gui::TextButton("Level Editor", this)), |
|
|
options(new gui::TextButton("Options", this)), |
|
|
credits(new gui::TextButton("Credits", this)), |
|
|
quit(new gui::TextButton("Quit", this)) |
|
|
{ |
|
|
int x0=(640-150)/2; |
|
|
int y0=200; |
|
|
add(newgame, Rect(x0,y0,150,40)); |
|
|
add(leveled, Rect(x0,y0+50,150,40)); |
|
|
add(options, Rect(x0,y0+100,150,40)); |
|
|
add(credits, Rect(x0,y0+150,150,40)); |
|
|
add(quit, Rect(x0,y0+200,150,40)); |
|
|
} |
|
|
private: |
|
|
// Menu interface. |
|
|
void draw_background(px::GC &gc) |
|
|
{ |
|
|
video::SetCaption("Enigma - Main Menu"); |
|
|
sound::PlayMusic("sound/menu.s3m"); |
|
|
|
|
|
blit(gc, 0,0, enigma::GetImage("menu_bg")); |
|
|
|
|
|
Font *f = enigma::GetFont("levelmenu"); |
|
|
Surface * logo(enigma::GetImage("enigma_logo3")); |
|
|
int x0=(640-logo->width())/2; |
|
|
int y0=40; |
|
|
blit(gc, x0, y0, logo); |
|
|
f->render (get_screen(), 5, 460, "v" VERSION); |
|
|
} |
|
|
|
|
|
// ActionListener interface. |
|
|
void on_action(gui::Widget *w) { |
|
|
if (w == newgame) { |
|
|
game(); |
|
|
invalidate_all(); |
|
|
} else if (w == leveled) { |
|
|
editor::Run(); |
|
|
invalidate_all(); |
|
|
} else if (w == options) { |
|
|
optionsmenu(); |
|
|
invalidate_all(); |
|
|
} else if (w == credits) { |
|
|
show_credits (); |
|
|
invalidate_all (); |
|
|
} else if (w == quit) { |
|
|
Menu::quit(); |
|
|
} |
|
|
} |
|
|
|
|
|
// Private methods. |
|
|
void show_credits () |
|
|
{ |
|
|
static char *credits[] = { |
|
|
"Main developer:", |
|
|
" DANIEL HECK", |
|
|
"", |
|
|
"Additional Programming:", |
|
|
" SIEGFRIED FENNIG, MARTIN HAWLISCH, NAT PRYCE", |
|
|
"", |
|
|
"Level Design:", |
|
|
" SIEGFRIED FENNIG, MARTIN HAWLISCH, DANIEL HECK, NAT PRYCE", |
|
|
"", |
|
|
"Graphics:", |
|
|
" SIEGFRIED FENNIG, JOHANNES FORTMANN, MARTIN HAWLISCH,", |
|
|
" DANIEL HECK", |
|
|
"", |
|
|
"Music:", |
|
|
" ANDREW \"NECROS\" SEGA", |
|
|
"", |
|
|
"", |
|
|
"Enigma is free software and may be distributed under the", |
|
|
"terms of the GNU General Public License, version 2. See", |
|
|
"the accompanying COPYING.GPL for details.", |
|
|
0 |
|
|
}; |
|
|
|
|
|
Screen *scr = get_screen (); |
|
|
GC gc (scr->get_drawable()); |
|
|
blit (gc, 0,0, enigma::GetImage("menu_bg")); |
|
|
|
|
|
|
|
|
Font *f = enigma::GetFont("menufont"); |
|
|
for (int i=0; credits[i]; ++i) |
|
|
{ |
|
|
f->render (scr, 40, 40+i*f->get_height(), credits[i]); |
|
|
} |
|
|
scr->update_all (); |
|
|
scr->flush_updates(); |
|
|
|
|
|
SDL_Event e; |
|
|
for (;;) { |
|
|
SDL_WaitEvent(&e); |
|
|
if (e.type == SDL_KEYDOWN || e.type == SDL_MOUSEBUTTONDOWN) |
|
|
break; |
|
|
} |
|
|
} |
|
|
|
|
|
// Variables. |
|
|
gui::Widget *newgame, *leveled, *options; |
|
|
gui::Widget *credits, *quit; |
|
|
}; |
|
|
|
|
|
void mainmenu() |
|
|
{ |
|
|
video::SetMouseCursor(enigma::LoadImage("it-magicwand"), 4, 4); |
|
|
video::ShowMouse(); |
|
|
|
|
|
MainMenu m; |
|
|
m.manage(get_screen()); |
|
|
} |
|
|
} |
|
|
|
|
|
namespace |
|
|
{ |
|
|
class Button : public gui::TextButton, gui::ActionListener { |
|
|
public: |
|
|
Button () : TextButton("", this) {} |
|
|
}; |
|
|
|
|
|
class FullscreenButton : public Button { |
|
|
void update() { |
|
|
if (options::FullScreen > 0) |
|
|
set_text("Window"); |
|
|
else |
|
|
set_text("Fullscreen"); |
|
|
} |
|
|
// ActionListener interface. |
|
|
void on_action(Widget *) { |
|
|
video::ToggleFullscreen(); |
|
|
update(); |
|
|
} |
|
|
public: |
|
|
}; |
|
|
|
|
|
class AlphaShadowButton : public Button { |
|
|
void update() { |
|
|
// if (lua::get_num("AlphaShadows") > 0) |
|
|
// set_text("Blended Shadows"); |
|
|
// else |
|
|
// set_text("Stippled Shadows"); |
|
|
} |
|
|
// ActionListener interface. |
|
|
void on_action(Widget *) { |
|
|
// video::ToggleFullscreen(); |
|
|
update(); |
|
|
} |
|
|
}; |
|
|
|
|
|
class SoundVolumeButton : public Button { |
|
|
void update() { |
|
|
set_text("Sound volume"); |
|
|
} |
|
|
void on_action(Widget *w) { |
|
|
update(); |
|
|
} |
|
|
}; |
|
|
|
|
|
class MouseSpeedButton : public Button { |
|
|
void update() { |
|
|
set_text("Mouse speed: 10"); |
|
|
} |
|
|
void on_action(Widget *w) { |
|
|
update(); |
|
|
} |
|
|
}; |
|
|
|
|
|
|
|
|
class OptionsMenu : public gui::Menu, public gui::ActionListener { |
|
|
public: |
|
|
OptionsMenu() : quit(new TextButton("Back", this)) |
|
|
{ |
|
|
add(new FullscreenButton, Rect(0,0,150,40)); |
|
|
add (new SoundVolumeButton, Rect (0,50,150,40)); |
|
|
add (new MouseSpeedButton, Rect (0,100,150,40)); |
|
|
// add(new AlphaShadowButton, Rect(0,50,150,40)); |
|
|
add(quit, Rect(0,150,150,40)); |
|
|
} |
|
|
private: |
|
|
|
|
|
// ActionListener interface. |
|
|
void on_action(gui::Widget *w) |
|
|
{ |
|
|
if (w == quit) |
|
|
Menu::quit(); |
|
|
} |
|
|
|
|
|
// Menu interface. |
|
|
void draw_background(px::GC &gc) |
|
|
{ |
|
|
video::SetCaption("Enigma - Options Menu"); |
|
|
blit(gc, 0,0, enigma::GetImage("menu_bg")); |
|
|
} |
|
|
|
|
|
gui::Widget *quit; |
|
|
}; |
|
|
|
|
|
|
|
|
void optionsmenu() |
|
|
{ |
|
|
OptionsMenu m; |
|
|
m.center(get_screen()); |
|
|
m.manage(get_screen()); |
|
|
} |
|
|
} |
|
|
|
|
|
namespace |
|
|
{ |
|
574 |
class DataPathList { |
class DataPathList { |
575 |
public: |
public: |
576 |
DataPathList(const string &pathspec=DEFAULT_DATA_PATH) |
DataPathList(const string &pathspec=DEFAULT_DATA_PATH) |
631 |
return FindDataFile(path+"/"+filename); |
return FindDataFile(path+"/"+filename); |
632 |
} |
} |
633 |
|
|
634 |
|
//---------------------------------------------------------------------- |
635 |
|
// Resource management |
636 |
|
//---------------------------------------------------------------------- |
637 |
|
|
638 |
|
namespace |
639 |
|
{ |
640 |
|
cache::Cache<Font *, FontAlloc> font_cache; |
641 |
|
cache::Cache<Surface*, ImageAlloc> image_cache; |
642 |
|
} |
643 |
|
|
644 |
|
px::Font * |
645 |
|
enigma::LoadFont(const char *name) |
646 |
|
{ |
647 |
|
string png = string("fonts/") + name + ".png"; |
648 |
|
string bmf = string("fonts/") + name + ".bmf"; |
649 |
|
return px::LoadBitmapFont(FindDataFile(png).c_str(), |
650 |
|
FindDataFile(bmf).c_str()); |
651 |
|
} |
652 |
|
|
653 |
|
px::Font * |
654 |
|
enigma::GetFont(const char *name) |
655 |
|
{ |
656 |
|
return font_cache.get(name); |
657 |
|
} |
658 |
|
|
659 |
|
px::Surface * |
660 |
|
enigma::LoadImage(const char *name) |
661 |
|
{ |
662 |
|
string filename = FindDataFile(string("gfx/") + name + ".png"); |
663 |
|
return px::LoadImage(filename.c_str()); |
664 |
|
} |
665 |
|
|
666 |
|
px::Surface * |
667 |
|
enigma::GetImage(const char *name) |
668 |
|
{ |
669 |
|
string filename = FindDataFile(string("gfx/") + name + ".png"); |
670 |
|
Surface *s = image_cache.get(filename); |
671 |
|
assert(s); |
672 |
|
return s; |
673 |
|
} |
674 |
|
|
675 |
|
|
676 |
|
|
677 |
//---------------------------------------------------------------------- |
//---------------------------------------------------------------------- |
678 |
// Startup |
// Startup |
695 |
{ |
{ |
696 |
lua::Init(); |
lua::Init(); |
697 |
|
|
698 |
|
// Run initialization scripts |
699 |
|
lua::Dofile("init.lua"); |
700 |
|
lua::Dofile("levels/index.lua"); |
701 |
|
|
702 |
// Load preferences |
// Load preferences |
703 |
if (!options::Load()) |
if (!options::Load()) |
704 |
{ |
{ |
758 |
sound::Init(); |
sound::Init(); |
759 |
world::Init(); |
world::Init(); |
760 |
|
|
761 |
// Run initialization script |
video::SetMouseCursor(enigma::LoadImage("it-magicwand"), 4, 4); |
762 |
lua::Dofile("init.lua"); |
video::ShowMouse(); |
763 |
} |
} |
764 |
|
|
765 |
static void |
static void |
771 |
options::Save(); |
options::Save(); |
772 |
} |
} |
773 |
|
|
|
|
|
|
namespace |
|
|
{ |
|
|
class FontAlloc { |
|
|
public: |
|
|
Font *acquire(const std::string &name) { |
|
|
string fname = enigma::FindDataFile(string("fonts/") + name + ".png"); |
|
|
string dname = enigma::FindDataFile(string("fonts/") + name + ".bmf"); |
|
|
return px::LoadBitmapFont(fname.c_str(), dname.c_str()); |
|
|
} |
|
|
void release(Font *f) { delete f; } |
|
|
}; |
|
|
|
|
|
cache::Cache<Font *, FontAlloc> font_cache; |
|
|
cache::Cache<Surface*, ImageAlloc> image_cache; |
|
|
} |
|
|
|
|
|
px::Font * |
|
|
enigma::LoadFont(const char *name) |
|
|
{ |
|
|
string png = string("fonts/") + name + ".png"; |
|
|
string bmf = string("fonts/") + name + ".bmf"; |
|
|
return px::LoadBitmapFont(FindDataFile(png).c_str(), |
|
|
FindDataFile(bmf).c_str()); |
|
|
} |
|
|
|
|
|
px::Font * |
|
|
enigma::GetFont(const char *name) |
|
|
{ |
|
|
Font *f = font_cache.get(name); |
|
|
assert(f); |
|
|
return f; |
|
|
} |
|
|
|
|
|
px::Surface * |
|
|
enigma::LoadImage(const char *name) |
|
|
{ |
|
|
string filename = FindDataFile(string("gfx/") + name + ".png"); |
|
|
return px::LoadImage(filename.c_str()); |
|
|
} |
|
|
|
|
|
px::Surface * |
|
|
enigma::GetImage(const char *name) |
|
|
{ |
|
|
string filename = FindDataFile(string("gfx/") + name + ".png"); |
|
|
Surface *s = image_cache.get(filename); |
|
|
assert(s); |
|
|
return s; |
|
|
} |
|
|
|
|
774 |
int |
int |
775 |
main(int argc, char** argv) |
main(int argc, char** argv) |
776 |
{ |
{ |
|
// try { |
|
777 |
copy(argv+1, argv+argc, back_inserter(::args)); |
copy(argv+1, argv+argc, back_inserter(::args)); |
778 |
init(); |
init(); |
779 |
mainmenu(); |
|
780 |
|
GUI_MainMenu(LevelPacks[0], 0); |
781 |
shutdown(); |
shutdown(); |
|
// } |
|
|
// catch (px::XGeneric& e) { |
|
|
// fprintf(stderr, "main: caught px exception: %s\n", e.what()); |
|
|
// shutdown(); |
|
|
// return 1; |
|
|
// } |
|
|
// catch (std::exception& e) { |
|
|
// fprintf(stderr, "main: caught exception: %s\n", e.what()); |
|
|
// shutdown(); |
|
|
// return 1; |
|
|
// } |
|
782 |
return 0; |
return 0; |
783 |
} |
} |