diff --git a/lib/camera_controller.rb b/lib/camera_controller.rb new file mode 100644 index 0000000..45af8c2 --- /dev/null +++ b/lib/camera_controller.rb @@ -0,0 +1,90 @@ +class IMICFPS + class CameraController + include CommonMethods + + def initialize(mode: :fpv, camera:, entity:) + # :fpv - First Person View + # :tpv - Third Person View + @mode = mode + @camera = camera + @entity = entity + + @distance = 4 + @origin_distance = @distance + @constant_pitch = 0 + + window.mouse_x, window.mouse_y = window.width / 2, window.height / 2 + + @true_mouse = Point.new(window.width / 2, window.height / 2) + @mouse_sensitivity = 20.0 # Less is faster, more is slower + @mouse_captured = true + @mouse_checked = 0 + end + + def distance_from_object + @distance + end + + def horizontal_distance_from_object + distance_from_object * Math.cos(@constant_pitch) + end + + def vertical_distance_from_object + distance_from_object * Math.sin(@constant_pitch) + end + + def position_camera + if defined?(@entity.first_person_view) + if @entity.first_person_view + @distance = 0 + else + @distance = @origin_distance + end + end + + x_offset = horizontal_distance_from_object * Math.sin(@entity.orientation.y.degrees_to_radians) + z_offset = horizontal_distance_from_object * Math.cos(@entity.orientation.y.degrees_to_radians) + + eye_height = @entity.bounding_box.max.y + + @camera.position.x = @entity.position.x - x_offset + @camera.position.y = @entity.position.y + eye_height + @camera.position.z = @entity.position.z - z_offset + + @camera.orientation.y = 180 - @entity.orientation.y + end + + def update + position_camera + + if @mouse_captured + delta = Float(@true_mouse.x - self.mouse_x) / (@mouse_sensitivity * @camera.field_of_view) * 70 + @camera.orientation.y -= delta + @camera.orientation.y %= 360.0 + + @camera.orientation.x -= Float(@true_mouse.y - window.mouse_y) / (@mouse_sensitivity * @camera.field_of_view) * 70 + @camera.orientation.x = @camera.orientation.x.clamp(-90.0, 90.0) + + @entity.orientation.y += delta + @entity.orientation.y %= 360.0 + + window.mouse_x = window.width / 2 if window.mouse_x <= 1 || window.mouse_x >= window.width-1 + window.mouse_y = window.height / 2 if window.mouse_y <= 1 || window.mouse_y >= window.height-1 + @true_mouse.x, @true_mouse.y = window.mouse_x, window.mouse_y + end + end + + def button_down(id) + case id + when Gosu::KB_LEFT_ALT, Gosu::KB_RIGHT_ALT + @mouse_captured = false + window.needs_cursor = true + when Gosu::MS_LEFT, Gosu::MS_MIDDLE, Gosu::MS_RIGHT + @mouse_captured = true + window.needs_cursor = false + end + end + + def button_up(id); end + end +end diff --git a/lib/hud.rb b/lib/hud.rb index 83e902a..5592e28 100644 --- a/lib/hud.rb +++ b/lib/hud.rb @@ -6,6 +6,8 @@ class IMICFPS @health = HealthWidget.new({ player: player }) @chat_history = ChatHistoryWidget.new({ player: player }) @score_board = ScoreBoardWidget.new({ player: player }) + @squad = SquadWidget.new( { player: player } ) + @crosshair = CrosshairWidget.new( { player: player } ) @hud_elements = [ @ammo, @@ -13,6 +15,9 @@ class IMICFPS @health, @chat_history, @score_board, + @squad, + + @crosshair, ] end @@ -24,4 +29,4 @@ class IMICFPS @hud_elements.each(&:update) end end -end \ No newline at end of file +end diff --git a/lib/hud/widgets/crosshair.rb b/lib/hud/widgets/crosshair.rb new file mode 100644 index 0000000..95d7cc3 --- /dev/null +++ b/lib/hud/widgets/crosshair.rb @@ -0,0 +1,36 @@ +class IMICFPS + class HUD + class CrosshairWidget < HUD::Widget + def setup + @scale = 0.75 + @color = Gosu::Color.new(0x44ffffff) + + @image = Gosu::Image.new("#{GAME_ROOT_PATH}/static/crosshairs/crosshair.png") + + @last_changed_time = Gosu.milliseconds + @change_interval = 1_500 + + @colors = [0xffffffff, 0xaaffffff, 0x88ffffff, 0x22ffffff] + end + + def draw + @image.draw( + window.width / 2 - (@image.width * @scale) / 2, + window.height / 2 - (@image.height * @scale) / 2, + 46, + @scale, + @scale, + @color + ) + end + + def update + if Gosu.milliseconds - @last_changed_time >= @change_interval + @last_changed_time = Gosu.milliseconds + + @color = @colors.sample + end + end + end + end +end diff --git a/lib/hud/widgets/radar.rb b/lib/hud/widgets/radar.rb index 4387854..a7426d0 100644 --- a/lib/hud/widgets/radar.rb +++ b/lib/hud/widgets/radar.rb @@ -7,6 +7,8 @@ class IMICFPS @radar_color = Gosu::Color.new(0x88212121) @text = Text.new("RADAR", size: 18, mode: :add, font: MONOSPACE_FONT) + @image = Gosu::Image.new("#{CYBERARM_ENGINE_ROOT_PATH}/assets/textures/default.png", retro: true) + @scale = (@size - @padding * 2.0) / @image.width end def draw @@ -21,15 +23,17 @@ class IMICFPS @size - @padding * 2, @size - @padding * 2, @radar_color ) + + @image.draw(@margin + @padding, window.height - (@size + @margin) + @padding, 46, @scale, @scale, 0x88ffffff) @text.draw end def update - @text.text = "RADAR: X #{@player.position.x.round(1)} Y #{@player.position.z.round(1)}" + @text.text = "RADAR: X #{@player.position.x.round(1)} Y #{@player.position.y.round(1)} Z #{@player.position.z.round(1)}" @text.x = @margin + @size / 2 - @text.width / 2 @text.y = window.height - (@margin + @size + @text.height) end end end -end \ No newline at end of file +end diff --git a/lib/hud/widgets/squad.rb b/lib/hud/widgets/squad.rb new file mode 100644 index 0000000..475c1d5 --- /dev/null +++ b/lib/hud/widgets/squad.rb @@ -0,0 +1,21 @@ +class IMICFPS + class HUD + class SquadWidget < HUD::Widget + def setup + @size = 288 # RADAR size + @color = Gosu::Color.new(0x8800aa00) + + @text = Text.new("MATE\nTinyTanker\nOther Player Dude\nHuman 0xdeadbeef", size: 18, mode: :add, font: MONOSPACE_FONT, color: @color) + end + + def draw + @text.draw + end + + def update + @text.x = @margin + @size + @padding + @text.y = window.height - (@margin + @text.height) + end + end + end +end diff --git a/lib/states/game_states/game.rb b/lib/states/game_states/game.rb index c684ce2..8d9e3b9 100644 --- a/lib/states/game_states/game.rb +++ b/lib/states/game_states/game.rb @@ -8,17 +8,15 @@ class IMICFPS @player = @map.find_entity_by(name: "character") @camera = PerspectiveCamera.new( position: @player.position.clone, aspect_ratio: window.aspect_ratio ) + @camera_controller = CameraController.new(mode: :first_person, camera: @camera, entity: @player) @director = Networking::Director.new @director.load_map(map_parser: @options[:map_parser]) @connection = Networking::Connection.new(address: "localhost", port: Networking::DEFAULT_SERVER_PORT) @connection.connect - @crosshair = Crosshair.new @hud = HUD.new(@player) - @text = Text.new("Pending...", x: 10, y: 22, z: 1, size: 18, font: "DejaVu Sans", shadow_color: Gosu::Color::BLACK) - if ARGV.join.include?("--playdemo") @demo = Demo.new(camera: @camera, player: @player, demo: "./demo.dat", mode: :play) if File.exist?("./demo.dat") @@ -30,9 +28,7 @@ class IMICFPS def draw @map.render(@camera) - @crosshair.draw @hud.draw - @text.draw end def update @@ -40,17 +36,12 @@ class IMICFPS control_player @hud.update + @camera_controller.update @connection.update @director.tick(window.dt) @map.update - if window.config.get(:debug_options, :stats) - @text.text = update_text - else - @text.text = "" - end - @demo.update if @demo end @@ -60,13 +51,6 @@ OpenGL Vendor: #{glGetString(GL_VENDOR)} OpenGL Renderer: #{glGetString(GL_RENDERER)} OpenGL Version: #{glGetString(GL_VERSION)} OpenGL Shader Language Version: #{glGetString(GL_SHADING_LANGUAGE_VERSION)} - -Camera Pitch: #{@camera.orientation.x.round(2)} Yaw: #{@camera.orientation.y.round(2)} Roll #{@camera.orientation.z.round(2)} -Camera X: #{@camera.position.x.round(2)} Y: #{@camera.position.y.round(2)} Z: #{@camera.position.z.round(2)} -Camera Field Of View: #{@camera.field_of_view} -Camera Mouse Sesitivity: nil - -Player X: #{@player.position.x.round(2)} Y: #{@player.position.y.round(2)} Z: #{@player.position.z.round(2)}" eos end @@ -88,6 +72,7 @@ eos return end @demo.button_down(id) if @demo + @camera_controller.button_down(id) InputMapper.keydown(id) Publisher.instance.publish(:button_down, nil, id) @@ -99,6 +84,7 @@ eos def button_up(id) @demo.button_up(id) if @demo + @camera_controller.button_up(id) InputMapper.keyup(id) Publisher.instance.publish(:button_up, nil, id) diff --git a/lib/window.rb b/lib/window.rb index e572ded..6e12689 100644 --- a/lib/window.rb +++ b/lib/window.rb @@ -64,7 +64,7 @@ class IMICFPS _canvas_size = Vector.new(self.width, self.height) if @canvas_size != _canvas_size - @renderer.canvas_size_changed + @renderer = Renderer.new#@renderer.canvas_size_changed @canvas_size = _canvas_size end end diff --git a/static/crosshairs/crosshair.png b/static/crosshairs/crosshair.png new file mode 100644 index 0000000..12f4b3d Binary files /dev/null and b/static/crosshairs/crosshair.png differ diff --git a/svg/crosshairs/crosshair.svg b/svg/crosshairs/crosshair.svg new file mode 100644 index 0000000..57c153a --- /dev/null +++ b/svg/crosshairs/crosshair.svg @@ -0,0 +1,118 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + +