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 "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")

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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

View File

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

View File

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

View File

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

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