Basic working with ships partly implimented
This commit is contained in:
@@ -0,0 +1,146 @@
|
||||
# Nathan Hinton 30 Dec 2025
|
||||
# Ship file for the game
|
||||
|
||||
require 'securerandom'
|
||||
|
||||
# Load the ships into a constant:
|
||||
require 'yaml'
|
||||
SHIP_DATA = File.open('lib/game/ships.yaml', 'r') do |fi|
|
||||
YAML.safe_load(fi.read())
|
||||
end
|
||||
|
||||
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
|
||||
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
|
||||
class ShipError < StandardError
|
||||
end
|
||||
Reference in New Issue
Block a user