mirror of
https://github.com/cyberarm/i-mic-rts.git
synced 2025-12-15 15:52:34 +00:00
TileMap parser can now load spawn locations, added construction yard building, added particle emitters, added smoke sprite and svg.
This commit is contained in:
34
lib/entities/buildings/construction_yard.rb
Normal file
34
lib/entities/buildings/construction_yard.rb
Normal file
@@ -0,0 +1,34 @@
|
||||
IMICRTS::Entity.define_entity(:construction_yard, :building, 2_000, "Provides radar and builds construction workers") do |entity|
|
||||
entity.radius = 40
|
||||
entity.max_health = 100.0
|
||||
|
||||
entity.body_image = "buildings/construction_yard/construction_yard.png"
|
||||
entity.shell_image = "buildings/construction_yard/construction_yard_shell.png"
|
||||
entity.overlay_image = "buildings/construction_yard/construction_yard_overlay.png"
|
||||
|
||||
position = entity.position.clone
|
||||
position.z = IMICRTS::ZOrder::OVERLAY
|
||||
emitters = []
|
||||
|
||||
p1 = position.clone
|
||||
p1.x -= 25
|
||||
p1.y -= 8
|
||||
p2 = p1.clone
|
||||
p2.y += 25
|
||||
|
||||
p3 = position.clone
|
||||
p3.x += 8
|
||||
p3.y -= 15
|
||||
p4 = p3.clone
|
||||
p4.x += 21
|
||||
|
||||
emitters.push(p1, p2, p3, p4)
|
||||
|
||||
|
||||
emitters.each do |pos|
|
||||
entity.particle_emitters << IMICRTS::SmokeEmitter.new(position: pos)
|
||||
end
|
||||
|
||||
entity.on_tick do
|
||||
end
|
||||
end
|
||||
@@ -18,7 +18,7 @@ class IMICRTS
|
||||
attr_reader :player, :id, :name, :type, :speed
|
||||
attr_accessor :position, :angle, :radius, :target, :state,
|
||||
:movement, :health, :max_health,
|
||||
:turret, :center
|
||||
:turret, :center, :particle_emitters
|
||||
def initialize(name:, player:, id:, position:, angle:, director:)
|
||||
@player = player
|
||||
@id = id
|
||||
@@ -27,10 +27,13 @@ class IMICRTS
|
||||
@director = director
|
||||
@speed = 0.5
|
||||
|
||||
@radius = 32 / 2
|
||||
@sight_radius = 5 # tiles
|
||||
@range_radius = 3 # tiles
|
||||
@radius = 32 / 2 # pixels
|
||||
@target = nil
|
||||
@state = :idle
|
||||
@center = CyberarmEngine::Vector.new(0.5, 0.5)
|
||||
@particle_emitters = []
|
||||
|
||||
@components = {}
|
||||
|
||||
@@ -101,7 +104,7 @@ class IMICRTS
|
||||
end
|
||||
|
||||
def render
|
||||
@render = Gosu.render(32, 32, retro: true) do
|
||||
@render = Gosu.render(@shell_image.width, @shell_image.height, retro: true) do
|
||||
@body_image.draw(0, 0, 0) if @body_image
|
||||
@shell_image.draw(0, 0, 0, 1, 1, @player.color)
|
||||
@overlay_image.draw(0, 0, 0) if @overlay_image
|
||||
@@ -113,6 +116,7 @@ class IMICRTS
|
||||
@render.draw_rot(@position.x, @position.y, @position.z, @angle, @center.x, @center.y)
|
||||
|
||||
component(:turret).draw if component(:turret)
|
||||
@particle_emitters.each(&:draw)
|
||||
end
|
||||
|
||||
def update
|
||||
@@ -123,6 +127,11 @@ class IMICRTS
|
||||
|
||||
component(:movement).follow_path
|
||||
end
|
||||
|
||||
@particle_emitters.each do |emitter|
|
||||
@particle_emitters.delete(emitter) if emitter.die?
|
||||
emitter.update
|
||||
end
|
||||
end
|
||||
|
||||
def tick(tick_id)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
class IMICRTS
|
||||
class Map
|
||||
attr_reader :tile_size, :tiles, :ores, :width, :height
|
||||
attr_reader :tile_size, :tiles, :ores, :spawnpoints, :width, :height
|
||||
def initialize(map_file:)
|
||||
@tiled_map = TiledMap.new(map_file)
|
||||
|
||||
@@ -9,6 +9,7 @@ class IMICRTS
|
||||
|
||||
@tiles = {}
|
||||
@ores = {}
|
||||
@spawnpoints = @tiled_map.spawnpoints.freeze
|
||||
|
||||
@tiled_map.layers.each do |layer|
|
||||
layer.height.times do |y|
|
||||
|
||||
93
lib/particle_emitter.rb
Normal file
93
lib/particle_emitter.rb
Normal file
@@ -0,0 +1,93 @@
|
||||
class IMICRTS
|
||||
class ParticleEmitter
|
||||
def initialize(position:, direction: CyberarmEngine::Vector.up, time_to_live: 1000, particle_time_to_live: 500, speed: 10.0, max_particles: 128, frequency: 10.0, images: [], color: Gosu::Color::WHITE.dup, jitter: 10.0)
|
||||
@position = position
|
||||
@direction = direction
|
||||
@time_to_live = time_to_live
|
||||
@particle_time_to_live = particle_time_to_live
|
||||
@speed = speed
|
||||
@max_particles = max_particles
|
||||
@frequency = frequency
|
||||
@images = images
|
||||
@color = color
|
||||
@jitter = jitter
|
||||
|
||||
@born_at = Gosu.milliseconds
|
||||
@last_emitted_at = 0
|
||||
@particles = []
|
||||
@factor = CyberarmEngine::Vector.new(1.0 ,1.0)
|
||||
|
||||
setup
|
||||
end
|
||||
|
||||
def setup
|
||||
end
|
||||
|
||||
def emit
|
||||
dir = @direction.clone
|
||||
dir.x = rand(-@jitter.to_f..@jitter.to_f) * 1
|
||||
dir.normalized
|
||||
|
||||
@particles << Particle.new(
|
||||
position: @position, direction: dir,
|
||||
factor: @factor.clone, angle: rand(360.0),
|
||||
speed: @speed, time_to_live: @particle_time_to_live, image: @images.sample,
|
||||
color: @color.dup
|
||||
)
|
||||
|
||||
@last_emitted_at = Gosu.milliseconds
|
||||
end
|
||||
|
||||
def draw
|
||||
@particles.each(&:draw)
|
||||
end
|
||||
|
||||
def update
|
||||
if @particles.count < @max_particles && Gosu.milliseconds >= @last_emitted_at + (1000.0 / @frequency)
|
||||
emit
|
||||
end
|
||||
|
||||
@particles.each do |particle|
|
||||
@particles.delete(particle) if particle.die?
|
||||
particle.update
|
||||
end
|
||||
end
|
||||
|
||||
def die?
|
||||
Gosu.milliseconds >= @born_at + @time_to_live
|
||||
end
|
||||
end
|
||||
|
||||
class Particle
|
||||
attr_accessor :position, :direction, :factor, :angle, :speed, :time_to_live, :image, :color, :born_at
|
||||
def initialize(position:, direction:, factor:, angle:, speed:, time_to_live:, image:, color:)
|
||||
@position = position
|
||||
@direction = direction
|
||||
@factor = factor
|
||||
@angle = angle
|
||||
@speed = speed
|
||||
@time_to_live = time_to_live
|
||||
@image = image
|
||||
@color = color
|
||||
|
||||
@born_at = Gosu.milliseconds
|
||||
end
|
||||
|
||||
def draw
|
||||
@image.draw_rot(*@position.to_a[0..2], @angle, 0.5, 0.5, @factor.x, @factor.y, @color)
|
||||
end
|
||||
|
||||
def update
|
||||
@position -= (@direction * @speed) * $window.dt
|
||||
end
|
||||
|
||||
def die?
|
||||
Gosu.milliseconds >= @born_at + @time_to_live
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Dir.glob("#{IMICRTS::GAME_ROOT_PATH}/lib/particle_emitters/**/*.rb").each do |emitter|
|
||||
p emitter
|
||||
require_relative emitter
|
||||
end
|
||||
37
lib/particle_emitters/smoke_emitter.rb
Normal file
37
lib/particle_emitters/smoke_emitter.rb
Normal file
@@ -0,0 +1,37 @@
|
||||
class IMICRTS
|
||||
class SmokeEmitter < ParticleEmitter
|
||||
def setup
|
||||
@time_to_live = Float::INFINITY
|
||||
@particle_time_to_live = 2_500
|
||||
@frequency = 10.0
|
||||
@color = Gosu::Color.rgba(255, 255, 255, 255.0 * 0.4)
|
||||
@direction = CyberarmEngine::Vector.up
|
||||
@direction.y = 4.5
|
||||
@jitter = 25.0
|
||||
|
||||
@images = Gosu::Image.load_tiles("#{IMICRTS::ASSETS_PATH}/smoke/smoke.png", 32, 32, retro: false)
|
||||
end
|
||||
|
||||
def emit
|
||||
super
|
||||
|
||||
@particles.last.factor = CyberarmEngine::Vector.new(0.1, 0.1)
|
||||
end
|
||||
|
||||
def update
|
||||
super
|
||||
|
||||
@particles.each do |particle|
|
||||
life_cycle = (Gosu.milliseconds - particle.born_at.to_f) / particle.time_to_live
|
||||
scale = (2.0 * life_cycle) + 0.25
|
||||
particle.factor.x = scale
|
||||
particle.factor.y = scale
|
||||
|
||||
particle.color.alpha = ((255.0 * (1.0 - life_cycle)) - 255.0 * 0.4).clamp(0.0, 255.0)
|
||||
particle.angle += rand(0.1..0.5)
|
||||
|
||||
particle.direction.x = Math.cos(Gosu.milliseconds / 1_000.0) * 0.162
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -65,7 +65,24 @@ class IMICRTS
|
||||
end
|
||||
end
|
||||
|
||||
100.times { |i| [@c, @h, @t].sample.instance_variable_get("@block").call }
|
||||
# 100.times { |i| [@c, @h, @t].sample.instance_variable_get("@block").call }
|
||||
spawnpoint = @director.map.spawnpoints.last
|
||||
@player.entities << Entity.new(
|
||||
name: :construction_yard,
|
||||
director: @director,
|
||||
player: @player,
|
||||
id: @player.next_entity_id,
|
||||
position: CyberarmEngine::Vector.new(spawnpoint.x, spawnpoint.y, ZOrder::BUILDING),
|
||||
angle: 0
|
||||
)
|
||||
@player.entities << Entity.new(
|
||||
name: :construction_worker,
|
||||
director: @director,
|
||||
player: @player,
|
||||
id: @player.next_entity_id,
|
||||
position: CyberarmEngine::Vector.new(spawnpoint.x - 64, spawnpoint.y + 64, ZOrder::GROUND_VEHICLE),
|
||||
angle: 0
|
||||
)
|
||||
end
|
||||
|
||||
def draw
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
class IMICRTS
|
||||
class TiledMap
|
||||
attr_reader :width, :height, :tile_size
|
||||
attr_reader :layers, :tilesets
|
||||
attr_reader :layers, :tilesets, :spawnpoints
|
||||
def initialize(map_file)
|
||||
@xml = Nokogiri::XML(File.read("#{IMICRTS::ASSETS_PATH}/#{map_file}"))
|
||||
|
||||
@@ -10,6 +10,7 @@ class IMICRTS
|
||||
|
||||
@layers = []
|
||||
@tilesets = []
|
||||
@spawnpoints = []
|
||||
|
||||
@tiles = []
|
||||
|
||||
@@ -33,6 +34,15 @@ class IMICRTS
|
||||
@xml.search("//layer").each do |layer|
|
||||
@layers << Layer.new(layer)
|
||||
end
|
||||
|
||||
@xml.search("//objectgroup").each do |objectgroup|
|
||||
if objectgroup.attr("name") == "spawns"
|
||||
objectgroup.children.each do |object|
|
||||
next unless object.attr("name") && object.attr("name").downcase.strip == "spawn"
|
||||
@spawnpoints << SpawnPoint.new(object)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def get_tile(tile_id)
|
||||
@@ -121,5 +131,14 @@ class IMICRTS
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
class SpawnPoint
|
||||
attr_reader :x, :y
|
||||
def initialize(xml_object)
|
||||
@x, @y = Integer(xml_object.attr("x")), Integer(xml_object.attr("y"))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user