Asteroids prototype

I created a GitHub repository for anyone to check my project:
paper-space-defold github repo

If you propose changes, please do it in small chunks for me to better digest information. I don’t want huge solution to everything. I want to understand what I’m doing, why this is better than that technique. etc…

This is a mess. I struggle with many concepts. Everything is fuzzy in my head and I feel lost in many aspects of the project.
I managed to spawn missiles from input release (SPACE bar on keyboard) but they appear on top of the ship and I can’t find a good way to fix it. I thought about attaching an empty game object to the neck of the ship sprite with a lower depth value and use its position as the spawn point instead of the ship game object position but I can’t attach a game object to another.
I also created a collection factory inside the main collection. I set it to start the title collection but I’m lost on how to change from collection to collection. Yes, I understand I have to unload the current one and load another one but how can I do that from a script inside a spawned collection?
As of now, I feel overwhelmed and desperate.

Using a bullet factory component on a child game object attached to the correct spawn point is a good solution.

You should turn your ship.go into a ship.collection. You are able to nest game objects when you are editing a .collection file. You can’t do that when you are editing a .go file.

You should have some kind of loader/controller collection that gets loaded first. This loader collection has collection proxies for your title screen and game screen. You put the load/unload code in the loader collection. When a script on the title screen wishes to transition from title to game screen you send a message to the loader and it will take care of the unload/load cycle. You can see this in the proxy example: https://defold.com/examples/collection/proxy

1 Like

Yes, I truly meant collection proxy instead of collection factory.

@britzl Based upon your suggestions, I’d prefer to attach a “bullets” factory to the ship game object instead of creating a “ship” collection. It seems easier.
Edit: Adding a factory component to the ship game object doesn"t solve anything since it doesn’t have any position properties. I forgot that detail.
If I set a “bullets” factory inside the “ship” game object at the position where I want the bullets to spawn, How can I make sure they spawn under the ship but in front of the background which only exists in the collection?

  • I created a new ship collection.
  • I added my ship game object (with its sprite, collision object+shape and its script) and I attached a new game object with a bullets_factory component to the ship game object.

How do I address a sub game object? I searched in that documentation adressing documentation but I couldn’t find anything about this.
Edit: I found a workaround by using absolute adressing. I don’t know if there is a better way…

ship_collection_structure

Also, how come the bullets_factory game object is in italics even if it’s added in place?

I resolved my problem about the missile not firing when I pressed other keys.
I used that code before:

self.left = action_id == hash('left') and not action.released
self.right = action_id == hash('right') and not action.released
self.up = action_id == hash('up') and not action.released
self.down = action_id == hash('down') and not action.released	
self.action = action_id == hash('action') and action.released 

And now I’m using this one:

if action_id == hash('left') then
	self.left = not action.released
end
if action_id == hash('right') then
	self.right = not action.released
end
if action_id == hash('up') then
	self.up = not action.released
end
if action_id == hash('down') then
	self.down = not action.released
end
if action_id == hash('action') then
	self.action = action.pressed
end

The self.action property is reset to false after a missile is created. All properties are also set to false in the init function.
@COCO as you can see, your code example was a good start that got me thinking.

OK, thanks to all your help, I managed to fix most of my bugs. I updated the itch page with the latest version.
Edit: I also updated the github repo for everyone to take a look.

Great work and it’s nice to see the process you went through. Learning how input works (…and coding in general) takes time and some parts of it don’t seem intuitive. But if you stick at it, you’ll realise how powerful and logical the system is. I like that you don’t have gravity like in the original asteroids. this is a nice controls system.

2 Likes

@88.josh thank you for your feedback.

If I have to tweak the amplitude of movements, tell me.

I think my major problem is to make sense of everything at the same time. I’ve got a general idea of the engine but I don’t understand it deeply so I make false assumptions. Learning a game engine in the context of a game jam may not be a good idea. However, it also forced me to dive deeper in Defold…

Jams are good cause they give you a goal and a deadline and that’s great for motivation! Hopefully it was an enjoyable experience and you’ve learned a lot. When I go over code (even when it’s something i wrote just 4 or 5 months ago), it always shocks me how bad and hacky it is.

1 Like

I’m not finished yet. I’m not even halfway through. I’m sure I’ll still need help from you awesome people!

