I made the parent a canvas later so that it would follow the player as they move through the level.
The issue is when I instantiate the scene on the level the bubbles keep spawning on the same static positions. I tried adding the instance as a child of a canvas layer on the main scene and that did make the spawn points follow along but also the bubbles as they move with their position always relative to the player so they’re impossible to catch.
(I thought the get_parent().add_child() I added on the spawner solved this by making them a child of the root once spawned but it doesn’t seem to be working)
Is there a way to solve this?
My other issue is that I have two spawn points to the right and two to the left
I wanted the bubbles that spawn on the left to travel right and vice versa
func _physics_process(delta):
if moving == true:
# Move balloons based on spawn position
if Vector2.RIGHT:
global_position.x -= bubble_speed * delta
elif Vector2.LEFT:
global_position.x += bubble_speed * delta
I originally did it by a check if global_position.x > 0: and else:
but logically the bubbles were getting stuck when they got to 0 on the x axis, and I want them to keep moving until they leave the screen.
I solved this with the code above but… now the ones on the left also travel rightwards
Any clues how to solves these issues?
Many thanks!
That’s the source of your troubles. CanvasLayer is like a transparent film stuck to the front of the camera. Anything that you attach to that will remain in the same position just like a fly stuck to the film. Only use CanvasLayer for UI elements.
So change from CanvasLayer to Node2D. Then to have the camera follow the player, just add node of type Camera2D as child of your player node.
Thank you for your reply! The problem is not the camera not following I already have that
The issue is that I want the bubbles to spawn from the sides at all times and I wanted to avoid to create innumerable spawn points across the level so I created the scene and added it to a canvas layer so that it would “follow” the player
Right. But anything you add to a canvas layer cannot move… it will forever stay in the same location because it’s not actually in your level/world, if that makes sense. It’s stuck to the lens in front of the camera like a fly or a speck of dirt.
You must add the spawn markers to your Level scene or w/e it’s called. The same one that Player is a child of.
Here’s my code for generating enemies around the player just outside the visible area. Feel free to use/modify to suit your needs if you are tired of markers
func _generate_spawn_coords() -> Vector2:
# randomize whether enemy spawns on the left or right side of the map
var side_x = -1
if randi_range(0,1) == 1:
side_x = 1
# randomize whether enemy spawns in the top or bottom of the map
var side_y = -1
if randi_range(0,1) == 1:
side_y = 1
var margin = 25 # half of biggest enemy's width/height, todo: pass enemy size as parameter
var spawn_area_size:int = 20
# only spawn outside visible area
# half of screen + a little margin = nearest allowed distance for spawn
var screen_edge_x: int = int(get_viewport().size.x / 2)
var screen_edge_y: int = int(get_viewport().size.y / 2)
var x: int
var y: int
# flip a coin on whether x or y axis will start from 0.
# we can't start both from 0 b/c then the enemy will apear within visible screen
# i.e. either x or y must be > (viewport.size / 2)
var edge_coin_flip: bool = randi_range(0,1)
if edge_coin_flip:
# free the x coord range but restrict y coord range
# this spawns enemy outside top or bottom screen edge
# so x can be 0 -> screen edge, but y must be > screen edge so enemy is invisible
x = randi_range(0, screen_edge_x + spawn_area_size)
x = x * side_x
var min_y = screen_edge_y + margin
y = randi_range(min_y, min_y + spawn_area_size) * side_y
else:
# enemy will spawn beyond left or right edge of the screen
# y can be between 0 and height of screen + height of spawn area,
# but x must be large to put enemy outside of visible area
y = randi_range(0, screen_edge_y + spawn_area_size)
y = y * side_y
var min_x = screen_edge_x + margin
x = randi_range(min_x, min_x + spawn_area_size) * side_x
return Vector2(Game.player.global_position.x + x, Game.player.global_position.y + y)
Right. Apologies! I’m no programming genius and very new at this so my logic is often wonky.
I did it this way cause i followed a tutorial for another type of game where they created a square path out of the camera bounds and then generated a random number on the progress to spawn enemies from there and it was set to a canvas layer so it was always following the player around so I thought I could do something similar but this was set on the level itself instead on a separate scene so maybe that’s the reason it won’t work
That’s very kind of you to share your code! I’ll take a closer look later but at a glance this appears to be beyond my league but I can surely take or learn something,
Thanks again!
Maybe they used the markers that were on canvas layer to get their .global_position property to get a position where bubble should be spawned, but once they spawned the bubble, they added it to the Level/main scene, not canvas layer? Then it would make sense.
As long as you want bubbles to spawn randomly on any side of the screen (just outside visible edge), you can just do:
var my_new_bubble.global_position = _generate_spawn_coords()
The bubble will get a position that’s between 20 and 45 units away from the randomly-picked edge of screen. If you want them to spawn closer, play with those values or set them to negative values if you want bubbles to spawn within visible area (i.e. what camera sees).
Then at the end, replace Game.player with your reference to the Player object. I have a an autoloaded singleton called Game that stores reference to player, but ofc your app’s structure may be different.
Finally, if you want want bubbles to only spawn on left and right sides of screen, change
var edge_coin_flip: bool = randi_range(0,1)
to
var edge_coin_flip: bool = false #randi_range(0,1)
And ofc for only top/bottom edges, just true instead of false.
Exactly! This is what get_parent().add_child() was supposed to do, as soon as it spawns add it to the root node as a child to make it independent. But I guess since it was built in the main scene and not an instance it worked as intended.
Thanks for the help!
FYI I managed to solve it by just adding the marker2d spawn points and making them a child of the player on the main scene
The ones on the left are still travelling right for some reason but I think I can figure out a way around it.
Thanks for the help!