Renamed objects/ to game_objects/ removed redundant entities, added Map loader and test map, made LoadingState use Map for entity asset loading.

This commit is contained in:
2019-09-25 10:09:05 -05:00
parent 42191729ae
commit ee844f256f
18 changed files with 246 additions and 82 deletions

View File

@@ -1,6 +1,8 @@
require "fiddle" require "fiddle"
require "yaml" require "yaml"
require "json"
require "abbrev" require "abbrev"
require "time"
require "opengl" require "opengl"
require "glu" 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/game"
require_relative "lib/states/game_states/loading_state" require_relative "lib/states/game_states/loading_state"
require_relative "lib/objects/entity" require_relative "lib/game_objects/entity"
require_relative "lib/objects/model_loader" require_relative "lib/game_objects/model_loader"
require_relative "lib/objects/light" require_relative "lib/game_objects/light"
require_relative "lib/objects/camera" require_relative "lib/game_objects/camera"
require_relative "lib/objects/entities/player" require_relative "lib/game_objects/entities/player"
require_relative "lib/objects/entities/tree" require_relative "lib/game_objects/entities/skydome"
require_relative "lib/objects/entities/skydome" require_relative "lib/game_objects/entities/terrain"
require_relative "lib/objects/entities/test_object"
require_relative "lib/objects/entities/terrain"
require_relative "lib/wavefront/model" require_relative "lib/wavefront/model"
require_relative "lib/map"
require_relative "lib/window" require_relative "lib/window"
if ARGV.join.include?("--profile") if ARGV.join.include?("--profile")

View File

@@ -4,9 +4,9 @@ class IMICFPS
attr_accessor :field_of_view, :mouse_sensitivity attr_accessor :field_of_view, :mouse_sensitivity
attr_reader :entity, :position, :orientation, :mouse_captured attr_reader :entity, :position, :orientation, :mouse_captured
def initialize(x: 0, y: 0, z: 0, fov: 70.0, view_distance: 155.0) def initialize(position:, orientation: Vector.new(0, 0, 0), fov: 70.0, view_distance: 155.0)
@position = Vector.new(x,y,z) @position = position
@orientation = Vector.new(0, 0, 0) @orientation = orientation
@field_of_view = fov @field_of_view = fov
@view_distance = view_distance @view_distance = view_distance
@constant_pitch = 20.0 @constant_pitch = 20.0
@@ -54,14 +54,14 @@ class IMICFPS
end end
end end
x_offset = horizontal_distance_from_object * Math.sin(@entity.rotation.y.degrees_to_radians) x_offset = horizontal_distance_from_object * Math.sin(@entity.orientation.y.degrees_to_radians)
z_offset = horizontal_distance_from_object * Math.cos(@entity.rotation.y.degrees_to_radians) z_offset = horizontal_distance_from_object * Math.cos(@entity.orientation.y.degrees_to_radians)
# p @entity.x, @entity.z;exit
@position.x = @entity.position.x - x_offset @position.x = @entity.position.x - x_offset
@position.y = @entity.position.y + 2 @position.y = @entity.position.y + 2
@position.z = @entity.position.z - z_offset @position.z = @entity.position.z - z_offset
@orientation.y = 180 - @entity.rotation.y @orientation.y = 180 - @entity.orientation.y
end end
def draw 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 -= Float(@true_mouse.y - self.mouse_y) / (@mouse_sensitivity * @field_of_view) * 70
@orientation.z = @orientation.z.clamp(-90.0, 90.0) @orientation.z = @orientation.z.clamp(-90.0, 90.0)
@entity.rotation.y += delta if @entity if @entity
free_move unless @entity @entity.orientation.y += delta
position_camera if @entity @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_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 self.mouse_y = window.height / 2 if self.mouse_y <= 1 || window.mouse_y >= window.height-1

View File

