1 /* 2 * GameController.hpp 3 * 4 * This file is part of Leges Motus, a networked, 2D shooter set in zero gravity. 5 * 6 * Copyright 2009-2010 Andrew Ayer, Nathan Partlan, Jeffrey Pfau 7 * 8 * Leges Motus is free and open source software. You may redistribute it and/or 9 * modify it under the terms of version 2, or (at your option) version 3, of the 10 * GNU General Public License (GPL), as published by the Free Software Foundation. 11 * 12 * Leges Motus is distributed in the hope that it will be useful, but WITHOUT ANY 13 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 14 * PARTICULAR PURPOSE. See the full text of the GNU General Public License for 15 * further detail. 16 * 17 * For a full copy of the GNU General Public License, please see the COPYING file 18 * in the root of the source code tree. You may also retrieve a copy from 19 * <http://www.gnu.org/licenses/gpl-2.0.txt>, or request a copy by writing to the 20 * Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 21 * 02111-1307 USA 22 * 23 */ 24 25 #ifndef LM_CLIENT_GAMECONTROLLER_HPP 26 #define LM_CLIENT_GAMECONTROLLER_HPP 27 28 #include "GameWindow.hpp" 29 #include "GraphicalMap.hpp" 30 #include "ClientNetwork.hpp" 31 #include "TextManager.hpp" 32 #include "SoundController.hpp" 33 #include "TableBackground.hpp" 34 #include "ServerBrowser.hpp" 35 #include "ClientConfiguration.hpp" 36 #include "TransitionManager.hpp" 37 #include "ChatLog.hpp" 38 #include "common/PathManager.hpp" 39 #include "common/PacketReader.hpp" 40 #include "common/misc.hpp" 41 #include "common/GameParameters.hpp" 42 #include "common/WeaponReader.hpp" 43 #include "common/Polygon.hpp" 44 #include "GraphicalPlayer.hpp" 45 #include "Radar.hpp" 46 #include "Font.hpp" 47 #include "ScrollArea.hpp" 48 #include "ScrollBar.hpp" 49 #include "MapReceiver.hpp" 50 #include "ArbitraryMenu.hpp" 51 #include "TextMenuItem.hpp" 52 #include "ListMenuItem.hpp" 53 #include "Form.hpp" 54 #include "RadialBackground.hpp" 55 #include "RadialMenu.hpp" 56 #include "GraphicsCache.hpp" 57 #include "TextInput.hpp" 58 59 #include <string> 60 #include <vector> 61 #include <map> 62 #include <memory> 63 64 namespace LM { 65 class TiledGraphic; 66 class IPAddress; 67 class Weapon; 68 69 class GameController { 70 public: 71 static const Color BLUE_COLOR; 72 static const Color RED_COLOR; 73 static const Color BRIGHT_GREEN; 74 static const Color BRIGHT_ORANGE; 75 static const Color BLUE_SHADOW; 76 static const Color RED_SHADOW; 77 static const Color TEXT_COLOR; 78 static const Color TEXT_SHADOW; 79 static const Color GREYED_COLOR; 80 static const Color GREYED_SHADOW; 81 static const Color TEXT_BG_COLOR; 82 static const Color BUTTON_HOVER_COLOR; 83 static const Color BUTTON_HOVER_SHADOW; 84 85 const static int MESSAGE_DISPLAY_TIME; 86 const static unsigned int MAX_MESSAGES_TO_DISPLAY; 87 const static int SHOT_DISPLAY_TIME; 88 const static uint64_t MUZZLE_FLASH_LENGTH; 89 const static int GATE_WARNING_FLASH_LENGTH; 90 const static double RANDOM_ROTATION_SCALE; 91 const static int GATE_STATUS_RECT_WIDTH; 92 const static int FROZEN_STATUS_RECT_WIDTH; 93 const static int ENERGY_BAR_WIDTH; 94 const static int COOLDOWN_BAR_WIDTH; 95 const static int STATUS_BAR_HEIGHT; 96 const static int DOUBLE_CLICK_TIME; 97 const static int NETWORK_TIMEOUT_LIMIT; 98 const static int TEXT_LAYER; 99 const static unsigned int PING_FREQUENCY; 100 const static unsigned int CHAT_TRANSITION_TIME; 101 const static unsigned int CHAT_LIMIT; 102 103 private: 104 struct KeyBindings { 105 int quit; 106 int jump; 107 int show_overlay; 108 int show_menu; 109 int open_chat; 110 int open_team_chat; 111 int open_console; 112 int send_chat; 113 int weapon_1; 114 int weapon_2; 115 int weapon_3; 116 int weapon_4; 117 int weapon_5; 118 int weapon_6; 119 int weapon_7; 120 int weapon_8; 121 }; 122 123 enum { 124 SHOW_MENUS = 0, 125 GAME_IN_PROGRESS = 1, 126 GAME_OVER = 2, 127 SHOW_OPTIONS_MENU = 3, 128 SHOW_SERVER_BROWSER = 4 129 }; 130 131 struct Message { 132 Text* message; 133 Transition* transition; 134 uint64_t timeout; 135 }; 136 137 PathManager& m_path_manager; 138 ClientConfiguration* m_configuration; 139 140 GameWindow* m_window; 141 ClientNetwork m_network; 142 TextManager* m_text_manager; 143 SoundController* m_sound_controller; 144 TransitionManager m_transition_manager; 145 ServerBrowser* m_server_browser; 146 ChatLog* m_chat_log; 147 Font* m_font; 148 Font* m_bold_font; 149 Font* m_medium_font; 150 Font* m_menu_font; 151 Font* m_large_menu_font; 152 153 std::string m_name; 154 std::string m_client_version; 155 std::string m_input_text; 156 std::vector<Message> m_messages; 157 std::vector<std::pair<Graphic*, unsigned int> > m_shots; 158 int m_protocol_number; 159 int m_screen_width; 160 int m_screen_height; 161 int m_map_width; 162 int m_map_height; 163 Polygon m_map_polygon; 164 int m_pixel_depth; 165 int m_game_state; 166 bool m_fullscreen; 167 bool m_quit_game; 168 bool m_restart; 169 bool m_offline_mode; 170 double m_offset_x; 171 double m_offset_y; 172 double m_mouse_x; 173 double m_mouse_y; 174 Uint8* m_keys; 175 KeyBindings m_key_bindings; 176 KeyBindings m_alt_key_bindings; 177 std::map<uint32_t, GraphicalPlayer> m_players; 178 uint32_t m_player_id; 179 bool m_holding_gate; 180 int m_gate_lower_sounds[2]; 181 uint64_t m_last_clicked; 182 uint64_t m_join_sent_time; 183 uint64_t m_muzzle_flash_start; 184 uint64_t m_last_weapon_switch; 185 186 uint64_t m_last_damage_time; 187 uint64_t m_last_recharge_time; 188 uint64_t m_time_to_unfreeze; 189 uint64_t m_total_time_frozen; 190 191 uint64_t m_round_end_time; 192 uint64_t m_last_ping_sent; 193 uint32_t m_current_ping_id; 194 uint64_t m_ping; 195 uint64_t m_framerate; 196 197 // TEMPORARY SPRITE CODE 198 GraphicsCache m_graphics_cache; 199 200 GraphicGroup blue_player; 201 Sprite* blue_sprite; 202 Sprite* blue_back_arm; 203 GraphicGroup red_player; 204 Sprite* red_sprite; 205 Sprite* red_back_arm; 206 Sprite* m_crosshairs; 207 TextInput* m_chat_input; 208 TableBackground* m_chat_window_back; 209 Transition* m_chat_window_transition_x; 210 Transition* m_chat_window_transition_y; 211 212 TextMenuItem* m_version_nag1; 213 TextMenuItem* m_version_nag2; 214 215 Sprite* m_logo; 216 TableBackground* m_menu_back; 217 218 TextMenuItem* m_item_resume; 219 TextMenuItem* m_item_disconnect; 220 ArbitraryMenu m_main_menu; 221 ArbitraryMenu m_options_menu; 222 Form m_options_form; 223 224 size_t m_num_resolutions; 225 size_t m_resolution_selected; 226 std::vector<std::pair<int, int> > m_resolutions; 227 228 bool m_show_overlay; 229 TableBackground* m_overlay_background; 230 std::map<std::string, Text*> m_overlay_items; 231 ScrollBar* m_overlay_scrollbar; 232 ScrollArea* m_overlay_scrollarea; 233 234 RadialBackground* m_weapon_selector_back; 235 RadialMenu* m_weapon_selector; 236 237 TableBackground* m_red_gate_status_rect; 238 TableBackground* m_blue_gate_status_rect; 239 TableBackground* m_red_gate_status_rect_back; 240 TableBackground* m_blue_gate_status_rect_back; 241 Graphic* m_red_gate_status_text; 242 Graphic* m_blue_gate_status_text; 243 uint64_t m_last_gate_packet_seq_no[2]; 244 245 Graphic* m_gate_warning; 246 uint64_t m_gate_warning_time; 247 248 TableBackground* m_frozen_status_rect; 249 TableBackground* m_frozen_status_rect_back; 250 Graphic* m_frozen_status_text; 251 252 TableBackground* m_energy_bar; 253 TableBackground* m_energy_bar_back; 254 Graphic* m_energy_text; 255 256 TableBackground* m_cooldown_bar; 257 TableBackground* m_cooldown_bar_back; 258 bool m_cooldown_updated; 259 Graphic* m_curr_weapon_image; 260 261 void update_visible_elements(); 262 263 // RADAR CODE BY JEFFREY 264 Radar* m_radar; 265 void set_radar_mode(RadarMode mode); // wrapper around Radar::set_mode 266 267 // TEMPORARY MAP CODE BY ANDREW 268 GameParameters m_params; 269 GraphicalMap* m_map; 270 std::auto_ptr<MapReceiver> m_map_receiver; 271 272 // NEW WEAPON CODE 273 Weapon* m_current_weapon; 274 std::map<std::string, Weapon*> m_weapons; 275 276 // NEW INPUT CODE 277 TextInput* m_focus; 278 TextInput* m_name_input; 279 TableBackground* m_name_bar_back; 280 bool m_team_chatting; 281 282 Weapon* get_weapon(const std::string& name); 283 void init_weapon_selector(); 284 void set_weapons(); 285 void update_curr_weapon_image(); 286 void reset_weapons(); // Call reset() on all weapons. Call at end of every round. 287 void clear_weapons(); // Remove all weapons, handling memory management. 288 289 // Server Browsing/Scanning 290 IPAddress m_metaserver_address; 291 uint32_t m_current_scan_id; 292 293 static uint32_t get_next_scan_id(); 294 void preinit(ClientConfiguration* config); 295 void init(GameWindow* window); 296 void process_input(); 297 const GraphicalPlayer* get_player_by_id(uint32_t player_id) const; 298 GraphicalPlayer* get_player_by_id(uint32_t player_id); 299 GraphicalPlayer* get_player_by_name(const char* name); 300 void send_my_player_update(); 301 void attempt_jump(); 302 303 // Scan a particular server: 304 void scan_server(const IPAddress& server_address); 305 void ping_server(const IPAddress& server_address); 306 307 // Scan the local network for servers: 308 void scan_local_network(); 309 310 // Connect to the meta server to scan the Internet 311 void contact_metaserver(); 312 313 bool load_map(const char* map_name, int map_revision); 314 void request_map(); 315 void init_map(int map_width, int map_height); 316 317 // Display legalese in the chat window 318 void display_legalese(); 319 320 void send_ack(const PacketReader& packet); 321 322 // Misc. helpers 323 324 // Return the current angle (in radians) from the player to the crosshairs 325 // Doesn't take into account the player rotation 326 double get_crosshairs_angle() const; 327 328 void add_front_arm(GraphicGroup& group, const char* sprite_name); 329 void populate_graphic_group(GraphicGroup& group, const char* str); 330 void make_front_arm_graphic(GraphicGroup& player_sprite, const char* arm, const char* gun_normal, const char* gun_firing); 331 332 public: 333 explicit GameController(PathManager& pathman, ClientConfiguration* config); 334 GameController(PathManager& pathman, ClientConfiguration* config, int width, int height, bool fullscreen =false, int depth =24); 335 ~GameController(); 336 337 void run(int lockfps=60); 338 void set_screen_dimensions(int width, int height); 339 void initialize_key_bindings(); 340 void parse_key_input(); 341 void move_objects(float timescale); 342 void connect_to_server(const IPAddress& server_address, char team =0); 343 void connect_to_server(int servernum); 344 void disconnect(); 345 void send_message(std::string message); 346 void send_team_message(std::string message); display_message(std::string message)347 void display_message(std::string message) { display_message(message, TEXT_COLOR, TEXT_SHADOW); } 348 void display_message(std::string message, Color, Color, bool bold=false); 349 void send_gate_hold(bool holding); 350 void set_gate_hold(bool holding); 351 void set_players_visible(bool visible); 352 void process_mouse_click(SDL_Event event); 353 void send_animation_packet(std::string sprite, std::string field, int value); 354 void send_name_change_packet(const char* new_name); 355 void send_team_change_packet(char new_team); 356 void toggle_main_menu(bool visible); 357 void toggle_options_menu(bool visible); 358 void toggle_score_overlay(bool visible); 359 void toggle_server_browser(bool visible); 360 void set_hud_visible(bool visible); 361 void update_energy_bar(int new_energy=-1); 362 void update_cooldown_bar(double new_cooldown=-1); 363 void delete_server_browser_entry(int num); 364 void change_team_scores(int bluescore, int redscore); 365 void update_individual_scores(); 366 void update_individual_score_line(int count, const GraphicalPlayer& currplayer); 367 void delete_individual_score(const GraphicalPlayer& currplayer); 368 void set_player_name(std::string name); get_player_name() const369 std::string get_player_name() const { return m_name; }; 370 void clear_players(); 371 bool wants_restart(); 372 void reset_options(); 373 void next_weapon(); 374 void previous_weapon(); 375 void change_weapon(const char* name); 376 void change_weapon(unsigned int n); // change to the nth weapon (0-indexed) 377 void change_weapon(Weapon* weapon); 378 void recreate_name(GraphicalPlayer* player); 379 std::string get_server_address(); 380 std::string format_time_from_millis(uint64_t milliseconds); 381 void reduce_freeze_time(uint64_t milliseconds); 382 void freeze(uint64_t how_long); 383 void unfreeze(); 384 385 // This is a COMPATIBILITY WRAPPER around the more general shoot_in_line() function below. 386 // Code should be migrated to use the new function. 387 Point find_shootable_object(Point startpos, double direction, BaseMapObject*& hit_map_object, Player*& hit_player); 388 389 // A HitObject represents an object (player or map object) that was hit by a weapon discharge 390 struct HitObject { 391 double distance; // Distance from where the weapon was discharged 392 Point point; // Where in the arena that the object was hit 393 BaseMapObject* map_object; // The map object that was hit (if applicable, NULL otherwise) 394 Player* player; // The player that was hit (if applicable, NULL otherwise) 395 396 HitObject (double distance, Point point, BaseMapObject* map_object =NULL); 397 HitObject (double distance, Point point, Player* player); operator <LM::GameController::HitObject398 bool operator<(const HitObject& other) const { return distance < other.distance; } 399 }; 400 401 // Starting from the given point, shoot in a STRAIGHT LINE in the given direction, 402 // and populate the given set with the objects that are hit. 403 void shoot_in_line(Point startpos, double direction, std::multiset<HitObject>& hit_objects); 404 405 // Find all hit objects in the given shape, and populate the given set 406 // Planned for future: bool penetrate_players, bool penetrate_obstacles 407 std::list<Point> shoot_in_region(const Shape& shape, const Point& pivot, std::list<Player*>& hit_players); 408 409 // Check if an object is occluded from view from a given point 410 Point is_occluded(const Point& startpos, Point& objectcenter, HitObject& object); 411 412 // Scan both the local network and the meta server for servers: 413 void scan_all(); 414 415 // Contact the meta server to check for upgrades 416 void check_for_upgrade(); 417 418 // Network callbacks: 419 void send_packet(const PacketWriter& packet); 420 void send_reliable_packet(const PacketWriter& packet); 421 void welcome(PacketReader& reader); 422 void player_update(PacketReader& reader); 423 void announce(PacketReader& reader); 424 void leave(PacketReader& reader); 425 void weapon_discharged(PacketReader& reader); 426 void player_hit(PacketReader& reader); 427 void message(PacketReader& reader); 428 void gate_update(PacketReader& reader); 429 void new_round(PacketReader& reader); 430 void round_over(PacketReader& reader); 431 void round_start(PacketReader& reader); 432 void spawn_packet(PacketReader& reader); 433 void score_update(PacketReader& reader); 434 void animation_packet(PacketReader& reader); 435 void request_denied(PacketReader& reader); 436 void name_change(PacketReader& reader); 437 void team_change(PacketReader& reader); 438 void map_info_packet(PacketReader& reader); 439 void map_object_packet(PacketReader& reader); 440 void game_param_packet(PacketReader& reader); 441 void player_died(PacketReader& reader); 442 void weapon_info_packet(PacketReader& reader); 443 void server_info(const IPAddress& server_address, PacketReader& reader); 444 void upgrade_available(const IPAddress& server_address, PacketReader& reader); 445 void hole_punch_packet(const IPAddress& server_address, PacketReader& reader); 446 void excessive_packet_drop(); 447 448 // Sound callbacks: 449 void play_sound(const char* name); 450 void sound_finished(int channel); 451 452 // Weapon callbacks: 453 void activate_radar_blip(const Player& player); 454 void show_muzzle_flash(); 455 void show_bullet_impact(Point position, const char* sprite_name); 456 void register_front_arm_graphic(Player& player, const char* normal, const char* firing); 457 458 // Damage the player by this amount of energy 459 // aggressor is the player who did the damage, or NULL if no player did it (e.g. hazerdous map object) 460 // Returns true if the player died as a result, false if the player is still alive 461 bool damage (int amount, const Player* aggressor); 462 }; 463 } 464 465 #endif 466 467