lib/gamebox/core/viewport.rb in gamebox-0.4.1 vs lib/gamebox/core/viewport.rb in gamebox-0.5.0
- old
+ new
@@ -8,10 +8,11 @@
attr_accessor :x_offset, :y_offset, :follow_target, :width,
:height, :x_offset_range, :y_offset_range, :boundary, :rotation
attr_reader :speed
+ alias :follow_target? :follow_target
def debug
"xoff:#{@x_offset} yoff:#{@y_offset}"
end
@@ -57,68 +58,33 @@
return @y_offset if layer == 1
@y_offset / layer
end
def update(time)
- scrolled = false
- if @follow_target
- x = @follow_target.x
- y = @follow_target.y
- if @x_offset_range
- x = @x_offset_range.min if @x_offset_range.min > x
- x = @x_offset_range.max if @x_offset_range.max < x
- end
- if @y_offset_range
- y = @y_offset_range.min if @y_offset_range.min > y
- y = @y_offset_range.max if @y_offset_range.max < y
- end
- x_diff = @width/2 + @follow_offset_x - x - @x_offset
- if x_diff.abs > @buffer_x
- # move screen
- if x_diff > 0
- @x_offset += (x_diff - @buffer_x) * @speed
- else
- @x_offset += (x_diff + @buffer_x) * @speed
- end
-
- scrolled = true
- end
-
- y_diff = @height/2 + @follow_offset_y - y - @y_offset
- if y_diff.abs > @buffer_y
- # move screen
- if y_diff > 0
- @y_offset += (y_diff - @buffer_y) * @speed
- else
- @y_offset += (y_diff + @buffer_y) * @speed
- end
- scrolled = true
- end
-
- # constrain_x_offset
- if @boundary
- if @x_offset > 0 - @boundary[0] # Left-wall bump
- @x_offset = @boundary[0]
- elsif @x_offset < @width - @boundary[2] # right-wall bump
- @x_offset = @width - @boundary[2]
- end
- end
-
- # constrain_y_offset
- if @boundary
- if @y_offset > 0 - @boundary[1]
- @y_offset = @boundary[1]
- elsif @y_offset < @height - @boundary[3]
- @y_offset = @height - @boundary[3]
- end
- end
-
+ if follow_target?
+ scrolled = move_towards_target
+ clamp_to_boundary
fire :scrolled if scrolled
end
end
+ # Viewport will stay centered on the targets x,y
+ #
+ # args hash:
+ # :x_offset - keep the viewport centered on x + x_offset
+ # :y_offset - keep the viewport centered on y + y_offset
+ # :x_chain_length - allow this much x slack when following
+ # :y_chain_length - allow this much y slack when following
+ def stay_centered_on(target, args={})
+ offset_x = args[:x_offset] || 0
+ offset_y = args[:y_offset] || 0
+ x_chain_length = args[:x_chain_length] || 0
+ y_chain_length = args[:y_chain_length] || 0
+ follow target, [-offset_x, -offset_y], [x_chain_length, y_chain_length]
+ end
+ # deprecated; use #stay_centered_on
def follow(target, off=[0,0], buff=[0,0])
@follow_target = target
@follow_offset_x = off[0]
@follow_offset_y = off[1]
@buffer_x = buff[0]
@@ -131,9 +97,67 @@
end
def bounds
left = -@x_offset
top = -@y_offset
- Rect.new left, top, left + @width, top + @height
+ # Rect.new left, top, left + @width, top + @height
+ Rect.new left, top, @width, @height
+ end
+
+ private
+ def move_towards_target
+ scrolled = false
+
+ x = @follow_target.x
+ y = @follow_target.y
+
+ if @x_offset_range
+ x = @x_offset_range.min if @x_offset_range.min > x
+ x = @x_offset_range.max if @x_offset_range.max < x
+ end
+ if @y_offset_range
+ y = @y_offset_range.min if @y_offset_range.min > y
+ y = @y_offset_range.max if @y_offset_range.max < y
+ end
+ x_diff = @width/2 + @follow_offset_x - x - @x_offset
+ if x_diff.abs > @buffer_x
+ # move screen
+ if x_diff > 0
+ @x_offset += (x_diff - @buffer_x) * @speed
+ else
+ @x_offset += (x_diff + @buffer_x) * @speed
+ end
+
+ scrolled = true
+ end
+
+ y_diff = @height/2 + @follow_offset_y - y - @y_offset
+ if y_diff.abs > @buffer_y
+ # move screen
+ if y_diff > 0
+ @y_offset += (y_diff - @buffer_y) * @speed
+ else
+ @y_offset += (y_diff + @buffer_y) * @speed
+ end
+ scrolled = true
+ end
+
+ scrolled
+ end
+
+ def clamp_to_boundary
+ if @boundary
+ if @x_offset > 0 - @boundary[0] # Left-wall bump
+ @x_offset = @boundary[0]
+ elsif @x_offset < @width - @boundary[2] # right-wall bump
+ @x_offset = @width - @boundary[2]
+ end
+
+ if @y_offset > 0 - @boundary[1]
+ @y_offset = @boundary[1]
+ elsif @y_offset < @height - @boundary[3]
+ @y_offset = @height - @boundary[3]
+ end
+ end
end
end