#how do we implement explosions in Godot 2d that do stuff(eg. damage)

174 messages · Page 1 of 1 (latest)

austere mesa
#

just use an Area2D/3D where the explosion is happening and deal damage to any overlapping objects

iron steppe
#

because then you would be able to do damage through walls and stuff

#

thats what i thought of too actually

violet wadi
#

what i usually do is add a raycast at the center thats the same length as the radius of the explosion, and have it loop through every overlapping body and check if the raycast result is that body, if it is apply damage. if its not, do nothing

reef remnant
#

basically what I was about to say

iron steppe
#

ty

violet wadi
#

yea its a useful thing to learn, good for not letting players pick up objects through walls, and for vision cones not seeing thru stuff

reef remnant
#

(I stuck with the alternative because it provided better results for light detection, but it's heavy on performance)

violet wadi
#

you can create a new raycast per target, or reuse the same raycast and call force_raycast_update() every time it gets_collider()

#

before it gets_collider(), rather

iron steppe
#

btw do we use autoloads for functions we want to use through the code, so say i want to use the explosion function, i would pass in coords and radius and i want to use it anywhere in the code

#

i would use globals right

violet wadi
violet wadi
#

so its like Global.create_explosion(radius, position) which can be called from anywhere

iron steppe
#

the actual script name doesent matter when we use globals right

violet wadi
#

yeah you can set it to be anything

normal badge
#

reduces the messiness of needing to do lots of things through an external node

iron steppe
#

like say i made a grenade

#

also how do we make global nodes for the area2d and ray casts required

iron steppe
normal badge
#

if you're queue freeing it, then you'd still need to instantiate it, and can do so in the player
get_tree().current_scene.add_child()
is how you'd put it in the scene

#

then that also puts the preload in the player, which is pretty sensible

#

or you could even export a packed scene

#

can't do that with an autoload

reef remnant
#

I think the idea is that several things may want to do explosions, so they want to implement it in an autoload to make life as easy as possible

iron steppe
#

but i still need to add it as a child of something for it to work right

#

i added it as a child of the autoload but that doesent work

reef remnant
#

What's the issue?

iron steppe
#

i made an explosion class and am testing it rn
func explode():
print("called explode")
get_node("Explosion area").get_node("explosion radius").get_node("Shape2D").radius = radius
var bodies = get_node("Explosion Area").get_overlapping_bodies()
print(str(bodies))

#

i put the explosion radius really high (50 pixels), the game is pixel art so that should be enough. i make a new explosion every time a player dies

#

so i killed on of the players, but it doesent print anything

reef remnant
#

Oh, a quick tip. Often a better way to get child nodes like that is with an @onready variable:

iron steppe
#

oh nvm, it seems the method isnt getting called at all

reef remnant
reef remnant
#

Then you can just refer to explosion_shape instead of the big string of .get_node() calls

iron steppe
#

i forgot about that 💀

reef remnant
#

But anyway, onto the actual problem, what's the code that the player uses to create the explosion

iron steppe
#

func die():
print(name + " died")
Global.explosion(position, 30)

reef remnant
#

And you're seeing it print the died message?

iron steppe
#

i can see the died in the output

#

yes

reef remnant
#

Okay, so let's look at the function in the Global autoload

iron steppe
#

@onready var explosion_class = preload("res://explosion.tscn")
func explosion(position: Vector2, radius: float):
var explosion = explosion_class.instantiate()
explosion.radius = radius
explosion.position = position

reef remnant
#

Mhm. So, does the explosion script call the explode() function at any point?

#

Or does that need to be called from outside?

iron steppe
#

oh lol

#

wait i added it lemme see if it works

#

atleast it calls it now

#

explosion_shape.radius = radius

#

its claiming that the object is of type nil

reef remnant
#

What's the tree structure of the explosion scene?

iron steppe
reef remnant
#

Ah, right

flint lily
#

You can use a shapecast that does not change its position and checks for anything, if found then it damages the enemy

reef remnant
#

Knowing that, you actually want to do the following:
@onready explosion_shape = $Explosion Area/explosion radius
And then:
explosion_shape.shape.radius = radius

flint lily
#

I'm not really good at explaining

reef remnant
flint lily
reef remnant
flint lily
iron steppe
#

it gives me an error if i dont use quotation marks

reef remnant
reef remnant
reef remnant
iron steppe
#

anyway its still showing nil

reef remnant
#

What thing is it saying is nil?

iron steppe
reef remnant
#

Hm. Could be an issue with order? What does your explosion() function inside the autoload look like now?

iron steppe
#

func explosion(position: Vector2, radius: float):
var explosion = explosion_class.instantiate()
explosion.radius = radius
explosion.position = position
explosion.explode()

reef remnant
#

Oh, you haven't actually added it to the tree

#

You'll need to use add_child somewhere to do that

#

If you don't add it to the tree, then it never actually readies itself

iron steppe
reef remnant
#

After

iron steppe
#

but since its an autoload, what will it be a child of

reef remnant
#

The explosion could be a child of the autoload itself (that's totally fine, since an autoload is just a node)

#

There are other options, but for now that should work

#

I think the ideal is probably adding it as a child of the current level, so that it'd be removed when the level is unloaded

#

You can get the current scene using get_tree().current_scene

iron steppe
#

but it still doesent add my tank in the bodies hit

#

P2 died
bodies hit []

reef remnant
#

Check the collision layers?

iron steppe
#

all are on 1

reef remnant
#

You can tick "Visible Collision Shapes" so you can see the area's shape appear

#

That might help with debugging?

iron steppe
#

ohh, i didnt know that was an option

#

ill go ahead and do that

#

yep its quite big

#

bigger than the screen infact

reef remnant
#

As an alternative to using .get_overlapping_bodies(), you could use the body_entered signal?

#

It might be the case that you're asking the area for overlapping bodies before it's gotten a chance to check for them

reef remnant
#

Yeah, that kind of thing can happen in some cases

iron steppe
#

how would i impliment it with the body entered signal, have an array and append it for every time the signal is called?

reef remnant
#

You could, or you could just apply the effect inside the on_body_entered implementation

iron steppe
#

oh right

reef remnant
#

No need to maintain a list in most cases

iron steppe
#

oh ok nice it lists the bodies now

reef remnant
#

:D

iron steppe
#

wierd, i implimented the damage function in it

#

func _on_explosion_area_body_entered(body: Node2D) -> void:
print(str(body))
if(body is TANK):
body.damage()

#

and it just drains all the hp and destroys the game

#

like literally hangs it

#

ahh

#

i got it

#

since i do damage but dont delete the tanks when they die

#

they just keep killing each other using explosions

reef remnant
#

Oop

iron steppe
#

nice the explosion finally works

#

tysm

reef remnant
#

Glad to hear!

#

I remember you wanted to make it not hit things behind walls?

iron steppe
#

tbh i feel like i should have started with either using unity or godot with C#, since i aldready knew java and C# is apparently just microsoft flavor java

reef remnant
#

mm..

#

Godot does support C#

#

But not fully, to a degree

iron steppe
#

yeah i think now that ive started with GDscript im just going to continue

reef remnant
#

I know there's issues with web builds when using C#, for instance

iron steppe
#

oof, still godot better than unity cuz open source

reef remnant
#

Which, for me, was an instant massive issue.

#

GDScript is a perfectly good language

#

And not hard to learn

#

I think it fits Godot well

iron steppe
reef remnant
#

For me, until Godot C# has support for web builds, I can't even consider using it. Web builds are just too important for the things I do (almost entirely game jams)

iron steppe
reef remnant
#

That and, I've become really comfortable with GDScript at this point

iron steppe
#

so it might be worth holding out

#

seriously though interfaces are like quite a common thing

#

weird that they arent in godot

reef remnant
#

I get what you mean, but they're kind of unnecessary because of the philosophy of the language.

iron steppe
#

wdym

reef remnant
#

Kind of. They'd still have uses, of course.

#

In GDScript, the idea is that you don't care so much whether a certain object implements an interface or is of a certain class, you care about what it can do. If you want to damage it, just check if it can be damaged, no need to check if it's a player or an enemy or what have you. That's why you have stuff like the has_method() function

#

Of course, that's not the entirety of the language's philosophy.

iron steppe
#

cuz you might name it slightly different accidentally in some classes

#

or might forget to impliment the function

#

but ig it works

reef remnant
#

Godot really isn't meant for huge games

#

Stuff like that becomes more important as scale increases

#

But with smaller games and smaller teams, stuff like that is much easier to just go in and fix

iron steppe
#

fair ig, but you shouldnt be needing to fix it in the first place

reef remnant
#

With an interface, you can still forget to implement the interface, or one of the functions

#

If the argument is "you could forget to do something", then that can always happen

#

I'm not saying it's a perfect system. Interfaces would have uses.

#

But you honestly get used to it

normal badge
reef remnant
#

Or including them as parameters (probably with default values)

iron steppe
#

but atp idc, i aldready implimented the global so i might as well use it

#

im new to godot so some of my structuring decisions do end up a bit weird

#

but we improve with time

#

👍

normal badge
#

just wanted to share some ideas, but yea, anything works if it works

normal badge