Answers for "Godot parallax loop"

C++
0

Godot parallax loop

# Displays a background texture which loops infinitely in all directions.
# It should be put on a Node2D under the root of your scene.
# Differences from ParallaxBackground node:
# - Just drop a texture on it, done
# - No need to have a large enough image, tiling fills all visible area
# - Works on the same layer, adjust Z as you see fit
# - Focused on camera center, so zooming won't trouble the parallax. (TODO zoom parallax?)

extends Node2D

# Background texture to repeat
export(Texture) var texture = null
# Parallax motion speed. 
# The closer to zero, the slower the background will move.
# (1,1) is in sync, above is faster.
export var parallax = Vector2(0.5, 0.5)

var _tiles_x = 0
var _tiles_y = 0


func _ready():
    update_tiles()
    _update_position()
    set_process(true)

# If zoom changes too much in your game,
# you should call this, then update() to redraw tiles to the right range.
func update_tiles():
    _calculate_required_tiles()
    var ntiles = _calculate_required_tiles()
    _tiles_x = ntiles.x
    _tiles_y = ntiles.y
    #update()


func _process(delta):
    _update_position()


func _update_position():
    var cam_pos = _get_camera_center()
    #print("cam_zoom = " + str(Vector2(1,1)/get_canvas_transform().get_scale()))

    var parallax_pos = -cam_pos * parallax

    var tsize = texture.get_size()
    var tiled_pos = parallax_pos / tsize
    var floored_parallax_pos = tsize * Vector2(floor(tiled_pos.x), floor(tiled_pos.y))

    var new_pos = cam_pos + (parallax_pos - floored_parallax_pos)

    set_pos(new_pos)


func _get_camera_center():
    var ctrans = get_canvas_transform()
    var top_left = -ctrans.get_origin()
    var vsize = get_viewport_rect().size
    var center = (top_left + 0.5*vsize) / ctrans.get_scale()
    return center


func _calculate_required_tiles():
    var tile_size = texture.get_size() * get_scale()
    var view_size = get_viewport_rect().size / get_canvas_transform().get_scale()
    var fn = view_size / tile_size
    return Vector2(ceil(fn.x), ceil(fn.y))


func _draw():
    var tsize = texture.get_size()
    var nx = _tiles_x / 2 + 1
    var ny = _tiles_y / 2 + 1
    # Draw tiles around the center
    for y in range(-ny, ny):
        for x in range(-nx, nx):
            draw_texture(texture, Vector2(x,y) * tsize)

    #draw_rect(Rect2(Vector2(0,0), Vector2(8,8)), Color(1,0,0))
Posted by: Guest on July-19-2021

Browse Popular Code Answers by Language