# Copyright 2007 Jay McGavren, jay@mcgavren.com. # # This file is part of Zyps. # # Zyps is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . require 'zyps' module Zyps #Keeps all objects within a set of walls. class Enclosure < EnvironmentalFactor #X coordinate of left boundary. attr_accessor :left #Y coordinate of top boundary. attr_accessor :top #X coordinate of right boundary. attr_accessor :right #Y coordinate of bottom boundary. attr_accessor :bottom def initialize(left = 0, top = 0, right = 0, bottom = 0) self.left, self.top, self.right, self.bottom = left, top, right, bottom end #If object is beyond a boundary, set its position equal to the boundary and reflect it. def act(object) if (object.location.x < @left) then object.location.x = @left object.vector.pitch = Utility.find_reflection_angle(90, object.vector.pitch) elsif (object.location.x > @right) then object.location.x = @right object.vector.pitch = Utility.find_reflection_angle(270, object.vector.pitch) end if (object.location.y > @top) then object.location.y = @top object.vector.pitch = Utility.find_reflection_angle(0, object.vector.pitch) elsif (object.location.y < @bottom) then object.location.y = @bottom object.vector.pitch = Utility.find_reflection_angle(180, object.vector.pitch) end end end #Keeps all objects at/under the assigned speed. class SpeedLimit < EnvironmentalFactor #Maximum allowed speed in units. attr_accessor :maximum def initialize(units) self.maximum = units end #If object is over the speed, reduce its speed. def act(object) object.vector.speed = Utility.constrain_value(object.vector.speed, @maximum) end end #A force that pushes on all objects. class Accelerator < EnvironmentalFactor #Vector to apply to objects. attr_accessor :vector def initialize(vector) self.vector = vector @clocks = {} #Don't use Hash.new , as it can't transmit via DRb. end #Accelerate the target away from the actor, but limited by elapsed time. def act(object) #Track time since last action for each GameObject. @clocks[object] ||= Clock.new #Push on object. object.vector += Vector.new(@vector.speed * @clocks[object].elapsed_time, @vector.pitch) end end #Gravity pulls all objects downward. class Gravity < Accelerator #Rate of acceleration. attr_accessor :force def initialize(force = 9.8) super(Vector.new(force, 90)) self.force = force end def force= (force) @vector.speed = force end end #A force that slows all objects. class Friction < EnvironmentalFactor #Rate of slowing. attr_accessor :force def initialize(force) self.force = force #Track time since last action for each GameObject. @clocks = {} #Don't use Hash.new , as it can't transmit via DRb. end #Reduce the target's speed at the given rate. def act(object) #Track time since last action for each GameObject. @clocks[object] ||= Clock.new #Slow object. acceleration = @force * @clocks[object].elapsed_time speed = object.vector.speed if speed > 0 speed -= acceleration speed = 0 if speed < 0 elsif speed < 0 speed += acceleration speed = 0 if speed > 0 end object.vector.speed = speed end end class PopulationLimit < EnvironmentalFactor #Environment to remove objects from. attr_accessor :environment #Maximum allowed population. attr_accessor :count def initialize(environment, count) self.environment = environment self.count = count end #Remove target if there are too many objects in environment. def act(object) if environment.objects.length > @count environment.objects.delete(object) end end end end #module Zyps