X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=src%2Fworldmap%2Ftux.cpp;h=365b98537ce94ebb99edb5af4f49bee79dbce51f;hb=b91dbe6bc1d5047a127cdc688dda836c59e8c2d1;hp=f1086af52f31797f42df30ad5a31f5153f75cb0f;hpb=c0fed8bdef7dbc9540b476fd28949ebad7d3c2ba;p=supertux.git diff --git a/src/worldmap/tux.cpp b/src/worldmap/tux.cpp index f1086af52..365b98537 100644 --- a/src/worldmap/tux.cpp +++ b/src/worldmap/tux.cpp @@ -1,13 +1,11 @@ -// $Id: worldmap.cpp 3327 2006-04-13 15:02:40Z ravu_al_hemio $ -// // SuperTux - A Jump'n Run -// Copyright (C) 2004 Ingo Ruhnke +// Copyright (C) 2004 Ingo Ruhnke // Copyright (C) 2006 Christoph Sommer // -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -15,35 +13,42 @@ // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -#include +// along with this program. If not, see . -#include "tux.hpp" +#include "control/input_manager.hpp" +#include "scripting/squirrel_util.hpp" +#include "sprite/sprite.hpp" #include "sprite/sprite_manager.hpp" -#include "video/drawing_context.hpp" -#include "player_status.hpp" -#include "worldmap.hpp" -#include "level.hpp" -#include "special_tile.hpp" -#include "control/joystickkeyboardcontroller.hpp" -#include "main.hpp" - -namespace WorldMapNS +#include "supertux/globals.hpp" +#include "supertux/player_status.hpp" +#include "supertux/savegame.hpp" +#include "supertux/tile.hpp" +#include "worldmap/level.hpp" +#include "worldmap/tux.hpp" + +namespace worldmap { + +static const float TUXSPEED = 200; +static const float map_message_TIME = 2.8f; + +Tux::Tux(WorldMap* worldmap_) : + back_direction(), + worldmap(worldmap_), + sprite(SpriteManager::current()->create("images/worldmap/common/tux.sprite")), + controller(), + input_direction(), + direction(), + tile_pos(), + offset(), + moving(), + ghost_mode() { - -static const float TUXSPEED = 200; -static const float map_message_TIME = 2.8; - -Tux::Tux(WorldMap* worldmap_) - : worldmap(worldmap_) -{ - sprite.reset(sprite_manager->create("images/worldmap/common/tux.sprite")); - offset = 0; moving = false; direction = D_NONE; input_direction = D_NONE; + + ghost_mode = false; } Tux::~Tux() @@ -53,13 +58,22 @@ Tux::~Tux() void Tux::draw(DrawingContext& context) { - switch (player_status->bonus) { + switch (worldmap->get_savegame().get_player_status()->bonus) { case GROWUP_BONUS: sprite->set_action(moving ? "large-walking" : "large-stop"); break; case FIRE_BONUS: sprite->set_action(moving ? "fire-walking" : "fire-stop"); break; + case ICE_BONUS: + sprite->set_action(moving ? "ice-walking" : "ice-stop"); + break; + case AIR_BONUS: + sprite->set_action(moving ? "air-walking" : "air-stop"); + break; + case EARTH_BONUS: + sprite->set_action(moving ? "earth-walking" : "earth-stop"); + break; case NO_BONUS: sprite->set_action(moving ? "small-walking" : "small-stop"); break; @@ -72,7 +86,6 @@ Tux::draw(DrawingContext& context) sprite->draw(context, get_pos(), LAYER_OBJECTS); } - Vector Tux::get_pos() { @@ -80,7 +93,7 @@ Tux::get_pos() float y = tile_pos.y * 32; switch(direction) - { + { case D_WEST: x -= offset - 32; break; @@ -95,8 +108,8 @@ Tux::get_pos() break; case D_NONE: break; - } - + } + return Vector(x, y); } @@ -115,103 +128,134 @@ Tux::set_direction(Direction dir) input_direction = dir; } -void -Tux::tryStartWalking() +void +Tux::set_ghost_mode(bool enabled) +{ + ghost_mode = enabled; +} + +bool +Tux::get_ghost_mode() +{ + return ghost_mode; +} + +void +Tux::tryStartWalking() { if (moving) - return; + return; if (input_direction == D_NONE) return; - Level* level = worldmap->at_level(); + LevelTile* level = worldmap->at_level(); // We got a new direction, so lets start walking when possible Vector next_tile; - if ((!level || level->solved) && worldmap->path_ok(input_direction, tile_pos, &next_tile)) - { + if ((!level || level->solved || level->perfect) + && worldmap->path_ok(input_direction, tile_pos, &next_tile)) { tile_pos = next_tile; moving = true; direction = input_direction; back_direction = reverse_dir(direction); - } - else if (input_direction == back_direction) - { + } else if (ghost_mode || (input_direction == back_direction)) { moving = true; direction = input_direction; tile_pos = worldmap->get_next_tile(tile_pos, direction); back_direction = reverse_dir(direction); } - } -bool -Tux::canWalk(const Tile* tile, Direction dir) +bool +Tux::canWalk(int tile_data, Direction dir) { - return ((tile->getData() & Tile::WORLDMAP_NORTH && dir == D_NORTH) || - (tile->getData() & Tile::WORLDMAP_SOUTH && dir == D_SOUTH) || - (tile->getData() & Tile::WORLDMAP_EAST && dir == D_EAST) || - (tile->getData() & Tile::WORLDMAP_WEST && dir == D_WEST)); + return ghost_mode || + ((tile_data & Tile::WORLDMAP_NORTH && dir == D_NORTH) || + (tile_data & Tile::WORLDMAP_SOUTH && dir == D_SOUTH) || + (tile_data & Tile::WORLDMAP_EAST && dir == D_EAST) || + (tile_data & Tile::WORLDMAP_WEST && dir == D_WEST)); } -void +void Tux::tryContinueWalking(float elapsed_time) { - if (!moving) return; + if (!moving) + return; // Let tux walk offset += TUXSPEED * elapsed_time; // Do nothing if we have not yet reached the next tile - if (offset <= 32) return; + if (offset <= 32) + return; offset -= 32; + SpriteChange* sprite_change = worldmap->at_sprite_change(tile_pos); + if(sprite_change != NULL) { + sprite = sprite_change->sprite->clone(); + sprite_change->clear_stay_action(); + } + // if this is a special_tile with passive_message, display it SpecialTile* special_tile = worldmap->at_special_tile(); - if(special_tile && special_tile->passive_message) - { + if(special_tile) + { // direction and the apply_action_ are opposites, since they "see" // directions in a different way if((direction == D_NORTH && special_tile->apply_action_south) || - (direction == D_SOUTH && special_tile->apply_action_north) || - (direction == D_WEST && special_tile->apply_action_east) || - (direction == D_EAST && special_tile->apply_action_west)) + (direction == D_SOUTH && special_tile->apply_action_north) || + (direction == D_WEST && special_tile->apply_action_east) || + (direction == D_EAST && special_tile->apply_action_west)) { - worldmap->passive_message = special_tile->map_message; - worldmap->passive_message_timer.start(map_message_TIME); + if(special_tile->passive_message) { + worldmap->passive_message = special_tile->map_message; + worldmap->passive_message_timer.start(map_message_TIME); + } else if(special_tile->script != "") { + try { + std::istringstream in(special_tile->script); + worldmap->run_script(in, "specialtile"); + } catch(std::exception& e) { + log_warning << "Couldn't execute special tile script: " << e.what() + << std::endl; + } + } } } - - - // stop if we reached a level, a WORLDMAP_STOP tile or a special tile without a passive_message - if ((worldmap->at_level()) || (worldmap->at(tile_pos)->getData() & Tile::WORLDMAP_STOP) || (special_tile && !special_tile->passive_message)) - { - if(special_tile && !special_tile->map_message.empty() && !special_tile->passive_message) worldmap->passive_message_timer.start(0); + // check if we are at a Teleporter + Teleporter* teleporter = worldmap->at_teleporter(tile_pos); + + // stop if we reached a level, a WORLDMAP_STOP tile, a teleporter or a special tile without a passive_message + if ((worldmap->at_level()) + || (worldmap->tile_data_at(tile_pos) & Tile::WORLDMAP_STOP) + || (special_tile && !special_tile->passive_message + && special_tile->script == "") + || (teleporter) || ghost_mode) { + if(special_tile && !special_tile->map_message.empty() + && !special_tile->passive_message) + worldmap->passive_message_timer.start(0); stop(); return; } // if user wants to change direction, try changing, else guess the direction in which to walk next - const Tile* tile = worldmap->at(tile_pos); - if (direction != input_direction) - { - if(canWalk(tile, input_direction)) - { - direction = input_direction; - back_direction = reverse_dir(direction); - } - } - else - { + const int tile_data = worldmap->tile_data_at(tile_pos); + if ((direction != input_direction) && canWalk(tile_data, input_direction)) { + direction = input_direction; + back_direction = reverse_dir(direction); + } else { Direction dir = D_NONE; - if (tile->getData() & Tile::WORLDMAP_NORTH && back_direction != D_NORTH) dir = D_NORTH; - else if (tile->getData() & Tile::WORLDMAP_SOUTH && back_direction != D_SOUTH) dir = D_SOUTH; - else if (tile->getData() & Tile::WORLDMAP_EAST && back_direction != D_EAST) dir = D_EAST; - else if (tile->getData() & Tile::WORLDMAP_WEST && back_direction != D_WEST) dir = D_WEST; - - if (dir == D_NONE) - { + if (tile_data & Tile::WORLDMAP_NORTH && back_direction != D_NORTH) + dir = D_NORTH; + else if (tile_data & Tile::WORLDMAP_SOUTH && back_direction != D_SOUTH) + dir = D_SOUTH; + else if (tile_data & Tile::WORLDMAP_EAST && back_direction != D_EAST) + dir = D_EAST; + else if (tile_data & Tile::WORLDMAP_WEST && back_direction != D_WEST) + dir = D_WEST; + + if (dir == D_NONE) { // Should never be reached if tiledata is good log_warning << "Could not determine where to walk next" << std::endl; stop(); @@ -224,39 +268,65 @@ Tux::tryContinueWalking(float elapsed_time) } // Walk automatically to the next tile - if(direction != D_NONE) - { - Vector next_tile; - if (worldmap->path_ok(direction, tile_pos, &next_tile)) - { - tile_pos = next_tile; - } - else - { - log_warning << "Tilemap data is buggy" << std::endl; - stop(); - } + if(direction == D_NONE) + return; + + Vector next_tile; + if (!ghost_mode && !worldmap->path_ok(direction, tile_pos, &next_tile)) { + log_debug << "Tilemap data is buggy" << std::endl; + stop(); + return; + } + + SpriteChange* next_sprite = worldmap->at_sprite_change(next_tile); + if(next_sprite != NULL && next_sprite->change_on_touch) { + sprite = next_sprite->sprite->clone(); + next_sprite->clear_stay_action(); + } + SpriteChange* last_sprite = worldmap->at_sprite_change(tile_pos); + if(last_sprite != NULL && next_sprite != NULL) { + log_debug << "Old: " << tile_pos << " New: " << next_tile << std::endl; + last_sprite->set_stay_action(); } + + tile_pos = next_tile; } void Tux::updateInputDirection() { - if(main_controller->hold(Controller::UP)) + Controller* controller_ = InputManager::current()->get_controller(); + if(controller_->hold(Controller::UP)) input_direction = D_NORTH; - else if(main_controller->hold(Controller::DOWN)) + else if(controller_->hold(Controller::DOWN)) input_direction = D_SOUTH; - else if(main_controller->hold(Controller::LEFT)) + else if(controller_->hold(Controller::LEFT)) input_direction = D_WEST; - else if(main_controller->hold(Controller::RIGHT)) + else if(controller_->hold(Controller::RIGHT)) input_direction = D_EAST; } void Tux::update(float elapsed_time) { - updateInputDirection(); - if (moving) tryContinueWalking(elapsed_time); else tryStartWalking(); + updateInputDirection(); + if (moving) + tryContinueWalking(elapsed_time); + else + tryStartWalking(); } +void +Tux::setup() +{ + // check if we already touch a SpriteChange object + SpriteChange* sprite_change = worldmap->at_sprite_change(tile_pos); + if(sprite_change != NULL) { + sprite = sprite_change->sprite->clone(); + sprite_change->clear_stay_action(); + } } + +} // namespace WorldmapNS + +/* EOF */