FIND_PACKAGE(SDL REQUIRED)
INCLUDE_DIRECTORIES(${SDL_INCLUDE_DIR})
+SET(HAVE_SDL TRUE)
FIND_PACKAGE(SDL_image REQUIRED)
INCLUDE_DIRECTORIES(${SDLIMAGE_INCLUDE_DIR})
OPTION(ENABLE_OPENGL "Enable OpenGL support" ON)
IF(ENABLE_OPENGL)
FIND_PACKAGE(OpenGL)
- IF(${OPENGL_FOUND} STREQUAL "YES")
+ IF(OPENGL_FOUND)
INCLUDE_DIRECTORIES(${OPENGL_INCLUDE_DIR})
SET(HAVE_OPENGL TRUE)
- ENDIF(${OPENGL_FOUND} STREQUAL "YES")
+ ENDIF(OPENGL_FOUND)
ENDIF(ENABLE_OPENGL)
FIND_PACKAGE(OpenAL REQUIRED)
#cmakedefine HAVE_OPENGL
+#cmakedefine HAVE_SDL
+
#cmakedefine HAVE_LIBCURL
#endif /*CONFIG_H*/
(mode "normal")
)
(decal
- (x 528)
- (y 176)
- (image "images/creatures/tux/small/walk-0.png")
+ (solid #t)
+ (sprite "images/creatures/tux/tux.sprite")
+ (action "small-walk-right")
+ (x 536)
+ (y 192)
)
(decal
(y 176)
- (image "images/creatures/tux/small/walk-2.png")
+ (sprite "images/creatures/tux/small/walk-2.png")
)
(decal
(x 128)
(y 352)
- (image "images/creatures/tux/small/jump-0.png")
+ (sprite "images/creatures/tux/small/jump-0.png")
)
(decal
(x 688)
(y 336)
- (image "images/creatures/tux/small/skid-0.png")
+ (sprite "images/creatures/tux/small/skid-0.png")
)
(decal
(x 736)
(y 432)
- (image "images/creatures/nolok/walk-0.png")
+ (sprite "images/creatures/nolok/walk-0.png")
)
(decal
(x 412)
(y 112)
- (image "images/creatures/nolok/walk-1.png")
+ (sprite "images/creatures/nolok/walk-1.png")
)
(decal
(x 304)
(y 432)
- (image "images/creatures/nolok/walk-1.png")
+ (sprite "images/creatures/nolok/walk-1.png")
)
(decal
(x 752)
(y 400)
(layer -50)
- (image "images/objects/particles/smoke-2.png")
+ (sprite "images/objects/particles/smoke-2.png")
)
(decal
(x 752)
(y 400)
- (image "images/objects/particles/smoke-2.png")
+ (sprite "images/objects/particles/smoke-2.png")
)
(decal
(x 800)
(y 112)
- (image "images/creatures/nolok/walk-2.png")
+ (sprite "images/creatures/nolok/walk-2.png")
)
(tilemap
(z-pos -100)
HitResponse
KamikazeSnowball::collision_player(Player& player, const CollisionHit& hit)
{
+ //Hack to tell if we should die
HitResponse response = BadGuy::collision_player(player, hit);
- if(response == FORCE_MOVE){
+ if(response == FORCE_MOVE) {
kill_collision();
- response = ABORT_MOVE;
}
- return response;
+
+ return ABORT_MOVE;
}
IMPLEMENT_FACTORY(KamikazeSnowball, "kamikazesnowball");
HitResponse
MrIceBlock::collision_player(Player& player, const CollisionHit& hit)
{
- if(ice_state == ICESTATE_GRABBED)
- return FORCE_MOVE;
-
if(dir == UP) {
return FORCE_MOVE;
}
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
+#include <SDL.h>
+#undef main
+
#include "supertux/main.hpp"
-int main(int argc, char** argv)
+int SDL_main(int argc, char** argv)
{
return Main().main(argc, argv);
}
}
- return SOLID;
+ return FORCE_MOVE;
}
void
#include "util/reader.hpp"
Decal::Decal(const Reader& reader) :
- pos(),
- imagefile(),
- layer(LAYER_OBJECTS),
- image()
+ MovingSprite(reader, LAYER_OBJECTS, COLGROUP_DISABLED)
{
- float px = 0;
- float py = 0;
- reader.get("x", px);
- reader.get("y", py);
- pos = Vector(px, py);
-
- if(!reader.get("image", imagefile)) throw std::runtime_error("Must specify image for decal");
- image = Surface::create(imagefile);
-
reader.get("layer", layer);
-}
-Decal::~Decal()
-{
+ bool solid = false;
+ reader.get("solid", solid);
+ if(solid)
+ set_group(COLGROUP_STATIC);
+ std::string action;
+ if(reader.get("action", action))
+ set_action(action, -1);
}
-void
-Decal::update(float)
-{
-}
-
-void
-Decal::draw(DrawingContext& context)
+Decal::~Decal()
{
- if(!image.get()) return;
- context.draw_surface(image.get(), pos, layer);
}
IMPLEMENT_FACTORY(Decal, "decal");
#ifndef HEADER_SUPERTUX_OBJECT_DECAL_HPP
#define HEADER_SUPERTUX_OBJECT_DECAL_HPP
-#include "supertux/game_object.hpp"
+#include "object/moving_sprite.hpp"
#include "util/reader_fwd.hpp"
-#include "video/drawing_context.hpp"
-
-class DisplayManager;
/**
- * Non-interactive, decorative image
+ * A decorative image, perhaps part of the terrain
*/
-class Decal : public GameObject
+class Decal : public MovingSprite
{
public:
Decal(const Reader& reader);
virtual ~Decal();
-
- virtual void update(float elapsed_time);
- virtual void draw(DrawingContext& context);
-
-private:
- Vector pos; /**< coordinates of upper-left corner */
- std::string imagefile; /**< name of image to draw */
- int layer; /**< layer to draw on */
-
- std::auto_ptr<Surface> image; /**< image to draw, anchored at pos */
+ virtual HitResponse collision(GameObject& , const CollisionHit& ) {
+ return FORCE_MOVE;
+ }
};
#endif /*SUPERTUX_DECAL_H*/
HitResponse
MagicBlock::collision(GameObject& /*other*/, const CollisionHit& /*hit*/)
{
- return SOLID;
+ return FORCE_MOVE;
}
IMPLEMENT_FACTORY(MagicBlock, "magicblock");
}
MovingSprite::MovingSprite(const Reader& reader, const Vector& pos, int layer, CollisionGroup collision_group) :
- sprite_name(sprite_name),
+ sprite_name(),
sprite(),
layer(layer)
{
Rock::collision(GameObject& other, const CollisionHit& hit)
{
if(grabbed) {
- return PASSTHROUGH;
+ return ABORT_MOVE;
}
if(!on_ground) {
if(hit.bottom && physic.get_velocity_y() > 200) {
{
movement = pos - get_pos();
last_movement = movement;
- set_group(COLGROUP_TOUCHABLE);
+ set_group(COLGROUP_DISABLED);
on_ground = false;
grabbed = true;
}
sprite->set_action("crumbling", 1);
}
}
- return SOLID;
+ return FORCE_MOVE;
}
void
}
std::vector<float> hitbox;
if (lisp.get("hitbox", hitbox)) {
- if (hitbox.size() != 4) throw std::runtime_error("hitbox must specify exactly 4 coordinates");
- action->x_offset = hitbox[0];
- action->y_offset = hitbox[1];
- action->hitbox_w = hitbox[2];
- action->hitbox_h = hitbox[3];
+ switch(hitbox.size()) {
+ case 4:
+ action->hitbox_h = hitbox[3];
+ action->hitbox_w = hitbox[2];
+
+ //fall-through
+ case 2:
+ action->y_offset = hitbox[1];
+ action->x_offset = hitbox[0];
+ break;
+
+ default:
+ throw std::runtime_error("hitbox should specify 2/4 coordinates");
+ }
}
lisp.get("z-order", action->z_order);
lisp.get("fps", action->fps);
if(!mirror_action.empty()) {
Action* act_tmp = get_action(mirror_action);
if(act_tmp == NULL) {
- throw std::runtime_error("Could not mirror action. Action not found\n"
+ throw std::runtime_error("Could not mirror action. Action not found.\n"
"Mirror actions must be defined after the real one!");
} else {
float max_w = 0;
max_h = std::max(max_h, (float) surface->get_height());
action->surfaces.push_back(surface);
}
- if (action->hitbox_w < 1) action->hitbox_w = max_w;
- if (action->hitbox_h < 1) action->hitbox_h = max_h;
+ if (action->hitbox_w < 1) action->hitbox_w = max_w - action->x_offset;
+ if (action->hitbox_h < 1) action->hitbox_h = max_h - action->y_offset;
}
} else { // Load images
std::vector<std::string> images;
max_h = std::max(max_h, (float) surface->get_height());
action->surfaces.push_back(surface);
}
- if (action->hitbox_w < 1) action->hitbox_w = max_w;
- if (action->hitbox_h < 1) action->hitbox_h = max_h;
+ if (action->hitbox_w < 1) action->hitbox_w = max_w - action->x_offset;
+ if (action->hitbox_h < 1) action->hitbox_h = max_h - action->y_offset;
}
actions[action->name] = action;
}
const lisp::Lisp* root;
try {
- root = parser.parse(filename);
+ if(filename.size() >= 7 && filename.compare(filename.size() - 7, 7, ".sprite") == 0) {
+ // Sprite file
+ root = parser.parse(filename);
+ } else {
+ // Load image file directly
+ std::stringstream lisptext;
+ lisptext << "(supertux-sprite (action "
+ << "(name \"default\") "
+ << "(images \"" << FileSystem::basename(filename) << "\")))";
+
+ root = parser.parse(lisptext, "SpriteManager::load");
+ }
} catch(const std::exception& e) {
std::ostringstream msg;
msg << "Parse error when trying to load sprite '" << filename
*/
enum HitResponse
{
- /// don't move the object
+ // Dynamic collision responses
+
+ /// Call collision() but do no collision handling
ABORT_MOVE = 0,
/// move object out of collision and check for collisions again
- /// if this happens to often then the move will just be aborted
+ /// if this happens too often then the move will just be aborted
+ /// (normal physics)
CONTINUE,
- /// do the move ignoring the collision
- FORCE_MOVE,
- /// passes movement to collided object
- PASS_MOVEMENT,
-
- /// the object should not appear solid
- PASSTHROUGH,
- /// the object should appear solid
- SOLID
+ /// Treat object as kinematic, with infinite inertia/mass
+ /// pushing other (CONTINUE) objects out of the way
+ FORCE_MOVE
};
/**
#include <version.h>
#include <SDL_image.h>
+#undef main
#include <physfs.h>
#include <iostream>
#include <binreloc.h>
/** Objects in DISABLED group are not tested for collisions */
COLGROUP_DISABLED = 0,
- /** "default" is moving object. MovingObjects get tested against all
- other objects and against other movingobjects */
+ /** Tested against:
+ - tiles + attributes
+ - static obstacles
+ - touchables
+ - other moving objects
+ and it counts as an obstacle during static collision phase.
+
+ Use for kinematic moving objects like platforms and rocks. */
+ COLGROUP_MOVING_STATIC,
+
+ /** Tested against:
+ - tiles + attributes
+ - static obstacles
+ - touchables
+ - other moving objects
+
+ Use for ordinary objects. */
COLGROUP_MOVING,
- /** a Moving object, that is not tested against other MovingObjects
- (or other MovingOnlyStatic objects), but is tested against all
- other objects. */
+ /** Tested against:
+ - tiles + attributes
+ - static obstacles
+
+ Use for interactive particles and decoration. */
COLGROUP_MOVING_ONLY_STATIC,
- /** TODO write docu :-/ */
- COLGROUP_MOVING_STATIC,
+ /** Tested against:
+ - moving objects
+ and it counts as an obstacle during static collision phase.
- /**
- * Doesn't move and isn't explicitly checked for collisions with
- * other objects (but other objects might check with this) The
- * difference to COLGROUP_TOUCHABLE is that we can do multiple
- * collision response tests in a row which is needed for static object
- * that tux walks on. The results for collisions with STATIC objects
- * are also sorted by time (so that the first hit gets handled first).
- *
- * Use this for static obstacles
- */
+ Use for static obstacles that Tux walks on. */
COLGROUP_STATIC,
- /** Isn't explicitly checked for collisions with other objects. But
- other objects might check with this object. Difference to
- COLGROUP_STATIC is that collisions with this object are only
- tested once and collision response is typically not handled
-
- Use this for touchable things like spikes/areas or collectibles
- like coins */
- COLGROUP_TOUCHABLE,
-
- /** Should be used for tilemaps */
- COLGROUP_TILEMAP
+ /** Tested against:
+ - moving objects
+
+ Use for triggers like spikes/areas or collectibles like coins. */
+ COLGROUP_TOUCHABLE
};
/** Base class for all dynamic/moving game objects. This class
constraints->ground_movement += addl_ground_movement;
if(other != NULL) {
HitResponse response = other->collision(*object, dummy);
- if(response == PASSTHROUGH)
+ if(response == ABORT_MOVE)
return;
if(other->get_movement() != Vector(0, 0)) {
namespace worldmap {
-// from worldmap.cpp
-Direction string_to_direction(const std::string& directory);
-
SpawnPoint::SpawnPoint(const Reader& slisp) :
name(),
pos(),