February 3, 2019 at 7:45 am
There are days when an enormous amount of stuff just easily falls into place. Yesterday was not such a day. There are too many things I don’t know about using Godot that make simple tasks take a ton of research.
I posted what I managed to complete last night on itch.io:
I totally underestimated how little I know about making stuff in Godot. Things that should have worked quickly took way too much time. Especially since I’m using all built-in magic.
The first experiments I did with Godot, I imported an SVG version of the spaceship since that seemed like a clever way to have precise art and allow it to rotate nicely, etc. However, I can’t get the SVGs I create in CorelDraw to have color properties which is why both ships in the early demos are black.
The first thing I did was recreate the graphics as png files. This required a lot of experimentation to get it to work the way I wanted it to. I don’t know what the preferred common practice is. I tried making graphics actual pixel size (the game screen is 800×450 pixels so I was making the ship about 33 pixels tall). The graphics just came out blocky and I have no idea why. If they look fine on the screen in CorelDraw at actual pixel size, then why do they look crappy on the export?
What I finally settled with that seemed to work was to export the spaceship as a two-color png (the ship color and with black as transparent) with no anti-aliasing but 160 pixels wide and 280 pixels high. I then scale these in Godot (I think to 1/4 the size) and somehow the lines all wind up looking smooth with proper transparency even when the spaceship is rotated. There’s some magic going on there that I did not expect. This is how I originally intended the ship to look – like a vector graphic from an old arcade machine.
To add the thrust flames I had to increase the number of colors in the png. Now I have a green player and a purple player that have graphics.
I started with a fresh Godot project and figured it would be quick and easy to replicate what I already had created. I discovered that I can run two instances of Godot so that I can have my old project available and the project I’m working on. This was useful for being able to examine code since I’m still not familiar with Godot basics. The one problem I ran into repeatedly was switching from a web browser looking up back to the wrong instance of Godot and making changes to my old version instead of the new version I’m working on.
I created a sprite with the green ship and added the collision shape to it. I then wanted to reuse that sprite with the purple ship. At that point, I could not figure out a way to change the sprite texture of the ship with code, so I tried to create two different ship sprites by duplicating the first one. This was a MESS. They both wound up using the same script file, so every change I made affected both sprites (changing the controls from the left player to the right to the left…). This wasted a LOT of time.
I finally figured out to “save as” the scripts to make them two different script files that were attached to the two different sprites. This wound up being a lot of work to be able to use the same collision polygon for both sprites.
- There must be a way to copy the collision polygon in code. I didn’t want to hand-draw the collision polygon twice and have the 2 ships come out slightly different. I achieved this by doing lots of “save as” and deleting/reattaching scripts until I got the correct script on the correct ship.
- Later in the day I did figure out how to change the texture of a sprite (so that the sprite could change to the thrusting sprite) – which means I could have had one sprite thing and instanced it to make the two different ships instead of needing to maintain 2 separate scripts.
There is this constant problem of “knowing something must be possible” but not knowing how to do it.
I found this reference:
Change sprite image in code?
This wound up being the code to change the sprite graphic to the thrust version. I had to do one of these for each player.
extends Sprite var green_thrust_sound onready var greenshipsprite = get_node(".") var greenship = load("res://player ship 02 green.png") var greenshipthrust = load("res://player ship 02 green thrust.png") func _ready(): # Called when the node is added to the scene for the first time. # Initialization here green_thrust_sound = AudioStreamPlayer.new() self.add_child(green_thrust_sound) green_thrust_sound.stream = load("res://Explosion 4.ogg") pass func _physics_process(delta): # Called every frame. Delta is time since last frame. # Update game logic here. if Input.is_key_pressed(KEY_SLASH): greenshipsprite.texture = greenshipthrust green_thrust_sound.play() else: greenshipsprite.texture = greenship green_thrust_sound.stop() pass
It took me a long time to get this to work.
First was the:
onready var greenshipsprite = get_node(“.”)
I could not figure out what to put in the get_node that meant “refer to self”
Then, the example code I found for loading sprite textures had me doing:
var greenship = “res://player ship 02 green.png”
instead of doing:
var greenship = load(“res://player ship 02 green.png”)
Two problems I kept running into:
- There are a lot of examples out there for Godot 2.x that are no longer correct in Godot 3.x.
- There are a lot of people who are familiar enough with Godot that they can look at example code and “fill in the blanks” for what’s missing because someone typed it quickly as an answer rather than actually making sure the code worked. That’s how I wound up loading a string with the filename of the texture instead of loading the texture.
In what is currently the “main node” (I don’t know the technical term for this) I figured out how to change the gravity since it felt too high now that the play area is only 450 pixels high.
extends Node2D var default_gravity = ProjectSettings.get_setting("physics/2d/default_gravity") func _ready(): # Called when the node is added to the scene for the first time. # Initialization here default_gravity=60 Physics2DServer.area_set_param(get_world_2d().space, Physics2DServer.AREA_PARAM_GRAVITY, default_gravity) pass
I’d like to figure out how to make some global variables, since right now the settings for how much thrust the ships have and how much they bounce are in the scripts for the individual scripts (so I have to make changes in two places to fine-tune things). This seems to be done with Singletons – but that’s as far as I’ve gotten since I don’t know what a Singleton is.
On my laptop, this demo runs really poorly in the browser and it has no sound. I still have to find an example of how to quit/exit a Godot program so that I can make it exit the game when hitting ESC in the PC version.
I don’t have a good solution for what to do when a player gets stuck. I would like to have them hit a button and get sent back to their original starting position. However, it seems that accessing the coordinates of a RigidBody2D is a no-no. The other thing I was thinking of is to make an explosion near the ship that is placed randomly – so the player might have to trigger it a few times until it knocks the ship in a way that allows the player to move again. I would think this is doable by making a point source “negative gravity” object that exists only for a short amount of time. Ah – but I don’t know how to do a lot of the things in that sentence.
I need to create a “racetrack” with some goal spots for each player – get to checkpoint #1, #2, #3 and so on. And then need to implement some kind of collision detection (I also haven’t done collision detection yet since all the physics works via magic) so that the game knows which checkpoints the player has hit and where the player has to go next.
I think that’s a good rundown for now, back to work!