I’m creating parallax scrolling backgrounds by creating ‘panel’ objects whose sprite components can be tiled in the scrolling direction. An issue I’m encountering is that when I’m scrolling the background, there are certain points where the seam between tiled ‘panels’ is broken, it looks very ugly:
The background collections are setup like this:
This is the script for the layer:
require 'true2tile.globals'
local v3 = v3 -- vector3 shortcuts
go.property('vertical', false)
go.property('tiling_interval', 0)
go.property('radius', 0)
function init(self)
self.world_position = go.get_world_position()
self.offset = go.get_position().y
self.panels = {}
local center_index = self.radius + 1
self.panels[center_index] = factory.create('#factory', v3.up(self.offset))
for i = 1, self.radius do
self.panels[center_index - i] = factory.create('#factory', v3.left(self.tiling_interval * i) + v3.up(self.offset))
self.panels[center_index + i] = factory.create('#factory', v3.right(self.tiling_interval * i) + v3.up(self.offset))
end
for _, id in ipairs(self.panels) do
go.set_parent(id, go.get_id(), false)
end
end
function update(self, dt)
local panel_first = go.get_position(self.panels[1])
local panel_last = go.get_position(self.panels[#self.panels])
if panel_first.x < -self.tiling_interval*(self.radius+1) then
local new_position = go.get_position(self.panels[#self.panels]) + v3.right(self.tiling_interval)
go.set_position(new_position, self.panels[1])
local p = self.panels[1]
table.remove(self.panels, 1)
table.insert(self.panels, #self.panels + 1, p)
end
if panel_last.x > self.tiling_interval*(self.radius+1) then
local new_position = go.get_position(self.panels[1]) + v3.left(self.tiling_interval)
go.set_position(new_position, self.panels[#self.panels])
local p = self.panels[#self.panels]
table.remove(self.panels, #self.panels)
table.insert(self.panels, 1, p)
end
local panel_center = go.get_position(self.panels[self.radius+1])
do -- realign the panels relative to each other
local center_index = self.radius + 1
for i = 1, self.radius do
go.set_position(v3.left(self.tiling_interval * i) + panel_center, self.panels[center_index - i])
go.set_position(v3.right(self.tiling_interval * i) + panel_center, self.panels[center_index + i])
end
end
end
And the script for the panels themselves:
local camera = require 'orthographic.camera'
go.property('scroll_speed_power_x',0)
go.property('scroll_speed_power_y',0)
function update(self, dt)
self.velocity = vmath.vector3()
self.velocity.x = camera.get_position_delta().x * (self.scroll_speed_power_x) * (-0.01)
self.velocity.y = camera.get_position_delta().y * (self.scroll_speed_power_y) * (-0.01)
local new_position = go.get_position() + self.velocity
go.set_position(new_position)
end
The script for the parent ‘parallax’ GO just sets the position of that object to match the camera’s position.
My current theory for this behaviour is that because I’m using a reduced size viewport but still lerping with higher than per-pixel precision, something with how the exact value of a decimal number needing to be represented as an integer to represent the correct pixel is causing this (would this be considered something like a subpixel?)
How can I get around this?