themselfes. This could speed up rendering of tilemaps.
[M] Make the gamelogic run in a fixed logical framerate
---Miscellaneous--
-[?] think about how to implement scripting, and how to make a simple and easy to
- use api for the scripting interface
- (language will probably be lua - just have to figure out how well we can do
- without OO support in the scripting language.
- Other candidates are python, ruby and less likely java, mono/.net,
- surely no own invention, perl or 1 of these c-like scripting languages)
+--Objects--
[H] Create a "sound object" that is an object or area, that can be placed on the
map and constantly plays a .wav file to improve game athmosphere.
Good examples would be a water sound which can be placed at waterfalls,
[H] Add a rope object on which tux is able to climb, also add a ? block that
emits a rope when hit
[H] redo trampolines
+
+--Miscellaneous--
+[?] think about how to implement scripting, and how to make a simple and easy to
+ use api for the scripting interface
+ (language will probably be lua - just have to figure out how well we can do
+ without OO support in the scripting language.
+ Other candidates are python, ruby and less likely java, mono/.net,
+ surely no own invention, perl or 1 of these c-like scripting languages)
[H] Buttjump related things
- enable buttjump again
- Should kill enemies with a certain range
(y-offset 0)
(images "shared/stomp.png")
))
+
+ (sprite (name "bell")
+ (action
+ (name "default")
+ (x-offset 0)
+ (y-offset 0)
+ (images "shared/bell/bell-m.png")
+ )
+ (action
+ (name "ringing")
+ (images "shared/bell/bell-l.png"
+ "shared/bell/bell-m.png"
+ "shared/bell/bell-r.png"
+ "shared/bell/bell-m.png"
+ )
+ )
+ )
)
;; EOF ;;
(reset-points
)
(objects
+ (bell (x 609) (y 6500))
+ (bell (x 543) (y 3655))
)
)
return movement;
}
+ /** places the moving object at a specific position. Be carefull when
+ * using this function. There are no collision detection checks performed
+ * here so bad things could happen.
+ */
+ virtual void set_pos(const Vector& pos)
+ {
+ bbox.set_pos(pos);
+ }
+
protected:
friend class Sector;
friend class CollisionGrid;
- friend class FlipLevelTransformer;
/** The bounding box of the object (as used for collision detection, this
* isn't necessarily the bounding box for graphics)
void
FlipLevelTransformer::transform_moving_object(float height, MovingObject*object)
{
- Vector pos = object->bbox.p1;
+ Vector pos = object->get_pos();
pos.y = height - pos.y;
- object->bbox.set_pos(pos);
+ object->set_pos(pos);
}
context = new DrawingContext();
- last_swap_point = Vector(-1, -1);
- last_swap_stats.reset();
-
restart_level();
}
global_stats.set_total_points(BADGUYS_KILLED_STAT, level->get_total_badguys());
global_stats.set_total_points(TIME_NEEDED_STAT, level->timelimit);
- currentsector = level->get_sector("main");
- if(!currentsector)
- Termination::abort("Level has no main sector.", "");
- currentsector->activate("main");
-
-#if 0
- // Set Tux to the nearest reset point
- if(tux_pos.x != -1)
- {
- tux_pos = currentsector->get_best_spawn_point(tux_pos);
-
- if(last_swap_point.x > tux_pos.x)
- tux_pos = last_swap_point;
- else // new swap point
- {
- last_swap_point = tux_pos;
-
- last_swap_stats += global_stats;
- }
-
- currentsector->player->base.x = tux_pos.x;
- currentsector->player->base.y = tux_pos.y;
-
- // has to reset camera on swapping
- currentsector->camera->reset(Vector(currentsector->player->base.x,
- currentsector->player->base.y));
- }
-#endif
-
- if (st_gl_mode != ST_GL_DEMO_GAME)
- {
- if(st_gl_mode == ST_GL_PLAY || st_gl_mode == ST_GL_LOAD_LEVEL_FILE)
- levelintro();
+ if(reset_sector != "") {
+ currentsector = level->get_sector(reset_sector);
+ if(!currentsector) {
+ std::stringstream msg;
+ msg << "Couldn't find sector '" << reset_sector << "' for resetting tux.";
+ throw std::runtime_error(msg.str());
}
+ currentsector->activate(reset_pos);
+ } else {
+ currentsector = level->get_sector("main");
+ if(!currentsector)
+ throw std::runtime_error("Couldn't find main sector");
+ currentsector->activate("main");
+ }
+
+ if(st_gl_mode == ST_GL_PLAY || st_gl_mode == ST_GL_LOAD_LEVEL_FILE)
+ levelintro();
start_timers();
currentsector->play_music(LEVEL_MUSIC);
}
void
-GameSession::levelintro(void)
+GameSession::levelintro()
{
SoundManager::get()->halt_music();
}
}
- /* Check if chacrater is ASCII */
- char ch[2];
- if((event.key.keysym.unicode & 0xFF80) == 0)
- {
- ch[0] = event.key.keysym.unicode & 0x7F;
- ch[1] = '\0';
- }
+ /* Check if chacrater is ASCII */
+ char ch[2];
+ if((event.key.keysym.unicode & 0xFF80) == 0)
+ {
+ ch[0] = event.key.keysym.unicode & 0x7F;
+ ch[1] = '\0';
+ }
last_keys.append(ch); // add to cheat keys
handle_cheats();
break;
/* End of level? */
if(end_sequence && endsequence_timer.check()) {
- exit_status = ES_LEVEL_FINISHED;
- global_stats += last_swap_stats; // add swap points stats
- return;
+ exit_status = ES_LEVEL_FINISHED;
+ return;
} else if (!end_sequence && tux->is_dead()) {
player_status.bonus = PlayerStatus::NO_BONUS;
}
void
+GameSession::set_reset_point(const std::string& sector, const Vector& pos)
+{
+ reset_sector = sector;
+ reset_pos = pos;
+}
+
+void
GameSession::start_sequence(const std::string& sequencename)
{
if(sequencename == "endsequence" || sequencename == "fireworks") {
keeping the speed and framerate sane, etc. */
class GameSession
{
-private:
- Uint32 fps_ticks;
- Timer2 endsequence_timer;
- Level* level;
- Sector* currentsector;
-
- int st_gl_mode;
- int levelnb;
- float fps_fps;
- int pause_menu_frame;
-
- /** If true the end_sequence will be played, user input will be
- ignored while doing that */
- enum EndSequenceState {
- NO_ENDSEQUENCE,
- ENDSEQUENCE_RUNNING, // tux is running right
- ENDSEQUENCE_WAITING // waiting for the end of the music
- };
- EndSequenceState end_sequence;
- float last_x_pos;
-
- bool game_pause;
-
- std::string levelfile;
-
- // the sector and spawnpoint we shoudl spawn after this frame
- std::string newsector;
- std::string newspawnpoint;
-
public:
enum ExitStatus { ES_NONE, ES_LEVEL_FINISHED, ES_GAME_OVER, ES_LEVEL_ABORT };
-private:
- ExitStatus exit_status;
+
public:
DrawingContext* context;
Timer2 time_left;
void respawn(const std::string& sectorname,
const std::string& spawnpointname);
+ void set_reset_point(const std::string& sectorname,
+ const Vector& pos);
Sector* get_current_sector()
{ return currentsector; }
void start_sequence(const std::string& sequencename);
private:
- static GameSession* current_;
-
- // for cheating
- std::string last_keys;
-
- // swap points
- Vector last_swap_point;
- Statistics last_swap_stats;
-
- Statistics* best_level_statistics;
-
void restart_level();
void check_end_conditions();
void on_escape_press();
void process_menu();
+
+
+ Uint32 fps_ticks;
+ Timer2 endsequence_timer;
+ Level* level;
+ Sector* currentsector;
+
+ int st_gl_mode;
+ int levelnb;
+ float fps_fps;
+ int pause_menu_frame;
+
+ /** If true the end_sequence will be played, user input will be
+ ignored while doing that */
+ enum EndSequenceState {
+ NO_ENDSEQUENCE,
+ ENDSEQUENCE_RUNNING, // tux is running right
+ ENDSEQUENCE_WAITING // waiting for the end of the music
+ };
+ EndSequenceState end_sequence;
+ float last_x_pos;
+
+ bool game_pause;
+
+ std::string levelfile;
+
+ // reset point (the point where tux respawns if he dies)
+ std::string reset_sector;
+ Vector reset_pos;
+
+ // the sector and spawnpoint we should spawn after this frame
+ std::string newsector;
+ std::string newspawnpoint;
+
+ static GameSession* current_;
+
+ // for cheating
+ std::string last_keys;
+
+ Statistics* best_level_statistics;
+
+ ExitStatus exit_status;
};
std::string slotinfo(int slot);
-void bumpbrick(float x, float y);
-
/** Return true if the gameloop() was entered, false otherwise */
bool process_load_game_menu();
--- /dev/null
+#include <config.h>
+
+#include "bell.h"
+#include "resources.h"
+#include "special/sprite_manager.h"
+#include "video/drawing_context.h"
+#include "player.h"
+#include "object_factory.h"
+#include "gameloop.h"
+#include "sector.h"
+
+Bell::Bell(const lisp::Lisp& lisp)
+ : ringing(false)
+{
+ lisp.get("x", bbox.p1.x);
+ lisp.get("y", bbox.p1.y);
+ bbox.set_size(32, 32);
+ sprite = sprite_manager->create("bell");
+}
+
+Bell::~Bell()
+{
+ delete sprite;
+}
+
+void
+Bell::write(lisp::Writer& writer)
+{
+ writer.start_list("bell");
+ writer.write_float("x", bbox.p1.x);
+ writer.write_float("y", bbox.p1.y);
+ writer.end_list("bell");
+}
+
+void
+Bell::action(float )
+{
+}
+
+void
+Bell::draw(DrawingContext& context)
+{
+ sprite->draw(context, get_pos(), LAYER_TILES);
+}
+
+HitResponse
+Bell::collision(GameObject& other, const CollisionHit& )
+{
+ if(ringing)
+ return ABORT_MOVE;
+
+ Player* player = dynamic_cast<Player*> (&other);
+ if(player) {
+ ringing = true;
+ // TODO play sound
+ sprite->set_action("ringing");
+ GameSession::current()->set_reset_point(Sector::current()->get_name(),
+ get_pos());
+ }
+
+ return ABORT_MOVE;
+}
+
+IMPLEMENT_FACTORY(Bell, "bell");
--- /dev/null
+#ifndef __BELL_H__
+#define __BELL_H__
+
+#include "lisp/lisp.h"
+#include "special/moving_object.h"
+#include "special/sprite.h"
+#include "serializable.h"
+
+using namespace SuperTux;
+
+/**
+ * A bell: When tux touches it, it begins ringing and you will respawn at this
+ * position.
+ */
+class Bell : public MovingObject, public Serializable
+{
+public:
+ Bell(const lisp::Lisp& lisp);
+ ~Bell();
+
+ void write(lisp::Writer& writer);
+ void action(float elapsed_time);
+ void draw(DrawingContext& context);
+ HitResponse collision(GameObject& other, const CollisionHit& hit);
+
+private:
+ Sprite* sprite;
+ bool ringing;
+};
+
+#endif
+
-#ifndef __BOX_H__
-#define __BOX_H__
+#ifndef __BLOCK_H__
+#define __BLOCK_H__
#include "special/moving_object.h"
virtual_width = screen->w * 2;
- // create some random snowflakes
+ // create some random raindrops
size_t raindropcount = size_t(virtual_width/8.0);
for(size_t i=0; i<raindropcount; ++i) {
RainParticle* particle = new RainParticle;
return;
}
- if(input.fire == false)
+ if(input.fire == false && grabbed_object) {
grabbed_object = 0;
-
+ // move the grabbed object a bit away from tux
+ Vector pos = get_pos() +
+ Vector(dir == LEFT ? -bbox.get_width() : bbox.get_width(),
+ bbox.get_height()*0.66666 - 32);
+ MovingObject* object = dynamic_cast<MovingObject*> (grabbed_object);
+ if(object) {
+ object->set_pos(pos);
+ } else {
+#ifdef DEBUG
+ std::cout << "Non MovingObjetc grabbed?!?\n";
+#endif
+ }
+ }
if(!dying)
handle_input();
class Portable
{
public:
- /**
- * called each frame when the object has been grabbed.
- */
+ virtual ~Portable()
+ { }
+
+ /**
+ * called each frame when the object has been grabbed.
+ */
virtual void grab(MovingObject& object, const Vector& pos) = 0;
+
+ /** called when object isn't grabbed anymore */
+ virtual void ungrab(MovingObject& object)
+ {
+ (void) object;
+ }
};
#endif
void
Sector::activate(const std::string& spawnpoint)
{
+ SpawnPoint* sp = 0;
+ for(SpawnPoints::iterator i = spawnpoints.begin(); i != spawnpoints.end();
+ ++i) {
+ if((*i)->name == spawnpoint) {
+ sp = *i;
+ break;
+ }
+ }
+ if(!sp) {
+ std::cerr << "Spawnpoint '" << spawnpoint << "' not found.\n";
+ if(spawnpoint != "main") {
+ activate("main");
+ } else {
+ activate(Vector(0, 0));
+ }
+ } else {
+ activate(sp->pos);
+ }
+}
+
+void
+Sector::activate(const Vector& player_pos)
+{
_current = this;
// Apply bonuses from former levels
- switch (player_status.bonus)
- {
+ switch (player_status.bonus) {
case PlayerStatus::NO_BONUS:
break;
case PlayerStatus::GROWUP_BONUS:
player->grow(false);
break;
- }
- SpawnPoint* sp = 0;
- for(SpawnPoints::iterator i = spawnpoints.begin(); i != spawnpoints.end();
- ++i) {
- if((*i)->name == spawnpoint) {
- sp = *i;
+ default:
+ std::cerr << "Unknown bonus in PlayerStatus?!?\n";
break;
- }
- }
- if(!sp) {
- std::cerr << "Spawnpoint '" << spawnpoint << "' not found.\n";
- } else {
- player->move(sp->pos);
}
+ player->move(player_pos);
camera->reset(player->get_pos());
}
-Vector
-Sector::get_best_spawn_point(Vector pos)
-{
- Vector best_reset_point = Vector(-1,-1);
-
- for(SpawnPoints::iterator i = spawnpoints.begin(); i != spawnpoints.end();
- ++i) {
- if((*i)->name != "main")
- continue;
- if((*i)->pos.x > best_reset_point.x && (*i)->pos.x < pos.x)
- best_reset_point = (*i)->pos;
- }
-
- return best_reset_point;
-}
-
Rectangle
Sector::get_active_region()
{
void write(lisp::Writer& writer);
/// activates this sector (change music, intialize player class, ...)
- void activate(const std::string& spawnpoint = "main");
- /// get best spawn point
- Vector get_best_spawn_point(Vector pos);
+ void activate(const std::string& spawnpoint);
+ void activate(const Vector& player_pos);
void action(float elapsed_time);
void update_game_objects();
{
// FIXME: shouldn't be needed if GameSession
// didn't relay on global variables
- titlesession->get_current_sector()->activate();
+ titlesession->get_current_sector()->activate("main");
titlesession->set_current();
frame_rate.update();
contrib_subset_menu->additem(MN_HL,"",0,0);
contrib_subset_menu->additem(MN_BACK, _("Back"), 0, 0);
- titlesession->get_current_sector()->activate();
+ titlesession->get_current_sector()->activate("main");
titlesession->set_current();
}
}
logo = new Surface(datadir + "/images/title/logo.png", true);
img_choose_subset = new Surface(datadir + "/images/status/choose-level-subset.png", true);
- titlesession->get_current_sector()->activate();
+ titlesession->get_current_sector()->activate("main");
titlesession->set_current();
/* --- Main title loop: --- */