Trying to implement explosions in Side scrolling tutorial

Hi all,

I continue my quest to produce a passable clone of the 194X type vertical shooter, based on the excellent Side-Scroller from Scratch tutorial.

My enemy planes are basically the stars from the original tutorial moving in a different direction.

My player plane spawns bullets which are basically stars moving in the opposite direction.

Currently I can detect the different collision types so that a enemy plane hit by a bullet produces an increase in score, and a red plane colliding with the player’s plane produces a huge reduction in score. I plan to change this to a loss of a life with four or five lives represented by images of the player’s plane near the top right of the screen.

I’ve tried to make the enemy planes disappear into an explosion (sprite borrowed from the War Battle tutorial).

I’ve tried using

lua
sprite.play_flipbook("#explosion", "explosion")

to play the sprite. The sprite is in the same atlas as everything else, including the enemy plane sprites.

The error message I get is:

Component ‘/instance0#explosion’ could not be found when dispatching message ‘play_animation’ sent from main:/instance0#red_plane

I checked the explosion sprite ID , it definitely explosion.

Obviously I am missing something important and/or fundamental.

Should I be treating the explosion sprite as just an extra animation added onto the enemy plane script or should I be creating them as a separate object, powered and created by their own factory?

Any help or suggestions welcome.

Thanks and regards

Frank

Try

msg.url('#explosion')

Can you show a screenshot of the Editor outline for the red plane game object?

1 Like

Note that in this call:

sprite.play_flipbook("#explosion", "explosion")

the first argument is not the animation name. It is the id/address of the sprite component that should play the animation.

So Defold is looking for a sprite component called explosion on your enemy game object:

/instance0#explosion

and the error means that this component does not exist (or is not named “explosion” in your project)

If your enemy plane has a sprite component called e.g. sprite (as default) , you probably want:

sprite.play_flipbook("#sprite", "explosion")

Please double check and show us the outline with the script and the sprite component in this game object.

2 Likes

Hi all,

Thank you all for your replies.

I have not been able to get the explosion sprite to play. I am (still) obviously doing something wrong. I’ve taken the easy way out and implemented the ParticleFx from the original Side Scroller Demo, and made it all Red. It still ‘flows’ in a leftward direction but that is not (that) important.

Can any one point me toward other Tutorials or examples that might help me sort out this kind of error?

Thank you all for helping. It is greatly appreciated.

Regards

Frank

If you want to make a shooter I have a tutorial with a horizontal one, so after making it, you can change the code and setup a bit to make it vertical easily, but most importantly you might get the addressing better:

If you want to understand it further, check out this manual:

and also my video:

2 Likes

Hi all,

Many thanks to everyone who has replied.

I’ve watched Pawel’s videos through about 3 times. I really struggle to get the ‘watching video’ and ‘doing stuff’ into the same brain space. How does everyone else do it? I’m thinking one dedicated computer for the video and one for the programming. I’ve got a couple of old laptops lying around that should be able to run Defold or stream Youtube, but not both at once.

That said: I got the project to the state of the game at the end of 2nd video. Then I broke everything somehow.

I don’t know how to make a video of it but I could upload the project to somewhere if anyone wants to look.

I added a second enemy type and put a couple of each on the screen.

This is what my defold main.collection looks like:

I can’t even do a screen grab fast enough to catch what happens next. The 3 enemy1 sprites, the flying saucers, all move down the play area, just like they had a movement update in their script, but there is no code to do that. their entire script looks like:

function on_message(self, message_id, message, sender)
	if message_id == hash("trigger_response") and message.enter then
		go.delete()
	end
end

The enemy2 objects use a script that looked the exactly the same and don’t move. WTH am I doing wrong?

Any help would be greatly appreciated.

Thanks and regards

Frank

Hi Frank. Could you check if their Collision Objects are set to dynamic? Because that’s the only reason I can think of without looking at the project that would explain this behavior.

1 Like

Hi all, especially illo.

Wow, yes, I had somehow changed the Collision Object back to dynamic. How, I don’t know. I would have never thought to look there.

One click of the mouse and a rebuild and it works perfectly. Now to make those damn aliens EXPLODE!

REgards

Frank

2 Likes

Glad to hear! As for those aliens, give 'em hell, lol!

Hi all,

I have exploding aliens. I will soon have exploding red_planes. Thank you all.

This has to be the best, most supportive online community that I’ve ever encountered.

Thank you all.

Regards

Frank

5 Likes

Hi all,

Disappointingly I don’t yet have exploding planes.

I’ve got the following two blocks of code supposed to be doing the detecting collisions and playing the explosion.

local function explode(self)
	
	self.speed = 0
	print("explosion")
	sprite.play_flipbook("#sprite", "explosion", function()
		-- go.delete()
	end)	
end

function on_message(self, message_id, message, sender)
	if message_id == hash("trigger_response") then
		print(message_id)
		print(message.other_group)
		if message.other_group == hash("bullet") then
			print("bullet hit red plane")
			explode(self)
			-- msg.post("main#gui", "add_score", {amount = score})
		elseif message.other_group == hash("plane") then 
			print("plane hit red plane")
			explode(self)
		end

		go.delete()
	end
end

The observant observer will notice a lot of print statements spuing out little bits of information. These are me trying to track what is happening.

Unfortunately I still don’t get the explosion animation to play.

When the line calling the animation in the function explode(self) is called as written (sprite.play_flipbook(“#sprite”, “explosion”, function()
end)

I get the error: component ‘/instance14#sprite’ could not be found when dispatching message ‘play_animation’ sent from main:/instance14#enemy_plane11

when I change the “#sprite” to just “#” I still don’t get an explosion but I don’t get the error message.

Does it matter that the enemy planes are being spawned by a factory. Is this interfering with the URL resolution?

Now I might still be missing something major. The explosion sprite exists in the main atlas for the project, right there with the two planes and the bullet sprites. It is called explosion. I’ve double checked that I haven’t transposed any letters. I even copy and pasted the name in the atlas into the code.

The explosion sprite does not have a game object or script file. From Pawel’s Demo on Youtube I am / was certain the sprite doesn’t need either of those.

Is it possible that this is a Z ordering issue? I’ve got a big blue (actually according to MSPaint Aqua 1) background sprite at Z order of zero. But if it was a Z-ordering issue I wouldn’t get error messages.

Any help or direction would be greatly appreciated. Thank you for putting up with my newb-ness.

Regards
Frank

Could it be that you renamed (changed the id field in the editor) your sprite component of plane game object?

If you post a screenshot of the plane game object outline pane it will be easier to help.

Hold on. You are playing a sprite animation AND deleting the game object containing the sprite? That explains why you don’t see the animation if the game object is deleted. Two solutions:

  1. Delay the call to go.delete() until after the animation has played (there is a callback you can add to sprite.play_anim())
  2. Delete the game object immediately and spawn an explosion game object. Delete this explosion object when the explosion animation has finished
1 Like

Hi all, and particular hi britzl

britzl wrote:

Hold on. You are playing a sprite animation AND deleting the game object containing the sprite? That explains why you don’t see the animation if the game object is deleted. Two solutions:

  1. Delay the call to go.delete() until after the animation has played (there is a callback you can add to sprite.play_anim())

Delete the game object immediately and spawn an explosion game object. Delete this explosion object when the explosion animation has finished

if I delete the final go.delete() the enemy plane sprite is not deleted, and can collide with both a bullet and the player plane.

If I leave a go.delete() in the explode(self) it doesn’t seem to make a difference.

I am wondering if the error message :

Component ‘/instance5#sprite’ could not be found when dispatching message ‘play_animation’ sent from main:/instance5#enemy_plane1

doesn’t contain a clue. The enemy_plane1 instances are created by a factory, and obviously the factory is attaching the ‘instanceX’ to the path that it uses to deal with the individual enemy_plane1.

I’ve tried creating an explosion_factory and calling that with a factory.create(component, p) but I got no positive result.

I hate to ask but is there somewhere I can upload the project to so that someone can review it in its whole and maybe work out what I’ve done wrong? The whole project runs into about 240 kb. The last screen shot I posted was 144kb.

Sorry to all for my stupid newbness.

Thanks and regards

Frank

When you create or respond to a message, there’s an upload icon. Just zip your project and upload it.

image

Hi all, and Andrew in particular,

Thanks for all the support. Here is my project. I assume I didn’t need to include the build folder, which somehow is several megabytes . I have previously made copies of projects deleted the build and been able to rebuild without any fuss.

Franks_194X.zip (164.6 KB)

None of the art is mine. I also haven’t implemented GUI or ParticleFX yet. I want to get this explosion problem sorted once and for all.

Thank you to everyone who has offered advice and support.

Regards

Frank

Hi.

In the on_message function of the enemy plane script, go.delete() is called immediately after detecting a collision, which removes the plane before any animation can play.

In enemy_plane1.go, the sprite component is named “enemy_plane,” so sprite functions need to reference “#enemy_plane.” Since this sprite has a scale of 0.3,0.3,1, the explosion animation appears very small, so the sprite scale should be adjusted before swapping the animation.

The updated script includes an init function with a self.dead variable, which is set to true once the ship is hit to prevent bullets from retriggering the explosion.

local speed = -200
local score = 10

function init(self)
	self.dead = false
end

local function explode(self)
	
	print("explosion")
	self.speed = 0

	-- scale sprite
	go.set("#enemy_plane","scale.xy",vmath.vector3(2,2,1))

	-- play anim and delete object once finished
	sprite.play_flipbook("#enemy_plane", "explosion", function() go.delete() end)
	
end

function update(self, dt)
	local p = go.get_position()
	p.y = p.y + speed * dt
	if p.y < -32 then
		go.delete()
	end
	-- print("should display")
	go.set_position(p)
end

function on_message(self, message_id, message, sender)
	if message_id == hash("trigger_response") then
		print(message_id)
		print(message.other_group)
		if message.other_group == hash("bullet") and self.dead==false then
			print("bullet hit red plane")
			self.dead = true
			explode(self)
			-- msg.post("main#gui", "add_score", {amount = score})
		elseif message.other_group == hash("plane") and self.dead == false then 
			print("plane hit red plane")
			self.dead = true
			explode(self)
		end
	end
end
3 Likes

hi all, and Andrew_Fowler in particular,

THANK YOU. I think I understand your solution. The sight of exploding red planes has never been so sweet.

I didn’t realize the enemy plane scaling would be carried over. Something I will need to keep in mind.

Again THANK YOU to everyone who has helped me get to this point.

Regards

Frank

2 Likes

You probably don’t want you player plane to survive a crash with an enemy either :slightly_smiling_face: .

The animation is pretty short, so you can simply delete the plane when it collides (add this to the player.script):

function on_message(self, message_id, message, sender)
	if message_id == hash("trigger_response") then
		if message.other_group == hash("enemy1") then 
			print("red plane hit player plane")
			go.delete()
		end
	end
end

Or, just like for the enemy, maybe play a different animation.