I've done the float sprite movement a while ago. Included is a little test of it. Paste above Main.
=begin
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Allows sprites to have their x and y values changed via float values rather than
automatically converting to int.
Normally, when you change the x/y of a sprite by a Float, it will floor the
value before setting the sprite.
Examples:
sprite.x = 0.5 = floor(0.5) = 0
sprite.y = -0.5 = floor(-0.5) = -1
sprite.x = -1E10 = floor(-1E10) = -1
Also, adding a series of floats will do nothing. Look at the following:
while true
sprite.x += 0.99999
end
This will not move the sprite at all.
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
=end
# Takes in a number and an amount. This will add or reduce the number by that
# amount, whatever gets it closer to 0. If it would go beyond 0, it will stop at
# 0 (and if it is already 0, it will do nothing).
# You can make the amount negative to make the number move AWAY from 0 as well.
def to0(num, amt)
# First check if the number is already 0
if num.integer?
return num if num == 0
else
return num if num =~ 0
end
# Now check whether we need to ADD or SUBTRACT to reach (or avoid) 0
if num > 0
num = [num - amt, 0].max
else
num = [num + amt, 0].min
end
end
class Float
# A close float comparison. Because of rounding errors, this comparison will
# help compensate for that. Since 0 and 0.0001 are very close to each other,
# it's best to use this custom comparison.
def =~(num)
return (self + 0.0001 >= num && self - 0.0001 <= num)
end
end
# Contains modified set methods for X/Y that allow the use of Floats
class IntFloat
attr_reader :value
def initialize(n)
@value = n
end
def to_i; @value.to_i; end
def ceil; @value.ceil; end
def floor; @value.floor; end
def to_f; @value; end
def inspect; @value.to_i; end
def +(other)
if other.is_a?(IntFloat)
r = @value + other.value
elsif other.is_a?(Integer)
r = @value.floor + other
elsif other.is_a?(Float)
r = @value + other
else
raise "Cannot perform addition on a non-numeric object!"
end
r
end
def -(other)
if other.is_a?(IntFloat)
r = @value - other.value
elsif other.is_a?(Integer)
r = @value.floor - other
elsif other.is_a?(Float)
r = @value - other
else
raise "Cannot perform subtraction on a non-numeric object!"
end
r
end
def *(other)
if other.is_a?(IntFloat)
r = @value * other.value
elsif other.is_a?(Integer)
r = @value.floor * other
elsif other.is_a?(Float)
r = @value * other
else
raise "Cannot perform multiplication on a non-numeric object!"
end
r
end
def /(other)
if other.is_a?(IntFloat)
r = @value / other.value
elsif other.is_a?(Integer)
r = @value.floor / other
elsif other.is_a?(Float)
r = @value / other
else
raise "Cannot perform division on a non-numeric object!"
end
r
end
def set(other)
if other.is_a?(IntFloat)
@value = other.value
elsif other.is_a?(Integer) || other.is_a?(Float)
@value = other
else
raise "Cannot assign to a non-numeric object!"
end
roundOff
@value
end
def roundOff
if @value.to_f.abs =~ 1
@value = @value.round
end
end
end
class Sprite
alias init_offsets initialize
def initialize(vp = nil)
@intfloat_x = IntFloat.new(0.0)
@intfloat_y = IntFloat.new(0.0)
init_offsets(vp)
end
def x; @intfloat_x; end
def y; @intfloat_y; end
alias set_x x=
def x=(amt)
@intfloat_x.set(amt)
set_x(@intfloat_x.to_i)
end
alias set_y y=
def y=(amt)
@intfloat_y.set(amt)
set_y(@intfloat_y.to_i)
end
def xInt(x)
set_x(x)
end
def yInt(y)
set_y(y)
end
def xInt=(x)
xInt(x)
end
def yInt=(y)
yInt(y)
end
def actualX
return @intfloat_x.to_f
end
def actualY
return @intfloat_y.to_f
end
end
=begin
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Just a test program with the Float sprite movement. Move a red square around the
screen. Has a standard acceleration setup that is added to the sprite's X/Y
coordinates. If using Console debugger, hold SHIFT key to see values.
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
=end
begin
#Graphics.resize_screen(1024, 1024)
sprite = Sprite.new
sprite.bitmap = Bitmap.new(32,32)
sprite.bitmap.fill_rect(0,0,32,32, Color.new(255, 0, 0))
accel_x = 0.0
accel_y = 0.0
while true
Graphics.update
Input.update
input = Input.dir8
if Input.press?(Input::SHIFT)
#puts ["Sprite Location: ", sprite.x, sprite.y]
#puts ["Sprite Acutal: ",sprite.actualX, sprite.actualY]
#puts ["accel: ", accel_x, accel_y]
#puts "-------"
end
if Input.trigger?(Input::C)
sprite.y += 10
end
if Input.trigger?(Input::B)
sprite.x += 0.3
elsif Input.trigger?(Input::A)
sprite.x -= 0.3
end
# Get input and set sprite acceleration
if input != 0
if [1,2,3].include?(input)
accel_y += (accel_y >= 0 ? 0.2 : 0.5)
elsif [7,8,9].include?(input)
accel_y -= (accel_y <= 0 ? 0.2 : 0.5)
end
if [1,4,7].include?(input)
accel_x -= (accel_x <= 0 ? 0.2 : 0.5)
elsif [3,6,9].include?(input)
accel_x += (accel_x >= 0 ? 0.2 : 0.5)
end
end
# If not inputting in a desired direction, slow down in that direction
if [0,4,6].include?(input)
accel_y = to0(accel_y, 0.1).to_f
end
if [0,2,8].include?(input)
accel_x = to0(accel_x, 0.1).to_f
end
# Acceleration speed cap
if accel_y.abs > 10
accel_y = (accel_y > 0 ? 10 : -10)
end
if accel_x.abs > 10
accel_x = (accel_x > 0 ? 10 : -10)
end
# Move the sprite
sprite.x += accel_x
sprite.y += accel_y
end
end