/[enigma]/enigma/src/enigma.cc
ViewVC logotype

Diff of /enigma/src/enigma.cc

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.6 by dheck, Sun Jan 19 17:26:47 2003 UTC revision 1.7 by dheck, Thu Jan 23 22:41:00 2003 UTC
# Line 17  Line 17 
17   *   *
18   * $Id$   * $Id$
19   */   */
20    #include "config.h"             // for DEFAULT_DATA_PATH
21  #include "common.hh"  #include "enigma.hh"
 #include "config.h"  
 #include "options.hh"  
 #include "editor.hh"  
 #include "world.hh"  
 #include "player.hh"  
 #include "lua.hh"  
 #include "sound.hh"  
22  #include "system.hh"  #include "system.hh"
23  #include "gui.hh"  #include "px/px.hh"
 #include "menus.hh"  
 #include "oxyd.hh"  
   
 #include "game.hh"  
   
 #include "px/sdl.hh"  
 #include "px/argp.hh"  
24    
25  #include <algorithm>  #include <algorithm>
26  #include <fstream>  #include <fstream>
27  #include <iostream>  #include <iostream>
28    #include <list>
29    #include <functional>
30    
31  using namespace std;  using namespace std;
32  using namespace px;  using namespace px;
33  using namespace enigma;  using namespace enigma;
34    
35  Direction  namespace
 enigma::reverse(Direction d)  
 {  
     Direction rdir[] = { EAST, NORTH, WEST, SOUTH };  
     return d==NODIR ? NODIR : rdir[d];  
 }  
   
 string  
 enigma::to_suffix(Direction d)  
 {  
     static char *sfx[] = { "", "-w", "-s", "-e", "-n" };  
     return sfx[d+1];  
 }  
   
   
 //======================================================================  
 // MENUS  
 //======================================================================  
 namespace  
