Search code examples
godotgodot4

Godot setting anchor to "full rect" doesn't stretch the background image across entire game play field


I am following a book example of Chris Bradfield "Godot 4 Gave Development Projects - Build Five cross platform 2D and 3D games 2nd Edition".

I am at the stage of having a very simple game "Coin Dash" where an animated fox can collect randomly spawn animated coins. Next stage is to take a green grass tile background image and stretch it over entire gameplay field, the author of the book claims:

Add the following nodes as children of Main:
• A TextureRect node named Background – for the background image
• A Timer node named GameTimer – for the countdown timer
>
Make sure Background is the first child node by dragging it above the player in the node list. Nodes are drawn in the order shown in the tree, so if Background is first, that ensures it’s drawn behind the player. Add an image to the Background node by dragging the grass.png image from the assets folder into the Texture property. Change Stretch Mode to Tile, and then set the size to Full Rect by clicking the layout button at the top of the editor window:

https://i.sstatic.net/5mtOL.png

My project structure looks like

And yet the 2D screen after setting the stretch mode to tile looks like

While the game works no problem, that little square in the top left screen corner should cover entire game play field and it doesn't. The frustration of a noob following a deceiving book is real since I have so little knowledge to juggle what is wrong in here:

Actual running game

The main script is as follows:

extends Node
@export var coin_scene : PackedScene
@export var playtime = 30
var level = 1
var score = 0
var time_left = 0
var screensize = Vector2.ZERO
var playing = false

func _ready():
    screensize = get_viewport().get_visible_rect().size
    $Player.screensize = screensize
    $Player.hide()
    new_game()
    
func new_game():
    playing = true
    level = 1
    score = 0
    time_left = playtime
    $Player.start()
    $Player.show()
    $GameTimer.start()
    spawn_coins()
    
func spawn_coins():
    for i in level + 4:
        var c = coin_scene.instantiate()
        c.screensize = screensize
        add_child(c)
        c.position = Vector2(randi_range(0, screensize.x), randi_range(0, screensize.y))

Setting up full rect as anchor size and set "Stretch Mode" to "Tile"


Solution

  • The issue is that Main (the roof of the scene) is a Node2D (I know it is a Node2D because it has a blue circle icon).

    And as Node2D it does not have an size (yes, some Node2D have a concept of size by virtue of having a texture, but that is not true for Node2D in general, nor would it help here).

    So when Background tries to expand to the "Full Rect" of its parent, it can't. Because, to reiterate, its parent Main does not have a size.

    I have three options for you…


    Option A

    • Change the type of Main to be a Node

    I believe this is the intention of the author, given that your script is defined to extend Node.

    The way this works is that the Control will disregard the parent Node, so it takes the size of the parent Viewport (which is the root of the scene tree, the same one you get with get_viewport).


    Option B

    • Change the type of Main to be a Control
    • Set it to "Full Rect"

    The way this works is that the Main node will take the size of the parent viewport, so the background can take the size from it.


    Option C

    • Set the size of Background from the Main script.

    You are already getting the size for the purpose of limiting the area where the coins can spawn. You can also set that size to Background.

    By the way, you might want to handle the size_changed signal of the Viewport, you can connect to it via code, see Using Signals.