void
BadGuy::action_laptop()
{
+ Player& tux = *World::current()->get_tux();
+
fall();
/* Move left/right: */
else if (mode == HELD)
{ /* FIXME: The pbad object shouldn't know about pplayer objects. */
/* If we're holding the laptop */
- dir=tux.dir;
+ dir = tux.dir;
if(dir==RIGHT)
{
base.x = tux.base.x + 16;
void
BadGuy::action_money()
{
+ Player& tux = *World::current()->get_tux();
+
static const float JUMPV = 6;
fall();
void
BadGuy::action_stalactite()
{
+ Player& tux = *World::current()->get_tux();
+
static const int SHAKETIME = 800;
static const int RANGE = 40;
#include "bitmask.h"
#include "scene.h"
#include "world.h"
+#include "level.h"
#include "tile.h"
bool rectcollision(base_type* one, base_type* two)
#include "collision.h"
#include "tile.h"
#include "particlesystem.h"
-
-/* extern variables */
-
-int game_started = false;
-
-/* Local variables: */
-static SDL_Event event;
-static SDLKey key;
-static char level_subset[100];
-static float fps_fps;
-static int st_gl_mode;
-static unsigned int last_update_time;
-static unsigned int update_time;
-static int pause_menu_frame;
-static int debug_fps;
+#include "resources.h"
GameSession* GameSession::current_ = 0;
-/* Local function prototypes: */
-void levelintro(void);
-void loadshared(void);
-void unloadshared(void);
-void drawstatus(void);
-void drawendscreen(void);
-void drawresultscreen(void);
+void
+GameSession::init()
+{
+ game_pause = false;
+}
GameSession::GameSession()
{
GameSession::GameSession(const std::string& filename)
{
+ init();
+
+ //assert(!"Don't call me");
current_ = this;
- world = &::global_world;
+ world = new World; // &::global_world;
timer_init(&fps_timer, true);
timer_init(&frame_timer, true);
world->load(filename);
}
-GameSession::GameSession(const std::string& subset, int levelnb, int mode)
+GameSession::GameSession(const std::string& subset_, int levelnb, int mode)
+ : subset(subset_)
{
+ init();
+
current_ = this;
- world = &::global_world;
+ world = new World; // &::global_world;
timer_init(&fps_timer, true);
timer_init(&frame_timer, true);
- game_started = true;
-
st_gl_mode = mode;
- level = levelnb;
+ level = levelnb;
/* Init the game: */
world->arrays_free();
world->set_defaults();
- strcpy(level_subset, subset.c_str());
-
if (st_gl_mode == ST_GL_LOAD_LEVEL_FILE)
{
- if (world->load(level_subset))
+ if (world->load(subset))
exit(1);
}
else
{
- if(world->load(level_subset, level) != 0)
+ if(world->load(subset, level) != 0)
exit(1);
}
world->activate_particle_systems();
world->get_level()->load_song();
- tux.init();
-
if(st_gl_mode != ST_GL_TEST)
load_hs();
loadgame(levelnb);
}
+GameSession::~GameSession()
+{
+ delete world;
+}
+
void
GameSession::levelintro(void)
{
+ Player& tux = *world->get_tux();
+
char str[60];
/* Level Intro: */
clearscreen(0, 0, 0);
void
GameSession::process_events()
{
+ Player& tux = *world->get_tux();
+
+ SDL_Event event;
while (SDL_PollEvent(&event))
{
/* Check for menu-events, if the menu is shown */
quit = true;
break;
case SDL_KEYDOWN: /* A keypress! */
- key = event.key.keysym.sym;
-
- if(tux.key_event(key,DOWN))
- break;
-
- switch(key)
- {
- case SDLK_ESCAPE: /* Escape: Open/Close the menu: */
- if(!game_pause)
- {
- if(st_gl_mode == ST_GL_TEST)
- quit = true;
- else if(show_menu)
- {
- Menu::set_current(game_menu);
- show_menu = 0;
- st_pause_ticks_stop();
- }
- else
- {
- Menu::set_current(game_menu);
- show_menu = 1;
- st_pause_ticks_start();
- }
- }
- break;
- default:
+ {
+ SDLKey key = event.key.keysym.sym;
+
+ if(tux.key_event(key,DOWN))
break;
- }
+
+ switch(key)
+ {
+ case SDLK_ESCAPE: /* Escape: Open/Close the menu: */
+ if(!game_pause)
+ {
+ if(st_gl_mode == ST_GL_TEST)
+ quit = true;
+ else if(show_menu)
+ {
+ Menu::set_current(game_menu);
+ show_menu = 0;
+ st_pause_ticks_stop();
+ }
+ else
+ {
+ Menu::set_current(game_menu);
+ show_menu = 1;
+ st_pause_ticks_start();
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ }
break;
case SDL_KEYUP: /* A keyrelease! */
- key = event.key.keysym.sym;
-
- if(tux.key_event(key, UP))
- break;
+ {
+ SDLKey key = event.key.keysym.sym;
- switch(key)
- {
- case SDLK_p:
- if(!show_menu)
- {
- if(game_pause)
- {
- game_pause = 0;
- st_pause_ticks_stop();
- }
- else
- {
- game_pause = 1;
- st_pause_ticks_start();
- }
- }
- break;
- case SDLK_TAB:
- if(debug_mode)
- {
- tux.size = !tux.size;
- if(tux.size == BIG)
- {
- tux.base.height = 64;
- }
- else
- tux.base.height = 32;
- }
- break;
- case SDLK_END:
- if(debug_mode)
- distros += 50;
- break;
- case SDLK_SPACE:
- if(debug_mode)
- next_level = 1;
- break;
- case SDLK_DELETE:
- if(debug_mode)
- tux.got_coffee = 1;
- break;
- case SDLK_INSERT:
- if(debug_mode)
- timer_start(&tux.invincible_timer,TUX_INVINCIBLE_TIME);
- break;
- case SDLK_l:
- if(debug_mode)
- --tux.lives;
- break;
- case SDLK_s:
- if(debug_mode)
- score += 1000;
- case SDLK_f:
- if(debug_fps)
- debug_fps = false;
- else
- debug_fps = true;
- break;
- default:
+ if(tux.key_event(key, UP))
break;
- }
+
+ switch(key)
+ {
+ case SDLK_p:
+ if(!show_menu)
+ {
+ if(game_pause)
+ {
+ game_pause = false;
+ st_pause_ticks_stop();
+ }
+ else
+ {
+ game_pause = true;
+ st_pause_ticks_start();
+ }
+ }
+ break;
+ case SDLK_TAB:
+ if(debug_mode)
+ {
+ tux.size = !tux.size;
+ if(tux.size == BIG)
+ {
+ tux.base.height = 64;
+ }
+ else
+ tux.base.height = 32;
+ }
+ break;
+ case SDLK_END:
+ if(debug_mode)
+ distros += 50;
+ break;
+ case SDLK_SPACE:
+ if(debug_mode)
+ next_level = 1;
+ break;
+ case SDLK_DELETE:
+ if(debug_mode)
+ tux.got_coffee = 1;
+ break;
+ case SDLK_INSERT:
+ if(debug_mode)
+ timer_start(&tux.invincible_timer,TUX_INVINCIBLE_TIME);
+ break;
+ case SDLK_l:
+ if(debug_mode)
+ --tux.lives;
+ break;
+ case SDLK_s:
+ if(debug_mode)
+ score += 1000;
+ case SDLK_f:
+ if(debug_fps)
+ debug_fps = false;
+ else
+ debug_fps = true;
+ break;
+ default:
+ break;
+ }
+ }
break;
case SDL_JOYAXISMOTION:
int
GameSession::action()
{
+ Player& tux = *world->get_tux();
+
if (tux.is_dead() || next_level)
{
/* Tux either died, or reached the end of a level! */
if (st_gl_mode == ST_GL_LOAD_LEVEL_FILE)
{
- if(world->get_level()->load(level_subset) != 0)
+ if(world->get_level()->load(subset) != 0)
return 0;
}
else
{
- if(world->get_level()->load(level_subset,level) != 0)
+ if(world->get_level()->load(subset, level) != 0)
return 0;
}
int
GameSession::run()
{
+ Player& tux = *world->get_tux();
current_ = this;
int fps_cnt;
bool done;
global_frame_counter = 0;
- game_pause = 0;
+ game_pause = false;
timer_init(&fps_timer,true);
timer_init(&frame_timer,true);
last_update_time = st_get_ticks();
/* Play music: */
play_current_music();
- while (SDL_PollEvent(&event))
- {}
+ // Eat unneeded events
+ SDL_Event event;
+ while (SDL_PollEvent(&event)) {}
draw();
}
/* Handle events: */
-
tux.input.old_fire = tux.input.fire;
process_events();
unloadshared();
world->arrays_free();
- game_started = false;
-
- return(quit);
+ return quit;
}
/* Bounce a brick: */
}
/* (Status): */
-void drawstatus(void)
+void
+GameSession::drawstatus()
{
+ Player& tux = *world->get_tux();
char str[60];
sprintf(str, "%d", score);
text_draw(&gold_text, str, screen->h + 60, 40, 1);
}
- for(int i=0; i < tux.lives; ++i)
+ for(int i= 0; i < tux.lives; ++i)
{
texture_draw(&tux_life,565+(18*i),20);
}
}
-
-void drawendscreen(void)
+void
+GameSession::drawendscreen()
{
char str[80];
wait_for_event(event,2000,5000,true);
}
-void drawresultscreen(void)
+void
+GameSession::drawresultscreen(void)
{
char str[80];
}
void
-GameSession::savegame(int slot)
+GameSession::savegame(int)
{
+#if 0
char savefile[1024];
FILE* fi;
unsigned int ui;
fwrite(&score,sizeof(int),1,fi);
fwrite(&distros,sizeof(int),1,fi);
fwrite(&scroll_x,sizeof(float),1,fi);
- fwrite(&tux,sizeof(Player),1,fi);
- timer_fwrite(&tux.invincible_timer,fi);
- timer_fwrite(&tux.skidding_timer,fi);
- timer_fwrite(&tux.safe_timer,fi);
- timer_fwrite(&tux.frame_timer,fi);
+ //FIXME:fwrite(&tux,sizeof(Player),1,fi);
+ //FIXME:timer_fwrite(&tux.invincible_timer,fi);
+ //FIXME:timer_fwrite(&tux.skidding_timer,fi);
+ //FIXME:timer_fwrite(&tux.safe_timer,fi);
+ //FIXME:timer_fwrite(&tux.frame_timer,fi);
timer_fwrite(&time_left,fi);
ui = st_get_ticks();
fwrite(&ui,sizeof(int),1,fi);
}
fclose(fi);
-
+#endif
}
void
-GameSession::loadgame(int slot)
+GameSession::loadgame(int)
{
+#if 0
char savefile[1024];
char str[100];
FILE* fi;
fread(&score, sizeof(int),1,fi);
fread(&distros, sizeof(int),1,fi);
fread(&scroll_x,sizeof(float),1,fi);
- fread(&tux, sizeof(Player), 1, fi);
- timer_fread(&tux.invincible_timer,fi);
- timer_fread(&tux.skidding_timer,fi);
- timer_fread(&tux.safe_timer,fi);
- timer_fread(&tux.frame_timer,fi);
+ //FIXME:fread(&tux, sizeof(Player), 1, fi);
+ //FIXME:timer_fread(&tux.invincible_timer,fi);
+ //FIXME:timer_fread(&tux.skidding_timer,fi);
+ //FIXME:timer_fread(&tux.safe_timer,fi);
+ //FIXME:timer_fread(&tux.frame_timer,fi);
timer_fread(&time_left,fi);
fread(&ui,sizeof(int),1,fi);
fclose(fi);
}
-
+#endif
}
std::string slotinfo(int slot)
{
private:
bool quit;
- timer_type fps_timer, frame_timer;
+ timer_type fps_timer;
+ timer_type frame_timer;
World* world;
+ int st_gl_mode;
+
+ float fps_fps;
+ unsigned int last_update_time;
+ unsigned int update_time;
+ int pause_menu_frame;
+ int debug_fps;
+ bool game_pause;
+
+ // FIXME: Hack for restarting the level
+ std::string subset;
public:
GameSession();
GameSession(const std::string& filename);
GameSession(const std::string& subset, int levelnb, int mode);
-
+ ~GameSession();
+
+ /** Enter the busy loop */
int run();
+
void draw();
int action();
- void process_events();
Level* get_level() { return world->get_level(); }
World* get_world() { return world; }
private:
static GameSession* current_;
- void levelintro();
+ void init();
+
void start_timers();
+ void process_events();
+
+ void levelintro();
+ void drawstatus();
+ void drawendscreen();
+ void drawresultscreen(void);
};
std::string slotinfo(int slot);
bkgd_red = 0;
bkgd_green = 0;
bkgd_blue = 0;
+ endpos = 0;
for(int i = 0; i < 15; ++i)
{
}
int
-Level::load(const char *subset, int level)
+Level::load(const std::string& subset, int level)
{
char filename[1024];
// Load data file:
- snprintf(filename, 1024, "%s/levels/%s/level%d.stl", st_dir, subset, level);
+ snprintf(filename, 1024, "%s/levels/%s/level%d.stl", st_dir, subset.c_str(), level);
if(!faccessible(filename))
- snprintf(filename, 1024, "%s/levels/%s/level%d.stl", datadir.c_str(), subset, level);
+ snprintf(filename, 1024, "%s/levels/%s/level%d.stl", datadir.c_str(), subset.c_str(), level);
return load(filename);
}
}
}
- // FIXME: Set the global gravity to the latest loaded level's gravity
- ::gravity = gravity;
-
// Mark the end position of this level!
// FIXME: -10 is a rather random value, we still need some kind of
// real levelend gola
int bkgd_green;
int bkgd_blue;
int width;
+ int endpos;
float gravity;
std::vector<BadGuyData> badguy_data;
/** Load data for this level:
Returns -1, if the loading of the level failed. */
- int load(const char* subset, int level);
+ int load(const std::string& subset, int level);
/** Load data for this level:
Returns -1, if the loading of the level failed. */
#include "scene.h"
#include "button.h"
#include "tile.h"
+#include "resources.h"
/* definitions to aid development */
#define DONE_LEVELEDITOR 1
#define SELECT_W 2 // size of the selections lines
#define SELECT_CLR 0, 255, 0, 255 // lines color (R, G, B, A)
-/* gameloop funcs declerations */
-
-void loadshared(void);
-void unloadshared(void);
-
/* own declerations */
/* crutial ones (main loop) */
int le_init();
#include <iostream>
#include <math.h>
#include "globals.h"
+#include "world.h"
+#include "level.h"
#include "scene.h"
ParticleSystem::ParticleSystem()
do {
particle->speed = snowsize/60.0 + (float(rand()%10)/300.0);
} while(particle->speed < 0.01);
- particle->speed *= gravity;
+ particle->speed *= World::current()->get_level()->gravity;
particles.push_back(particle);
}
#include "defines.h"
#include "physic.h"
#include "timer.h"
-
-float gravity;
+#include "world.h"
+#include "level.h"
Physic::Physic()
: ax(0), ay(0), vx(0), vy(0), gravity_enabled(true)
void
Physic::apply(float &x, float &y)
{
- float grav;
- if(gravity_enabled)
- grav = gravity / 100.0;
- else
- grav = 0;
+ float gravity = World::current()->get_level()->gravity;
+ float grav;
+ if(gravity_enabled)
+ grav = gravity / 100.0;
+ else
+ grav = 0;
- x += vx * frame_ratio + ax * frame_ratio * frame_ratio;
- y += vy * frame_ratio + (ay + grav) * frame_ratio * frame_ratio;
- vx += ax * frame_ratio;
- vy += (ay + grav) * frame_ratio;
+ x += vx * frame_ratio + ax * frame_ratio * frame_ratio;
+ y += vy * frame_ratio + (ay + grav) * frame_ratio * frame_ratio;
+ vx += ax * frame_ratio;
+ vy += (ay + grav) * frame_ratio;
}
bool gravity_enabled;
};
-/* global variables. */
-extern float gravity;
-
#endif /*SUPERTUX_PHYSIC_H*/
timer_init(&skidding_timer,true);
timer_init(&safe_timer,true);
timer_init(&frame_timer,true);
+
physic.reset();
}
// timer_check(&skidding_timer); // disabled
/* End of level? */
-
- if (base.x >= endpos && endpos != 0)
+ if (base.x >= World::current()->get_level()->endpos
+ && World::current()->get_level()->endpos != 0)
{
next_level = 1;
}
void
Player::keep_in_bounds()
{
- Level* plevel = GameSession::current()->get_level();
+ Level* plevel = World::current()->get_level();
/* Keep tux in bounds: */
if (base.x< 0)
}
else if (base.x > screen->w / 2 + scroll_x
- && scroll_x < ((GameSession::current()->get_level()->width * 32) - screen->w))
+ && scroll_x < ((World::current()->get_level()->width * 32) - screen->w))
{
// FIXME: Scrolling needs to be handled by a seperate View
// class, doing it as a player huck is ugly
class Player
{
public:
- player_input_type input;
player_keymap_type keymap;
+ int lives;
int score;
int distros;
+
+ player_input_type input;
bool got_coffee;
int size;
bool duck;
bool jumping;
int frame_;
int frame_main;
- int lives;
- base_type base;
- base_type old_base;
- base_type previous_base;
+
+ base_type base;
+ base_type old_base;
+ base_type previous_base;
timer_type invincible_timer;
timer_type skidding_timer;
timer_type safe_timer;
void keep_in_bounds();
bool on_ground();
bool under_solid();
+
private:
void handle_horizontal_input(int dir);
void handle_vertical_input();
#include "player.h"
#include "badguy.h"
#include "gameobjs.h"
+#include "special.h"
#include "resources.h"
texture_type img_waves[3];
int distros;
int level;
int next_level;
-int game_pause;
int score_multiplier;
-int endpos;
bool counting_distros;
int distro_counter;
timer_type super_bkgd_timer;
+
+// FIXME: Move this into a view class
float scroll_x;
+
unsigned int global_frame_counter;
-Player tux;
texture_type img_box_full;
texture_type img_box_empty;
texture_type img_mints;
#ifndef SUPERTUX_SCENE_H
#define SUPERTUX_SCENE_H
-#include "defines.h"
-#include "player.h"
-#include "badguy.h"
-#include "special.h"
-#include "level.h"
-#include "particlesystem.h"
+#include "texture.h"
+#include "timer.h"
#define FRAME_RATE 10 // 100 Frames per second (10ms)
-extern int score;
-extern int distros;
-extern int level;
-extern int next_level;
-extern int game_pause;
-extern int score_multiplier;
-extern int endpos;
+extern int score;
+extern int distros;
+extern int level;
+extern int next_level;
+extern int score_multiplier;
extern bool counting_distros;
-extern int distro_counter;
+extern int distro_counter;
extern timer_type super_bkgd_timer;
extern float scroll_x;
extern unsigned int global_frame_counter;
-extern Player tux;
extern texture_type img_box_full, img_box_empty, img_mints, img_coffee, img_super_bkgd, img_red_glow;
extern timer_type time_left;
extern double frame_ratio;
options_controls_menu->additem(MN_LABEL,"Controls",0,0);
options_controls_menu->additem(MN_HL,"",0,0);
- options_controls_menu->additem(MN_CONTROLFIELD,"Move Right",tux.keymap.right,0);
+ //FIXME:options_controls_menu->additem(MN_CONTROLFIELD,"Move Right", tux.keymap.right,0);
options_controls_menu->additem(MN_HL,"",0,0);
options_controls_menu->additem(MN_BACK,"Back",0,0);
Menu::set_current(main_menu);
}
else
- { // Slot contains a level, so load it
+ {
+ puts("Warning: Loading games isn't supported at the moment");
+#if 0
+ // Slot contains a level, so load it
if (game_started)
{
GameSession session("default",slot - 1,ST_GL_LOAD_GAME);
else
{
//loadgame(slot - 1);
- puts("Warning: Loading games isn't supported at the moment");
}
+#endif
}
st_pause_ticks_stop();
return true;
#include "player.h"
#include "math.h"
#include "tile.h"
-
-void loadshared(void);
+#include "resources.h"
static texture_type bkg_title;
static texture_type logo;
static texture_type img_choose_subset;
static bool walking;
-static Player titletux;
static timer_type random_timer;
static SDL_Event event;
texture_draw_bg(&bkg_title);
}
-void draw_demo(Level* plevel)
+void draw_demo(GameSession* session)
{
+ World::set_current(session->get_world());
+ //World* world = session->get_world();
+ Level* plevel = session->get_level();
+ Player* tux = session->get_world()->get_tux();
+
/* FIXME:
// update particle systems
std::vector<ParticleSystem*>::iterator p;
}
global_frame_counter++;
- titletux.key_event(SDLK_RIGHT,DOWN);
+ tux->key_event(SDLK_RIGHT,DOWN);
if(timer_check(&random_timer))
{
if(walking)
- titletux.key_event(SDLK_UP,UP);
+ tux->key_event(SDLK_UP,UP);
else
- titletux.key_event(SDLK_UP,DOWN);
+ tux->key_event(SDLK_UP,DOWN);
}
else
{
}
// Wrap around at the end of the level back to the beginnig
- if(plevel->width * 32 - 320 < titletux.base.x)
+ if(plevel->width * 32 - 320 < tux->base.x)
{
- titletux.base.x = titletux.base.x - (plevel->width * 32 - 640);
- scroll_x = titletux.base.x - 320;
+ tux->base.x = tux->base.x - (plevel->width * 32 - 640);
+ scroll_x = tux->base.x - 320;
}
- float last_tux_x_pos = titletux.base.x;
- titletux.action();
+ float last_tux_x_pos = tux->base.x;
+ tux->action();
// Jump if tux stays in the same position for one loop, ie. if he is
// stuck behind a wall
- if (last_tux_x_pos == titletux.base.x)
+ if (last_tux_x_pos == tux->base.x)
walking = false;
- titletux.draw();
+ tux->draw();
/* DEMO end */
}
/* --- TITLE SCREEN --- */
-
bool title(void)
{
string_list_type level_subsets;
timer_init(&random_timer, true);
walking = true;
- titletux.init();
st_pause_ticks_init();
GameSession session(datadir + "/levels/misc/menu.stl");
loadshared();
+
//FIXME:activate_particle_systems();
- /* Lower the gravity that tux doesn't jump to hectically through the demo */
- //gravity = 5;
/* Reset menu variables */
menu_reset();
/* Draw the background: */
draw_background();
- draw_demo(session.get_level());
+ draw_demo(&session);
if (current_menu == main_menu)
texture_draw(&logo, 160, 30);
{
if (process_load_game_menu())
{
+ // FIXME: shouldn't be needed if GameSession doesn't relay on global variables
// reset tux
scroll_x = 0;
- titletux.level_begin();
+ //titletux.level_begin();
update_time = st_get_ticks();
}
}
current_ = this;
level = new Level;
+ tux.init();
}
World::~World()
counting_distros = false;
distro_counter = 0;
- endpos = 0;
-
/* set current song/music */
set_current_music(LEVEL_MUSIC);
}
int
-World::load(const char* subset, int level_nr)
+World::load(const std::string& subset, int level_nr)
{
return level->load(subset, level_nr);
}
#include "type.h"
#include "scene.h"
#include "special.h"
+#include "badguy.h"
#include "particlesystem.h"
#include "gameobjs.h"
+class Level;
+
/** The World class holds a level and all the game objects (badguys,
bouncy distros, etc) that are needed to run a game. */
class World
{
public:
Level* level;
+
+ Player tux;
std::vector<BouncyDistro> bouncy_distros;
std::vector<BrokenBrick> broken_bricks;
std::vector<ParticleSystem*> particle_systems;
static World* current_;
+
public:
static World* current() { return current_; }
+ static void set_current(World* w) { current_ = w; }
World();
~World();
- Level* get_level() { return level; }
+ Level* get_level() { return level; }
+ Player* get_tux() { return &tux; }
void set_defaults();
/** Load data for this level:
Returns -1, if the loading of the level failed. */
- int load(const char* subset, int level);
+ int load(const std::string& subset, int level);
/** Load data for this level:
Returns -1, if the loading of the level failed. */
{
std::cout << "Enter the current level: " << i->name << std::endl;;
halt_music();
- GameSession session(const_cast<char*>((datadir + "levels/default/" + i->name).c_str()),
+ GameSession session(datadir + "levels/default/" + i->name,
1, ST_GL_LOAD_LEVEL_FILE);
session.run();
play_music(song, 1);