diff --git a/Gemfile.lock b/Gemfile.lock index 25d5c4e..7b3d6e5 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -15,6 +15,7 @@ GEM mini_portile2 (~> 2.4.0) PLATFORMS + ruby x86_64-linux DEPENDENCIES diff --git a/i-mic-rts.rb b/i-mic-rts.rb index 14fcf45..8c8831e 100755 --- a/i-mic-rts.rb +++ b/i-mic-rts.rb @@ -26,6 +26,7 @@ require_relative "lib/states/closing" require_relative "lib/states/menus/main_menu" require_relative "lib/states/menus/credits_menu" require_relative "lib/states/menus/settings_menu" +require_relative "lib/states/menus/pause_menu" require_relative "lib/states/menus/solo_play_menu" require_relative "lib/states/menus/multiplayer_menu" require_relative "lib/states/menus/solo_lobby_menu" diff --git a/lib/components/spawner.rb b/lib/components/spawner.rb index c6d3a4c..9eb4ee0 100644 --- a/lib/components/spawner.rb +++ b/lib/components/spawner.rb @@ -5,15 +5,12 @@ class IMICRTS return unless item - item.progress += 1 + item.progress += 1 if @parent.component(:building).construction_complete? - if item.progress >= item.entity.build_steps - unless item.completed - item.completed = true + return unless item.progress >= item.entity.build_steps && !item.completed - @parent.director.schedule_order(IMICRTS::Order::BUILD_UNIT_COMPLETE, @parent.player.id, @parent.id) - end - end + item.completed = true + @parent.director.schedule_order(IMICRTS::Order::BUILD_UNIT_COMPLETE, @parent.player.id, @parent.id) end end end \ No newline at end of file diff --git a/lib/director.rb b/lib/director.rb index 9de68c3..4a562a8 100644 --- a/lib/director.rb +++ b/lib/director.rb @@ -2,19 +2,24 @@ class IMICRTS class Director attr_reader :current_tick, :map, :game, :players - def initialize(game:, map:, players: [], networking_mode:, tick_rate: 10) + def initialize(game:, map:, players: [], networking_mode:, tick_rate: 10, local_game: true) @game = game @map = map @players = players @connection = IMICRTS::Connection.new(director: self, mode: networking_mode) @networking_mode = networking_mode @tick_rate = tick_rate + @local_game = local_game @last_tick_at = Gosu.milliseconds @tick_time = 1000.0 / @tick_rate @current_tick = 0 end + def local_game? + @local_game + end + def add_player(player) @players << player end @@ -145,7 +150,8 @@ class IMICRTS end def finalize - @connection.finalize + @server&.stop + @connection&.finalize end end end diff --git a/lib/setting.rb b/lib/setting.rb index c3a60db..3e71e7d 100644 --- a/lib/setting.rb +++ b/lib/setting.rb @@ -12,6 +12,8 @@ class IMICRTS def self.save_defaults hash = { player_name: "Rookie", + player_color: :orange, + player_team: 1, player_default_map_spawn: 0, default_map: "test_map", @@ -43,7 +45,7 @@ class IMICRTS end def self.save! - File.open(Setting.file_path, "w") {|f| f.write(JSON.dump(@store))} + File.open(Setting.file_path, "w") { |f| f.write(JSON.dump(@store)) } end end end \ No newline at end of file diff --git a/lib/states/game.rb b/lib/states/game.rb index a63f0c2..563589e 100644 --- a/lib/states/game.rb +++ b/lib/states/game.rb @@ -2,17 +2,31 @@ class IMICRTS class Game < CyberarmEngine::GuiState Overlay = Struct.new(:image, :position, :angle, :alpha) - attr_reader :sidebar, :sidebar_actions, :overlays + attr_reader :sidebar, :sidebar_actions, :overlays, :director attr_accessor :selected_entities + def setup window.show_cursor = true - @options[:networking_mode] ||= :host + @options[:networking_mode] ||= :virtual + @options[:map] ||= Map.new(map_file: "maps/test_map.tmx") + @options[:local_player_id] ||= 0 - @director = Director.new(game: self, map: Map.new(map_file: "maps/test_map.tmx"), networking_mode: @options[:networking_mode]) - @player = Player.new(id: 0, spawnpoint: @director.map.spawnpoints.last) - @player2 = Player.new(id: 1, spawnpoint: @director.map.spawnpoints.first) - @director.add_player(@player) - @director.add_player(@player2) + @director = Director.new(game: self, map: @options[:map], networking_mode: @options[:networking_mode]) + @options[:players] ||= [ + { id: 0, team: 1, spawnpoint: @director.map.spawnpoints.last, color: :orange }, + { id: 1, team: 2, spawnpoint: @director.map.spawnpoints.first, color: :lightblue } + ] + + @options[:players].each do |pl| + player = Player.new(id: pl[:id], spawnpoint: pl[:spawnpoint], team: pl[:team], color: TeamColors[pl[:color]]) + @player = player if player.id == @options[:local_player_id] + @director.add_player(player) + end + + # @player = Player.new(id: 0, spawnpoint: @director.map.spawnpoints.last) + # @player2 = Player.new(id: 1, spawnpoint: @director.map.spawnpoints.first) + # @director.add_player(@player) + # @director.add_player(@player2) @selected_entities = [] @tool = set_tool(:entity_controller) @@ -20,7 +34,7 @@ class IMICRTS @debug_info = CyberarmEngine::Text.new("", y: 10, z: Float::INFINITY, shadow_color: Gosu::Color.rgba(0, 0, 0, 200)) - @sidebar = stack(height: 1.0) do + @sidebar = stack(width: 350, height: 1.0) do background [0x55555555, 0x55666666] label "SIDEBAR", text_size: 78, margin_bottom: 20 @@ -115,6 +129,8 @@ class IMICRTS @tool.button_down(id) if @tool @player.camera.button_down(id) unless @sidebar.hit?(window.mouse_x, window.mouse_y) + + push_state(PauseMenu) if id == Gosu::KB_ESCAPE end def button_up(id) diff --git a/lib/states/menus/credits_menu.rb b/lib/states/menus/credits_menu.rb index 278bbb3..fd53a7d 100644 --- a/lib/states/menus/credits_menu.rb +++ b/lib/states/menus/credits_menu.rb @@ -3,11 +3,11 @@ class IMICRTS def setup background [0xff7b6ead, 0xff7a0d71, 0xff7a0d71, 0xff7b6ead] - stack(height: 1.0) do + stack(width: 600, height: 1.0) do background [0xff555555, Gosu::Color::GRAY] label "About I-MIC-RTS", text_size: 78, margin: 20 - label "Words go here.\nMore words also go here. Thank you and have a nice day." + label "Words go here. More words also go here. Thank you and have a nice day.", text_wrap: :word_wrap button("Back", width: 1.0, margin_top: 20) do push_state(MainMenu) diff --git a/lib/states/menus/main_menu.rb b/lib/states/menus/main_menu.rb index 829e77c..8d17ad7 100644 --- a/lib/states/menus/main_menu.rb +++ b/lib/states/menus/main_menu.rb @@ -5,10 +5,13 @@ class IMICRTS background [0xff7b6ead, 0xff7a0d71, 0xff7a0d71, 0xff7b6ead] - stack(height: 1.0) do + stack(width: 350, height: 1.0) do background [0xff555555, Gosu::Color::GRAY] label "I-MIC-RTS", text_size: 78, margin: 20 - button("Solo Play", width: 1.0) do + button("Campaign", width: 1.0) do + end + + button("Skirmish", width: 1.0) do # push_state(SoloPlayMenu) push_state(SoloLobbyMenu) end diff --git a/lib/states/menus/multiplayer_menu.rb b/lib/states/menus/multiplayer_menu.rb index 15e7e84..9c8da0a 100644 --- a/lib/states/menus/multiplayer_menu.rb +++ b/lib/states/menus/multiplayer_menu.rb @@ -14,8 +14,12 @@ class IMICRTS button("Refresh") do refresh_games end - button("Host Game") - button("Join Game") + button("Host Game") do + push_state(HostMultiplayerGameMenu) + end + button("Join Game") do + push_state(MultiplayerLobbyMenu) + end end button("Back", width: 1.0, margin_top: 20) do diff --git a/lib/states/menus/pause_menu.rb b/lib/states/menus/pause_menu.rb new file mode 100644 index 0000000..5238a06 --- /dev/null +++ b/lib/states/menus/pause_menu.rb @@ -0,0 +1,39 @@ +class IMICRTS + class PauseMenu < CyberarmEngine::GuiState + def setup + stack(width: 350) do + button "Resume", width: 1.0 do + pop_state + end + button "Settings", width: 1.0 do + push_state(SettingsMenu) + end + button "Quit", width: 1.0 do + # TODO: Confirm + + previous_state.director.finalize + + if previous_state&.director.local_game? + push_state(SoloLobbyMenu) + else + push_state(MultiplayerLobbyMenu) + end + end + end + end + + def draw + previous_state&.draw + + # Gosu.flush + + super + end + + def update + super + + previous_state&.director.update unless previous_state&.director.local_game? + end + end +end \ No newline at end of file diff --git a/lib/states/menus/settings_menu.rb b/lib/states/menus/settings_menu.rb index 093d0e0..2cffba2 100644 --- a/lib/states/menus/settings_menu.rb +++ b/lib/states/menus/settings_menu.rb @@ -3,7 +3,7 @@ class IMICRTS def setup background [0xff7b6ead, 0xff7a0d71, 0xff7a0d71, 0xff7b6ead] - stack(height: 1.0) do + stack(width: 350, height: 1.0) do background [0xff555555, Gosu::Color::GRAY] label "Settings", text_size: 78, margin: 20 @@ -24,12 +24,12 @@ class IMICRTS if valid_options? save_settings - push_state(MainMenu) + pop_state end end button("Back", width: 1.0, margin_top: 20) do - push_state(MainMenu) + pop_state end end end diff --git a/lib/states/menus/solo_lobby_menu.rb b/lib/states/menus/solo_lobby_menu.rb index 862a7ae..17f5e5e 100644 --- a/lib/states/menus/solo_lobby_menu.rb +++ b/lib/states/menus/solo_lobby_menu.rb @@ -3,40 +3,67 @@ class IMICRTS def setup background [0xff7b6ead, 0xff7a0d71, 0xff7a0d71, 0xff7b6ead] - stack(height: 1.0) do + stack(width: 0.5, min_width: 720, height: 1.0) do background [0xff555555, Gosu::Color::GRAY] label "Lobby", text_size: 78, margin: 20 - stack do - flow do + flow(width: 1.0, height: 0.8) do + flow(width: 0.70, height: 1.0) do + stack(width: 0.40) do + label "Name" + @player_name = edit_line Setting.get(:player_name), width: 1.0 - elements = [:edit_line, :button, :button, :toggle_button] - ["Players", "Color", "Team", "Map Preview"].each_with_index do |item, index| - stack do - label item, background: 0xff7a0d71 + 7.times do |i| + list_box items: [:open, :closed, :easy, :hard, :brutal], width: 1.0 + end + end - stack do - case elements[index] - when :edit_line - @player_name = edit_line Setting.get(:player_name) - when :button - button item - when :toggle_button - toggle_button - end + stack(width: 0.29) do + label "Color" + @player_color = list_box items: TeamColors.keys, choose: Setting.get(:player_color).to_sym, width: 1.0 + @player_color.style.background = (TeamColors[@player_color.value.to_sym]) + @player_color.subscribe(:changed) do |sender, value| + @player_color.style.background = TeamColors[value.to_sym] + :handled + end + + 7.times do |i| + box = list_box items: TeamColors.keys, choose: TeamColors.keys[i + 1], width: 1.0 + box.style.background = (TeamColors[box.value.to_sym]) + box.subscribe(:changed) do |sender, value| + box.style.background = TeamColors[value.to_sym] + :handled end end end + + stack(width: 0.29) do + label "Team" + @player_team = list_box items: Array(1..8), choose: Setting.get(:player_team), width: 1.0 + + 7.times do |i| + list_box items: Array(1..8), choose: i + 2, width: 1.0 + end + end end - stack(height: 100) do + stack(width: 0.30, height: 1.0) do + # TODO: Show preview image + label "Map" + @map_name = list_box items: [:test_map], choose: :test_map, width: 1.0 + image "#{GAME_ROOT_PATH}/assets/logo.png", width: 1.0 end end - flow(width: 1.0) do - button("Accept", width: 0.5) do + flow(width: 1.0, height: 0.2) do + button("Accept") do save_playerdata - push_state(Game, networking_mode: :virtual) + map = Map.new(map_file: "maps/#{@map_name.value}.tmx") + players = [ + { id: 0, team: @player_team.value.to_i, spawnpoint: map.spawnpoints.last, color: @player_color.value.to_sym }, + { id: 1, team: 2, spawnpoint: map.spawnpoints.first, color: :lightblue } + ] + push_state(Game, networking_mode: :virtual, map: map, players: players) end button("Back", align: :right) do @@ -49,6 +76,8 @@ class IMICRTS def save_playerdata Setting.set(:player_name, @player_name.value) + Setting.set(:player_color, @player_color.value.to_sym) + Setting.set(:player_team, @player_team.value.to_i) Setting.save! end diff --git a/lib/window.rb b/lib/window.rb index cadd048..21faeeb 100644 --- a/lib/window.rb +++ b/lib/window.rb @@ -51,12 +51,5 @@ class IMICRTS def dt delta_time / 1000.0 end - - # Override CyberarmEngine::Window#push_state to only ever have 1 state - def push_state(*args) - @states.clear - - super(*args) - end end end