Godot Version
v4.5.dev5.official [64b09905c]
Question
Please look at below two GDScript files.
Should draw something on the screen, but nothing is drawn on screen?
Runs with no errors or warnings.
Below is “main.gd” which is attached to scene’s “Node2D”:
extends Node2D
var visualsClass = VisualsClass.new()
func _ready():
visualsClass.LoadAllImages()
set_process(true)
visualsClass.ScreenIsDirty = true
func _process(_delta):
if (visualsClass.ScreenIsDirty == true): visualsClass.DrawImageOnScreen(0, 1280.0/2.0, 720.0/2.0)
visualsClass.ScreenIsDirty = false
Below is “visuals.gd”:
class_name VisualsClass extends Node2D
var ScreenFade
var ImageArray = []
var ScreenIsDirty = true
func LoadAllImages():
ScreenFade = Sprite2D.new()
ScreenFade.texture = load("res://assets/images/BG_Black.png")
add_child(ScreenFade)
ScreenFade.global_position = Vector2(1280.0/2.0, 720.0/2.0)
ScreenFade.self_modulate.a = 0.0
ImageArray.resize(500)
for index in range(0, 500):
ImageArray[index] = Sprite2D.new()
if index == 0:
ImageArray[index].texture = load("res://assets/images/BG_Brick_Wall.png")
add_child(ImageArray[index])
ImageArray[index].global_position = Vector2(1280.0/2.0, 720.0/2.0)
ImageArray[index].self_modulate.a = 0.0
func DrawImageOnScreen(index, scrX, scrY):
ImageArray[index].self_modulate.a = 1.0
ImageArray[index].global_position = Vector2(scrX, scrY)
You’re creating 500 Sprite2D
, but you’re only actually calling add_child()
on one of them.
Your if index == 0
test there will mean 499 of your sprites will be uninitialized and undrawn, and the last one may well be displaying offscreen depending on parenting and origin.
i changed below to only do one image, still nothing on the screen?
func LoadAllImages():
ScreenFade = Sprite2D.new()
ScreenFade.texture = load("res://assets/images/BG_Black.png")
add_child(ScreenFade)
ScreenFade.global_position = Vector2(1280.0/2.0, 720.0/2.0)
ScreenFade.self_modulate.a = 0.0
ImageArray.resize(500)
for index in range(0, 1):
ImageArray[index] = Sprite2D.new()
if index == 0:
ImageArray[index].texture = load("res://assets/images/BG_Brick_Wall.png")
add_child(ImageArray[index])
ImageArray[index].global_position = Vector2(1280.0/2.0, 720.0/2.0)
ImageArray[index].self_modulate.a = 0.0
If you set self_modulate.alpha
to 0.0
you’re making it invisible.
Correct, but below function to draw image sets alpha to 1.0:
func DrawImageOnScreen(index, scrX, scrY):
ImageArray[index].self_modulate.a = 1.0
ImageArray[index].global_position = Vector2(scrX, scrY)
At this point, my advice would be to print stuff; the location of the sprite and things like that. See if anything looks out of place.
OK, followed your advice and did the following:
func DrawImageOnScreen(index, scrX, scrY):
ImageArray[index].self_modulate.a = 1.0
ImageArray[index].global_position = Vector2(scrX, scrY)
print("DrawImageOnScreen self_modulate.a = ",ImageArray[index].self_modulate.a)
print("DrawImageOnScreen global_position = ",ImageArray[index].global_position)
Output says:
Godot Engine v4.5.dev5.official.64b09905c - https://godotengine.org
OpenGL API 3.3.0 NVIDIA 570.133.07 - Compatibility - Using Device: NVIDIA - NVIDIA GeForce RTX 3060
DrawImageOnScreen self_modulate.a = 1.0
DrawImageOnScreen global_position = (640.0, 360.0)
--- Debugging process stopped ---
Perhaps someone knows how to fix this?
What do you get if you print:
ImageArray[index]
ImageArray[index].texture
ImageArray[index].self_modulate
In particular, I seem to recall some shenanigans around what calling load()
on .png
will get you.
Thanks for your help, here is requested output:
@Sprite2D@3:<Sprite2D#25937577317>
<CompressedTexture2D#-9223372010816535180>
(1.0, 1.0, 1.0, 1.0)
That all looks right. Everything looks like it ought to be working, really.
Unless you’ve got a Camera2D
or something that is pulling the view away, I’m not sure why that wouldn’t draw. I’m assuming this isn’t something silly like the parent Node2D having its visibility set to false
.
Hmm.
yesko
June 10, 2025, 9:03pm
11
Not a solution, but I wouldn’t use magic numbers like 1280.0/2
or 720.0/2
. I assume that’s the centre of the screen but I can’t know for sure without knowing your intentions. Also, it’s repeated so if the number ever changes, you have to update both instances.
In this case, Vector2(get_viewport().size) / 2
would be much clearer. It would probably even be best to define the size once at the top of the function and then just use the variable
OP did get a (640.0, 360.0)
result when printing it, so while it could definitely be clearer in the code, it appears in this case that it’s producing the desired results.
yesko
June 10, 2025, 9:09pm
13
Well if the window ever changes size it won’t work but you’re right that that’s probably not exactly relevant to the question. I just wanted to point that out because not repeating code (or at least making it readable) is a very good practice
OK, I have pinpointed the issue:
Issue is with “add_child()”
I made two changes below and now the brick wall image is shown
Any ideas now about what is wrong?
“main.gd”:
extends Node2D
var initializeClass = InitializeClass.new()
var visualsClass = VisualsClass.new()
func _ready():
initializeClass.Ready = true
visualsClass.LoadAllImages()
set_process(true)
visualsClass.ScreenIsDirty = true
add_child(visualsClass.ImageArray[0])
func _process(_delta):
if initializeClass.Ready == true:
if (visualsClass.ScreenIsDirty == true): visualsClass.DrawImageOnScreen(0, 1280.0/2.0, 720.0/2.0)
visualsClass.ScreenIsDirty = false
“initialize.gd”:
class_name InitializeClass extends Node2D
var Ready = false
“visuals.gd”:
class_name VisualsClass extends Node2D
var ScreenFade
var ImageArray = []
var ScreenIsDirty = true
func LoadAllImages():
ScreenFade = Sprite2D.new()
ScreenFade.texture = load("res://assets/images/BG_Black.png")
add_child(ScreenFade)
ScreenFade.global_position = Vector2(1280.0/2.0, 720.0/2.0)
ScreenFade.self_modulate.a = 0.0
ImageArray.resize(500)
for index in range(0, 1):
ImageArray[index] = Sprite2D.new()
if index == 0:
ImageArray[index].texture = load("res://assets/images/BG_Brick_Wall.png")
ImageArray[index].global_position = Vector2(1280.0/2.0, 720.0/2.0)
ImageArray[index].self_modulate.a = 0.0
func DrawImageOnScreen(index, scrX, scrY):
ImageArray[index].self_modulate.a = 1.0
ImageArray[index].global_position = Vector2(scrX, scrY)
print("DrawImageOnScreen self_modulate.a = ",ImageArray[index].self_modulate.a)
print("DrawImageOnScreen global_position = ",ImageArray[index].global_position)
print(ImageArray[index])
print(ImageArray[index].texture)
print(ImageArray[index].self_modulate)
That tends to imply your add_child()
in visuals.gd
was adding to the wrong parent. Where is the node that owns visuals.gd
in the tree?
“visuals.gd” does not have its own node in the tree.
Please see below screenshot:
yesko
June 11, 2025, 8:21am
18
visuals.gd
and initialize.gd
were apparently just instances of the script stored in Main
but not added to the tree.
If a node outside the scene tree adds a child to itself, nothing will appear to happen because the node isn’t part of the world. That’s why the add_child
in main.gd
was necessary.
However, as I understand it, the 500 images in ImageArray
still never show; they are never added to the tree with add_child
visuals.gd
.
.
.
func LoadAllImages(myParent: Node2D): # <-------------------
ScreenFade = Sprite2D.new()
ScreenFade.texture = load("res://assets/images/BG_Black.png")
ScreenFade.global_position = Vector2(1280.0/2.0, 720.0/2.0)
ScreenFade.self_modulate.a = 0.0
myParent.add_child(ScreenFade) # <--------------------------
ImageArray.resize(500)
for index in range(0, 1):
ImageArray[index] = Sprite2D.new()
if index == 0:
ImageArray[index].texture = load("res://assets/images/BG_Brick_Wall.png")
myParent.add_child(ImageArray[index]) # <--------------------------
ImageArray[index].global_position = Vector2(1280.0/2.0, 720.0/2.0)
ImageArray[index].self_modulate.a = 0.0
.
.
.
main.gd
func _ready():
initializeClass.Ready = true
visualsClass.LoadAllImages(self) # <--------------------------
Is this what you wanted?