From ee844f256f3d8cfd51273887ea34de7b01c0e29a Mon Sep 17 00:00:00 2001 From: Cyberarm Date: Wed, 25 Sep 2019 10:09:05 -0500 Subject: [PATCH] Renamed objects/ to game_objects/ removed redundant entities, added Map loader and test map, made LoadingState use Map for entity asset loading. --- i-mic-fps.rb | 20 ++-- lib/{objects => game_objects}/camera.rb | 24 ++-- .../entities/player.rb | 11 +- .../entities/skydome.rb | 5 +- lib/game_objects/entities/terrain.rb | 4 + lib/{objects => game_objects}/entity.rb | 17 +-- lib/{objects => game_objects}/light.rb | 0 lib/{objects => game_objects}/model_loader.rb | 0 lib/managers/collision_manager.rb | 2 +- lib/map.rb | 103 ++++++++++++++++++ lib/objects/entities/terrain.rb | 8 -- lib/objects/entities/test_object.rb | 8 -- lib/objects/entities/tree.rb | 7 -- lib/renderer/opengl_renderer.rb | 6 +- lib/states/game_states/game.rb | 27 +++-- lib/states/game_states/loading_state.rb | 14 ++- lib/ui/menus/main_menu.rb | 2 +- maps/test_map.json | 70 ++++++++++++ 18 files changed, 246 insertions(+), 82 deletions(-) rename lib/{objects => game_objects}/camera.rb (92%) rename lib/{objects => game_objects}/entities/player.rb (95%) rename lib/{objects => game_objects}/entities/skydome.rb (71%) create mode 100644 lib/game_objects/entities/terrain.rb rename lib/{objects => game_objects}/entity.rb (84%) rename lib/{objects => game_objects}/light.rb (100%) rename lib/{objects => game_objects}/model_loader.rb (100%) create mode 100644 lib/map.rb delete mode 100644 lib/objects/entities/terrain.rb delete mode 100644 lib/objects/entities/test_object.rb delete mode 100644 lib/objects/entities/tree.rb create mode 100644 maps/test_map.json diff --git a/i-mic-fps.rb b/i-mic-fps.rb index b270f74..f0bb4ce 100644 --- a/i-mic-fps.rb +++ b/i-mic-fps.rb @@ -1,6 +1,8 @@ require "fiddle" require "yaml" +require "json" require "abbrev" +require "time" require "opengl" require "glu" @@ -105,19 +107,19 @@ require_relative "lib/ui/menus/main_menu" require_relative "lib/states/game_states/game" require_relative "lib/states/game_states/loading_state" -require_relative "lib/objects/entity" -require_relative "lib/objects/model_loader" -require_relative "lib/objects/light" +require_relative "lib/game_objects/entity" +require_relative "lib/game_objects/model_loader" +require_relative "lib/game_objects/light" -require_relative "lib/objects/camera" -require_relative "lib/objects/entities/player" -require_relative "lib/objects/entities/tree" -require_relative "lib/objects/entities/skydome" -require_relative "lib/objects/entities/test_object" -require_relative "lib/objects/entities/terrain" +require_relative "lib/game_objects/camera" +require_relative "lib/game_objects/entities/player" +require_relative "lib/game_objects/entities/skydome" +require_relative "lib/game_objects/entities/terrain" require_relative "lib/wavefront/model" +require_relative "lib/map" + require_relative "lib/window" if ARGV.join.include?("--profile") diff --git a/lib/objects/camera.rb b/lib/game_objects/camera.rb similarity index 92% rename from lib/objects/camera.rb rename to lib/game_objects/camera.rb index 0774178..71e2348 100644 --- a/lib/objects/camera.rb +++ b/lib/game_objects/camera.rb @@ -4,9 +4,9 @@ class IMICFPS attr_accessor :field_of_view, :mouse_sensitivity attr_reader :entity, :position, :orientation, :mouse_captured - def initialize(x: 0, y: 0, z: 0, fov: 70.0, view_distance: 155.0) - @position = Vector.new(x,y,z) - @orientation = Vector.new(0, 0, 0) + def initialize(position:, orientation: Vector.new(0, 0, 0), fov: 70.0, view_distance: 155.0) + @position = position + @orientation = orientation @field_of_view = fov @view_distance = view_distance @constant_pitch = 20.0 @@ -54,14 +54,14 @@ class IMICFPS end end - x_offset = horizontal_distance_from_object * Math.sin(@entity.rotation.y.degrees_to_radians) - z_offset = horizontal_distance_from_object * Math.cos(@entity.rotation.y.degrees_to_radians) - # p @entity.x, @entity.z;exit + 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) + @position.x = @entity.position.x - x_offset @position.y = @entity.position.y + 2 @position.z = @entity.position.z - z_offset - @orientation.y = 180 - @entity.rotation.y + @orientation.y = 180 - @entity.orientation.y end def draw @@ -89,9 +89,13 @@ class IMICFPS @orientation.z -= Float(@true_mouse.y - self.mouse_y) / (@mouse_sensitivity * @field_of_view) * 70 @orientation.z = @orientation.z.clamp(-90.0, 90.0) - @entity.rotation.y += delta if @entity - free_move unless @entity - position_camera if @entity + if @entity + @entity.orientation.y += delta + @entity.orientation.y %= 360 + position_camera + else + free_move + end self.mouse_x = window.width / 2 if self.mouse_x <= 1 || window.mouse_x >= window.width-1 self.mouse_y = window.height / 2 if self.mouse_y <= 1 || window.mouse_y >= window.height-1 diff --git a/lib/objects/entities/player.rb b/lib/game_objects/entities/player.rb similarity index 95% rename from lib/objects/entities/player.rb rename to lib/game_objects/entities/player.rb index 22cd13e..8cf2eca 100644 --- a/lib/objects/entities/player.rb +++ b/lib/game_objects/entities/player.rb @@ -106,7 +106,7 @@ class IMICFPS end def relative_y_rotation - @rotation.y * -1 + @orientation.y * -1 end def forward @@ -130,11 +130,12 @@ class IMICFPS end def turn_left - @rotation.y += @turn_speed * delta_time + puts "CALLED" + @orientation.y += @turn_speed * delta_time end def turn_right - @rotation.y -= @turn_speed * delta_time + @orientation.y -= @turn_speed * delta_time end def jump @@ -166,8 +167,8 @@ class IMICFPS end def turn_180 - @rotation.y = @rotation.y + 180 - @rotation.y %= 360 + @orientation.y = @orientation.y + 180 + @orientation.y %= 360 end end end diff --git a/lib/objects/entities/skydome.rb b/lib/game_objects/entities/skydome.rb similarity index 71% rename from lib/objects/entities/skydome.rb rename to lib/game_objects/entities/skydome.rb index 97e249d..6e9e1b1 100644 --- a/lib/objects/entities/skydome.rb +++ b/lib/game_objects/entities/skydome.rb @@ -1,7 +1,6 @@ class IMICFPS class Skydome < Entity def setup - bind_model("base", "skydome") @collision = :none end @@ -12,8 +11,8 @@ class IMICFPS end def update - @rotation.y += 0.01 - @rotation.y %= 360 + @orientation.y += 0.01 + @orientation.y %= 360 super end end diff --git a/lib/game_objects/entities/terrain.rb b/lib/game_objects/entities/terrain.rb new file mode 100644 index 0000000..c585351 --- /dev/null +++ b/lib/game_objects/entities/terrain.rb @@ -0,0 +1,4 @@ +class IMICFPS + class Terrain < Entity + end +end diff --git a/lib/objects/entity.rb b/lib/game_objects/entity.rb similarity index 84% rename from lib/objects/entity.rb rename to lib/game_objects/entity.rb index ae37f99..9d4e576 100644 --- a/lib/objects/entity.rb +++ b/lib/game_objects/entity.rb @@ -6,17 +6,20 @@ class IMICFPS include CommonMethods attr_accessor :scale, :visible, :renderable, :backface_culling - attr_accessor :position, :rotation, :velocity + attr_accessor :position, :orientation, :velocity attr_reader :name, :debug_color, :bounding_box, :collision, :physics, :mass, :drag, :camera - def initialize(x: 0, y: 0, z: 0, bound_model: nil, scale: MODEL_METER_SCALE, backface_culling: true, auto_manage: true, manifest_file: nil) - @position = Vector.new(x, y, z) - @scale = scale - @bound_model = bound_model + def initialize(map_entity: nil, spawnpoint: nil, backface_culling: true, auto_manage: true) + @position = map_entity ? map_entity.position : spawnpoint.position + @orientation = map_entity ? map_entity.orientation : spawnpoint.position + @scale = map_entity ? map_entity.scale : 1.0 + @backface_culling = backface_culling + @bound_model = map_entity ? bind_model(map_entity.package, map_entity.model) : nil + @visible = true @renderable = true - @rotation = Vector.new(0, 0, 0) + @velocity = Vector.new(0, 0, 0) @drag = 1.0 @@ -61,7 +64,7 @@ class IMICFPS @bound_model.model.objects.each { |o| o.scale = self.scale } @bounding_box = normalize_bounding_box_with_offset - # box = normalize_bounding_box + return model end def model diff --git a/lib/objects/light.rb b/lib/game_objects/light.rb similarity index 100% rename from lib/objects/light.rb rename to lib/game_objects/light.rb diff --git a/lib/objects/model_loader.rb b/lib/game_objects/model_loader.rb similarity index 100% rename from lib/objects/model_loader.rb rename to lib/game_objects/model_loader.rb diff --git a/lib/managers/collision_manager.rb b/lib/managers/collision_manager.rb index 7dfa518..645d8cb 100644 --- a/lib/managers/collision_manager.rb +++ b/lib/managers/collision_manager.rb @@ -72,7 +72,7 @@ class IMICFPS # AABBTree on entities is relative to model origin of 0,0,0 def localize_entity_bounding_box(entity, target) - return entity.bounding_box if target.position == 0 && target.rotation == 0 + return entity.bounding_box if target.position == 0 && target.orientation == 0 # "tranform" entity bounding box into target's space local = (target.position) # needs tweaking, works well enough for now diff --git a/lib/map.rb b/lib/map.rb new file mode 100644 index 0000000..107163d --- /dev/null +++ b/lib/map.rb @@ -0,0 +1,103 @@ +class IMICFPS + class Map + attr_reader :metadata, :terrain, :skydome, :entities, :spawnpoints + attr_reader :assets, :missing_assets + def initialize(map_file:) + @metadata = Map::MetaData.new + @terrain = Map::Entity.new + @skydome = Map::Entity.new + @entities = [] + @spawnpoints = [] + + @assets = [] + @missing_assets = [] + + parse(map_file) + end + + def parse(file) + data = JSON.parse(File.read(file)) + + if section = data["metadata"] + @metadata.name = section["name"] + @metadata.gamemode = section["gamemode"] + @metadata.authors = section["authors"] + @metadata.datetime = Time.parse(section["datetime"]) + @metadata.thumbnail = section["thumbnail"] # TODO: convert thumbnail to Image + @metadata.description = section["description"] + else + raise "Map metadata is missing!" + end + + if section = data["terrain"] + @terrain.package = section["package"] + @terrain.model = section["model"] + @terrain.position = Vector.new + @terrain.orientation = Vector.new + @terrain.scale = 1.0 + @terrain.water_level = section["water_level"] + else + raise "Map terrain data is missing!" + end + + if section = data["skydome"] + @skydome.package = section["package"] + @skydome.model = section["model"] + @skydome.position = Vector.new + @skydome.orientation = Vector.new + @skydome.scale = section["scale"] ? section["scale"] : 1.0 + else + raise "Map skydome data is missing!" + end + + if section = data["entities"] + section.each do |ent| + entity = Map::Entity.new + entity.package = ent["package"] + entity.model = ent["model"] + entity.position = Vector.new( + ent["position"]["x"], + ent["position"]["y"], + ent["position"]["z"] + ) + entity.orientation = Vector.new( + ent["orientation"]["x"], + ent["orientation"]["y"], + ent["orientation"]["z"] + ) + entity.scale = ent["scale"] + entity.scripts = ent["scripts"] + + @entities << entity + end + else + raise "Map has no entities!" + end + + if section = data["spawnpoints"] + section.each do |point| + spawnpoint = SpawnPoint.new + spawnpoint.team = point["team"] + spawnpoint.position = Vector.new( + point["position"]["x"], + point["position"]["y"], + point["position"]["z"] + ) + spawnpoint.orientation = Vector.new( + point["orientation"]["x"], + point["orientation"]["y"], + point["orientation"]["z"] + ) + + @spawnpoints << spawnpoint + end + else + raise "Map has no spawnpoints!" + end + end + + MetaData = Struct.new(:name, :gamemode, :authors, :datetime, :thumbnail, :description) + Entity = Struct.new(:package, :model, :position, :orientation, :scale, :water_level, :scripts) + SpawnPoint = Struct.new(:team, :position, :orientation) + end +end \ No newline at end of file diff --git a/lib/objects/entities/terrain.rb b/lib/objects/entities/terrain.rb deleted file mode 100644 index a4dba02..0000000 --- a/lib/objects/entities/terrain.rb +++ /dev/null @@ -1,8 +0,0 @@ -class IMICFPS - class Terrain < Entity - def setup - bind_model("base", "randomish_terrain") - # bind_model("base", "river_terrain") - end - end -end diff --git a/lib/objects/entities/test_object.rb b/lib/objects/entities/test_object.rb deleted file mode 100644 index e3a5b31..0000000 --- a/lib/objects/entities/test_object.rb +++ /dev/null @@ -1,8 +0,0 @@ -class IMICFPS - class TestObject < Entity - def setup - bind_model("base", "war_factory") - @backface_culling = false - end - end -end diff --git a/lib/objects/entities/tree.rb b/lib/objects/entities/tree.rb deleted file mode 100644 index 2cd3e06..0000000 --- a/lib/objects/entities/tree.rb +++ /dev/null @@ -1,7 +0,0 @@ -class IMICFPS - class Tree < Entity - def setup - bind_model("base", "tree") - end - end -end diff --git a/lib/renderer/opengl_renderer.rb b/lib/renderer/opengl_renderer.rb index 351fa6e..70549a2 100644 --- a/lib/renderer/opengl_renderer.rb +++ b/lib/renderer/opengl_renderer.rb @@ -9,9 +9,9 @@ class IMICFPS glPushMatrix glTranslatef(object.position.x, object.position.y, object.position.z) - glRotatef(object.rotation.x, 1.0, 0, 0) - glRotatef(object.rotation.y, 0, 1.0, 0) - glRotatef(object.rotation.z, 0, 0, 1.0) + glRotatef(object.orientation.x, 1.0, 0, 0) + glRotatef(object.orientation.y, 0, 1.0, 0) + glRotatef(object.orientation.z, 0, 0, 1.0) handleGlError diff --git a/lib/states/game_states/game.rb b/lib/states/game_states/game.rb index 713925c..edfa781 100644 --- a/lib/states/game_states/game.rb +++ b/lib/states/game_states/game.rb @@ -5,27 +5,26 @@ class IMICFPS def setup @collision_manager = CollisionManager.new(game_state: self) @renderer = Renderer.new(game_state: self) - add_entity(Terrain.new) + @map = @options[:map] + add_entity(Terrain.new(map_entity: @map.terrain)) + @draw_skydome = true - @skydome = Skydome.new(scale: 0.08, backface_culling: false) + @skydome = Skydome.new(map_entity: @map.skydome, backface_culling: false) add_entity(@skydome) - 25.times do - add_entity(Tree.new) + @map.entities.each do |ent| + add_entity(Entity.new(map_entity: ent)) end - add_entity(TestObject.new(z: 10)) - - @player = Player.new(x: 1, y: 0, z: -1) + @player = Player.new(spawnpoint: @map.spawnpoints.sample) add_entity(@player) - @camera = Camera.new(x: 0, y: -2, z: 1) + @camera = Camera.new(position: @player.position.clone) @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 = Text.new("Pending...", x: 10, y: 10, z: 1, size: 18, font: "DejaVu Sans", shadow_color: Gosu::Color::BLACK) Light.new(x: 3, y: -6, z: 6, game_state: self) @@ -126,8 +125,8 @@ class IMICFPS self.button_down(key) elsif data.first == "mouse" - @camera.pitch = data[1].to_f - @player.rotation.y = (data[2].to_f * -1) - 180 + @camera.orientation.z = data[1].to_f + @player.orientation.y = (data[2].to_f * -1) - 180 else # hmm end @@ -145,9 +144,9 @@ class IMICFPS @demo_file.puts("tick #{@demo_index}") end - @demo_file.puts("mouse #{@camera.pitch} #{@camera.yaw}") - @demo_last_pitch = @camera.pitch - @demo_last_yaw = @camera.yaw + @demo_file.puts("mouse #{@camera.z} #{@camera.y}") + @demo_last_pitch = @camera.z + @demo_last_yaw = @camera.y end @demo_changed = false diff --git a/lib/states/game_states/loading_state.rb b/lib/states/game_states/loading_state.rb index 5e54072..09b7e92 100644 --- a/lib/states/game_states/loading_state.rb +++ b/lib/states/game_states/loading_state.rb @@ -1,9 +1,10 @@ class IMICFPS class LoadingState < Menu def setup + @map = Map.new(map_file: @options[:map_file]) + title "I-MIC FPS" - #@header = Text.new("I-MIC FPS", y: 10, size: 100, alignment: :center) - @subheading = Text.new("Loading Assets", y: 100, size: 50, alignment: :center) + @subheading = Text.new("Loading Map: #{@map.metadata.name}", y: 100, size: 50, alignment: :center) @state = Text.new("Preparing...", y: window.height/2-40, size: 40, alignment: :center) @percentage = Text.new("0%", y: window.height - 100 + 25, size: 50, alignment: :center) @@ -12,9 +13,10 @@ class IMICFPS @asset_index = 0 # add_asset(:shader, nil, "default") - add_asset(:model, "base", "randomish_terrain") - add_asset(:model, "base", "skydome") - add_asset(:model, "base", "tree") + @map.entities.each do |entity| + add_asset(:model, entity.package, entity.model) + end + add_asset(:model, "base", "biped") @act = false @@ -58,7 +60,7 @@ class IMICFPS unless @asset_index < @assets.count if @act && Gosu.milliseconds-@completed_for_ms > 250 - push_state(@options[:forward]) + push_state(@options[:forward], map: @map) else @act = true @completed_for_ms = Gosu.milliseconds unless @lock diff --git a/lib/ui/menus/main_menu.rb b/lib/ui/menus/main_menu.rb index 4fb942e..61dc937 100644 --- a/lib/ui/menus/main_menu.rb +++ b/lib/ui/menus/main_menu.rb @@ -3,7 +3,7 @@ class IMICFPS def setup title "I-MIC FPS" link "Single Player" do - push_state(LoadingState.new(forward: Game)) + push_state(LoadingState.new(forward: Game, map_file: GAME_ROOT_PATH + "/maps/test_map.json")) end link "Settings" do # push_game_state(SettingsMenu) diff --git a/maps/test_map.json b/maps/test_map.json new file mode 100644 index 0000000..b45785b --- /dev/null +++ b/maps/test_map.json @@ -0,0 +1,70 @@ +{ + "metadata": { + "name":"Testing Map", + "gamemode":"C&C", + "authors":["Cyberarm"], + "datetime":"2019-09-25 13:54:34 UTC", + "thumbnail":"", + "description":"A map for testing the map specification." + }, + + "terrain":{ + "package":"base", + "model":"river_terrain", + "water_level":null + }, + + "skydome":{ + "package":"base", + "model":"skydome", + "scale":0.08 + }, + + "entities":[ + { + "package":"base", + "model":"tree", + "position": { + "x":0, + "y":1, + "z":0 + }, + "orientation": { + "x": 0, + "y": 0, + "z": 0 + }, + "scale": 1.0, + "scripts": [] + } + ], + + "spawnpoints": [ + { + "team":0, + "position": { + "x": 0, + "y": 1, + "z": 0 + }, + "orientation": { + "x": 0, + "y": 0, + "z": 0 + } + }, + { + "team":1, + "position": { + "x": 0, + "y": 1, + "z": 0 + }, + "orientation": { + "x": 0, + "y": 0, + "z": 0 + } + } + ] +} \ No newline at end of file