diff --git a/i-mic-fps.rb b/i-mic-fps.rb index 12359f7..63a40fc 100644 --- a/i-mic-fps.rb +++ b/i-mic-fps.rb @@ -45,6 +45,11 @@ require_relative "lib/common_methods" require_relative "lib/managers/object_manager" require_relative "lib/managers/light_manager" +require_relative "lib/states/game_state" +require_relative "lib/states/game_states/game" +require_relative "lib/states/menu" +require_relative "lib/states/menus/main_menu" + require_relative "lib/objects/text" require_relative "lib/objects/multi_line_text" require_relative "lib/objects/game_object" diff --git a/lib/common_methods.rb b/lib/common_methods.rb index 4278dfc..3f4d93e 100644 --- a/lib/common_methods.rb +++ b/lib/common_methods.rb @@ -1,12 +1,27 @@ class IMICFPS module CommonMethods - def delta_time; $window.delta_time; end + def delta_time + (Gosu.milliseconds-@delta_time)/1000.0 + end def button_down?(id); $window.button_down?(id); end def mouse_x; $window.mouse_x; end def mouse_y; $window.mouse_y; end def mouse_x=int; $window.mouse_x=int; end def mouse_y=int; $window.mouse_y=int; end + + def gl(&block) + $window.gl do + block.call + end + end + + def draw_rect(*args) + $window.draw_rect(*args) + end + def draw_quad(*args) + $window.draw_quad(*args) + end end end diff --git a/lib/objects/game_object.rb b/lib/objects/game_object.rb index e74fc45..25f989b 100644 --- a/lib/objects/game_object.rb +++ b/lib/objects/game_object.rb @@ -20,6 +20,7 @@ class IMICFPS @debug_color = Color.new(0.0, 1.0, 0.0) @terrain = terrain @width, @height, @depth = 0,0,0 + @delta_time = Gosu.milliseconds ObjectManager.add_object(self) if auto_manage setup @@ -78,6 +79,7 @@ class IMICFPS def update model.update + @delta_time = Gosu.milliseconds end # Do two Axis Aligned Bounding Boxes intersect? diff --git a/lib/objects/player.rb b/lib/objects/player.rb index 8490d97..66235dd 100644 --- a/lib/objects/player.rb +++ b/lib/objects/player.rb @@ -87,8 +87,6 @@ class IMICFPS end def update - super - @floor = @terrain.height_at(self, 4.5) relative_speed = @speed @@ -153,6 +151,8 @@ class IMICFPS # distance = 2.0 # x_offset = distance * Math.cos(@bound_model.y_rotation) # z_offset = distance * Math.sin(@bound_model.y_rotation) + + super end def button_up(id) diff --git a/lib/objects/skydome.rb b/lib/objects/skydome.rb index f7cad12..b9699e4 100644 --- a/lib/objects/skydome.rb +++ b/lib/objects/skydome.rb @@ -11,9 +11,9 @@ class IMICFPS end def update - super @y_rotation+=0.01 @y_rotation%=360 + super end end end diff --git a/lib/states/game_state.rb b/lib/states/game_state.rb new file mode 100644 index 0000000..6804913 --- /dev/null +++ b/lib/states/game_state.rb @@ -0,0 +1,22 @@ +class IMICFPS + class GameState + include CommonMethods + + def initialize + @delta_time = Gosu.milliseconds + setup + end + + def setup + end + + def draw + end + + def update + end + + def button_up(id) + end + end +end \ No newline at end of file diff --git a/lib/states/game_states/game.rb b/lib/states/game_states/game.rb new file mode 100644 index 0000000..61437e2 --- /dev/null +++ b/lib/states/game_states/game.rb @@ -0,0 +1,148 @@ +class IMICFPS + class Game < GameState + include OpenGL + include GLU + + def setup + @terrain = Terrain.new#(size: 170, height: 0) + @draw_skydome = true + @skydome = Skydome.new(scale: 0.08, backface_culling: false, auto_manage: false) + + 25.times do + Tree.new(x: rand(@terrain.width)-(@terrain.width/2.0), z: rand(@terrain.depth)-(@terrain.depth/2.0), terrain: @terrain) + end + + @player = Player.new(x: 1, y: 0, z: -1, terrain: @terrain) + @camera = Camera.new(x: 0, y: -2, z: 1) + @camera.attach_to(@player) + + @crosshair_size = 10 + @crosshair_thickness = 3 + @crosshair_color = Gosu::Color.rgb(255,127,0) + + # @font = Gosu::Font.new(18, name: "DejaVu Sans") + @text = MultiLineText.new("Pending...", x: 10, y: 10, z: 1, size: 18, font: "DejaVu Sans") + + Light.new(x: 3, y: -6, z: 6) + Light.new(x: 0, y: 100, z: 0, diffuse: Color.new(1.0, 0.5, 0.1)) + end + + def glError? + e = glGetError() + if e != GL_NO_ERROR + $stderr.puts "OpenGL error in: #{gluErrorString(e)} (#{e})\n" + exit + end + end + + def draw + glError? + + gl do + glError? + glClearColor(0,0.2,0.5,1) # skyish blue + glError? + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) # clear the screen and the depth buffer + glError? + + LightManager.lights.each(&:draw) + + @camera.draw + @skydome.draw if @skydome.renderable + glEnable(GL_DEPTH_TEST) + + ObjectManager.objects.each do |object| + object.draw if object.visible && object.renderable + end + end + + # Draw crosshair + draw_rect($window.width/2-@crosshair_size, ($window.height/2-@crosshair_size)-@crosshair_thickness/2, @crosshair_size*2, @crosshair_thickness, @crosshair_color, 0, :default) + draw_rect(($window.width/2)-@crosshair_thickness/2, $window.height/2-(@crosshair_size*2), @crosshair_thickness, @crosshair_size*2, @crosshair_color, 0, :default) + + @text.draw + end + + def update + @last_frame_time = Gosu.milliseconds + begin + string = <<-eos +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.pitch.round(2)} Yaw: #{@camera.yaw.round(2)} Roll #{@camera.roll.round(2)} +Camera X:#{@camera.x.round(2)} Y:#{@camera.y.round(2)} Z:#{@camera.z.round(2)} +#{if @camera.game_object then "Actor X:#{@camera.game_object.x.round(2)} Y:#{@camera.game_object.y.round(2)} Z:#{@camera.game_object.z.round(2)}";end} +Field Of View: #{@camera.field_of_view} +Mouse Sesitivity: #{@camera.mouse_sensitivity} +Faces: #{@number_of_faces} +Last Frame: #{delta_time*1000.0}ms (#{Gosu.fps} fps) + +Draw Skydome: #{@draw_skydome} +Debug mode: #{$debug} +eos + rescue ArgumentError + string = <<-eos +Unable to call glGetString! + +Camera pitch: #{@camera.pitch.round(2)} Yaw: #{@camera.yaw.round(2)} Roll #{@camera.roll.round(2)} +Camera X:#{@camera.x.round(2)} Y:#{@camera.y.round(2)} Z:#{@camera.z.round(2)} +#{if @camera.game_object then "Actor X:#{@camera.game_object.x.round(2)} Y:#{@camera.game_object.y.round(2)} Z:#{@camera.game_object.z.round(2)}";end} +Field Of View: #{@camera.field_of_view} +Mouse Sesitivity: #{@camera.mouse_sensitivity} +Faces: #{@number_of_faces} +Last Frame: #{delta_time*1000.0}ms (#{Gosu.fps} fps) + +Draw Skydome: #{@draw_skydome} +Debug mode: #{$debug} +eos + end + @text.text = string + + # ObjectManager.objects.each do |object| + # ObjectManager.objects.each do |b| + # next if b == object + # if object.intersect(object, b) + # # puts "#{object} is intersecting #{b}" + # end + # end + # object.update + # end + ObjectManager.objects.each(&:update) + + @skydome.update if @skydome.renderable + + @camera.update + + $window.close if $window.button_down?(Gosu::KbEscape) + @number_of_faces = 0 + @delta_time = Gosu.milliseconds + end + + def button_up(id) + ObjectManager.objects.each do |object| + object.button_up(id) if defined?(object.button_up) + end + + @camera.button_up(id) + + case id + when Gosu::KbZ + @draw_skydome = !@draw_skydome + when Gosu::KbBacktick + $debug = !$debug + end + @skydome.renderable = @draw_skydome + end + + def needs_cursor? + @needs_cursor + end + + def lose_focus + puts 'Bye' + end + end +end \ No newline at end of file diff --git a/lib/states/menu.rb b/lib/states/menu.rb new file mode 100644 index 0000000..69d8ba6 --- /dev/null +++ b/lib/states/menu.rb @@ -0,0 +1,9 @@ +class IMICFPS + class Menu < GameState + def title(text, color = Gosu::Color.rgba(127, 64, 0, 200)) + end + + def link(text, color = Gosu::Color::BLUE, &block) + end + end +end \ No newline at end of file diff --git a/lib/states/menus/main_menu.rb b/lib/states/menus/main_menu.rb new file mode 100644 index 0000000..86e8d8e --- /dev/null +++ b/lib/states/menus/main_menu.rb @@ -0,0 +1,7 @@ +class IMICFPS + class MainMenu < Menu + def setup + title "I-MIC FPS" + end + end +end \ No newline at end of file diff --git a/lib/window.rb b/lib/window.rb index 623ac7d..c56d7f1 100644 --- a/lib/window.rb +++ b/lib/window.rb @@ -1,10 +1,6 @@ class IMICFPS GRAVITY = 9.8 # m/s class Window < Gosu::Window - include OpenGL - include GLU - # include GLUT - attr_accessor :number_of_faces, :needs_cursor attr_reader :camera @@ -19,158 +15,19 @@ class IMICFPS @needs_cursor = false @number_of_faces = 0 - @delta_time = Gosu.milliseconds - - @terrain = Terrain.new#(size: 170, height: 0) - @draw_skydome = true - @skydome = Skydome.new(scale: 0.08, backface_culling: false, auto_manage: false) - - 25.times do - Tree.new(x: rand(@terrain.width)-(@terrain.width/2.0), z: rand(@terrain.depth)-(@terrain.depth/2.0), terrain: @terrain) - end - # Tree.new(x: 1, z: -5, terrain: @terrain) - # Tree.new(x: 5, z: 5, terrain: @terrain) - # TestObject.new(scale: 1) - # p ObjectManager.objects.map {|o| o.name} - # Model.new(type: :obj, file_path: "objects/tree.obj", z: -5) - # Model.new(type: :obj, file_path: "objects/tree.obj", x: -2, z: -6) - # Model.new(type: :obj, file_path: "objects/sponza.obj", scale: 1, y: -0.2) - - @player = Player.new(x: 1, y: 0, z: -1, terrain: @terrain) - @camera = Camera.new(x: 0, y: -2, z: 1) - @camera.attach_to(@player) - - @crosshair_size = 10 - @crosshair_thickness = 3 - @crosshair_color = Gosu::Color.rgb(255,127,0) - - # @font = Gosu::Font.new(18, name: "DejaVu Sans") - @text = MultiLineText.new("Pending...", x: 10, y: 10, z: 1, size: 18, font: "DejaVu Sans") - - Light.new(x: 3, y: -6, z: 6) - Light.new(x: 0, y: 100, z: 0, diffuse: Color.new(1.0, 0.5, 0.1)) - end - - def glError? - e = glGetError() - if e != GL_NO_ERROR - $stderr.puts "OpenGL error in: #{gluErrorString(e)} (#{e})\n" - exit - end + @active_state = Game.new end def draw - glError? - - gl do - glError? - glClearColor(0,0.2,0.5,1) # skyish blue - glError? - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) # clear the screen and the depth buffer - glError? - - LightManager.lights.each(&:draw) - - @camera.draw - @skydome.draw if @skydome.renderable - glEnable(GL_DEPTH_TEST) - - ObjectManager.objects.each do |object| - object.draw if object.visible && object.renderable - end - end - - # Draw crosshair - draw_rect(width/2-@crosshair_size, (height/2-@crosshair_size)-@crosshair_thickness/2, @crosshair_size*2, @crosshair_thickness, @crosshair_color, 0, :default) - draw_rect((width/2)-@crosshair_thickness/2, height/2-(@crosshair_size*2), @crosshair_thickness, @crosshair_size*2, @crosshair_color, 0, :default) - - @text.draw + @active_state.draw end def update - @last_frame_time = Gosu.milliseconds - begin - string = <<-eos -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.pitch.round(2)} Yaw: #{@camera.yaw.round(2)} Roll #{@camera.roll.round(2)} -Camera X:#{@camera.x.round(2)} Y:#{@camera.y.round(2)} Z:#{@camera.z.round(2)} -#{if @camera.game_object then "Actor X:#{@camera.game_object.x.round(2)} Y:#{@camera.game_object.y.round(2)} Z:#{@camera.game_object.z.round(2)}";end} -Field Of View: #{@camera.field_of_view} -Mouse Sesitivity: #{@camera.mouse_sensitivity} -Faces: #{@number_of_faces} -Last Frame: #{delta_time*1000.0}ms (#{Gosu.fps} fps) - -Draw Skydome: #{@draw_skydome} -Debug mode: #{$debug} -eos - rescue ArgumentError - string = <<-eos -Unable to call glGetString! - -Camera pitch: #{@camera.pitch.round(2)} Yaw: #{@camera.yaw.round(2)} Roll #{@camera.roll.round(2)} -Camera X:#{@camera.x.round(2)} Y:#{@camera.y.round(2)} Z:#{@camera.z.round(2)} -#{if @camera.game_object then "Actor X:#{@camera.game_object.x.round(2)} Y:#{@camera.game_object.y.round(2)} Z:#{@camera.game_object.z.round(2)}";end} -Field Of View: #{@camera.field_of_view} -Mouse Sesitivity: #{@camera.mouse_sensitivity} -Faces: #{@number_of_faces} -Last Frame: #{delta_time*1000.0}ms (#{Gosu.fps} fps) - -Draw Skydome: #{@draw_skydome} -Debug mode: #{$debug} -eos - end - @text.text = string - - # ObjectManager.objects.each do |object| - # ObjectManager.objects.each do |b| - # next if b == object - # if object.intersect(object, b) - # # puts "#{object} is intersecting #{b}" - # end - # end - # object.update - # end - ObjectManager.objects.each(&:update) - - @skydome.update if @skydome.renderable - - @camera.update - - $window.close if $window.button_down?(Gosu::KbEscape) - @number_of_faces = 0 - @delta_time = Gosu.milliseconds + @active_state.update end def button_up(id) - ObjectManager.objects.each do |object| - object.button_up(id) if defined?(object.button_up) - end - - @camera.button_up(id) - - case id - when Gosu::KbZ - @draw_skydome = !@draw_skydome - when Gosu::KbBacktick - $debug = !$debug - end - @skydome.renderable = @draw_skydome - end - - def needs_cursor? - @needs_cursor - end - - def lose_focus - puts 'Bye' - end - - def delta_time - (Gosu.milliseconds-@delta_time)/1000.0 + @active_state.button_up(id) end end end