# Represents a space-faring vessel owned by a player. # Handles movement and validation of ship creation. require 'securerandom' # Load the ships into a constant: require 'yaml' # Configuration data for all available ships SHIP_DATA = File.open('lib/game/data/ships.yaml', 'r') do |fi| YAML.safe_load(fi.read()) end # Represents a space-faring vessel owned by a player. class Ship attr_reader :owner, :position # Ships are built by a player so we should *always* know what player is # owning a ship # # @param player [Player] The player who owns the ship # @param position_x [Float] The starting x position of the ship. # @param position_y [Float] The starting y position of the ship. # @param position_z [Float] The starting z position of the ship. def initialize(player, position_x, position_y, position_z, name) @owner = player @ship_id = SecureRandom.hex @position = [position_x, position_y, position_z] @target = @position @speed = 1 @ship_info = validate_creation(name) end # Validates that the ship name exists and it is unlocked by the player (Has # the right buildings and tech to actually create). This means that you might # be able to start a ship however when it is 'finished' if a required # building has been removed it will fail to finish properly. In this case the # player resources should be refunded (with some lost) and the ship creation # will raise an error. def validate_creation(name) ship = SHIP_DATA[name] raise ShipError, "invalid ship name '#{name}'" if ship.nil? # Validate that the owner has the correct tech: ship['required_tech'].each do |tech_needed| if !(@owner.researched_tech.include? tech_needed) raise ShipError, "Player needs the tech of '#{tech_needed}'" end end # Validate the buildings: ship['required_buildings'].each do |building_needed| if !(@owner.buildings.include? building_needed) raise ShipError, "Player needs the building of '#{building_needed}' to build this ship" end end return ship end # Teleport the ship to a given position. Really only should be used for admin # stuff. # # @param position_x [Float] The new x position of the ship. # @param position_y [Float] The new y position of the ship. # @param position_z [Float] The new z position of the ship. def teleport(position_x, position_y, position_z) @position = [position_x, position_y, position_z] end # Sets the target position of a ship. # # @param position_x [Float] The new x position of the ship. # @param position_y [Float] The new y position of the ship. # @param position_z [Float] The new z position of the ship. def move(position_x, position_y, position_z) @target = [position_x, position_y, position_z] end # Contains the logic to move a ship # # @param delta_time [Float] The delta time elapsed in the game def update(delta_time) # Movement logic: if @position == @target # Do nothing else # Calculate the difference of the position and the target x_dist = @target[0] - @position[0] y_dist = @target[1] - @position[1] z_dist = @target[2] - @position[2] total_dist = Math.sqrt(x_dist**2 + y_dist**2 + z_dist**2) speed = (@speed/total_dist) * delta_time new_x = @position[0] + (x_dist * speed) new_y = @position[1] + (y_dist * speed) new_z = @position[2] + (z_dist * speed) if x_dist > 0 # Going right if new_x > @target[0] new_x = @target[0] end elsif x_dist < 0 # Going left if new_x < @target[0] new_x = @target[0] end end if y_dist > 0 # Going right if new_y > @target[1] new_y = @target[1] end elsif y_dist < 0 # Going left if new_y < @target[1] new_y = @target[1] end end if z_dist > 0 # Going right if new_z > @target[2] new_z = @target[2] end elsif z_dist < 0 # Going left if new_z < @target[2] new_z = @target[2] end end @position = [new_x, new_y, new_z] end end # Save a player to a file def save_to_file File.open("game_data/#{self.planet_id}.save", 'wb') do |fi| # Load resources for the player: fi.write(Marshal.dump(self)) end return self.planet_id end # Load a player from a file def self.load_from_save(fname) File.open("game_data/#{fname}_ship_.save", 'rb') do |fi| # Load resources for the player: Marshal.load(fi.read) end end end # Error class for ships # Represents a space-faring vessel owned by a player. class ShipError < StandardError end