}
GameSession::GameSession(const std::string& levelfile_, int mode,
- bool flip_level_, Statistics* statistics)
+ Statistics* statistics)
: level(0), currentsector(0), st_gl_mode(mode),
end_sequence(NO_ENDSEQUENCE), levelfile(levelfile_),
- flip_level(flip_level_), best_level_statistics(statistics)
+ best_level_statistics(statistics)
{
current_ = this;
context = new DrawingContext();
- if(flip_levels_mode)
- flip_level = true;
-
last_swap_point = Vector(-1, -1);
last_swap_stats.reset();
level = new Level;
level->load(levelfile);
- if(flip_level)
- level->do_vertical_flip();
global_stats.reset();
global_stats.set_total_points(COINS_COLLECTED_STAT, level->get_total_coins());
Vector(screen->w/2, 350), CENTER_ALLIGN, LAYER_FOREGROUND1);
- if(flip_level)
- context.draw_text(white_text,
- _("Level Vertically Flipped!"),
- Vector(screen->w/2, 310), CENTER_ALLIGN, LAYER_FOREGROUND1);
-
if(best_level_statistics != NULL)
best_level_statistics->draw_message_info(context, _("Best Level Statistics"));
bool game_pause;
std::string levelfile;
- bool flip_level;
// the sector and spawnpoint we shoudl spawn after this frame
std::string newsector;
DrawingContext* context;
Timer2 time_left;
- GameSession(const std::string& levelfile, int mode, bool flip_level_ = false,
- Statistics* statistics = 0);
+ GameSession(const std::string& levelfile, int mode, Statistics* statistics=0);
~GameSession();
/** Enter the busy loop */
#include "object/gameobjs.h"
#include "object/camera.h"
#include "object/tilemap.h"
+#include "object/coin.h"
using namespace std;
}
void
-Level::do_vertical_flip()
-{
-#if 0
- for(Sectors::iterator i = sectors.begin(); i != sectors.end(); ++i)
- i->second->do_vertical_flip();
-#endif
-}
-
-void
Level::add_sector(Sector* sector)
{
sectors.insert(std::make_pair(sector->get_name(), sector));
{
int total_coins = 0;
for(Sectors::iterator i = sectors.begin(); i != sectors.end(); ++i) {
- TileMap* solids = i->second->solids;
- assert(solids != 0);
- for(size_t x = 0; x < solids->get_width(); ++x)
- for(size_t y = 0; y < solids->get_height(); ++y) {
- const Tile* tile = solids->get_tile(x, y);
- if(tile == 0) {
- std::cerr << "Invalid tile in sector '" << i->first << "'.\n";
- continue;
- }
- if(tile->attributes & Tile::COIN)
- total_coins++;
- }
+ Sector* sector = i->second;
+ for(Sector::GameObjects::iterator o = sector->gameobjects.begin();
+ o != sector->gameobjects.end(); ++o) {
+ Coin* coin = dynamic_cast<Coin*> (*o);
+ if(coin)
+ total_coins++;
+ }
}
return total_coins;
}
const std::string& get_author() const
{ return author; }
- /** Flips the level vertically */
- void do_vertical_flip();
-
void add_sector(Sector* sector);
Sector* get_sector(const std::string& name);
if(!tile)
continue;
- Surface* surface;
- if(tile->editor_images.size())
- surface = tile->editor_images[0];
- else if(tile->images.size())
- surface = tile->images[0];
- else
+ Surface* surface = tile->get_editor_image();
+ if(!surface)
continue;
Button button = Button(surface, "", SDLKey(0));
{
vector.push_back(tilemap->get_tile(x +
(int)(((selection_ini.x+scroll.x)*zoom)/32),
- y + (int)(((selection_ini.y+scroll.y)*zoom)/32))->id);
+ y + (int)(((selection_ini.y+scroll.y)*zoom)/32))->getID());
}
selection.push_back(vector);
}
const Tile* tile = solids->get_tile(x, y);
Vector pos(x*32, y*32);
- if(tile->id == 112) {
+ if(tile->getID() == 112) {
add_object(new InvisibleBlock(pos));
solids->change(x, y, 0);
- } else if(tile->id == 295) {
+ } else if(tile->getID() == 295) {
add_object(new Spike(pos, Spike::NORTH));
solids->change(x, y, 0);
- } else if(tile->id == 296) {
+ } else if(tile->getID() == 296) {
add_object(new Spike(pos, Spike::EAST));
solids->change(x, y, 0);
- } else if(tile->id == 297) {
+ } else if(tile->getID() == 297) {
add_object(new Spike(pos, Spike::SOUTH));
solids->change(x, y, 0);
- } else if(tile->id == 298) {
+ } else if(tile->getID() == 298) {
add_object(new Spike(pos, Spike::WEST));
solids->change(x, y, 0);
- } else if(tile->attributes & Tile::COIN) {
+ } else if(tile->getAttributes() & Tile::COIN) {
add_object(new Coin(pos));
solids->change(x, y, 0);
- } else if(tile->attributes & Tile::FULLBOX) {
- add_object(new BonusBlock(pos, tile->data));
+ } else if(tile->getAttributes() & Tile::FULLBOX) {
+ add_object(new BonusBlock(pos, tile->getData()));
solids->change(x, y, 0);
- } else if(tile->attributes & Tile::BRICK) {
- add_object(new Brick(pos, tile->data));
+ } else if(tile->getAttributes() & Tile::BRICK) {
+ add_object(new Brick(pos, tile->getData()));
solids->change(x, y, 0);
- } else if(tile->attributes & Tile::GOAL) {
+ } else if(tile->getAttributes() & Tile::GOAL) {
add_object(new SequenceTrigger(pos, "endsequence"));
solids->change(x, y, 0);
}
const Tile* tile = solids->get_tile(x, y);
if(!tile)
continue;
- if(!(tile->attributes & Tile::SOLID))
+ if(!(tile->getAttributes() & Tile::SOLID))
continue;
- if((tile->attributes & Tile::UNISOLID) && object->movement.y < 0)
+ if((tile->getAttributes() & Tile::UNISOLID) && object->movement.y < 0)
continue;
- if(tile->attributes & Tile::SLOPE) { // slope tile
+ if(tile->getAttributes() & Tile::SLOPE) { // slope tile
AATriangle triangle;
Vector p1(x*32, y*32);
Vector p2((x+1)*32, (y+1)*32);
- triangle = AATriangle(p1, p2, tile->data);
+ triangle = AATriangle(p1, p2, tile->getData());
if(Collision::rectangle_aatriangle(temphit, dest, object->movement,
triangle)) {
#include "app/globals.h"
#include "tile.h"
#include "scene.h"
+#include "resources.h"
#include "utils/lispreader.h"
#include "math/vector.h"
#include "video/drawing_context.h"
-/** Dirty little helper to create a surface from a snipped of lisp:
- *
- * "filename"
- * (region "filename" x y w h)
- */
-static
-Surface* create_surface(lisp_object_t* cur)
-{
- if (lisp_string_p(cur))
- {
- return new Surface(datadir + "/images/tilesets/" + lisp_string(cur),
- true);
- }
- else if (lisp_cons_p(cur) && lisp_symbol_p(lisp_car(cur)))
- {
- lisp_object_t* sym = lisp_car(cur);
- lisp_object_t* data = lisp_cdr(cur);
-
- if (strcmp(lisp_symbol(sym), "region") == 0)
- {
- if (lisp_list_length(data) == 5) // (image-region filename x y w h)
- {
- return new Surface(datadir + "/images/tilesets/" + lisp_string(lisp_car(data)),
- lisp_integer(lisp_list_nth(data, 1)),
- lisp_integer(lisp_list_nth(data, 2)),
- lisp_integer(lisp_list_nth(data, 3)),
- lisp_integer(lisp_list_nth(data, 4)),
- true);
- }
- else
- {
- std::cout << "Tile: Type mispatch, should be '(region \"somestring\" x y w h)'" << std::endl;
- return 0;
- }
- }
- else
- {
- std::cout << "Tile: Unhandled tag: " << lisp_symbol(sym) << std::endl;
- return 0;
- }
- }
-
- std::cout << "Tile: unhandled element" << std::endl;
- return 0;
-}
-
-/** Create a vector of surfaces (aka Sprite) from a piece of lisp:
- ((image "bla.png") (image-region "bla.png") ...)
- */
-static
-std::vector<Surface*> create_surfaces(lisp_object_t* cur)
-{
- std::vector<Surface*> surfs;
-
- while(cur)
- {
- Surface* surface = create_surface(lisp_car(cur));
- if (surface)
- surfs.push_back(surface);
- else
- std::cout << "Tile: Couldn't create image" << std::endl;
-
- cur = lisp_cdr(cur);
- }
-
- return surfs;
-}
-
Tile::Tile()
- : id(0), attributes(0), data(0), next_tile(0), anim_fps(1)
+ : id(0), editor_image(0), attributes(0), data(0), anim_fps(1)
{
}
++i) {
delete *i;
}
- for(std::vector<Surface*>::iterator i = editor_images.begin();
- i != editor_images.end(); ++i) {
- delete *i;
- }
+ delete editor_image;
}
void
-Tile::read(LispReader& reader)
+Tile::parse(LispReader& reader)
{
if(!reader.read_uint("id", id)) {
throw std::runtime_error("Missing tile-id.");
reader.read_int("data", data);
reader.read_float("anim-fps", anim_fps);
- reader.read_int("next-tile", next_tile);
if(reader.read_int("slope-type", data)) {
attributes |= SOLID | SLOPE;
}
- images = create_surfaces(reader.read_lisp("images"));
- editor_images = create_surfaces(reader.read_lisp("editor-images"));
+ parse_images(reader.read_lisp("images"));
+ reader.read_string("editor-images", editor_imagefile);
+}
+
+void
+Tile::parse_images(lisp_object_t* list)
+{
+ while(!lisp_nil_p(list)) {
+ lisp_object_t* cur = lisp_car(list);
+ if(lisp_string_p(cur)) {
+ imagespecs.push_back(ImageSpec(lisp_string(cur), Rectangle(0, 0, 0, 0)));
+ } else if(lisp_cons_p(cur) && lisp_symbol_p(lisp_car(cur))) {
+ lisp_object_t* sym = lisp_car(cur);
+ lisp_object_t* data = lisp_cdr(cur);
+
+ if (strcmp(lisp_symbol(sym), "region") == 0) {
+ float x = lisp_integer(lisp_list_nth(data, 1));
+ float y = lisp_integer(lisp_list_nth(data, 2));
+ float width = lisp_integer(lisp_list_nth(data, 3));
+ float height = lisp_integer(lisp_list_nth(data, 4));
+ imagespecs.push_back(ImageSpec(lisp_string(lisp_car(data)),
+ Rectangle(x, y, x+width, y+height)));
+ } else {
+ std::cerr << "Tile: Type mismatch, should be '(region \"somestring\" x y w h)'" << std::endl;
+ continue;
+ }
+ } else {
+ std::cerr << "Expected string or list in images tag.\n";
+ continue;
+ }
+
+ list = lisp_cdr(list);
+ }
+}
+
+void
+Tile::load_images()
+{
+ assert(images.size() == 0);
+ for(std::vector<ImageSpec>::iterator i = imagespecs.begin(); i !=
+ imagespecs.end(); ++i) {
+ const ImageSpec& spec = *i;
+ Surface* surface;
+ std::string file
+ = get_resource_filename(std::string("images/tilesets/") + spec.file);
+ if(spec.rect.get_width() <= 0) {
+ surface = new Surface(file, true);
+ } else {
+ surface = new Surface(file,
+ (int) spec.rect.p1.x,
+ (int) spec.rect.p1.y,
+ (int) spec.rect.get_width(),
+ (int) spec.rect.get_height(), true);
+ }
+ images.push_back(surface);
+ }
+ if(editor_imagefile != "") {
+ editor_image = new Surface(
+ get_resource_filename(
+ std::string("images/tilesets/") + editor_imagefile), true);
+ }
+}
+
+Surface*
+Tile::get_editor_image() const
+{
+ if(editor_image)
+ return editor_image;
+ if(images.size() > 0)
+ return images[0];
+
+ return 0;
}
void
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
// 02111-1307, USA.
-
#ifndef TILE_H
#define TILE_H
#include <vector>
-#include "SDL.h"
#include "video/surface.h"
+#include "utils/lispreader.h"
+#include "math/rectangle.h"
using namespace SuperTux;
-namespace SuperTux {
-class LispReader;
-}
-
/**
Tile Class
*/
class Tile
{
public:
- Tile();
- ~Tile();
-
- /// parses the tile and returns it's id number
- void read(LispReader& reader);
-
+ /// bitset for tile attributes
+ enum {
+ /** solid tile that is indestructable by Tux */
+ SOLID = 0x0001,
+ /** uni-directional solid tile */
+ UNISOLID = 0x0002,
+ /** a brick that can be destroyed by jumping under it */
+ BRICK = 0x0004,
+ /** an ice brick that makes tux sliding more than usual */
+ ICE = 0x0008,
+ /** a water tile in which tux starts to swim */
+ WATER = 0x0010,
+ /** a tile that hurts the player if he touches it */
+ SPIKE = 0x0020,
+ /** Bonusbox, content is stored in \a data */
+ FULLBOX = 0x0040,
+ /** Tile is a coin */
+ COIN = 0x0080,
+ /** the level should be finished when touching a goaltile.
+ * if data is 0 then the endsequence should be triggered, if data is 1
+ * then we can finish the level instantly.
+ */
+ GOAL = 0x0100,
+ /** slope tile */
+ SLOPE = 0x0200
+ };
+
+private:
unsigned int id;
- std::vector<Surface*> images;
- std::vector<Surface*> editor_images;
-
- /// bitset for tileflags
- enum {
- /** solid tile that is indestructable by Tux */
- SOLID = 0x0001,
- /** uni-directional solid tile */
- UNISOLID = 0x0002,
- /** a brick that can be destroyed by jumping under it */
- BRICK = 0x0004,
- /** an ice brick that makes tux sliding more than usual */
- ICE = 0x0008,
- /** a water tile in which tux starts to swim */
- WATER = 0x0010,
- /** a tile that hurts the player if he touches it */
- SPIKE = 0x0020,
- /** Bonusbox, content is stored in \a data */
- FULLBOX = 0x0040,
- /** Tile is a coin */
- COIN = 0x0080,
- /** the level should be finished when touching a goaltile.
- * if data is 0 then the endsequence should be triggered, if data is 1
- * then we can finish the level instantly.
- */
- GOAL = 0x0100,
- /** slope tile */
- SLOPE = 0x0200
+ struct ImageSpec {
+ ImageSpec(const std::string& newfile, const Rectangle& newrect)
+ : file(newfile), rect(newrect)
+ { }
+
+ std::string file;
+ Rectangle rect;
};
+ std::vector<ImageSpec> imagespecs;
+ std::vector<Surface*> images;
+ std::string editor_imagefile;
+ Surface* editor_image;
+
/** tile attributes */
Uint32 attributes;
/** General purpose data attached to a tile (content of a box, type of coin)*/
int data;
- /** Id of the tile that is going to replace this tile once it has
- been collected or jumped at */
- int next_tile;
-
float anim_fps;
+public:
+ ~Tile();
+
/** Draw a tile on the screen */
void draw(DrawingContext& context, const Vector& pos, int layer) const;
+ Surface* get_editor_image() const;
+
+ unsigned int getID() const
+ { return id; }
+
+ Uint32 getAttributes() const
+ { return attributes; }
+
+ int getData() const
+ { return data; }
+
/// returns the width of the tile in pixels
int getWidth() const
{
return 0;
return images[0]->h;
}
+
+protected:
+ friend class TileManager;
+ Tile();
+
+ void load_images();
+
+ /// parses the tile and returns it's id number
+ void parse(LispReader& reader);
+ void parse_images(lisp_object_t* cur);
};
#endif
-
-/* EOF */
void TileManager::load_tileset(std::string filename)
{
- if(filename == current_tileset)
- return;
-
// free old tiles
for(Tiles::iterator i = tiles.begin(); i != tiles.end(); ++i)
delete *i;
LispReader reader(lisp_cdr(element));
Tile* tile = new Tile;
- tile->read(reader);
+ tile->parse(reader);
while(tile->id >= tiles.size()) {
tiles.push_back(0);
}
lisp_free(root_obj);
- current_tileset = filename;
}
#include <map>
#include <stdint.h>
#include <assert.h>
-
-class Tile;
+#include "tile.h"
struct TileGroup
{
class TileManager
{
- private:
+private:
TileManager();
~TileManager();
std::set<TileGroup> tilegroups;
void load_tileset(std::string filename);
- std::string current_tileset;
-
- public:
+public:
static TileManager* instance()
{ return instance_ ? instance_ : instance_ = new TileManager(); }
static void destroy_instance()
const Tile* get(uint32_t id) const
{
assert(id < tiles.size());
- Tile* t = tiles[id];
- if (t)
- {
- return t;
- }
- else
- {
- std::cout << "TileManager: Invalid tile: " << id << std::endl;
- return tiles[0];
- }
+ Tile* tile = tiles[id];
+ if(!tile) {
+ std::cout << "TileManager: Invalid tile: " << id << std::endl;
+ return tiles[0];
+ }
+
+ if(tile->images.size() == 0 && tile->imagespecs.size() != 0)
+ tile->load_images();
+
+ return tile;
}
uint32_t get_max_tileid() const
// TODO
}
-SequenceTrigger::SequenceTrigger(const Vector& pos,
- const std::string& sequence)
+SequenceTrigger::SequenceTrigger(const Vector& pos, const std::string& sequence)
{
bbox.set_pos(pos);
bbox.set_size(32, 32);
+ offset.y)), 500);
GameSession session(
get_resource_filename(std::string("levels/" + level->name)),
- ST_GL_LOAD_LEVEL_FILE, level->vertical_flip,
- &level->statistics);
+ ST_GL_LOAD_LEVEL_FILE, &level->statistics);
switch (session.run())
{