diff --git a/README.md b/README.md new file mode 100644 index 0000000..c872d52 --- /dev/null +++ b/README.md @@ -0,0 +1,53 @@ +SFMechSimulator +=============== + +_A pseudo 3D Mech Simulator created with C++ and SFML_
+ +Pilot a giant robot and battle other giant robots in a psuedo 3D environment.
+Repair and upgrade your mech between missions.
+Carefully select upgrades and develop winning strategies in combat.
+ +SF Mech Sim + +**Compiling**
+ +_Windows:_
+ +Download SFML and GCC here https://www.sfml-dev.org/download/sfml/2.5.1/
+You will need 'MinGW Builds 7.3.0 (64-bit)' and SFML 'GCC 7.3.0 MinGW (SEH) - 64-bit'
+For 32 bit systems you will need 'MinGW Builds 7.3.0 (32-bit)' and 'GCC 7.3.0 MinGW (DW2) - 32-bit'
+ +Clone this repository to C:\ so the source code is present at C:\SFMechSimulator
+Extract the downloaded SFML package to C:\ so SFML is present at C:\SFML-2.5.1
+Run the compile_windows.bat script
+Run SFMechSimulator.exe to play the game
+To run the game in a window, use the command line argument '-window'
+ie: 'SFMechSimulator.exe -window 1280 720'
+The window cannot be smaller than 1280x720
+ +_Mac:_
+ +Clone this repository.
+Install g++ as described here http://www.edparrish.net/common/macgpp.php#installg++
+Download SFML here https://www.sfml-dev.org/download/sfml/2.5.1/
+Copy the contents of the SFML Frameworks and extlibs directories to /Library/Frameworks
+Run the compile_mac.sh script
+Run the SFMechSimulator executable to play the game
+To run the game in a window, use the command line argument '-window'
+ie: './SFMechSimulator -window 1280 720'
+The window cannot be smaller than 1280x720
+ +_Linux:_
+ +Clone this repository.
+Install SFML, ie: 'sudo apt-get install libsfml-dev'
+Run the compile_linux.sh script
+Run the SFMechSimulator executable to play the game
+To run the game in a window, use the command line argument '-window'
+ie: './SFMechSimulator -window 1280 720'
+The window cannot be smaller than 1280x720
+ +**Playing the Game**
+ +Click the 'NEW GAME' button at the main menu
+Press F1 to start the tutorial
diff --git a/assets/Exoplanetaria-gxxJ5.ttf b/assets/Exoplanetaria-gxxJ5.ttf new file mode 100644 index 0000000..a2a07c6 Binary files /dev/null and b/assets/Exoplanetaria-gxxJ5.ttf differ diff --git a/assets/Orbitron Medium.ttf b/assets/Orbitron Medium.ttf new file mode 100644 index 0000000..88499ff Binary files /dev/null and b/assets/Orbitron Medium.ttf differ diff --git a/assets/sounds/cannon.ogg b/assets/sounds/cannon.ogg new file mode 100644 index 0000000..f60b7d4 Binary files /dev/null and b/assets/sounds/cannon.ogg differ diff --git a/assets/sounds/crash.ogg b/assets/sounds/crash.ogg new file mode 100644 index 0000000..36d0a0f Binary files /dev/null and b/assets/sounds/crash.ogg differ diff --git a/assets/sounds/explosion.ogg b/assets/sounds/explosion.ogg new file mode 100644 index 0000000..1756a73 Binary files /dev/null and b/assets/sounds/explosion.ogg differ diff --git a/assets/sounds/guns.ogg b/assets/sounds/guns.ogg new file mode 100644 index 0000000..6bb1030 Binary files /dev/null and b/assets/sounds/guns.ogg differ diff --git a/assets/sounds/hydraulic.ogg b/assets/sounds/hydraulic.ogg new file mode 100644 index 0000000..2d73d5c Binary files /dev/null and b/assets/sounds/hydraulic.ogg differ diff --git a/assets/sounds/impact.ogg b/assets/sounds/impact.ogg new file mode 100644 index 0000000..7ef6c47 Binary files /dev/null and b/assets/sounds/impact.ogg differ diff --git a/assets/sounds/intermission_menu.ogg b/assets/sounds/intermission_menu.ogg new file mode 100644 index 0000000..3d7e2d9 Binary files /dev/null and b/assets/sounds/intermission_menu.ogg differ diff --git a/assets/sounds/main_menu.ogg b/assets/sounds/main_menu.ogg new file mode 100644 index 0000000..4d6cb03 Binary files /dev/null and b/assets/sounds/main_menu.ogg differ diff --git a/assets/sounds/mission.ogg b/assets/sounds/mission.ogg new file mode 100644 index 0000000..dd05ccb Binary files /dev/null and b/assets/sounds/mission.ogg differ diff --git a/assets/sounds/power_down.ogg b/assets/sounds/power_down.ogg new file mode 100644 index 0000000..e30698b Binary files /dev/null and b/assets/sounds/power_down.ogg differ diff --git a/assets/sounds/power_up.ogg b/assets/sounds/power_up.ogg new file mode 100644 index 0000000..a4e213e Binary files /dev/null and b/assets/sounds/power_up.ogg differ diff --git a/assets/sounds/purchase.ogg b/assets/sounds/purchase.ogg new file mode 100644 index 0000000..8cb70e1 Binary files /dev/null and b/assets/sounds/purchase.ogg differ diff --git a/assets/sounds/stomp.ogg b/assets/sounds/stomp.ogg new file mode 100644 index 0000000..1fd7889 Binary files /dev/null and b/assets/sounds/stomp.ogg differ diff --git a/assets/sounds/victory.ogg b/assets/sounds/victory.ogg new file mode 100644 index 0000000..2c04c4e Binary files /dev/null and b/assets/sounds/victory.ogg differ diff --git a/assets/textures/buttons/cancel_button.png b/assets/textures/buttons/cancel_button.png new file mode 100644 index 0000000..f71cba5 Binary files /dev/null and b/assets/textures/buttons/cancel_button.png differ diff --git a/assets/textures/buttons/cancel_button_hover.png b/assets/textures/buttons/cancel_button_hover.png new file mode 100644 index 0000000..4edf747 Binary files /dev/null and b/assets/textures/buttons/cancel_button_hover.png differ diff --git a/assets/textures/buttons/create_new_button.png b/assets/textures/buttons/create_new_button.png new file mode 100644 index 0000000..614b8f3 Binary files /dev/null and b/assets/textures/buttons/create_new_button.png differ diff --git a/assets/textures/buttons/create_new_button_hover.png b/assets/textures/buttons/create_new_button_hover.png new file mode 100644 index 0000000..a3346e7 Binary files /dev/null and b/assets/textures/buttons/create_new_button_hover.png differ diff --git a/assets/textures/buttons/exit_game_button.png b/assets/textures/buttons/exit_game_button.png new file mode 100644 index 0000000..dd1e6b5 Binary files /dev/null and b/assets/textures/buttons/exit_game_button.png differ diff --git a/assets/textures/buttons/exit_game_button_hover.png b/assets/textures/buttons/exit_game_button_hover.png new file mode 100644 index 0000000..0036648 Binary files /dev/null and b/assets/textures/buttons/exit_game_button_hover.png differ diff --git a/assets/textures/buttons/load_button.png b/assets/textures/buttons/load_button.png new file mode 100644 index 0000000..e2a3bfe Binary files /dev/null and b/assets/textures/buttons/load_button.png differ diff --git a/assets/textures/buttons/load_button_hover.png b/assets/textures/buttons/load_button_hover.png new file mode 100644 index 0000000..ec11f6b Binary files /dev/null and b/assets/textures/buttons/load_button_hover.png differ diff --git a/assets/textures/buttons/main_menu_button.png b/assets/textures/buttons/main_menu_button.png new file mode 100644 index 0000000..34985cb Binary files /dev/null and b/assets/textures/buttons/main_menu_button.png differ diff --git a/assets/textures/buttons/main_menu_button_hover.png b/assets/textures/buttons/main_menu_button_hover.png new file mode 100644 index 0000000..b810022 Binary files /dev/null and b/assets/textures/buttons/main_menu_button_hover.png differ diff --git a/assets/textures/buttons/market_button.png b/assets/textures/buttons/market_button.png new file mode 100644 index 0000000..2625193 Binary files /dev/null and b/assets/textures/buttons/market_button.png differ diff --git a/assets/textures/buttons/market_button_hover.png b/assets/textures/buttons/market_button_hover.png new file mode 100644 index 0000000..465743a Binary files /dev/null and b/assets/textures/buttons/market_button_hover.png differ diff --git a/assets/textures/buttons/next_mission_button.png b/assets/textures/buttons/next_mission_button.png new file mode 100644 index 0000000..e490899 Binary files /dev/null and b/assets/textures/buttons/next_mission_button.png differ diff --git a/assets/textures/buttons/next_mission_button_hover.png b/assets/textures/buttons/next_mission_button_hover.png new file mode 100644 index 0000000..dd81920 Binary files /dev/null and b/assets/textures/buttons/next_mission_button_hover.png differ diff --git a/assets/textures/buttons/options_button.png b/assets/textures/buttons/options_button.png new file mode 100644 index 0000000..394867d Binary files /dev/null and b/assets/textures/buttons/options_button.png differ diff --git a/assets/textures/buttons/options_button_hover.png b/assets/textures/buttons/options_button_hover.png new file mode 100644 index 0000000..7e0c466 Binary files /dev/null and b/assets/textures/buttons/options_button_hover.png differ diff --git a/assets/textures/buttons/repair_button.png b/assets/textures/buttons/repair_button.png new file mode 100644 index 0000000..523fd84 Binary files /dev/null and b/assets/textures/buttons/repair_button.png differ diff --git a/assets/textures/buttons/repair_button_hover.png b/assets/textures/buttons/repair_button_hover.png new file mode 100644 index 0000000..2f33c0e Binary files /dev/null and b/assets/textures/buttons/repair_button_hover.png differ diff --git a/assets/textures/buttons/save_button.png b/assets/textures/buttons/save_button.png new file mode 100644 index 0000000..32e731c Binary files /dev/null and b/assets/textures/buttons/save_button.png differ diff --git a/assets/textures/buttons/save_button_hover.png b/assets/textures/buttons/save_button_hover.png new file mode 100644 index 0000000..f4c4f90 Binary files /dev/null and b/assets/textures/buttons/save_button_hover.png differ diff --git a/assets/textures/buttons/start_game_button.png b/assets/textures/buttons/start_game_button.png new file mode 100644 index 0000000..3ae1132 Binary files /dev/null and b/assets/textures/buttons/start_game_button.png differ diff --git a/assets/textures/buttons/start_game_button_hover.png b/assets/textures/buttons/start_game_button_hover.png new file mode 100644 index 0000000..f24afd8 Binary files /dev/null and b/assets/textures/buttons/start_game_button_hover.png differ diff --git a/assets/textures/cockpit/cockpit.bmp b/assets/textures/cockpit/cockpit.bmp new file mode 100644 index 0000000..c8e3573 Binary files /dev/null and b/assets/textures/cockpit/cockpit.bmp differ diff --git a/assets/textures/cockpit/cockpit_cannon.bmp b/assets/textures/cockpit/cockpit_cannon.bmp new file mode 100644 index 0000000..94e0d76 Binary files /dev/null and b/assets/textures/cockpit/cockpit_cannon.bmp differ diff --git a/assets/textures/cockpit/cockpit_cannon_left.bmp b/assets/textures/cockpit/cockpit_cannon_left.bmp new file mode 100644 index 0000000..fb86b4a Binary files /dev/null and b/assets/textures/cockpit/cockpit_cannon_left.bmp differ diff --git a/assets/textures/cockpit/cockpit_cannon_right.bmp b/assets/textures/cockpit/cockpit_cannon_right.bmp new file mode 100644 index 0000000..9a1193f Binary files /dev/null and b/assets/textures/cockpit/cockpit_cannon_right.bmp differ diff --git a/assets/textures/cockpit/cockpit_destroyed.bmp b/assets/textures/cockpit/cockpit_destroyed.bmp new file mode 100644 index 0000000..416448b Binary files /dev/null and b/assets/textures/cockpit/cockpit_destroyed.bmp differ diff --git a/assets/textures/cockpit/cockpit_fire.bmp b/assets/textures/cockpit/cockpit_fire.bmp new file mode 100644 index 0000000..5efd6d7 Binary files /dev/null and b/assets/textures/cockpit/cockpit_fire.bmp differ diff --git a/assets/textures/cockpit/cockpit_fire_left.bmp b/assets/textures/cockpit/cockpit_fire_left.bmp new file mode 100644 index 0000000..1853644 Binary files /dev/null and b/assets/textures/cockpit/cockpit_fire_left.bmp differ diff --git a/assets/textures/cockpit/cockpit_fire_right.bmp b/assets/textures/cockpit/cockpit_fire_right.bmp new file mode 100644 index 0000000..d465c37 Binary files /dev/null and b/assets/textures/cockpit/cockpit_fire_right.bmp differ diff --git a/assets/textures/cockpit/cockpit_impact.bmp b/assets/textures/cockpit/cockpit_impact.bmp new file mode 100644 index 0000000..de5448f Binary files /dev/null and b/assets/textures/cockpit/cockpit_impact.bmp differ diff --git a/assets/textures/crosshair.png b/assets/textures/crosshair.png new file mode 100644 index 0000000..2383545 Binary files /dev/null and b/assets/textures/crosshair.png differ diff --git a/assets/textures/ground.bmp b/assets/textures/ground.bmp new file mode 100644 index 0000000..48ca6f6 Binary files /dev/null and b/assets/textures/ground.bmp differ diff --git a/assets/textures/ground_2.bmp b/assets/textures/ground_2.bmp new file mode 100644 index 0000000..6ae18c4 Binary files /dev/null and b/assets/textures/ground_2.bmp differ diff --git a/assets/textures/gui_background.png b/assets/textures/gui_background.png new file mode 100644 index 0000000..a0fc4c9 Binary files /dev/null and b/assets/textures/gui_background.png differ diff --git a/assets/textures/gui_background_2.png b/assets/textures/gui_background_2.png new file mode 100644 index 0000000..7ac9a0e Binary files /dev/null and b/assets/textures/gui_background_2.png differ diff --git a/assets/textures/mech/explosion.png b/assets/textures/mech/explosion.png new file mode 100644 index 0000000..a9f280a Binary files /dev/null and b/assets/textures/mech/explosion.png differ diff --git a/assets/textures/mech/mech.bmp b/assets/textures/mech/mech.bmp new file mode 100644 index 0000000..c1b75a5 Binary files /dev/null and b/assets/textures/mech/mech.bmp differ diff --git a/assets/textures/mech/mech_cannon_fire.bmp b/assets/textures/mech/mech_cannon_fire.bmp new file mode 100644 index 0000000..e2f5c31 Binary files /dev/null and b/assets/textures/mech/mech_cannon_fire.bmp differ diff --git a/assets/textures/mech/mech_cannon_left.bmp b/assets/textures/mech/mech_cannon_left.bmp new file mode 100644 index 0000000..3f77b16 Binary files /dev/null and b/assets/textures/mech/mech_cannon_left.bmp differ diff --git a/assets/textures/mech/mech_cannon_right.bmp b/assets/textures/mech/mech_cannon_right.bmp new file mode 100644 index 0000000..e8940b9 Binary files /dev/null and b/assets/textures/mech/mech_cannon_right.bmp differ diff --git a/assets/textures/mech/mech_fire.bmp b/assets/textures/mech/mech_fire.bmp new file mode 100644 index 0000000..7f12a1e Binary files /dev/null and b/assets/textures/mech/mech_fire.bmp differ diff --git a/assets/textures/mech/mech_fire_left.bmp b/assets/textures/mech/mech_fire_left.bmp new file mode 100644 index 0000000..218950b Binary files /dev/null and b/assets/textures/mech/mech_fire_left.bmp differ diff --git a/assets/textures/mech/mech_fire_right.bmp b/assets/textures/mech/mech_fire_right.bmp new file mode 100644 index 0000000..8474994 Binary files /dev/null and b/assets/textures/mech/mech_fire_right.bmp differ diff --git a/assets/textures/mech/mech_hit.bmp b/assets/textures/mech/mech_hit.bmp new file mode 100644 index 0000000..1e67764 Binary files /dev/null and b/assets/textures/mech/mech_hit.bmp differ diff --git a/assets/textures/mech/mech_hit_center.bmp b/assets/textures/mech/mech_hit_center.bmp new file mode 100644 index 0000000..1e67764 Binary files /dev/null and b/assets/textures/mech/mech_hit_center.bmp differ diff --git a/assets/textures/mech/mech_hit_cockpit.bmp b/assets/textures/mech/mech_hit_cockpit.bmp new file mode 100644 index 0000000..6e70a7d Binary files /dev/null and b/assets/textures/mech/mech_hit_cockpit.bmp differ diff --git a/assets/textures/mech/mech_hit_left_arm.bmp b/assets/textures/mech/mech_hit_left_arm.bmp new file mode 100644 index 0000000..7118085 Binary files /dev/null and b/assets/textures/mech/mech_hit_left_arm.bmp differ diff --git a/assets/textures/mech/mech_hit_left_leg.bmp b/assets/textures/mech/mech_hit_left_leg.bmp new file mode 100644 index 0000000..476ba7c Binary files /dev/null and b/assets/textures/mech/mech_hit_left_leg.bmp differ diff --git a/assets/textures/mech/mech_hit_right_arm.bmp b/assets/textures/mech/mech_hit_right_arm.bmp new file mode 100644 index 0000000..beb62ed Binary files /dev/null and b/assets/textures/mech/mech_hit_right_arm.bmp differ diff --git a/assets/textures/mech/mech_hit_right_leg.bmp b/assets/textures/mech/mech_hit_right_leg.bmp new file mode 100644 index 0000000..69702a2 Binary files /dev/null and b/assets/textures/mech/mech_hit_right_leg.bmp differ diff --git a/assets/textures/mech_repair.png b/assets/textures/mech_repair.png new file mode 100644 index 0000000..27c1bbc Binary files /dev/null and b/assets/textures/mech_repair.png differ diff --git a/assets/textures/mech_repair_spark_1.png b/assets/textures/mech_repair_spark_1.png new file mode 100644 index 0000000..75f5276 Binary files /dev/null and b/assets/textures/mech_repair_spark_1.png differ diff --git a/assets/textures/mech_repair_spark_2.png b/assets/textures/mech_repair_spark_2.png new file mode 100644 index 0000000..95220cf Binary files /dev/null and b/assets/textures/mech_repair_spark_2.png differ diff --git a/assets/textures/mech_status.bmp b/assets/textures/mech_status.bmp new file mode 100644 index 0000000..1f8f2ea Binary files /dev/null and b/assets/textures/mech_status.bmp differ diff --git a/assets/textures/menu_background.png b/assets/textures/menu_background.png new file mode 100644 index 0000000..0ddb3fb Binary files /dev/null and b/assets/textures/menu_background.png differ diff --git a/assets/textures/mob_icon.png b/assets/textures/mob_icon.png new file mode 100644 index 0000000..cf0c3af Binary files /dev/null and b/assets/textures/mob_icon.png differ diff --git a/assets/textures/player_icon.png b/assets/textures/player_icon.png new file mode 100644 index 0000000..bbf427e Binary files /dev/null and b/assets/textures/player_icon.png differ diff --git a/assets/textures/sky.bmp b/assets/textures/sky.bmp new file mode 100644 index 0000000..2974e26 Binary files /dev/null and b/assets/textures/sky.bmp differ diff --git a/assets/textures/sky_2.png b/assets/textures/sky_2.png new file mode 100644 index 0000000..cc46993 Binary files /dev/null and b/assets/textures/sky_2.png differ diff --git a/assets/textures/target_gui_background.png b/assets/textures/target_gui_background.png new file mode 100644 index 0000000..307e930 Binary files /dev/null and b/assets/textures/target_gui_background.png differ diff --git a/assets/textures/target_icon.png b/assets/textures/target_icon.png new file mode 100644 index 0000000..867862e Binary files /dev/null and b/assets/textures/target_icon.png differ diff --git a/assets/textures/term.bmp b/assets/textures/term.bmp new file mode 100644 index 0000000..8ff9d72 Binary files /dev/null and b/assets/textures/term.bmp differ diff --git a/assets/textures/tree.bmp b/assets/textures/tree.bmp new file mode 100644 index 0000000..b9ee5b7 Binary files /dev/null and b/assets/textures/tree.bmp differ diff --git a/assets/textures/tree_2.png b/assets/textures/tree_2.png new file mode 100644 index 0000000..fb56c35 Binary files /dev/null and b/assets/textures/tree_2.png differ diff --git a/assets/textures/tree_3.png b/assets/textures/tree_3.png new file mode 100644 index 0000000..35ae26e Binary files /dev/null and b/assets/textures/tree_3.png differ diff --git a/assets/textures/tree_4.png b/assets/textures/tree_4.png new file mode 100644 index 0000000..b06495c Binary files /dev/null and b/assets/textures/tree_4.png differ diff --git a/assets/textures/wall.bmp b/assets/textures/wall.bmp new file mode 100644 index 0000000..64881ab Binary files /dev/null and b/assets/textures/wall.bmp differ diff --git a/assets/textures/wall_2.bmp b/assets/textures/wall_2.bmp new file mode 100644 index 0000000..18a37fa Binary files /dev/null and b/assets/textures/wall_2.bmp differ diff --git a/assets/textures/wall_icon.png b/assets/textures/wall_icon.png new file mode 100644 index 0000000..38eb512 Binary files /dev/null and b/assets/textures/wall_icon.png differ diff --git a/bindings.list b/bindings.list new file mode 100644 index 0000000..10f0ae1 --- /dev/null +++ b/bindings.list @@ -0,0 +1,16 @@ +throttle_up:W +throttle_down:S +turn_left:A +turn_right:D +look_left:Left +look_right:Right +look_up:Up +look_down:Down +fire_guns:Space +fire_cannon:LControl +lock_target:T +select_component:C +map:M +show_tutorial:F1 +show_keys:F2 +show_fps:F3 diff --git a/compile_linux.sh b/compile_linux.sh new file mode 100755 index 0000000..db0ad1d --- /dev/null +++ b/compile_linux.sh @@ -0,0 +1,2 @@ +#! /bin/bash +g++ main.cpp $PWD/src/settings_menu.cpp $PWD/src/cockpit.cpp $PWD/src/settings.cpp $PWD/src/market_menu.cpp $PWD/src/tutorial.cpp $PWD/src/key_bindings.cpp $PWD/src/assets.cpp $PWD/src/calc_helper.cpp $PWD/src/entity.cpp $PWD/src/file_handler.cpp $PWD/src/hud.cpp $PWD/src/intermission_menu.cpp $PWD/src/main_menu.cpp $PWD/src/mech.cpp $PWD/src/player_controller.cpp $PWD/src/world_generator.cpp -Iinclude -o SFMechSimulator -lsfml-graphics -lsfml-audio -lsfml-window -lsfml-system diff --git a/compile_mac.sh b/compile_mac.sh new file mode 100755 index 0000000..15dcd90 --- /dev/null +++ b/compile_mac.sh @@ -0,0 +1,3 @@ +#! /bin/bash + +g++ -std=c++11 -F/Library/Frameworks -Iinclude -framework sfml-window -framework sfml-graphics -framework sfml-audio -framework sfml-system main.cpp $PWD/src/settings_menu.cpp $PWD/src/cockpit.cpp $PWD/src/settings.cpp $PWD/src/market_menu.cpp $PWD/src/tutorial.cpp $PWD/src/key_bindings.cpp $PWD/src/assets.cpp $PWD/src/calc_helper.cpp $PWD/src/entity.cpp $PWD/src/file_handler.cpp $PWD/src/hud.cpp $PWD/src/intermission_menu.cpp $PWD/src/main_menu.cpp $PWD/src/mech.cpp $PWD/src/player_controller.cpp $PWD/src/world_generator.cpp -o SFMechSimulator diff --git a/compile_windows.bat b/compile_windows.bat new file mode 100644 index 0000000..393e0cf --- /dev/null +++ b/compile_windows.bat @@ -0,0 +1,18 @@ +g++.exe -Wall -O2 -IC:\SFML-2.5.1\include -Iinclude -Isrc -c C:\SFMechSimulator\main.cpp -o obj\Release\main.o +g++.exe -Wall -O2 -IC:\SFML-2.5.1\include -Iinclude -Isrc -c C:\SFMechSimulator\src\assets.cpp -o obj\Release\src\assets.o +g++.exe -Wall -O2 -IC:\SFML-2.5.1\include -Iinclude -Isrc -c C:\SFMechSimulator\src\calc_helper.cpp -o obj\Release\src\calc_helper.o +g++.exe -Wall -O2 -IC:\SFML-2.5.1\include -Iinclude -Isrc -c C:\SFMechSimulator\src\cockpit.cpp -o obj\Release\src\cockpit.o +g++.exe -Wall -O2 -IC:\SFML-2.5.1\include -Iinclude -Isrc -c C:\SFMechSimulator\src\entity.cpp -o obj\Release\src\entity.o +g++.exe -Wall -O2 -IC:\SFML-2.5.1\include -Iinclude -Isrc -c C:\SFMechSimulator\src\file_handler.cpp -o obj\Release\src\file_handler.o +g++.exe -Wall -O2 -IC:\SFML-2.5.1\include -Iinclude -Isrc -c C:\SFMechSimulator\src\hud.cpp -o obj\Release\src\hud.o +g++.exe -Wall -O2 -IC:\SFML-2.5.1\include -Iinclude -Isrc -c C:\SFMechSimulator\src\intermission_menu.cpp -o obj\Release\src\intermission_menu.o +g++.exe -Wall -O2 -IC:\SFML-2.5.1\include -Iinclude -Isrc -c C:\SFMechSimulator\src\key_bindings.cpp -o obj\Release\src\key_bindings.o +g++.exe -Wall -O2 -IC:\SFML-2.5.1\include -Iinclude -Isrc -c C:\SFMechSimulator\src\main_menu.cpp -o obj\Release\src\main_menu.o +g++.exe -Wall -O2 -IC:\SFML-2.5.1\include -Iinclude -Isrc -c C:\SFMechSimulator\src\market_menu.cpp -o obj\Release\src\market_menu.o +g++.exe -Wall -O2 -IC:\SFML-2.5.1\include -Iinclude -Isrc -c C:\SFMechSimulator\src\mech.cpp -o obj\Release\src\mech.o +g++.exe -Wall -O2 -IC:\SFML-2.5.1\include -Iinclude -Isrc -c C:\SFMechSimulator\src\player_controller.cpp -o obj\Release\src\player_controller.o +g++.exe -Wall -O2 -IC:\SFML-2.5.1\include -Iinclude -Isrc -c C:\SFMechSimulator\src\settings.cpp -o obj\Release\src\settings.o +g++.exe -Wall -O2 -IC:\SFML-2.5.1\include -Iinclude -Isrc -c C:\SFMechSimulator\src\settings_menu.cpp -o obj\Release\src\settings_menu.o +g++.exe -Wall -O2 -IC:\SFML-2.5.1\include -Iinclude -Isrc -c C:\SFMechSimulator\src\tutorial.cpp -o obj\Release\src\tutorial.o +g++.exe -Wall -O2 -IC:\SFML-2.5.1\include -Iinclude -Isrc -c C:\SFMechSimulator\src\world_generator.cpp -o obj\Release\src\world_generator.o +g++.exe -LC:\SFML-2.5.1\lib -o bin\Release\SFMechSimulator.exe obj\Release\main.o obj\Release\src\assets.o obj\Release\src\calc_helper.o obj\Release\src\cockpit.o obj\Release\src\entity.o obj\Release\src\file_handler.o obj\Release\src\hud.o obj\Release\src\intermission_menu.o obj\Release\src\key_bindings.o obj\Release\src\main_menu.o obj\Release\src\market_menu.o obj\Release\src\mech.o obj\Release\src\player_controller.o obj\Release\src\settings.o obj\Release\src\settings_menu.o obj\Release\src\tutorial.o obj\Release\src\world_generator.o -s -lmingw32 -luser32 -lgdi32 -lwinmm -ldxguid -lsfml-graphics -lsfml-audio -lsfml-window -lsfml-system -mwindows diff --git a/credits.txt b/credits.txt new file mode 100644 index 0000000..61c0726 --- /dev/null +++ b/credits.txt @@ -0,0 +1,30 @@ +main menu music: https://freesound.org/people/LittleRobotSoundFactory/sounds/274169/ +intermission music: https://freesound.org/people/szegvari/sounds/560746/ +mission music: https://freesound.org/people/FoolBoyMedia/sounds/270366/ +victory sound: https://freesound.org/people/joshuaempyre/sounds/404024/ + +gun sound: https://freesound.org/people/CJDeets/sounds/476740/ +cannon sound: https://freesound.org/people/Kneeling/sounds/448002/ +power up sound: https://freesound.org/people/Breviceps/sounds/557593/ +power down sound: https://freesound.org/people/qubodup/sounds/222372/ +stomp sound: https://freesound.org/people/studiomandragore/sounds/401628/ +crash sound: https://freesound.org/people/qubodup/sounds/182429/ +impact sound: https://freesound.org/people/Oddworld/sounds/75328/ +hydraulic sound: https://freesound.org/people/eardeer/sounds/385083/ + +mech sprite: https://opengameart.org/content/unit-666-mech +dead tree sprites: https://opengameart.org/content/knarled-trees +green tree sprites: https://opengameart.org/content/tree-collection-v26-bleeds-game-art +cannon effect: https://opengameart.org/content/blue-fire-effect +small explosion sprites: https://gaph.artstation.com/ +large explosion sprite: https://www.freepngimg.com/png/31556-atomic-explosion-transparent-background +menu background and sky: https://free-images.com/lg/5434/planet_earth_moon_science.jpg +welder: https://opengameart.org/content/16-bit-alien +welding sparks: https://opengameart.org/content/spark-particles-set-of-8 +skull and bones: https://openclipart.org/image/400px/1010 +sky: https://svs.gsfc.nasa.gov/3895 +moon: https://www.publicdomainpictures.net/en/view-image.php?image=44955&picture=full-moon-at-midnight-close-up +blue sky: https://www.pexels.com/photo/blue-and-white-sky-with-stars-4737484/ + +orbitron font: https://www.1001freefonts.com/orbitron.font +exoplanetaria font: https://www.fontspace.com/exoplanetaria-font-f41401 diff --git a/include/assets.h b/include/assets.h new file mode 100644 index 0000000..84b5f4c --- /dev/null +++ b/include/assets.h @@ -0,0 +1,182 @@ +#ifndef ASSETS_H +#define ASSETS_H + +#include +#include + +class assets +{ + public: + // Sounds + sf::SoundBuffer gun_sound_buffer; + sf::Sound gun_sound; + + sf::SoundBuffer cannon_sound_buffer; + sf::Sound cannon_sound; + + sf::SoundBuffer explo_sound_buffer; + sf::Sound explosion_sound; + + sf::SoundBuffer hydraulic_sound_buffer; + sf::Sound hydraulic_sound; + + sf::SoundBuffer stomp_sound_buffer; + sf::Sound stomp_sound; + + sf::SoundBuffer crash_sound_buffer; + sf::Sound crash_sound; + + sf::SoundBuffer impact_sound_buffer; + sf::Sound impact_sound; + + sf::SoundBuffer power_down_sound_buffer; + sf::Sound power_down_sound; + + sf::SoundBuffer power_up_sound_buffer; + sf::Sound power_up_sound; + + sf::SoundBuffer purchase_sound_buffer; + sf::Sound purchase_sound; + + sf::SoundBuffer main_menu_music_buffer; + sf::Sound main_menu_music; + + sf::SoundBuffer intermission_music_buffer; + sf::Sound intermission_music; + + sf::SoundBuffer mission_music_buffer; + sf::Sound mission_music; + + sf::SoundBuffer victory_sound_buffer; + sf::Sound victory_sound; + + // Textures + sf::Texture mech_status_texture; + sf::Texture mech_texture; + sf::Texture mech_fire_guns_texture; + sf::Texture mech_fire_guns_left_texture; + sf::Texture mech_fire_guns_right_texture; + sf::Texture mech_fire_cannons_texture; + sf::Texture mech_fire_cannons_left_texture; + sf::Texture mech_fire_cannons_right_texture; + sf::Texture mech_hit_center_texture; + sf::Texture mech_hit_left_leg_texture; + sf::Texture mech_hit_right_leg_texture; + sf::Texture mech_hit_left_arm_texture; + sf::Texture mech_hit_right_arm_texture; + sf::Texture mech_hit_cockpit_texture; + std::vector mech_textures; + + sf::Texture cockpit_texture; + sf::Texture cockpit_fire_texture; + sf::Texture cockpit_fire_left_texture; + sf::Texture cockpit_fire_right_texture; + sf::Texture cockpit_cannon_texture; + sf::Texture cockpit_cannon_left_texture; + sf::Texture cockpit_cannon_right_texture; + sf::Texture cockpit_impact_texture; + sf::Texture cockpit_destroyed_texture; + + sf::Texture explosion_texture; + sf::Texture crosshair_texture; + sf::Texture ground_texture; + sf::Texture ground_2_texture; + sf::Sprite ground_sprite; + sf::Texture sky_texture; + sf::Texture sky_2_texture; + sf::Texture wall_texture; + sf::Texture wall_2_texture; + sf::Texture tree_texture; + sf::Texture tree_2_texture; + sf::Texture tree_3_texture; + sf::Texture tree_4_texture; + sf::Texture player_icon_texture; + sf::Texture mob_icon_texture; + sf::Texture target_icon_texture; + sf::Texture wall_icon_texture; + + sf::Texture gui_background_texture; + sf::Texture gui_background_2_texture; + sf::Texture target_gui_background_texture; + + sf::Texture menu_background_texture; + sf::Texture menu_mech_texture; + sf::Texture menu_mech_spark_1_texture; + sf::Texture menu_mech_spark_2_texture; + sf::Texture term_texture; + + sf::Texture start_game_button_texture; + sf::Texture start_game_button_hover_texture; + sf::Texture main_menu_button_texture; + sf::Texture main_menu_button_hover_texture; + sf::Texture save_game_button_texture; + sf::Texture save_game_button_hover_texture; + sf::Texture load_game_button_texture; + sf::Texture load_game_button_hover_texture; + sf::Texture next_mission_button_texture; + sf::Texture next_mission_button_hover_texture; + sf::Texture repair_button_texture; + sf::Texture repair_button_hover_texture; + sf::Texture market_button_texture; + sf::Texture market_button_hover_texture; + sf::Texture exit_game_button_texture; + sf::Texture exit_game_button_hover_texture; + sf::Texture create_new_button_texture; + sf::Texture create_new_button_hover_texture; + sf::Texture cancel_button_texture; + sf::Texture cancel_button_hover_texture; + sf::Texture options_button_texture; + sf::Texture options_button_hover_texture; + + // Sprites + sf::Sprite cockpit_sprite; + sf::Sprite sky_sprite; + sf::Sprite map_sprite; + sf::Sprite term_sprite; + sf::Sprite crosshair_sprite; + sf::Sprite player_icon; + sf::Sprite mob_icon; + sf::Sprite wall_icon; + sf::Sprite target_icon; + + sf::Sprite start_game_button_sprite; + sf::Sprite main_menu_button_sprite; + sf::Sprite save_game_button_sprite; + sf::Sprite create_new_button_sprite; + sf::Sprite cancel_button_sprite; + sf::Sprite load_game_button_sprite; + sf::Sprite options_button_sprite; + sf::Sprite next_mission_button_sprite; + sf::Sprite repair_button_sprite; + sf::Sprite market_button_sprite; + sf::Sprite exit_game_button_sprite; + sf::Sprite menu_background_sprite; + sf::Sprite menu_mech_sprite; + + // Fonts + sf::Font orbitron; + sf::Font exoplanetaria; + + // Text Objects + sf::Text notice; + sf::Text keys; + sf::Text fps_counter; + sf::Text throttle_display; + sf::Text torso_display; + sf::Text input_text; + sf::Text mech_status; + sf::Text target_status; + sf::Text target_info; + + void init(std::string cwd); + + private: + void load_sound_buffers(std::string cwd); + void load_textures(std::string cwd); + void load_fonts(std::string cwd); + void init_sounds(); + void init_sprites(); + void init_text(); +}; + +#endif // ASSETS_H diff --git a/include/calc_helper.h b/include/calc_helper.h new file mode 100644 index 0000000..bdc7b01 --- /dev/null +++ b/include/calc_helper.h @@ -0,0 +1,11 @@ +#ifndef CALC_HELPER_H +#define CALC_HELPER_H + +#include + +float get_angle(sf::Vector2f v1, sf::Vector2f v2); +float get_distance(sf::Vector2f v1, sf::Vector2f v2); +sf::Vector2f get_midpoint(sf::Vector2f v1, sf::Vector2f v2); +std::vector x_sort(std::vector vectors, int total); + +#endif // CALC_HELPER_H diff --git a/include/cockpit.h b/include/cockpit.h new file mode 100644 index 0000000..40eaafa --- /dev/null +++ b/include/cockpit.h @@ -0,0 +1,10 @@ +#ifndef COCKPIT_H +#define COCKPIT_H + +#include +#include +#include + +void draw_cockpit(sf::RenderWindow &window, assets &resources, player_controller &pc, bool took_damage); + +#endif // COCKPIT_H diff --git a/include/entity.h b/include/entity.h new file mode 100644 index 0000000..f73754b --- /dev/null +++ b/include/entity.h @@ -0,0 +1,42 @@ +#ifndef ENTITY_H +#define ENTITY_H + +#include +#include +#include +#include + +class entity +{ + public: + float draw_x; + float draw_y; + float move_x; + float move_y; + float distance; + float old_pos; + float think_timer; + bool visible; + bool firing; + bool dying; + bool dead; + bool init; + int id; + int targeted_component; + sf::Sprite sprite; + sf::Sprite icon; + sf::Vector2f position; + std::string type; + std::string sub_type; + std::string components [7]; + entity(); + mech entity_mech; + void fire_weapons(assets &resources); + void update(sf::Vector2f camera_pos, bool maze); + + private: + bool wall_blocking(sf::Vector2f camera_pos, bool maze); + void avoid_walls(bool maze); +}; + +#endif // ENTITY_H diff --git a/include/file_handler.h b/include/file_handler.h new file mode 100644 index 0000000..d427521 --- /dev/null +++ b/include/file_handler.h @@ -0,0 +1,11 @@ +#ifndef FILE_HANDLER_H +#define FILE_HANDLER_H + +#include +#include + +std::string get_file_contents(std::string file_path); +std::string write_to_file(std::string file_path, std::string data); +std::string append_file(std::string file_path, std::string data); + +#endif diff --git a/include/hud.h b/include/hud.h new file mode 100644 index 0000000..25f743f --- /dev/null +++ b/include/hud.h @@ -0,0 +1,24 @@ +#ifndef HUD_H +#define HUD_H + +#include +#include +#include +#include + +class hud +{ + public: + std::string notice; + bool show_notice; + float notice_timer; + void init(assets &resources); + void display_notice(sf::RenderWindow &window, std::string notice, float frame_time); + void draw_hud(sf::RenderWindow &window, float frame_time, int target_id, float speed, float torso_angle, mech &player_mech, mech &target_mech); + + private: + assets resources; + void draw_mech(float x_pos, mech &mech_to_draw, sf::RenderWindow &window); +}; + +#endif // HUD_H diff --git a/include/intermission_menu.h b/include/intermission_menu.h new file mode 100644 index 0000000..923dbb1 --- /dev/null +++ b/include/intermission_menu.h @@ -0,0 +1,56 @@ +#ifndef INTERMISSION_MENU_H +#define INTERMISSION_MENU_H + +#include +#include +#include +#include +#include +#include +#include + +class intermission_menu +{ + public: + intermission_menu(); + market_menu market; + bool start_game; + bool return_to_main; + void init(std::string cwd, assets &resources); + bool draw_menu(sf::RenderWindow &window, player_controller &pc, float frame_time); + + private: + assets resources; + settings_menu s_menu; + sf::Vector2i mouse_position; + sf::String input; + std::string cwd; + std::string notice; + std::string get_save_data(player_controller &pc); + std::vector saved_game_buttons; + std::vector delete_save_buttons; + std::vector delete_save_labels; + std::vector saved_game_labels; + int kp; + float notice_timer; + float spark_timer; + bool create_save_prompt_open; + bool save_prompt_open; + bool load_prompt_open; + bool repair_prompt_open; + bool show_notice; + bool prompt_displayed(); + void create_save(player_controller &pc); + void save_game(player_controller &pc, int i); + void display_notice(sf::RenderWindow &window, std::string notice, float frame_time); + void reset_game(player_controller &pc); + void load_game(std::string cwd, std::string file, player_controller &pc); + void delete_save_game(int i); + void draw_saved_game_buttons(sf::RenderWindow &window); + void draw_delete_buttons(sf::RenderWindow &window); + void draw_save_menu(sf::RenderWindow &window); + void draw_load_menu(sf::RenderWindow &window); + void draw_repair_menu(sf::RenderWindow &window, player_controller &pc); +}; + +#endif // INTERMISSION_MENU_H diff --git a/include/key_bindings.h b/include/key_bindings.h new file mode 100644 index 0000000..946ccaf --- /dev/null +++ b/include/key_bindings.h @@ -0,0 +1,16 @@ +#ifndef KEY_BINDINGS_H +#define KEY_BINDINGS_H + +#include +#include + +class key_bindings +{ + public: + std::map bindings; + void load(std::string cwd); + private: + std::map keys; +}; + +#endif // KEY_BINDINGS_H diff --git a/include/main_menu.h b/include/main_menu.h new file mode 100644 index 0000000..8416419 --- /dev/null +++ b/include/main_menu.h @@ -0,0 +1,38 @@ +#ifndef MAIN_MENU_H +#define MAIN_MENU_H + +#include +#include +#include +#include +#include + +class main_menu +{ + public: + bool start_game; + bool game_loaded; + void init(std::string cwd, assets &resources); + bool draw_menu(sf::RenderWindow &window, player_controller &pc, float frame_time); + + private: + assets resources; + settings_menu s_menu; + sf::Vector2i mouse_position; + bool load_prompt_open; + bool show_load_notice; + bool show_delete_notice; + float delete_notice_timer; + float load_notice_timer; + float spark_timer; + std::string cwd; + std::vector load_game_buttons; + std::vector load_game_labels; + std::vector delete_save_buttons; + std::vector delete_save_labels; + void load_game(std::string cwd, std::string file, player_controller &pc); + void delete_save_game(int i); + void draw_load_menu(sf::RenderWindow &window); +}; + +#endif // MAIN_MENU_H diff --git a/include/market_menu.h b/include/market_menu.h new file mode 100644 index 0000000..05cc9a6 --- /dev/null +++ b/include/market_menu.h @@ -0,0 +1,80 @@ +#ifndef MARKET_MENU_H +#define MARKET_MENU_H + +#include +#include +#include + +class market_menu +{ + public: + market_menu(); + + struct item + { + std::string name; + std::string type; + int level; + int modifier; + int secondary_modifier; + int price; + }; + + std::vector item_worth; + std::string notice; + bool visible; + bool show_notice; + void generate_items(); + void init(std::string cwd); + void handle_events(sf::Event event, player_controller &pc, sf::Vector2i mouse_position); + void draw_menu(sf::RenderWindow &window, player_controller &pc, sf::Vector2i mouse_position); + + private: + sf::Font market_font; + sf::Texture gui_background_texture; + sf::VertexArray exit_button; + + sf::SoundBuffer purchase_sound_buffer; + sf::Sound purchase_sound; + + std::vector sell_categories; + + std::vector guns; + std::vector cannons; + std::vector reactors; + std::vector coolers; + std::vector cockpits; + std::vector arms; + std::vector legs; + + std::vector sell_buttons; + std::vector gun_buttons; + std::vector cannon_buttons; + std::vector reactor_buttons; + std::vector cooler_buttons; + std::vector cockpit_buttons; + std::vector arm_buttons; + std::vector leg_buttons; + + std::vector sell_button_labels; + std::vector gun_button_labels; + std::vector cannon_button_labels; + std::vector reactor_button_labels; + std::vector cooler_button_labels; + std::vector cockpit_button_labels; + std::vector arm_button_labels; + std::vector leg_button_labels; + + std::vector gun_descriptions; + std::vector cannon_descriptions; + std::vector reactor_descriptions; + std::vector cooler_descriptions; + std::vector cockpit_descriptions; + std::vector arm_descriptions; + std::vector leg_descriptions; + + void purchase_item(player_controller &pc, item item_bought); + void sell_item(player_controller &pc, std::string category); +}; + +#endif // MARKET_MENU_H diff --git a/include/mech.h b/include/mech.h new file mode 100644 index 0000000..c139941 --- /dev/null +++ b/include/mech.h @@ -0,0 +1,61 @@ +#ifndef MECH_H +#define MECH_H + +#include + +class mech +{ + public: + mech(); + + int weapon; + int weight; + + int reactor_integrity; + int cooler_integrity; + int left_leg_integrity; + int right_leg_integrity; + int left_arm_integrity; + int right_arm_integrity; + int cockpit_integrity; + int total_integrity(); + + int cooler_modifier; + int guns_modifier; + int cannons_modifier; + int max_reactor_integrity; + int max_cooler_integrity; + int max_left_leg_integrity; + int max_right_leg_integrity; + int max_left_arm_integrity; + int max_right_arm_integrity; + int max_cockpit_integrity; + int max_total_integrity(); + + std::string primary_weapon; + std::string secondary_weapon; + std::string reactor; + std::string cooler; + std::string left_leg; + std::string right_leg; + std::string left_arm; + std::string right_arm; + std::string cockpit; + + float heat; + float speed; + float damage_timer; + bool is_player; + bool power_down; + bool taking_damage; + bool can_move(); + bool can_fire(); + bool destroyed(); + bool left_arm_destroyed(); + bool right_arm_destroyed(); + void update(); + void repair(); + void take_damage(std::string target, float distance, int weapon); +}; + +#endif // MECH_H diff --git a/include/player_controller.h b/include/player_controller.h new file mode 100644 index 0000000..5c20280 --- /dev/null +++ b/include/player_controller.h @@ -0,0 +1,70 @@ +#ifndef PLAYER_CONTROLLER_H +#define PLAYER_CONTROLLER_H + +#include +#include +#include +#include +#include +#include +#include + +class player_controller +{ + public: + player_controller(); + key_bindings kb; + mech player_mech; + sf::Vector2f player_pos; + sf::Vector2f look_pos; + sf::Vector2f back_pos; + sf::Vector2f left_pos; + sf::Vector2f right_pos; + std::vector components; + int credits; + int credits_earned; + int targeted_component; + int target_id; + int enemy_id; + int mission; + bool guns_firing; + bool cannon_firing; + bool player_firing; + bool muzzle_flash; + bool cannon_flash; + bool hit_target; + bool turn_left; + bool turn_right; + bool look_left; + bool look_right; + bool look_up; + bool look_down; + float muzzle_flash_timer; + float cannon_flash_timer; + float look_offset; + float torso_angle; + void reset(); + void init(std::string cwd, assets &resources); + void collision_check(entity other, float view_range); + void fire_guns(std::vector &entities, int entity_count, float window_width); + void fire_cannon(std::vector &entities, int entity_count, float window_width); + void lock_target(std::vector &entities, int entity_count, float window_width); + void update(sf::RenderWindow &window, float frame_time); + void handle_events(sf::RenderWindow &window, sf::Event event); + void fixed_update(sf::Transformable player); + + private: + assets resources; + float stomp_timer; + float step_timer; + float mouse_move_timer; + float guns_timer; + float cannon_timer; + bool move_forward; + bool move_back; + bool throttle_up; + bool throttle_down; + bool mouse_moved; +}; + +#endif diff --git a/include/settings.h b/include/settings.h new file mode 100644 index 0000000..b6cd0fe --- /dev/null +++ b/include/settings.h @@ -0,0 +1,11 @@ +#ifndef SETTINGS_H +#define SETTINGS_H + +extern bool music; +extern bool invert_mouse; +extern double audio_volume; + +void save_settings(std::string cwd); +void load_settings(std::string cwd); + +#endif // SETTINGS_H diff --git a/include/settings_menu.h b/include/settings_menu.h new file mode 100644 index 0000000..2561e20 --- /dev/null +++ b/include/settings_menu.h @@ -0,0 +1,28 @@ +#ifndef SETTINGS_MENU_H +#define SETTINGS_MENU_H + +#include + +class settings_menu +{ + public: + bool visible; + bool in_game; + bool abort_mission; + bool abort_prompt_open; + void init(std::string cwd, assets &resources, bool in_game); + void handle_events(sf::Event event, sf::Vector2i mouse_position); + void draw_menu(sf::RenderWindow &window, sf::Vector2i mouse_position, float frame_time); + private: + assets resources; + std::string cwd; + std::vector buttons; + std::vector abort_buttons; + std::vector button_labels; + std::vector abort_button_labels; + std::vector button_values; + std::vector button_text; + std::vector abort_button_text; +}; + +#endif // SETTINGS_MENU_H diff --git a/include/tutorial.h b/include/tutorial.h new file mode 100644 index 0000000..01ccafa --- /dev/null +++ b/include/tutorial.h @@ -0,0 +1,23 @@ +#ifndef TUTORIAL_H +#define TUTORIAL_H + +#include +#include +#include + +class tutorial +{ + public: + int step; + bool visible; + tutorial(std::string cwd); + void draw_tutorial(sf::RenderWindow &window, bool show_keys, float speed, float torso_angle, float heat); + + private: + sf::Texture gui_background_texture; + sf::Sprite gui_background_sprite; + sf::Text tutorial_text; + sf::Font tutorial_font; +}; + +#endif // TUTORIAL_H diff --git a/include/world_generator.h b/include/world_generator.h new file mode 100644 index 0000000..fe06083 --- /dev/null +++ b/include/world_generator.h @@ -0,0 +1,26 @@ +#ifndef WORLD_GENERATOR_H +#define WORLD_GENERATOR_H + +#include +#include + +class world_generator +{ + public: + int theme; + int mission; + bool maze; + void generate_world(assets &resources, std::vector &entities, int entity_count); + void flip_walls_vertical(std::vector &entities, int entity_count, bool inverse); + void flip_walls_horizontal(std::vector &entities, int entity_count, bool inverse); + world_generator(); + + protected: + + private: + int wall_count; + int mob_count; + bool min_npc_spawned; +}; + +#endif // WORLD_GENERATOR_H diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..acda394 --- /dev/null +++ b/main.cpp @@ -0,0 +1,1033 @@ +#ifdef __cplusplus + #include +#else + #include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Class objects +assets resources; +player_controller pc; +world_generator world_gen; +main_menu m_menu; +settings_menu s_menu; +intermission_menu i_menu; +hud player_hud; + +// Player +sf::Transformable player; +sf::Transformable camera; + +// Graphics +int view_range = 60; +int camera_width = 60; +int ray_count = view_range * camera_width; +int wall_height = 40; +float fov_mod = 0; +float sky_x; +float sky_y; +std::vector camera_plane(camera_width); +std::vector rays(ray_count); +std::vector origins(ray_count); + +// Engine +int draw_count = 0; +int entity_count = 2000; +bool flipped_vertical; +bool flipped_horizontal; +bool show_fps; +float fps; +float frame_time; +float frame_timer; +std::string cwd; +std::vector entities(entity_count); +std::vector mobs(entity_count); + + +// Game +bool show_map = true; +bool show_keys = false; +bool bullet_hit = false; +bool main_menu = true; +bool intermission_menu = false; +bool game_started = false; +bool show_victory_notice = false; +float victory_timer; +float game_over_timer; +float map_scale = 0.25; +float bullet_delay; +float damage_timer; +bool taking_damage; +bool took_damage; + +// Framerate +std::chrono::high_resolution_clock::time_point fps_start; +std::chrono::high_resolution_clock::time_point fps_finish; + +void start_game() +{ + int rand_map = rand() % 100; + world_gen.maze = rand_map > 50 ? true : false; + int rand_theme = rand() % 100; + world_gen.theme = rand_theme > 50 ? 1 : 2; + world_gen.mission = pc.mission; + world_gen.generate_world(resources, entities, entity_count); + player.rotate(90); + camera.rotate(90); + game_started = true; + resources.power_up_sound.setVolume(50 * audio_volume); + resources.power_up_sound.play(); +} + +void complete_mission() +{ + player.setRotation(0); + camera.setRotation(0); + sky_x = 0; + sky_y = 0; + s_menu.visible = false; + pc.credits += (pc.credits_earned + 20000); + pc.reset(); + pc.mission++; + bullet_delay = 0; + game_started = false; + i_menu.market.generate_items(); + i_menu.start_game = false; + intermission_menu = true; +} + +void abort_mission() +{ + resources.mission_music.stop(); + player.setRotation(0); + camera.setRotation(0); + sky_x = 0; + sky_y = 0; + pc.reset(); + bullet_delay = 0; + game_started = false; + s_menu.visible = false; + intermission_menu = true; + i_menu.start_game = false; + s_menu.abort_mission = false; +} + +int main(int argc, char * argv[]) +{ + srand(time(NULL)); + + char cwd_char[PATH_MAX]; + if (getcwd(cwd_char, sizeof(cwd_char)) != NULL) + { + cwd = cwd_char; + } + + tutorial tut(cwd); + load_settings(cwd); + resources.init(cwd); + + pc.init(cwd, resources); + player_hud.init(resources); + m_menu.init(cwd, resources); + i_menu.init(cwd, resources); + s_menu.init(cwd, resources, true); + i_menu.market.generate_items(); + + sf::RenderWindow window; + + bool windowed = false; + + if (argc > 3) + { + if (strcmp(argv[1], "-window") == 0) + { + windowed = true; + unsigned int x = std::stoi(argv[2]) < 1280 ? 1280 : std::stoi(argv[2]); + unsigned int y = std::stoi(argv[3]) < 720 ? 720 : std::stoi(argv[3]); + window.create(sf::VideoMode(x, y), "SF Mech Simulator", sf::Style::Close); + } + } + + if (windowed == false) + { + window.create(sf::VideoMode(sf::VideoMode::getDesktopMode().width, sf::VideoMode::getDesktopMode().height), "SF Mech Simulator", sf::Style::Fullscreen); + } + + window.setFramerateLimit(60); + + // Start the game loop + while (window.isOpen()) + { + fps_start = std::chrono::high_resolution_clock::now(); + + if (main_menu == true) + { + window.setMouseCursorVisible(true); + main_menu = m_menu.draw_menu(window, pc, frame_time); + } + else if (m_menu.game_loaded == true) + { + m_menu.game_loaded = false; + i_menu.market.generate_items(); + intermission_menu = true; + } + else if (intermission_menu == true) + { + if (i_menu.return_to_main == false) + { + window.setMouseCursorVisible(true); + intermission_menu = i_menu.draw_menu(window, pc, frame_time); + } + else + { + i_menu.return_to_main = false; + m_menu.game_loaded = false; + m_menu.start_game = false; + intermission_menu = false; + game_started = false; + main_menu = true; + } + } + else + { + if (game_started == false) + { + start_game(); + } + + if (intermission_menu == false && pc.player_mech.power_down == false && show_victory_notice == false) + { + resources.mission_music.setVolume(50 * audio_volume); + + if (music == true && resources.mission_music.getStatus() != sf::Sound::Playing) + { + resources.mission_music.play(); + } + } + + window.setMouseCursorVisible(s_menu.visible); + + // Process events + sf::Event event; + while (window.pollEvent(event)) + { + if (s_menu.visible == true) + { + sf::Vector2i mouse_pos = sf::Mouse().getPosition(window); + s_menu.handle_events(event, mouse_pos); + } + else + { + pc.handle_events(window, event); + } + + if (event.type == sf::Event::Closed) + { + window.close(); + } + + if(event.type == sf::Event::KeyPressed) + { + if (pc.player_mech.destroyed() == false) + { + if(event.key.code == pc.kb.bindings["lock_target"]) + { + int j = 0; + for (int i = 0; i < entity_count; i++) + { + if (entities[i].type == "mob") + { + mobs[j] = entities[i]; + j++; + } + } + mobs.resize(j); + pc.lock_target(mobs, j, window.getView().getSize().x); + } + + if(event.key.code == pc.kb.bindings["map"]) + { + if (show_map == true) + { + if (map_scale == 0.25) + { + map_scale = 0.5; + } + else if (map_scale == 0.5) + { + map_scale = 0.75; + } + else if (map_scale == 0.75) + { + map_scale = 0.25; + show_map = !show_map; + } + } + else + { + show_map = !show_map; + } + } + + if (event.key.code == pc.kb.bindings["show_keys"]) + { + show_keys = !show_keys; + } + + if (event.key.code == pc.kb.bindings["show_tutorial"]) + { + tut.visible = !tut.visible; + } + + if (event.key.code == pc.kb.bindings["show_fps"]) + { + show_fps = !show_fps; + } + + if (event.key.code == sf::Keyboard::Escape && show_victory_notice == false) + { + s_menu.visible = !s_menu.visible; + } + + if (tut.visible && event.key.code == sf::Keyboard::Return) + { + tut.step = tut.step < 10 ? tut.step + 1 : 0; + } + } + } + } + + if (s_menu.visible == false) + { + // Walls need to be placed in descending order of distance to the camera + if (camera.getRotation() > 0 && camera.getRotation() < 180 && flipped_vertical == false) + { + world_gen.flip_walls_vertical(entities, entity_count, true); + flipped_vertical = true; + } + + if (camera.getRotation() >= 180 && flipped_vertical == true) + { + world_gen.flip_walls_vertical(entities, entity_count, false); + flipped_vertical = false; + } + + if ((camera.getRotation() >= 270 || camera.getRotation() <= 90) && flipped_horizontal == false) + { + world_gen.flip_walls_horizontal(entities, entity_count, true); + flipped_horizontal = true; + } + + if (camera.getRotation() > 90 && camera.getRotation() < 270 && flipped_horizontal == true) + { + world_gen.flip_walls_horizontal(entities, entity_count, false); + flipped_horizontal = false; + } + + if(pc.turn_left == true && pc.player_mech.can_move() == true) + { + player.rotate(-10 * frame_time); + camera.rotate(-10 * frame_time); + sky_x -= 100 * frame_time; + } + + if(pc.turn_right == true && pc.player_mech.can_move() == true) + { + player.rotate(10 * frame_time); + camera.rotate(10 * frame_time); + sky_x += 100 * frame_time; + } + + if (pc.look_left == true && pc.torso_angle > -89 && pc.player_mech.cockpit_integrity > 0) + { + camera.rotate(-10 * frame_time); + pc.torso_angle -= 10 * frame_time; + sky_x -= 100 * frame_time; + } + + if (pc.look_right == true && pc.torso_angle < 90 && pc.player_mech.cockpit_integrity > 0) + { + camera.rotate(10 * frame_time); + pc.torso_angle += 10 * frame_time; + sky_x += 100 * frame_time; + } + + // Vertical cockpit movement + if (pc.look_up == true) + { + if (pc.look_offset < 15 && pc.player_mech.cockpit_integrity > 0) + { + pc.look_offset += 5 * frame_time; + sky_y -= 50 * frame_time; + } + } + + if (pc.look_down == true && pc.player_mech.cockpit_integrity > 0) + { + if (pc.look_offset > -27) + { + pc.look_offset -= 5 * frame_time; + sky_y += 50 * frame_time; + } + } + + pc.update(window, frame_time); + + // Frame rate independent updates + frame_timer += frame_time; + if (frame_timer >= 0.1) + { + frame_timer = 0; + + pc.fixed_update(player); + + int mob_count = 0; + for (int i = 0; i < entity_count; i++) + { + if (entities[i].type == "mob" && entities[i].sub_type == "mech" && entities[i].dead == false) + { + mob_count++; + entities[i].update(camera_plane[camera_width / 2], world_gen.maze); + if (entities[i].firing == true && pc.player_mech.destroyed() == false && pc.enemy_id == 0) + { + entities[i].fire_weapons(resources); + taking_damage = true; + pc.enemy_id = i; + } + } + } + + if (mob_count == 0) + { + show_victory_notice = true; + } + + // Firing weapons + if (pc.player_firing == true) + { + int j = 0; + for (int i = 0; i < entity_count; i++) + { + if (entities[i].type == "mob") + { + mobs[j] = entities[i]; + j++; + } + } + mobs.resize(j); + + if (pc.player_mech.weapon == 1 && pc.guns_firing == false) + { + pc.fire_guns(mobs, j, window.getView().getSize().x); + } + + if (pc.player_mech.weapon == 5 && pc.cannon_firing == false) + { + pc.fire_cannon(mobs, j, window.getView().getSize().x); + } + } + + // Taking damage + if (taking_damage == true) + { + damage_timer++; + if (damage_timer >= 2 && damage_timer < 4) + { + entities[pc.enemy_id].sprite.setTexture(resources.mech_texture); + } + else if (damage_timer >= 4 && damage_timer < 6) + { + if (took_damage == false && pc.player_mech.destroyed() == false) + { + resources.impact_sound.setVolume(100 * audio_volume); + resources.impact_sound.play(); + + entity enemy = entities[pc.enemy_id]; + mech enemy_mech = entities[pc.enemy_id].entity_mech; + std::string component = enemy.components[enemy.targeted_component]; + int modifier = enemy_mech.weapon == 1 ? enemy_mech.guns_modifier : enemy_mech.cannons_modifier; + int damage = enemy_mech.weapon + modifier; + + if (enemy_mech.left_arm_destroyed() || enemy_mech.right_arm_destroyed()) + { + damage = damage / 2; + } + + pc.player_mech.take_damage(component, enemy.distance, damage); + took_damage = true; + } + } + else if (damage_timer >= 6) + { + taking_damage = false; + took_damage = false; + pc.enemy_id = 0; + damage_timer = 0; + } + } + + // Dealing damage + if (pc.hit_target == true) + { + bullet_delay++; + if (bullet_delay >= 4 && bullet_delay < 6 && bullet_hit == false) + { + if (entities[pc.target_id].entity_mech.destroyed() == true) + { + resources.explosion_sound.setVolume(50 * audio_volume); + resources.explosion_sound.play(); + entities[pc.target_id].sprite.setTexture(resources.explosion_texture); + } + else + { + resources.impact_sound.setVolume(50 * audio_volume); + resources.impact_sound.play(); + entities[pc.target_id].sprite.setTexture(resources.mech_textures[pc.targeted_component]); + } + bullet_hit = true; + } + else if (bullet_delay >= 6) + { + if (entities[pc.target_id].entity_mech.destroyed() == true) + { + entities[pc.target_id].visible = false; + entities[pc.target_id].dead = true; + pc.credits_earned += 10000; + } + else + { + entities[pc.target_id].sprite.setTexture(resources.mech_texture); + } + + mech player_mech = pc.player_mech; + entity target = entities[pc.target_id]; + std::string component = pc.components[pc.targeted_component]; + int modifier = player_mech.weapon == 1 ? player_mech.guns_modifier : player_mech.cannons_modifier; + int damage = player_mech.weapon + modifier; + + if (player_mech.left_arm_destroyed() || player_mech.right_arm_destroyed()) + { + damage = damage / 2; + } + + entities[pc.target_id].entity_mech.take_damage(component, target.distance, damage); + pc.hit_target = false; + bullet_hit = false; + bullet_delay = 0; + } + } + + if (pc.player_mech.destroyed() == true) + { + show_keys = false; + tut.visible = false; + s_menu.visible = false; + resources.cockpit_sprite.setTexture(resources.cockpit_destroyed_texture); + pc.player_mech.speed = 0; + + if (pc.player_mech.power_down == false) + { + resources.mission_music.stop(); + resources.power_down_sound.setVolume(50 * audio_volume); + resources.power_down_sound.play(); + pc.player_mech.power_down = true; + } + + game_over_timer++; + if (game_over_timer >= 100) + { + pc.player_mech.power_down = false; + game_over_timer = 0; + player.setRotation(0); + camera.setRotation(0); + sky_x = 0; + sky_y = 0; + pc.reset(); + bullet_delay = 0; + game_started = false; + intermission_menu = true; + i_menu.start_game = false; + } + } + else + { + resources.cockpit_sprite.setTexture(resources.cockpit_texture); + } + } + } + + // Camera plane creation + sf::Vector2f camera_pos; + camera_pos.x = player.getPosition().x + 10 * cos (camera.getRotation() * (3.14 / 180)); + camera_pos.y = player.getPosition().y + 10 * sin (camera.getRotation() * (3.14 / 180)); + + float pos = camera_width / 2; + for (int i = 0; i < camera_width / 2; i++) + { + camera_plane[i].x = camera_pos.x + pos * cos ((camera.getRotation() - 90) * (3.14 / 180)); + camera_plane[i].y = camera_pos.y + pos * sin ((camera.getRotation() - 90) * (3.14 / 180)); + pos --; + } + + pos = 0; + for (int i = camera_width / 2; i < camera_width; i++) + { + camera_plane[i].x = camera_pos.x + pos * cos ((camera.getRotation() + 90) * (3.14 / 180)); + camera_plane[i].y = camera_pos.y + pos * sin ((camera.getRotation() + 90) * (3.14 / 180)); + pos ++; + } + + // Raycasting + int k = 0; + for (int i = 0; i < view_range; i++) + { + for (int j = 0; j < camera_width; j++) + { + float angle = j; + if (j < camera_width / 2) + { + angle = (((camera_width / 2) - j) * -1) * fov_mod; + } + else + { + angle = (j - (camera_width / 2)) * fov_mod; + } + rays[k].x = camera_plane[j].x + i * cos ((camera.getRotation() + angle) * (3.14 / 180)); + rays[k].y = camera_plane[j].y + i * sin ((camera.getRotation() + angle) * (3.14 / 180)); + origins[k] = camera_plane[j]; + k++; + } + } + + // Determine entitites visible to the camera + for (int i = 0; i < entity_count; i++) + { + float distance = get_distance(camera_plane[camera_width / 2], entities[i].position); + if (distance < view_range) + { + int index; + float wall_ray = 0; + float near_ray = 0; + float dist = 100; + bool visible = false; + bool culling = false; + + for (int j = 0; j < ray_count; j++) + { + dist = (get_distance(rays[j], entities[i].position)); + if (dist < 1 && entities[i].dead == false) + { + pc.collision_check(entities[i], view_range); + entities[i].distance = get_distance(entities[i].position, origins[j]); + index = j; + visible = true; + + if (entities[i].type == "wall") + { + wall_ray = (float)j / (float)camera_width; + wall_ray = wall_ray - floor(wall_ray); + wall_ray = wall_ray * camera_width; + culling = true; + } + } + + if (culling == true) + { + near_ray = (float)j / (float)camera_width; + near_ray = near_ray - floor(near_ray); + near_ray = near_ray * camera_width; + if (near_ray > wall_ray - 5 && near_ray < wall_ray + 5) + { + rays[j] = origins[j]; + } + } + } + + if (visible == true) + { + // Center the entity between the closest raycasts, for smoother movement + float dist_to_left = (get_distance(rays[index - 1], entities[i].position)); + float dist_to_right = (get_distance(rays[index + 1], entities[i].position)); + int offset = dist_to_left < dist_to_right ? index - 1 : index + 1; + float offset_percent = ((float)offset) / (float)camera_width; + offset_percent = offset_percent - floor(offset_percent); + float screen_percent = (float)index / (float)camera_width; + screen_percent = screen_percent - floor(screen_percent); + float final_pos = (offset_percent + screen_percent) / 2; + float distance_moved = 0; + + if (entities[i].old_pos > final_pos) + { + distance_moved = entities[i].old_pos - final_pos; + } + else + { + distance_moved = final_pos - entities[i].old_pos; + } + + if (distance_moved > 0.02) + { + final_pos = (final_pos + entities[i].old_pos) / 2; + } + + float entity_draw_x = window.getView().getSize().x * final_pos; + entities[i].draw_x = entity_draw_x; + entities[i].old_pos = final_pos; + } + + entities[i].visible = visible; + } + else + { + entities[i].visible = false; + entities[i].old_pos = 0; + } + } + + // Position the player in the world + player.setPosition(pc.player_pos.x, pc.player_pos.y); + + // Clear screen + window.clear(); + + // Draw the sky + resources.sky_sprite.setTextureRect(sf::IntRect(sky_x, sky_y, window.getView().getSize().x, window.getView().getSize().y)); + if (world_gen.theme == 1) + { + resources.sky_sprite.setTexture(resources.sky_texture); + } + else + { + resources.sky_sprite.setTexture(resources.sky_2_texture); + } + window.draw(resources.sky_sprite); + + // Draw the ground + resources.ground_sprite.setPosition(0, ((window.getView().getSize().y / 2) + pc.look_offset * 10)); + float ground_scale_x = window.getView().getSize().x / resources.ground_sprite.getLocalBounds().width; + float ground_scale_y = resources.ground_sprite.getLocalBounds().height; + resources.ground_sprite.setScale(ground_scale_x, ground_scale_y); + if (world_gen.theme == 1) + { + resources.ground_sprite.setTexture(resources.ground_texture); + } + else + { + resources.ground_sprite.setTexture(resources.ground_2_texture); + } + window.draw(resources.ground_sprite); + + for (int i = 0; i < entity_count; i++) + { + if (entities[i].visible == true) + { + draw_count++; + } + } + + if (draw_count > 0) + { + std::vector entities_to_draw(draw_count); + draw_count = 0; + + // Find all visible objects + for (int i = 0; i < entity_count; i++) + { + if (entities[i].visible == true) + { + entities_to_draw[draw_count] = entities[i]; + draw_count++; + } + } + + // The upper and lower vertices of wall segments + std::vector verts_low(draw_count); + std::vector verts_high(draw_count); + + // Create sprites and wall segments for drawing to the screen + for (int i = 0; i < draw_count; i++) + { + if (entities_to_draw[i].type == "wall") // Create lines with scaled height for drawing wall quads + { + float scale = 6 - (entities_to_draw[i].distance * 0.095) - pc.look_offset * 0.005; + scale = scale < 0 ? 0 : scale; + sf::Vector2f v1; + v1.x = entities_to_draw[i].draw_x; + v1.y = (window.getView().getSize().y / 2) - (wall_height * scale) + pc.look_offset * 10; + sf::Vector2f v2; + v2.x = entities_to_draw[i].draw_x; + v2.y = (window.getView().getSize().y / 2) + (wall_height * scale) + pc.look_offset * 10; + verts_high[i] = v1; + verts_low[i] = v2; + } + else // Prepare sprites for drawing to the screen + { + float scale = 3 - (entities_to_draw[i].distance * 0.05) - pc.look_offset * 0.005; + scale = scale < 0 ? 0 : scale; + entities_to_draw[i].sprite.setScale(scale, scale); + entities_to_draw[i].sprite.setScale(scale, scale); + float window_center = window.getView().getSize().y / 2; + float sprite_width = entities_to_draw[i].sprite.getTexture()->getSize().y; + float sprite_scale = entities_to_draw[i].sprite.getScale().y; + entities_to_draw[i].draw_y = window_center - ((sprite_width * sprite_scale) / 2); + entities_to_draw[i].draw_y += (120 - (entities_to_draw[i].distance * 2)) + pc.look_offset * 10; + entities_to_draw[i].sprite.setPosition(entities_to_draw[i].draw_x, entities_to_draw[i].draw_y); + } + } + + // Sort wall segments from left to right on the window's x axis, for drawing quads + verts_low = x_sort(verts_low, draw_count); + verts_high = x_sort(verts_high, draw_count); + + // Create the quads + std::vector walls (draw_count); + for (int wall_index = 0; wall_index < draw_count - 1; wall_index++) + { + if (get_distance(verts_high[wall_index], verts_high[wall_index + 1]) < window.getView().getSize().x * 0.4) + { + if (verts_low[wall_index].x != 0) + { + sf::VertexArray quad(sf::Quads, 4); + quad[0].position = verts_low[wall_index]; + quad[1].position = verts_low[wall_index + 1]; + quad[2].position = verts_high[wall_index + 1]; + quad[3].position = verts_high[wall_index]; + quad[0].texCoords = sf::Vector2f(0.f, 512.f); + quad[1].texCoords = sf::Vector2f(512.f, 512.f); + quad[2].texCoords = sf::Vector2f(512.f, 0.f); + quad[3].texCoords = sf::Vector2f(0.f, 0.f); + if (world_gen.theme == 1) + { + window.draw(quad, &resources.wall_texture); + } + else + { + window.draw(quad, &resources.wall_2_texture); + } + } + } + } + + // Sort sprites by their distance from the camera, so farther sprites are drawn first + entity temp; + int i, j; + + for(i = 0; i < draw_count; i++) + { + for(j = i + 1; j < draw_count; j++) + { + if(entities_to_draw[i].distance < entities_to_draw[j].distance) + { + temp = entities_to_draw[i]; + entities_to_draw[i] = entities_to_draw[j]; + entities_to_draw[j] = temp; + } + } + } + + // Draw sprites + for (int i = 0; i < draw_count; i++) + { + if (entities_to_draw[i].type != "wall") + { + window.draw(entities_to_draw[i].sprite); + if (entities_to_draw[i].type == "mob") + { + if (pc.target_id == entities_to_draw[i].id) + { + float scale = 3 - (entities_to_draw[i].distance * 0.05) - pc.look_offset * 0.005; + scale = scale < 0 ? 0 : scale; + float x = entities_to_draw[i].sprite.getPosition().x; + float y = entities_to_draw[i].sprite.getPosition().y; + float width = entities_to_draw[i].sprite.getTexture()->getSize().x * scale; + float height = entities_to_draw[i].sprite.getTexture()->getSize().y * scale; + sf::Vector2f top_left = sf::Vector2f(x - 10, y - 10); + sf::Vector2f bottom_left = sf::Vector2f(x - 10, y + height + 10); + sf::Vector2f top_right = sf::Vector2f(x + width + 10, y - 10); + sf::Vector2f bottom_right = sf::Vector2f(x + width + 10, y + height + 10); + sf::VertexArray target_box(sf::LineStrip, 5); + target_box[0].position = bottom_left; + target_box[1].position = bottom_right; + target_box[2].position = top_right; + target_box[3].position = top_left; + target_box[4].position = bottom_left; + for (int j = 0; j < 5; j++) + { + target_box[j].color = sf::Color::Red; + } + window.draw(target_box); + std::string target_distance = std::to_string((int)entities[pc.target_id].distance * 10); + std::string info = "Distance: " + target_distance + " meters\nTargeting: " + pc.components[pc.targeted_component]; + resources.target_info.setString(info); + sf::Vector2f info_pos = sf::Vector2f(top_left.x, top_left.y - 40); + resources.target_info.setPosition(info_pos); + window.draw(resources.target_info); + } + } + } + } + } + + // Draw the cockpit + draw_cockpit(window, resources, pc, took_damage); + + //Draw the HUD + player_hud.draw_hud(window, frame_time, pc.target_id, pc.player_mech.speed, pc.torso_angle, pc.player_mech, entities[pc.target_id].entity_mech); + + // Draw entities on the map + for (int i = 0; i < entity_count; i++) + { + if (show_map == true && pc.player_mech.destroyed() == false) + { + if (entities[i].type == "mob") + { + if (pc.target_id == entities[i].id) + { + entities[i].icon.setTexture(resources.target_icon_texture); + } + else + { + entities[i].icon.setTexture(resources.mob_icon_texture); + } + } + if (entities[i].dead == false) + { + entities[i].icon.setPosition(entities[i].position.x * map_scale, entities[i].position.y * map_scale); + window.draw(entities[i].icon); + } + } + } + + // Draw the player on the map + if (show_map == true && pc.player_mech.destroyed() == false) + { + sf::VertexArray line1(sf::LinesStrip, 2); + sf::Vector2f map_player_pos = sf::Vector2f(pc.player_pos.x * map_scale, pc.player_pos.y * map_scale); + sf::Vector2f map_look_pos = sf::Vector2f(pc.look_pos.x * map_scale, pc.look_pos.y * map_scale); + sf::Vector2f map_cam_pos = sf::Vector2f(rays[camera_width / 2 + camera_width * 5].x * map_scale, rays[camera_width / 2 + camera_width * 5].y * map_scale); + sf::Vector2f mid = get_midpoint(map_player_pos, map_look_pos); + + resources.player_icon.setPosition(sf::Vector2f((pc.player_pos.x - 16) * map_scale, (pc.player_pos.y - 16) * map_scale)); + resources.player_icon.setScale(map_scale, map_scale); + window.draw(resources.player_icon); + + line1[0].position = map_player_pos; + line1[1].position = mid; + line1[0].color = sf::Color::Green; + line1[1].color = sf::Color::Green; + window.draw(line1); + + sf::VertexArray line2(sf::LinesStrip, 2); + line2[0].position = map_player_pos; + line2[1].position = map_cam_pos; + line2[0].color = sf::Color::Red; + line2[1].color = sf::Color::Red; + window.draw(line2); + } + + if (show_keys == true) + { + sf::Vector2f bg_pos; + float x = window.getView().getSize().x - 150; + bg_pos.x = x - (resources.keys.getGlobalBounds().width / 2); + bg_pos.y = (window.getView().getSize().y / 2) - 175; + sf::Sprite bg = sf::Sprite(resources.gui_background_texture); + bg.setPosition(bg_pos); + bg.setScale(0.1, 1); + window.draw(bg); + + std::string bindings = get_file_contents(cwd + "/bindings.list"); + resources.keys.setString(bindings); + resources.keys.setPosition(x - 50, (window.getView().getSize().y / 2) - 150); + window.draw(resources.keys); + } + + if (tut.visible == true) + { + tut.draw_tutorial(window, show_keys, pc.player_mech.speed, pc.torso_angle, pc.player_mech.heat); + } + + if (show_victory_notice == true) + { + resources.mission_music.stop(); + if (resources.victory_sound.getStatus() != sf::Sound::Playing) + { + resources.victory_sound.setVolume(100 * audio_volume); + resources.victory_sound.play(); + } + + tut.visible = false; + s_menu.visible = false; + resources.notice.setFont(resources.orbitron); + resources.notice.setString("MISSION COMPLETE"); + sf::Vector2f text_pos; + text_pos.x = (window.getView().getSize().x / 2) - (resources.notice.getGlobalBounds().width / 2); + text_pos.y = (window.getView().getSize().y / 2) - 150; + resources.notice.setPosition(text_pos); + window.draw(resources.notice); + resources.notice.setFont(resources.exoplanetaria); + + victory_timer += 10 * frame_time; + if (victory_timer >= 60) + { + victory_timer = 0; + show_victory_notice = false; + complete_mission(); + } + } + + if (s_menu.visible == true) + { + tut.visible = false; + sf::Vector2i mouse_pos = sf::Mouse().getPosition(window); + s_menu.draw_menu(window, mouse_pos, frame_time); + + if (s_menu.abort_mission == true) + { + abort_mission(); + } + } + + // Draw frame rate at the bottom left corner of the screen + if (show_fps == true) + { + sf::String fps_string = "FPS: " + std::to_string(fps); + resources.fps_counter.setString(fps_string); + resources.fps_counter.setPosition(10, window.getView().getSize().y * 0.96); + window.draw(resources.fps_counter); + } + + // Display on screen what has been rendered to the window so far + window.display(); + } + + // Calculate framerate + fps_finish = std::chrono::high_resolution_clock::now(); + fps = (float)1e9/(float)std::chrono::duration_cast(fps_finish-fps_start).count(); + frame_time = 1 / fps; + } + + return EXIT_SUCCESS; +} diff --git a/save/saves.list b/save/saves.list new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/save/saves.list @@ -0,0 +1 @@ + diff --git a/settings.list b/settings.list new file mode 100644 index 0000000..76f56f2 --- /dev/null +++ b/settings.list @@ -0,0 +1,3 @@ +volume:1.000000 +music:1 + diff --git a/src/assets.cpp b/src/assets.cpp new file mode 100644 index 0000000..f299776 --- /dev/null +++ b/src/assets.cpp @@ -0,0 +1,647 @@ +#include +#include +#include + +// Loads sounds from file +void assets::load_sound_buffers(std::string cwd) +{ + if (!main_menu_music_buffer.loadFromFile(cwd + "/assets/sounds/main_menu.ogg")) + { + std::cout << "Error loading sound file main_menu.ogg"; + std::cout << "\n"; + } + + if (!intermission_music_buffer.loadFromFile(cwd + "/assets/sounds/intermission_menu.ogg")) + { + std::cout << "Error loading sound file intermission_menu.ogg"; + std::cout << "\n"; + } + + if (!mission_music_buffer.loadFromFile(cwd + "/assets/sounds/mission.ogg")) + { + std::cout << "Error loading sound file mission.ogg"; + std::cout << "\n"; + } + + if (!power_down_sound_buffer.loadFromFile(cwd + "/assets/sounds/power_down.ogg")) + { + std::cout << "Error loading sound file power_down.ogg"; + std::cout << "\n"; + } + + if (!victory_sound_buffer.loadFromFile(cwd + "/assets/sounds/victory.ogg")) + { + std::cout << "Error loading sound file victory.ogg"; + std::cout << "\n"; + } + + if (!power_up_sound_buffer.loadFromFile(cwd + "/assets/sounds/power_up.ogg")) + { + std::cout << "Error loading sound file power_up.ogg"; + std::cout << "\n"; + } + + if (!hydraulic_sound_buffer.loadFromFile(cwd + "/assets/sounds/hydraulic.ogg")) + { + std::cout << "Error loading sound file hydraulic.ogg"; + std::cout << "\n"; + } + + if (!gun_sound_buffer.loadFromFile(cwd + "/assets/sounds/guns.ogg")) + { + std::cout << "Error loading sound file guns.ogg"; + std::cout << "\n"; + } + + if (!cannon_sound_buffer.loadFromFile(cwd + "/assets/sounds/cannon.ogg")) + { + std::cout << "Error loading sound file cannon.ogg"; + std::cout << "\n"; + } + + if (!explo_sound_buffer.loadFromFile(cwd + "/assets/sounds/explosion.ogg")) + { + std::cout << "Error loading sound file explosion.ogg"; + std::cout << "\n"; + } + + if (!stomp_sound_buffer.loadFromFile(cwd + "/assets/sounds/stomp.ogg")) + { + std::cout << "Error loading sound file stomp.ogg"; + std::cout << "\n"; + } + + if (!crash_sound_buffer.loadFromFile(cwd + "/assets/sounds/crash.ogg")) + { + std::cout << "Error loading sound file crash.ogg"; + std::cout << "\n"; + } + + if (!impact_sound_buffer.loadFromFile(cwd + "/assets/sounds/impact.ogg")) + { + std::cout << "Error loading sound file impact.ogg"; + std::cout << "\n"; + } + + if (!purchase_sound_buffer.loadFromFile(cwd + "/assets/sounds/purchase.ogg")) + { + std::cout << "Error loading sound file purchase.ogg"; + std::cout << "\n"; + } +} + +// Loads textures from file +void assets::load_textures(std::string cwd) +{ + if (!mech_texture.loadFromFile(cwd + "/assets/textures/mech/mech.bmp")) + { + std::cout << "Error loading image file mech.bmp"; + std::cout << "\n"; + } + + if (!mech_fire_guns_texture.loadFromFile(cwd + "/assets/textures/mech/mech_fire.bmp")) + { + std::cout << "Error loading image file mech_fire.bmp"; + std::cout << "\n"; + } + + if (!mech_fire_guns_left_texture.loadFromFile(cwd + "/assets/textures/mech/mech_fire_left.bmp")) + { + std::cout << "Error loading image file mech_fire_left.bmp"; + std::cout << "\n"; + } + + if (!mech_fire_guns_right_texture.loadFromFile(cwd + "/assets/textures/mech/mech_fire_right.bmp")) + { + std::cout << "Error loading image file mech_fire_right.bmp"; + std::cout << "\n"; + } + + if (!mech_fire_cannons_texture.loadFromFile(cwd + "/assets/textures/mech/mech_cannon_fire.bmp")) + { + std::cout << "Error loading image file mech_cannon_fire.bmp"; + std::cout << "\n"; + } + + if (!mech_fire_cannons_left_texture.loadFromFile(cwd + "/assets/textures/mech/mech_cannon_left.bmp")) + { + std::cout << "Error loading image file mech_cannon_fire_left.bmp"; + std::cout << "\n"; + } + + if (!mech_fire_cannons_right_texture.loadFromFile(cwd + "/assets/textures/mech/mech_cannon_right.bmp")) + { + std::cout << "Error loading image file mech_cannon_fire_right.bmp"; + std::cout << "\n"; + } + + if (!mech_hit_center_texture.loadFromFile(cwd + "/assets/textures/mech/mech_hit_center.bmp")) + { + std::cout << "Error loading image file mech_hit_center.bmp"; + std::cout << "\n"; + } + + if (!mech_hit_cockpit_texture.loadFromFile(cwd + "/assets/textures/mech/mech_hit_cockpit.bmp")) + { + std::cout << "Error loading image file mech_hit_cockpit.bmp"; + std::cout << "\n"; + } + + if (!mech_hit_left_leg_texture.loadFromFile(cwd + "/assets/textures/mech/mech_hit_left_leg.bmp")) + { + std::cout << "Error loading image file mech_hit_left_leg.bmp"; + std::cout << "\n"; + } + + if (!mech_hit_right_leg_texture.loadFromFile(cwd + "/assets/textures/mech/mech_hit_right_leg.bmp")) + { + std::cout << "Error loading image file mech_hit_right_leg.bmp"; + std::cout << "\n"; + } + + if (!mech_hit_left_arm_texture.loadFromFile(cwd + "/assets/textures/mech/mech_hit_left_arm.bmp")) + { + std::cout << "Error loading image file mech_hit_left_arm.bmp"; + std::cout << "\n"; + } + + if (!mech_hit_right_arm_texture.loadFromFile(cwd + "/assets/textures/mech/mech_hit_right_arm.bmp")) + { + std::cout << "Error loading image file mech_hit_right_arm.bmp"; + std::cout << "\n"; + } + + if (!explosion_texture.loadFromFile(cwd + "/assets/textures/mech/explosion.png")) + { + std::cout << "Error loading image file explosion.bmp"; + std::cout << "\n"; + } + + if (!crosshair_texture.loadFromFile(cwd + "/assets/textures/crosshair.png")) + { + std::cout << "Error loading image file crosshair.bmp"; + std::cout << "\n"; + } + + if (!cockpit_texture.loadFromFile(cwd + "/assets/textures/cockpit/cockpit.bmp")) + { + std::cout << "Error loading image file cockpit.bmp"; + std::cout << "\n"; + } + + if (!cockpit_fire_texture.loadFromFile(cwd + "/assets/textures/cockpit/cockpit_fire.bmp")) + { + std::cout << "Error loading image file cockpit_fire.bmp"; + std::cout << "\n"; + } + + if (!cockpit_fire_left_texture.loadFromFile(cwd + "/assets/textures/cockpit/cockpit_fire_left.bmp")) + { + std::cout << "Error loading image file cockpit_fire_left.bmp"; + std::cout << "\n"; + } + + if (!cockpit_fire_right_texture.loadFromFile(cwd + "/assets/textures/cockpit/cockpit_fire_right.bmp")) + { + std::cout << "Error loading image file cockpit_fire_right.bmp"; + std::cout << "\n"; + } + + if (!cockpit_cannon_texture.loadFromFile(cwd + "/assets/textures/cockpit/cockpit_cannon.bmp")) + { + std::cout << "Error loading image file cockpit_cannon.bmp"; + std::cout << "\n"; + } + + if (!cockpit_cannon_left_texture.loadFromFile(cwd + "/assets/textures/cockpit/cockpit_cannon_left.bmp")) + { + std::cout << "Error loading image file cockpit_cannon_left.bmp"; + std::cout << "\n"; + } + + if (!cockpit_cannon_right_texture.loadFromFile(cwd + "/assets/textures/cockpit/cockpit_cannon_right.bmp")) + { + std::cout << "Error loading image file cockpit_cannon_right.bmp"; + std::cout << "\n"; + } + + if (!cockpit_impact_texture.loadFromFile(cwd + "/assets/textures/cockpit/cockpit_impact.bmp")) + { + std::cout << "Error loading image file cockpit_impact.bmp"; + std::cout << "\n"; + } + + if (!cockpit_destroyed_texture.loadFromFile(cwd + "/assets/textures/cockpit/cockpit_destroyed.bmp")) + { + std::cout << "Error loading image file cockpit_destroyed.bmp"; + std::cout << "\n"; + } + + if (!ground_texture.loadFromFile(cwd + "/assets/textures/ground.bmp")) + { + std::cout << "Error loading image file ground.bmp"; + std::cout << "\n"; + } + + if (!ground_2_texture.loadFromFile(cwd + "/assets/textures/ground_2.bmp")) + { + std::cout << "Error loading image file ground_2.bmp"; + std::cout << "\n"; + } + + if (!sky_texture.loadFromFile(cwd + "/assets/textures/sky.bmp")) + { + std::cout << "Error loading image file sky.bmp"; + std::cout << "\n"; + } + + if (!sky_2_texture.loadFromFile(cwd + "/assets/textures/sky_2.png")) + { + std::cout << "Error loading image file sky_2.bmp"; + std::cout << "\n"; + } + + if (!mech_status_texture.loadFromFile(cwd + "/assets/textures/mech_status.bmp")) + { + std::cout << "Error loading image file mech_status.bmp"; + std::cout << "\n"; + } + + if (!gui_background_texture.loadFromFile(cwd + "/assets/textures/gui_background.png")) + { + std::cout << "Error loading image file gui_background.bmp"; + std::cout << "\n"; + } + + if (!gui_background_2_texture.loadFromFile(cwd + "/assets/textures/gui_background_2.png")) + { + std::cout << "Error loading image file gui_background_2.bmp"; + std::cout << "\n"; + } + + if (!target_gui_background_texture.loadFromFile(cwd + "/assets/textures/target_gui_background.png")) + { + std::cout << "Error loading image file target_gui_background.bmp"; + std::cout << "\n"; + } + + if (!wall_texture.loadFromFile(cwd + "/assets/textures/wall.bmp")) + { + std::cout << "Error loading image file wall.bmp"; + std::cout << "\n"; + } + + if (!wall_2_texture.loadFromFile(cwd + "/assets/textures/wall_2.bmp")) + { + std::cout << "Error loading image file wall_2.bmp"; + std::cout << "\n"; + } + + if (!tree_texture.loadFromFile(cwd + "/assets/textures/tree.bmp")) + { + std::cout << "Error loading image file tree.bmp"; + std::cout << "\n"; + } + + if (!tree_2_texture.loadFromFile(cwd + "/assets/textures/tree_2.png")) + { + std::cout << "Error loading image file tree_2.bmp"; + std::cout << "\n"; + } + + if (!tree_3_texture.loadFromFile(cwd + "/assets/textures/tree_3.png")) + { + std::cout << "Error loading image file tree_3.bmp"; + std::cout << "\n"; + } + + if (!tree_4_texture.loadFromFile(cwd + "/assets/textures/tree_4.png")) + { + std::cout << "Error loading image file tree_4.bmp"; + std::cout << "\n"; + } + + if (!player_icon_texture.loadFromFile(cwd + "/assets/textures/player_icon.png")) + { + std::cout << "Error loading image file player_icon.bmp"; + std::cout << "\n"; + } + + if (!mob_icon_texture.loadFromFile(cwd + "/assets/textures/mob_icon.png")) + { + std::cout << "Error loading image file mob_icon.bmp"; + std::cout << "\n"; + } + + if (!target_icon_texture.loadFromFile(cwd + "/assets/textures/target_icon.png")) + { + std::cout << "Error loading image file target_icon.bmp"; + std::cout << "\n"; + } + + if (!wall_icon_texture.loadFromFile(cwd + "/assets/textures/wall_icon.png")) + { + std::cout << "Error loading image file wall_icon.bmp"; + std::cout << "\n"; + } + + if (!menu_background_texture.loadFromFile(cwd + "/assets/textures/menu_background.png")) + { + std::cout << "Error loading image file menu_background.bmp"; + std::cout << "\n"; + } + + if (!menu_mech_texture.loadFromFile(cwd + "/assets/textures/mech_repair.png")) + { + std::cout << "Error loading image file mech_repair.bmp"; + std::cout << "\n"; + } + + if (!menu_mech_spark_1_texture.loadFromFile(cwd + "/assets/textures/mech_repair_spark_1.png")) + { + std::cout << "Error loading image file mech_repair_spark_1.bmp"; + std::cout << "\n"; + } + + if (!menu_mech_spark_2_texture.loadFromFile(cwd + "/assets/textures/mech_repair_spark_2.png")) + { + std::cout << "Error loading image file mech_repair_spark_2.bmp"; + std::cout << "\n"; + } + + if (!start_game_button_texture.loadFromFile(cwd + "/assets/textures/buttons/start_game_button.png")) + { + std::cout << "Error loading image file start_game_button.bmp"; + std::cout << "\n"; + } + + if (!start_game_button_hover_texture.loadFromFile(cwd + "/assets/textures/buttons/start_game_button_hover.png")) + { + std::cout << "Error loading image file start_game_button_hover.bmp"; + std::cout << "\n"; + } + + if (!main_menu_button_texture.loadFromFile(cwd + "/assets/textures/buttons/main_menu_button.png")) + { + std::cout << "Error loading image file main_menu_button.bmp"; + std::cout << "\n"; + } + + if (!main_menu_button_hover_texture.loadFromFile(cwd + "/assets/textures/buttons/main_menu_button_hover.png")) + { + std::cout << "Error loading image file main_menu_button_hover.bmp"; + std::cout << "\n"; + } + + if (!save_game_button_texture.loadFromFile(cwd + "/assets/textures/buttons/save_button.png")) + { + std::cout << "Error loading image file save_button.bmp"; + std::cout << "\n"; + } + + if (!save_game_button_hover_texture.loadFromFile(cwd + "/assets/textures/buttons/save_button_hover.png")) + { + std::cout << "Error loading image file save_button_hover.bmp"; + std::cout << "\n"; + } + + if (!load_game_button_texture.loadFromFile(cwd + "/assets/textures/buttons/load_button.png")) + { + std::cout << "Error loading image file load_button.bmp"; + std::cout << "\n"; + } + + if (!load_game_button_hover_texture.loadFromFile(cwd + "/assets/textures/buttons/load_button_hover.png")) + { + std::cout << "Error loading image file load_button_hover.bmp"; + std::cout << "\n"; + } + + if (!options_button_texture.loadFromFile(cwd + "/assets/textures/buttons/options_button.png")) + { + std::cout << "Error loading image file options_button.bmp"; + std::cout << "\n"; + } + + if (!options_button_hover_texture.loadFromFile(cwd + "/assets/textures/buttons/options_button_hover.png")) + { + std::cout << "Error loading image file options_button_hover.bmp"; + std::cout << "\n"; + } + + if (!repair_button_texture.loadFromFile(cwd + "/assets/textures/buttons/repair_button.png")) + { + std::cout << "Error loading image file repair_button.bmp"; + std::cout << "\n"; + } + + if (!market_button_texture.loadFromFile(cwd + "/assets/textures/buttons/market_button.png")) + { + std::cout << "Error loading image file market_button.bmp"; + std::cout << "\n"; + } + + if (!market_button_hover_texture.loadFromFile(cwd + "/assets/textures/buttons/market_button_hover.png")) + { + std::cout << "Error loading image file market_button_hover.bmp"; + std::cout << "\n"; + } + + if (!repair_button_hover_texture.loadFromFile(cwd + "/assets/textures/buttons/repair_button_hover.png")) + { + std::cout << "Error loading image file repair_button_hover.bmp"; + std::cout << "\n"; + } + + if (!exit_game_button_texture.loadFromFile(cwd + "/assets/textures/buttons/exit_game_button.png")) + { + std::cout << "Error loading image file exit_game_button.bmp"; + std::cout << "\n"; + } + + if (!exit_game_button_hover_texture.loadFromFile(cwd + "/assets/textures/buttons/exit_game_button_hover.png")) + { + std::cout << "Error loading image file exit_game_button_hover.bmp"; + std::cout << "\n"; + } + + if (!next_mission_button_texture.loadFromFile(cwd + "/assets/textures/buttons/next_mission_button.png")) + { + std::cout << "Error loading image file next_mission_button.bmp"; + std::cout << "\n"; + } + + if (!next_mission_button_hover_texture.loadFromFile(cwd + "/assets/textures/buttons/next_mission_button_hover.png")) + { + std::cout << "Error loading image file next_mission_button_hover.bmp"; + std::cout << "\n"; + } + + if (!create_new_button_texture.loadFromFile(cwd + "/assets/textures/buttons/create_new_button.png")) + { + std::cout << "Error loading image file create_new_button.bmp"; + std::cout << "\n"; + } + + if (!create_new_button_hover_texture.loadFromFile(cwd + "/assets/textures/buttons/create_new_button_hover.png")) + { + std::cout << "Error loading image file create_new_button_hover.bmp"; + std::cout << "\n"; + } + + if (!cancel_button_texture.loadFromFile(cwd + "/assets/textures/buttons/cancel_button.png")) + { + std::cout << "Error loading image file cancel_button.bmp"; + std::cout << "\n"; + } + + if (!cancel_button_hover_texture.loadFromFile(cwd + "/assets/textures/buttons/cancel_button_hover.png")) + { + std::cout << "Error loading image file cancel_button_hover.bmp"; + std::cout << "\n"; + } + + if (!term_texture.loadFromFile(cwd + "/assets/textures/term.bmp")) + { + std::cout << "Error loading image file term.bmp"; + std::cout << "\n"; + } +} + +// Loads fonts from file +void assets::load_fonts(std::string cwd) +{ + if (!orbitron.loadFromFile(cwd + "/assets/Orbitron Medium.ttf")) + { + std::cout << "Error loading font file Orbitron Medium.ttf"; + std::cout << "\n"; + } + + if (!exoplanetaria.loadFromFile(cwd + "/assets/Exoplanetaria-gxxJ5.ttf")) + { + std::cout << "Error loading font file Exoplanetaria-gxxJ5.ttf"; + std::cout << "\n"; + } +} + +// Assigns sound buffers +void assets::init_sounds() +{ + main_menu_music.setBuffer(main_menu_music_buffer); + intermission_music.setBuffer(intermission_music_buffer); + mission_music.setBuffer(mission_music_buffer); + power_down_sound.setBuffer(power_down_sound_buffer); + victory_sound.setBuffer(victory_sound_buffer); + power_up_sound.setBuffer(power_up_sound_buffer); + hydraulic_sound.setBuffer(hydraulic_sound_buffer); + gun_sound.setBuffer(gun_sound_buffer); + cannon_sound.setBuffer(cannon_sound_buffer); + explosion_sound.setBuffer(explo_sound_buffer); + stomp_sound.setBuffer(stomp_sound_buffer); + crash_sound.setBuffer(crash_sound_buffer); + impact_sound.setBuffer(impact_sound_buffer); + purchase_sound.setBuffer(purchase_sound_buffer); +} + +// Assigns textures to sprites +void assets::init_sprites() +{ + crosshair_sprite.setTexture(crosshair_texture); + cockpit_sprite.setTexture(cockpit_texture); + ground_sprite.setTexture(ground_texture); + sky_sprite.setTexture(sky_texture); + player_icon.setTexture(player_icon_texture); + mob_icon.setTexture(mob_icon_texture); + target_icon.setTexture(target_icon_texture); + wall_icon.setTexture(wall_icon_texture); + menu_background_sprite.setTexture(menu_background_texture); + menu_mech_sprite.setTexture(menu_mech_texture); + start_game_button_sprite.setTexture(start_game_button_texture); + main_menu_button_sprite.setTexture(main_menu_button_texture); + save_game_button_sprite.setTexture(save_game_button_texture); + load_game_button_sprite.setTexture(load_game_button_texture); + options_button_sprite.setTexture(options_button_texture); + repair_button_sprite.setTexture(repair_button_texture); + market_button_sprite.setTexture(market_button_texture); + exit_game_button_sprite.setTexture(exit_game_button_texture); + next_mission_button_sprite.setTexture(next_mission_button_texture); + create_new_button_sprite.setTexture(create_new_button_texture); + cancel_button_sprite.setTexture(cancel_button_texture); + term_sprite.setTexture(term_texture); +} + +// Sets up text objects +void assets::init_text() +{ + fps_counter.setFont(orbitron); + fps_counter.setString("0"); + fps_counter.setCharacterSize(12); + fps_counter.setFillColor(sf::Color::White); + + keys.setFont(exoplanetaria); + keys.setString(""); + keys.setCharacterSize(12); + keys.setFillColor(sf::Color::White); + + mech_status.setFont(orbitron); + mech_status.setString(""); + mech_status.setCharacterSize(12); + mech_status.setFillColor(sf::Color::Green); + + target_status.setFont(orbitron); + target_status.setString(""); + target_status.setCharacterSize(12); + target_status.setFillColor(sf::Color::Red); + + throttle_display.setFont(orbitron); + throttle_display.setString("0"); + throttle_display.setCharacterSize(12); + throttle_display.setFillColor(sf::Color::Green); + + torso_display.setFont(orbitron); + torso_display.setString("0"); + torso_display.setCharacterSize(12); + torso_display.setFillColor(sf::Color::Green); + + target_info.setFont(orbitron); + target_info.setString(""); + target_info.setCharacterSize(12); + target_info.setFillColor(sf::Color::Red); + + input_text.setFont(orbitron); + input_text.setString(""); + input_text.setCharacterSize(12); + input_text.setFillColor(sf::Color::White); + + notice.setFont(exoplanetaria); + notice.setString(""); + notice.setCharacterSize(24); + notice.setFillColor(sf::Color::White); +} + +// Initializes all assets +void assets::init(std::string cwd) +{ + load_sound_buffers(cwd); + load_textures(cwd); + load_fonts(cwd); + + init_sounds(); + init_sprites(); + init_text(); + + mech_textures = {mech_hit_center_texture, + mech_hit_center_texture, + mech_hit_left_arm_texture, + mech_hit_right_arm_texture, + mech_hit_left_leg_texture, + mech_hit_right_leg_texture, + mech_hit_cockpit_texture}; + + sky_texture.setRepeated(true); + sky_2_texture.setRepeated(true); + + unsigned int x = sf::VideoMode::getDesktopMode().width; + unsigned int y = sf::VideoMode::getDesktopMode().height; + sky_sprite.setTextureRect(sf::IntRect(0, 0, x, y)); +} diff --git a/src/calc_helper.cpp b/src/calc_helper.cpp new file mode 100644 index 0000000..b63ead7 --- /dev/null +++ b/src/calc_helper.cpp @@ -0,0 +1,49 @@ +#include +#include +#include +#include + +// Returns the distance between two vectors +float get_distance(sf::Vector2f v1, sf::Vector2f v2) +{ + float xdif = v2.x - v1.x; + float ydif = v2.y - v1.y; + float xdifsqrd = xdif * xdif; + float ydifsqrd = ydif * ydif; + return sqrt(xdifsqrd + ydifsqrd); +} + +// Returns the midpoint between two vectors +sf::Vector2f get_midpoint(sf::Vector2f v1, sf::Vector2f v2) +{ + float xmid = (v1.x + v2.x) / 2; + float ymid = (v1.y + v2.y) / 2; + sf::Vector2f vmid(xmid, ymid); + return vmid; +} + +// Returns the angle between two vectors +float get_angle(sf::Vector2f v1, sf::Vector2f v2) +{ + return atan2(v2.y - v1.y, v2.x - v1.x) * (180 / 3.14); +} + +// Sorts vectors based on their position along the x axis +std::vector x_sort(std::vector vectors, int total) +{ + sf::Vector2f temp_vector; + int current_index, next_index; + for(current_index = 0; current_index < total; current_index++) + { + for(next_index = current_index + 1; next_index < total; next_index++) + { + if(vectors[current_index].x > vectors[next_index].x) + { + temp_vector = vectors[current_index]; + vectors[current_index] = vectors[next_index]; + vectors[next_index] = temp_vector; + } + } + } + return vectors; +} diff --git a/src/cockpit.cpp b/src/cockpit.cpp new file mode 100644 index 0000000..69eca9f --- /dev/null +++ b/src/cockpit.cpp @@ -0,0 +1,66 @@ +#include + +// Draws the cockpit, muzzle flashes and hit effects +void draw_cockpit(sf::RenderWindow &window, assets &resources, player_controller &pc, bool took_damage) +{ + float cockpit_x = window.getView().getSize().x / resources.cockpit_sprite.getLocalBounds().width; + float cockpit_y = window.getView().getSize().y / resources.cockpit_sprite.getLocalBounds().height; + resources.cockpit_sprite.setScale(cockpit_x, cockpit_y); + resources.cockpit_sprite.setPosition(0, 0); + window.draw(resources.cockpit_sprite); + + if (pc.player_mech.destroyed() == false) + { + if (pc.muzzle_flash == true) + { + sf::Sprite fire_sprite; + + if (pc.player_mech.left_arm_destroyed()) + { + fire_sprite = sf::Sprite(resources.cockpit_fire_right_texture); + } + else if (pc.player_mech.right_arm_destroyed()) + { + fire_sprite = sf::Sprite(resources.cockpit_fire_left_texture); + } + else + { + fire_sprite = sf::Sprite(resources.cockpit_fire_texture); + } + + fire_sprite.setScale(cockpit_x, cockpit_y); + fire_sprite.setPosition(0, 0); + window.draw(fire_sprite); + } + + if (pc.cannon_flash == true) + { + sf::Sprite fire_sprite; + + if (pc.player_mech.left_arm_destroyed()) + { + fire_sprite = sf::Sprite(resources.cockpit_cannon_right_texture); + } + else if (pc.player_mech.right_arm_destroyed()) + { + fire_sprite = sf::Sprite(resources.cockpit_cannon_left_texture); + } + else + { + fire_sprite = sf::Sprite(resources.cockpit_cannon_texture); + } + + fire_sprite.setScale(cockpit_x, cockpit_y); + fire_sprite.setPosition(0, 0); + window.draw(fire_sprite); + } + + if (took_damage == true) + { + sf::Sprite damage_sprite = sf::Sprite(resources.cockpit_impact_texture); + damage_sprite.setScale(cockpit_x, cockpit_y); + damage_sprite.setPosition(0, 0); + window.draw(damage_sprite); + } + } +} diff --git a/src/entity.cpp b/src/entity.cpp new file mode 100644 index 0000000..8e40046 --- /dev/null +++ b/src/entity.cpp @@ -0,0 +1,269 @@ +#include +#include +#include +#include + +entity::entity() +{ + id = 0; + draw_x = 0; + draw_y = 0; + move_x = 0; + move_y = 0; + old_pos = 0; + distance = 0; + think_timer = 0; + targeted_component = 0; + + dead = false; + init = false; + dying = false; + firing = false; + visible = false; + + components[0] = "reactor"; + components[1] = "cooler"; + components[2] = "left arm"; + components[3] = "right arm"; + components[4] = "left leg"; + components[5] = "right leg"; + components[6] = "cockpit"; +} + +// Prevents mobs from running into walls +void entity::avoid_walls(bool maze) +{ + if (position.x < 65) + { + position.x += 1; + } + + if (position.x > 545) + { + position.x -= 1; + } + + if (position.y < 45) + { + position.y += 1; + } + + if (position.y > 645) + { + position.y -= 1; + } + + if (maze == true) + { + if (position.x < 300 && position.y > 395) + { + position.y -= 1; + } + + if (position.x > 175 && position.x < 180 && position.y < 280) + { + position.x -= 1; + position.y += 5; + } + + if (position.x < 185 && position.x > 180 && position.y < 280) + { + position.x += 1; + position.y += 5; + } + + if (position.x > 295 && position.x < 300 && position.y > 150) + { + position.x -= 1; + position.y -= 5; + } + + if (position.x > 300 && position.x < 305 && position.y > 150) + { + position.x += 1; + position.y -= 5; + } + + if (position.x > 415 && position.x < 420 && position.y < 520) + { + position.x -= 1; + position.y += 5; + } + + if (position.x > 420 && position.x < 425 && position.y < 520) + { + position.x += 1; + position.y += 5; + } + } +} + +// Returns true if there is a wall between this entity and the player +bool entity::wall_blocking(sf::Vector2f camera_pos, bool maze) +{ + if (maze == false) + { + return false; + } + + if (camera_pos.x < 180 && position.x > 180 && position.y < 280) + { + return true; + } + + if (camera_pos.x > 180 && position.x < 180 && position.y < 280) + { + return true; + } + + if (camera_pos.x < 300 && position.x > 300 && position.y > 150) + { + return true; + } + + if (camera_pos.x > 300 && position.x < 300 && position.y > 150) + { + return true; + } + + if (camera_pos.x < 420 && position.x > 420 && position.y < 520) + { + return true; + } + + if (camera_pos.x > 420 && position.x < 420 && position.y < 520) + { + return true; + } + + return false; +} + +// NPC mech weapons firing +void entity::fire_weapons(assets &resources) +{ + if (sprite.getTexture() == &resources.mech_texture) + { + if (entity_mech.weapon == 1) + { + if (entity_mech.left_arm_destroyed() == true) + { + sprite.setTexture(resources.mech_fire_guns_right_texture); + } + else if (entity_mech.right_arm_destroyed() == true) + { + sprite.setTexture(resources.mech_fire_guns_left_texture); + } + else + { + sprite.setTexture(resources.mech_fire_guns_texture); + } + + resources.gun_sound.setVolume(25 * audio_volume); + resources.gun_sound.play(); + + float heat_gen = entity_mech.heat + 10 + entity_mech.guns_modifier; + entity_mech.heat = entity_mech.heat >= 90 ? 100 : heat_gen; + } + else + { + if (entity_mech.left_arm_destroyed() == true) + { + sprite.setTexture(resources.mech_fire_cannons_right_texture); + } + else if (entity_mech.right_arm_destroyed() == true) + { + sprite.setTexture(resources.mech_fire_cannons_left_texture); + } + else + { + sprite.setTexture(resources.mech_fire_cannons_texture); + } + + resources.cannon_sound.setVolume(25 * audio_volume); + resources.cannon_sound.play(); + + float heat_gen = entity_mech.heat + 50 + entity_mech.cannons_modifier; + entity_mech.heat = entity_mech.heat >= 50 ? 100 : heat_gen; + } + firing = false; + } +} + +// Handles npc logic +void entity::update(sf::Vector2f camera_pos, bool maze) +{ + if (type == "mob" && sub_type == "mech") + { + think_timer++; + + if (think_timer >= 10) + { + float camera_range = get_distance(camera_pos, position); + + if (entity_mech.can_move() == true) + { + int leg_integrity = entity_mech.left_leg_integrity + entity_mech.right_leg_integrity; + entity_mech.speed = camera_range > 60 ? leg_integrity * 0.00002 : leg_integrity * 0.00001; + float dir = entity_mech.speed; + + if (entity_mech.taking_damage == true || entity_mech.heat >= 50) + { + dir = -entity_mech.speed; + } + + if (position.x < camera_pos.x) + { + move_x = dir; + } + + if (position.x > camera_pos.x) + { + move_x = -dir; + } + + if (position.y < camera_pos.y) + { + move_y = dir; + } + + if (position.y > camera_pos.y) + { + move_y = -dir; + } + } + else + { + move_x = 0; + move_y = 0; + } + + if (entity_mech.can_fire() == true && entity_mech.heat <= 50) + { + if (camera_range < 60 && wall_blocking(camera_pos, maze) == false) + { + int fire_decision = rand() % 100; + + if (fire_decision > 25) + { + targeted_component = rand() % 7; + int weapon_decision = rand() % 100; + entity_mech.weapon = weapon_decision >= 75 ? 5 : 1; + firing = true; + } + else + { + firing = false; + } + } + } + + think_timer = 0; + } + + avoid_walls(maze); + entity_mech.update(); + position.x += move_x; + position.y += move_y; + } +} diff --git a/src/file_handler.cpp b/src/file_handler.cpp new file mode 100644 index 0000000..da7f819 --- /dev/null +++ b/src/file_handler.cpp @@ -0,0 +1,35 @@ +#include +#include +#include + +// Reads the contents of a file line by line and returns the result +std::string get_file_contents(std::string file_path) +{ + std::ifstream stream; + stream.open(file_path); + std::string text; + std::string result; + while(getline(stream, text)) + { + result += text + "\n"; + } + return result; +} + +// Writes the given data to a file, overwriting the existing data +std::string write_to_file(std::string file_path, std::string data) +{ + std::ofstream file; + file.open(file_path); + file << data << "\n"; + file.close(); + return data; +} + +// Gets the contents of a file, adds the given data and overwrites the file +std::string append_file(std::string file_path, std::string data) +{ + std::string current = get_file_contents(file_path); + std::string appended = current + data; + return write_to_file(file_path, appended); +} diff --git a/src/hud.cpp b/src/hud.cpp new file mode 100644 index 0000000..caf52d3 --- /dev/null +++ b/src/hud.cpp @@ -0,0 +1,286 @@ +#include +#include +#include + +// Initializes reference to main assets class +void hud::init(assets &resources) +{ + this->resources = resources; +} + +// Displays a notice with the given string +void hud::display_notice(sf::RenderWindow &window, std::string notice, float frame_time) +{ + sf::Vector2f notice_pos; + notice_pos.x = (window.getView().getSize().x / 2) - (resources.notice.getGlobalBounds().width / 2); + notice_pos.y = (window.getView().getSize().y / 2); + resources.notice.setString(notice); + resources.notice.setPosition(notice_pos); + window.draw(resources.notice); + + notice_timer += 10 * frame_time; + if (notice_timer >= 30) + { + notice_timer = 0; + show_notice = false; + } +} + +// Draws mech status image with color based on damage +void hud::draw_mech(float x_pos, mech &mech_to_draw, sf::RenderWindow &window) +{ + // Right arm + sf::VertexArray right_arm_quad(sf::Quads, 4); + right_arm_quad[0].position = sf::Vector2f(window.getView().getSize().x * x_pos, window.getView().getSize().y * 0.8 + 65); + right_arm_quad[1].position = sf::Vector2f(window.getView().getSize().x * x_pos + 40, window.getView().getSize().y * 0.8 + 65); + right_arm_quad[2].position = sf::Vector2f(window.getView().getSize().x * x_pos + 40, window.getView().getSize().y * 0.8); + right_arm_quad[3].position = sf::Vector2f(window.getView().getSize().x * x_pos, window.getView().getSize().y * 0.8); + right_arm_quad[0].texCoords = sf::Vector2f(0.f, 130.f); + right_arm_quad[1].texCoords = sf::Vector2f(76.f, 130.f); + right_arm_quad[2].texCoords = sf::Vector2f(76.f, 0.f); + right_arm_quad[3].texCoords = sf::Vector2f(0.f, 0.f); + + float right_arm_red = 255 - (255 * ((float)mech_to_draw.right_arm_integrity / (float)mech_to_draw.max_right_arm_integrity)); + float right_arm_green = 100 * ((float)mech_to_draw.right_arm_integrity / (float)mech_to_draw.max_right_arm_integrity); + for (int i = 0; i < 4; i++) + { + right_arm_quad[i].color = sf::Color(right_arm_red, right_arm_green, 0, 255); + } + window.draw(right_arm_quad, &resources.mech_status_texture); + + // Cockpit + sf::VertexArray cockpit_quad(sf::Quads, 4); + cockpit_quad[0].position = sf::Vector2f(window.getView().getSize().x * x_pos + 40, window.getView().getSize().y * 0.8 + 30); + cockpit_quad[1].position = sf::Vector2f(window.getView().getSize().x * x_pos + 92, window.getView().getSize().y * 0.8 + 30); + cockpit_quad[2].position = sf::Vector2f(window.getView().getSize().x * x_pos + 92, window.getView().getSize().y * 0.8); + cockpit_quad[3].position = sf::Vector2f(window.getView().getSize().x * x_pos + 40, window.getView().getSize().y * 0.8); + cockpit_quad[0].texCoords = sf::Vector2f(76.f, 59.f); + cockpit_quad[1].texCoords = sf::Vector2f(180.f, 59.f); + cockpit_quad[2].texCoords = sf::Vector2f(180.f, 0.f); + cockpit_quad[3].texCoords = sf::Vector2f(76.f, 0.f); + + float cockpit_red = 255 - (255 * ((float)mech_to_draw.cockpit_integrity / (float)mech_to_draw.max_cockpit_integrity)); + float cockpit_green = 100 * ((float)mech_to_draw.cockpit_integrity / (float)mech_to_draw.max_cockpit_integrity); + for (int i = 0; i < 4; i++) + { + cockpit_quad[i].color = sf::Color(cockpit_red, cockpit_green, 0, 255); + } + window.draw(cockpit_quad, &resources.mech_status_texture); + + // Left arm + sf::VertexArray left_arm_quad(sf::Quads, 4); + left_arm_quad[0].position = sf::Vector2f(window.getView().getSize().x * x_pos + 92, window.getView().getSize().y * 0.8 + 65); + left_arm_quad[1].position = sf::Vector2f(window.getView().getSize().x * x_pos + 132, window.getView().getSize().y * 0.8 + 65); + left_arm_quad[2].position = sf::Vector2f(window.getView().getSize().x * x_pos + 132, window.getView().getSize().y * 0.8); + left_arm_quad[3].position = sf::Vector2f(window.getView().getSize().x * x_pos + 92, window.getView().getSize().y * 0.8); + left_arm_quad[0].texCoords = sf::Vector2f(178.f, 130.f); + left_arm_quad[1].texCoords = sf::Vector2f(256.f, 130.f); + left_arm_quad[2].texCoords = sf::Vector2f(256.f, 0.f); + left_arm_quad[3].texCoords = sf::Vector2f(178.f, 0.f); + + float left_arm_red = 255 - (255 * ((float)mech_to_draw.left_arm_integrity / (float)mech_to_draw.max_left_arm_integrity)); + float left_arm_green = 100 * ((float)mech_to_draw.left_arm_integrity / (float)mech_to_draw.max_left_arm_integrity); + for (int i = 0; i < 4; i++) + { + left_arm_quad[i].color = sf::Color(left_arm_red, left_arm_green, 0, 255); + } + window.draw(left_arm_quad, &resources.mech_status_texture); + + // Reactor + sf::VertexArray reactor_quad(sf::Quads, 4); + reactor_quad[0].position = sf::Vector2f(window.getView().getSize().x * x_pos + 45, window.getView().getSize().y * 0.8 + 50); + reactor_quad[1].position = sf::Vector2f(window.getView().getSize().x * x_pos + 88, window.getView().getSize().y * 0.8 + 50); + reactor_quad[2].position = sf::Vector2f(window.getView().getSize().x * x_pos + 88, window.getView().getSize().y * 0.8 + 30); + reactor_quad[3].position = sf::Vector2f(window.getView().getSize().x * x_pos + 45, window.getView().getSize().y * 0.8 + 30); + reactor_quad[0].texCoords = sf::Vector2f(85.f, 96.f); + reactor_quad[1].texCoords = sf::Vector2f(170.f, 96.f); + reactor_quad[2].texCoords = sf::Vector2f(170.f, 56.f); + reactor_quad[3].texCoords = sf::Vector2f(85.f, 56.f); + + float reactor_red = 255 - (255 * ((float)mech_to_draw.reactor_integrity / (float)mech_to_draw.max_reactor_integrity)); + float reactor_green = 100 * ((float)mech_to_draw.reactor_integrity / (float)mech_to_draw.max_reactor_integrity); + for (int i = 0; i < 4; i++) + { + reactor_quad[i].color = sf::Color(reactor_red, reactor_green, 0, 255); + } + window.draw(reactor_quad, &resources.mech_status_texture); + + // Cooler + sf::VertexArray cooler_quad(sf::Quads, 4); + cooler_quad[0].position = sf::Vector2f(window.getView().getSize().x * x_pos + 45, window.getView().getSize().y * 0.8 + 70); + cooler_quad[1].position = sf::Vector2f(window.getView().getSize().x * x_pos + 88, window.getView().getSize().y * 0.8 + 70); + cooler_quad[2].position = sf::Vector2f(window.getView().getSize().x * x_pos + 88, window.getView().getSize().y * 0.8 + 50); + cooler_quad[3].position = sf::Vector2f(window.getView().getSize().x * x_pos + 45, window.getView().getSize().y * 0.8 + 50); + cooler_quad[0].texCoords = sf::Vector2f(85.f, 134.f); + cooler_quad[1].texCoords = sf::Vector2f(170.f, 134.f); + cooler_quad[2].texCoords = sf::Vector2f(170.f, 96.f); + cooler_quad[3].texCoords = sf::Vector2f(85.f, 96.f); + + float cooler_red = 255 - (255 * ((float)mech_to_draw.cooler_integrity / (float)mech_to_draw.max_cooler_integrity)); + float cooler_green = 100 * ((float)mech_to_draw.cooler_integrity / (float)mech_to_draw.max_cooler_integrity); + for (int i = 0; i < 4; i++) + { + cooler_quad[i].color = sf::Color(cooler_red, cooler_green, 0, 255); + } + window.draw(cooler_quad, &resources.mech_status_texture); + + // Right leg + sf::VertexArray right_leg_quad(sf::Quads, 4); + right_leg_quad[0].position = sf::Vector2f(window.getView().getSize().x * x_pos + 3, window.getView().getSize().y * 0.8 + 133); + right_leg_quad[1].position = sf::Vector2f(window.getView().getSize().x * x_pos + 67, window.getView().getSize().y * 0.8 + 133); + right_leg_quad[2].position = sf::Vector2f(window.getView().getSize().x * x_pos + 67, window.getView().getSize().y * 0.8 + 69); + right_leg_quad[3].position = sf::Vector2f(window.getView().getSize().x * x_pos + 3, window.getView().getSize().y * 0.8 + 69); + right_leg_quad[0].texCoords = sf::Vector2f(0.f, 256.f); + right_leg_quad[1].texCoords = sf::Vector2f(128.f, 256.f); + right_leg_quad[2].texCoords = sf::Vector2f(128.f, 131.f); + right_leg_quad[3].texCoords = sf::Vector2f(0.f, 131.f); + + float right_leg_red = 255 - (255 * ((float)mech_to_draw.right_leg_integrity / (float)mech_to_draw.max_right_leg_integrity)); + float right_leg_green = 100 * ((float)mech_to_draw.right_leg_integrity / (float)mech_to_draw.max_right_leg_integrity); + for (int i = 0; i < 4; i++) + { + right_leg_quad[i].color = sf::Color(right_leg_red, right_leg_green, 0, 255); + } + window.draw(right_leg_quad, &resources.mech_status_texture); + + // Left leg + sf::VertexArray left_leg_quad(sf::Quads, 4); + left_leg_quad[0].position = sf::Vector2f(window.getView().getSize().x * x_pos + 67, window.getView().getSize().y * 0.8 + 133); + left_leg_quad[1].position = sf::Vector2f(window.getView().getSize().x * x_pos + 131, window.getView().getSize().y * 0.8 + 133); + left_leg_quad[2].position = sf::Vector2f(window.getView().getSize().x * x_pos + 131, window.getView().getSize().y * 0.8 + 69); + left_leg_quad[3].position = sf::Vector2f(window.getView().getSize().x * x_pos + 67, window.getView().getSize().y * 0.8 + 69); + left_leg_quad[0].texCoords = sf::Vector2f(128.f, 256.f); + left_leg_quad[1].texCoords = sf::Vector2f(256.f, 256.f); + left_leg_quad[2].texCoords = sf::Vector2f(256.f, 131.f); + left_leg_quad[3].texCoords = sf::Vector2f(128.f, 131.f); + + float left_leg_red = 255 - (255 * ((float)mech_to_draw.left_leg_integrity / (float)mech_to_draw.max_left_leg_integrity)); + float left_leg_green = 100 * ((float)mech_to_draw.left_leg_integrity / (float)mech_to_draw.max_left_leg_integrity); + for (int i = 0; i < 4; i++) + { + left_leg_quad[i].color = sf::Color(left_leg_red, left_leg_green, 0, 255); + } + window.draw(left_leg_quad, &resources.mech_status_texture); +} + +void hud::draw_hud(sf::RenderWindow &window, float frame_time, int target_id, float speed, float torso_angle, mech &player_mech, mech &target_mech) +{ + sf::Sprite status_bg = sf::Sprite(resources.gui_background_texture); + status_bg.setPosition(0, window.getView().getSize().y * 0.786); + status_bg.setScale(window.getView().getSize().x / 2977, window.getView().getSize().y / 1600); + window.draw(status_bg); + + // Draw torso angle a the bottom right corner of the screen + int torso_angle_int = floor(torso_angle); + sf::String torso_string = "TORSO: " + std::to_string(torso_angle_int); + resources.torso_display.setString(torso_string); + resources.torso_display.setPosition(window.getView().getSize().x * 0.05, window.getView().getSize().y * 0.83); + window.draw(resources.torso_display); + + // Draw throttle percentage a the bottom right corner of the screen + int throttle = floor((speed) / 0.125 * 100); + sf::String throttle_string = "THROTTLE: " + std::to_string(throttle); + resources.throttle_display.setString(throttle_string); + resources.throttle_display.setPosition(window.getView().getSize().x * 0.05, window.getView().getSize().y * 0.86); + window.draw(resources.throttle_display); + + // Draw mech status at the bottom of the screen + sf::String status = + "MECH STATUS\n\nRIGHT LEG: " + std::to_string(player_mech.right_leg_integrity) + "\n" + + "LEFT LEG: " + std::to_string(player_mech.left_leg_integrity) + "\n" + + "RIGHT ARM: " + std::to_string(player_mech.right_arm_integrity) + "\n" + + "LEFT ARM: " + std::to_string(player_mech.left_arm_integrity) + "\n" + + "REACTOR: " + std::to_string(player_mech.reactor_integrity) + "\n" + + "COOLER: " + std::to_string(player_mech.cooler_integrity) + "\n" + + "COCKPIT: " + std::to_string(player_mech.cockpit_integrity) + "\n" + + "HEAT: " + std::to_string((int)player_mech.heat); + resources.mech_status.setString(status); + resources.mech_status.setPosition(window.getView().getSize().x * 0.15, window.getView().getSize().y * 0.80); + window.draw(resources.mech_status); + draw_mech(0.265, player_mech, window); + + // Draw player heat meter + sf::VertexArray heat_quad_bg(sf::Quads, 4); + heat_quad_bg[0].position = sf::Vector2f(window.getView().getSize().x * 0.265 + 178, window.getView().getSize().y * 0.825 + 106); + heat_quad_bg[1].position = sf::Vector2f(window.getView().getSize().x * 0.265 + 213, window.getView().getSize().y * 0.825 + 106); + heat_quad_bg[2].position = sf::Vector2f(window.getView().getSize().x * 0.265 + 213, window.getView().getSize().y * 0.825); + heat_quad_bg[3].position = sf::Vector2f(window.getView().getSize().x * 0.265 + 178, window.getView().getSize().y * 0.825); + for (int i = 0; i < 4; i++) + { + heat_quad_bg[i].color = sf::Color::Black; + } + window.draw(heat_quad_bg); + + sf::VertexArray heat_quad(sf::Quads, 4); + heat_quad[0].position = sf::Vector2f(window.getView().getSize().x * 0.265 + 180, window.getView().getSize().y * 0.83 + 100); + heat_quad[1].position = sf::Vector2f(window.getView().getSize().x * 0.265 + 212, window.getView().getSize().y * 0.83 + 100); + heat_quad[2].position = sf::Vector2f(window.getView().getSize().x * 0.265 + 212, window.getView().getSize().y * 0.83 + 100 - player_mech.heat); + heat_quad[3].position = sf::Vector2f(window.getView().getSize().x * 0.265 + 180, window.getView().getSize().y * 0.83 + 100 - player_mech.heat); + for (int i = 0; i < 4; i++) + { + heat_quad[i].color = sf::Color(200, 0, 0, 255); + } + window.draw(heat_quad); + + // Draw target status at the bottom of the screen + if (target_id != 0) + { + sf::Sprite status_bg = sf::Sprite(resources.target_gui_background_texture); + status_bg.setPosition(window.getView().getSize().x * 0.685, window.getView().getSize().y * 0.786); + status_bg.setScale(window.getView().getSize().x / 2285, window.getView().getSize().y / 1600); + window.draw(status_bg); + + sf::String status = + "TARGET STATUS\n\nRIGHT LEG: " + std::to_string(target_mech.right_leg_integrity) + "\n" + + "LEFT LEG: " + std::to_string(target_mech.left_leg_integrity) + "\n" + + "RIGHT ARM: " + std::to_string(target_mech.right_arm_integrity) + "\n" + + "LEFT ARM: " + std::to_string(target_mech.left_arm_integrity) + "\n" + + "REACTOR: " + std::to_string(target_mech.reactor_integrity) + "\n" + + "COOLER: " + std::to_string(target_mech.cooler_integrity) + "\n" + + "COCKPIT: " + std::to_string(target_mech.cockpit_integrity) + "\n" + + "HEAT: " + std::to_string((int)target_mech.heat); + resources.target_status.setString(status); + resources.target_status.setPosition(window.getView().getSize().x * 0.7, window.getView().getSize().y * 0.80); + window.draw(resources.target_status); + draw_mech(0.82, target_mech, window); + + // Draw target heat meter + sf::VertexArray heat_quad_bg(sf::Quads, 4); + heat_quad_bg[0].position = sf::Vector2f(window.getView().getSize().x * 0.82 + 178, window.getView().getSize().y * 0.825 + 106); + heat_quad_bg[1].position = sf::Vector2f(window.getView().getSize().x * 0.82 + 214, window.getView().getSize().y * 0.825 + 106); + heat_quad_bg[2].position = sf::Vector2f(window.getView().getSize().x * 0.82 + 214, window.getView().getSize().y * 0.825); + heat_quad_bg[3].position = sf::Vector2f(window.getView().getSize().x * 0.82 + 178, window.getView().getSize().y * 0.825); + for (int i = 0; i < 4; i++) + { + heat_quad_bg[i].color = sf::Color::Black; + } + window.draw(heat_quad_bg); + + sf::VertexArray heat_quad(sf::Quads, 4); + heat_quad[0].position = sf::Vector2f(window.getView().getSize().x * 0.82 + 180, window.getView().getSize().y * 0.83 + 100); + heat_quad[1].position = sf::Vector2f(window.getView().getSize().x * 0.82 + 212, window.getView().getSize().y * 0.83 + 100); + heat_quad[2].position = sf::Vector2f(window.getView().getSize().x * 0.82 + 212, window.getView().getSize().y * 0.83 + 100 - target_mech.heat); + heat_quad[3].position = sf::Vector2f(window.getView().getSize().x * 0.82 + 180, window.getView().getSize().y * 0.83 + 100 - target_mech.heat); + for (int i = 0; i < 4; i++) + { + heat_quad[i].color = sf::Color(200, 0, 0, 255); + } + window.draw(heat_quad); + } + + // Draw the crosshair + if (player_mech.destroyed() == false) + { + float chx = (window.getView().getSize().x / 2) - (resources.crosshair_texture.getSize().x / 2); + float chy = (window.getView().getSize().y / 2) - (resources.crosshair_texture.getSize().y / 2) * 3; + sf::Vector2f chv(chx, chy); + resources.crosshair_sprite.setPosition(chv); + window.draw(resources.crosshair_sprite); + } + + // Draw notices + if (show_notice == true) + { + display_notice(window, notice, frame_time); + } +} diff --git a/src/intermission_menu.cpp b/src/intermission_menu.cpp new file mode 100644 index 0000000..f5b89dc --- /dev/null +++ b/src/intermission_menu.cpp @@ -0,0 +1,1050 @@ +#include +#include +#include + +// Constructor +intermission_menu::intermission_menu() +{ + kp = 0; + spark_timer = 0; + start_game = false; + return_to_main = false; +} + +// Gets the current directory, initializes resources, market menu and settings menu +void intermission_menu::init(std::string cwd, assets &resources) +{ + this->cwd = cwd; + this->resources = resources; + market.init(cwd); + s_menu.init(cwd, resources, false); +} + +// Returns true if a prompt is displayed +bool intermission_menu::prompt_displayed() +{ + return save_prompt_open == true || load_prompt_open == true || repair_prompt_open == true; +} + +// Displays a notice with the given string +void intermission_menu::display_notice(sf::RenderWindow &window, std::string notice, float frame_time) +{ + sf::Vector2f notice_pos; + notice_pos.x = (window.getView().getSize().x / 2) - (resources.notice.getGlobalBounds().width / 2); + notice_pos.y = (window.getView().getSize().y / 2) - 100; + resources.notice.setString(notice); + resources.notice.setPosition(notice_pos); + window.draw(resources.notice); + + notice_timer += 10 * frame_time; + if (notice_timer >= 30) + { + notice_timer = 0; + show_notice = false; + market.show_notice = false; + } +} + +// Draws butons associated with saved games +void intermission_menu::draw_saved_game_buttons(sf::RenderWindow &window) +{ + float x = window.getView().getSize().x / 2 - 150; + + for (unsigned int i = 0; i < saved_game_labels.size(); i++) + { + saved_game_buttons[i] = sf::VertexArray(sf::Quads, 4); + saved_game_buttons[i][0].position = sf::Vector2f(x, (200 + i * 35) - 4); + saved_game_buttons[i][1].position = sf::Vector2f(x, (200 + i * 35) + 24); + saved_game_buttons[i][2].position = sf::Vector2f(x + 225, (200 + i * 35) + 24); + saved_game_buttons[i][3].position = sf::Vector2f(x + 225, (200 + i * 35) - 4); + + sf::VertexArray saved_game_shadow = sf::VertexArray(sf::Quads, 4); + saved_game_shadow[0].position = sf::Vector2f(x, (200 + i * 35) - 4); + saved_game_shadow[1].position = sf::Vector2f(x, (200 + i * 35) + 27); + saved_game_shadow[2].position = sf::Vector2f(x + 228, (200 + i * 35) + 27); + saved_game_shadow[3].position = sf::Vector2f(x + 228, (200 + i * 35) - 4); + + saved_game_shadow[0].color = sf::Color::Black; + saved_game_shadow[1].color = sf::Color::Black; + saved_game_shadow[2].color = sf::Color::Black; + saved_game_shadow[3].color = sf::Color::Black; + + if (saved_game_buttons[i].getBounds().contains(mouse_position.x, mouse_position.y)) + { + saved_game_buttons[i][0].color = sf::Color(53, 53, 53, 255); + saved_game_buttons[i][1].color = sf::Color(53, 53, 53, 255); + saved_game_buttons[i][2].color = sf::Color(53, 53, 53, 255); + saved_game_buttons[i][3].color = sf::Color(53, 53, 53, 255); + } + else + { + saved_game_buttons[i][0].color = sf::Color(35, 35, 35, 255); + saved_game_buttons[i][1].color = sf::Color(35, 35, 35, 255); + saved_game_buttons[i][2].color = sf::Color(35, 35, 35, 255); + saved_game_buttons[i][3].color = sf::Color(35, 35, 35, 255); + } + + saved_game_labels[i].setFont(resources.exoplanetaria); + saved_game_labels[i].setCharacterSize(16); + saved_game_labels[i].setFillColor(sf::Color::Black); + saved_game_labels[i].setPosition(x + 20, 200 + (i * 35)); + + if (saved_game_labels[i].getString() != "") + { + window.draw(saved_game_shadow); + window.draw(saved_game_buttons[i]); + window.draw(saved_game_labels[i]); + } + } +} + +// Draws buttons used to delete saved games +void intermission_menu::draw_delete_buttons(sf::RenderWindow &window) +{ + float x = window.getView().getSize().x / 2 + 100; + + for (unsigned int i = 0; i < saved_game_labels.size(); i++) + { + delete_save_buttons[i] = sf::VertexArray(sf::Quads, 4); + delete_save_buttons[i][0].position = sf::Vector2f(x, (200 + i * 35) - 4); + delete_save_buttons[i][1].position = sf::Vector2f(x, (200 + i * 35) + 24); + delete_save_buttons[i][2].position = sf::Vector2f(x + 70, (200 + i * 35) + 24); + delete_save_buttons[i][3].position = sf::Vector2f(x + 70, (200 + i * 35) - 4); + + sf::VertexArray delete_save_shadow = sf::VertexArray(sf::Quads, 4); + delete_save_shadow[0].position = sf::Vector2f(x, (200 + i * 35) - 4); + delete_save_shadow[1].position = sf::Vector2f(x, (200 + i * 35) + 27); + delete_save_shadow[2].position = sf::Vector2f(x + 73, (200 + i * 35) + 27); + delete_save_shadow[3].position = sf::Vector2f(x + 73, (200 + i * 35) - 4); + + delete_save_shadow[0].color = sf::Color::Black; + delete_save_shadow[1].color = sf::Color::Black; + delete_save_shadow[2].color = sf::Color::Black; + delete_save_shadow[3].color = sf::Color::Black; + + if (delete_save_buttons[i].getBounds().contains(mouse_position.x, mouse_position.y)) + { + delete_save_buttons[i][0].color = sf::Color(53, 53, 53, 255); + delete_save_buttons[i][1].color = sf::Color(53, 53, 53, 255); + delete_save_buttons[i][2].color = sf::Color(53, 53, 53, 255); + delete_save_buttons[i][3].color = sf::Color(53, 53, 53, 255); + } + else + { + delete_save_buttons[i][0].color = sf::Color(35, 35, 35, 255); + delete_save_buttons[i][1].color = sf::Color(35, 35, 35, 255); + delete_save_buttons[i][2].color = sf::Color(35, 35, 35, 255); + delete_save_buttons[i][3].color = sf::Color(35, 35, 35, 255); + } + + delete_save_labels[i].setFont(resources.exoplanetaria); + delete_save_labels[i].setCharacterSize(16); + delete_save_labels[i].setFillColor(sf::Color::Black); + delete_save_labels[i].setPosition(x + 10, 200 + (i * 35)); + delete_save_labels[i].setString("DELETE"); + + if (saved_game_labels[i].getString() != "") + { + window.draw(delete_save_shadow); + window.draw(delete_save_buttons[i]); + window.draw(delete_save_labels[i]); + } + } +} + +// Returns saved game data as a single string +std::string intermission_menu::get_save_data(player_controller &pc) +{ + return std::to_string(pc.credits) + "\n" + + std::to_string(pc.mission) + "\n" + + std::to_string(pc.player_mech.cockpit_integrity) + "\n" + + std::to_string(pc.player_mech.reactor_integrity) + "\n" + + std::to_string(pc.player_mech.cooler_integrity)+ "\n" + + std::to_string(pc.player_mech.left_arm_integrity) + "\n" + + std::to_string(pc.player_mech.right_arm_integrity) + "\n" + + std::to_string(pc.player_mech.left_leg_integrity) + "\n" + + std::to_string(pc.player_mech.right_leg_integrity) + "\n" + + std::to_string(pc.player_mech.max_cockpit_integrity) + "\n" + + std::to_string(pc.player_mech.max_reactor_integrity) + "\n" + + std::to_string(pc.player_mech.max_cooler_integrity) + "\n" + + std::to_string(pc.player_mech.max_left_arm_integrity) + "\n" + + std::to_string(pc.player_mech.max_right_arm_integrity) + "\n" + + std::to_string(pc.player_mech.max_left_leg_integrity) + "\n" + + std::to_string(pc.player_mech.max_right_leg_integrity) + "\n" + + std::to_string(pc.player_mech.cooler_modifier) + "\n" + + std::to_string(pc.player_mech.guns_modifier) + "\n" + + std::to_string(pc.player_mech.cannons_modifier) + "\n" + + std::to_string(pc.player_mech.weight) + "\n" + + pc.player_mech.primary_weapon + "\n" + + pc.player_mech.secondary_weapon + "\n" + + pc.player_mech.reactor + "\n" + + pc.player_mech.cooler + "\n" + + pc.player_mech.left_leg + "\n" + + pc.player_mech.right_leg + "\n" + + pc.player_mech.left_arm + "\n" + + pc.player_mech.right_arm + "\n" + + pc.player_mech.cockpit; +} + +// Creates a new save game +void intermission_menu::create_save(player_controller &pc) +{ + std::string saves = get_file_contents(cwd + "/save/saves.list"); + std::string delimiter = "\n"; + std::string token; + + int index = 0; + size_t pos = 0; + while ((pos = saves.find(delimiter)) != std::string::npos) + { + token = saves.substr(0, pos); + saves.erase(0, pos + delimiter.length()); + index++; + } + + if (index < 10) + { + std::string save = append_file(cwd + "/save/saves.list", input); + std::string result = write_to_file(cwd + "/save/" + input + ".sav", get_save_data(pc)); + save_prompt_open = false; + create_save_prompt_open = false; + notice = "GAME SAVED"; + show_notice = true; + } + else + { + notice = "SAVE LIMIT REACHED"; + show_notice = true; + } + + input = ""; + resources.input_text.setString(input); +} + +// Overwrites an existing save game +void intermission_menu::save_game(player_controller &pc, int i) +{ + std::string result = write_to_file(cwd + "/save/" + saved_game_labels[i].getString() + ".sav", get_save_data(pc)); + save_prompt_open = false; + notice = "GAME SAVED"; + show_notice = true; +} + +// Loads a saved game +void intermission_menu::load_game(std::string cwd, std::string file, player_controller &pc) +{ + int index = 0; + size_t pos = 0; + std::string token; + std::string delimiter = "\n"; + std::vector values(30); + std::string data = get_file_contents(cwd + "/save/" + file + ".sav"); + + while ((pos = data.find(delimiter)) != std::string::npos) + { + values[index] = data.substr(0, pos); + data.erase(0, pos + delimiter.length()); + index++; + } + + pc.credits = std::stoi(values[0]); + pc.mission = std::stoi(values[1]); + pc.player_mech.cockpit_integrity = std::stoi(values[2]); + pc.player_mech.reactor_integrity = std::stoi(values[3]); + pc.player_mech.cooler_integrity = std::stoi(values[4]); + pc.player_mech.left_arm_integrity = std::stoi(values[5]); + pc.player_mech.right_arm_integrity = std::stoi(values[6]); + pc.player_mech.left_leg_integrity = std::stoi(values[7]); + pc.player_mech.right_leg_integrity = std::stoi(values[8]); + pc.player_mech.max_cockpit_integrity = std::stoi(values[9]); + pc.player_mech.max_reactor_integrity = std::stoi(values[10]); + pc.player_mech.max_cooler_integrity = std::stoi(values[11]); + pc.player_mech.max_left_arm_integrity = std::stoi(values[12]); + pc.player_mech.max_right_arm_integrity = std::stoi(values[13]); + pc.player_mech.max_left_leg_integrity = std::stoi(values[14]); + pc.player_mech.max_right_leg_integrity = std::stoi(values[15]); + pc.player_mech.cooler_modifier = std::stoi(values[16]); + pc.player_mech.guns_modifier = std::stoi(values[17]); + pc.player_mech.cannons_modifier = std::stoi(values[18]); + pc.player_mech.weight = std::stoi(values[19]); + pc.player_mech.primary_weapon = values[20]; + pc.player_mech.secondary_weapon = values[21]; + pc.player_mech.reactor = values[22]; + pc.player_mech.cooler = values[23]; + pc.player_mech.left_leg = values[24]; + pc.player_mech.right_leg = values[25]; + pc.player_mech.left_arm = values[26]; + pc.player_mech.right_arm = values[27]; + pc.player_mech.cockpit = values[28]; +} + +// Deletes a saved game +void intermission_menu::delete_save_game(int i) +{ + std::string save_to_delete = cwd + "/save/" + saved_game_labels[i].getString() + ".sav"; + char file [100]; + sprintf(file, "%s", save_to_delete.c_str()); + std::remove(file); + std::string saves = get_file_contents(cwd + "/save/saves.list"); + std::string delimiter = "\n"; + std::string new_saves; + std::string token; + size_t pos = 0; + while ((pos = saves.find(delimiter)) != std::string::npos) + { + token = saves.substr(0, pos); + if (token != saved_game_labels[i].getString()) + { + new_saves += token + "\n"; + } + saves.erase(0, pos + delimiter.length()); + } + new_saves.erase(new_saves.find_last_not_of(" \n\r\t")+1); + write_to_file(cwd + "/save/saves.list", new_saves); + notice = "SAVE DELETED"; + show_notice = true; +} + +// Resets all game related progress +void intermission_menu::reset_game(player_controller &pc) +{ + pc.credits = 0; + pc.mission = 1; + pc.player_mech.cockpit_integrity = 1000; + pc.player_mech.reactor_integrity = 1000; + pc.player_mech.cooler_integrity = 1000; + pc.player_mech.left_arm_integrity = 1000; + pc.player_mech.right_arm_integrity = 1000; + pc.player_mech.left_leg_integrity = 1000; + pc.player_mech.right_leg_integrity = 1000; + pc.player_mech.max_cockpit_integrity = 1000; + pc.player_mech.max_reactor_integrity = 1000; + pc.player_mech.max_cooler_integrity = 1000; + pc.player_mech.max_left_arm_integrity = 1000; + pc.player_mech.max_right_arm_integrity = 1000; + pc.player_mech.max_left_leg_integrity = 1000; + pc.player_mech.max_right_leg_integrity = 1000; + pc.player_mech.cooler_modifier = 0; + pc.player_mech.guns_modifier = 0; + pc.player_mech.cannons_modifier = 0; + pc.player_mech.weight = 70; + pc.player_mech.primary_weapon = "Standard Pulse Laser"; + pc.player_mech.secondary_weapon = "Standard Autocannon"; + pc.player_mech.reactor = "Standard Reactor"; + pc.player_mech.cooler = "Standard Cooler"; + pc.player_mech.left_leg = "Standard Left Leg"; + pc.player_mech.right_leg = "Standard Right Leg"; + pc.player_mech.left_arm = "Standard Left Arm"; + pc.player_mech.right_arm = "Standard Right Arm"; + pc.player_mech.cockpit = "Standard Cockpit"; +} + +// Draws the repair menu +void intermission_menu::draw_repair_menu(sf::RenderWindow &window, player_controller &pc) +{ + // Title + int cost_to_repair = 10 * (pc.player_mech.max_total_integrity() - pc.player_mech.total_integrity()); + sf::Vector2f notice_pos; + notice_pos.x = (window.getView().getSize().x / 2) - (resources.notice.getGlobalBounds().width / 2); + notice_pos.y = (window.getView().getSize().y / 2) - 120; + if (cost_to_repair > 0) + { + resources.notice.setString("Repairing your mech will cost " + std::to_string(cost_to_repair) + " credits."); + } + else + { + resources.notice.setString("Your mech is not in need of repair."); + } + resources.notice.setPosition(notice_pos); + window.draw(resources.notice); + + // Repair Button + if (resources.repair_button_sprite.getGlobalBounds().contains(mouse_position.x, mouse_position.y)) + { + resources.repair_button_sprite.setTexture(resources.repair_button_hover_texture); + } + else + { + resources.repair_button_sprite.setTexture(resources.repair_button_texture); + } + float b3x = (window.getView().getSize().x / 2) - (resources.repair_button_texture.getSize().x / 2); + float b3y = (window.getView().getSize().y / 2) - 20; + sf::Vector2f b3v(b3x, b3y); + resources.repair_button_sprite.setPosition(b3v); + window.draw(resources.repair_button_sprite); + + // Cancel Button + if (resources.cancel_button_sprite.getGlobalBounds().contains(mouse_position.x, mouse_position.y)) + { + resources.cancel_button_sprite.setTexture(resources.cancel_button_hover_texture); + } + else + { + resources.cancel_button_sprite.setTexture(resources.cancel_button_texture); + } + float cx = (window.getView().getSize().x / 2) - (resources.cancel_button_texture.getSize().x / 2); + float cy = (window.getView().getSize().y / 2) + 20; + sf::Vector2f cv(cx, cy); + resources.cancel_button_sprite.setPosition(cv); + window.draw(resources.cancel_button_sprite); +} + +// Draws the save game menu +void intermission_menu::draw_save_menu(sf::RenderWindow &window) +{ + if (create_save_prompt_open == true) + { + sf::Vector2f term_pos; + sf::Vector2f text_pos; + term_pos.x = (window.getView().getSize().x / 2) - (resources.term_sprite.getTexture()->getSize().x / 2); + term_pos.y = (window.getView().getSize().y / 2) - 70; + text_pos.x = term_pos.x + 8; + text_pos.y = term_pos.y + 8; + resources.term_sprite.setPosition(term_pos); + resources.input_text.setPosition(text_pos); + window.draw(resources.term_sprite); + window.draw(resources.input_text); + + sf::Vector2f notice_pos; + notice_pos.x = (window.getView().getSize().x / 2) - (resources.notice.getGlobalBounds().width / 2); + notice_pos.y = (window.getView().getSize().y / 2) - 120; + resources.notice.setString("Enter a name for your saved game."); + resources.notice.setPosition(notice_pos); + window.draw(resources.notice); + + // Save Button + if (resources.save_game_button_sprite.getGlobalBounds().contains(mouse_position.x, mouse_position.y)) + { + resources.save_game_button_sprite.setTexture(resources.save_game_button_hover_texture); + } + else + { + resources.save_game_button_sprite.setTexture(resources.save_game_button_texture); + } + float b3x = (window.getView().getSize().x / 2) - (resources.save_game_button_texture.getSize().x / 2); + float b3y = (window.getView().getSize().y / 2) - 20; + sf::Vector2f b3v(b3x, b3y); + resources.save_game_button_sprite.setPosition(b3v); + window.draw(resources.save_game_button_sprite); + + // Cancel Button + if (resources.cancel_button_sprite.getGlobalBounds().contains(mouse_position.x, mouse_position.y)) + { + resources.cancel_button_sprite.setTexture(resources.cancel_button_hover_texture); + } + else + { + resources.cancel_button_sprite.setTexture(resources.cancel_button_texture); + } + float b4x = (window.getView().getSize().x / 2) - (resources.load_game_button_texture.getSize().x / 2); + float b4y = (window.getView().getSize().y / 2) + 20; + sf::Vector2f b4v(b4x, b4y); + resources.cancel_button_sprite.setPosition(b4v); + window.draw(resources.cancel_button_sprite); + } + else + { + // Create new save button + if (resources.create_new_button_sprite.getGlobalBounds().contains(mouse_position.x, mouse_position.y)) + { + resources.create_new_button_sprite.setTexture(resources.create_new_button_hover_texture); + } + else + { + resources.create_new_button_sprite.setTexture(resources.create_new_button_texture); + } + float bx = (window.getView().getSize().x / 2) - (resources.create_new_button_texture.getSize().x / 2); + float by = 150; + sf::Vector2f bv(bx, by); + resources.create_new_button_sprite.setPosition(bv); + window.draw(resources.create_new_button_sprite); + + // Cancel button + if (resources.cancel_button_sprite.getGlobalBounds().contains(mouse_position.x, mouse_position.y)) + { + resources.cancel_button_sprite.setTexture(resources.cancel_button_hover_texture); + } + else + { + resources.cancel_button_sprite.setTexture(resources.cancel_button_texture); + } + float cx = (window.getView().getSize().x / 2) - (resources.cancel_button_texture.getSize().x / 2); + float cy = 100; + sf::Vector2f cv(cx, cy); + resources.cancel_button_sprite.setPosition(cv); + window.draw(resources.cancel_button_sprite); + + int index = 0; + size_t pos = 0; + std::string saves = get_file_contents(cwd + "/save/saves.list"); + std::string delimiter = "\n"; + std::string token; + + // Get the number of saved games + while ((pos = saves.find(delimiter)) != std::string::npos) + { + token = saves.substr(0, pos); + saves.erase(0, pos + delimiter.length()); + index++; + } + + // Resize arrays + saved_game_buttons.resize(index); + saved_game_labels.resize(index); + delete_save_buttons.resize(index); + delete_save_labels.resize(index); + + // Reset variables + pos = 0; + index = 0; + saves = get_file_contents(cwd + "/save/saves.list"); + + // Create text objects for all existing save files + while ((pos = saves.find(delimiter)) != std::string::npos) + { + token = saves.substr(0, pos); + saved_game_labels[index].setString(token); + saves.erase(0, pos + delimiter.length()); + index++; + } + + // Save game buttons + draw_saved_game_buttons(window); + + // Delete save buttons + draw_delete_buttons(window); + } +} + +// Draws the load game menu +void intermission_menu::draw_load_menu(sf::RenderWindow &window) +{ + int index = 0; + size_t pos = 0; + std::string saves = get_file_contents(cwd + "/save/saves.list"); + std::string delimiter = "\n"; + std::string token; + + // Get the number of saved games + while ((pos = saves.find(delimiter)) != std::string::npos) + { + token = saves.substr(0, pos); + saves.erase(0, pos + delimiter.length()); + index++; + } + + // Resize arrays + saved_game_buttons.resize(index); + saved_game_labels.resize(index); + delete_save_buttons.resize(index); + delete_save_labels.resize(index); + + // Reset variables + pos = 0; + index = 0; + saves = get_file_contents(cwd + "/save/saves.list"); + + // Create text objects for all existing save files + while ((pos = saves.find(delimiter)) != std::string::npos) + { + token = saves.substr(0, pos); + saved_game_labels[index].setString(token); + saves.erase(0, pos + delimiter.length()); + index++; + } + + // Load game buttons + draw_saved_game_buttons(window); + + // Delete save buttons + draw_delete_buttons(window); + + // Cancel Button + if (resources.cancel_button_sprite.getGlobalBounds().contains(mouse_position.x, mouse_position.y)) + { + resources.cancel_button_sprite.setTexture(resources.cancel_button_hover_texture); + } + else + { + resources.cancel_button_sprite.setTexture(resources.cancel_button_texture); + } + float bx = (window.getView().getSize().x / 2) - (resources.cancel_button_texture.getSize().x / 2); + float by = 150; + sf::Vector2f bv(bx, by); + resources.cancel_button_sprite.setPosition(bv); + window.draw(resources.cancel_button_sprite); +} + +// Handles all drawing and interaction with the menu +bool intermission_menu::draw_menu(sf::RenderWindow &window, player_controller &pc, float frame_time) +{ + if (start_game == false && return_to_main == false) + { + // Play intermission music + resources.intermission_music.setVolume(50 * audio_volume); + + if (resources.intermission_music.getStatus() != sf::Sound::Playing) + { + resources.intermission_music.play(); + } + + // Process events + sf::Event event; + while (window.pollEvent(event)) + { + // Close window : exit + if (event.type == sf::Event::Closed) + { + window.close(); + } + + if(event.type == sf::Event::MouseMoved) + { + mouse_position = sf::Mouse().getPosition(window); + } + + if (event.type == sf::Event::MouseButtonPressed) + { + if(event.mouseButton.button == sf::Mouse::Left) + { + if (prompt_displayed() == false && show_notice == false && market.visible == false && s_menu.visible == false) + { + if (resources.next_mission_button_sprite.getGlobalBounds().contains(mouse_position.x, mouse_position.y)) + { + if (pc.player_mech.destroyed() == false) + { + resources.intermission_music.stop(); + start_game = true; + } + else + { + notice = "YOUR MECH IS INOPERABLE"; + show_notice = true; + } + } + + if (resources.repair_button_sprite.getGlobalBounds().contains(mouse_position.x, mouse_position.y)) + { + repair_prompt_open = true; + } + + if (resources.market_button_sprite.getGlobalBounds().contains(mouse_position.x, mouse_position.y)) + { + market.visible = true; + } + + if (resources.save_game_button_sprite.getGlobalBounds().contains(mouse_position.x, mouse_position.y)) + { + save_prompt_open = true; + } + + if (resources.load_game_button_sprite.getGlobalBounds().contains(mouse_position.x, mouse_position.y)) + { + load_prompt_open = true; + } + + if (resources.options_button_sprite.getGlobalBounds().contains(mouse_position.x, mouse_position.y)) + { + s_menu.visible = true; + } + + if (resources.main_menu_button_sprite.getGlobalBounds().contains(mouse_position.x, mouse_position.y)) + { + resources.intermission_music.stop(); + reset_game(pc); + return_to_main = true; + } + } + else if (save_prompt_open == true) + { + if (create_save_prompt_open == true) + { + if (resources.save_game_button_sprite.getGlobalBounds().contains(mouse_position.x, mouse_position.y)) + { + create_save(pc); + } + + if (resources.cancel_button_sprite.getGlobalBounds().contains(mouse_position.x, mouse_position.y)) + { + create_save_prompt_open = false; + } + } + else + { + if (resources.create_new_button_sprite.getGlobalBounds().contains(mouse_position.x, mouse_position.y)) + { + create_save_prompt_open = true; + } + + if (resources.cancel_button_sprite.getGlobalBounds().contains(mouse_position.x, mouse_position.y)) + { + save_prompt_open = false; + } + + for (unsigned int i = 0; i < saved_game_labels.size(); i++) + { + if (saved_game_buttons[i].getBounds().contains(mouse_position.x, mouse_position.y)) + { + save_game(pc, i); + } + } + + for (unsigned int i = 0; i < delete_save_labels.size(); i++) + { + if (delete_save_buttons[i].getBounds().contains(mouse_position.x, mouse_position.y)) + { + delete_save_game(i); + save_prompt_open = false; + } + } + } + } + else if (load_prompt_open == true) + { + if (resources.cancel_button_sprite.getGlobalBounds().contains(mouse_position.x, mouse_position.y)) + { + load_prompt_open = false; + } + + for (unsigned int i = 0; i < saved_game_labels.size(); i++) + { + if (saved_game_buttons[i].getBounds().contains(mouse_position.x, mouse_position.y)) + { + load_game(cwd, saved_game_labels[i].getString(), pc); + load_prompt_open = false; + notice = "GAME LOADED"; + show_notice = true; + } + } + + for (unsigned int i = 0; i < delete_save_labels.size(); i++) + { + if (delete_save_buttons[i].getBounds().contains(mouse_position.x, mouse_position.y)) + { + delete_save_game(i); + load_prompt_open = false; + } + } + } + else if (repair_prompt_open == true) + { + if (resources.repair_button_sprite.getGlobalBounds().contains(mouse_position.x, mouse_position.y)) + { + int cost_to_repair = 10 * (pc.player_mech.max_total_integrity() - pc.player_mech.total_integrity()); + if (cost_to_repair > 0) + { + if (pc.credits >= cost_to_repair) + { + pc.credits -= cost_to_repair; + pc.player_mech.repair(); + resources.purchase_sound.setVolume(100 * audio_volume); + resources.purchase_sound.play(); + repair_prompt_open = false; + notice = "MECH REPAIRED"; + show_notice = true; + } + else + { + notice = "INSUFFICIENT FUNDS"; + show_notice = true; + } + } + } + + if (resources.cancel_button_sprite.getGlobalBounds().contains(mouse_position.x, mouse_position.y)) + { + repair_prompt_open = false; + } + } + else if (market.visible == true) + { + market.handle_events(event, pc, mouse_position); + } + else if (s_menu.visible == true) + { + s_menu.handle_events(event, mouse_position); + } + } + } + + if (event.type == sf::Event::TextEntered && save_prompt_open == true) + { + if (event.text.unicode != '\b' && event.text.unicode != '`' && input.getSize() < 24) + { + input += event.text.unicode; + resources.input_text.setString(input); + kp++; + } + } + + if (event.type == sf::Event::KeyPressed) + { + if (save_prompt_open == true) + { + if (event.key.code == sf::Keyboard::Return) + { + input += "\n"; + resources.input_text.setString(input); + kp = 0; + } + + if (event.key.code == sf::Keyboard::BackSpace) + { + if (input.getSize() > 0) + { + input.erase(input.getSize() - 1, 1); + resources.input_text.setString(input); + } + } + + if (event.key.code == sf::Keyboard::Escape) + { + save_prompt_open = false; + } + } + else if (load_prompt_open == true) + { + if (event.key.code == sf::Keyboard::Escape) + { + load_prompt_open = false; + } + } + else if (repair_prompt_open == true) + { + if (event.key.code == sf::Keyboard::Escape) + { + repair_prompt_open = false; + } + } + else if (market.visible == true) + { + if (event.key.code == sf::Keyboard::Escape) + { + market.visible = false; + } + } + else if (s_menu.visible == true) + { + if (event.key.code == sf::Keyboard::Escape) + { + s_menu.visible = false; + } + } + } + } + window.clear(); + + // Draw the background + resources.menu_background_sprite.setPosition(0,0); + resources.menu_background_sprite.setScale( + window.getView().getSize().x / resources.menu_background_sprite.getTexture()->getSize().x, + window.getView().getSize().y / resources.menu_background_sprite.getTexture()->getSize().y); + window.draw(resources.menu_background_sprite); + + // Randomly display welding sparks for the mech being repaired in the background + spark_timer += 10 * frame_time; + if (spark_timer >= 10) + { + spark_timer = 0; + int random_spark = rand() % 90; + + if (random_spark >= 0 && random_spark < 30) + { + resources.menu_mech_sprite.setTexture(resources.menu_mech_texture); + } + else if (random_spark >= 30 && random_spark < 60) + { + resources.menu_mech_sprite.setTexture(resources.menu_mech_spark_1_texture); + } + else if (random_spark >= 60) + { + resources.menu_mech_sprite.setTexture(resources.menu_mech_spark_2_texture); + } + } + resources.menu_mech_sprite.setScale(1.1, 1.1); + float mech_x = window.getView().getSize().x / 2 - ((resources.menu_mech_sprite.getTexture()->getSize().x * 1.1) / 2); + float mech_y = window.getView().getSize().y - 550; + sf::Vector2f mech_position = sf::Vector2f(mech_x, mech_y); + resources.menu_mech_sprite.setPosition(mech_position); + window.draw(resources.menu_mech_sprite); + + // Draw saved game information + sf::Sprite bg_sprite = sf::Sprite(resources.gui_background_2_texture); + bg_sprite.setPosition(10, window.getView().getSize().y * 0.23); + bg_sprite.setScale(0.24, 1); + window.draw(bg_sprite); + + sf::String status = + "CREDITS: " + std::to_string(pc.credits) + "\n" + + "MISSION: " + std::to_string(pc.mission) + "\n\n" + + "MECH LOADOUT\n\nWEIGHT: " + std::to_string(pc.player_mech.weight) + "/110" + "\n" + + "PRIMARY WEAPON: " + pc.player_mech.primary_weapon+ " +" + std::to_string(pc.player_mech.guns_modifier) + "\n" + + "SECONDARY WEAPON: " + pc.player_mech.secondary_weapon + " +" + std::to_string(pc.player_mech.cannons_modifier) + "\n" + + "COCKPIT: " + pc.player_mech.cockpit + "\n" + + "REACTOR: " + pc.player_mech.reactor + "\n" + + "COOLER: " + pc.player_mech.cooler + " +" + std::to_string(pc.player_mech.cooler_modifier) + "\n" + + "LEFT ARM: " + pc.player_mech.left_arm + "\n" + + "RIGHT ARM: " + pc.player_mech.right_arm + "\n" + + "LEFT LEG: " + pc.player_mech.left_leg + "\n" + + "RIGHT LEG: " + pc.player_mech.right_leg + "\n\n" + + "MECH STATUS\n\nRIGHT LEG: " + std::to_string(pc.player_mech.right_leg_integrity) + " / " + std::to_string(pc.player_mech.max_right_leg_integrity) + "\n" + + "LEFT LEG: " + std::to_string(pc.player_mech.left_leg_integrity) + " / " + std::to_string(pc.player_mech.max_left_leg_integrity) + "\n" + + "RIGHT ARM: " + std::to_string(pc.player_mech.right_arm_integrity) + " / " + std::to_string(pc.player_mech.max_right_arm_integrity) + "\n" + + "LEFT ARM: " + std::to_string(pc.player_mech.left_arm_integrity) + " / " + std::to_string(pc.player_mech.max_left_arm_integrity) + "\n" + + "REACTOR: " + std::to_string(pc.player_mech.reactor_integrity) + " / " + std::to_string(pc.player_mech.max_reactor_integrity) + "\n" + + "COOLER: " + std::to_string(pc.player_mech.cooler_integrity) + " / " + std::to_string(pc.player_mech.max_cooler_integrity) + "\n" + + "COCKPIT: " + std::to_string(pc.player_mech.cockpit_integrity) + " / " + std::to_string(pc.player_mech.max_cockpit_integrity); + resources.mech_status.setString(status); + resources.mech_status.setPosition(20, window.getView().getSize().y * 0.25); + window.draw(resources.mech_status); + + if (prompt_displayed() == false && show_notice == false && market.visible == false && s_menu.visible == false) + { + // Next Mission + if (resources.next_mission_button_sprite.getGlobalBounds().contains(mouse_position.x, mouse_position.y)) + { + resources.next_mission_button_sprite.setTexture(resources.next_mission_button_hover_texture); + } + else + { + resources.next_mission_button_sprite.setTexture(resources.next_mission_button_texture); + } + float bx = (window.getView().getSize().x / 2) - (resources.next_mission_button_texture.getSize().x / 2); + float by = resources.menu_mech_sprite.getPosition().y - 120; + sf::Vector2f bv(bx, by); + resources.next_mission_button_sprite.setPosition(bv); + window.draw(resources.next_mission_button_sprite); + + // Repair + if (resources.repair_button_sprite.getGlobalBounds().contains(mouse_position.x, mouse_position.y)) + { + resources.repair_button_sprite.setTexture(resources.repair_button_hover_texture); + } + else + { + resources.repair_button_sprite.setTexture(resources.repair_button_texture); + } + float b2x = (window.getView().getSize().x / 2) - (resources.repair_button_texture.getSize().x / 2); + float b2y = resources.menu_mech_sprite.getPosition().y - 70; + sf::Vector2f b2v(b2x, b2y); + resources.repair_button_sprite.setPosition(b2v); + window.draw(resources.repair_button_sprite); + + // Market + if (resources.market_button_sprite.getGlobalBounds().contains(mouse_position.x, mouse_position.y)) + { + resources.market_button_sprite.setTexture(resources.market_button_hover_texture); + } + else + { + resources.market_button_sprite.setTexture(resources.market_button_texture); + } + float b3x = (window.getView().getSize().x / 2) - (resources.market_button_texture.getSize().x / 2); + float b3y = resources.menu_mech_sprite.getPosition().y - 20; + sf::Vector2f b3v(b3x, b3y); + resources.market_button_sprite.setPosition(b3v); + window.draw(resources.market_button_sprite); + + // Save + if (resources.save_game_button_sprite.getGlobalBounds().contains(mouse_position.x, mouse_position.y)) + { + resources.save_game_button_sprite.setTexture(resources.save_game_button_hover_texture); + } + else + { + resources.save_game_button_sprite.setTexture(resources.save_game_button_texture); + } + float b4x = (window.getView().getSize().x / 2) - (resources.save_game_button_texture.getSize().x / 2); + float b4y = resources.menu_mech_sprite.getPosition().y + 30; + sf::Vector2f b4v(b4x, b4y); + resources.save_game_button_sprite.setPosition(b4v); + window.draw(resources.save_game_button_sprite); + + // Load + if (resources.load_game_button_sprite.getGlobalBounds().contains(mouse_position.x, mouse_position.y)) + { + resources.load_game_button_sprite.setTexture(resources.load_game_button_hover_texture); + } + else + { + resources.load_game_button_sprite.setTexture(resources.load_game_button_texture); + } + float b5x = (window.getView().getSize().x / 2) - (resources.load_game_button_texture.getSize().x / 2); + float b5y = resources.menu_mech_sprite.getPosition().y + 80; + sf::Vector2f b5v(b5x, b5y); + resources.load_game_button_sprite.setPosition(b5v); + window.draw(resources.load_game_button_sprite); + + // Options + if (resources.options_button_sprite.getGlobalBounds().contains(mouse_position.x, mouse_position.y)) + { + resources.options_button_sprite.setTexture(resources.options_button_hover_texture); + } + else + { + resources.options_button_sprite.setTexture(resources.options_button_texture); + } + float b6x = (window.getView().getSize().x / 2) - (resources.options_button_texture.getSize().x / 2); + float b6y = resources.menu_mech_sprite.getPosition().y + 130; + sf::Vector2f b6v(b6x, b6y); + resources.options_button_sprite.setPosition(b6v); + window.draw(resources.options_button_sprite); + + // Main Menu + if (resources.main_menu_button_sprite.getGlobalBounds().contains(mouse_position.x, mouse_position.y)) + { + resources.main_menu_button_sprite.setTexture(resources.main_menu_button_hover_texture); + } + else + { + resources.main_menu_button_sprite.setTexture(resources.main_menu_button_texture); + } + float b7x = (window.getView().getSize().x / 2) - (resources.main_menu_button_texture.getSize().x / 2); + float b7y = resources.menu_mech_sprite.getPosition().y + 180; + sf::Vector2f b7v(b7x, b7y); + resources.main_menu_button_sprite.setPosition(b7v); + window.draw(resources.main_menu_button_sprite); + } + else if (save_prompt_open == true) + { + draw_save_menu(window); + } + else if (load_prompt_open == true) + { + draw_load_menu(window); + } + else if (repair_prompt_open == true) + { + draw_repair_menu(window, pc); + } + else if (prompt_displayed() == false) + { + if (show_notice == true) + { + display_notice(window, notice, frame_time); + } + else if (market.visible == true) + { + if (market.show_notice == true) + { + display_notice(window, market.notice, frame_time); + } + else + { + market.draw_menu(window, pc, mouse_position); + } + } + else if (s_menu.visible == true) + { + s_menu.draw_menu(window, mouse_position, frame_time); + } + } + + window.display(); + return true; + } + else + { + return false; + } +} diff --git a/src/key_bindings.cpp b/src/key_bindings.cpp new file mode 100644 index 0000000..e7b8aac --- /dev/null +++ b/src/key_bindings.cpp @@ -0,0 +1,117 @@ +#include + +// Creates aliases for key binds and loads current bindings from file +void key_bindings::load(std::string cwd) +{ + keys["A"] = sf::Keyboard::A; + keys["B"] = sf::Keyboard::B; + keys["C"] = sf::Keyboard::C; + keys["D"] = sf::Keyboard::D; + keys["E"] = sf::Keyboard::E; + keys["F"] = sf::Keyboard::F; + keys["G"] = sf::Keyboard::G; + keys["H"] = sf::Keyboard::H; + keys["I"] = sf::Keyboard::I; + keys["J"] = sf::Keyboard::J; + keys["K"] = sf::Keyboard::K; + keys["L"] = sf::Keyboard::L; + keys["M"] = sf::Keyboard::M; + keys["N"] = sf::Keyboard::N; + keys["O"] = sf::Keyboard::O; + keys["P"] = sf::Keyboard::P; + keys["Q"] = sf::Keyboard::Q; + keys["R"] = sf::Keyboard::R; + keys["S"] = sf::Keyboard::S; + keys["T"] = sf::Keyboard::T; + keys["U"] = sf::Keyboard::U; + keys["V"] = sf::Keyboard::V; + keys["W"] = sf::Keyboard::W; + keys["X"] = sf::Keyboard::X; + keys["Y"] = sf::Keyboard::Y; + keys["Z"] = sf::Keyboard::Z; + + keys["Up"] = sf::Keyboard::Up; + keys["Down"] = sf::Keyboard::Down; + keys["Left"] = sf::Keyboard::Left; + keys["Right"] = sf::Keyboard::Right; + + keys["LControl"] = sf::Keyboard::LControl; + keys["RControl"] = sf::Keyboard::RControl; + keys["LShift"] = sf::Keyboard::LShift; + keys["RShift"] = sf::Keyboard::RShift; + keys["LAlt"] = sf::Keyboard::LAlt; + keys["RAlt"] = sf::Keyboard::RAlt; + keys["Space"] = sf::Keyboard::Space; + keys["Return"] = sf::Keyboard::Return; + + keys["Num0"] = sf::Keyboard::Num0; + keys["Num1"] = sf::Keyboard::Num1; + keys["Num2"] = sf::Keyboard::Num2; + keys["Num3"] = sf::Keyboard::Num3; + keys["Num4"] = sf::Keyboard::Num4; + keys["Num5"] = sf::Keyboard::Num5; + keys["Num6"] = sf::Keyboard::Num6; + keys["Num7"] = sf::Keyboard::Num7; + keys["Num8"] = sf::Keyboard::Num8; + keys["Num9"] = sf::Keyboard::Num9; + + keys["Numpad0"] = sf::Keyboard::Numpad0; + keys["Numpad1"] = sf::Keyboard::Numpad1; + keys["Numpad2"] = sf::Keyboard::Numpad2; + keys["Numpad3"] = sf::Keyboard::Numpad3; + keys["Numpad4"] = sf::Keyboard::Numpad4; + keys["Numpad5"] = sf::Keyboard::Numpad5; + keys["Numpad6"] = sf::Keyboard::Numpad6; + keys["Numpad7"] = sf::Keyboard::Numpad7; + keys["Numpad8"] = sf::Keyboard::Numpad8; + keys["Numpad9"] = sf::Keyboard::Numpad9; + + keys["F1"] = sf::Keyboard::F1; + keys["F2"] = sf::Keyboard::F2; + keys["F3"] = sf::Keyboard::F3; + keys["F4"] = sf::Keyboard::F4; + keys["F5"] = sf::Keyboard::F5; + keys["F6"] = sf::Keyboard::F6; + keys["F7"] = sf::Keyboard::F7; + keys["F8"] = sf::Keyboard::F8; + keys["F9"] = sf::Keyboard::F9; + keys["F10"] = sf::Keyboard::F10; + keys["F11"] = sf::Keyboard::F11; + keys["F12"] = sf::Keyboard::F12; + + keys["Tilde"] = sf::Keyboard::Tilde; + keys["Tab"] = sf::Keyboard::Tab; + + keys["Home"] = sf::Keyboard::Home; + keys["PageUp"] = sf::Keyboard::PageUp; + keys["PageDown"] = sf::Keyboard::PageDown; + keys["Insert"] = sf::Keyboard::Insert; + keys["BackSpace"] = sf::Keyboard::BackSpace; + keys["Delete"] = sf::Keyboard::Delete; + keys["Pause"] = sf::Keyboard::Pause; + + keys["Dash"] = sf::Keyboard::Dash; + keys["Equal"] = sf::Keyboard::Equal; + keys["BackSlash"] = sf::Keyboard::BackSlash; + keys["LBracket"] = sf::Keyboard::LBracket; + keys["RBracket"] = sf::Keyboard::RBracket; + keys["SemiColon"] = sf::Keyboard::SemiColon; + keys["Quote"] = sf::Keyboard::Quote; + keys["Comma"] = sf::Keyboard::Comma; + keys["Period"] = sf::Keyboard::Period; + keys["Slash"] = sf::Keyboard::Slash; + + size_t pos = 0; + std::string entry; + std::string delimeter = "\n"; + std::string saved_bindings = get_file_contents(cwd + "/bindings.list"); + + while ((pos = saved_bindings.find(delimeter)) != std::string::npos) + { + entry = saved_bindings.substr(0, pos); + std::string action = entry.substr(0, entry.find(":")); + std::string bound = entry.substr(entry.find(":") + 1, pos); + bindings[action] = keys[bound]; + saved_bindings.erase(0, pos + delimeter.length()); + } +} diff --git a/src/main_menu.cpp b/src/main_menu.cpp new file mode 100644 index 0000000..3d457b4 --- /dev/null +++ b/src/main_menu.cpp @@ -0,0 +1,497 @@ +#include +#include +#include + +// Gets current directory, initializes resources and settings menu +void main_menu::init(std::string cwd, assets &resources) +{ + this->cwd = cwd; + this->resources = resources; + s_menu.init(cwd, resources, false); +} + +// Loads saved game data from file +void main_menu::load_game(std::string cwd, std::string file, player_controller &pc) +{ + int index = 0; + size_t pos = 0; + std::string token; + std::string delimiter = "\n"; + std::vector values(30); + std::string data = get_file_contents(cwd + "/save/" + file + ".sav"); + + while ((pos = data.find(delimiter)) != std::string::npos) + { + values[index] = data.substr(0, pos); + data.erase(0, pos + delimiter.length()); + index++; + } + + pc.credits = std::stoi(values[0]); + pc.mission = std::stoi(values[1]); + pc.player_mech.cockpit_integrity = std::stoi(values[2]); + pc.player_mech.reactor_integrity = std::stoi(values[3]); + pc.player_mech.cooler_integrity = std::stoi(values[4]); + pc.player_mech.left_arm_integrity = std::stoi(values[5]); + pc.player_mech.right_arm_integrity = std::stoi(values[6]); + pc.player_mech.left_leg_integrity = std::stoi(values[7]); + pc.player_mech.right_leg_integrity = std::stoi(values[8]); + pc.player_mech.max_cockpit_integrity = std::stoi(values[9]); + pc.player_mech.max_reactor_integrity = std::stoi(values[10]); + pc.player_mech.max_cooler_integrity = std::stoi(values[11]); + pc.player_mech.max_left_arm_integrity = std::stoi(values[12]); + pc.player_mech.max_right_arm_integrity = std::stoi(values[13]); + pc.player_mech.max_left_leg_integrity = std::stoi(values[14]); + pc.player_mech.max_right_leg_integrity = std::stoi(values[15]); + pc.player_mech.cooler_modifier = std::stoi(values[16]); + pc.player_mech.guns_modifier = std::stoi(values[17]); + pc.player_mech.cannons_modifier = std::stoi(values[18]); + pc.player_mech.weight = std::stoi(values[19]); + pc.player_mech.primary_weapon = values[20]; + pc.player_mech.secondary_weapon = values[21]; + pc.player_mech.reactor = values[22]; + pc.player_mech.cooler = values[23]; + pc.player_mech.left_leg = values[24]; + pc.player_mech.right_leg = values[25]; + pc.player_mech.left_arm = values[26]; + pc.player_mech.right_arm = values[27]; + pc.player_mech.cockpit = values[28]; +} + +// Deletes a saved game +void main_menu::delete_save_game(int i) +{ + std::string save_to_delete = cwd + "/save/" + load_game_labels[i].getString() + ".sav"; + char file [100]; + sprintf(file, "%s", save_to_delete.c_str()); + std::remove(file); + std::string saves = get_file_contents(cwd + "/save/saves.list"); + std::string delimiter = "\n"; + std::string new_saves; + std::string token; + size_t pos = 0; + while ((pos = saves.find(delimiter)) != std::string::npos) + { + token = saves.substr(0, pos); + if (token != load_game_labels[i].getString()) + { + new_saves += token + "\n"; + } + saves.erase(0, pos + delimiter.length()); + } + new_saves.erase(new_saves.find_last_not_of(" \n\r\t")+1); + write_to_file(cwd + "/save/saves.list", new_saves); + load_prompt_open = false; + show_delete_notice = true; +} + +// Draws the load game menu +void main_menu::draw_load_menu(sf::RenderWindow &window) +{ + int index = 0; + size_t pos = 0; + std::string saves = get_file_contents(cwd + "/save/saves.list"); + std::string delimiter = "\n"; + std::string token; + + // Get the number of saved games + while ((pos = saves.find(delimiter)) != std::string::npos) + { + token = saves.substr(0, pos); + saves.erase(0, pos + delimiter.length()); + index++; + } + + load_game_buttons.resize(index); + load_game_labels.resize(index); + delete_save_buttons.resize(index); + delete_save_labels.resize(index); + + // Reset variables + pos = 0; + index = 0; + saves = get_file_contents(cwd + "/save/saves.list"); + + // Create text objects for all existing save files + while ((pos = saves.find(delimiter)) != std::string::npos) + { + token = saves.substr(0, pos); + load_game_labels[index].setString(token); + saves.erase(0, pos + delimiter.length()); + index++; + } + + // Load game buttons + for (unsigned int i = 0; i < load_game_labels.size(); i++) + { + float x = window.getView().getSize().x / 2 - 150; + + load_game_buttons[i] = sf::VertexArray(sf::Quads, 4); + load_game_buttons[i][0].position = sf::Vector2f(x, (200 + i * 35) - 4); + load_game_buttons[i][1].position = sf::Vector2f(x, (200 + i * 35) + 24); + load_game_buttons[i][2].position = sf::Vector2f(x + 225, (200 + i * 35) + 24); + load_game_buttons[i][3].position = sf::Vector2f(x + 225, (200 + i * 35) - 4); + + sf::VertexArray load_game_shadow = sf::VertexArray(sf::Quads, 4); + load_game_shadow[0].position = sf::Vector2f(x, (200 + i * 35) - 4); + load_game_shadow[1].position = sf::Vector2f(x, (200 + i * 35) + 27); + load_game_shadow[2].position = sf::Vector2f(x + 228, (200 + i * 35) + 27); + load_game_shadow[3].position = sf::Vector2f(x + 228, (200 + i * 35) - 4); + + load_game_shadow[0].color = sf::Color::Black; + load_game_shadow[1].color = sf::Color::Black; + load_game_shadow[2].color = sf::Color::Black; + load_game_shadow[3].color = sf::Color::Black; + + if (load_game_buttons[i].getBounds().contains(mouse_position.x, mouse_position.y)) + { + load_game_buttons[i][0].color = sf::Color(53, 53, 53, 255); + load_game_buttons[i][1].color = sf::Color(53, 53, 53, 255); + load_game_buttons[i][2].color = sf::Color(53, 53, 53, 255); + load_game_buttons[i][3].color = sf::Color(53, 53, 53, 255); + } + else + { + load_game_buttons[i][0].color = sf::Color(35, 35, 35, 255); + load_game_buttons[i][1].color = sf::Color(35, 35, 35, 255); + load_game_buttons[i][2].color = sf::Color(35, 35, 35, 255); + load_game_buttons[i][3].color = sf::Color(35, 35, 35, 255); + } + + load_game_labels[i].setFont(resources.exoplanetaria); + load_game_labels[i].setCharacterSize(16); + load_game_labels[i].setFillColor(sf::Color::Black); + load_game_labels[i].setPosition(x + 20, 202 + (i * 35 - 2)); + + if (load_game_labels[i].getString() != "") + { + window.draw(load_game_shadow); + window.draw(load_game_buttons[i]); + window.draw(load_game_labels[i]); + } + } + + // Delete save buttons + for (unsigned int i = 0; i < load_game_labels.size(); i++) + { + float x = window.getView().getSize().x / 2 + 100; + + delete_save_buttons[i] = sf::VertexArray(sf::Quads, 4); + delete_save_buttons[i][0].position = sf::Vector2f(x, (200 + i * 35) - 4); + delete_save_buttons[i][1].position = sf::Vector2f(x, (200 + i * 35) + 24); + delete_save_buttons[i][2].position = sf::Vector2f(x + 70, (200 + i * 35) + 24); + delete_save_buttons[i][3].position = sf::Vector2f(x + 70, (200 + i * 35) - 4); + + sf::VertexArray delete_save_shadow = sf::VertexArray(sf::Quads, 4); + delete_save_shadow[0].position = sf::Vector2f(x, (200 + i * 35) - 4); + delete_save_shadow[1].position = sf::Vector2f(x, (200 + i * 35) + 27); + delete_save_shadow[2].position = sf::Vector2f(x + 73, (200 + i * 35) + 27); + delete_save_shadow[3].position = sf::Vector2f(x + 73, (200 + i * 35) - 4); + + delete_save_shadow[0].color = sf::Color::Black; + delete_save_shadow[1].color = sf::Color::Black; + delete_save_shadow[2].color = sf::Color::Black; + delete_save_shadow[3].color = sf::Color::Black; + + if (delete_save_buttons[i].getBounds().contains(mouse_position.x, mouse_position.y)) + { + delete_save_buttons[i][0].color = sf::Color(53, 53, 53, 255); + delete_save_buttons[i][1].color = sf::Color(53, 53, 53, 255); + delete_save_buttons[i][2].color = sf::Color(53, 53, 53, 255); + delete_save_buttons[i][3].color = sf::Color(53, 53, 53, 255); + } + else + { + delete_save_buttons[i][0].color = sf::Color(35, 35, 35, 255); + delete_save_buttons[i][1].color = sf::Color(35, 35, 35, 255); + delete_save_buttons[i][2].color = sf::Color(35, 35, 35, 255); + delete_save_buttons[i][3].color = sf::Color(35, 35, 35, 255); + } + + delete_save_labels[i].setFont(resources.exoplanetaria); + delete_save_labels[i].setCharacterSize(16); + delete_save_labels[i].setFillColor(sf::Color::Black); + delete_save_labels[i].setPosition(x + 10, 200 + (i * 35)); + delete_save_labels[i].setString("DELETE"); + + if (load_game_labels[i].getString() != "") + { + window.draw(delete_save_shadow); + window.draw(delete_save_buttons[i]); + window.draw(delete_save_labels[i]); + } + } + + // Cancel Button + if (resources.cancel_button_sprite.getGlobalBounds().contains(mouse_position.x, mouse_position.y)) + { + resources.cancel_button_sprite.setTexture(resources.cancel_button_hover_texture); + } + else + { + resources.cancel_button_sprite.setTexture(resources.cancel_button_texture); + } + float bx = (window.getView().getSize().x / 2) - (resources.cancel_button_texture.getSize().x / 2); + float by = 150; + sf::Vector2f bv(bx, by); + resources.cancel_button_sprite.setPosition(bv); + window.draw(resources.cancel_button_sprite); +} + +// Handles all drawing and interaction with the menu +bool main_menu::draw_menu(sf::RenderWindow &window, player_controller &pc, float frame_time) +{ + if (start_game == false) + { + // Play music + resources.main_menu_music.setVolume(100 * audio_volume); + + if (resources.main_menu_music.getStatus() != sf::Sound::Playing) + { + resources.main_menu_music.play(); + } + + // Process events + sf::Event event; + while (window.pollEvent(event)) + { + if(event.type == sf::Event::MouseMoved) + { + mouse_position = sf::Mouse().getPosition(window); + } + + if (event.type == sf::Event::Closed) + { + window.close(); + } + + if (s_menu.visible == false) + { + if (event.type == sf::Event::MouseButtonPressed) + { + if(event.mouseButton.button == sf::Mouse::Left) + { + if (load_prompt_open == false) + { + if (resources.start_game_button_sprite.getGlobalBounds().contains(mouse_position.x, mouse_position.y)) + { + resources.main_menu_music.stop(); + start_game = true; + } + + if (resources.options_button_sprite.getGlobalBounds().contains(mouse_position.x, mouse_position.y)) + { + s_menu.visible = true; + } + + if (resources.load_game_button_sprite.getGlobalBounds().contains(mouse_position.x, mouse_position.y)) + { + load_prompt_open = true; + } + + if (resources.exit_game_button_sprite.getGlobalBounds().contains(mouse_position.x, mouse_position.y)) + { + window.close(); + } + } + else + { + if (resources.cancel_button_sprite.getGlobalBounds().contains(mouse_position.x, mouse_position.y)) + { + load_prompt_open = false; + } + + for (unsigned int i = 0; i < load_game_labels.size(); i++) + { + if (load_game_buttons[i].getBounds().contains(mouse_position.x, mouse_position.y)) + { + load_game(cwd, load_game_labels[i].getString(), pc); + load_prompt_open = false; + show_load_notice = true; + } + } + + for (unsigned int i = 0; i < delete_save_labels.size(); i++) + { + if (delete_save_buttons[i].getBounds().contains(mouse_position.x, mouse_position.y)) + { + delete_save_game(i); + } + } + } + } + } + + if (event.type == sf::Event::KeyPressed) + { + if (load_prompt_open == true) + { + if (event.key.code == sf::Keyboard::Escape) + { + load_prompt_open = false; + } + } + else if (s_menu.visible == true) + { + if (event.key.code == sf::Keyboard::Escape) + { + s_menu.visible = false; + } + } + } + } + else + { + s_menu.handle_events(event, mouse_position); + } + } + window.clear(); + + // Draw the background + resources.menu_background_sprite.setPosition(0,0); + resources.menu_background_sprite.setScale( + window.getView().getSize().x / resources.menu_background_sprite.getTexture()->getSize().x, + window.getView().getSize().y / resources.menu_background_sprite.getTexture()->getSize().y); + window.draw(resources.menu_background_sprite); + + // Randomly display welding sparks for the mech being repaired in the background + spark_timer += 10 * frame_time; + if (spark_timer >= 10) + { + spark_timer = 0; + int random_spark = rand() % 90; + + if (random_spark >= 0 && random_spark < 30) + { + resources.menu_mech_sprite.setTexture(resources.menu_mech_texture); + } + else if (random_spark >= 30 && random_spark < 60) + { + resources.menu_mech_sprite.setTexture(resources.menu_mech_spark_1_texture); + } + else if (random_spark >= 60) + { + resources.menu_mech_sprite.setTexture(resources.menu_mech_spark_2_texture); + } + } + resources.menu_mech_sprite.setScale(1.1, 1.1); + float mech_x = window.getView().getSize().x / 2 - ((resources.menu_mech_sprite.getTexture()->getSize().x * 1.1) / 2); + float mech_y = window.getView().getSize().y - 550; + sf::Vector2f mech_position = sf::Vector2f(mech_x, mech_y); + resources.menu_mech_sprite.setPosition(mech_position); + window.draw(resources.menu_mech_sprite); + + if (load_prompt_open == false && s_menu.visible == false && show_load_notice == false && show_delete_notice == false) + { + // Start Game Button + if (resources.start_game_button_sprite.getGlobalBounds().contains(mouse_position.x, mouse_position.y)) + { + resources.start_game_button_sprite.setTexture(resources.start_game_button_hover_texture); + } + else + { + resources.start_game_button_sprite.setTexture(resources.start_game_button_texture); + } + float bx = (window.getView().getSize().x / 2) - (resources.start_game_button_texture.getSize().x / 2); + float by = resources.menu_mech_sprite.getPosition().y + 40; + sf::Vector2f bv(bx, by); + resources.start_game_button_sprite.setPosition(bv); + window.draw(resources.start_game_button_sprite); + + // Load Game Button + if (resources.load_game_button_sprite.getGlobalBounds().contains(mouse_position.x, mouse_position.y)) + { + resources.load_game_button_sprite.setTexture(resources.load_game_button_hover_texture); + } + else + { + resources.load_game_button_sprite.setTexture(resources.load_game_button_texture); + } + float b2x = (window.getView().getSize().x / 2) - (resources.load_game_button_texture.getSize().x / 2); + float b2y = resources.menu_mech_sprite.getPosition().y + 90; + sf::Vector2f b2v(b2x, b2y); + resources.load_game_button_sprite.setPosition(b2v); + window.draw(resources.load_game_button_sprite); + + // Options + if (resources.options_button_sprite.getGlobalBounds().contains(mouse_position.x, mouse_position.y)) + { + resources.options_button_sprite.setTexture(resources.options_button_hover_texture); + } + else + { + resources.options_button_sprite.setTexture(resources.options_button_texture); + } + float b3x = (window.getView().getSize().x / 2) - (resources.options_button_texture.getSize().x / 2); + float b3y = resources.menu_mech_sprite.getPosition().y + 140; + sf::Vector2f b3v(b3x, b3y); + resources.options_button_sprite.setPosition(b3v); + window.draw(resources.options_button_sprite); + + // Exit Button + if (resources.exit_game_button_sprite.getGlobalBounds().contains(mouse_position.x, mouse_position.y)) + { + resources.exit_game_button_sprite.setTexture(resources.exit_game_button_hover_texture); + } + else + { + resources.exit_game_button_sprite.setTexture(resources.exit_game_button_texture); + } + float b4x = (window.getView().getSize().x / 2) - (resources.exit_game_button_texture.getSize().x / 2); + float b4y = resources.menu_mech_sprite.getPosition().y + 190; + sf::Vector2f b4v(b4x, b4y); + resources.exit_game_button_sprite.setPosition(b4v); + window.draw(resources.exit_game_button_sprite); + } + else if (load_prompt_open == true) + { + draw_load_menu(window); + } + else if (show_load_notice == true && show_delete_notice == false) + { + sf::Vector2f text_pos; + text_pos.x = (window.getView().getSize().x / 2) - (resources.notice.getGlobalBounds().width / 2); + text_pos.y = (window.getView().getSize().y / 2) - 100; + resources.notice.setString("GAME LOADED"); + resources.notice.setPosition(text_pos); + window.draw(resources.notice); + + load_notice_timer += 10 * frame_time; + if (load_notice_timer >= 30) + { + resources.main_menu_music.stop(); + load_notice_timer = 0; + show_load_notice = false; + game_loaded = true; + start_game = true; + } + } + else if (show_load_notice == false && show_delete_notice == true) + { + sf::Vector2f text_pos; + text_pos.x = (window.getView().getSize().x / 2) - (resources.notice.getGlobalBounds().width / 2); + text_pos.y = (window.getView().getSize().y / 2) - 100; + resources.notice.setString("SAVE DELETED"); + resources.notice.setPosition(text_pos); + window.draw(resources.notice); + + delete_notice_timer += 10 * frame_time; + if (delete_notice_timer >= 30) + { + delete_notice_timer = 0; + show_delete_notice = false; + } + } + else if (s_menu.visible == true) + { + s_menu.draw_menu(window, mouse_position, frame_time); + } + + window.display(); + return true; + } + else + { + return false; + } +} diff --git a/src/market_menu.cpp b/src/market_menu.cpp new file mode 100644 index 0000000..65a9704 --- /dev/null +++ b/src/market_menu.cpp @@ -0,0 +1,1144 @@ +#include +#include + +// Constructor +market_menu::market_menu() +{ + visible = false; + item_worth.resize(7); + sell_buttons.resize(7); + sell_button_labels.resize(7); + sell_categories = {"GUNS", "CANNONS", "COOLER", "REACTOR", "COCKPIT", "ARMS", "LEGS"}; +} + +// Loads resources from disk +void market_menu::init(std::string cwd) +{ + if (!market_font.loadFromFile(cwd + "/assets/Exoplanetaria-gxxJ5.ttf")) + { + std::cout << "Failed to load font."; + std::cout << "\n"; + } + + if (!gui_background_texture.loadFromFile(cwd + "/assets/textures/gui_background_2.png")) + { + std::cout << "Failed to load textures."; + } + + if (!purchase_sound_buffer.loadFromFile(cwd + "/assets/sounds/purchase.ogg")) + { + std::cout << "Error loading sound file purchase.ogg"; + std::cout << "\n"; + } + + purchase_sound.setBuffer(purchase_sound_buffer); +} + +// Purchases an item from the market +void market_menu::purchase_item(player_controller &pc, item item_bought) +{ + if (pc.credits >= item_bought.price && pc.player_mech.weight <= 100) + { + purchase_sound.setVolume(100 * audio_volume); + purchase_sound.play(); + pc.credits -= item_bought.price; + pc.player_mech.weight += 10; + + if (item_bought.type == "guns") + { + pc.player_mech.primary_weapon = item_bought.name; + pc.player_mech.guns_modifier = item_bought.modifier; + } + else if (item_bought.type == "cannons") + { + pc.player_mech.secondary_weapon = item_bought.name; + pc.player_mech.cannons_modifier = item_bought.modifier; + } + else if (item_bought.type == "cooler") + { + pc.player_mech.cooler = item_bought.name; + pc.player_mech.cooler_integrity = item_bought.modifier; + pc.player_mech.max_cooler_integrity = item_bought.modifier; + pc.player_mech.cooler_modifier = item_bought.secondary_modifier; + } + else if (item_bought.type == "reactor") + { + pc.player_mech.reactor = item_bought.name; + pc.player_mech.reactor_integrity = item_bought.modifier; + pc.player_mech.max_reactor_integrity = item_bought.modifier; + } + else if (item_bought.type == "cockpit") + { + pc.player_mech.cockpit = item_bought.name; + pc.player_mech.cockpit_integrity = item_bought.modifier; + pc.player_mech.max_cockpit_integrity = item_bought.modifier; + } + else if (item_bought.type == "arms") + { + pc.player_mech.left_arm = item_bought.name; + pc.player_mech.left_arm_integrity = item_bought.modifier; + pc.player_mech.max_left_arm_integrity = item_bought.modifier; + + pc.player_mech.right_arm = item_bought.name; + pc.player_mech.right_arm_integrity = item_bought.modifier; + pc.player_mech.max_right_arm_integrity = item_bought.modifier; + } + else if (item_bought.type == "legs") + { + pc.player_mech.left_leg = item_bought.name; + pc.player_mech.left_leg_integrity = item_bought.modifier; + pc.player_mech.max_left_leg_integrity = item_bought.modifier; + + pc.player_mech.right_leg = item_bought.name; + pc.player_mech.right_leg_integrity = item_bought.modifier; + pc.player_mech.max_right_leg_integrity = item_bought.modifier; + } + } +} + +// Sells an item installed on the player's mech +void market_menu::sell_item(player_controller &pc, std::string category) +{ + if (category == "GUNS") + { + if (pc.player_mech.primary_weapon != "Standard Pulse Laser") + { + pc.credits += (item_worth[0]); + pc.player_mech.weight -= 10; + pc.player_mech.primary_weapon = "Standard Pulse Laser"; + pc.player_mech.guns_modifier = 0; + purchase_sound.setVolume(100 * audio_volume); + purchase_sound.play(); + } + else + { + notice = "CANNOT SELL THIS ITEM"; + show_notice = true; + } + } + else if (category == "CANNONS") + { + if (pc.player_mech.secondary_weapon != "Standard Autocannon") + { + pc.credits += (item_worth[1]); + pc.player_mech.weight -= 10; + pc.player_mech.secondary_weapon = "Standard Autocannon"; + pc.player_mech.cannons_modifier = 0; + purchase_sound.setVolume(100 * audio_volume); + purchase_sound.play(); + } + else + { + notice = "CANNOT SELL THIS ITEM"; + show_notice = true; + } + } + else if (category == "COOLER") + { + if (pc.player_mech.cooler != "Standard Cooler") + { + pc.credits += (item_worth[2]); + pc.player_mech.weight -= 10; + pc.player_mech.cooler = "Standard Cooler"; + pc.player_mech.cooler_modifier = 0; + pc.player_mech.cooler_integrity = 1000; + pc.player_mech.max_cooler_integrity = 1000; + purchase_sound.setVolume(100 * audio_volume); + purchase_sound.play(); + } + else + { + notice = "CANNOT SELL THIS ITEM"; + show_notice = true; + } + } + else if (category == "REACTOR") + { + if (pc.player_mech.reactor != "Standard Reactor") + { + pc.credits += (item_worth[3]); + pc.player_mech.weight -= 10; + pc.player_mech.reactor = "Standard Reactor"; + pc.player_mech.reactor_integrity = 1000; + pc.player_mech.max_reactor_integrity = 1000; + purchase_sound.setVolume(100 * audio_volume); + purchase_sound.play(); + } + else + { + notice = "CANNOT SELL THIS ITEM"; + show_notice = true; + } + } + else if (category == "COCKPIT") + { + if (pc.player_mech.cockpit != "Standard Cockpit") + { + pc.credits += (item_worth[4]); + pc.player_mech.weight -= 10; + pc.player_mech.cockpit = "Standard Cockpit"; + pc.player_mech.cockpit_integrity = 1000; + pc.player_mech.max_cockpit_integrity = 1000; + purchase_sound.setVolume(100 * audio_volume); + purchase_sound.play(); + } + else + { + notice = "CANNOT SELL THIS ITEM"; + show_notice = true; + } + } + else if (category == "ARMS") + { + if (pc.player_mech.left_arm != "Standard Left Arm") + { + pc.credits += (item_worth[5]); + pc.player_mech.weight -= 10; + + pc.player_mech.left_arm = "Standard Left Arm"; + pc.player_mech.left_arm_integrity = 1000; + pc.player_mech.max_left_arm_integrity = 1000; + + pc.player_mech.right_arm = "Standard Right Arm"; + pc.player_mech.right_arm_integrity = 1000; + pc.player_mech.max_right_arm_integrity = 1000; + + purchase_sound.setVolume(100 * audio_volume); + purchase_sound.play(); + } + else + { + notice = "CANNOT SELL THIS ITEM"; + show_notice = true; + } + } + else if (category == "LEGS") + { + if (pc.player_mech.left_leg != "Standard Left Leg") + { + pc.credits += (item_worth[6]); + pc.player_mech.weight -= 10; + + pc.player_mech.left_leg = "Standard Left Leg"; + pc.player_mech.left_leg_integrity = 1000; + pc.player_mech.max_left_leg_integrity = 1000; + + pc.player_mech.right_leg = "Standard Right Leg"; + pc.player_mech.right_leg_integrity = 1000; + pc.player_mech.max_right_leg_integrity = 1000; + + purchase_sound.setVolume(100 * audio_volume); + purchase_sound.play(); + } + else + { + notice = "CANNOT SELL THIS ITEM"; + show_notice = true; + } + } +} + +// Generates items for sale +void market_menu::generate_items() +{ + int gun_amount = 4; + guns.resize(gun_amount); + gun_buttons.resize(gun_amount); + gun_button_labels.resize(gun_amount); + gun_descriptions.resize(gun_amount); + for (int i = 0; i < gun_amount; i++) + { + guns[i].type = "guns"; + + int level = rand() % 100; + + if (level > 90) + { + guns[i].name = "L3 Pulse Laser"; + guns[i].level = 3; + guns[i].modifier = 6 + ( rand() % ( 9 - 6 + 1 ) ); + guns[i].price = guns[i].modifier * 10000; + } + else if (level <= 90 && level > 60) + { + guns[i].name = "L2 Pulse Laser"; + guns[i].level = 2; + guns[i].modifier = 4 + ( rand() % ( 6 - 4 + 1 ) ); + guns[i].price = guns[i].modifier * 10000; + } + else + { + guns[i].name = "L1 Pulse Laser"; + guns[i].level = 1; + guns[i].modifier = 1 + ( rand() % ( 3 - 1 + 1 ) ); + guns[i].price = guns[i].modifier * 10000; + } + } + + int cannon_amount = 4; + cannons.resize(cannon_amount); + cannon_buttons.resize(cannon_amount); + cannon_button_labels.resize(cannon_amount); + cannon_descriptions.resize(cannon_amount); + for (int i = 0; i < cannon_amount; i++) + { + cannons[i].type = "cannons"; + + int level = rand() % 100; + if (level > 90) + { + cannons[i].name = "L3 Autocannon"; + cannons[i].level = 3; + cannons[i].modifier = 7 + ( rand() % ( 9 - 7 + 1 ) ); + cannons[i].price = cannons[i].modifier * 10000; + } + else if (level <= 90 && level > 60) + { + cannons[i].name = "L2 Autocannon"; + cannons[i].level = 2; + cannons[i].modifier = 4 + ( rand() % ( 6 - 4 + 1 ) ); + cannons[i].price = cannons[i].modifier * 10000; + } + else + { + cannons[i].name = "L1 Autocannon"; + cannons[i].level = 1; + cannons[i].modifier = 1 + ( rand() % ( 3 - 1 + 1 ) ); + cannons[i].price = cannons[i].modifier * 10000; + } + } + + int cooler_amount = 4; + coolers.resize(cooler_amount); + cooler_buttons.resize(cooler_amount); + cooler_button_labels.resize(cooler_amount); + cooler_descriptions.resize(cooler_amount); + for (int i = 0; i < cooler_amount; i++) + { + coolers[i].type = "cooler"; + + int level = rand() % 100; + if (level > 90) + { + coolers[i].name = "L3 Cooler"; + coolers[i].level = 3; + coolers[i].modifier = 3000 + ( rand() % ( 3500 - 3000 + 1 ) ); + coolers[i].secondary_modifier = 7 + ( rand() % ( 9 - 7 + 1 ) ); + coolers[i].price = coolers[i].modifier * 15 + coolers[i].secondary_modifier * 5000; + } + else if (level <= 90 && level > 60) + { + coolers[i].name = "L2 Cooler"; + coolers[i].level = 2; + coolers[i].modifier = 2000 + ( rand() % ( 2500 - 2000 + 1 ) ); + coolers[i].secondary_modifier = 4 + ( rand() % ( 6 - 4 + 1 ) ); + coolers[i].price = coolers[i].modifier * 10 + coolers[i].secondary_modifier * 5000; + } + else + { + coolers[i].name = "L1 Cooler"; + coolers[i].level = 1; + coolers[i].modifier = 1000 + ( rand() % ( 1500 - 1000 + 1 ) ); + coolers[i].secondary_modifier = 1 + ( rand() % ( 3 - 1 + 1 ) ); + coolers[i].price = coolers[i].modifier * 5 + coolers[i].secondary_modifier * 5000; + } + } + + int reactor_amount = 4; + reactors.resize(reactor_amount); + reactor_buttons.resize(reactor_amount); + reactor_button_labels.resize(reactor_amount); + reactor_descriptions.resize(reactor_amount); + for (int i = 0; i < reactor_amount; i++) + { + reactors[i].type = "reactor"; + + int level = rand() % 100; + if (level > 90) + { + reactors[i].name = "L3 Reactor"; + reactors[i].level = 3; + reactors[i].modifier = 3000 + ( rand() % ( 3500 - 3000 + 1 ) ); + reactors[i].price = reactors[i].modifier * 15; + } + else if (level <= 90 && level > 60) + { + reactors[i].name = "L2 Reactor"; + reactors[i].level = 2; + reactors[i].modifier = 2000 + ( rand() % ( 2500 - 2000 + 1 ) ); + reactors[i].price = reactors[i].modifier * 10; + } + else + { + reactors[i].name = "L1 Reactor"; + reactors[i].level = 1; + reactors[i].modifier = 1000 + ( rand() % ( 1500 - 1000 + 1 ) ); + reactors[i].price = reactors[i].modifier *5; + } + } + + int cockpit_amount = 4; + cockpits.resize(cockpit_amount); + cockpit_buttons.resize(cockpit_amount); + cockpit_button_labels.resize(cockpit_amount); + cockpit_descriptions.resize(cockpit_amount); + for (int i = 0; i < cockpit_amount; i++) + { + cockpits[i].type = "cockpit"; + + int level = rand() % 100; + if (level > 90) + { + cockpits[i].name = "L3 Cockpit"; + cockpits[i].level = 3; + cockpits[i].modifier = 4000 + ( rand() % ( 3500 - 3000 + 1 ) ); + cockpits[i].price = cockpits[i].modifier * 15; + } + else if (level <= 90 && level > 60) + { + cockpits[i].name = "L2 Cockpit"; + cockpits[i].level = 2; + cockpits[i].modifier = 2000 + ( rand() % ( 2500 - 2000 + 1 ) ); + cockpits[i].price = cockpits[i].modifier *10; + } + else + { + cockpits[i].name = "L1 Cockpit"; + cockpits[i].level = 1; + cockpits[i].modifier = 1000 + ( rand() % ( 1500 - 1000 + 1 ) ); + cockpits[i].price = cockpits[i].modifier * 5; + } + } + + int arm_amount = 4; + arms.resize(arm_amount); + arm_buttons.resize(arm_amount); + arm_button_labels.resize(arm_amount); + arm_descriptions.resize(arm_amount); + for (int i = 0; i < arm_amount; i++) + { + arms[i].type = "arms"; + + int level = rand() % 100; + if (level > 90) + { + arms[i].name = "L3 Arms"; + arms[i].level = 3; + arms[i].modifier = 3000 + ( rand() % ( 3500 - 3000 + 1 ) ); + arms[i].price = arms[i].modifier * 15; + } + else if (level <= 90 && level > 60) + { + arms[i].name = "L2 Arms"; + arms[i].level = 2; + arms[i].modifier = 2000 + ( rand() % ( 2500 - 2000 + 1 ) ); + arms[i].price = arms[i].modifier * 10; + } + else + { + arms[i].name = "L1 Arms"; + arms[i].level = 1; + arms[i].modifier = 1000 + ( rand() % ( 1500 - 1000 + 1 ) ); + arms[i].price = arms[i].modifier * 5; + } + } + + int leg_amount = 4; + legs.resize(leg_amount); + leg_buttons.resize(leg_amount); + leg_button_labels.resize(leg_amount); + leg_descriptions.resize(leg_amount); + for (int i = 0; i < leg_amount; i++) + { + legs[i].type = "legs"; + + int level = rand() % 100; + if (level > 90) + { + legs[i].name = "L3 Legs"; + legs[i].level = 3; + legs[i].modifier = 3000 + ( rand() % ( 3500 - 3000 + 1 ) ); + legs[i].price = legs[i].modifier * 15; + } + else if (level <= 90 && level > 60) + { + legs[i].name = "L2 Legs"; + legs[i].level = 2; + legs[i].modifier = 2000 + ( rand() % ( 2500 - 2000 + 1 ) ); + legs[i].price = legs[i].modifier * 10; + } + else + { + legs[i].name = "L1 Legs"; + legs[i].level = 1; + legs[i].modifier = 1000 + ( rand() % ( 1500 - 1000 + 1 ) ); + legs[i].price = legs[i].modifier * 5; + } + } +} + +// Mouse click events +void market_menu::handle_events(sf::Event event, player_controller &pc, sf::Vector2i mouse_position) +{ + if (event.type == sf::Event::MouseButtonPressed) + { + if(event.mouseButton.button == sf::Mouse::Left) + { + for (unsigned int i = 0; i < gun_buttons.size(); i++) + { + if (gun_buttons[i].getBounds().contains(mouse_position.x, mouse_position.y)) + { + purchase_item(pc, guns[i]); + } + } + + for (unsigned int i = 0; i < cannon_buttons.size(); i++) + { + if (cannon_buttons[i].getBounds().contains(mouse_position.x, mouse_position.y)) + { + purchase_item(pc, cannons[i]); + } + } + + for (unsigned int i = 0; i < cooler_buttons.size(); i++) + { + if (cooler_buttons[i].getBounds().contains(mouse_position.x, mouse_position.y)) + { + purchase_item(pc, coolers[i]); + } + } + + for (unsigned int i = 0; i < reactor_buttons.size(); i++) + { + if (reactor_buttons[i].getBounds().contains(mouse_position.x, mouse_position.y)) + { + purchase_item(pc, reactors[i]); + } + } + + for (unsigned int i = 0; i < cockpit_buttons.size(); i++) + { + if (cockpit_buttons[i].getBounds().contains(mouse_position.x, mouse_position.y)) + { + purchase_item(pc, cockpits[i]); + } + } + + for (unsigned int i = 0; i < arm_buttons.size(); i++) + { + if (arm_buttons[i].getBounds().contains(mouse_position.x, mouse_position.y)) + { + purchase_item(pc, arms[i]); + } + } + + for (unsigned int i = 0; i < leg_buttons.size(); i++) + { + if (leg_buttons[i].getBounds().contains(mouse_position.x, mouse_position.y)) + { + purchase_item(pc, legs[i]); + } + } + + for (unsigned int i = 0; i < sell_buttons.size(); i++) + { + if (sell_buttons[i].getBounds().contains(mouse_position.x, mouse_position.y)) + { + sell_item(pc, sell_categories[i]); + } + } + + if (exit_button.getBounds().contains(mouse_position.x, mouse_position.y)) + { + visible = false; + } + } + } +} + +// Draws the market menu +void market_menu::draw_menu(sf::RenderWindow &window, player_controller &pc, sf::Vector2i mouse_position) +{ + sf::Sprite bg_sprite = sf::Sprite(gui_background_texture); + bg_sprite.setPosition(window.getView().getSize().x / 2 - 210, 20); + bg_sprite.setScale(0.54, 2); + window.draw(bg_sprite); + + for (unsigned int i = 0; i < gun_buttons.size(); i++) + { + float x = window.getView().getSize().x / 2 + 100; + + gun_buttons[i] = sf::VertexArray(sf::Quads, 4); + gun_buttons[i][0].position = sf::Vector2f(x + 10, (80 + i * 35) - 4); + gun_buttons[i][1].position = sf::Vector2f(x + 10, (80 + i * 35) + 24); + gun_buttons[i][2].position = sf::Vector2f(x + 80, (80 + i * 35) + 24); + gun_buttons[i][3].position = sf::Vector2f(x + 80, (80 + i * 35) - 4); + + sf::VertexArray gun_button_shadow = sf::VertexArray(sf::Quads, 4); + gun_button_shadow[0].position = sf::Vector2f(x + 10, (80 + i * 35) - 4); + gun_button_shadow[1].position = sf::Vector2f(x + 10, (80 + i * 35) + 27); + gun_button_shadow[2].position = sf::Vector2f(x + 83, (80 + i * 35) + 27); + gun_button_shadow[3].position = sf::Vector2f(x + 83, (80 + i * 35) - 4); + + gun_button_shadow[0].color = sf::Color::Black; + gun_button_shadow[1].color = sf::Color::Black; + gun_button_shadow[2].color = sf::Color::Black; + gun_button_shadow[3].color = sf::Color::Black; + + if (gun_buttons[i].getBounds().contains(mouse_position.x, mouse_position.y)) + { + gun_buttons[i][0].color = sf::Color(53, 53, 53, 255); + gun_buttons[i][1].color = sf::Color(53, 53, 53, 255); + gun_buttons[i][2].color = sf::Color(53, 53, 53, 255); + gun_buttons[i][3].color = sf::Color(53, 53, 53, 255); + } + else + { + gun_buttons[i][0].color = sf::Color(35, 35, 35, 255); + gun_buttons[i][1].color = sf::Color(35, 35, 35, 255); + gun_buttons[i][2].color = sf::Color(35, 35, 35, 255); + gun_buttons[i][3].color = sf::Color(35, 35, 35, 255); + } + + std::string desc = guns[i].name + ": +" + std::to_string(guns[i].modifier) + " damage, $" + std::to_string(guns[i].price); + gun_descriptions[i].setFont(market_font); + gun_descriptions[i].setCharacterSize(14); + if (guns[i].level == 3) + { + gun_descriptions[i].setFillColor(sf::Color::Green); + } + else if (guns[i].level == 2) + { + gun_descriptions[i].setFillColor(sf::Color::Yellow); + } + else if (guns[i].level == 1) + { + gun_descriptions[i].setFillColor(sf::Color::Red); + } + gun_descriptions[i].setPosition(x - 280, 80 + (i * 35)); + gun_descriptions[i].setString(desc); + + gun_button_labels[i].setFont(market_font); + gun_button_labels[i].setCharacterSize(16); + gun_button_labels[i].setFillColor(sf::Color::Black); + gun_button_labels[i].setPosition(x + 28, 80 + (i * 35)); + gun_button_labels[i].setString("BUY"); + + window.draw(gun_descriptions[i]); + window.draw(gun_button_shadow); + window.draw(gun_buttons[i]); + window.draw(gun_button_labels[i]); + } + + for (unsigned int i = 0; i < cannon_buttons.size(); i++) + { + float x = window.getView().getSize().x / 2 + 100; + + cannon_buttons[i] = sf::VertexArray(sf::Quads, 4); + cannon_buttons[i][0].position = sf::Vector2f(x + 10, (220 + i * 35) - 4); + cannon_buttons[i][1].position = sf::Vector2f(x + 10, (220 + i * 35) + 24); + cannon_buttons[i][2].position = sf::Vector2f(x + 80, (220 + i * 35) + 24); + cannon_buttons[i][3].position = sf::Vector2f(x + 80, (220 + i * 35) - 4); + + sf::VertexArray cannon_button_shadow = sf::VertexArray(sf::Quads, 4); + cannon_button_shadow[0].position = sf::Vector2f(x + 10, (220 + i * 35) - 4); + cannon_button_shadow[1].position = sf::Vector2f(x + 10, (220 + i * 35) + 27); + cannon_button_shadow[2].position = sf::Vector2f(x + 83, (220 + i * 35) + 27); + cannon_button_shadow[3].position = sf::Vector2f(x + 83, (220 + i * 35) - 4); + + cannon_button_shadow[0].color = sf::Color::Black; + cannon_button_shadow[1].color = sf::Color::Black; + cannon_button_shadow[2].color = sf::Color::Black; + cannon_button_shadow[3].color = sf::Color::Black; + + if (cannon_buttons[i].getBounds().contains(mouse_position.x, mouse_position.y)) + { + cannon_buttons[i][0].color = sf::Color(53, 53, 53, 255); + cannon_buttons[i][1].color = sf::Color(53, 53, 53, 255); + cannon_buttons[i][2].color = sf::Color(53, 53, 53, 255); + cannon_buttons[i][3].color = sf::Color(53, 53, 53, 255); + } + else + { + cannon_buttons[i][0].color = sf::Color(35, 35, 35, 255); + cannon_buttons[i][1].color = sf::Color(35, 35, 35, 255); + cannon_buttons[i][2].color = sf::Color(35, 35, 35, 255); + cannon_buttons[i][3].color = sf::Color(35, 35, 35, 255); + } + + std::string desc = cannons[i].name + ": +" + std::to_string(cannons[i].modifier) + " damage, $" + std::to_string(cannons[i].price); + cannon_descriptions[i].setFont(market_font); + cannon_descriptions[i].setCharacterSize(14); + if (cannons[i].level == 3) + { + cannon_descriptions[i].setFillColor(sf::Color::Green); + } + else if (cannons[i].level == 2) + { + cannon_descriptions[i].setFillColor(sf::Color::Yellow); + } + else if (cannons[i].level == 1) + { + cannon_descriptions[i].setFillColor(sf::Color::Red); + } + cannon_descriptions[i].setPosition(x - 280, 220 + (i * 35)); + cannon_descriptions[i].setString(desc); + + cannon_button_labels[i].setFont(market_font); + cannon_button_labels[i].setCharacterSize(16); + cannon_button_labels[i].setFillColor(sf::Color::Black); + cannon_button_labels[i].setPosition(x + 28, 220 + (i * 35)); + cannon_button_labels[i].setString("BUY"); + + window.draw(cannon_descriptions[i]); + window.draw(cannon_button_shadow); + window.draw(cannon_buttons[i]); + window.draw(cannon_button_labels[i]); + } + + for (unsigned int i = 0; i < cooler_buttons.size(); i++) + { + float x = window.getView().getSize().x / 2 + 100; + + cooler_buttons[i] = sf::VertexArray(sf::Quads, 4); + cooler_buttons[i][0].position = sf::Vector2f(x + 10, (360 + i * 35) - 4); + cooler_buttons[i][1].position = sf::Vector2f(x + 10, (360 + i * 35) + 24); + cooler_buttons[i][2].position = sf::Vector2f(x + 80, (360 + i * 35) + 24); + cooler_buttons[i][3].position = sf::Vector2f(x + 80, (360 + i * 35) - 4); + + sf::VertexArray cooler_button_shadow = sf::VertexArray(sf::Quads, 4); + cooler_button_shadow[0].position = sf::Vector2f(x + 10, (360 + i * 35) - 4); + cooler_button_shadow[1].position = sf::Vector2f(x + 10, (360 + i * 35) + 27); + cooler_button_shadow[2].position = sf::Vector2f(x + 83, (360 + i * 35) + 27); + cooler_button_shadow[3].position = sf::Vector2f(x + 83, (360 + i * 35) - 4); + + cooler_button_shadow[0].color = sf::Color::Black; + cooler_button_shadow[1].color = sf::Color::Black; + cooler_button_shadow[2].color = sf::Color::Black; + cooler_button_shadow[3].color = sf::Color::Black; + + if (cooler_buttons[i].getBounds().contains(mouse_position.x, mouse_position.y)) + { + cooler_buttons[i][0].color = sf::Color(53, 53, 53, 255); + cooler_buttons[i][1].color = sf::Color(53, 53, 53, 255); + cooler_buttons[i][2].color = sf::Color(53, 53, 53, 255); + cooler_buttons[i][3].color = sf::Color(53, 53, 53, 255); + } + else + { + cooler_buttons[i][0].color = sf::Color(35, 35, 35, 255); + cooler_buttons[i][1].color = sf::Color(35, 35, 35, 255); + cooler_buttons[i][2].color = sf::Color(35, 35, 35, 255); + cooler_buttons[i][3].color = sf::Color(35, 35, 35, 255); + } + + std::string desc = coolers[i].name + ": " + std::to_string(coolers[i].modifier) + " armor, +" + std::to_string(coolers[i].secondary_modifier) + " kbtu, $"+ std::to_string(coolers[i].price); + cooler_descriptions[i].setFont(market_font); + cooler_descriptions[i].setCharacterSize(14); + if (coolers[i].level == 3) + { + cooler_descriptions[i].setFillColor(sf::Color::Green); + } + else if (coolers[i].level == 2) + { + cooler_descriptions[i].setFillColor(sf::Color::Yellow); + } + else if (coolers[i].level == 1) + { + cooler_descriptions[i].setFillColor(sf::Color::Red); + } + cooler_descriptions[i].setPosition(x - 280, 360 + (i * 35)); + cooler_descriptions[i].setString(desc); + + cooler_button_labels[i].setFont(market_font); + cooler_button_labels[i].setCharacterSize(16); + cooler_button_labels[i].setFillColor(sf::Color::Black); + cooler_button_labels[i].setPosition(x + 28, 360 + (i * 35)); + cooler_button_labels[i].setString("BUY"); + + window.draw(cooler_descriptions[i]); + window.draw(cooler_button_shadow); + window.draw(cooler_buttons[i]); + window.draw(cooler_button_labels[i]); + } + + for (unsigned int i = 0; i < reactor_buttons.size(); i++) + { + float x = window.getView().getSize().x / 2 + 100; + + reactor_buttons[i] = sf::VertexArray(sf::Quads, 4); + reactor_buttons[i][0].position = sf::Vector2f(x + 10, (500 + i * 35) - 4); + reactor_buttons[i][1].position = sf::Vector2f(x + 10, (500 + i * 35) + 24); + reactor_buttons[i][2].position = sf::Vector2f(x + 80, (500 + i * 35) + 24); + reactor_buttons[i][3].position = sf::Vector2f(x + 80, (500 + i * 35) - 4); + + sf::VertexArray reactor_button_shadow = sf::VertexArray(sf::Quads, 4); + reactor_button_shadow[0].position = sf::Vector2f(x + 10, (500 + i * 35) - 4); + reactor_button_shadow[1].position = sf::Vector2f(x + 10, (500 + i * 35) + 27); + reactor_button_shadow[2].position = sf::Vector2f(x + 83, (500 + i * 35) + 27); + reactor_button_shadow[3].position = sf::Vector2f(x + 83, (500 + i * 35) - 4); + + reactor_button_shadow[0].color = sf::Color::Black; + reactor_button_shadow[1].color = sf::Color::Black; + reactor_button_shadow[2].color = sf::Color::Black; + reactor_button_shadow[3].color = sf::Color::Black; + + if (reactor_buttons[i].getBounds().contains(mouse_position.x, mouse_position.y)) + { + reactor_buttons[i][0].color = sf::Color(53, 53, 53, 255); + reactor_buttons[i][1].color = sf::Color(53, 53, 53, 255); + reactor_buttons[i][2].color = sf::Color(53, 53, 53, 255); + reactor_buttons[i][3].color = sf::Color(53, 53, 53, 255); + } + else + { + reactor_buttons[i][0].color = sf::Color(35, 35, 35, 255); + reactor_buttons[i][1].color = sf::Color(35, 35, 35, 255); + reactor_buttons[i][2].color = sf::Color(35, 35, 35, 255); + reactor_buttons[i][3].color = sf::Color(35, 35, 35, 255); + } + + std::string desc = reactors[i].name + ": " + std::to_string(reactors[i].modifier) + " armor, $" + std::to_string(reactors[i].price); + reactor_descriptions[i].setFont(market_font); + reactor_descriptions[i].setCharacterSize(14); + if (reactors[i].level == 3) + { + reactor_descriptions[i].setFillColor(sf::Color::Green); + } + else if (reactors[i].level == 2) + { + reactor_descriptions[i].setFillColor(sf::Color::Yellow); + } + else if (reactors[i].level == 1) + { + reactor_descriptions[i].setFillColor(sf::Color::Red); + } + reactor_descriptions[i].setPosition(x - 280, 502 + (i * 35 - 2)); + reactor_descriptions[i].setString(desc); + + reactor_button_labels[i].setFont(market_font); + reactor_button_labels[i].setCharacterSize(16); + reactor_button_labels[i].setFillColor(sf::Color::Black); + reactor_button_labels[i].setPosition(x + 28, 502 + (i * 35 - 2)); + reactor_button_labels[i].setString("BUY"); + + window.draw(reactor_descriptions[i]); + window.draw(reactor_button_shadow); + window.draw(reactor_buttons[i]); + window.draw(reactor_button_labels[i]); + } + + for (unsigned int i = 0; i < cockpit_buttons.size(); i++) + { + float x = window.getView().getSize().x / 2 + 500; + + cockpit_buttons[i] = sf::VertexArray(sf::Quads, 4); + cockpit_buttons[i][0].position = sf::Vector2f(x, (80 + i * 35) - 4); + cockpit_buttons[i][1].position = sf::Vector2f(x, (80 + i * 35) + 24); + cockpit_buttons[i][2].position = sf::Vector2f(x + 70, (80 + i * 35) + 24); + cockpit_buttons[i][3].position = sf::Vector2f(x + 70, (80 + i * 35) - 4); + + sf::VertexArray cockpit_button_shadow = sf::VertexArray(sf::Quads, 4); + cockpit_button_shadow[0].position = sf::Vector2f(x, (80 + i * 35) - 4); + cockpit_button_shadow[1].position = sf::Vector2f(x, (80 + i * 35) + 27); + cockpit_button_shadow[2].position = sf::Vector2f(x + 73, (80 + i * 35) + 27); + cockpit_button_shadow[3].position = sf::Vector2f(x + 73, (80 + i * 35) - 4); + + cockpit_button_shadow[0].color = sf::Color::Black; + cockpit_button_shadow[1].color = sf::Color::Black; + cockpit_button_shadow[2].color = sf::Color::Black; + cockpit_button_shadow[3].color = sf::Color::Black; + + if (cockpit_buttons[i].getBounds().contains(mouse_position.x, mouse_position.y)) + { + cockpit_buttons[i][0].color = sf::Color(53, 53, 53, 255); + cockpit_buttons[i][1].color = sf::Color(53, 53, 53, 255); + cockpit_buttons[i][2].color = sf::Color(53, 53, 53, 255); + cockpit_buttons[i][3].color = sf::Color(53, 53, 53, 255); + } + else + { + cockpit_buttons[i][0].color = sf::Color(35, 35, 35, 255); + cockpit_buttons[i][1].color = sf::Color(35, 35, 35, 255); + cockpit_buttons[i][2].color = sf::Color(35, 35, 35, 255); + cockpit_buttons[i][3].color = sf::Color(35, 35, 35, 255); + } + + std::string desc = cockpits[i].name + ": " + std::to_string(cockpits[i].modifier) + " armor, $" + std::to_string(cockpits[i].price); + cockpit_descriptions[i].setFont(market_font); + cockpit_descriptions[i].setCharacterSize(14); + if (cockpits[i].level == 3) + { + cockpit_descriptions[i].setFillColor(sf::Color::Green); + } + else if (cockpits[i].level == 2) + { + cockpit_descriptions[i].setFillColor(sf::Color::Yellow); + } + else if (cockpits[i].level == 1) + { + cockpit_descriptions[i].setFillColor(sf::Color::Red); + } + cockpit_descriptions[i].setPosition(x - 230, 82 + (i * 35 - 2)); + cockpit_descriptions[i].setString(desc); + + cockpit_button_labels[i].setFont(market_font); + cockpit_button_labels[i].setCharacterSize(16); + cockpit_button_labels[i].setFillColor(sf::Color::Black); + cockpit_button_labels[i].setPosition(x + 18, 82 + (i * 35 - 2)); + cockpit_button_labels[i].setString("BUY"); + + window.draw(cockpit_descriptions[i]); + window.draw(cockpit_button_shadow); + window.draw(cockpit_buttons[i]); + window.draw(cockpit_button_labels[i]); + } + + for (unsigned int i = 0; i < arm_buttons.size(); i++) + { + float x = window.getView().getSize().x / 2 + 500; + + arm_buttons[i] = sf::VertexArray(sf::Quads, 4); + arm_buttons[i][0].position = sf::Vector2f(x, (220 + i * 35) - 4); + arm_buttons[i][1].position = sf::Vector2f(x, (220 + i * 35) + 24); + arm_buttons[i][2].position = sf::Vector2f(x + 70, (220 + i * 35) + 24); + arm_buttons[i][3].position = sf::Vector2f(x + 70, (220 + i * 35) - 4); + + sf::VertexArray arm_button_shadow = sf::VertexArray(sf::Quads, 4); + arm_button_shadow[0].position = sf::Vector2f(x, (220 + i * 35) - 4); + arm_button_shadow[1].position = sf::Vector2f(x, (220 + i * 35) + 27); + arm_button_shadow[2].position = sf::Vector2f(x + 73, (220 + i * 35) + 27); + arm_button_shadow[3].position = sf::Vector2f(x + 73, (220 + i * 35) - 4); + + arm_button_shadow[0].color = sf::Color::Black; + arm_button_shadow[1].color = sf::Color::Black; + arm_button_shadow[2].color = sf::Color::Black; + arm_button_shadow[3].color = sf::Color::Black; + + if (arm_buttons[i].getBounds().contains(mouse_position.x, mouse_position.y)) + { + arm_buttons[i][0].color = sf::Color(53, 53, 53, 255); + arm_buttons[i][1].color = sf::Color(53, 53, 53, 255); + arm_buttons[i][2].color = sf::Color(53, 53, 53, 255); + arm_buttons[i][3].color = sf::Color(53, 53, 53, 255); + } + else + { + arm_buttons[i][0].color = sf::Color(35, 35, 35, 255); + arm_buttons[i][1].color = sf::Color(35, 35, 35, 255); + arm_buttons[i][2].color = sf::Color(35, 35, 35, 255); + arm_buttons[i][3].color = sf::Color(35, 35, 35, 255); + } + + std::string desc = arms[i].name + ": " + std::to_string(arms[i].modifier) + " armor, $" + std::to_string(arms[i].price); + arm_descriptions[i].setFont(market_font); + arm_descriptions[i].setCharacterSize(14); + if (arms[i].level == 3) + { + arm_descriptions[i].setFillColor(sf::Color::Green); + } + else if (arms[i].level == 2) + { + arm_descriptions[i].setFillColor(sf::Color::Yellow); + } + else if (arms[i].level == 1) + { + arm_descriptions[i].setFillColor(sf::Color::Red); + } + arm_descriptions[i].setPosition(x - 230, 222 + (i * 35 - 2)); + arm_descriptions[i].setString(desc); + + arm_button_labels[i].setFont(market_font); + arm_button_labels[i].setCharacterSize(16); + arm_button_labels[i].setFillColor(sf::Color::Black); + arm_button_labels[i].setPosition(x + 18, 222 + (i * 35 - 2)); + arm_button_labels[i].setString("BUY"); + + window.draw(arm_descriptions[i]); + window.draw(arm_button_shadow); + window.draw(arm_buttons[i]); + window.draw(arm_button_labels[i]); + } + + for (unsigned int i = 0; i < leg_buttons.size(); i++) + { + float x = window.getView().getSize().x / 2 + 500; + + leg_buttons[i] = sf::VertexArray(sf::Quads, 4); + leg_buttons[i][0].position = sf::Vector2f(x, (360 + i * 35) - 4); + leg_buttons[i][1].position = sf::Vector2f(x, (360 + i * 35) + 24); + leg_buttons[i][2].position = sf::Vector2f(x + 70, (360 + i * 35) + 24); + leg_buttons[i][3].position = sf::Vector2f(x + 70, (360 + i * 35) - 4); + + sf::VertexArray leg_button_shadow = sf::VertexArray(sf::Quads, 4); + leg_button_shadow[0].position = sf::Vector2f(x, (360 + i * 35) - 4); + leg_button_shadow[1].position = sf::Vector2f(x, (360 + i * 35) + 27); + leg_button_shadow[2].position = sf::Vector2f(x + 73, (360 + i * 35) + 27); + leg_button_shadow[3].position = sf::Vector2f(x + 73, (360 + i * 35) - 4); + + leg_button_shadow[0].color = sf::Color::Black; + leg_button_shadow[1].color = sf::Color::Black; + leg_button_shadow[2].color = sf::Color::Black; + leg_button_shadow[3].color = sf::Color::Black; + + if (leg_buttons[i].getBounds().contains(mouse_position.x, mouse_position.y)) + { + leg_buttons[i][0].color = sf::Color(53, 53, 53, 255); + leg_buttons[i][1].color = sf::Color(53, 53, 53, 255); + leg_buttons[i][2].color = sf::Color(53, 53, 53, 255); + leg_buttons[i][3].color = sf::Color(53, 53, 53, 255); + } + else + { + leg_buttons[i][0].color = sf::Color(35, 35, 35, 255); + leg_buttons[i][1].color = sf::Color(35, 35, 35, 255); + leg_buttons[i][2].color = sf::Color(35, 35, 35, 255); + leg_buttons[i][3].color = sf::Color(35, 35, 35, 255); + } + + std::string desc = legs[i].name + ": " + std::to_string(legs[i].modifier) + " armor, $"+ std::to_string(legs[i].price); + leg_descriptions[i].setFont(market_font); + leg_descriptions[i].setCharacterSize(14); + if (legs[i].level == 3) + { + leg_descriptions[i].setFillColor(sf::Color::Green); + } + else if (legs[i].level == 2) + { + leg_descriptions[i].setFillColor(sf::Color::Yellow); + } + else if (legs[i].level == 1) + { + leg_descriptions[i].setFillColor(sf::Color::Red); + } + leg_descriptions[i].setPosition(x - 230, 362 + (i * 35 - 2)); + leg_descriptions[i].setString(desc); + + leg_button_labels[i].setFont(market_font); + leg_button_labels[i].setCharacterSize(16); + leg_button_labels[i].setFillColor(sf::Color::Black); + leg_button_labels[i].setPosition(x + 18, 362 + (i * 35 - 2)); + leg_button_labels[i].setString("BUY"); + + window.draw(leg_descriptions[i]); + window.draw(leg_button_shadow); + window.draw(leg_buttons[i]); + window.draw(leg_button_labels[i]); + } + + item_worth[0] = pc.player_mech.guns_modifier * 5000; + item_worth[1] = pc.player_mech.cannons_modifier * 5000; + item_worth[2] = pc.player_mech.cooler_modifier * 7 + pc.player_mech.cooler_modifier * 2500; + item_worth[3] = pc.player_mech.max_reactor_integrity * 3; + item_worth[4] = pc.player_mech.max_cockpit_integrity * 3; + item_worth[5] = pc.player_mech.max_left_arm_integrity * 3; + item_worth[6] = pc.player_mech.max_left_leg_integrity * 3; + + sf::Text worth; + worth.setString(""); + + for (unsigned int i = 0; i < sell_categories.size(); i++) + { + float y_origin = window.getView().getSize().y * 0.725; + float x = i <= 3 ? 10 : 180; + float y = i <= 3 ? i : i - 4; + + sell_buttons[i] = sf::VertexArray(sf::Quads, 4); + sell_buttons[i][0].position = sf::Vector2f(x, (y_origin + y * 35) - 4); + sell_buttons[i][1].position = sf::Vector2f(x, (y_origin + y * 35) + 24); + sell_buttons[i][2].position = sf::Vector2f(x + 140, (y_origin + y * 35) + 24); + sell_buttons[i][3].position = sf::Vector2f(x + 140, (y_origin + y * 35) - 4); + + sf::VertexArray sell_button_shadow = sf::VertexArray(sf::Quads, 4); + sell_button_shadow[0].position = sf::Vector2f(x, (y_origin + y * 35) - 4); + sell_button_shadow[1].position = sf::Vector2f(x, (y_origin + y * 35) + 27); + sell_button_shadow[2].position = sf::Vector2f(x + 143, (y_origin + y * 35) + 27); + sell_button_shadow[3].position = sf::Vector2f(x + 143, (y_origin + y * 35) - 4); + + sell_button_shadow[0].color = sf::Color::Black; + sell_button_shadow[1].color = sf::Color::Black; + sell_button_shadow[2].color = sf::Color::Black; + sell_button_shadow[3].color = sf::Color::Black; + + if (sell_buttons[i].getBounds().contains(mouse_position.x, mouse_position.y)) + { + sell_buttons[i][0].color = sf::Color(53, 53, 53, 255); + sell_buttons[i][1].color = sf::Color(53, 53, 53, 255); + sell_buttons[i][2].color = sf::Color(53, 53, 53, 255); + sell_buttons[i][3].color = sf::Color(53, 53, 53, 255); + } + else + { + sell_buttons[i][0].color = sf::Color(35, 35, 35, 255); + sell_buttons[i][1].color = sf::Color(35, 35, 35, 255); + sell_buttons[i][2].color = sf::Color(35, 35, 35, 255); + sell_buttons[i][3].color = sf::Color(35, 35, 35, 255); + } + + sell_button_labels[i].setFont(market_font); + sell_button_labels[i].setCharacterSize(16); + sell_button_labels[i].setFillColor(sf::Color::Black); + sell_button_labels[i].setPosition(x + 18, (y_origin + 2) + (y * 35 - 2)); + sell_button_labels[i].setString("SELL " + sell_categories[i]); + + window.draw(sell_button_shadow); + window.draw(sell_buttons[i]); + window.draw(sell_button_labels[i]); + + if (sell_buttons[i].getBounds().contains(mouse_position.x, mouse_position.y)) + { + worth.setString("$" + std::to_string(item_worth[i])); + worth.setFont(market_font); + worth.setCharacterSize(16); + worth.setFillColor(sf::Color::White); + worth.setPosition(mouse_position.x + 20, mouse_position.y); + } + } + + window.draw(worth); + + float x = window.getView().getSize().x / 2 + 500; + + exit_button = sf::VertexArray(sf::Quads, 4); + exit_button[0].position = sf::Vector2f(x, 596); + exit_button[1].position = sf::Vector2f(x, 624); + exit_button[2].position = sf::Vector2f(x + 70, 624); + exit_button[3].position = sf::Vector2f(x + 70, 596); + + sf::VertexArray exit_button_shadow = sf::VertexArray(sf::Quads, 4); + exit_button_shadow[0].position = sf::Vector2f(x, 596); + exit_button_shadow[1].position = sf::Vector2f(x, 627); + exit_button_shadow[2].position = sf::Vector2f(x + 73, 627); + exit_button_shadow[3].position = sf::Vector2f(x + 73, 596); + + exit_button_shadow[0].color = sf::Color::Black; + exit_button_shadow[1].color = sf::Color::Black; + exit_button_shadow[2].color = sf::Color::Black; + exit_button_shadow[3].color = sf::Color::Black; + + if (exit_button.getBounds().contains(mouse_position.x, mouse_position.y)) + { + exit_button[0].color = sf::Color(53, 53, 53, 255); + exit_button[1].color = sf::Color(53, 53, 53, 255); + exit_button[2].color = sf::Color(53, 53, 53, 255); + exit_button[3].color = sf::Color(53, 53, 53, 255); + } + else + { + exit_button[0].color = sf::Color(35, 35, 35, 255); + exit_button[1].color = sf::Color(35, 35, 35, 255); + exit_button[2].color = sf::Color(35, 35, 35, 255); + exit_button[3].color = sf::Color(35, 35, 35, 255); + } + + sf::Text exit_button_label; + exit_button_label.setFont(market_font); + exit_button_label.setCharacterSize(18); + exit_button_label.setFillColor(sf::Color::Black); + exit_button_label.setPosition(x + 18, 598); + exit_button_label.setString("EXIT"); + + window.draw(exit_button_shadow); + window.draw(exit_button); + window.draw(exit_button_label); +} diff --git a/src/mech.cpp b/src/mech.cpp new file mode 100644 index 0000000..03dcb33 --- /dev/null +++ b/src/mech.cpp @@ -0,0 +1,190 @@ +#include +#include +#include + +// Constructor +mech::mech() +{ + heat = 0; + speed = 0; + weapon = 0; + weight = 70; + + cockpit_integrity = 1000; + right_leg_integrity = 1000; + left_leg_integrity = 1000; + right_arm_integrity = 1000; + left_arm_integrity = 1000; + cooler_integrity = 1000; + reactor_integrity = 1000; + + guns_modifier = 0; + cannons_modifier = 0; + cooler_modifier = 0; + max_reactor_integrity = 1000; + max_cooler_integrity = 1000; + max_left_leg_integrity = 1000; + max_right_leg_integrity = 1000; + max_left_arm_integrity = 1000; + max_right_arm_integrity = 1000; + max_cockpit_integrity = 1000; + + primary_weapon = "Standard Pulse Laser"; + secondary_weapon = "Standard Autocannon"; + reactor = "Standard Reactor"; + cooler = "Standard Cooler"; + left_leg = "Standard Left Leg"; + right_leg = "Standard Right Leg"; + left_arm = "Standard Left Arm"; + right_arm = "Standard Right Arm"; + cockpit = "Standard Cockpit"; + + is_player = false; + power_down = false; + taking_damage = false; +} + +// Removes all damage from the mech +void mech::repair() +{ + power_down = false; + heat = 0; + cockpit_integrity = max_cockpit_integrity; + right_leg_integrity = max_right_leg_integrity; + left_leg_integrity = max_left_leg_integrity; + right_arm_integrity = max_right_arm_integrity; + left_arm_integrity = max_left_arm_integrity; + cooler_integrity = max_cooler_integrity; + reactor_integrity = max_reactor_integrity; +} + +// Heat and damage calculations +void mech::update() +{ + if (heat >= 90) + { + reactor_integrity = reactor_integrity >= 1 ? reactor_integrity - 1 : 0; + } + + float cooling = ((1 + cooler_modifier) * ((float)cooler_integrity / (float)max_cooler_integrity)) + 0.01; + heat = heat > 0 ? heat - cooling : 0; + + if (taking_damage == true) + { + damage_timer++; + if (damage_timer >= 100) + { + taking_damage = false; + damage_timer = 0; + } + } +} + +// Returns the total integrity of the mech +int mech::total_integrity() +{ + return reactor_integrity + + cooler_integrity + right_arm_integrity + + left_arm_integrity + right_leg_integrity + + left_leg_integrity + cockpit_integrity; +} + +// Returns the maximum total integrity of the mech +int mech::max_total_integrity() +{ + return max_reactor_integrity + + max_cooler_integrity + max_right_arm_integrity + + max_left_arm_integrity + max_right_leg_integrity + + max_left_leg_integrity + max_cockpit_integrity; +} + +// Returns true if the mech's legs are not destroyed +bool mech::can_move() +{ + return left_leg_integrity > 0 && right_leg_integrity > 0; +} + +// Returns true if the mech's arms are not destroyed +bool mech::can_fire() +{ + return left_arm_integrity > 0 || right_arm_integrity > 0; +} + +// Returns true if only the left arm has been destroyed +bool mech::left_arm_destroyed() +{ + return left_arm_integrity < 1 && right_arm_integrity > 0; +} + +// Returns true if only the right arm has been destroyed +bool mech::right_arm_destroyed() +{ + return left_arm_integrity > 0 && right_arm_integrity < 1; +} + +// Returns true if the mech's total integrity is less than 50% or the mech's reactor is destroyed +bool mech::destroyed() +{ + if (reactor_integrity < 1) + { + return true; + } + + if (total_integrity() < max_total_integrity() / 2) + { + return true; + } + + return false; +} + +// Calculates damage dealt to the targeted component +void mech::take_damage(std::string target, float distance, int weapon) +{ + float dist_mod = weapon == 1 ? 0.05 : 0.01; + taking_damage = true; + damage_timer = 0; + + if (target == "reactor") + { + int damage_dealt = weapon * ((rand() % 10) - (distance * dist_mod) - (speed * 10)); + damage_dealt = damage_dealt > 0 ? damage_dealt : 0; + reactor_integrity = reactor_integrity - damage_dealt > 0 ? reactor_integrity - damage_dealt : 0; + } + else if (target == "cooler") + { + int damage_dealt = weapon * ((rand() % 20) - (distance * dist_mod) - (speed * 20)); + damage_dealt = damage_dealt > 0 ? damage_dealt : 0; + cooler_integrity = cooler_integrity - damage_dealt > 0 ? cooler_integrity - damage_dealt : 0; + } + else if (target == "left arm") + { + int damage_dealt = weapon * ((rand() % 30) - (distance * dist_mod) - (speed * 30)); + damage_dealt = damage_dealt > 0 ? damage_dealt : 0; + left_arm_integrity = left_arm_integrity - damage_dealt > 0 ? left_arm_integrity - damage_dealt : 0; + } + else if (target == "right arm") + { + int damage_dealt = weapon * ((rand() % 30) - (distance * dist_mod) - (speed * 30)); + damage_dealt = damage_dealt > 0 ? damage_dealt : 0; + right_arm_integrity = right_arm_integrity - damage_dealt > 0 ? right_arm_integrity - damage_dealt : 0; + } + else if (target == "left leg") + { + int damage_dealt = weapon * ((rand() % 40) - (distance * dist_mod) - (speed * 40)); + damage_dealt = damage_dealt > 0 ? damage_dealt : 0; + left_leg_integrity = left_leg_integrity - damage_dealt > 0 ? left_leg_integrity - damage_dealt : 0; + } + else if (target == "right leg") + { + int damage_dealt = weapon * ((rand() % 40) - (distance * dist_mod) - (speed * 40)); + damage_dealt = damage_dealt > 0 ? damage_dealt : 0; + right_leg_integrity = right_leg_integrity - damage_dealt > 0 ? right_leg_integrity - damage_dealt : 0; + } + else if (target == "cockpit") + { + int damage_dealt = weapon * ((rand() % 30) - (distance * dist_mod) - (speed * 30)); + damage_dealt = damage_dealt > 0 ? damage_dealt : 0; + cockpit_integrity = cockpit_integrity - damage_dealt > 0 ? cockpit_integrity - damage_dealt : 0; + } +} diff --git a/src/player_controller.cpp b/src/player_controller.cpp new file mode 100644 index 0000000..a91b718 --- /dev/null +++ b/src/player_controller.cpp @@ -0,0 +1,628 @@ +#include +#include +#include +#include +#include +#include + +// Constructor +player_controller::player_controller() +{ + credits = 0; + credits_earned = 0; + cannon_flash_timer = 0; + muzzle_flash_timer = 0; + target_id = 0; + enemy_id = 0; + mission = 1; + guns_timer = 0; + cannon_timer = 0; + stomp_timer = 0; + step_timer = 0; + torso_angle = 0; + look_offset = -6; + player_pos.x = 140; + player_pos.y = 140; + targeted_component = 0; + mouse_move_timer = 0; + components = {"reactor", "cooler", "left arm", "right arm", "left leg", "right leg", "cockpit"}; +} + +// Gets current directory, initializes resources and key bindings +void player_controller::init(std::string cwd, assets &resources) +{ + this->resources = resources; + kb.load(cwd); +} + +// Collision checking +void player_controller::collision_check(entity other, float view_range) +{ + if (other.type == "wall") + { + if (get_distance(other.position, player_pos) < view_range * 0.4) + { + resources.crash_sound.setVolume(100 * audio_volume); + resources.crash_sound.play(); + player_mech.speed = 0; + + if (other.position.x > player_pos.x) + { + player_pos.x -= 20; + } + + if (other.position.x < player_pos.x) + { + player_pos.x += 20; + } + + if (other.position.y < player_pos.y) + { + player_pos.y += 20; + } + + if (other.position.y > player_pos.y) + { + player_pos.y -= 20; + } + } + } +} + +// Target locking +void player_controller::lock_target(std::vector &entities, int entity_count, float window_width) +{ + for (int i = 0; i < entity_count; i++) + { + if (entities[i].visible == true) + { + float scale = 3 - (entities[i].distance * 0.05) - look_offset * 0.005; + float sprite_width = entities[i].sprite.getTexture()->getSize().x * scale; + float center = entities[i].draw_x + (sprite_width / 2); + + if (entities[i].visible == true && + entities[i].dead == false && + center > window_width * 0.45 && + center < window_width * 0.55) + { + target_id = entities[i].id; + break; + } + } + } +} + +// Firing guns +void player_controller::fire_guns(std::vector &entities, int entity_count, float window_width) +{ + if(player_mech.can_fire() == true && guns_firing == false && cannon_firing == false) + { + guns_firing = true; + muzzle_flash = true; + player_mech.heat = player_mech.heat >= 90 ? 100 : player_mech.heat + 10 + player_mech.guns_modifier; + + for (int i = 0; i < entity_count; i++) + { + if (entities[i].visible == true && hit_target == false) + { + float scale = 3 - (entities[i].distance * 0.05) - look_offset * 0.005; + float sprite_width = entities[i].sprite.getTexture()->getSize().x * scale; + float center = entities[i].draw_x + (sprite_width / 2); + + if (entities[i].visible == true && + entities[i].dead == false && + center > window_width * 0.45 && + center < window_width * 0.55) + { + if (target_id != entities[i].id) + { + target_id = entities[i].id; + } + + hit_target = true; + break; + } + } + } + + resources.gun_sound.setVolume(50 * audio_volume); + resources.gun_sound.play(); + } +} + +// Firing cannon +void player_controller::fire_cannon(std::vector &entities, int entity_count, float window_width) +{ + if(player_mech.can_fire() == true && cannon_firing == false && guns_firing == false) + { + cannon_firing = true; + cannon_flash = true; + player_mech.heat = player_mech.heat >= 50 ? 100 : player_mech.heat + 50 + player_mech.cannons_modifier; + + for (int i = 0; i < entity_count; i++) + { + if (entities[i].visible == true && hit_target == false) + { + float scale = 3 - (entities[i].distance * 0.05) - look_offset * 0.005; + float sprite_width = entities[i].sprite.getTexture()->getSize().x * scale; + float center = entities[i].draw_x + (sprite_width / 2); + + if (entities[i].visible == true && + entities[i].dead == false && + center > window_width * 0.45 && + center < window_width * 0.55) + { + if (target_id != entities[i].id) + { + target_id = entities[i].id; + } + + hit_target = true; + break; + } + } + } + + resources.cannon_sound.setVolume(50 * audio_volume); + resources.cannon_sound.play(); + } +} + +// Resets all volatile variables +void player_controller::reset() +{ + throttle_up = false; + throttle_down = false; + move_forward = false; + move_back = false; + turn_left = false; + turn_right = false; + look_left = false; + look_right = false; + look_up = false; + look_down = false; + player_firing = false; + target_id = 0; + enemy_id = 0; + guns_timer = 0; + stomp_timer = 0; + step_timer = 0; + torso_angle = 0; + look_offset = -6; + player_mech.speed = 0; + player_pos.x = 140; + player_pos.y = 140; + targeted_component = 0; + credits_earned = 0; +} + +// Called by main window event handler to handle events related to the player controller +void player_controller::handle_events(sf::RenderWindow &window, sf::Event event) +{ + if(event.type == sf::Event::KeyPressed) + { + if (player_mech.destroyed() == false) + { + if(event.key.code == kb.bindings["throttle_up"]) + { + throttle_up = true; + } + + if(event.key.code == kb.bindings["throttle_down"]) + { + throttle_down = true; + } + + if(event.key.code == kb.bindings["turn_left"]) + { + turn_left = true; + } + + if(event.key.code == kb.bindings["turn_right"]) + { + turn_right = true; + } + + if(event.key.code == kb.bindings["look_left"]) + { + look_left = true; + } + + if(event.key.code == kb.bindings["look_right"]) + { + look_right = true; + } + + if (event.key.code == kb.bindings["look_down"]) + { + look_down = true; + } + + if (event.key.code == kb.bindings["look_up"]) + { + look_up = true; + } + + if(event.key.code == kb.bindings["select_component"]) + { + if (targeted_component < 6) + { + targeted_component++; + } + else + { + targeted_component = 0; + } + } + + if (event.key.code == kb.bindings["fire_guns"]) + { + player_mech.weapon = 1; + player_firing = true; + } + + if (event.key.code == kb.bindings["fire_cannon"]) + { + player_mech.weapon = 5; + player_firing = true; + } + } + } + + if(event.type == sf::Event::KeyReleased) + { + if(event.key.code == kb.bindings["throttle_up"]) + { + throttle_up = false; + } + + if(event.key.code == kb.bindings["throttle_down"]) + { + throttle_down = false; + } + + if(event.key.code == kb.bindings["turn_left"]) + { + turn_left = false; + } + + if(event.key.code == kb.bindings["turn_right"]) + { + turn_right = false; + } + + if(event.key.code == kb.bindings["look_left"]) + { + look_left = false; + } + + if(event.key.code == kb.bindings["look_right"]) + { + look_right = false; + } + + if(event.key.code == kb.bindings["look_down"]) + { + look_down = false; + } + + if(event.key.code == kb.bindings["look_up"]) + { + look_up = false; + } + + if (event.key.code == kb.bindings["fire_guns"]) + { + player_firing = false; + } + + if (event.key.code == kb.bindings["fire_cannon"]) + { + player_firing = false; + } + } + + if(event.type == sf::Event::MouseMoved) + { + mouse_moved = true; + + sf::Vector2i mouse_pos = sf::Mouse().getPosition(window); + + if (mouse_pos.x >= window.getView().getSize().x * 0.51) + { + look_right = true; + look_left = false; + sf::Vector2i center; + center.x = sf::Mouse().getPosition(window).x - 1; + center.y = sf::Mouse().getPosition(window).y; + sf::Mouse().setPosition(center, window); + } + + if (mouse_pos.x <= window.getView().getSize().x * 0.49) + { + look_left = true; + look_right = false; + sf::Vector2i center; + center.x = sf::Mouse().getPosition(window).x + 1; + center.y = sf::Mouse().getPosition(window).y; + sf::Mouse().setPosition(center, window); + } + + if (mouse_pos.y > window.getView().getSize().y * 0.55) + { + if (invert_mouse == true) + { + look_up = true; + look_down = false; + } + else + { + look_down = true; + look_up = false; + } + + sf::Vector2i center; + center.x = sf::Mouse().getPosition(window).x; + center.y = window.getView().getSize().y * 0.55; + sf::Mouse().setPosition(center, window); + } + + if (mouse_pos.y < window.getView().getSize().y * 0.45) + { + if (invert_mouse == true) + { + look_down = true; + look_up = false; + } + else + { + look_up = true; + look_down = false; + } + + sf::Vector2i center; + center.x = sf::Mouse().getPosition(window).x; + center.y = window.getView().getSize().y * 0.45; + sf::Mouse().setPosition(center, window); + } + } + + if (event.type == sf::Event::MouseButtonPressed) + { + if(event.mouseButton.button == sf::Mouse::Left) + { + player_mech.weapon = 1; + player_firing = true; + } + + if(event.mouseButton.button == sf::Mouse::Right) + { + player_mech.weapon = 5; + player_firing = true; + } + } + + if (event.type == sf::Event::MouseButtonReleased) + { + if(event.mouseButton.button == sf::Mouse::Left) + { + player_firing = false; + } + + if(event.mouseButton.button == sf::Mouse::Right) + { + player_firing = false; + } + } +} + +// Update function called every frame +void player_controller::update(sf::RenderWindow &window, float frame_time) +{ + if (mouse_moved == true) + { + mouse_move_timer += frame_time; + if (mouse_move_timer >= frame_time * 3) + { + mouse_moved = false; + mouse_move_timer = 0; + look_right = false; + look_left = false; + look_up = false; + look_down = false; + } + } +} + +// Update function called ten times per second +void player_controller::fixed_update(sf::Transformable player) +{ + player_mech.update(); + + // Player movement vectors + look_pos.x = player.getPosition().x + 30 * cos (player.getRotation() * (3.14 / 180)); + look_pos.y = player.getPosition().y + 30 * sin (player.getRotation() * (3.14 / 180)); + + back_pos.x = player.getPosition().x + 30 * cos ((player.getRotation() - 180) * (3.14 / 180)); + back_pos.y = player.getPosition().y + 30 * sin ((player.getRotation() - 180) * (3.14 / 180)); + + left_pos.x = player.getPosition().x + 30 * cos ((player.getRotation() - 90) * (3.14 / 180)); + left_pos.y = player.getPosition().y + 30 * sin ((player.getRotation() - 90) * (3.14 / 180)); + + right_pos.x = player.getPosition().x + 30 * cos ((player.getRotation() + 90) * (3.14 / 180)); + right_pos.y = player.getPosition().y + 30 * sin ((player.getRotation() + 90) * (3.14 / 180)); + + // Movement + if (player_mech.speed > 0) + { + move_forward = true; + } + else + { + move_forward = false; + } + + if (player_mech.speed < 0) + { + move_back = true; + } + else + { + move_back = false; + } + + if (move_forward) + { + if (player_pos.x < look_pos.x) + { + player_pos.x += player_mech.speed; + } + if (player_pos.y < look_pos.y) + { + player_pos.y += player_mech.speed; + } + if (player_pos.x > look_pos.x) + { + player_pos.x -= player_mech.speed; + } + if (player_pos.y > look_pos.y) + { + player_pos.y -= player_mech.speed; + } + } + + if (move_back) + { + if (player_pos.x < back_pos.x) + { + player_pos.x -= player_mech.speed; + } + if (player_pos.y < back_pos.y) + { + player_pos.y -= player_mech.speed; + } + if (player_pos.x > back_pos.x) + { + player_pos.x += player_mech.speed; + } + if (player_pos.y > back_pos.y) + { + player_pos.y += player_mech.speed; + } + } + + look_offset = look_offset > 15 ? 15 : look_offset < -27 ? -27 : look_offset; + + // Throttle + if (throttle_up == true && player_mech.can_move() == true) + { + if (player_mech.speed < 0.125) + { + player_mech.speed += 0.001; + } + } + + if (throttle_down == true && player_mech.can_move() == true) + { + if (player_mech.speed > -0.0625) + { + player_mech.speed -= 0.001; + } + } + + if (player_mech.can_move() == false) + { + player_mech.speed = 0; + } + + // Mech stomp sounds + if (player_mech.speed != 0) + { + if (player_mech.speed > 0) + { + step_timer += player_mech.speed; + } + else + { + step_timer += -player_mech.speed; + } + + if (step_timer >= 0.25) + { + stomp_timer += 0.1; + + if (stomp_timer >= 0 && stomp_timer < 0.2) + { + resources.hydraulic_sound.setVolume(15 * audio_volume); + resources.hydraulic_sound.play(); + if (look_offset < 10) + { + look_offset -= 0.5; + } + } + else if (stomp_timer >= 0.2 && stomp_timer < 0.5) + { + if (look_offset > -10) + { + look_offset += 0.5; + } + } + else if (stomp_timer >= 0.5 && stomp_timer < 0.7) + { + if (look_offset < 10) + { + look_offset -= 0.5; + } + } + + if (stomp_timer >= 0.7) + { + resources.stomp_sound.setVolume(50 * audio_volume); + resources.stomp_sound.play(); + step_timer = 0; + stomp_timer = 0; + } + } + } + + // Weapons + if (muzzle_flash == true) + { + muzzle_flash_timer++; + if (muzzle_flash_timer >= 4) + { + muzzle_flash_timer = 0; + muzzle_flash = false; + } + } + + if (cannon_flash == true) + { + cannon_flash_timer++; + if (cannon_flash_timer >= 4) + { + cannon_flash_timer = 0; + cannon_flash = false; + } + } + + if (guns_firing == true) + { + guns_timer++; + if (guns_timer >= 6) + { + guns_timer = 0; + guns_firing = false; + } + } + + if (cannon_firing == true) + { + cannon_timer++; + if (cannon_timer >= 24) + { + cannon_timer = 0; + cannon_firing = false; + } + } +} diff --git a/src/settings.cpp b/src/settings.cpp new file mode 100644 index 0000000..7085b34 --- /dev/null +++ b/src/settings.cpp @@ -0,0 +1,46 @@ +#include +#include +#include + +bool music = true; +bool invert_mouse = false; +double audio_volume = 1; + +// Loads settings from file +void load_settings(std::string cwd) +{ + size_t pos = 0; + std::string entry; + std::string delimeter = "\n"; + std::string saved_settings = get_file_contents(cwd + "/settings.list"); + + while ((pos = saved_settings.find(delimeter)) != std::string::npos) + { + entry = saved_settings.substr(0, pos); + std::string key = entry.substr(0, entry.find(":")); + std::string value = entry.substr(entry.find(":") + 1, pos); + if (key == "volume") + { + audio_volume = std::stod(value); + } + if (key == "music") + { + music = std::stoi(value); + } + if (key == "invert_mouse") + { + invert_mouse = std::stoi(value); + } + saved_settings.erase(0, pos + delimeter.length()); + } +} + +// Saves settings to file +void save_settings(std::string cwd) +{ + std::string current_settings = "volume:" + std::to_string(audio_volume) + "\n" + + "music:" + std::to_string(music) + "\n"; + "invert_mouse:" + std::to_string(invert_mouse) + "\n"; + + write_to_file(cwd + "/settings.list", current_settings); +} diff --git a/src/settings_menu.cpp b/src/settings_menu.cpp new file mode 100644 index 0000000..51909f4 --- /dev/null +++ b/src/settings_menu.cpp @@ -0,0 +1,248 @@ +#include +#include +#include +#include + +// Gets the current working directory from main, initializes variables and objects +void settings_menu::init(std::string cwd, assets &resources, bool in_game) +{ + this->cwd = cwd; + this->resources = resources; + this->in_game = in_game; + visible = false; + abort_prompt_open = false; + buttons.resize(5); + button_text.resize(5); + button_labels.resize(5); + button_values.resize(5); + abort_buttons.resize(2); + abort_button_text.resize(2); + abort_button_labels.resize(2); + button_text[0] = " INVERT MOUSE"; + button_text[1] = " ENABLE MUSIC"; + button_text[2] = " AUDIO VOLUME"; + button_text[3] = " RESUME GAME"; + button_text[4] = "ABORT MISSION"; + abort_button_text[0] = "ABORT"; + abort_button_text[1] = "RESUME"; +} + +// Mouse click events +void settings_menu::handle_events(sf::Event event, sf::Vector2i mouse_position) +{ + if (event.type == sf::Event::MouseButtonPressed) + { + if(event.mouseButton.button == sf::Mouse::Left) + { + if (abort_prompt_open == false) + { + for (unsigned int i = 0; i < buttons.size(); i++) + { + if (buttons[i].getBounds().contains(mouse_position.x, mouse_position.y)) + { + if (i == 0) + { + invert_mouse = !invert_mouse; + } + else if (i == 1) + { + music = !music; + } + else if (i == 2) + { + if (audio_volume <= 0.9) + { + audio_volume += 0.1; + } + else + { + audio_volume = 0.1; + } + } + else if (i == 3) + { + save_settings(cwd); + visible = false; + } + else if (i == 4 && in_game == true) + { + abort_prompt_open = true; + } + } + } + } + else + { + for (unsigned int i = 0; i < abort_buttons.size(); i++) + { + if (abort_buttons[i].getBounds().contains(mouse_position.x, mouse_position.y)) + { + if (i == 0) + { + abort_mission = true; + abort_prompt_open = false; + } + else if (i == 1) + { + abort_prompt_open = false; + } + } + } + } + } + } +} + +// Draws the menu +void settings_menu::draw_menu(sf::RenderWindow &window, sf::Vector2i mouse_position, float frame_time) +{ + if (abort_prompt_open == false) + { + sf::Sprite bg_sprite = sf::Sprite(resources.gui_background_2_texture); + bg_sprite.setPosition(window.getView().getSize().x / 2 - 100, window.getView().getSize().y / 2 - 200); + float y_scale = in_game == true ? 0.6 : 0.5; + bg_sprite.setScale(0.2, y_scale); + window.draw(bg_sprite); + + float y = window.getView().getSize().y / 2 - 180; + + button_text[3] = in_game == true ? " RESUME GAME" : " EXIT MENU"; + button_values[0].setString(invert_mouse == true ? "YES" :"NO"); + button_values[1].setString(music == true ? "YES" :"NO"); + button_values[2].setString(std::to_string((int)((100 * audio_volume) + 0.5)) + "%"); + + for (unsigned int i = 0; i < buttons.size(); i++) + { + float x = window.getView().getSize().x / 2 - 70; + + buttons[i] = sf::VertexArray(sf::Quads, 4); + buttons[i][0].position = sf::Vector2f(x, (y + i * 35) - 4); + buttons[i][1].position = sf::Vector2f(x, (y + i * 35) + 24); + buttons[i][2].position = sf::Vector2f(x + 140, (y + i * 35) + 24); + buttons[i][3].position = sf::Vector2f(x + 140, (y + i * 35) - 4); + + sf::VertexArray button_shadow = sf::VertexArray(sf::Quads, 4); + button_shadow[0].position = sf::Vector2f(x, (y + i * 35) - 4); + button_shadow[1].position = sf::Vector2f(x, (y + i * 35) + 27); + button_shadow[2].position = sf::Vector2f(x + 143, (y + i * 35) + 27); + button_shadow[3].position = sf::Vector2f(x + 143, (y + i * 35) - 4); + + button_shadow[0].color = sf::Color::Black; + button_shadow[1].color = sf::Color::Black; + button_shadow[2].color = sf::Color::Black; + button_shadow[3].color = sf::Color::Black; + + if (buttons[i].getBounds().contains(mouse_position.x, mouse_position.y)) + { + buttons[i][0].color = sf::Color(53, 53, 53, 255); + buttons[i][1].color = sf::Color(53, 53, 53, 255); + buttons[i][2].color = sf::Color(53, 53, 53, 255); + buttons[i][3].color = sf::Color(53, 53, 53, 255); + } + else + { + buttons[i][0].color = sf::Color(35, 35, 35, 255); + buttons[i][1].color = sf::Color(35, 35, 35, 255); + buttons[i][2].color = sf::Color(35, 35, 35, 255); + buttons[i][3].color = sf::Color(35, 35, 35, 255); + } + + button_labels[i].setFont(resources.exoplanetaria); + button_labels[i].setCharacterSize(16); + button_labels[i].setFillColor(sf::Color::Black); + button_labels[i].setString(button_text[i]); + + button_values[i].setFont(resources.exoplanetaria); + button_values[i].setCharacterSize(14); + button_values[i].setFillColor(sf::Color::White); + + if (i == 0) + button_labels[i].setPosition(x + 12, y); + else + button_labels[i].setPosition(x + 12, y + (i * 35)); + + if (i == 0) + button_values[i].setPosition(x + 180, y); + else + button_values[i].setPosition(x + 180, y + (i * 35)); + + bool draw = true; + + if (i == 4) + { + draw = in_game == false? false : true; + } + + if (draw == true) + { + window.draw(button_shadow); + window.draw(buttons[i]); + window.draw(button_labels[i]); + window.draw(button_values[i]); + } + } + } + else + { + resources.notice.setFont(resources.orbitron); + resources.notice.setString("ABORT MISSION?"); + sf::Vector2f text_pos; + text_pos.x = (window.getView().getSize().x / 2) - (resources.notice.getGlobalBounds().width / 2); + text_pos.y = (window.getView().getSize().y / 2) - 150; + resources.notice.setPosition(text_pos); + window.draw(resources.notice); + resources.notice.setFont(resources.exoplanetaria); + + float x = window.getView().getSize().x / 2 - 70; + float y = window.getView().getSize().y / 2 - 75; + + for (unsigned int i = 0; i < abort_buttons.size(); i++) + { + abort_buttons[i] = sf::VertexArray(sf::Quads, 4); + abort_buttons[i][0].position = sf::Vector2f(x, (y + i * 35) - 4); + abort_buttons[i][1].position = sf::Vector2f(x, (y + i * 35) + 24); + abort_buttons[i][2].position = sf::Vector2f(x + 130, (y + i * 35) + 24); + abort_buttons[i][3].position = sf::Vector2f(x + 130, (y + i * 35) - 4); + + sf::VertexArray button_shadow = sf::VertexArray(sf::Quads, 4); + button_shadow[0].position = sf::Vector2f(x, (y + i * 35) - 4); + button_shadow[1].position = sf::Vector2f(x, (y + i * 35) + 27); + button_shadow[2].position = sf::Vector2f(x + 133, (y + i * 35) + 27); + button_shadow[3].position = sf::Vector2f(x + 133, (y + i * 35) - 4); + + button_shadow[0].color = sf::Color::Black; + button_shadow[1].color = sf::Color::Black; + button_shadow[2].color = sf::Color::Black; + button_shadow[3].color = sf::Color::Black; + + if (abort_buttons[i].getBounds().contains(mouse_position.x, mouse_position.y)) + { + abort_buttons[i][0].color = sf::Color(53, 53, 53, 255); + abort_buttons[i][1].color = sf::Color(53, 53, 53, 255); + abort_buttons[i][2].color = sf::Color(53, 53, 53, 255); + abort_buttons[i][3].color = sf::Color(53, 53, 53, 255); + } + else + { + abort_buttons[i][0].color = sf::Color(35, 35, 35, 255); + abort_buttons[i][1].color = sf::Color(35, 35, 35, 255); + abort_buttons[i][2].color = sf::Color(35, 35, 35, 255); + abort_buttons[i][3].color = sf::Color(35, 35, 35, 255); + } + + abort_button_labels[i].setFont(resources.exoplanetaria); + abort_button_labels[i].setCharacterSize(16); + abort_button_labels[i].setFillColor(sf::Color::Black); + abort_button_labels[i].setString(abort_button_text[i]); + + if (i == 0) + abort_button_labels[i].setPosition(x + 38, y); + else + abort_button_labels[i].setPosition(x + 38, y + (i * 35)); + + window.draw(button_shadow); + window.draw(abort_buttons[i]); + window.draw(abort_button_labels[i]); + } + } +} diff --git a/src/tutorial.cpp b/src/tutorial.cpp new file mode 100644 index 0000000..5f67175 --- /dev/null +++ b/src/tutorial.cpp @@ -0,0 +1,165 @@ +#include + +// Constructor +tutorial::tutorial(std::string cwd) +{ + step = 0; + visible = false; + + if (!gui_background_texture.loadFromFile(cwd + "/assets/textures/gui_background.png")) + { + std::cout << "Failed to load textures."; + } + gui_background_sprite.setTexture(gui_background_texture); + + if (!tutorial_font.loadFromFile(cwd + "/assets/Exoplanetaria-gxxJ5.ttf")) + { + std::cout << "Failed to load font."; + } +} + +// Draws tutorial messages +void tutorial::draw_tutorial(sf::RenderWindow &window, bool show_keys, float speed, float torso_angle, float heat) +{ + if (step == 0) + { + sf::String text = std::string("Key bindings can be changed by modifying the bindings.list file.\n") + + std::string("Press 'show_keys' (F2) now to view all of your current key bindings.\n") + + std::string("Press 'show_keys' (F2) again to stop displaying key bindings."); + tutorial_text.setString(text); + + if (show_keys == true) + { + step = 1; + } + } + else if (step == 1) + { + sf::String text = std::string("Your mech's torso and legs are controlled separately.\n") + + std::string("Press the 'look left' or 'look right' key now to rotate\n") + + std::string("your mech's torso 90 degrees to the left or right."); + tutorial_text.setString(text); + + if (torso_angle >= 80 || torso_angle <= -80) + { + step = 2; + } + } + else if (step == 2) + { + sf::String text = std::string("Press the 'map' key to increase the size of the mini-map / radar display.\n") + + std::string("The map key cycles between map sizes and toggles display of the map.\n") + + std::string("The white circle represents your mech's position in the world.\n") + + std::string("The green line represents the direction your mech's legs are facing.\n") + + std::string("The red line represents the direction your mech's torso is facing.\n\n") + + std::string("Press enter to continue."); + tutorial_text.setString(text); + } + else if (step == 3) + { + sf::String text = std::string("Rotate your mech's torso back to zero degrees.\n") + + std::string("This means the mech's legs and torso are facing the same direction."); + tutorial_text.setString(text); + + if (torso_angle >= -3 && torso_angle <= 3) + { + step = 4; + } + } + else if (step == 4) + { + sf::String text = std::string("Increase your mech's throttle by pressing and holding the 'throttle_up' key.\n") + + std::string("Try increasing the throttle to 25% now."); + tutorial_text.setString(text); + + int throttle = floor((speed) / 0.125 * 100); + if (throttle >= 25) + { + step = 5; + } + } + else if (step == 5) + { + sf::String text = std::string("Decrease your mech's throttle by pressing and holding the 'throttle_down' key.\n") + + std::string("Try decreasing the throttle to 3% now."); + tutorial_text.setString(text); + + int throttle = floor((speed) / 0.125 * 100); + if (throttle <= 3) + { + step = 6; + } + } + else if (step == 6) + { + sf::String text = std::string("Firing your weapons increases the amount of heat generated by your mech.\n") + + std::string("Generating too much heat will cause damage to the mech's reactor.\n") + + std::string("Autocannons are a long range weapon with a low rate of fire.\n") + + std::string("Pulse lasers are a short range weapon with a higher rate of fire.\n") + + std::string("Autocannons do more damage in a single shot compared to pulse lasers.\n") + + std::string("Fire your weapons now by pressing the 'fire_guns' or 'fire_cannons' key.\n") + + std::string("Pay close attention to the heat readout and meter on your HUD."); + tutorial_text.setString(text); + + if (heat > 0) + { + step = 7; + } + } + else if (step == 7) + { + sf::String text = std::string("If your mech's cooler is damaged, your mech will be more likely to overheat.\n") + + std::string("If your mech's arms are damaged, your weapons could be disabled.\n") + + std::string("If your mech's legs are damaged, you may become unable to move.\n") + + std::string("If your mech's cockpit is damaged, torso movement may be disabled.\n") + + std::string("If your mech's reactor is destroyed, the mech becomes inoperable.\n") + + std::string("If total combined damage exceeds 50%, the mech also becomes inoperable.\n\n") + + std::string("Press enter to continue."); + tutorial_text.setString(text); + } + else if (step == 8) + { + sf::String text = std::string("When encountering an enemy mech, press the 'lock_target' key\n") + + std::string("or fire weapons at the mech to activate a target lock.\n") + + std::string("Press the 'select component' key to change which component you are targeting.\n") + + std::string("Damage dealt by either mech is affected by speed and distance.\n") + + std::string("Some components are more resistant to damage such as the cooler and reactor.\n\n") + + std::string("Press enter to continue."); + tutorial_text.setString(text); + } + else if (step == 9) + { + sf::String text = std::string("The objective in each mission is to eliminate all enemy mechs.\n") + + std::string("Enemy mechs increase in number and difficulty as you progress.\n") + + std::string("You will notice enemies have increased armor or firepower in later missions.\n\n") + + std::string("Press enter to continue."); + tutorial_text.setString(text); + } + else if (step == 10) + { + sf::String text = std::string("After each mission, you will have the opportunity to upgrade your mech.\n") + + std::string("More powerful weapons increase heat. An upgraded cooler can help with this.\n") + + std::string("Your mech's chassis can only handle 110 tons of equipment.\n") + + std::string("You will need to keep this in mind when deciding which upgrades to install.\n") + + std::string("Upgrades can be sold for a portion of the original purchase price.\n\n") + + std::string("Press enter to restart the tutorial.\n") + + std::string("Press the 'show tutorial' key to hide these messages."); + tutorial_text.setString(text); + } + + sf::Vector2f bg_pos; + bg_pos.x = (window.getView().getSize().x / 2) - (tutorial_text.getGlobalBounds().width / 2) - 25; + bg_pos.y = (window.getView().getSize().y / 2) - 170; + gui_background_sprite.setPosition(bg_pos); + gui_background_sprite.setScale(tutorial_text.getGlobalBounds().width * 0.00075, tutorial_text.getGlobalBounds().height * 0.006); + window.draw(gui_background_sprite); + + tutorial_text.setFont(tutorial_font); + tutorial_text.setCharacterSize(18); + tutorial_text.setFillColor(sf::Color::White); + sf::Vector2f text_pos; + text_pos.x = (window.getView().getSize().x / 2) - (tutorial_text.getGlobalBounds().width / 2); + text_pos.y = (window.getView().getSize().y / 2) - 150; + tutorial_text.setPosition(text_pos); + window.draw(tutorial_text); +} diff --git a/src/world_generator.cpp b/src/world_generator.cpp new file mode 100644 index 0000000..8664e39 --- /dev/null +++ b/src/world_generator.cpp @@ -0,0 +1,769 @@ +#include +#include +#include +#include +#include +#include + +// Constructor +world_generator::world_generator() +{ + wall_count = 0; + mob_count = 0; + mission = 1; + theme = 1; + maze = true; + min_npc_spawned = false; +} + +// Generates the playing area and npc mechs +void world_generator::generate_world(assets &resources, std::vector &entities, int entity_count) +{ + int e = 0; + entities = std::vector(entity_count); + + // Border + for (int i = 0; i < 153; i++) + { + entities[e].position.x = 60; + entities[e].position.y = 40 + i * 4; + entities[e].type = "wall"; + entities[e].icon.setTexture(resources.wall_icon_texture); + e++; + } + + for (int i = 0; i < 153; i++) + { + entities[e].position.x = 550; + entities[e].position.y = 40 + i * 4; + entities[e].type = "wall"; + entities[e].icon.setTexture(resources.wall_icon_texture); + e++; + } + + for (int i = 0; i < 122; i++) + { + entities[e].position.x = 60 + i * 4; + entities[e].position.y = 40; + entities[e].type = "wall"; + entities[e].icon.setTexture(resources.wall_icon_texture); + e++; + } + + for (int i = 0; i < 122; i++) + { + entities[e].position.x = 60 + i * 4; + entities[e].position.y = 650; + entities[e].type = "wall"; + entities[e].icon.setTexture(resources.wall_icon_texture); + e++; + } + + if (maze == true) + { + // Wall + for (int i = 0; i < 60; i++) + { + entities[e].position.x = 180; + entities[e].position.y = 40 + i * 4; + entities[e].type = "wall"; + entities[e].icon.setTexture(resources.wall_icon_texture); + e++; + } + + // Wall + for (int i = 0; i < 125; i++) + { + entities[e].position.x = 300; + entities[e].position.y = 154 + i * 4; + entities[e].type = "wall"; + entities[e].icon.setTexture(resources.wall_icon_texture); + e++; + } + + // Wall + for (int i = 0; i < 120; i++) + { + entities[e].position.x = 420; + entities[e].position.y = 40 + i * 4; + entities[e].type = "wall"; + entities[e].icon.setTexture(resources.wall_icon_texture); + e++; + } + + // Wall + for (int i = 0; i < 60; i++) + { + entities[e].position.x = 60 + i * 4; + entities[e].position.y = 400; + entities[e].type = "wall"; + entities[e].icon.setTexture(resources.wall_icon_texture); + e++; + } + } + + wall_count = e; + + for (int i = wall_count; i < entity_count; i++) + { + int r = rand() % 1000; + + if (r < 1000 && r >= 950) + { + entities[e].type = "tree"; + if (maze == true) + { + entities[e].position.x = 75 + ( rand() % ( 165 - 75 + 1 ) ); + entities[e].position.y = 75 + ( rand() % ( 645 - 75 + 1 ) ); + } + else + { + entities[e].position.x = 70 + ( rand() % ( 540 - 70 + 1 ) ); + entities[e].position.y = 50 + ( rand() % ( 640 - 50 + 1 ) ); + } + + if (theme == 1) + { + entities[e].sprite.setTexture(resources.tree_texture); + } + else + { + entities[e].sprite.setTexture(resources.tree_3_texture); + } + } + else if (r < 950 && r >= 900) + { + entities[e].type = "tree"; + if (maze == true) + { + entities[e].position.x = 195 + ( rand() % ( 285 - 195 + 1 ) ); + entities[e].position.y = 75 + ( rand() % ( 645 - 75 + 1 ) ); + } + else + { + entities[e].position.x = 70 + ( rand() % ( 540 - 70 + 1 ) ); + entities[e].position.y = 50 + ( rand() % ( 640 - 50 + 1 ) ); + } + + if (theme == 1) + { + entities[e].sprite.setTexture(resources.tree_texture); + } + else + { + entities[e].sprite.setTexture(resources.tree_3_texture); + } + } + else if (r < 900 && r >= 850) + { + entities[e].type = "tree"; + if (maze == true) + { + entities[e].position.x = 315 + ( rand() % ( 405 - 315 + 1 ) ); + entities[e].position.y = 75 + ( rand() % ( 645 - 75 + 1 ) ); + } + else + { + entities[e].position.x = 70 + ( rand() % ( 540 - 70 + 1 ) ); + entities[e].position.y = 50 + ( rand() % ( 640 - 50 + 1 ) ); + } + + if (theme == 1) + { + entities[e].sprite.setTexture(resources.tree_texture); + } + else + { + entities[e].sprite.setTexture(resources.tree_3_texture); + } + } + else if (r < 850 && r >= 800) + { + entities[e].type = "tree"; + if (maze == true) + { + entities[e].position.x = 435 + ( rand() % ( 530 - 435 + 1 ) ); + entities[e].position.y = 75 + ( rand() % ( 645 - 75 + 1 ) ); + } + else + { + entities[e].position.x = 70 + ( rand() % ( 540 - 70 + 1 ) ); + entities[e].position.y = 50 + ( rand() % ( 640 - 50 + 1 ) ); + } + + if (theme == 1) + { + entities[e].sprite.setTexture(resources.tree_texture); + } + else + { + entities[e].sprite.setTexture(resources.tree_3_texture); + } + } + else if (r < 800 && r >= 750) + { + entities[e].type = "tree_2"; + if (maze == true) + { + entities[e].position.x = 75 + ( rand() % ( 175 - 75 + 1 ) ); + entities[e].position.y = 200 + ( rand() % ( 350 - 200 + 1 ) ); + } + else + { + entities[e].position.x = 70 + ( rand() % ( 540 - 70 + 1 ) ); + entities[e].position.y = 50 + ( rand() % ( 640 - 50 + 1 ) ); + } + + if (theme == 1) + { + entities[e].sprite.setTexture(resources.tree_2_texture); + } + else + { + entities[e].sprite.setTexture(resources.tree_4_texture); + } + } + else if (r < 750 && r >= 700) + { + entities[e].type = "tree_2"; + if (maze == true) + { + entities[e].position.x = 195 + ( rand() % ( 285 - 195 + 1 ) ); + entities[e].position.y = 200 + ( rand() % ( 350 - 200 + 1 ) ); + } + else + { + entities[e].position.x = 70 + ( rand() % ( 540 - 70 + 1 ) ); + entities[e].position.y = 50 + ( rand() % ( 640 - 50 + 1 ) ); + } + + if (theme == 1) + { + entities[e].sprite.setTexture(resources.tree_2_texture); + } + else + { + entities[e].sprite.setTexture(resources.tree_4_texture); + } + } + else if (r < 700 && r >= 650) + { + entities[e].type = "tree_2"; + if (maze == true) + { + entities[e].position.x = 435 + ( rand() % ( 530 - 435 + 1 ) ); + entities[e].position.y = 75 + ( rand() % ( 645 - 75 + 1 ) ); + } + else + { + entities[e].position.x = 70 + ( rand() % ( 540 - 70 + 1 ) ); + entities[e].position.y = 50 + ( rand() % ( 640 - 50 + 1 ) ); + } + + if (theme == 1) + { + entities[e].sprite.setTexture(resources.tree_2_texture); + } + else + { + entities[e].sprite.setTexture(resources.tree_4_texture); + } + } + else if (r < 650 && r >= 600) + { + entities[e].type = "tree_2"; + if (maze == true) + { + entities[e].position.x = 435 + ( rand() % ( 530 - 435 + 1 ) ); + entities[e].position.y = 75 + ( rand() % ( 645 - 75 + 1 ) ); + } + else + { + entities[e].position.x = 70 + ( rand() % ( 540 - 70 + 1 ) ); + entities[e].position.y = 50 + ( rand() % ( 640 - 50 + 1 ) ); + } + + if (theme == 1) + { + entities[e].sprite.setTexture(resources.tree_2_texture); + } + else + { + entities[e].sprite.setTexture(resources.tree_4_texture); + } + } + + int weapons_modifier = mission < 3 ? 0 : mission > 5 ? 3 : mission - 2 ; + int armor_modifier = mission < 3 ? 1000 : mission > 5 ? 3000 : (mission - 2) * 1000; + + r = std::rand() % 10000; + + if ((r < 10000 && r >= 10000 - mission * 2) || min_npc_spawned == false) + { + if (mob_count < mission) + { + entities[e].id = e; + entities[e].type = "mob"; + entities[e].sub_type = "mech"; + entities[e].sprite.setTexture(resources.mech_texture, true); + entities[e].icon.setTexture(resources.mob_icon_texture); + + int upgrade_chance = rand() % 100; + if (upgrade_chance >= 75) + { + int rand_upgrade = rand() % 100; + if (rand_upgrade >= 50) + { + entities[e].entity_mech.guns_modifier = weapons_modifier; + entities[e].entity_mech.cannons_modifier = weapons_modifier; + entities[e].entity_mech.cooler_modifier = weapons_modifier; + entities[e].entity_mech.cooler_integrity = armor_modifier; + entities[e].entity_mech.max_cooler_integrity = armor_modifier; + entities[e].entity_mech.reactor_integrity = armor_modifier; + entities[e].entity_mech.max_reactor_integrity = armor_modifier; + } + else + { + entities[e].entity_mech.reactor_integrity = armor_modifier; + entities[e].entity_mech.max_reactor_integrity = armor_modifier; + entities[e].entity_mech.cockpit_integrity = armor_modifier; + entities[e].entity_mech.max_cockpit_integrity = armor_modifier; + entities[e].entity_mech.left_arm_integrity = armor_modifier; + entities[e].entity_mech.max_left_arm_integrity = armor_modifier; + entities[e].entity_mech.right_arm_integrity = armor_modifier; + entities[e].entity_mech.max_right_arm_integrity = armor_modifier; + entities[e].entity_mech.left_leg_integrity = armor_modifier; + entities[e].entity_mech.max_left_leg_integrity = armor_modifier; + entities[e].entity_mech.right_leg_integrity = armor_modifier; + entities[e].entity_mech.max_right_leg_integrity = armor_modifier; + } + } + + if (maze == true) + { + entities[e].position.x = 75 + ( rand() % ( 175 - 75 + 1 ) ); + entities[e].position.y = 200 + ( rand() % ( 350 - 200 + 1 ) ); + } + else + { + entities[e].position.x = 70 + ( rand() % ( 540 - 70 + 1 ) ); + entities[e].position.y = 50 + ( rand() % ( 640 - 50 + 1 ) ); + } + + mob_count++; + min_npc_spawned = true; + } + } + else if (r < 10000 - mission * 2 && r >= 10000 - mission * 4 && mob_count < mission) + { + entities[e].id = e; + entities[e].type = "mob"; + entities[e].sub_type = "mech"; + entities[e].sprite.setTexture(resources.mech_texture, true); + entities[e].icon.setTexture(resources.mob_icon_texture); + + int upgrade_chance = rand() % 100; + if (upgrade_chance >= 75) + { + int rand_upgrade = rand() % 100; + if (rand_upgrade >= 50) + { + entities[e].entity_mech.guns_modifier = weapons_modifier; + entities[e].entity_mech.cannons_modifier = weapons_modifier; + entities[e].entity_mech.cooler_modifier = weapons_modifier; + entities[e].entity_mech.cooler_integrity = armor_modifier; + entities[e].entity_mech.max_cooler_integrity = armor_modifier; + entities[e].entity_mech.reactor_integrity = armor_modifier; + entities[e].entity_mech.max_reactor_integrity = armor_modifier; + } + else + { + entities[e].entity_mech.reactor_integrity = armor_modifier; + entities[e].entity_mech.max_reactor_integrity = armor_modifier; + entities[e].entity_mech.cockpit_integrity = armor_modifier; + entities[e].entity_mech.max_cockpit_integrity = armor_modifier; + entities[e].entity_mech.left_arm_integrity = armor_modifier; + entities[e].entity_mech.max_left_arm_integrity = armor_modifier; + entities[e].entity_mech.right_arm_integrity = armor_modifier; + entities[e].entity_mech.max_right_arm_integrity = armor_modifier; + entities[e].entity_mech.left_leg_integrity = armor_modifier; + entities[e].entity_mech.max_left_leg_integrity = armor_modifier; + entities[e].entity_mech.right_leg_integrity = armor_modifier; + entities[e].entity_mech.max_right_leg_integrity = armor_modifier; + } + } + + if (maze == true) + { + entities[e].position.x = 195 + ( rand() % ( 285 - 195 + 1 ) ); + entities[e].position.y = 200 + ( rand() % ( 350 - 200 + 1 ) ); + } + else + { + entities[e].position.x = 70 + ( rand() % ( 540 - 70 + 1 ) ); + entities[e].position.y = 50 + ( rand() % ( 640 - 50 + 1 ) ); + } + + mob_count++; + } + else if (r < 10000 - mission * 4 && r >= 10000 - mission * 6 && mob_count < mission) + { + entities[e].id = e; + entities[e].type = "mob"; + entities[e].sub_type = "mech"; + entities[e].sprite.setTexture(resources.mech_texture, true); + entities[e].icon.setTexture(resources.mob_icon_texture); + + int upgrade_chance = rand() % 100; + if (upgrade_chance >= 75) + { + int rand_upgrade = rand() % 100; + if (rand_upgrade >= 50) + { + entities[e].entity_mech.guns_modifier = weapons_modifier; + entities[e].entity_mech.cannons_modifier = weapons_modifier; + entities[e].entity_mech.cooler_modifier = weapons_modifier; + entities[e].entity_mech.cooler_integrity = armor_modifier; + entities[e].entity_mech.max_cooler_integrity = armor_modifier; + entities[e].entity_mech.reactor_integrity = armor_modifier; + entities[e].entity_mech.max_reactor_integrity = armor_modifier; + } + else + { + entities[e].entity_mech.reactor_integrity = armor_modifier; + entities[e].entity_mech.max_reactor_integrity = armor_modifier; + entities[e].entity_mech.cockpit_integrity = armor_modifier; + entities[e].entity_mech.max_cockpit_integrity = armor_modifier; + entities[e].entity_mech.left_arm_integrity = armor_modifier; + entities[e].entity_mech.max_left_arm_integrity = armor_modifier; + entities[e].entity_mech.right_arm_integrity = armor_modifier; + entities[e].entity_mech.max_right_arm_integrity = armor_modifier; + entities[e].entity_mech.left_leg_integrity = armor_modifier; + entities[e].entity_mech.max_left_leg_integrity = armor_modifier; + entities[e].entity_mech.right_leg_integrity = armor_modifier; + entities[e].entity_mech.max_right_leg_integrity = armor_modifier; + } + } + + if (maze == true) + { + entities[e].position.x = 315 + ( rand() % ( 405 - 315 + 1 ) ); + entities[e].position.y = 75 + ( rand() % ( 645 - 75 + 1 ) ); + } + else + { + entities[e].position.x = 70 + ( rand() % ( 540 - 70 + 1 ) ); + entities[e].position.y = 50 + ( rand() % ( 640 - 50 + 1 ) ); + } + + mob_count++; + } + else if (r < 10000 - mission * 6 && r >= 10000 - mission * 8 && mob_count < mission) + { + entities[e].id = e; + entities[e].type = "mob"; + entities[e].sub_type = "mech"; + entities[e].sprite.setTexture(resources.mech_texture, true); + entities[e].icon.setTexture(resources.mob_icon_texture); + + int upgrade_chance = rand() % 100; + if (upgrade_chance >= 75) + { + int rand_upgrade = rand() % 100; + if (rand_upgrade >= 50) + { + entities[e].entity_mech.guns_modifier = weapons_modifier; + entities[e].entity_mech.cannons_modifier = weapons_modifier; + entities[e].entity_mech.cooler_modifier = weapons_modifier; + entities[e].entity_mech.cooler_integrity = armor_modifier; + entities[e].entity_mech.max_cooler_integrity = armor_modifier; + entities[e].entity_mech.reactor_integrity = armor_modifier; + entities[e].entity_mech.max_reactor_integrity = armor_modifier; + } + else + { + entities[e].entity_mech.reactor_integrity = armor_modifier; + entities[e].entity_mech.max_reactor_integrity = armor_modifier; + entities[e].entity_mech.cockpit_integrity = armor_modifier; + entities[e].entity_mech.max_cockpit_integrity = armor_modifier; + entities[e].entity_mech.left_arm_integrity = armor_modifier; + entities[e].entity_mech.max_left_arm_integrity = armor_modifier; + entities[e].entity_mech.right_arm_integrity = armor_modifier; + entities[e].entity_mech.max_right_arm_integrity = armor_modifier; + entities[e].entity_mech.left_leg_integrity = armor_modifier; + entities[e].entity_mech.max_left_leg_integrity = armor_modifier; + entities[e].entity_mech.right_leg_integrity = armor_modifier; + entities[e].entity_mech.max_right_leg_integrity = armor_modifier; + } + } + + if (maze == true) + { + entities[e].position.x = 435 + ( rand() % ( 530 - 435 + 1 ) ); + entities[e].position.y = 75 + ( rand() % ( 645 - 75 + 1 ) ); + } + else + { + entities[e].position.x = 70 + ( rand() % ( 540 - 70 + 1 ) ); + entities[e].position.y = 50 + ( rand() % ( 640 - 50 + 1 ) ); + } + + mob_count++; + } + + e++; + } + + mob_count = 0; + min_npc_spawned = false; +} + +// Reverses placement direction of walls which don't render correctly when placed with ascending depth with respect to the camera +void world_generator::flip_walls_vertical(std::vector &entities, int entity_count, bool inverse) +{ + if (inverse == true) + { + int e = 0; + + // Border + for (int i = 0; i < 153; i++) + { + entities[e].position.x = 60; + entities[e].position.y = 648 - i * 4; + e++; + } + + for (int i = 0; i < 153; i++) + { + entities[e].position.x = 550; + entities[e].position.y = 648 - i * 4; + e++; + } + + for (int i = 0; i < 122; i++) + { + e++; + } + + for (int i = 0; i < 122; i++) + { + e++; + } + + if (maze == true) + { + // Wall + for (int i = 0; i < 60; i++) + { + entities[e].position.x = 180 ; + entities[e].position.y = 275 - i * 4; + e++; + } + + // Wall + for (int i = 0; i < 125; i++) + { + entities[e].position.x = 300; + entities[e].position.y = 650 - i * 4; + e++; + } + + // Wall + for (int i = 0; i < 120; i++) + { + entities[e].position.x = 420; + entities[e].position.y = 515 - i * 4; + e++; + } + + // Wall + for (int i = 0; i < 60; i++) + { + e++; + } + } + } + else + { + int e = 0; + + // Border + for (int i = 0; i < 153; i++) + { + entities[e].position.x = 60; + entities[e].position.y = 40 + i * 4; + e++; + } + + for (int i = 0; i < 153; i++) + { + entities[e].position.x = 550; + entities[e].position.y = 40 + i * 4; + e++; + } + + for (int i = 0; i < 122; i++) + { + e++; + } + + for (int i = 0; i < 122; i++) + { + e++; + } + + if (maze == true) + { + // Wall + for (int i = 0; i < 60; i++) + { + entities[e].position.x = 180; + entities[e].position.y = 40 + i * 4; + e++; + } + + // Wall + for (int i = 0; i < 125; i++) + { + entities[e].position.x = 300; + entities[e].position.y = 154 + i * 4; + e++; + } + + // Wall + for (int i = 0; i < 120; i++) + { + entities[e].position.x = 420; + entities[e].position.y = 40 + i * 4; + e++; + } + + // Wall + for (int i = 0; i < 60; i++) + { + e++; + } + } + } +} + +// Reverses placement direction of walls which don't render correctly when placed with ascending depth with respect to the camera +void world_generator::flip_walls_horizontal(std::vector &entities, int entity_count, bool inverse) +{ + if (inverse == true) + { + int e = 0; + + // Border + for (int i = 0; i < 153; i++) + { + e++; + } + + for (int i = 0; i < 153; i++) + { + e++; + } + + for (int i = 0; i < 122; i++) + { + entities[e].position.x = 550 - i * 4; + entities[e].position.y = 40; + e++; + } + + for (int i = 0; i < 122; i++) + { + entities[e].position.x = 550 - i * 4; + entities[e].position.y = 650; + e++; + } + + if (maze == true) + { + // Wall + for (int i = 0; i < 60; i++) + { + e++; + } + + // Wall + for (int i = 0; i < 125; i++) + { + e++; + } + + // Wall + for (int i = 0; i < 120; i++) + { + e++; + } + + // Wall + for (int i = 0; i < 60; i++) + { + entities[e].position.x = 300 - i * 4; + entities[e].position.y = 400; + e++; + } + } + } + else + { + int e = 0; + + // Border + for (int i = 0; i < 153; i++) + { + e++; + } + + for (int i = 0; i < 153; i++) + { + e++; + } + + for (int i = 0; i < 122; i++) + { + entities[e].position.x = 60 + i * 4; + entities[e].position.y = 40; + e++; + } + + for (int i = 0; i < 122; i++) + { + entities[e].position.x = 60 + i * 4; + entities[e].position.y = 650; + e++; + } + + if (maze == true) + { + // Wall + for (int i = 0; i < 60; i++) + { + e++; + } + + // Wall + for (int i = 0; i < 125; i++) + { + e++; + } + + // Wall + for (int i = 0; i < 120; i++) + { + e++; + } + + // Wall + for (int i = 0; i < 60; i++) + { + entities[e].position.x = 60 + i * 4; + entities[e].position.y = 400; + e++; + } + } + } +}