36  {  {
     using gui::TextButton;  
   
     class GameMenu : public gui::Menu {  
     public:  
         GameMenu()  
             : resume(new TextButton("Resume Level", this)),  
               restart(new TextButton("Restart Level", this)),  
               options(new TextButton("Options", this)),  
               abort(new TextButton("Abort Level", this))  
         {  
             add(resume,     Rect(0,0,150,40));  
             add(restart,    Rect(0,45,150,40));  
             add(options,    Rect(0,90,150,40));  
             add(abort,      Rect(0,135,150,40));  
             center(video::GetScreen());  
         }  
     private:  
         bool on_event (const SDL_Event &e) {  
             if (e.type == SDL_MOUSEBUTTONDOWN  
                 && e.button.button == SDL_BUTTON_RIGHT)  
             {  
                 Menu::quit();  
                 return true;  
             }  
             return false;  
         }  
   
         void on_action(gui::Widget *w) {  
             if (w == resume) {  
                 Menu::quit();  
             }  
             else if (w == abort) {  
                 enigma::QuitGame();  
                 Menu::quit();  
             }  
             else if (w == restart)  
             {  
                 enigma::RestartLevel();  
                 Menu::quit();  
             }  
             else if (w == options)  
             {  
                 GUI_OptionsMenu();  
                 Menu::quit();  
             }  
         }  
         gui::Widget *resume, *restart, *options, *abort;  
     };  
   
37      class FontAlloc {      class FontAlloc {
38      public:      public:
39          Font *acquire(const std::string &name) {          Font *acquire(const std::string &name) {
# Line 134  namespace Line 55  namespace
55      typedef Cache<Surface*, ImageAlloc> ImageCache;      typedef Cache<Surface*, ImageAlloc> ImageCache;
56  }  }
57    
   
 //======================================================================  
 // APPLICATION DATA  
 //======================================================================  
 namespace enigma  
 {  
     struct Flags {  
         bool nosound;  
     };  
   
     class Application {  
     public:  
   
         void init(int argc, char **argv) {  
             copy(argv+1, argv+argc, back_inserter(args));  
         }  
   
         // Variables.  
   
         vector<string>  args;       // List of command line arguments.  
   
         Flags                           flags;  
         Cache<Font *, FontAlloc>        font_cache;  
         Cache<Surface*, ImageAlloc>     image_cache;  
     };  
   
     vector<LevelPack *> LevelPacks;  
   
     Application app;  
58    
59    Direction
60    enigma::reverse(Direction d)
61    {
62        Direction rdir[] = { EAST, NORTH, WEST, SOUTH };
63        return d==NODIR ? NODIR : rdir[d];
64  }  }
65    
66    string
67    enigma::to_suffix(Direction d)
68    {
69        static char *sfx[] = { "", "-w", "-s", "-e", "-n" };
70        return sfx[d+1];
71    }
72    
73  /* The stream object that is used for logging messages.  As defined  
    here, it is not connected to any file or buffer. */  
 std::ostream enigma::Log(0);  
   
 /* This is the stream object that is used when logging to a file.  In  
    this case, enigma::Log uses this object's streambuffer. */  
 static std::fstream logfile;  
   
   
   
 //======================================================================  
 // MAIN PROGRAM  
 //======================================================================  
74    
75  //----------------------------------------------------------------------  //----------------------------------------------------------------------
76  // Level management  // Value implementation
77  //----------------------------------------------------------------------  //----------------------------------------------------------------------
78    Value::Value(const char* str)
79  // Run init_file to initialize the level list.      : type(STRING)
 void  
 LevelPack::init()  
80  {  {
81      string filename = enigma::FindDataFile(init_file);      val.str = new char[strlen(str)+1];
82      ifstream is(filename.c_str());      strcpy(val.str, str);
   
     if (!is) {  
         fprintf(stderr, "Couldn't load level pack %s.\n", filename.c_str());  
         return;  
     }  
     levels.clear();  
   
     string line;  
     vector<string> tokens;  
     while (getline(is, line)) {  
         split_copy(line, '|', back_inserter(tokens));  
         transform(tokens.begin(), tokens.end(),  
                   tokens.begin(), trim<string>);  
         if (tokens.size() == 2)  
             levels.push_back(LevelInfo(tokens[0], tokens[1], ""));  
         tokens.clear();  
     }  
83  }  }
84    
85  void  void Value::assign(const char* s)
 enigma::AddLevelPack (const char *init_file, const char *name)  
86  {  {
87      LevelPack *lp = new LevelPack(init_file, name);      clear();
88      LevelPacks.push_back(lp);      type = STRING;
89      lp->init();      val.str = new char[strlen(s)+1];
90        strcpy(val.str, s);
91  }  }
92    
93  //----------------------------------------------------------------------  void Value::clear()
94  // GAME  {
95  //----------------------------------------------------------------------      if (type == STRING)
96            delete[] val.str;
97        type = NIL;
98    }
99    
100  Game::Game()  Value::Value(const Value& other) : type(NIL)
     : state(INGAME),  
       input_state(I_NORMAL),  
       icurrent_level(0),  
       last_tick_time(0),  
       screen (0)  
101  {  {
102        this->operator=(other);
103  }  }
104    
105  void  Value&
106  Game::change_state(State newstate)  Value::operator=(const Value& other)
107  {  {
108      if (state == newstate) return;      if (this != &other) {
109      state = newstate;          clear();
110      switch (state) {          if (other.type == STRING) {
111      case LEVELFINISHED:              assign(other.val.str);
112          level_finished_dtime=0;          } else {
113          display::GetStatusBar()->show_text("Level finished!", display::TEXT_STATIC);              type = other.type;
114          player::LevelFinished(); // remove player-controlled actors              val = other.val;
115            }
         options::SetLevelFinished(level_pack->name,  
                                   level_pack->levels[icurrent_level].filename,  
                                   2); // difficulty  
         break;  
     case PLAYERDEAD:  
         actor_dead_dtime=0;  
 //        display::ShowText("You lost", display::TEXT_STATIC);  
         break;  
     default: break;  
116      }      }
117        return *this;
118  }  }
119    
120  void  double Value::get_double() const throw()
 Game::tick(double dtime)  
121  {  {
122      switch (state) {      assert(type == DOUBLE);
123      case RESTARTGAME:      return val.dval;
124          // Move the main actors to their respective starting positions  }
         player::NewGame(2);         // two virtual players  
         if( ! load_level(icurrent_level)) {  
             change_state(ABORT);  
         } else  
 //         load_level(icurrent_level);  
             change_state(INGAME);  
         break;  
125    
126      case PLAYERDEAD:  const char* Value::get_string() const throw()
127          actor_dead_dtime += dtime;  {
128          if (actor_dead_dtime <= 0.5) {      assert(type == STRING);
129              world::Tick(dtime);      return val.str;
130              display::Tick(dtime);  }
             display::Redraw(screen);  
             handle_events();  
         } else {  
             change_state (RESTARTGAME);  
         }  
         break;  
131    
132      case RELOADLEVEL:  Buffer& enigma::operator<<(Buffer& buf, const Value& val)
133          load_level(icurrent_level);  {
134          change_state(INGAME);      buf << Uint8(val.get_type());
         break;  
135    
136      case LEVELINFO:      switch (val.get_type()) {
137          // TODO: show level information (name, author, etc.)      case Value::NIL:
         change_state(INGAME);  
138          break;          break;
139        case Value::DOUBLE:
140      case LEVELFINISHED:          buf << val.get_double();
         level_finished_dtime += dtime;  
         if (level_finished_dtime <= 1.5) {  
             handle_events();  
             world::Tick(dtime);  
             display::Tick(dtime);  
             display::Redraw(screen);  
         } else {  
             unsigned next_level = 1+icurrent_level;  
             if (next_level == level_pack->levels.size())  
                 change_state(ABORT);  
             else {  
                 while (level_pack->levels[next_level].filename == "todo")  
                     if (++next_level >= level_pack->levels.size())  
                         break;  
                 load_level(next_level);  
                 change_state(LEVELINFO);  
             }  
         }  
141          break;          break;
142        case Value::STRING:
143            {
144                const char* str = val.get_string();
145                buf << (Uint16)strlen(str);
146                buf.write(str, strlen(str));
147            } break;
148        }
149        return buf;
150    }
151    
152      case INGAME:  Buffer& enigma::operator>>(Buffer& buf, Value& val)
153    {
154          if (player::AllActorsDead()) {      Uint8 type = Value::NIL;
155              change_state(PLAYERDEAD);      buf >> type;
         }  
   
         handle_events();  
         world::Tick(dtime);  
         display::Tick(dtime);  
         display::Redraw(screen);  
         break;  
156    
157      default:      switch (type) {
158        case Value::NIL:
159            // ## fixme
160          break;          break;
161        case Value::DOUBLE:
162            {
163                double tmp;
164                if (buf >> tmp)
165                    val = Value(tmp);
166            } break;
167        case Value::STRING:
168            {
169                Uint16 len;
170                if (buf >> len) {
171                    char* tmp = new char[len+1];
172                    tmp[len] = 0;
173                    if (buf.read(tmp, len))
174                        val.assign(tmp);
175                    delete[] tmp;
176                }
177            } break;
178      }      }
179        return buf;
180  }  }
181    
182  bool  int
183  Game::load_level(int ilevel)  enigma::to_int(const Value &v)
184  {  {
185  //    FX_Fade(video::FADEOUT);      switch (v.get_type()) {
186      vector<LevelInfo> &levels = level_pack->levels;      case Value::DOUBLE: return int(v.get_double());
187            case Value::STRING: return atoi(v.get_string());
188      icurrent_level=ilevel;      default: return 0;
189      if( ! world::Load(levels[icurrent_level].filename))      }
         return false;  
   
     GC gc(video::BackBuffer());  
     display::DrawAll(gc);  
     ShowScreen(video::TM_PUSH_RANDOM, video::BackBuffer());  
 //    FX_Fade(video::FADEIN);  
     sdl::FlushEvents();  
     update_mouse_button_state();  
     last_tick_time = SDL_GetTicks();  
     return true;  
190  }  }
191    
192  void  bool
193  Game::run (LevelPack *lp, int ilevel)  enigma::to_bool(const Value &v)
194  {  {
195      screen = video::GetScreen();      return (v.get_type() != Value::NIL);
196      class Avg {  }
         enum {N=20};  
         double dtimes[N];  
         int idx;  
     public:  
         Avg() : idx(0) { fill(dtimes, dtimes+N, 0.010); }  
         void add(double dtime) {  
             dtimes[idx++] = dtime;  
             idx = idx % N;  
         }  
         double get() {  
             double s=0;  
             for (int i=0; i<N; s+=dtimes[i++]);  
             return s/N;  
         }  
     };  
     static Avg average_dtime;  
   
     level_pack = lp;  
   
     icurrent_level = ilevel;  
   
     sdl::TempInputGrab grab(options::Nograb ? SDL_GRAB_OFF : SDL_GRAB_ON);  
     video::HideMouse();  
 //    sound::PlayMusic("/sound/Emilie.xm");  
     sound::FadeoutMusic();  
     sound::StopMusic();  
   
     double dtime=0;  
   
     state = RESTARTGAME;  
     while (state != ABORT)  
     {  
         last_tick_time=SDL_GetTicks();  
   
         tick(dtime);  
   
         int sleeptime = 10 - (SDL_GetTicks()-last_tick_time);  
         if (sleeptime > 0)  
             ; //SDL_Delay(sleeptime);  
   
         dtime=(SDL_GetTicks()-last_tick_time)/1000.0;  
   
         double adtime = average_dtime.get();  
         average_dtime.add(dtime);  
         if (abs(adtime-dtime)/adtime < 0.1) {  
             // less than 10% deviation from average frame time?  
             dtime = adtime;  
         }  
197    
198          if (dtime > 500.0) /* Time has done something strange, perhaps  double
199                                run backwards */  enigma::to_double(const Value &v)
200              dtime = 0.0;  {
201          else if (dtime > 0.5)      switch (v.get_type()) {
202              dtime = 0.5;      case Value::DOUBLE: return v.get_double();
203        case Value::STRING: return atof(v.get_string());
204        default: return 0;
205      }      }
     video::ShowMouse();  
206  }  }
207    
208  static void  const char *
209  mouse_force(int xrel, int yrel)  enigma::to_string(const Value &v)
210  {  {
211      px::V3 force(xrel, yrel,0);      static char buf[30];
212      double f = length(force);      switch (v.get_type()) {
213      if (f > 0)      case Value::NIL: return "";
214      {      case Value::DOUBLE:
215          force *= options::MouseSpeed;          sprintf(buf, "%f", v.get_double());
216          world::SetMouseForce(force);          return buf;
217        case Value::STRING: return v.get_string();
218        default: return 0;
219      }      }
220  }  }
221    
222  void  
223  Game::handle_events()  ostream& enigma::operator<<(ostream& os, const Value& val)
224  {  {
225      SDL_Event e;      switch (val.get_type()) {
226      while (SDL_PollEvent(&e))      case Value::NIL:   os << "nil"; break;
227      {      case Value::DOUBLE: os << val.get_double(); break;
228          switch (e.type) {      case Value::STRING: os << val.get_string(); break;
         case SDL_KEYDOWN:  
             on_keydown(e);  
             break;  
         case SDL_MOUSEMOTION:  
             mouse_force(e.motion.xrel, e.motion.yrel);  
             break;  
         case SDL_MOUSEBUTTONDOWN:  
         case SDL_MOUSEBUTTONUP:  
             on_mousebutton(e);  
             break;  
         case SDL_ACTIVEEVENT:  
             if( e.active.gain == 0)  
                 show_menu();  
             break;  
         case SDL_QUIT:  
             change_state(ABORT);  
             break;  
         }  
229      }      }
230        return os;
231  }  }
232    
233  void  //----------------------------------------------------------------------
234  Game::on_mousebutton(SDL_Event &e)  // Timer
235    //----------------------------------------------------------------------
236    
237    namespace enigma
238  {  {
239      if (e.button.state == SDL_PRESSED)      class Alarm {
240      {          TimeHandler * handler;
241          if (e.button.button == 1) {          double interval;
242              // left mousebutton -> activate first item in inventory          double timeleft;
243              player::ActivateItem();          bool repeatp;
244          }      public:
245          else if (e.button.button == 3) {          Alarm(TimeHandler* h, double interval, bool repeatp);
246              // right mousebutton -> rotate inventory          void tick(double dtime);
247              display::GetStatusBar()->hide_text();          bool expired() const { return timeleft <= 0; }
248              player::RotateInventory();  
249            bool operator==(const Alarm &a) const {
250                return a.handler == handler;
251          }          }
252      }      };
     update_mouse_button_state();  
 }  
253    
254  void      struct Timer::Rep {
255  Game::update_mouse_button_state()          std::list<TimeHandler*>  handlers;
256  {          std::list<Alarm>         alarms;
257      int b = SDL_GetMouseState(0, 0);      };
     player::InhibitPickup((b & SDL_BUTTON(1)) || (b & SDL_BUTTON(3)));  
258  }  }
259    
260  static void set_mousespeed(double spd)  Alarm::Alarm(TimeHandler* h, double i, bool r)
261        : handler(h), interval(i), timeleft(i), repeatp(r)
262    {}
263    
264    void
265    Alarm::tick(double dtime)
266  {  {
267      if (spd > 0 && spd < 15) {      timeleft -= dtime;
268          display::StatusBar *sb = display::GetStatusBar();      while (timeleft <= 0) {
269          char msg[200];          handler->alarm();
270          options::MouseSpeed = int(spd);          if (repeatp)
271          sprintf(msg, "Mouse speed: %d", int(spd));              timeleft += interval;
         sb->show_text(msg, display::TEXT_2SECONDS);  
272      }      }
273  }  }
274    
275  static void set_frictionfactor(double f)  Timer::Timer()
276        : rep(*new Rep)
277    {}
278    
279    Timer::~Timer()
280  {  {
281      if (f > 0 && f < 10) {      delete &rep;
         display::StatusBar *sb = display::GetStatusBar();  
         char msg[200];  
         f = int(2*f)/2.0;  
         options::FrictionFactor = f;  
         sprintf(msg, "Friction: %g", f);  
         sb->show_text(msg, display::TEXT_2SECONDS);  
     }  
282  }  }
283    
284  void  void
285  Game::on_keydown(SDL_Event &e)  Timer::deactivate(TimeHandler* th)
286  {  {
287      switch (e.key.keysym.sym) {  // This doesn't work: Some objects deactivate themselves from their
288      case SDLK_ESCAPE:  // `tick' method!
289          show_menu();  //    rep.handlers.remove(th);
         break;  
   
     case SDLK_LEFT: set_mousespeed(options::MouseSpeed - 1); break;  
     case SDLK_RIGHT: set_mousespeed(options::MouseSpeed + 1); break;  
     case SDLK_PAGEUP:  
         set_frictionfactor (options::FrictionFactor+0.5);  
         break;  
     case SDLK_PAGEDOWN:  
         set_frictionfactor (options::FrictionFactor-0.5);  
         break;  
290    
291      case SDLK_F10:      std::list<TimeHandler*>::iterator i;
         {  
             string fname = level_pack->levels[icurrent_level].filename + ".bmp";  
             video::Screenshot(fname.c_str());  
         }  
         break;  
     case SDLK_F3:  
         player::Suicide();  
 //        change_state(RELOADLEVEL);  
         break;  
     case SDLK_x:  
         if (e.key.keysym.mod & KMOD_ALT) {  
             change_state(ABORT);  
         }  
         break;  
     default:  
         break;  
     }  
292    
293      if (options::WizardMode > 0.0) {      i = find(rep.handlers.begin(), rep.handlers.end(), th);
294          switch (e.key.keysym.sym) {      if (i != rep.handlers.end()) {
295          case SDLK_f:          *i = 0;
             options::ShowFPS = !options::ShowFPS;  
             break;  
         case SDLK_l:  
             load_level(icurrent_level);  
             break;  
         case SDLK_t:  
             // Darken the current screen; useful for debugging screen updates  
             TintRect(screen, screen->size(), 0,0,0, 200);  
             screen->update_all();  
             screen->flush_updates();  
             break;  
         case SDLK_g:  
             if (e.key.keysym.mod & KMOD_ALT) {  
                 display::ReloadModels();  
                 load_level(icurrent_level);  
             }  
             break;  
         case SDLK_1: ToggleFlag(display::SHOW_FLOOR); break;  
         case SDLK_2: ToggleFlag(display::SHOW_ITEMS); break;  
         case SDLK_3: ToggleFlag(display::SHOW_SHADES); break;  
         case SDLK_4: ToggleFlag(display::SHOW_STONES); break;  
         case SDLK_5: ToggleFlag(display::SHOW_SPRITES); break;  
         default:  
             break;  
         }  
296      }      }
297  }  }
298    
299  void  void
300  Game::show_menu()  Timer::activate(TimeHandler *th)
301  {  {
302      sdl::TempInputGrab grab(SDL_GRAB_OFF);      if (find(rep.handlers.begin(), rep.handlers.end(), th) == rep.handlers.end())
303            rep.handlers.push_back(th);
     video::ShowMouse();  
     GameMenu m;  
     m.manage(screen);  
     video::HideMouse();  
     update_mouse_button_state();  
     last_tick_time = SDL_GetTicks();  
     if (state != ABORT)  
         display::RedrawAll(screen);  
304  }  }
305    
306  namespace  void
307    Timer::set_alarm(TimeHandler *th, double interval, bool repeatp)
308  {  {
309      Game game_inst;      if (interval > 0)
310            rep.alarms.push_back(Alarm(th, interval, repeatp));
311  }  }
312    
313  bool enigma::ConserveLevel = false;  void
314  int  enigma::Difficulty    = 1;  Timer::remove_alarm(TimeHandler *th)
   
 void  
 enigma::StartGame (LevelPack *lp, unsigned levelidx)  
315  {  {
316      if (lp->levels[levelidx].filename != "todo")      // only the ``handler'' entries are compared
317          game_inst.run (lp, levelidx);      rep.alarms.remove(Alarm(th,0,0));
318  }  }
319    
320    
321  void enigma::FinishLevel() {  void
322      game_inst.finish_level();  Timer::tick(double dtime)
323    {
324        rep.handlers.remove(0);     // remove inactive entries
325        for_each(rep.handlers.begin(), rep.handlers.end(),
326                 bind2nd(mem_fun(&TimeHandler::tick), dtime));
327    
328        // Explicit loop since `mem_fun_ref' requires a constant member function
329        for (list<Alarm>::iterator i=rep.alarms.begin(); i!=rep.alarms.end(); ++i)
330            i->tick(dtime);
331        rep.alarms.remove_if(mem_fun_ref(&Alarm::expired));
332  }  }
333    
 void enigma::RestartLevel() {  
     game_inst.restart_level();  
 }  
334    
335  void enigma::QuitGame() {  void
336      game_inst.quit();  Timer::clear()
337    {
338        rep.handlers.clear();
339        rep.alarms.clear();
340  }  }
341    
342    
343  //----------------------------------------------------------------------  //----------------------------------------------------------------------
344  // Data path  // Data path
345  //----------------------------------------------------------------------  //----------------------------------------------------------------------
# Line 617  namespace Line 348  namespace
348      class DataPathList {      class DataPathList {
349      public:      public:
350          DataPathList(const string &pathspec=DEFAULT_DATA_PATH)          DataPathList(const string &pathspec=DEFAULT_DATA_PATH)
351          { set_path(pathspec); }          {
352                set_path(pathspec);
353            }
354                    
355          void set_path(const string &pathspec)          void set_path(const string &pathspec)
356          {          {
# Line 668  enigma::FindDataFile(const string &filen Line 401  enigma::FindDataFile(const string &filen
401  {  {
402      string found_file;      string found_file;
403      if (!datapaths.find_file(filename, found_file)) {      if (!datapaths.find_file(filename, found_file)) {
404          fprintf(stderr, "File not found: %s\n", filename.c_str());          Log << "File not found: " << filename << endl;
405          return filename;          return filename;
406      }      }
407      return found_file;      return found_file;
# Line 683  enigma::FindDataFile(const string &path, Line 416  enigma::FindDataFile(const string &path,
416  //----------------------------------------------------------------------  //----------------------------------------------------------------------
417  // Resource management  // Resource management
418  //----------------------------------------------------------------------  //----------------------------------------------------------------------
419    namespace
420    {
421        px::Cache<px::Font *, FontAlloc>        font_cache;
422        px::Cache<px::Surface*, ImageAlloc>     image_cache;
423    }
424    
425  px::Font *  px::Font *
426  enigma::LoadFont (const char *name)  enigma::LoadFont (const char *name)
# Line 696  enigma::LoadFont (const char *name) Line 434  enigma::LoadFont (const char *name)
434  px::Font *  px::Font *
435  enigma::GetFont(const char *name)  enigma::GetFont(const char *name)
436  {  {
437      return app.font_cache.get(name);      return font_cache.get(name);
438  }  }
439    
440  px::Surface *  px::Surface *
# Line 710  px::Surface * Line 448  px::Surface *
448  enigma::GetImage(const char *name)  enigma::GetImage(const char *name)
449  {  {
450      string filename = FindDataFile(string("gfx/") + name + ".png");      string filename = FindDataFile(string("gfx/") + name + ".png");
451      Surface *s = app.image_cache.get(filename);      Surface *s = image_cache.get(filename);
452      assert(s);      assert(s);
453      return s;      return s;
454  }  }
   
 //----------------------------------------------------------------------  
 // Startup  
 //----------------------------------------------------------------------  
   
 static void usage()  
 {  
     printf("Available command line options for Enigma:\n\n"  
            "    --nosound      Disable music and sound\n"  
            "    --nomusic      Disable music\n"  
            "    --window       Run in a window; do not enter fullscreen mode\n"  
            "    --help -h      Show this help\n"  
            "    --version      Print the executable's version number\n"  
            "    --8bpp         Use 256 color mode\n"  
            "    --nograb       Do not use exclusive mouse/keyboard access\n"  
            "\n");  
 }  
   
 static void  
 init()  
 {  
     lua::Init();  
   
     // Run initialization scripts  
     lua::Dofile("init.lua");  
     lua::Dofile("levels/index.lua");  
       
     // Load preferences  
     if (!options::Load())  
     {  
         fprintf(stderr, "Error in configuration file.\n");  
     }  
   
     /*  
     ** Evaluate command line arguments.  
     */  
     struct AP : public argp::ArgParser {  
     public:  
         enum {  
             OPT_NOSOUND, OPT_NOMUSIC, OPT_VERSION, OPT_HELP,  
             OPT_WINDOW, OPT_WIZARD, OPT_NOGRAB, OPT_LOG,  
             OPT_8BPP, OPT_GAME,  
             OPT_PEROXYD, OPT_OXYD1, OPT_EXTRA, OPT_MAGNUM  
         };  
   
         AP() : ArgParser (app.args.begin(), app.args.end())  
         {  
             nosound = nomusic = show_help = show_version = do_log = false;  
             gamename = "";  
             gametype = GAMET_ENIGMA;  
   
             def (OPT_NOSOUND,   0,   "nosound");  
             def (OPT_NOMUSIC,   0,   "nomusic");  
             def (OPT_VERSION,   0,  "version");  
             def (OPT_HELP,      'h', "help");  
             def (OPT_WINDOW,    'w', "window");  
             def (OPT_WIZARD,    0,   "wizard");  
             def (OPT_NOGRAB,    0,   "nograb");  
             def (OPT_LOG,       'l', "log");  
             def (OPT_8BPP,      '8', "8bpp");  
             def (OPT_GAME,      'g', "game", true);  
             def (OPT_PEROXYD,   0,   "peroxyd");  
             def (OPT_OXYD1,     0,   "oxyd1");  
             def (OPT_EXTRA, 0,   "oxydextra");  
             def (OPT_MAGNUM,0,   "oxydmagnum");  
         }  
                                   
         // ArgParser interface.  
         void on_error (ErrorType t, const string &option) {  
             cout << errormsg(t, option) << endl;  
             show_help = true;  
         }  
   
         void on_option (int id, const string &param) {  
             switch (id) {  
             case OPT_NOSOUND: nosound=true; break;  
             case OPT_NOMUSIC: nomusic=true; break;  
             case OPT_VERSION: show_version=true; break;  
             case OPT_HELP:    show_help=true; break;  
             case OPT_WINDOW:  options::FullScreen=false; break;  
             case OPT_WIZARD:  options::WizardMode=true; break;  
             case OPT_NOGRAB:  options::Nograb=true; break;  
             case OPT_8BPP:    options::BitsPerPixel = 8; break;  
             case OPT_GAME:    gamename = param; break;  
             case OPT_LOG:     do_log = true; break;  
             case OPT_PEROXYD: gametype = GAMET_PEROXYD; break;  
             case OPT_OXYD1:   gametype = GAMET_OXYD1; break;  
             case OPT_EXTRA:   gametype = GAMET_OXYDEXTRA; break;  
             case OPT_MAGNUM:  gametype = GAMET_OXYDMAGNUM; break;  
             }  
         }  
   
         void on_argument (const string &arg) {  
         }  
   
         // Variables.  
         bool nosound, nomusic, show_help, show_version, do_log;  
         string gamename;  
         GameType gametype;  
     };  
     AP ap;  
     ap.parse();  
   
     if (ap.show_help || ap.show_version) {  
         printf("Enigma v%s\n",VERSION);  
         if (ap.show_help) usage();  
         exit(0);  
     }  
   
     if (ap.do_log) {  
         logfile.open("enigma.log", ios::out);  
         if (logfile)  
             enigma::Log.rdbuf(logfile.rdbuf());  
         else  
             fprintf(stderr,"Could not open log file \"enigma.log\" for writing.\n");  
     }  
   
     int sdl_flags = SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE;  
     if (!ap.nosound)  
         sdl_flags |= SDL_INIT_AUDIO;  
   
     if (SDL_Init(sdl_flags) < 0) {  
         fprintf(stderr, "Couldn't init SDL: %s\n", SDL_GetError());  
         exit(1);  
     }  
   
     if (ap.nosound)  
         sound::DisableSound();  
     else if (ap.nomusic)  
         sound::DisableMusic();  
   
     if (ap.gamename == "enigma") {  
         oxyd::Init();  
     }  
     video::Init();  
     video::SetPalette("enigma.pal");  
     display::Init();  
     sound::Init();  
     world::Init();  
   
     video::SetMouseCursor(enigma::LoadImage("cur-magic"), 4, 4);  
     video::ShowMouse();  
 }  
   
 static void  
 shutdown()  
 {  
     video::Shutdown();  
     display::Shutdown();  
     world::Shutdown();  
     options::Save();  
     delete_sequence(enigma::LevelPacks.begin(),  
                     enigma::LevelPacks.end());  
 }  
   
 int  
 main(int argc, char** argv)  
 {  
 #ifdef MACOSX  
     // In Mac OS X, applications are self-contained bundles,  
     // e.g. directories like "Enigma.app". Resources are  
     // placed in those bundles under "Enigma.app/Contents/Resources",  
     // the main executable would be "Enigma.app/Contents/MacOS/enigma".  
     // Here, we get the executable name, clip off the last bit, chdir into it,  
     // then chdir to ../Resources. The original SDL implementation chdirs to  
     // "../../..", i.e. the directory the bundle is placed in. This break  
     // the self-containedness.  
     char parentdir[1024];  
     char *c;  
   
     strncpy ( parentdir, argv[0], sizeof(parentdir) );  
     c = (char*) parentdir;  
   
     while (*c != '\0')     /* go to end */  
            c++;  
   
     while (*c != '/')      /* back up to parent */  
            c--;  
   
     *c++ = '\0';           /* cut off last part (binary name) */  
   
     chdir (parentdir);  /* chdir to the binary app's parent */  
     chdir ("../Resources/"); /* chdir to the .app's parent */  
 #endif //MACOSX  
   
     app.init(argc,argv);  
   
     init();  
       
     GUI_MainMenu(LevelPacks[0], 0);  
     shutdown();  
     return 0;  
 }  

Legend:
Removed from v.1.6  
changed lines
  Added in v.1.7

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26