How to dinamically draw images from (.png) files.

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By C:\Flavius

I am currently trying to make my own version of famous games and also programming simple games (like one that imitates the Linux terminal and you play using commands).
Now I’m trying the most classic game I know; Tetris.

For that I’m using 8x8 graphics, in a window of 120x240 pixels, with a play field of 104 pixels wide. All of this is divided in 8x8 squares, so the whole window is 15x30 squares.
I need to make the squares the tetrominos are made of appear and reappear in these sectors.
The problem is I don’t know how to make the squares appear and dissapear.
I have three ways in mind;

1.- Instead of making the squares appear and form the tetrominos, I just make png files of each tetromino, place a bunch of them otside the window where no player can see them and move them instead of drawing new ones. MEDIOCRE
2.- I place one square of every colour in every sector of the play field and make them visible and invisible depending on the value of a 2D array that represents it. Example; number 0 means all invisible, number 1 means red visible only…
3.- This is the one I actually want to do; have only the squares I need, no invisibility allowed. So it means I need to draw them dinamically.
For this I first tried using the main node (the one that gives it’s name to the scene) to draw a square at the beggining of the game in the middle of the play field using

var greensq = preload("res://greensq.png")

and in the ready function

draw_texture(greensq, Vector2(32, 32))

Of course this didn’t work so I created a Node2D and used the exact same code, but didn’t work. Then I realised and moved the draw texture function to the draw() function.
It didn’t work either so I browsed the internet for a while and tried

var sprgreensq = Sprite.new()
sprgreensq.set_texture(greensq)
sprgreensq.set_position(Vector2(32,32))

In the draw function too, but it didn’t work. I made sure to move this node to the top so it isn’t covered by any other nodes (I placed some decorative pngs and a background).
Then I tried making all of those other nodes invisible but it didn’t work either.

So I need any way of making the graphics of a tetris game to work.

Now I had diner, and I’m going to study calculus for a couple of hours before going to sleep so I will answer your replies tomorrow after class ( it is 22:24 now, so I’ll answer in anywhere from 17 hours to 25 hours).
Thank you in advance for your help!

Couldn’t you just-

  1. Make one Tetris brick texture which can then have it’s color modulated by a Node 2D.
  2. Apply this texture to a Node2D. No need for drawing code this way
  3. Make a library of Tetris brick shape scenes, each scene using a combination of aforementioned node with a different modulating colour.

SIsilicon | 2018-09-26 01:23

Hello.
I didn’t understand, can you make a scene appear on other scene as a tetromino?
I think I yet don’t know enough about Godot to understand that. I think I get steps 1 and 2 but not the third one…

C:\Flavius | 2018-09-27 14:53

When I say a library of brick scenes, I’m mean like a bunch of scenes that you can instance. Each scene would contain node2D’s as bricks. And some code to merge these node2Ds with the bricks that accumulate at the bottom. I think I may need to make an example scene for you to understand.

SIsilicon | 2018-09-27 16:30

I just made an extremely foolish mistake. I placed a different brick on every single position posible. Being a 13x27 play field, it is over 350 bricks, and then I created one script to give each one a color or hide them, then I started creating scripts for each of them to use that one script. This project has over 250 scripts already, most of which are exactly the same. This is because I don’t know how to properly reference a node from a script that extends another node. Then godot said the message queue was full so I closed it and re-opened it.
After like 5 minutes it’s still getting opened.
OMG I’m such a bad programer D:

I know what a library is, but I thought a scene is like the fabric of spacetime, so to me you are saying that I have to put a bunch of fabrics of space-time inside the fabric of spacetime… What I think you say is that I can create some scenes, each one containing some shape like the “T” tetromino. Then I can create instances of them from within the game field, am I wrong? I have no idea but I want to learn and improve to stop making 350+ sprites and 250 scripts (only 250 cause I stopped at like 60% to re-start godot, which is still trying to run, the console showing lots of messages each second…).

Edit: I know you, you helped me the last time and thanks to you I now know what the _process(delta) function is, and I already practiced a few ways of using it.

C:\Flavius | 2018-09-27 17:08

I shall teach you the ways of Godot. ( ͡°╭͜ʖ╮͡° )

SIsilicon | 2018-09-27 17:55

Did you know that-

You can create a scene, then instance that scene in another as many times as you want?

Eg:
Here’s a simple ball scene.

RigidBody2D (name: Ball)
|-> CollisonShape2D
|-> Sprite

Which can be used in another scene like this.

Node2D
|-> StaticBody2D (name: Platform)
| |-> CollisionShape2D
| |-> Sprite
|
|-> Ball
|-> Ball2 (in a different position)

SIsilicon | 2018-09-27 18:02

Did you know that-

Not only can a script extend from a Built-in class like Node, but it can also extend from another script.

Eg:

extends "another_script.gd"
#The string quotes is the path to the script. Either relative or absolute.

SIsilicon | 2018-09-27 18:05

Wow I had no idea let me try that right now, I’ll tell you if I been able to do ir right. Thanks a lot, Sisilicon

C:\Flavius | 2018-09-27 18:32

This is really useful!
I made two T shaped tetrominos that are child scenes of the play field scene. Just placed one, duplicated and bam!
I only have one question, can I instance them from a script, so that I can destroy them when not used and so that I don’t place 350 of them?

Also, is there a way to change their shape from script? Cause when you get a full line at the bottom they dissappear. I could just move every object down so that it cannot be seen in the window and when they are fully outside the field of view of the player, they get distroyed. I also guess they can be easily rotated instead of using the complicated method I came up with.

Also one more thing, how can I change their colours? (sorry if I ask too many questions, I guess I’ll just try to do these things myself, and learn through trial and error, but it’s alway nice to skip a bit of that proccess)

Thank you very much for this!!

C:\Flavius | 2018-09-27 18:43

I’m gonna go now. Again, I’m going to use what you taught me right now a lot tomorrow and try to make it as good as I can.
Thank you a lot for your help!

C:\Flavius | 2018-09-27 18:51

That’s a lot of questions for a comment.

can I instance them from a script, so that I can destroy them when not used and so that I don’t place 350 of them?

Yes.

var tetro = preload("path to tetromino scene").instance()

Also, is there a way to change their shape from script?

It depends on how you implement the tetrominoes and the bricks in general. When I upload an example you could look for your answer there.

Also one more thing, how can I change their colours?

Every Node2D has a modulate and self-modulate property. They are both colors that the Node2D’s color gets multiplied by. The difference between the two is that modulate effects the node and its children, while self-modulate only effects the node itself. modulate would be more useful here.

SIsilicon | 2018-09-28 00:11

Here it is. Sorry if it looks complex to you. I hope I did a good job with the comments. If not, ask away.

SIsilicon | 2018-09-29 01:33

Added a metallic property, because I can.

SIsilicon | 2018-09-29 16:53

You still there?

SIsilicon | 2018-10-07 23:59