Programming
~~~~~~~~~~~
--Collision Detection Rewrite (all [H])--
- * enemies:
- - implement fish
- - implement wingling
- - implement stalactite
- - implement tree (really?)
- - bring back stay on platform flag
** implement ability to cary mriceblock (and other objects) around
* smoke clouds are too fast
* rethink slopes collision feedback... tux becomes too slow when walking up
themselfes. This could speed up rendering of tilemaps.
[M] Make the gamelogic run in a fixed logical framerate
+--BadGuys--
+[H] Bring back stay on platform flag
+[H] Reimplement fish
+[H] Reimplement stalactite
+[H] Do something with the wingling
+[?] Do something with the tree?
+
--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.
- After enemy-kill is used, powerup should be removed from Tux
[H] Icebullet related things
- we should decide on specifics
-[H] Graphics
- - New forest tileset
- - Badguy sprites
- - Tux's buttjump animation
[M] Save score on per-level basis to make high-score
[M] Save time on per-level basis to make low-time-score
[M] Add bonus score for extra time left when finishing a level
[H] Create a graphics to visually present reset points. (Maybe a bell that
starts swinging once tux touched it?)
[M] Add graphics for ropes
+[H] Animation for the buttjump
[L] Create graphics for bubbles and soap (not necessary for milestone2)
-new enemies need to be designed and added
(y-offset 0)
(images "shared/stalactite.png"))
(action
- (name "broken")
+ (name "squished")
(x-offset 0)
(y-offset 16)
(images "shared/stalactite-broken.png")))
; Door
(sprite (name "door")
(action
- (name "default")
+ (name "normal")
(x-offset 0)
(y-offset 0)
(images "shared/door-1.png"))
; coin
(sprite (name "coin")
(action
- (name "default")
+ (name "normal")
(images "tilesets/coin-1.png"
"tilesets/coin-2.png"
"tilesets/coin-3.png"
(sprite (name "bonusblock")
(action
(fps 15)
- (name "default")
+ (name "normal")
(images "tilesets/bonus2-1.png"
"tilesets/bonus2-2.png"
"tilesets/bonus2-3.png"
(name "empty")
(images "tilesets/bonus2-d.png"))
(action
- (name "default")
+ (name "normal")
(images "tilesets/brick0.png"))
)
(name "empty")
(images "tilesets/bonus2-d.png"))
(action
- (name "default")
+ (name "normal")
(images "tilesets/brick1.png"))
)
(sprite (name "rock")
(action
- (name "default")
+ (name "normal")
(images "tilesets/block11.png"))
)
(sprite (name "bell")
(action
- (name "default")
+ (name "normal")
(x-offset 0)
(y-offset 0)
(images "shared/bell/bell-m.png")
(images "shared/unstable_tile.png"))
)
-; Hatch
+ (sprite (name "worldmaptux")
+ (action
+ (name "small")
+ (y-offset 10)
+ (images "worldmap/smalltux.png")
+ )
+ (action
+ (name "large")
+ (y-offset 10)
+ (images "worldmap/tux.png")
+ )
+ (action
+ (name "fire")
+ (y-offset 10)
+ (images "worldmap/firetux.png")
+ )
+ )
+
(sprite (name "hatch")
(action
(name "default")
"shared/hatch-6.png"))
)
)
-;; EOF ;;
(supertux-level
(version 1)
(author "Marek Moeckel")
- (name "Inside The Tree")
+ (name (_ "Inside The Tree"))
(width 30)
(height 300)
(start_pos_x 100)
Sprite::Sprite(SpriteData& newdata)
: data(newdata), frame(0), animation_loops(-1)
{
- action = data.actions.begin()->second;
+ action = data.get_action("normal");
+ if(!action)
+ action = data.actions.begin()->second;
last_ticks = SDL_GetTicks();
}
lisp->get("z-order", action->z_order);
lisp->get("fps", action->fps);
- // this doesn't seem to be used and implemented
-#if 0
- std::vector <int> mask_color;
- lispreader.read_int_vector("apply-mask", mask_color);
- if(mask_color.size() == 4) {
- for(std::vector<Surface*>::iterator i = action->surfaces.begin();
- i < action->surfaces.end(); i++) {
- (*i)->apply_filter(MASK_FILTER, Color(mask_color));
- }
- }
-#endif
-
std::string mirror_action;
lisp->get("mirror-action", mirror_action);
if(!mirror_action.empty()) {
{
Actions::iterator i = actions.find(act);
if(i == actions.end()) {
- std::cerr << "Warning: Action '" << act <<
- "' not found on Sprite '" << name << "'\n";
return 0;
}
return i->second;
void
DrawingContext::do_drawing()
{
+#ifdef DEBUG
+ assert(transformstack.empty());
+#endif
+ transformstack.clear();
+
std::stable_sort(drawingrequests.begin(), drawingrequests.end());
for(DrawingRequests::iterator i = drawingrequests.begin();
--- /dev/null
+#include <config.h>
+
+#include "stalactite.h"
+
+static const int SHAKE_RANGE = 40;
+static const float SHAKE_TIME = .8;
+static const float SQUISH_TIME = 2;
+
+Stalactite::Stalactite(const lisp::Lisp& lisp)
+{
+ lisp.get("x", start_position.x);
+ lisp.get("y", start_position.y);
+ bbox.set_size(31.8, 31.8);
+ sprite = sprite_manager->create("stalactite");
+ state = STALACTITE_HANGING;
+}
+
+void
+Stalactite::write(lisp::Writer& writer)
+{
+ writer.start_list("stalactite");
+ writer.write_float("x", start_position.x);
+ writer.write_float("y", start_position.y);
+ writer.end_list("stalactite");
+}
+
+void
+Stalactite::active_action(float elapsed_time)
+{
+ if(state == STALACTITE_HANGING) {
+ Player* player = Sector::current()->player;
+ if(player->get_bbox().p2.x > bbox.p1.x - SHAKE_RANGE
+ && player->get_bbox().p1.x < bbox.p2.x + SHAKE_RANGE
+ && player->get_bbox().p2.y > bbox.p1.y) {
+ timer.start(SHAKE_TIME);
+ state = STALACTITE_SHAKING;
+ }
+ } else if(state == STALACTITE_SHAKING) {
+ if(timer.check()) {
+ state = STALACTITE_FALLING;
+ physic.enable_gravity(true);
+ }
+ } else if(state == STALACTITE_FALLING || state == STALACTITE_SQUISHED) {
+ movement = physic.get_movement(elapsed_time);
+ if(state == STALACTITE_SQUISHED && timer.check())
+ remove_me();
+ }
+}
+
+HitResponse
+Stalactite::collision_solid(GameObject& , const CollisionHit& hit)
+{
+ if(state != STALACTITE_FALLING && state != STALACTITE_SQUISHED)
+ return FORCE_MOVE;
+
+ if(fabsf(hit.normal.y) > .5) { // hit floor or roof?
+ state = STALACTITE_SQUISHED;
+ physic.set_velocity_y(0);
+ sprite->set_action("squished");
+ if(!timer.started())
+ timer.start(SQUISH_TIME);
+ }
+
+ return CONTINUE;
+}
+
+HitResponse
+Stalactite::collision_player(Player& player, const CollisionHit& )
+{
+ if(state != STALACTITE_SQUISHED) {
+ player.kill(Player::SHRINK);
+ }
+
+ return FORCE_MOVE;
+}
+
+void
+Stalactite::kill_fall()
+{
+}
+
+void
+Stalactite::draw(DrawingContext& context)
+{
+ if(state == STALACTITE_SHAKING) {
+ sprite->draw(context, get_pos() + Vector((rand() % 6)-3, 0), LAYER_OBJECTS);
+ } else {
+ sprite->draw(context, get_pos(), LAYER_OBJECTS);
+ }
+}
+
+void
+Stalactite::deactivate()
+{
+ if(state != STALACTITE_HANGING)
+ remove_me();
+}
+
+IMPLEMENT_FACTORY(Stalactite, "stalactite")
--- /dev/null
+#ifndef __STALACTITE_H__
+#define __STALACTITE_H__
+
+#include "badguy.h"
+
+class Stalactite : public BadGuy
+{
+public:
+ Stalactite(const lisp::Lisp& reader);
+
+ void active_action(float elapsed_time);
+ void write(lisp::Writer& writer);
+ HitResponse collision_solid(GameObject& other, const CollisionHit& hit);
+ HitResponse collision_player(Player& player, const CollisionHit& hit);
+
+ void kill_fall();
+ void draw(DrawingContext& context);
+ void deactivate();
+
+private:
+ Physic physic;
+ Timer2 timer;
+
+ enum StalactiteState {
+ STALACTITE_HANGING,
+ STALACTITE_SHAKING,
+ STALACTITE_FALLING,
+ STALACTITE_SQUISHED
+ };
+ StalactiteState state;
+};
+
+#endif
+
// Cheating words (the goal of this is really for debugging,
// but could be used for some cheating, nothing wrong with that)
if(compare_last(last_keys, "grow")) {
- tux.grow(false);
+ tux.set_bonus(GROWUP_BONUS, false);
last_keys.clear();
}
if(compare_last(last_keys, "fire")) {
- tux.grow(false);
- tux.got_power = tux.FIRE_POWER;
+ tux.set_bonus(FIRE_BONUS, false);
last_keys.clear();
}
if(compare_last(last_keys, "ice")) {
- tux.grow(false);
- tux.got_power = tux.ICE_POWER;
+ tux.set_bonus(ICE_BONUS, false);
last_keys.clear();
}
if(compare_last(last_keys, "lifeup")) {
exit_status = ES_LEVEL_FINISHED;
return;
} else if (!end_sequence && tux->is_dead()) {
- player_status.bonus = PlayerStatus::NO_BONUS;
-
if (player_status.lives < 0) { // No more lives!?
exit_status = ES_GAME_OVER;
} else { // Still has lives, so reset Tux to the levelstart
// respawning in new sector?
if(newsector != "" && newspawnpoint != "") {
Sector* sector = level->get_sector(newsector);
+ if(sector == 0) {
+ std::cerr << "Sector '" << newsector << "' not found.\n";
+ }
+ sector->activate(newspawnpoint);
+ sector->play_music(LEVEL_MUSIC);
currentsector = sector;
- currentsector->activate(newspawnpoint);
- currentsector->play_music(LEVEL_MUSIC);
- newsector = newspawnpoint = "";
+ newsector = "";
+ newspawnpoint = "";
}
}
: Block(sprite_manager->create("bonusblock"))
{
bbox.set_pos(pos);
- sprite->set_action("default");
+ sprite->set_action("normal");
switch(data) {
case 1: contents = CONTENT_COIN; break;
case 2: contents = CONTENT_FIREGROW; break;
switch(contents) {
case CONTENT_COIN:
Sector::current()->add_object(new BouncyCoin(get_pos()));
- player.get_status().incCoins();
+ player.get_status()->incCoins();
break;
case CONTENT_FIREGROW:
- if(player.size == SMALL) {
+ if(player.get_status()->bonus == NO_BONUS) {
SpecialRiser* riser = new SpecialRiser(
new GrowUp(get_pos() + Vector(0, -32)));
sector->add_object(riser);
break;
case CONTENT_ICEGROW:
- if(player.size == SMALL) {
+ if(player.get_status()->bonus == NO_BONUS) {
SpecialRiser* riser = new SpecialRiser(
new GrowUp(get_pos() + Vector(0, -32)));
sector->add_object(riser);
if(coin_counter > 0) {
sector->add_object(new BouncyCoin(get_pos()));
coin_counter--;
- player.get_status().incCoins();
+ player.get_status()->incCoins();
if(coin_counter == 0)
sprite->set_action("empty");
start_bounce();
} else if(breakable) {
- if(playerhit && player.size == SMALL) {
+ if(playerhit && !player.is_big()) {
start_bounce();
return;
}
void
Coin::collect()
{
- Sector::current()->player->get_status().incCoins();
+ Sector::current()->player->get_status()->incCoins();
Sector::current()->add_object(new BouncyCoin(get_pos()));
global_stats.add_points(COINS_COLLECTED_STAT, 1);
remove_me();
return ABORT_MOVE;
if(type == FIREFLOWER)
- player->got_power = Player::FIRE_POWER;
+ player->set_bonus(FIRE_BONUS, true);
else
- player->got_power = Player::ICE_POWER;
+ player->set_bonus(ICE_BONUS, true);
+
SoundManager::get()->play_sound(IDToSound(SND_COFFEE));
remove_me();
return ABORT_MOVE;
Player* player = dynamic_cast<Player*>(&other);
if(player != 0) {
- player->grow();
+ player->set_bonus(GROWUP_BONUS, true);
SoundManager::get()->play_sound(IDToSound(SND_EXCELLENT));
remove_me();
{
Player* player = dynamic_cast<Player*> (&other);
if(player) {
- player->get_status().incLives();
+ player->get_status()->incLives();
remove_me();
return ABORT_MOVE;
}
#include "special/sprite_manager.h"
#include "player.h"
#include "tile.h"
-#include "player_status.h"
#include "special/sprite.h"
#include "sector.h"
#include "resources.h"
feet->draw(context, pos, layer-2, drawing_effect);
}
-Player::Player()
- : grabbed_object(0)
+Player::Player(PlayerStatus* _player_status)
+ : player_status(_player_status), grabbed_object(0)
{
smalltux_gameover = sprite_manager->create("smalltux-gameover");
smalltux_star = sprite_manager->create("smalltux-star");
void
Player::init()
{
- bbox.set_size(31.8, 31.8);
-
- size = SMALL;
- got_power = NONE_POWER;
+ if(is_big())
+ bbox.set_size(31.8, 63.8);
+ else
+ bbox.set_size(31.8, 31.8);
dir = RIGHT;
old_dir = dir;
flapping_velocity = 0;
// temporary to help player's choosing a flapping
- flapping_mode = MAREK_FLAP;
+ flapping_mode = NO_FLAP;
// Ricardo's flapping
flaps_nb = 0;
}
void
-Player::level_begin()
-{
- move(Vector(100, 170));
- duck = false;
-
- dying = false;
-
- input.reset();
-
- on_ground_flag = false;
-
- physic.reset();
-}
-
-PlayerStatus&
-Player::get_status()
-{
- return player_status;
-}
-
-void
Player::action(float elapsed_time)
{
if(dying && dying_timer.check()) {
return on_ground_flag;
}
+bool
+Player::is_big()
+{
+ if(player_status->bonus == NO_BONUS)
+ return false;
+
+ return true;
+}
+
void
Player::handle_horizontal_input()
{
can_jump = false;
can_flap = false;
flaps_nb = 0; // Ricardo's flapping
- if (size == SMALL)
- SoundManager::get()->play_sound(IDToSound(SND_JUMP));
- else
+ if (is_big())
SoundManager::get()->play_sound(IDToSound(SND_BIGJUMP));
+ else
+ SoundManager::get()->play_sound(IDToSound(SND_JUMP));
}
// Let go of jump key
else if(!input.jump)
butt_jump = false;
// Do butt jump
- if (butt_jump && on_ground() && size == BIG)
+ if (butt_jump && on_ground() && is_big())
{
// Add a smoke cloud
if (duck)
handle_vertical_input();
/* Shoot! */
- if (input.fire && !input.old_fire && got_power != NONE_POWER) {
+ if (input.fire && !input.old_fire && player_status->bonus == FIRE_BONUS) {
if(Sector::current()->add_bullet(
// get_pos() + Vector(0, bbox.get_height()/2),
get_pos() + ((dir == LEFT)? Vector(0, bbox.get_height()/2)
}
/* Duck! */
- if (input.down && size == BIG && !duck
+ if (input.down && is_big() && !duck
&& physic.get_velocity_y() == 0 && on_ground())
{
duck = true;
bbox.move(Vector(0, 32));
bbox.set_height(31.8);
}
- else if(!input.down && size == BIG && duck)
+ else if(!input.down && is_big() && duck)
{
// try if we can really unduck
bbox.move(Vector(0, -32));
}
void
-Player::grow(bool animate)
+Player::set_bonus(BonusType type, bool animate)
{
- if(size == BIG)
+ if(player_status->bonus == type)
return;
- size = BIG;
- bbox.set_height(63.8);
- bbox.move(Vector(0, -32));
-
- if(animate)
- growing_timer.start(GROWING_TIME);
+ if(player_status->bonus == NO_BONUS) {
+ bbox.set_height(63.8);
+ bbox.move(Vector(0, -32));
+ if(animate)
+ growing_timer.start(GROWING_TIME);
+ }
+
+ player_status->bonus = type;
}
void
{
TuxBodyParts* tux_body;
- if (size == SMALL)
- tux_body = small_tux;
- else if (got_power == FIRE_POWER)
+ if (player_status->bonus == GROWUP_BONUS)
+ tux_body = big_tux;
+ else if (player_status->bonus == FIRE_BONUS)
tux_body = fire_tux;
- else if (got_power == ICE_POWER)
+ else if (player_status->bonus == ICE_BONUS)
tux_body = ice_tux;
else
- tux_body = big_tux;
+ tux_body = small_tux;
int layer = LAYER_OBJECTS + 10;
/* Set Tux sprite action */
- if (duck && size == BIG)
+ if (duck && is_big())
{
if(dir == LEFT)
tux_body->set_action("duck-left");
else // dir == RIGHT
tux_body->set_action("kick-right");
}
- else if (butt_jump && size == BIG)
+ else if (butt_jump && is_big())
{
if(dir == LEFT)
tux_body->set_action("buttjump-left");
if(idle_timer.check())
{
- if(size == BIG)
+ if(is_big())
{
if(dir == LEFT)
tux_body->head->set_action("idle-left", 1);
if(dying) {
smalltux_gameover->draw(context, get_pos(), layer);
} else if(growing_timer.get_timeleft() > 0) {
- if(size == SMALL)
+ if(!is_big())
{
if (dir == RIGHT)
context.draw_surface(growingtux_right[GROWING_FRAMES-1 -
|| size_t(global_time*20)%2)
&& !dying)
{
- if (size == SMALL || duck)
+ if (!is_big() || duck)
smalltux_star->draw(context, get_pos(), layer + 5);
else
bigtux_star->draw(context, get_pos(), layer + 5);
physic.set_velocity_x(0);
- if (mode == SHRINK && size == BIG)
+ if (mode == SHRINK && is_big())
{
- if (got_power != NONE_POWER)
+ if (player_status->bonus == FIRE_BONUS
+ || player_status->bonus == ICE_BONUS)
{
safe_timer.start(TUX_SAFE_TIME);
- got_power = NONE_POWER;
+ player_status->bonus = GROWUP_BONUS;
}
- else
+ else
{
growing_timer.start(GROWING_TIME);
safe_timer.start(TUX_SAFE_TIME + GROWING_TIME);
- size = SMALL;
bbox.set_height(31.8);
duck = false;
+ player_status->bonus = NO_BONUS;
}
}
else
physic.enable_gravity(true);
physic.set_acceleration(0, 0);
physic.set_velocity(0, 700);
- --player_status.lives;
+ player_status->lives -= 1;
dying = true;
dying_timer.start(3.0);
flags |= FLAG_NO_COLLDET;
}
}
-/* Remove Tux's power ups */
-void
-Player::remove_powerups()
-{
- got_power = NONE_POWER;
- size = SMALL;
- bbox.set_height(31.8);
-}
-
void
Player::move(const Vector& vector)
{
bbox.set_pos(vector);
+ if(is_big())
+ bbox.set_size(31.8, 63.8);
+ else
+ bbox.set_size(31.8, 31.8);
+ on_ground_flag = false;
+ duck = false;
+
+ input.reset();
+ physic.reset();
}
void
#include "special/moving_object.h"
#include "special/sprite.h"
#include "math/physic.h"
+#include "player_status.h"
using namespace SuperTux;
#define TUX_FLAPPING_TIME 1 /* How long Tux can flap his wings to gain additional jump height */
#define TIME_WARNING 20 /* When to alert player they're low on time! */
-/* Sizes: */
-#define SMALL 0
-#define BIG 1
-
struct PlayerKeymap
{
public:
{
public:
enum HurtMode { KILL, SHRINK };
- enum Power { NONE_POWER, FIRE_POWER, ICE_POWER };
enum FallMode { ON_GROUND, JUMPING, TRAMPOLINE_JUMP, FALLING };
PlayerInputType input;
- int got_power;
- int size;
+ PlayerStatus* player_status;
bool duck;
bool dead;
int flaps_nb;
// temporary to help player's choosing a flapping
- enum { MAREK_FLAP, RICARDO_FLAP, RYAN_FLAP, NONE_FLAP };
+ enum { MAREK_FLAP, RICARDO_FLAP, RYAN_FLAP, NO_FLAP };
int flapping_mode;
Timer2 invincible_timer;
Physic physic;
public:
- Player();
+ Player(PlayerStatus* player_status);
virtual ~Player();
bool key_event(SDLKey key, bool state);
- void level_begin();
void handle_input();
- PlayerStatus& get_status();
-
virtual void action(float elapsed_time);
virtual void draw(DrawingContext& context);
virtual HitResponse collision(GameObject& other, const CollisionHit& hit);
void kill(HurtMode mode);
void player_remove_powerups();
void check_bounds(Camera* camera);
- void grow(bool animate = false);
void move(const Vector& vector);
+ void set_bonus(BonusType type, bool animate = false);
+ PlayerStatus* get_status()
+ {
+ return player_status;
+ }
void bounce(BadGuy& badguy);
bool is_dead() const
{ return dead; }
+ bool is_big();
private:
bool on_ground();
void handle_horizontal_input();
void handle_vertical_input();
- void remove_powerups();
Portable* grabbed_object;
PlayerStatus::write(lisp::Writer& writer)
{
switch(bonus) {
- case PlayerStatus::NO_BONUS:
+ case NO_BONUS:
writer.write_string("bonus", "none");
break;
- case PlayerStatus::GROWUP_BONUS:
+ case GROWUP_BONUS:
writer.write_string("bonus", "growup");
break;
- case PlayerStatus::FLOWER_BONUS:
+ case FIRE_BONUS:
writer.write_string("bonus", "fireflower");
break;
+ case ICE_BONUS:
+ writer.write_string("bonus", "iceflower");
+ break;
default:
std::cerr << "Unknown bonus type.\n";
writer.write_string("bonus", "none");
} else if(bonusname == "growup") {
bonus = GROWUP_BONUS;
} else if(bonusname == "fireflower") {
- bonus = FLOWER_BONUS;
+ bonus = FIRE_BONUS;
+ } else if(bonusname == "iceflower") {
+ bonus = ICE_BONUS;
} else {
std::cerr << "Unknown bonus '" << bonusname << "' in savefile.\n";
bonus = NO_BONUS;
#include "timer.h"
#include "serializable.h"
+enum BonusType {
+ NO_BONUS, GROWUP_BONUS, FIRE_BONUS, ICE_BONUS
+};
+
/**
* This class memorizes player status between different game sessions (for
* example when switching maps in the worldmap)
int distros;
int lives;
- enum BonusType { NO_BONUS, GROWUP_BONUS, FLOWER_BONUS };
BonusType bonus;
- int score_multiplier;
+ int score_multiplier;
int max_score_multiplier;
};
#include "badguy/jumpy.h"
#include "badguy/spike.h"
#include "trigger/sequence_trigger.h"
+#include "player_status.h"
//#define USE_GRID
currentmusic(LEVEL_MUSIC)
{
song_title = "Mortimers_chipdisko.mod";
- player = new Player();
+ player = new Player(&player_status);
add_object(player);
grid = new CollisionGrid(32000, 32000);
update_game_objects();
fix_old_tiles();
- update_game_objects();
if(!camera) {
std::cerr << "sector '" << name << "' does not contain a camera.\n";
- camera = new Camera(this);
- add_object(camera);
+ update_game_objects();
+ add_object(new Camera(this));
}
if(!solids)
throw std::runtime_error("sector does not contain a solid tile layer.");
+
+ update_game_objects();
}
void
{
_current = this;
- // Apply bonuses from former levels
- switch (player_status.bonus) {
- case PlayerStatus::NO_BONUS:
- break;
-
- case PlayerStatus::FLOWER_BONUS:
- player->got_power = Player::FIRE_POWER; // FIXME: add ice power to here
- // fall through
-
- case PlayerStatus::GROWUP_BONUS:
- player->grow(false);
- break;
-
- default:
- std::cerr << "Unknown bonus in PlayerStatus?!?\n";
- break;
- }
-
player->move(player_pos);
camera->reset(player->get_pos());
}
// TODO remove this function and move these checks elsewhere...
static const size_t MAX_FIRE_BULLETS = 2;
static const size_t MAX_ICE_BULLETS = 1;
-
- if(player->got_power == Player::FIRE_POWER) {
+
+ Bullet* new_bullet = 0;
+ if(player_status.bonus == FIRE_BONUS) {
if(bullets.size() > MAX_FIRE_BULLETS-1)
return false;
- } else if(player->got_power == Player::ICE_POWER) {
+ new_bullet = new Bullet(pos, xm, dir, FIRE_BULLET);
+ } else if(player_status.bonus == ICE_BONUS) {
if(bullets.size() > MAX_ICE_BULLETS-1)
return false;
- }
-
- Bullet* new_bullet = 0;
- if(player->got_power == Player::FIRE_POWER)
- new_bullet = new Bullet(pos, xm, dir, FIRE_BULLET);
- else if(player->got_power == Player::ICE_POWER)
new_bullet = new Bullet(pos, xm, dir, ICE_BULLET);
- else
- throw std::runtime_error("wrong bullet type.");
+ } else {
+ return false;
+ }
add_object(new_bullet);
SoundManager::get()->play_sound(IDToSound(SND_SHOOT));
*/
void resume_demo()
{
- // FIXME: shouldn't be needed if GameSession
- // didn't relay on global variables
+ player_status.reset();
titlesession->get_current_sector()->activate("main");
titlesession->set_current();
// Wrap around at the end of the level back to the beginnig
if(world->solids->get_width() * 32 - 320 < tux->get_pos().x)
{
- tux->level_begin();
+ world->activate("main");
world->camera->reset(tux->get_pos());
}
{
//Check if door animation is complete
if(sprite->check_animation()) {
+ sprite->set_action("normal");
GameSession::current()->respawn(target_sector, target_spawnpoint);
}
}
#include "video/screen.h"
#include "video/drawing_context.h"
#include "special/frame_rate.h"
+#include "special/sprite_manager.h"
#include "audio/sound_manager.h"
#include "lisp/parser.h"
#include "lisp/lisp.h"
Tux::Tux(WorldMap* worldmap_)
: worldmap(worldmap_)
{
- largetux_sprite = new Surface(datadir + "/images/worldmap/tux.png", true);
- firetux_sprite = new Surface(datadir + "/images/worldmap/firetux.png", true);
- smalltux_sprite = new Surface(datadir + "/images/worldmap/smalltux.png", true);
-
+ tux_sprite = sprite_manager->create("worldmaptux");
+
offset = 0;
moving = false;
tile_pos.x = worldmap->get_start_x();
Tux::~Tux()
{
- delete smalltux_sprite;
- delete firetux_sprite;
- delete largetux_sprite;
+ delete tux_sprite;
}
void
-Tux::draw(DrawingContext& context, const Vector& offset)
+Tux::draw(DrawingContext& context)
{
- Vector pos = get_pos();
- switch (player_status.bonus)
- {
- case PlayerStatus::GROWUP_BONUS:
- context.draw_surface(largetux_sprite,
- Vector(pos.x + offset.x, pos.y + offset.y - 10), LAYER_OBJECTS);
+ switch (player_status.bonus) {
+ case GROWUP_BONUS:
+ tux_sprite->set_action("large");
break;
- case PlayerStatus::FLOWER_BONUS:
- context.draw_surface(firetux_sprite,
- Vector(pos.x + offset.x, pos.y + offset.y - 10), LAYER_OBJECTS);
+ case FIRE_BONUS:
+ tux_sprite->set_action("fire");
break;
- case PlayerStatus::NO_BONUS:
- context.draw_surface(smalltux_sprite,
- Vector(pos.x + offset.x, pos.y + offset.y - 10), LAYER_OBJECTS);
+ case NO_BONUS:
+ tux_sprite->set_action("small");
break;
- }
+ default:
+#ifdef DBEUG
+ std::cerr << "Bonus type not handled in worldmap.\n";
+#endif
+ tux_sprite->set_action("large");
+ break;
+ }
+
+ tux_sprite->draw(context, get_pos(), LAYER_OBJECTS);
}
level->statistics.merge(global_stats);
calculate_total_stats();
- if (session.get_current_sector()->player->got_power !=
- session.get_current_sector()->player->NONE_POWER)
- player_status.bonus = PlayerStatus::FLOWER_BONUS;
- else if (session.get_current_sector()->player->size == BIG)
- player_status.bonus = PlayerStatus::GROWUP_BONUS;
- else
- player_status.bonus = PlayerStatus::NO_BONUS;
-
if (old_level_state != level->solved && level->auto_path)
{ // Try to detect the next direction to which we should walk
// FIXME: Mostly a hack
status. But the minimum lives and no bonus. */
player_status.distros = old_player_status.distros;
player_status.lives = std::min(old_player_status.lives, player_status.lives);
- player_status.bonus = player_status.NO_BONUS;
+ player_status.bonus = NO_BONUS;
break;
case GameSession::ES_GAME_OVER:
return 0;
}
-
void
-WorldMap::draw(DrawingContext& context, const Vector& offset)
+WorldMap::draw(DrawingContext& context)
{
for(int y = 0; y < height; ++y)
for(int x = 0; x < width; ++x)
{
const Tile* tile = at(Vector(x, y));
- tile->draw(context, Vector(x*32 + offset.x, y*32 + offset.y),
- LAYER_TILES);
+ tile->draw(context, Vector(x*32, y*32), LAYER_TILES);
}
for(Levels::iterator i = levels.begin(); i != levels.end(); ++i)
{
if (i->solved)
context.draw_surface(leveldot_green,
- Vector(i->pos.x*32 + offset.x, i->pos.y*32 + offset.y), LAYER_TILES+1);
+ Vector(i->pos.x*32, i->pos.y*32), LAYER_TILES+1);
else
context.draw_surface(leveldot_red,
- Vector(i->pos.x*32 + offset.x, i->pos.y*32 + offset.y), LAYER_TILES+1);
+ Vector(i->pos.x*32, i->pos.y*32), LAYER_TILES+1);
}
for(SpecialTiles::iterator i = special_tiles.begin(); i != special_tiles.end(); ++i)
if (i->teleport_dest != Vector(-1, -1))
context.draw_surface(teleporterdot,
- Vector(i->pos.x*32 + offset.x, i->pos.y*32 + offset.y), LAYER_TILES+1);
+ Vector(i->pos.x*32, i->pos.y*32), LAYER_TILES+1);
else if (!i->map_message.empty() && !i->passive_message)
context.draw_surface(messagedot,
- Vector(i->pos.x*32 + offset.x, i->pos.y*32 + offset.y), LAYER_TILES+1);
+ Vector(i->pos.x*32, i->pos.y*32), LAYER_TILES+1);
}
- tux->draw(context, offset);
+ tux->draw(context);
draw_status(context);
}
void
WorldMap::draw_status(DrawingContext& context)
{
+ context.push_transform();
+ context.set_translation(Vector(0, 0));
+
char str[80];
sprintf(str, " %d", total_stats.get_points(SCORE_STAT));
context.draw_text(gold_text, passive_message,
Vector(screen->w/2, screen->h - white_text->get_height() - 60),
CENTER_ALLIGN, LAYER_FOREGROUND1);
+
+ context.pop_transform();
}
void
if (offset.x < screen->w - width*32) offset.x = screen->w - width*32;
if (offset.y < screen->h - height*32) offset.y = screen->h - height*32;
-
- draw(context, offset);
+
+ context.push_transform();
+ context.set_translation(offset);
+ draw(context);
+ context.pop_transform();
get_input();
update(elapsed_time);
namespace SuperTux {
class Menu;
+ class Sprite;
}
extern Menu* worldmap_menu;
Direction back_direction;
private:
WorldMap* worldmap;
- Surface* largetux_sprite;
- Surface* firetux_sprite;
- Surface* smalltux_sprite;
+ Sprite* tux_sprite;
Direction input_direction;
Direction direction;
Tux(WorldMap* worldmap_);
~Tux();
- void draw(DrawingContext& context, const Vector& offset);
+ void draw(DrawingContext& context);
void action(float elapsed_time);
void set_direction(Direction dir);
void update(float delta);
/** Draw one frame */
- void draw(DrawingContext& context, const Vector& offset);
+ void draw(DrawingContext& context);
Vector get_next_tile(Vector pos, Direction direction);
const Tile* at(Vector pos);