From: Christoph Sommer Date: Sun, 18 Feb 2007 19:15:40 +0000 (+0000) Subject: Added patch that allows cooperative play with two players. Hacky, but lots of fun... X-Git-Url: https://git.verplant.org/?a=commitdiff_plain;h=2149c2e76fa695fb815367063e67c4319402b03c;p=supertux.git Added patch that allows cooperative play with two players. Hacky, but lots of fun... SVN-Revision: 4857 --- diff --git a/contrib/supertux-coop.diff b/contrib/supertux-coop.diff new file mode 100644 index 000000000..e3a58efda --- /dev/null +++ b/contrib/supertux-coop.diff @@ -0,0 +1,313 @@ +# +# 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; + } + +@@ -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 @@ + { + 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; + ++ // draw second player behind main player ++ if (name == "Penny") layer -= 20; ++ + /* Set Tux sprite action */ + if (climbing) + { +@@ -1049,6 +1053,12 @@ + return FORCE_MOVE; + } + ++ // Multiple Players pass through one another ++ Player* player = dynamic_cast (&other); ++ if(player) { ++ return FORCE_MOVE; ++ } ++ + if(hit.left || hit.right) { + try_grab(); //grab objects right now, in update it will be too late + } +@@ -1141,6 +1151,8 @@ + 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); + } ++ 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); + writer.end_list("control"); + } ++ if(secondary_controller) { ++ writer.start_list("control-p2"); ++ secondary_controller->write(writer); ++ writer.end_list("control-p2"); ++ } + + 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; + + int SCREEN_WIDTH; +@@ -514,6 +515,7 @@ + + timelog("controller"); + main_controller = new JoystickKeyboardController(); ++ 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; + 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; ++} ++ + 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) + { + 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); + } + ++ // 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()); ++ } ++ ++ + camera->reset(player->get_pos()); + update_game_objects(); + +@@ -639,6 +659,15 @@ + { + player->check_bounds(camera); + ++ // two-player hack: keep other players in bound, too ++ 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 @@ + 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; + } + this->player = player;