X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=contrib%2Fsupertux-coop.diff;h=f2c08b3ac2e64d658e9eaff2956c1e49fae1b3cf;hb=e449041f97af574103b20cca6d45c06d71677a98;hp=e3a58efda31664f5de7dd21a9218cdd7aa33acd9;hpb=2149c2e76fa695fb815367063e67c4319402b03c;p=supertux.git diff --git a/contrib/supertux-coop.diff b/contrib/supertux-coop.diff index e3a58efda..f2c08b3ac 100644 --- a/contrib/supertux-coop.diff +++ b/contrib/supertux-coop.diff @@ -1,313 +1,405 @@ -# -# SuperTux -coop patch -# Copyright (C) 2007 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 distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# 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. -# -# ----------------------------------------------------------------------------- -# -# This patch allows two players to cooperatively jump and run through -# SuperTux' levels. -# -# Note that this is more or less a friendly hack. Most objects and all levels -# of SuperTux were not designed to work with two players. Expect lots of bugs. -# -# Installing the patch should be pretty straightforward. Simply run the -# following command prior to running jam: -# -# patch -p0 < contrib/supertux-coop.diff -# -# This patch works for revision 4866. It may break for later revisions. -# -# ----------------------------------------------------------------------------- -Index: src/control/joystickkeyboardcontroller.cpp -=================================================================== ---- src/control/joystickkeyboardcontroller.cpp (revision 4856) -+++ src/control/joystickkeyboardcontroller.cpp (working copy) -@@ -29,6 +29,7 @@ - #include "game_session.hpp" - #include "console.hpp" - #include "gameconfig.hpp" -+#include "main.hpp" - - class JoystickKeyboardController::JoystickMenu : public Menu - { -@@ -339,7 +340,7 @@ - - ButtonMap::iterator i = joy_button_map.find(event.jbutton.button); - if(i == joy_button_map.end()) { -- log_debug << "Unmapped joybutton " << (int)event.jbutton.button << " pressed" << std::endl; -+ //log_debug << "Unmapped joybutton " << (int)event.jbutton.button << " pressed" << std::endl; - return; - } +Index: src/control/joystickkeyboardcontroller.cpp +=================================================================== +--- src/control/joystickkeyboardcontroller.cpp (revision 6139) ++++ src/control/joystickkeyboardcontroller.cpp (working copy) +@@ -479,11 +479,12 @@ + KeyMap::iterator key_mapping = keymap.find(event.key.keysym.sym); -@@ -360,13 +361,13 @@ // if console key was pressed: toggle console - if ((key_mapping != keymap.end()) && (key_mapping->second == CONSOLE)) { - if (event.type != SDL_KEYDOWN) return; -- Console::instance->toggle(); -+ if (this == main_controller) Console::instance->toggle(); - return; - } - - // if console is open: send key there - if (Console::instance->hasFocus()) { -- process_console_key_event(event); -+ if (this == main_controller) process_console_key_event(event); - return; - } - -@@ -378,7 +379,7 @@ - - // default action: update controls - if(key_mapping == keymap.end()) { -- log_debug << "Key " << event.key.keysym.sym << " is unbound" << std::endl; -+ //log_debug << "Key " << event.key.keysym.sym << " is unbound" << std::endl; - return; - } - Control control = key_mapping->second; -Index: src/options_menu.cpp -=================================================================== ---- src/options_menu.cpp (revision 4856) -+++ src/options_menu.cpp (working copy) -@@ -58,6 +58,8 @@ - } - add_submenu(_("Setup Keyboard"), main_controller->get_key_options_menu()); - add_submenu(_("Setup Joystick"),main_controller->get_joystick_options_menu()); -+ add_submenu(std::string(_("Setup Keyboard"))+" (P2)", secondary_controller->get_key_options_menu()); -+ add_submenu(std::string(_("Setup Joystick"))+" (P2)", secondary_controller->get_joystick_options_menu()); - add_hl(); - add_back(_("Back")); - } -Index: src/main.hpp -=================================================================== ---- src/main.hpp (revision 4856) -+++ src/main.hpp (working copy) -@@ -31,5 +31,6 @@ - // global variables - class JoystickKeyboardController; - extern JoystickKeyboardController* main_controller; -+extern JoystickKeyboardController* secondary_controller; - - #endif -Index: src/game_session.cpp -=================================================================== ---- src/game_session.cpp (revision 4856) -+++ src/game_session.cpp (working copy) -@@ -117,6 +117,7 @@ - end_sequence = 0; - - main_controller->reset(); -+ secondary_controller->reset(); - - currentsector = 0; - -@@ -542,9 +543,11 @@ - - // TODO make a screen out of this, another mainloop is ugly - main_controller->update(); -+ secondary_controller->update(); - SDL_Event event; - while (SDL_PollEvent(&event)) { - main_controller->process_event(event); -+ secondary_controller->process_event(event); - if(event.type == SDL_QUIT) - main_loop->quit(); - } -Index: src/mainloop.cpp -=================================================================== ---- src/mainloop.cpp (revision 4856) -+++ src/mainloop.cpp (working copy) -@@ -166,9 +166,11 @@ - MainLoop::process_events() - { - main_controller->update(); -+ secondary_controller->update(); - SDL_Event event; - while(SDL_PollEvent(&event)) { - main_controller->process_event(event); -+ secondary_controller->process_event(event); - if(Menu::current() != NULL) - Menu::current()->event(event); - if(event.type == SDL_QUIT) -Index: src/object/player.cpp -=================================================================== ---- src/object/player.cpp (revision 4856) -+++ src/object/player.cpp (working copy) -@@ -116,6 +116,7 @@ +- if ((key_mapping != keymap.end()) && (key_mapping->second == CONSOLE)) { ++ // only main controller does console ++ if ((key_mapping != keymap.end()) && (key_mapping->second == CONSOLE) && (this == g_main_controller)) { + if (event.type == SDL_KEYDOWN) + Console::instance->toggle(); + } else { +- if (Console::instance->hasFocus()) { ++ if (Console::instance->hasFocus() && (this == g_main_controller)) { + // if console is open: send key there + process_console_key_event(event); + } else if (MenuManager::current()) { +Index: src/object/player.cpp +=================================================================== +--- src/object/player.cpp (revision 6139) ++++ src/object/player.cpp (working copy) +@@ -152,7 +152,7 @@ + climbing(0) { this->name = name; - controller = main_controller; -+ if (name == "Penny") controller = secondary_controller; - smalltux_gameover = sprite_manager->create("images/creatures/tux_small/smalltux-gameover.sprite"); - smalltux_star = sprite_manager->create("images/creatures/tux_small/smalltux-star.sprite"); - bigtux_star = sprite_manager->create("images/creatures/tux_big/bigtux-star.sprite"); -@@ -875,6 +876,9 @@ - - int layer = LAYER_OBJECTS + 1; +- controller = g_main_controller; ++ controller = (name == "Penny") ? g_secondary_controller : g_main_controller; + scripting_controller.reset(new CodeController()); + sprite = sprite_manager->create("images/creatures/tux/tux.sprite"); + airarrow = Surface::create("images/engine/hud/airarrow.png"); +@@ -1015,6 +1015,16 @@ + else + sa_postfix = "-right"; -+ // draw second player behind main player -+ if (name == "Penny") layer -= 20; ++ // two-player hack: draw Penny in a different color ++ if (name == "Penny") { ++ sprite->set_color(Color(1.0f, 1.0f, 0.5f, 1.0f)); ++ } else { ++ sprite->set_color(Color(1.0f, 1.0f, 1.0f, 1.0f)); ++ } ++ // if/when we have complete penny gfx, we can ++ // load those instead of Tux's sprite in the ++ // constructor + /* Set Tux sprite action */ - if (climbing) - { -@@ -1049,6 +1053,12 @@ + if(dying) { + sprite->set_action("gameover"); +@@ -1177,6 +1187,11 @@ return FORCE_MOVE; } -+ // Multiple Players pass through one another + Player* player = dynamic_cast (&other); + if(player) { -+ return FORCE_MOVE; ++ return ABORT_MOVE; + } + if(hit.left || hit.right) { try_grab(); //grab objects right now, in update it will be too late } -@@ -1141,6 +1151,8 @@ +@@ -1276,8 +1291,11 @@ dying_timer.start(3.0); set_group(COLGROUP_DISABLED); -+ if (name == "Penny") return; -+ - DisplayEffect* effect = new DisplayEffect(); - effect->fade_out(3.0); - Sector::current()->add_object(effect); -Index: src/gameconfig.cpp -=================================================================== ---- src/gameconfig.cpp (revision 4856) -+++ src/gameconfig.cpp (working copy) -@@ -86,6 +86,10 @@ - if(config_control_lisp && main_controller) { - main_controller->read(*config_control_lisp); +- Sector::current()->effect->fade_out(3.0); +- sound_manager->stop_music(3.0); ++ // Two-player hack: ignore Penny's death ++ if (name != "Penny") { ++ Sector::current()->effect->fade_out(3.0); ++ sound_manager->stop_music(3.0); ++ } } -+ const lisp::Lisp* config_control_lisp2 = config_lisp->get_lisp("control-p2"); -+ if(config_control_lisp2 && secondary_controller) { -+ secondary_controller->read(*config_control_lisp2); -+ } } - void -@@ -116,6 +120,11 @@ - main_controller->write(writer); +Index: src/supertux/game_session.cpp +=================================================================== +--- src/supertux/game_session.cpp (revision 6139) ++++ src/supertux/game_session.cpp (working copy) +@@ -93,6 +93,7 @@ + end_sequence = 0; + + g_main_controller->reset(); ++ g_secondary_controller->reset(); + + currentsector = 0; + +@@ -434,6 +435,22 @@ + game_pause = false; + } + ++ // two-player hack: resurrect Penny when she dies ++ Player* tux = currentsector->player; ++ for(std::vector::iterator i = currentsector->gameobjects.begin(); i != currentsector->gameobjects.end(); ++i) { ++ Player* p = dynamic_cast(*i); ++ if (!p) continue; ++ if (p == tux) continue; ++ if (p->is_dead()) { ++ p->remove_me(); ++ static PlayerStatus* ps = new PlayerStatus(); ++ p = new Player(ps, "Penny"); ++ currentsector->add_object(p); ++ p->move(tux->get_pos()); ++ p->safe_timer.start(TUX_SAFE_TIME); ++ } ++ } ++ + check_end_conditions(); + + // respawning in new sector? +Index: src/supertux/gameconfig.cpp +=================================================================== +--- src/supertux/gameconfig.cpp (revision 6139) ++++ src/supertux/gameconfig.cpp (working copy) +@@ -94,6 +94,11 @@ + g_main_controller->read(*config_control_lisp); + } + ++ const lisp::Lisp* config_control_p2_lisp = config_lisp->get_lisp("control-p2"); ++ if(config_control_p2_lisp && g_secondary_controller) { ++ g_secondary_controller->read(*config_control_p2_lisp); ++ } ++ + const lisp::Lisp* config_addons_lisp = config_lisp->get_lisp("addons"); + if(config_addons_lisp) { + AddonManager::get_instance().read(*config_addons_lisp); +@@ -138,6 +143,12 @@ writer.end_list("control"); } -+ if(secondary_controller) { + ++ if(g_secondary_controller) { + writer.start_list("control-p2"); -+ secondary_controller->write(writer); ++ g_secondary_controller->write(writer); + writer.end_list("control-p2"); + } ++ + writer.start_list("addons"); + AddonManager::get_instance().write(writer); + writer.end_list("addons"); +Index: src/supertux/globals.cpp +=================================================================== +--- src/supertux/globals.cpp (revision 6139) ++++ src/supertux/globals.cpp (working copy) +@@ -19,6 +19,7 @@ - writer.end_list("supertux-config"); - } -Index: src/main.cpp -=================================================================== ---- src/main.cpp (revision 4856) -+++ src/main.cpp (working copy) -@@ -58,6 +58,7 @@ - - SDL_Surface* screen = 0; - JoystickKeyboardController* main_controller = 0; -+JoystickKeyboardController* secondary_controller = 0; - TinyGetText::DictionaryManager dictionary_manager; + SDL_Surface* g_screen; + JoystickKeyboardController* g_main_controller = 0; ++JoystickKeyboardController* g_secondary_controller = 0; + tinygettext::DictionaryManager* dictionary_manager = 0; int SCREEN_WIDTH; -@@ -514,6 +515,7 @@ +Index: src/supertux/globals.hpp +=================================================================== +--- src/supertux/globals.hpp (revision 6139) ++++ src/supertux/globals.hpp (working copy) +@@ -41,6 +41,7 @@ + + // global variables + extern JoystickKeyboardController* g_main_controller; ++extern JoystickKeyboardController* g_secondary_controller; + + extern SDL_Surface* g_screen; + +@@ -64,6 +65,7 @@ + + // global player state + extern PlayerStatus* player_status; ++extern PlayerStatus* second_player_status; + + extern SpriteManager* sprite_manager; + +Index: src/supertux/main.cpp +=================================================================== +--- src/supertux/main.cpp (revision 6139) ++++ src/supertux/main.cpp (working copy) +@@ -541,6 +541,7 @@ timelog("controller"); - main_controller = new JoystickKeyboardController(); -+ secondary_controller = new JoystickKeyboardController(); + g_main_controller = new JoystickKeyboardController(); ++ g_secondary_controller = new JoystickKeyboardController(); + timelog("config"); init_config(); - timelog("tinygettext"); -@@ -587,7 +589,9 @@ - delete config; - config = NULL; - delete main_controller; -+ delete secondary_controller; - main_controller = NULL; -+ secondary_controller = NULL; +@@ -629,6 +630,8 @@ + g_config = NULL; + delete g_main_controller; + g_main_controller = NULL; ++ delete g_secondary_controller; ++ g_secondary_controller = NULL; delete Console::instance; Console::instance = NULL; - Scripting::exit_squirrel(); -Index: src/sector.cpp -=================================================================== ---- src/sector.cpp (revision 4856) -+++ src/sector.cpp (working copy) -@@ -74,11 +74,21 @@ - bool Sector::show_collrects = false; - bool Sector::draw_solids_only = false; - -+namespace { -+ // two-player hack: second player's player_status -+ PlayerStatus* second_player_status = 0; + scripting::exit_squirrel(); +Index: src/supertux/menu/menu_storage.cpp +=================================================================== +--- src/supertux/menu/menu_storage.cpp (revision 6139) ++++ src/supertux/menu/menu_storage.cpp (working copy) +@@ -26,6 +26,8 @@ + ProfileMenu* MenuStorage::profile_menu = 0; + KeyboardMenu* MenuStorage::key_options_menu = 0; + JoystickMenu* MenuStorage::joystick_options_menu = 0; ++KeyboardMenu* MenuStorage::key_options_p2_menu = 0; ++JoystickMenu* MenuStorage::joystick_options_p2_menu = 0; + + OptionsMenu* + MenuStorage::get_options_menu() +@@ -63,4 +65,26 @@ + return joystick_options_menu; + } + ++KeyboardMenu* ++MenuStorage::get_key_options_p2_menu() ++{ ++ if (!key_options_p2_menu) ++ { // FIXME: this in never freed ++ key_options_p2_menu = new KeyboardMenu(g_secondary_controller); ++ } ++ ++ return key_options_p2_menu; ++} ++ ++JoystickMenu* ++MenuStorage::get_joystick_options_p2_menu() ++{ ++ if (!joystick_options_p2_menu) ++ { // FIXME: this in never freed ++ joystick_options_p2_menu = new JoystickMenu(g_secondary_controller); ++ } ++ ++ return joystick_options_p2_menu; +} + - Sector::Sector(Level* parent) - : level(parent), currentmusic(LEVEL_MUSIC), - ambient_light( 1.0f, 1.0f, 1.0f, 1.0f ), gravity(10.0), player(0), camera(0) + /* EOF */ +Index: src/supertux/menu/menu_storage.hpp +=================================================================== +--- src/supertux/menu/menu_storage.hpp (revision 6139) ++++ src/supertux/menu/menu_storage.hpp (working copy) +@@ -32,12 +32,16 @@ + static ProfileMenu* get_profile_menu(); + static KeyboardMenu* get_key_options_menu(); + static JoystickMenu* get_joystick_options_menu(); ++ static KeyboardMenu* get_key_options_p2_menu(); ++ static JoystickMenu* get_joystick_options_p2_menu(); + + private: + static OptionsMenu* options_menu; + static ProfileMenu* profile_menu; + static KeyboardMenu* key_options_menu; + static JoystickMenu* joystick_options_menu; ++ static KeyboardMenu* key_options_p2_menu; ++ static JoystickMenu* joystick_options_p2_menu; + + private: + MenuStorage(const MenuStorage&); +Index: src/supertux/menu/options_menu.cpp +=================================================================== +--- src/supertux/menu/options_menu.cpp (revision 6139) ++++ src/supertux/menu/options_menu.cpp (working copy) +@@ -161,6 +161,13 @@ + + add_submenu(_("Setup Joystick"), MenuStorage::get_joystick_options_menu()) + ->set_help(_("Configure joystick control-action mappings")); ++ ++ add_submenu(_("Setup P2 Keyboard"), MenuStorage::get_key_options_p2_menu()) ++ ->set_help(_("Configure key-action mappings")); ++ ++ add_submenu(_("Setup P2 Joystick"), MenuStorage::get_joystick_options_p2_menu()) ++ ->set_help(_("Configure joystick control-action mappings")); ++ + add_hl(); + add_back(_("Back")); + } +Index: src/supertux/player_status.cpp +=================================================================== +--- src/supertux/player_status.cpp (revision 6139) ++++ src/supertux/player_status.cpp (working copy) +@@ -30,6 +30,7 @@ + static const int MAX_COINS = 9999; + + PlayerStatus* player_status = 0; ++PlayerStatus* second_player_status = 0; + + PlayerStatus::PlayerStatus() : + coins(START_COINS), +Index: src/supertux/resources.cpp +=================================================================== +--- src/supertux/resources.cpp (revision 6139) ++++ src/supertux/resources.cpp (working copy) +@@ -48,6 +48,7 @@ + sprite_manager = new SpriteManager(); + + player_status = new PlayerStatus(); ++ second_player_status = new PlayerStatus(); + } + + /* Free shared data: */ +@@ -67,6 +68,9 @@ + + delete player_status; + player_status = NULL; ++ ++ delete second_player_status; ++ second_player_status = NULL; + } + + /* EOF */ +Index: src/supertux/screen_manager.cpp +=================================================================== +--- src/supertux/screen_manager.cpp (revision 6139) ++++ src/supertux/screen_manager.cpp (working copy) +@@ -190,11 +190,13 @@ + ScreenManager::process_events() + { + g_main_controller->update(); ++ g_secondary_controller->update(); + Uint8* keystate = SDL_GetKeyState(NULL); + SDL_Event event; + while(SDL_PollEvent(&event)) + { + g_main_controller->process_event(event); ++ g_secondary_controller->process_event(event); + + if(MenuManager::current() != NULL) + MenuManager::current()->event(event); +Index: src/supertux/sector.cpp +=================================================================== +--- src/supertux/sector.cpp (revision 6139) ++++ src/supertux/sector.cpp (working copy) +@@ -84,6 +84,7 @@ + effect(0) { add_object(new Player(player_status, "Tux")); -+ -+ // two-player hack: second player has dummy player_status -+ if (!second_player_status) second_player_status = new PlayerStatus(); + add_object(new Player(second_player_status, "Penny")); -+ add_object(new DisplayEffect("Effect")); add_object(new TextObject("Text")); -@@ -591,6 +601,16 @@ - player->move(npos); +@@ -572,19 +573,27 @@ } + try_expose_me(); + +- // spawn smalltux below spawnpoint +- if (!player->is_big()) { +- player->move(player_pos + Vector(0,32)); +- } else { +- player->move(player_pos); +- } +- // spawning tux in the ground would kill him +- if(!is_free_of_tiles(player->get_bbox())) { +- log_warning << "Tried spawning Tux in solid matter. Compensating." << std::endl; +- Vector npos = player->get_bbox().p1; +- npos.y-=32; +- player->move(npos); + // two-player hack: move other players to main player's position + for(GameObjects::iterator i = gameobjects.begin(); + i != gameobjects.end(); ++i) { + Player* p = dynamic_cast(*i); + if (!p) continue; -+ if (p == player) continue; -+ p->move(player->get_pos()); -+ } + ++ // spawn smalltux below spawnpoint ++ if (!p->is_big()) { ++ p->move(player_pos + Vector(0,32)); ++ } else { ++ p->move(player_pos); ++ } + - camera->reset(player->get_pos()); - update_game_objects(); ++ // spawning tux in the ground would kill him ++ if(!is_free_of_tiles(p->get_bbox())) { ++ log_warning << "Tried spawning Tux in solid matter. Compensating." << std::endl; ++ Vector npos = p->get_bbox().p1; ++ npos.y-=32; ++ p->move(npos); ++ } + } -@@ -639,6 +659,15 @@ + camera->reset(player->get_pos()); +@@ -645,7 +654,13 @@ + void + Sector::update(float elapsed_time) { - player->check_bounds(camera); - -+ // two-player hack: keep other players in bound, too +- player->check_bounds(camera); ++ // keep players in bounds + for(GameObjects::iterator i = gameobjects.begin(); + i != gameobjects.end(); ++i) { + Player* p = dynamic_cast(*i); + if (!p) continue; -+ if (p == player) continue; + p->check_bounds(camera); + } -+ + /* update objects */ for(GameObjects::iterator i = gameobjects.begin(); - i != gameobjects.end(); ++i) { -@@ -721,7 +750,7 @@ +@@ -741,10 +756,11 @@ Player* player = dynamic_cast (object); if(player != NULL) { if(this->player != 0) { - log_warning << "Multiple players added. Ignoring" << std::endl; -+ //log_warning << "Multiple players added. Ignoring" << std::endl; - return false; +- return false; ++// log_warning << "Multiple players added. Ignoring" << std::endl; ++// return false; ++ } else { ++ this->player = player; } - this->player = player; +- this->player = player; + } + + DisplayEffect* effect = dynamic_cast (object);