mirror of
https://github.com/cyberarm/i-mic-fps.git
synced 2025-12-15 07:32:35 +00:00
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:
20
i-mic-fps.rb
20
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")
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
4
lib/game_objects/entities/terrain.rb
Normal file
4
lib/game_objects/entities/terrain.rb
Normal file
@@ -0,0 +1,4 @@
|
||||
class IMICFPS
|
||||
class Terrain < Entity
|
||||
end
|
||||
end
|
||||
@@ -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
|
||||
@@ -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
103
lib/map.rb
Normal 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
|
||||
@@ -1,8 +0,0 @@
|
||||
class IMICFPS
|
||||
class Terrain < Entity
|
||||
def setup
|
||||
bind_model("base", "randomish_terrain")
|
||||
# bind_model("base", "river_terrain")
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,8 +0,0 @@
|
||||
class IMICFPS
|
||||
class TestObject < Entity
|
||||
def setup
|
||||
bind_model("base", "war_factory")
|
||||
@backface_culling = false
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,7 +0,0 @@
|
||||
class IMICFPS
|
||||
class Tree < Entity
|
||||
def setup
|
||||
bind_model("base", "tree")
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
70
maps/test_map.json
Normal 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
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user