@@ -106,7 +106,7 @@ class IMICFPS
end end
def relative_y_rotation def relative_y_rotation
@rotation.y * -1 @orientation.y * -1
end end
def forward def forward
@@ -130,11 +130,12 @@ class IMICFPS
end end
def turn_left def turn_left
@rotation.y += @turn_speed * delta_time puts "CALLED"
@orientation.y += @turn_speed * delta_time
end end
def turn_right def turn_right
@rotation.y -= @turn_speed * delta_time @orientation.y -= @turn_speed * delta_time
end end
def jump def jump
@@ -166,8 +167,8 @@ class IMICFPS
end end
def turn_180 def turn_180
@rotation.y = @rotation.y + 180 @orientation.y = @orientation.y + 180
@rotation.y %= 360 @orientation.y %= 360
end end
end end
end end

View File

@@ -1,7 +1,6 @@
class IMICFPS class IMICFPS
class Skydome < Entity class Skydome < Entity
def setup def setup
bind_model("base", "skydome")
@collision = :none @collision = :none
end end
@@ -12,8 +11,8 @@ class IMICFPS
end end
def update def update
@rotation.y += 0.01 @orientation.y += 0.01
@rotation.y %= 360 @orientation.y %= 360
super super
end end
end end

View File

@@ -0,0 +1,4 @@
class IMICFPS
class Terrain < Entity
end
end

View File

@@ -6,17 +6,20 @@ class IMICFPS
include CommonMethods include CommonMethods
attr_accessor :scale, :visible, :renderable, :backface_culling 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 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) def initialize(map_entity: nil, spawnpoint: nil, backface_culling: true, auto_manage: true)
@position = Vector.new(x, y, z) @position = map_entity ? map_entity.position : spawnpoint.position
@scale = scale @orientation = map_entity ? map_entity.orientation : spawnpoint.position
@bound_model = bound_model @scale = map_entity ? map_entity.scale : 1.0
@backface_culling = backface_culling @backface_culling = backface_culling
@bound_model = map_entity ? bind_model(map_entity.package, map_entity.model) : nil
@visible = true @visible = true
@renderable = true @renderable = true
@rotation = Vector.new(0, 0, 0)
@velocity = Vector.new(0, 0, 0) @velocity = Vector.new(0, 0, 0)
@drag = 1.0 @drag = 1.0
@@ -61,7 +64,7 @@ class IMICFPS
@bound_model.model.objects.each { |o| o.scale = self.scale } @bound_model.model.objects.each { |o| o.scale = self.scale }
@bounding_box = normalize_bounding_box_with_offset @bounding_box = normalize_bounding_box_with_offset
# box = normalize_bounding_box return model
end end
def model def model

View File

@@ -72,7 +72,7 @@ class IMICFPS
# AABBTree on entities is relative to model origin of 0,0,0 # AABBTree on entities is relative to model origin of 0,0,0
def localize_entity_bounding_box(entity, target) 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 # "tranform" entity bounding box into target's space
local = (target.position) # needs tweaking, works well enough for now local = (target.position) # needs tweaking, works well enough for now

103
lib/map.rb Normal file
View File

@@ -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

View File

@@ -1,8 +0,0 @@
class IMICFPS
class Terrain < Entity
def setup
bind_model("base", "randomish_terrain")
# bind_model("base", "river_terrain")
end
end
end

View File

@@ -1,8 +0,0 @@
class IMICFPS
class TestObject < Entity
def setup
bind_model("base", "war_factory")
@backface_culling = false
end
end
end

View File

@@ -1,7 +0,0 @@
class IMICFPS
class Tree < Entity
def setup
bind_model("base", "tree")
end
end
end

View File

@@ -9,9 +9,9 @@ class IMICFPS
glPushMatrix glPushMatrix
glTranslatef(object.position.x, object.position.y, object.position.z) glTranslatef(object.position.x, object.position.y, object.position.z)
glRotatef(object.rotation.x, 1.0, 0, 0) glRotatef(object.orientation.x, 1.0, 0, 0)
glRotatef(object.rotation.y, 0, 1.0, 0) glRotatef(object.orientation.y, 0, 1.0, 0)
glRotatef(object.rotation.z, 0, 0, 1.0) glRotatef(object.orientation.z, 0, 0, 1.0)
handleGlError handleGlError

View File

