mirror of
https://github.com/cyberarm/i-mic-rts.git
synced 2025-12-13 14:52:35 +00:00
Added Director, Player and stubbed Order, mostly working Entity#rotate_towards
This commit is contained in:
@@ -23,4 +23,8 @@ require_relative "lib/zorder"
|
|||||||
require_relative "lib/entity"
|
require_relative "lib/entity"
|
||||||
# require_relative "lib/entities/"
|
# require_relative "lib/entities/"
|
||||||
|
|
||||||
|
require_relative "lib/order"
|
||||||
|
require_relative "lib/director"
|
||||||
|
require_relative "lib/player"
|
||||||
|
|
||||||
IMICRTS::Window.new(width: Gosu.screen_width / 4 * 3, height: Gosu.screen_height / 4 * 3, fullscreen: false, resizable: true).show
|
IMICRTS::Window.new(width: Gosu.screen_width / 4 * 3, height: Gosu.screen_height / 4 * 3, fullscreen: false, resizable: true).show
|
||||||
@@ -16,7 +16,7 @@ class IMICRTS
|
|||||||
|
|
||||||
def window; $window; end
|
def window; $window; end
|
||||||
|
|
||||||
def draw(&block)
|
def draw(*args, &block)
|
||||||
if block
|
if block
|
||||||
center_point = center
|
center_point = center
|
||||||
Gosu.translate(@position.x, @position.y) do
|
Gosu.translate(@position.x, @position.y) do
|
||||||
|
|||||||
39
lib/director.rb
Normal file
39
lib/director.rb
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
class IMICRTS
|
||||||
|
class Director
|
||||||
|
def initialize(map:, players:, networking_mode: :virtual, tick_rate: 10)
|
||||||
|
@map = map
|
||||||
|
@players = players
|
||||||
|
@networking_mode = networking_mode
|
||||||
|
@tick_rate = tick_rate
|
||||||
|
|
||||||
|
@last_tick_at = Gosu.milliseconds
|
||||||
|
@tick_time = 1000.0 / @tick_rate
|
||||||
|
end
|
||||||
|
|
||||||
|
def update
|
||||||
|
if (Gosu.milliseconds - @last_tick_at) >= @tick_time
|
||||||
|
@last_tick_at = Gosu.milliseconds
|
||||||
|
|
||||||
|
tick
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def tick
|
||||||
|
@players.each(&:tick)
|
||||||
|
end
|
||||||
|
|
||||||
|
def player(id)
|
||||||
|
@players.find { |player| player.id == id }
|
||||||
|
end
|
||||||
|
|
||||||
|
def issue_order(player_id, order_id, *args)
|
||||||
|
# pp Order.order_name(order_id)
|
||||||
|
# pp args
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
def entities
|
||||||
|
@players.map { |player| player.entities }.flatten
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
class IMICRTS
|
class IMICRTS
|
||||||
class Entity
|
class Entity
|
||||||
attr_reader :position, :angle
|
attr_reader :position, :angle, :radius
|
||||||
def initialize(manifest: nil, images:, position:, angle:)
|
def initialize(manifest: nil, images:, position:, angle:)
|
||||||
@manifest = manifest
|
@manifest = manifest
|
||||||
@images = images
|
@images = images
|
||||||
@@ -37,5 +37,23 @@ class IMICRTS
|
|||||||
def draw_gizmos
|
def draw_gizmos
|
||||||
Gosu.draw_rect(@position.x - @radius, @position.y - (@radius + 2), @radius * 2, 2, Gosu::Color::GREEN, ZOrder::ENTITY_GIZMOS)
|
Gosu.draw_rect(@position.x - @radius, @position.y - (@radius + 2), @radius * 2, 2, Gosu::Color::GREEN, ZOrder::ENTITY_GIZMOS)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def rotate_towards(vector)
|
||||||
|
_angle = Gosu.angle(@position.x, @position.y, vector.x, vector.y)
|
||||||
|
a = (360 + (_angle - @angle)) % 360
|
||||||
|
|
||||||
|
# Fails if vector is directly behind entity
|
||||||
|
if @angle.between?(_angle - 3, _angle + 3)
|
||||||
|
@angle = _angle
|
||||||
|
elsif a < 180
|
||||||
|
@angle -= 1
|
||||||
|
else
|
||||||
|
@angle += 1
|
||||||
|
end
|
||||||
|
|
||||||
|
@angle %= 360
|
||||||
|
|
||||||
|
pp [a, _angle, @angle]
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
64
lib/order.rb
Normal file
64
lib/order.rb
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
class IMICRTS
|
||||||
|
class Order
|
||||||
|
@@orders = {}
|
||||||
|
|
||||||
|
def self.order_name(order_id)
|
||||||
|
IMICRTS::Order.constants(false).find { |const| IMICRTS::Order.const_get(const) == order_id }
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.define_handler(order_id, arguments: [], &handler)
|
||||||
|
raise "Handler from #{order_name(order_id)} already defined!" if @@orders.dig(order_id)
|
||||||
|
|
||||||
|
@@orders[order_id] = IMICRTS::Order.new(id: order_id, arguments: arguments, &handler)
|
||||||
|
end
|
||||||
|
|
||||||
|
def initialize(id:, arguments:, &handler)
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
def execute
|
||||||
|
@handler.call(self, Director.instance)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
orders = [
|
||||||
|
:CAMERA_MOVED,
|
||||||
|
:CAMERA_ZOOMED,
|
||||||
|
|
||||||
|
:ENTITY_SELECTED,
|
||||||
|
:ENTITY_DESELECTED,
|
||||||
|
:ENTITY_DESTROYED,
|
||||||
|
:ENTITY_DAMAGED,
|
||||||
|
:ENTITY_REPAIRED,
|
||||||
|
|
||||||
|
:SELECTED_UNITS,
|
||||||
|
:DESELECTED_UNITS,
|
||||||
|
|
||||||
|
:MOVE,
|
||||||
|
:STOP,
|
||||||
|
:GUARD,
|
||||||
|
:ATTACK,
|
||||||
|
:PATROL,
|
||||||
|
|
||||||
|
:BUILD_ORDER,
|
||||||
|
:CANCEL_BUILD_ORDER,
|
||||||
|
:BUILD_ORDER_COMPLETE,
|
||||||
|
|
||||||
|
:BUILDING_POWER_STATE,
|
||||||
|
:BUILDING_REPAIR,
|
||||||
|
:BUILDING_SELL,
|
||||||
|
|
||||||
|
:MESSAGE_BROADCAST,
|
||||||
|
:MESSGE_TEAM,
|
||||||
|
:MESSAGE_DIRECT,
|
||||||
|
]
|
||||||
|
|
||||||
|
offset = 0
|
||||||
|
orders.each_with_index do |order, i|
|
||||||
|
IMICRTS::Order.const_set(order, i + offset)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
Dir.glob("#{IMICRTS::GAME_ROOT_PATH}/lib/orders/*.rb").each do |order|
|
||||||
|
require_relative order
|
||||||
|
end
|
||||||
4
lib/orders/camera_moved.rb
Normal file
4
lib/orders/camera_moved.rb
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
IMICRTS::Order.define_handler(IMICRTS::Order::CAMERA_MOVED, arguments: [:player_id, :x, :y]) do |order, director|
|
||||||
|
director.player(order.player_id).move_camera(order.x, order.y)
|
||||||
|
end
|
||||||
|
|
||||||
20
lib/player.rb
Normal file
20
lib/player.rb
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
class IMICRTS
|
||||||
|
class Player
|
||||||
|
attr_reader :id, :name, :entities, :orders, :camera
|
||||||
|
def initialize(id:, name: nil)
|
||||||
|
@id = id
|
||||||
|
@name = name ? name : "Novice-#{id}"
|
||||||
|
|
||||||
|
@entities = []
|
||||||
|
@orders = []
|
||||||
|
@camera = Camera.new
|
||||||
|
end
|
||||||
|
|
||||||
|
def tick
|
||||||
|
puts "Player #{@id}-#{@name} ticked: #{Gosu.milliseconds}"
|
||||||
|
end
|
||||||
|
|
||||||
|
def entity(id)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -1,9 +1,11 @@
|
|||||||
class IMICRTS
|
class IMICRTS
|
||||||
class Game < CyberarmEngine::GuiState
|
class Game < CyberarmEngine::GuiState
|
||||||
def setup
|
def setup
|
||||||
@units = []
|
window.show_cursor = true
|
||||||
@selected_entities = []
|
@selected_entities = []
|
||||||
@camera = Camera.new
|
|
||||||
|
@player = Player.new(id: 0)
|
||||||
|
@director = Director.new(map: nil, players: [@player])
|
||||||
@mouse_pos = CyberarmEngine::Text.new("X: 0\nY: 0", x: 500, y: 10, z: Float::INFINITY)
|
@mouse_pos = CyberarmEngine::Text.new("X: 0\nY: 0", x: 500, y: 10, z: Float::INFINITY)
|
||||||
|
|
||||||
@sidebar = stack(height: 1.0) do
|
@sidebar = stack(height: 1.0) do
|
||||||
@@ -14,14 +16,14 @@ class IMICRTS
|
|||||||
flow do
|
flow do
|
||||||
@buttons = stack(width: 75) do
|
@buttons = stack(width: 75) do
|
||||||
@h = button("Harvester", width: 1.0) do
|
@h = button("Harvester", width: 1.0) do
|
||||||
@units << Entity.new(
|
@player.entities << Entity.new(
|
||||||
images: Gosu::Image.new("#{ASSETS_PATH}/vehicles/harvester/images/harvester.png", retro: true),
|
images: Gosu::Image.new("#{ASSETS_PATH}/vehicles/harvester/images/harvester.png", retro: true),
|
||||||
position: CyberarmEngine::Vector.new(rand(window.width), rand(window.height), ZOrder::GROUND_VEHICLE),
|
position: CyberarmEngine::Vector.new(rand(window.width), rand(window.height), ZOrder::GROUND_VEHICLE),
|
||||||
angle: rand(360)
|
angle: rand(360)
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
@c = button("Construction Worker", width: 1.0) do
|
@c = button("Construction Worker", width: 1.0) do
|
||||||
@units << Entity.new(
|
@player.entities << Entity.new(
|
||||||
images: Gosu::Image.new("#{ASSETS_PATH}/vehicles/construction_worker/images/construction_worker.png", retro: true),
|
images: Gosu::Image.new("#{ASSETS_PATH}/vehicles/construction_worker/images/construction_worker.png", retro: true),
|
||||||
position: CyberarmEngine::Vector.new(rand(window.width), rand(window.height), ZOrder::GROUND_VEHICLE),
|
position: CyberarmEngine::Vector.new(rand(window.width), rand(window.height), ZOrder::GROUND_VEHICLE),
|
||||||
angle: rand(360)
|
angle: rand(360)
|
||||||
@@ -49,8 +51,8 @@ class IMICRTS
|
|||||||
|
|
||||||
Gosu.draw_rect(0, 0, window.width, window.height, Gosu::Color.rgb(10, 175, 35))
|
Gosu.draw_rect(0, 0, window.width, window.height, Gosu::Color.rgb(10, 175, 35))
|
||||||
|
|
||||||
@camera.draw do
|
@player.camera.draw(0, 0, window.width, window.height) do
|
||||||
@units.each(&:draw)
|
@director.entities.each(&:draw)
|
||||||
@selected_entities.each(&:selected_draw)
|
@selected_entities.each(&:selected_draw)
|
||||||
|
|
||||||
# draw_rect(@camera.center.x - 10, @camera.center.y - 10, 20, 20, Gosu::Color::BLACK, Float::INFINITY)
|
# draw_rect(@camera.center.x - 10, @camera.center.y - 10, 20, 20, Gosu::Color::BLACK, Float::INFINITY)
|
||||||
@@ -66,14 +68,19 @@ class IMICRTS
|
|||||||
def update
|
def update
|
||||||
super
|
super
|
||||||
|
|
||||||
@camera.update
|
@director.update
|
||||||
|
@player.camera.update
|
||||||
|
|
||||||
|
@selected_entities.each do |ent|
|
||||||
|
ent.rotate_towards(@goal) if @goal
|
||||||
|
end
|
||||||
|
|
||||||
if @selection_start
|
if @selection_start
|
||||||
select_entities
|
select_entities
|
||||||
end
|
end
|
||||||
|
|
||||||
mouse = @camera.mouse_pick(window.mouse_x, window.mouse_y)
|
mouse = @player.camera.mouse_pick(window.mouse_x, window.mouse_y)
|
||||||
@mouse_pos.text = "Aspect Ratio: #{@camera.aspect_ratio}\nZoom: #{@camera.zoom}\nX: #{window.mouse_x}\nY: #{window.mouse_y}\n\nX: #{mouse.x}\nY: #{mouse.y}"
|
@mouse_pos.text = "Aspect Ratio: #{@player.camera.aspect_ratio}\nZoom: #{@player.camera.zoom}\nX: #{window.mouse_x}\nY: #{window.mouse_y}\n\nX: #{mouse.x}\nY: #{mouse.y}"
|
||||||
end
|
end
|
||||||
|
|
||||||
def button_down(id)
|
def button_down(id)
|
||||||
@@ -82,31 +89,36 @@ class IMICRTS
|
|||||||
case id
|
case id
|
||||||
when Gosu::MS_LEFT
|
when Gosu::MS_LEFT
|
||||||
unless @sidebar.hit?(window.mouse_x, window.mouse_y)
|
unless @sidebar.hit?(window.mouse_x, window.mouse_y)
|
||||||
@selection_start = CyberarmEngine::Vector.new(window.mouse_x, window.mouse_y) - @camera.position
|
@selection_start = CyberarmEngine::Vector.new(window.mouse_x, window.mouse_y) - @player.camera.position
|
||||||
end
|
end
|
||||||
when Gosu::MS_RIGHT
|
when Gosu::MS_RIGHT
|
||||||
@anchor = nil
|
@anchor = nil
|
||||||
end
|
end
|
||||||
@camera.button_down(id) unless @sidebar.hit?(window.mouse_x, window.mouse_y)
|
@player.camera.button_down(id) unless @sidebar.hit?(window.mouse_x, window.mouse_y)
|
||||||
end
|
end
|
||||||
|
|
||||||
def button_up(id)
|
def button_up(id)
|
||||||
super
|
super
|
||||||
|
|
||||||
case id
|
case id
|
||||||
|
when Gosu::MS_RIGHT
|
||||||
|
@goal = @player.camera.mouse_pick(window.mouse_x, window.mouse_y)
|
||||||
when Gosu::MS_LEFT
|
when Gosu::MS_LEFT
|
||||||
@box = nil
|
@box = nil
|
||||||
@selection_start = nil
|
@selection_start = nil
|
||||||
|
|
||||||
|
@director.issue_order(@player.id, Order::SELECTED_UNITS, @selected_entities)
|
||||||
end
|
end
|
||||||
|
|
||||||
@camera.button_up(id)
|
@player.camera.button_up(id)
|
||||||
end
|
end
|
||||||
|
|
||||||
def select_entities
|
def select_entities
|
||||||
@box = CyberarmEngine::BoundingBox.new(@selection_start, CyberarmEngine::Vector.new(window.mouse_x, window.mouse_y) - @camera.position)
|
@box = CyberarmEngine::BoundingBox.new(@selection_start, CyberarmEngine::Vector.new(window.mouse_x, window.mouse_y) - @player.camera.position)
|
||||||
|
|
||||||
selected_entities = @units.select do |ent|
|
selected_entities = @player.entities.select do |ent|
|
||||||
@box.point?(ent.position)
|
@box.point?(ent.position - ent.radius) ||
|
||||||
|
@box.point?(ent.position + ent.radius)
|
||||||
end
|
end
|
||||||
|
|
||||||
if Gosu.button_down?(Gosu::KB_LEFT_SHIFT) || Gosu.button_down?(Gosu::KB_RIGHT_SHIFT)
|
if Gosu.button_down?(Gosu::KB_LEFT_SHIFT) || Gosu.button_down?(Gosu::KB_RIGHT_SHIFT)
|
||||||
|
|||||||
@@ -4,8 +4,13 @@ class IMICRTS
|
|||||||
@last_update_time = Gosu.milliseconds
|
@last_update_time = Gosu.milliseconds
|
||||||
|
|
||||||
self.caption = "#{IMICRTS::NAME} (#{IMICRTS::VERSION} #{IMICRTS::VERSION_NAME})"
|
self.caption = "#{IMICRTS::NAME} (#{IMICRTS::VERSION} #{IMICRTS::VERSION_NAME})"
|
||||||
# push_state(Boot)
|
if ARGV.join.include?("--fast")
|
||||||
push_state(MainMenu)
|
push_state(MainMenu)
|
||||||
|
elsif ARGV.join.include?("--debug")
|
||||||
|
push_state(Game)
|
||||||
|
else
|
||||||
|
push_state(Boot)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def update
|
def update
|
||||||
|
|||||||
Reference in New Issue
Block a user