It is absolutely a good idea! I joined (or tried to join) three jams and even though I failed to make anything worthwhile each time, it pushed me a lot more than if I was just coding at my own pace.

1 Like

Well, I don’t take too well stress from being lost in documentation emptiness.
But I guess when a jam is gently pushing my limits, it could be fruitful.

Now, I’m trying to make sens of the collection proxy component.

This is a test based on this loop:

I wrote this code:

function init(self)
	msg.post('.', 'acquire_input_focus')
	msg.post("#title_proxy", "load")
	self.state = 'title'
end

function on_message(self, message_id, message, sender)
	if message_id == hash("proxy_loaded") then
		msg.post(sender, "init")
		msg.post(sender, "enable")
	end
	if message_id == hash("load_game") then
		msg.post("#title_proxy", "unload")
		msg.post("#game_proxy", "load")
	end
	if message_id == hash("load_title") then
		msg.post("#gameover_proxy", "unload")
		msg.post("#title_proxy", "load")
	end
	if message_id == hash("load_gameover") then
		msg.post("#game_proxy", "unload")
		msg.post("#gameover_proxy", "load")
	end
end

function on_input(self, action_id, action)
	if action_id == hash('action') and action.pressed then
		if self.state == 'title' then
			self.state = 'game'
			msg.post('.', 'load_game')
		elseif self.state == 'game' then
			self.state = 'gameover'
			msg.post('.', 'load_gameover')
		elseif self.state == 'gameover' then
			self.state = 'title'
			msg.post('.', 'load_title')
		end
	end
end

But I got the following error:

The collection 'main' could not be created since there is already a socket with the same name.

What am I doing wrong this time?

If I want to create two instances of a game object from a factory, is it better to call factory.create twice or to send a message twice that would trigger a single call to factory.create each time?

This:

function on_input(self, action_id, action)
    if action_id == 'start' then
        msg.post('create_asteroid')
        msg.post('create_asteroid')
    end
end

function on_message(self, message_id, message, sender)
	if message_id == hash('create_asteroid') then
		factory.create(('#asteroid_factory', go.get_position(sender))
	end
end

or that:

function on_input(self, action_id, action)
    if action_id == 'start' then
        msg.post('create_asteroid')
    end
end

function on_message(self, message_id, message, sender)
	if message_id == hash('create_asteroid') then
		factory.create(('#asteroid_factory', go.get_position(sender))
		factory.create(('#asteroid_factory', go.get_position(sender))
	end
end

For the collection proxies, did you make sure your collections have different names? Click on the base of your collections in the Outline panel and check their name properties. You can’t have two loaded at once with the same name.

It is generally better to send fewer messages, for performance reasons. However, unless you’re sending lots of them every frame, it won’t be a problem, so it’s better to focus on organizing your code clearly. In this case it could be confusing if sending a “create_asteroid” message creates two asteroids instead of one.

1 Like

@ross.grams Awesome. I didn’t thought that the id of collections would make it clash. Now it works fine.
OK, I see your point. I’ll replace the message with a create_two_asteroids instead.
Thank you very much for the help.

1 Like

You could also do:

msg.post('create_asteroid', {count = 2})

and

if message_id == hash('create_asteroid') then
    for i = 1, message.count do
        factory.create(('#asteroid_factory', go.get_position(sender))
    end
end

This would allow you to create an arbitrary number of asteroids with a similar call in the future.

3 Likes

@Klear Yes, very good idea. For this simple game where only one or two game objects need to be created, it may be overkill but the concept is brilliant. Thank you.

I struggled to make a script from a loaded collection proxy send a message to the bootstrap proxies manager game object then I realised I checked action_id == 'start' instead of action_id = hash('start'). :slight_smile:
Those hash systems are beyond my comprehension. I don’t understand their purpose.

I also struggled to animate the alpha value of a sprite (I did it in a former project but I wasn’t able to find the information again).
I finally found the information in this thread. I don’t understand why that tint property isn’t listed in the sprite API.
Anyway, my title screen is almost finished. I update the itch page. If you have ideas about improving its layout or design, feel free to tell me. I’ll consider if I have the skills/time to change it.
Now, I have to take care of those asteroids…