@@ -5,27 +5,26 @@ class IMICFPS
def setup def setup
@collision_manager = CollisionManager.new(game_state: self) @collision_manager = CollisionManager.new(game_state: self)
@renderer = Renderer.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 @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) add_entity(@skydome)
25.times do @map.entities.each do |ent|
add_entity(Tree.new) add_entity(Entity.new(map_entity: ent))
end end
add_entity(TestObject.new(z: 10)) @player = Player.new(spawnpoint: @map.spawnpoints.sample)
@player = Player.new(x: 1, y: 0, z: -1)
add_entity(@player) add_entity(@player)
@camera = Camera.new(x: 0, y: -2, z: 1) @camera = Camera.new(position: @player.position.clone)
@camera.attach_to(@player) @camera.attach_to(@player)
@crosshair_size = 10 @crosshair_size = 10
@crosshair_thickness = 3 @crosshair_thickness = 3
@crosshair_color = Gosu::Color.rgb(255,127,0) @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) @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) Light.new(x: 3, y: -6, z: 6, game_state: self)
@@ -126,8 +125,8 @@ class IMICFPS
self.button_down(key) self.button_down(key)
elsif data.first == "mouse" elsif data.first == "mouse"
@camera.pitch = data[1].to_f @camera.orientation.z = data[1].to_f
@player.rotation.y = (data[2].to_f * -1) - 180 @player.orientation.y = (data[2].to_f * -1) - 180
else else
# hmm # hmm
end end
@@ -145,9 +144,9 @@ class IMICFPS
@demo_file.puts("tick #{@demo_index}") @demo_file.puts("tick #{@demo_index}")
end end
@demo_file.puts("mouse #{@camera.pitch} #{@camera.yaw}") @demo_file.puts("mouse #{@camera.z} #{@camera.y}")
@demo_last_pitch = @camera.pitch @demo_last_pitch = @camera.z
@demo_last_yaw = @camera.yaw @demo_last_yaw = @camera.y
end end
@demo_changed = false @demo_changed = false

View File

@@ -1,9 +1,10 @@
class IMICFPS class IMICFPS
class LoadingState < Menu class LoadingState < Menu
def setup def setup
@map = Map.new(map_file: @options[:map_file])
title "I-MIC FPS" title "I-MIC FPS"
#@header = Text.new("I-MIC FPS", y: 10, size: 100, alignment: :center) @subheading = Text.new("Loading Map: #{@map.metadata.name}", y: 100, size: 50, alignment: :center)
@subheading = Text.new("Loading Assets", y: 100, size: 50, alignment: :center)
@state = Text.new("Preparing...", y: window.height/2-40, size: 40, 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) @percentage = Text.new("0%", y: window.height - 100 + 25, size: 50, alignment: :center)
@@ -12,9 +13,10 @@ class IMICFPS
@asset_index = 0 @asset_index = 0
# add_asset(:shader, nil, "default") # add_asset(:shader, nil, "default")
add_asset(:model, "base", "randomish_terrain") @map.entities.each do |entity|
add_asset(:model, "base", "skydome") add_asset(:model, entity.package, entity.model)
add_asset(:model, "base", "tree") end
add_asset(:model, "base", "biped") add_asset(:model, "base", "biped")
@act = false @act = false
@@ -58,7 +60,7 @@ class IMICFPS
unless @asset_index < @assets.count unless @asset_index < @assets.count
if @act && Gosu.milliseconds-@completed_for_ms > 250 if @act && Gosu.milliseconds-@completed_for_ms > 250
push_state(@options[:forward]) push_state(@options[:forward], map: @map)
else else
@act = true @act = true
@completed_for_ms = Gosu.milliseconds unless @lock @completed_for_ms = Gosu.milliseconds unless @lock

View File

@@ -3,7 +3,7 @@ class IMICFPS
def setup def setup
title "I-MIC FPS" title "I-MIC FPS"
link "Single Player" do 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 end
link "Settings" do link "Settings" do
# push_game_state(SettingsMenu) # push_game_state(SettingsMenu)

70
maps/test_map.json Normal file
View File

@@ -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
}
}
]
}