Looks like you're not logged in

Login or Register to continue

Lesson Q&A

Use this space for questions related to what you're learning. For any other type of support (website, learning platform, payments, etc...) please get in touch using the contact form.

  • Buggy shadow tween due to missing pivotsNPGameDevHey Nathan, I was trying to create the code for the bird hopping and, due to not setting the pivot correctly, the shadow was shifting "weirdly" because it was losing its local position offset relative to the bird. The same behaviour is there for the script provided above, so I'd assume it is intentional to use the tween that way, without having to track the position offset manually but instead using the Sprite2D > Offset property when setting it up in the scene. I was a bit confused for a while until looking into the solution from the completed lessons. Looking at the hints for a fix to the shadow issue didn't help, as there was no mention of said necessary offset, that's why I ended up addressing it via code on my solution, until I realized about it in the solution scene. As a suggestion, could you add a Hint or something that points towards the Offset as a requirement for the setup? Otherwise, it is easy to miss it and the script will make the shadow look really weird because it's actually written with the assumption of that Offset. Thanks for all the cool scripts! 9 6 Mar. 25, 2024
  • I challenge yall to tween the bird flipping directions when jumping to the rightShaneIf anyone's interested I think this is a pretty simple extra challenge, try animating the bird flipping to face the right when jumping to the right, and switching back to facing left when jumping left. The solution I came up with is: `var tween = create_tween()` `if land_position.x > position.x:` `tween.tween_property(sprite2d, "scale:x", -1, 0.3)` `else:` `tween.tween_property(sprite2d, "scale:x", 1, 0.3)` 24 4 Apr. 04, 2024
  • Awesome Challenge!AJ Studios"Making a bird that hops around" has been a great challenge. In the end I had to look at the code since I couldn't get it right on my own however, that made me read the code several times and it helped me make more sense of how it works. I'm looking forward to more challenges like this one. 7 3 Apr. 12, 2024
  • Sharing script functions across scriptssalty-dinosaurI'm coming from Javascript land where importing and exporting functions is a breeze. Is there something similar in GDScript? My question is: because I'm re-using the `is_left_click` logic check across multiple scripts, I'd like to see how I could refactor this check into a reusable getter function that I can then do as something like... ```gdscript var is_left_click = get_was_left_mouse_clicked() ``` This would remove multiple lines of repeated code and ensure the clicking logic only lives in one place. If I'm understanding Godot correctly, I suppose one solution would be to create a new parent node with this function that is the root for any node I want to be left-clickable? 3 1 Sep. 06, 2024
  • How to Add Item Clicked Counter?Owl KnightSince the item script is shared between randomly instantiated array scenes, which themselves are nested decently far from the main scene (mini_dungeon), I am a bit confused. How can I connect a signal from the item.gd script to the mini_dungeon scene? I am assuming/using a setup where I have added a Label as a child of mini_dungeon and want to update the text within to display the current count of items clicked MiniDungeon `extends Node2D` `var count: int = 0` `@onready var item_count: Label = $ItemCount` `func _on_add_count() -> void:` ` count += 1` ` item_count.text = str(count)` 3 1 Jul. 11, 2024
  • tween property selfMainzelHi there, maybe I didnt read everything right but was there a section where you told us about the self parameter? I tried to do the dissapearing / clicking task with: tween.tween_property(----, "scale", Vector2(0, 0), 0.3) but had no idea what to insert in ---- until I saw the solution with "self" as the answer. Maybe you could clarify that for me (sry for bad english) 5 1 Jun. 07, 2024
  • Solved it slightly differently..are there any disadvantages to doing it this way?inferior-gnat```gdscript extends Node2D @onready var area_2d: Area2D = $Area2D @onready var timer: Timer = $Timer @export var min_movement_distance := 60.0 @export var max_movement_distance := 120.0 @export var jump_height := 10.0 @export var anim_duration := 0.4 var flight_anim_duration: float: get: return anim_duration / 2 func _ready() -> void: timer.timeout.connect(wander) func wander() -> void: var distance := randf_range(min_movement_distance, max_movement_distance) var direction := Vector2(1.0, 0).rotated(randf_range(0.0, deg_to_rad(360.0))) var target_position: Vector2 = direction * distance var land_position: Vector2 = position + target_position var tween := create_tween().set_parallel() tween.tween_property(self, "position", land_position, anim_duration) tween = create_tween().set_trans(Tween.TRANS_QUAD).set_ease(Tween.EASE_OUT) tween.tween_property(area_2d, "position:y", area_2d.position.y - jump_height, flight_anim_duration) tween.set_ease(Tween.EASE_IN) tween.tween_property(area_2d, "position:y", area_2d.position.y, flight_anim_duration) ``` This was my solution. I handled the ground movement at the parent level, since the bird and shadow have to move to the same spot anyway. I then just tweened the jump anim on the child Area2D. Curious whether there are any disadvantages to doing it this way? 1 1 Jun. 07, 2024
  • How to use the offset function?humble-pelicanRegarding the offset of the shadow, I would like to ask how to use this function? Because I did not see the offset function in the solution code provided, my code is written like this, but I would like to know how to write it using the offset function, thank you ```gdscript var tween := create_tween().set_parallel() tween.tween_property(sparrow,"position:x",land_position.x,JUMP_DURATION) tween.tween_property(shadow,"position",Vector2(land_position.x-5,land_position.y+15),JUMP_DURATION) ``` 2 1 May. 29, 2024
  • tween confusionStonemonkeyI don't quite get how the tweens work. I tried experimenting but I don't get the results I was expecting. Here one of the things I was trying to do is move the sprite in a "V" movement. Instead the x movement is being combined so the sprite moves to the 900 position in one movement. This is part of my confusion with how the animations we have done is split up between the x and y movement. Does `create_tween()` stop the first `set_parallel` ? So that the next set of movement can happen sequentially for example. ```gdscript extends Node2D @onready var sprite_2d: Sprite2D = $Sprite2D func _ready() -> void: generic_animation() func generic_animation(): #The bird sprite is manually placed in the scene at (546, 266) var tween = create_tween() tween.set_parallel() tween.tween_property(sprite_2d, "position:x", 700.0, 2 ) tween.tween_property(sprite_2d, "position:y", 400.0, 2 ) # #tween = create_tween() ##tween.set_parallel() #tween.tween_property(sprite_2d, "position:x", 900.0, 2 ) #tween.tween_property(sprite_2d, "position:y", 200.0, 2 ) ``` 3 1 Apr. 22, 2024
  • Another solution for shadowsTai921```gdscript extends Node2D @onready var wait_time : Timer = $Timer @onready var bird:Sprite2D = $Sprite2D @onready var Shadow:Sprite2D = $Shadow # Called when the node enters the scene tree for the first time. func _ready() -> void: wait_time.wait_time = randf_range(1.0,3.0) wait_time.one_shot = true wait_time.timeout.connect(_on_jump) wait_time.start() pass # Replace with function body. # Called every frame. 'delta' is the elapsed time since the previous frame. func _process(delta: float) -> void: pass func _on_jump() -> void: const FLIGHT_TIME := 0.4 const HALF_FLIGHT_TIME := FLIGHT_TIME / 2.0 # 取得亂數位置 / Get random position var random_angle := randf_range(0.0, 2.0 * PI) var random_direction := Vector2(1.0, 0.0).rotated(random_angle) var random_distance := randf_range(5.0, 10.0) var land_position := random_direction * random_distance var tween := create_tween().set_parallel() #鳥移動到哪裡,影子就移動到哪裡 / Wherever the bird moves, the shadow moves tween.tween_property(bird, "position", land_position, FLIGHT_TIME) #針對影子進行額外的計算 / Perform additional calculations for shadows tween.tween_property(Shadow, "position", Vector2(land_position.x - 6.0, land_position.y + 15.0), HALF_FLIGHT_TIME) #print("land_position.y + shadow_offset.y = " , land_position.y + shadow_offset.y) #讓鳥跳起來 / make the bird jump const jump_heright = 16.0 tween = create_tween().set_trans(Tween.TRANS_QUAD).set_ease(Tween.EASE_OUT) tween.tween_property(bird,"position:y", land_position.y - jump_heright, HALF_FLIGHT_TIME) tween.tween_property(bird,"position:y", land_position.y, HALF_FLIGHT_TIME) tween = create_tween().set_trans(Tween.TRANS_QUAD).set_ease(Tween.EASE_OUT) tween.tween_property(Shadow, "scale", Vector2(0.5, 0.5), HALF_FLIGHT_TIME) tween.tween_property(Shadow, "scale", Vector2(1.563, 0.977), HALF_FLIGHT_TIME) wait_time.wait_time = randf_range(1.0,3.0) tween.finished.connect(wait_time.start) pass ``` This is a fun challenge! 1 1 Apr. 20, 2024
  • Confused about Bird SolutionshadowI think it doesn't really matter because the birds are sort of decoration in this case (and maybe I'm reading it incorrectly) but doesn't the provided solution mean that we're never actually moving the bird ***object*** itself, but only relocating its associated shadow ***sprite*** and bird ***sprite***? In its current state it seems like the bird object is actually more of a bird controller object where the "bird" is sort of being moved independently of the object that contains it. What I did instead is I tweened the "offset:y" and the "scale" of the shadow: ```gdscript var shadow_scale := shadow.scale var tween := create_tween() tween.tween_property(self, "position:x", random_spot.x, hop_time) tween = create_tween() tween.set_trans(Tween.TRANS_QUAD) tween.set_parallel() tween.set_ease(Tween.EASE_OUT) tween.tween_property(shadow, "offset:y", 18.0 + (hop_height * 2.0), half_hop_time) tween.tween_property(shadow, "scale", shadow_scale * 0.75, half_hop_time) tween.tween_property(self, "position:y", random_spot.y - hop_height, half_hop_time) await tween.finished tween = create_tween() tween.set_trans(Tween.TRANS_QUAD) tween.set_parallel() tween.set_ease(Tween.EASE_IN) tween.tween_property(shadow, "offset:y", 18.0, half_hop_time) tween.tween_property(shadow, "scale", shadow_scale, half_hop_time) tween.tween_property(self, "position:y", random_spot.y, half_hop_time) ``` This solution could definitely be improved on, but I think for now it gives me a pretty decent hop and keeps the shadow separate from the body during movement, while also keeping the bird's sprite location tied to the location of the bird object This would be important if it was an enemy, I think. Again, I could be totally wrong on this, but this is what I came to. 3 1 Apr. 17, 2024
  • My birds seem to get yeeted to a specific position before hoppingMartinBTried to set this up so that my birds at random intervals will do a little hop, sometimes they'll hop very soon after hopping and other times they'll wait a bit. But for some reason before they start hopping, they fly over to the top left, and then start hopping. `func sparrow_hop() -> void:` `const FLIGHT_TIME := 0.1` `const HALF_FLIGHT_TIME := FLIGHT_TIME / 2` `var random_angle := randf_range(0.0, 2.0 * PI)` `var random_direction := Vector2(1.0, 0.0).rotated(random_angle)` `var random_distance := randf_range(1.0, 15.0)` `var jump_height := 10.0` `var landing_position := random_direction * random_distance` `var tween := create_tween().set_parallel()` `tween.tween_property(sparrow, "position:x", landing_position.x, FLIGHT_TIME)` `tween = create_tween()` `tween.tween_property(sparrow, "position:y", landing_position.y - jump_height, HALF_FLIGHT_TIME)` `tween.tween_property(sparrow, "position:y", landing_position.y, HALF_FLIGHT_TIME)` `func _on_hop_timer_timeout():` `sparrow_hop()` `hop_timer.wait_time = randf_range(0.1, 4.0)` 4 1 Apr. 01, 2024
  • Torch: Variable defined under input function is removed? VerryHello! I love the solution with using `var = not var`, though I'd like to know what happens under the hood, so I defined `if` statement, where I change `torch_active` state. My question is: It seems that the flame doesn't turn back on when the var `torch_active` is defined under the `if` statement (commented line 20), in the `_input_event()`. It has to be defined outside all functions, of course at the beginning of the script. I have an explanation for it, but I'd like to know if I'm correct, please. My understanding is that when any variable is defined under `_input_event()` (or other event function), it is defined when mouse clicks (in this example), but after that happens, it's removed/forgotten? So it cannot get changed, checked again, etc. Thank you! ```gdscript extends Area2D @onready var flame: Sprite2D = $Flame var torch_active : bool = true func _ready() -> void: # This parameter of the shader material gives each flame a slightly different look and randomized animation. flame.material.set("shader_parameter/offset", global_position * 0.1) func _input_event(viewport: Viewport, event: InputEvent, shape_idx: int) -> void: event = event as InputEventMouseButton var torch_clicked : bool = ( event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT and event.is_released() ) if torch_clicked: #var torch_active : bool = true if torch_active: flame.visible = false torch_active = false else: flame.visible = true torch_active = true ``` 1 0 Sep. 18, 2024
  • Navigating to scripts not in the Top-Left hierarchy enraged-manateeHi, Today, I was trying to complete the resize challenge above without looking at any hints. I knew, I'd have to edit the item script. But my problem was, no matter how I drilled down in the DungeonGame scene, I could not find the item.gd anywhere. Did we create the item.gd script in a prior lesson? I don't remember doing that, and couldn't find it. Figured I'd have to create one. But then I got stuck figuring out how to reference the items packed scenes in a new script. I finally gave up and peeked at the hints above to see that items.gd already existed. Anyway, I know if I have orphaned scripts laying around, I'll lose them. is there a way to find Items.gd by drilling down from the MiniDungeon scene? Hope I'm making sense.. Thanks 1 0 Sep. 17, 2024
  • Prevent items overlapping challengePaulI was interested in the problem of stopping the items overlapping, so decided to take this on as a challenge. I've introduced some new code into the spawn function to try to get this to work, but after some time of fiddling it's not working so if there's any guidance on what I could look into that would be superb. The function is below. My hope was to loop from the position, and an area around the position. If a match was found on the x & y axis, it would generate a new land_position until it was clear by the given amount (100 in the code below). In this current form, this would only work for 2 items, so I suppose I would need to store each instance's position in an array, and loop around those or something as well. I'm sure there's a much better way of achieving this! It was good practice writing loops and such though so, hopefully wasn't wasted time even if it is a load of rubbish. ```gdscript func _spawn_random_loot() -> void: var last_land_position := Vector2(0.0, 0.0) var land_position := Vector2(0.0, 0.0) var same_x_area := true var same_y_area := true var loot_item: Area2D = possible_items.pick_random().instantiate() add_child(loot_item) while same_x_area and same_y_area: var random_angle := randf_range(0.0, 2.0 * PI) var random_direction := Vector2(1.0, 0.0).rotated(random_angle) var random_distance := randf_range(60.0, 100.0) land_position = random_direction * random_distance for last_land_x in range(last_land_position.x - 100, last_land_position.x + 100): if land_position.x == last_land_x: same_x_area = true break else: same_x_area = false for last_land_y in range(last_land_position.y - 100, last_land_position.y + 100): if land_position.y == last_land_y: same_y_area = true break else: same_y_area = false last_land_position = land_position same_x_area = true same_y_area = true const FLIGHT_TIME := 0.4 const HALF_FLIGHT_TIME := FLIGHT_TIME / 2 var tween := create_tween() tween.set_parallel() loot_item.scale = Vector2(0.25, 0.25) tween.tween_property(loot_item, "scale", Vector2(1.0, 1.0), HALF_FLIGHT_TIME) tween.tween_property(loot_item, "position:x", land_position.x, FLIGHT_TIME) tween = create_tween() tween.set_trans(Tween.TRANS_QUAD) tween.set_ease(Tween.EASE_OUT) var jump_height := randf_range(80.0, 150.0) tween.tween_property(loot_item, "position:y", land_position.y - jump_height, HALF_FLIGHT_TIME) tween.set_ease(Tween.EASE_IN) tween.tween_property(loot_item, "position:y", land_position.y, HALF_FLIGHT_TIME) ``` 8 0 Sep. 17, 2024
  • Hoppingrewarding-chimpanzeeI seem to have a problem with the bird hopping, when I run the main scene (there are 3 birds in it ) they all seem to jump at the start of the scene all at once and then at the set random intervals my Timer node is setup in the inspector maybe it gets the values at wrong orders or smth. My script for the bird : ```gdscript extends Node2D @onready var sprite_2d: Sprite2D = $Sprite2D @onready var timer: Timer = $Timer func _ready() -> void: timer.wait_time = randf_range(2.0, 8.0) func _on_timer_timeout() -> void: hop() func hop() -> void: const HOP_TIME := 0.35 const HALF_HOP_TIME := HOP_TIME / 2.0 var random_angle := randf_range(0.0, 2.0 * PI) var random_direction := Vector2(1.0, 0.0).rotated(random_angle) var random_distance := randf_range(10.0, 35.0) var land_position := random_direction * random_distance var jump_hight := randf_range(15.0, 25.0) var tween = create_tween() tween.set_parallel(true) tween.tween_property(sprite_2d, "position:x", land_position.x, HOP_TIME) tween.set_ease(Tween.EASE_OUT) tween.set_trans(Tween.TRANS_QUAD) tween.tween_property(sprite_2d, "position:y", land_position.y - jump_hight, HALF_HOP_TIME) tween.set_ease(Tween.EASE_IN) tween.tween_property(sprite_2d, "position:y", land_position.y , HALF_HOP_TIME) if sprite_2d.position.x >= land_position.x: sprite_2d.flip_h = false else : sprite_2d.flip_h = true ``` 1 0 Sep. 17, 2024
  • A few question after completing the bird hopping challengeVertPingouinAfter making my birds hop, I got the hop of the two birds I added synchronized with a repeating timer. After looking up the complete code, I'm puzzled about the fact that the birds seems both to have their own timer with different wait_time. But there is only one timer, how can this be ? Another thing I don't quite get : after letting my birds hop freely for a long time, I expected them to go away randomly offscreen but they seem stuck to their start position (which is good indeed but I can figure out why). 4 0 Sep. 13, 2024
  • Note about the phrase "divide and conquer"raincloudThe phrase is commonly used within Western countries to refer to the process of breaking a project into smaller tasks, and in some cases allocating those tasks between members of a team. However, the phrase originates with brutal colonialist tactics that involve exploiting divisions within a colonized people in order to subjugate them. Folks taking this course who live in formerly (or currently) colonized territories may find the original meaning more apparent, and painful, than the meaning you're intending. I would encourage you to choose a different phrase. 1 0 Sep. 07, 2024
  • Lighting the torch againServin```gdscript func _input_event(Viewport: Node, event: InputEvent, shape_index: int) -> void: var event_is_mouse_click: bool = ( event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT and event.is_pressed() ) if event_is_mouse_click: flame_invisible() var event_is_right_click: bool = ( event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_RIGHT and event.is_pressed() ) if event_is_right_click: flame_visible() func flame_invisible() -> void: var tween = create_tween() tween.tween_property(flame, "scale", Vector2(), 3) tween.finished.connect(flame.queue_free) func flame_visible() -> void: var tween = create_tween() tween.tween_property(flame, "scale", Vector2(0.2,0.2), 1) ``` 3 0 Sep. 07, 2024
  • Set tweens for torch lighting and unlightingunripe-tarsierI don't know if this is good but I got it working like this on the torch. extends Area2D @onready var flame: Sprite2D = $Flame @onready var torch: Area2D = self var point = Vector2(0,0) func _ready() -> void: var shape_index = torch.get_index() # This parameter of the shader material gives each flame a slightly different look and randomized animation. flame.material.set("shader_parameter/offset", global_position * 0.1) #flame.set_visible(false) torch.input_event.connect( _on_input_event) func _on_input_event(viewport: , event: InputEvent , shape_index): if event is InputEventMouseButton: if event.button_index == MOUSE_BUTTON_LEFT and event.pressed: if flame.is_visible() == true: var off_tween = create_tween() off_tween.tween_property(flame , "scale", Vector2(0,0), 1) await off_tween.finished flame.set_visible(false) elif flame.is_visible() == false: var on_tween = create_tween() on_tween.tween_property(flame , "scale" , Vector2(.25,.25) , 0.5) flame.set_visible(true) 3 0 Sep. 05, 2024
  • Completed the bird challenge! (Though my code is a bit different to the teacher’s)FioretinHere’s the code that I wrote for the hopping bird challenge. It’s different than the one here though, is that okay? ```gdscript extends Node2D @onready var timer := $Timer @onready var sparrow := $Sparrow @onready var shadow := $Shadow # Called when the node enters the scene tree for the first time. func _ready() -> void: _on_timer_timeout() func hopping_animation() -> void: var random_angle := randf_range(0.0, 2 * PI) var random_direction := Vector2.RIGHT.rotated(random_angle) var random_distance := randf_range(20.0, 40.0) var random_position := random_direction * random_distance const FLIGHT_TIME := 0.4 const HALF_FLIGHT_TIME := FLIGHT_TIME / 2.0 var tween := sparrow.create_tween() tween.set_parallel() #Shadow's tween: tween.tween_property(shadow, "position:y", random_position.y + 20, FLIGHT_TIME) tween.tween_property(shadow, "position:x", random_position.x - 6, FLIGHT_TIME) #Bird's tween: tween.tween_property(sparrow, "position:x", random_position.x, FLIGHT_TIME) tween.tween_property(sparrow,"position:y", random_position.y - 40.0, HALF_FLIGHT_TIME) tween.tween_property(sparrow,"position:y", random_position.y, HALF_FLIGHT_TIME) func _on_timer_timeout() -> void: hopping_animation() ``` When I did this, I noticed that the shadow isn’t placed neatly beneath the bird when it hops, so I added +20 to the `random_position.y` and -6 to `random_position.x` for the shadow’s tween properties 1 0 Sep. 03, 2024
  • Excellent lesson and challengesLaevusThanks for this one. The chance to play around like this within the confines of the course and immediately after learning about the documentation was a fantastic chance to see what I could remember from earlier lessons. As soon as I saw the bird hop challenge, I knew I was going to do it (my partner and me both love birds), but I had to do an important thing before making it hop – make it sparkle for three seconds if you click on it and show a little message to say you've just fed it. When showing my partner, and without telling her, she saw the bird hop and immediately tried to click on it to feed it :D Worth it! It was good practice to make sure the hierarchies were set up so the sprite, shadow, and collision area all moved with each hop. This is the first time in the course that multiple things have clicked and I feel like I can do some ideas that come to mind, and I now can't wait to do more of the course. 1 0 Sep. 02, 2024
  • my shadow desyncs on first jump cautious-crabwhen the bird jump for some reason the shadow consistently desyncs from it. no idea on why it happens, even checked reference and should be the same to me but still the shadow is not synchronized to the bird's landing spot ```gdscript extends Node2D @onready var timer := $JumpTimer @onready var bird := $BirdSprite @onready var shadow := $Shadow func _ready() -> void: timer.timeout.connect(jump) func jump() -> void: print("pulei") var random_angle := randf_range(0.0, 2.0 * PI) var random_direction := Vector2(1.0, 0.0).rotated(random_angle) var random_distance := randf_range(0, 30.0) var jump_position := random_direction * random_distance var jump_height := randf_range(10.0, 20.0) const JUMP_TIME := 0.25 var tween := create_tween() tween.set_parallel() tween.tween_property(bird, "position:x", jump_position.x, JUMP_TIME) tween.tween_property(shadow, "position", jump_position, JUMP_TIME) tween = create_tween() tween.set_trans(Tween.TRANS_QUAD) tween.set_ease(Tween.EASE_OUT) tween.tween_property(bird, "position:y", jump_position.y - jump_height, JUMP_TIME/2) tween.set_ease(Tween.EASE_IN) tween.tween_property(bird, "position:y", jump_position.y, JUMP_TIME/2) ``` 4 0 Sep. 02, 2024
  • Two items overlappingHarbingerShI saw some people saying that with `get_viewport().set_input_as_handled()` they are collecting the bottom-most item, I have no idea what they are doing wrong, however, it's working fine for me, this is the code attached to `item.gd` script on the `_input_event()` function: ```gdscript @export_category("items Types") enum ITEMS { APPLE, KEY, POTION } @export var type: ITEMS func _on_collect_item() -> void: input_pickable = !input_pickable match type: ITEMS.APPLE: get_tree().current_scene.apples += 1 ITEMS.KEY: get_tree().current_scene.keys += 1 ITEMS.POTION: get_tree().current_scene.potions += 1 var tween: Tween = create_tween() tween.set_ease(Tween.EASE_IN_OUT) tween.tween_property(self, "scale", Vector2(1.2, 1.2), 0.1) tween.tween_property(self, "scale", Vector2(0.0, 0.0), 0.1) await tween.finished queue_free() func _input_event(_viewport: Viewport, event: InputEvent, _shape_idx: int) -> void: if event is InputEventMouseButton && event.button_index == MOUSE_BUTTON_LEFT && event.pressed: get_viewport().set_input_as_handled() _on_collect_item() ``` here i created a new script attatched to the MiniDungeon node (the root node) so i can group all items in one base node: ```gdscript signal spawn_object(object, new_position: Vector2) @onready var objects: Node2D = %Objects var apples: int = 0: set(amount): apples = amount _on_update_texts("UI/Container/Apple/Amount", str(amount)) var keys: int = 0: set(amount): keys = amount _on_update_texts("UI/Container/Key/Amount", str(amount)) var potions: int = 0: set(amount): potions = amount _on_update_texts("UI/Container/Potion/Amount", str(amount)) func _ready() -> void: spawn_object.connect(_on_spawn_object) func _on_spawn_object(object, new_position: Vector2) -> void: objects.add_child(object) object.global_position = new_position func _on_update_texts(node_path: String, amount: String) -> void: get_node(node_path).set_text("x" + amount) ``` here i added a new node to the scene tree a `Node2D` for Objects only as a child of the MiniDungeon node and this is on the `chest.gd` script where we spawn random items around the chest: ```gdscript func _on_spawn_items() -> void: var new_item = items.pick_random().instantiate() #we add items to the object node which hold all items in the entire GAEM! #we pass the global position of the current scene so it spawn relevant to this scene position get_tree().current_scene.spawn_object.emit(new_item, global_position) var random_angle: float = randf_range(0.0, 2.0 * PI) var new_direction: Vector2 = Vector2.RIGHT.rotated(random_angle) var new_distence: float = randf_range(60.0, 120.0) var target_position: Vector2 = new_direction * new_distence #we added the global position from the target position so it will be relevant // #to the global position of the chest and so the item lands in the correct target position new_item._on_item_droped(target_position + global_position) #we do that so the items always be on top of all chests plus organize all items in one node func _on_open() -> void: input_pickable = !input_pickable animation.play("Open") if !items.is_empty(): for item in range(randi_range(1, 3)): _on_spawn_items() func _input_event(_viewport: Viewport, event: InputEvent, _shape_idx: int) -> void: if event is InputEventMouseButton && event.button_index == MOUSE_BUTTON_LEFT && event.pressed: _on_open() ``` in this case I am alomst always collecting the top-most item i am using Godot 4.2.2 1 0 Sep. 01, 2024
  • Change Shadow Scale to Show Change in Distance From GroundiguessfiveA good extra feature for the bird challenge is to change the shadow's scale property when leaving the ground and restoring it back when landing. To make the bird look like it's leaving the ground when jumping. My solution for this is: ```gdscript # Stored the original scale of the shadow in constant const ORIGINAL_SHADOW_SIZE := Vector2(1.563, 0.977) # Created a constant for the scale factor to change the shadow by const SHADOW_SCALE_FACTOR = 0.9 # Created a new tween to run in parallel with other tweens tween = create_tween() tween.tween_property(shadow, "scale", shadow.scale * SHADOW_SCALE_FACTOR, HALF_THE_TIME_FOR_EACH_HOP) tween.tween_property(shadow, "scale", ORIGINAL_SHADOW_SIZE, HALF_THE_TIME_FOR_EACH_HOP) ``` There is a slight bug when the bird jumps south of the screen, the shadow looks out of place. Any tips to fix this? 3 0 Aug. 25, 2024
  • my solution to the collecting challenge with a message busmrelectroni tried to use a message bus for this challange, so here is what i did: created a message bus like so: ```gdscript extends Node signal item_update_should_trigger(item_name:String) ``` then set it to autoload from the project settings by going to project>project settings>autoload tab: selected the path to the script, then added it. after that, in the item.gd which is the script attached to all three items, i have added comments prefixed with mychanges to describe what i did and my thought process: Script for pickable items. We don't use inheritance here, just composition: an item is any Area2D scene with a child sprite and this script attached. See gem.tscn and health_pack.tscn. ```gdscript extends Area2D #signal item_update_should_trigger(item_name:String) @onready var sprite_2d :Sprite2D = get_node("Sprite2D") #mychanges: added to store the item name when its first instantiated var item_name : String ="" #mychanges: added to store the deuration of the distruction tween var run_duration: float=0.5 func _ready() -> void: play_floating_animation() #mychanges: added to connect the input event to my function input_event.connect(_on_mouse_pressed) func play_floating_animation() -> void: var tween := create_tween() tween.set_loops() tween.set_trans(Tween.TRANS_SINE) var position_offset := Vector2(0.0, 4.0) var duration = randf_range(0.8, 1.2) sprite_2d.position = -1.0 * position_offset tween.tween_property(sprite_2d, "position", position_offset, duration) tween.tween_property(sprite_2d, "position", -1.0 * position_offset, duration) #mychanges: the function that will be called when the input_event signal is emitted func _on_mouse_pressed(viewport: Node, event:InputEvent, shape_idx: int)->void: #mychanges:logic to detect that the event is a left mouse click var event_is_mouse_click: bool = ( event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT and event.is_pressed() ) if event_is_mouse_click: #mychanges: emiting to the message bus that an item update should #trigger with the item name as an arg MessageBus.item_update_should_trigger.emit(item_name) #mychanges: a simple tween animation, since just disapearing is boring var tween = create_tween() tween.set_ease(Tween.EASE_OUT) tween.tween_property(sprite_2d,"scale",Vector2(0,0),run_duration) #mychanges: connecting to the tween finished signal so that the queue_free #isn't called before the tween finishes tween.finished.connect(_queue_free) #mychanges: just calles the queue_free, used after the tween finishes func _queue_free()->void: queue_free() ``` then i made some changes to the spawning function in the chest.gd ```gdscript func _spawn_random_item() ->void: var loot_item_scene :PackedScene= possible_items.pick_random() var loot_item :Area2D=loot_item_scene.instantiate() add_child(loot_item) var idx:=possible_items.find(loot_item_scene) if idx==0: loot_item.item_name="apple" elif idx==1: loot_item.item_name="key" elif idx==2: loot_item.item_name="potion" #.... ``` basically, i just added a way to detect what item is going to be spawned and set its name property, to be honest, i don't like this approach, its too tightly coupled, and if i added a fourth item, then i will have to update this script. but that was the best i could come up with atm after that, i created the UI as a new scene, it basicaly looks like this: [https://postimg.cc/8fHf3Gr2](https://postimg.cc/8fHf3Gr2) and here is the ui.dg script attached to the control node. ```gdscript extends Control #getting refrences to the label nodes for future updating @onready var label_potion: Label = $LabelPotion @onready var label_key: Label = $LabelKey @onready var label_apple: Label = $LabelApple #initial data var potion_count:=0 var key_count:=0 var apple_count:=0 func _ready() -> void: #connecting the update_item function with the item_update_should_trigger #signal from the message bus MessageBus.connect("item_update_should_trigger",_update_item) #setting inital text label_apple.text="x"+str(apple_count) label_key.text="x"+str(key_count) label_potion.text="x"+str(potion_count) #the update item function func _update_item(item_name: String)-> void: #logic to increment the state based on the item name received by the signal if item_name=="apple": apple_count+=1 elif item_name=="key": key_count+=1 elif item_name=="potion": potion_count+=1 #updating the ui label_apple.text="x"+str(apple_count) label_key.text="x"+str(key_count) label_potion.text="x"+str(potion_count) ``` i used this video to learn about the message bus [https://www.youtube.com/watch?v=vbw1ncvSUYg](https://www.youtube.com/watch?v=vbw1ncvSUYg) would love any and all feedback on how to improve further, and if my solution has any glaring inefficiency or bad practices 1 0 Aug. 24, 2024
  • Question - why can't I use timer node's own timeout signal to restart itself?MatejHello again! So in the very last code reference (bird_completed.gd ), in the last line (line 43), we use this to restart the timer: ```gdscript tween.finished.connect(wait_timer.start) ``` And I understand completely why in this instance, we wait until the last piece of animation finishes until we restart the timer. This prevents the bird hopping animation from restarting too soon (if the 'wait_time' timer property is short enough and tween animation duration long enough that is). That being said, what I tried to do in place of that line while trying to solve the challenge was: ```gdscript wait_timer.timeout.connect(wait_timer.start) # 👆 Well that didn't work! # So I replaced that with the following line. wait_timer.start() ``` Ignoring that this might lead to unwarned behavior involving tween animations, it brought up a question - why the 'wait_timer.timeout.connect(wait_timer.start)' line doesn't restart the one shot timer? 2 0 Aug. 14, 2024
  • My answer for the UI challengeuntrue-giraffeUsing what I know atm this is my solution for the UI challenge I would love to know if doing this is incorrect in any way. I don't know if getting a node reference from far away on the tree is slow or something. Sorry for the bad formatting, the code block is not working on my end. First I created the UI elements and added this script to the parent control node: #collected.gd extends Control var apple_count = 0 var key_count= 0 var potion_count = 0 @onready var label_apple: Label = $VBoxContainer/HBoxContainer/Label_apple @onready var label_key: Label = $VBoxContainer/HBoxContainer2/Label_key @onready var label_potion: Label = $VBoxContainer/HBoxContainer3/Label_Potion # Called when the node enters the scene tree for the first time. func _ready() -> void: label_apple.text = "0" label_key.text = "0" label_potion.text = "0" func add_point(item_name)-> void: print(item_name) match item_name: "apple": apple_count+=1 label_apple.text = "x" + str(apple_count) "key": key_count+=1 label_key.text = "x" + str(key_count) "potion": potion_count+=1 label_potion.text = "x" + str(potion_count) Then on every item scene I assigned them a group and in its script, I checked to which group they belong, on left mouse press: #item.gd signal Collected(item_name) func _input_event(viewport: Viewport, event: InputEvent, shape_idx: int) -> void: ... var item_type:= get_item_type() Collected.emit(item_type) func get_item_type()-> String: if is_in_group("apple"): return "apple" elif is_in_group("key"): return "key" else: return "potion" and lastly on the chest after creating the scene instance I connected the ui with the signal from the item element: var item_instance: Area2D = possible_items.pick_random().instantiate() add_child(item_instance) var collected_ui = $"../CanvasLayer/Collected" if collected_ui: item_instance.connect("Collected", Callable(collected_ui, "add_point")) 1 0 Aug. 14, 2024
  • Bird Challenge - Anticipation before jump animationIronEvaI have struggled with adding a little flavour to the Bird Challenge. What I want to happen is this: **1)** Do an anticipation before the jump which I will fake by using the Skew on the transform. **2)** Then go back to the original skew value, faking a push-off on the jump. **1** and **2** I know I want these to play in a set order, which is perfect as by default tweens work this way. It gets tricky when I create another tween as it then wants to play in parallel with the first part of the animation, which I don't want to happen. Is there a way to delay the creation of a tween? I tried to use the tween.interval but I just got errors for that? I must have spent about 5 hours trying to figure out what I have done wrong and feel like I am losing hair. ;) ```gdscript func _on_timeout(): var random_angle = randf_range(0.0, 2.0) * PI var random_direction = Vector2(1.0, 0).rotated(random_angle) var random_jump_distance = randf_range(25.0, 75.0) var landing_position = random_direction * random_jump_distance #print(random_jump_distance, random_direction, landing_position) var jump_height: float = randf_range(30.0, 60.0) var time_distance: float = 0.5 var half_time_distance: float = time_distance / 2 #---------------------Anticipation---------------- #create a tween to do the following, do an anticipation then, go back to normal skew var tween = create_tween().set_trans(Tween.TRANS_BACK).set_ease(Tween.EASE_OUT) #Do an anticipation before the jump tween.tween_property(bird_sprite_2d, 'skew', 0.6, time_distance) #learn forward and go back to normal skew value tween.tween_property(bird_sprite_2d, 'skew', 0, 0.25) #------------------------------------------------- #--------------------Move to Location------------ #need a wait to delay the tween creation but tween.interval(1) didn't work tween = create_tween().set_trans(Tween.TRANS_CUBIC).set_ease(Tween.EASE_OUT) tween.tween_property(self, 'position', position + landing_position, time_distance) #------JUMP-------------------------------------- tween = create_tween() tween.tween_property(bird_sprite_2d, 'position:y', bird_sprite_2d.position.y - jump_height, half_time_distance) tween.set_ease(Tween.EASE_IN) tween.tween_property(bird_sprite_2d, 'position:y', bird_sprite_2d.position.y, time_distance) ``` 4 0 Aug. 12, 2024
  • Flipping with @export and setter OctarinaI am so happy for this course, I feel I am starting to be able to do more what I want with the code now. I really appreciate these experiments, I feel I learn a lot and also from other's attempts! :D What I wanted was to do the FLIP challenge, and also make it so one can in-editor set the direction on bird. ```gdscript enum look {LEFT, RIGHT} @export var direction :look: set(value): direction = value if sprite_2d and sprite_2d.is_inside_tree(): if value == look.RIGHT: sprite_2d.flip_h = true elif value == look.LEFT: sprite_2d.flip_h = false get: return direction ``` Then use it like this: ```gdscript if land_position.x > 0: direction = look.LEFT else: direction = look.RIGHT ``` Now I am sure I got this to work once, it updated in editor if I add @tool and also worked when running from editor. Now it feels sometimes the flip is off, shadow gone ect. Or is this doomed to cause issues? I really like that I can see that direct feedback in-editor how something looks or behaves when I change a property. I get a sense this is an "over complicated" solution I found, is this the right way to approach things? It feels a bit odd to check is inside tree. I found that searching since it crashed sometimes on start. I tried to really understand the order things run in, but it seems like the setter is called before _ready and @onready? 4 0 Jul. 31, 2024
  • Torches keep switching on/off in sync.GillooI am having an issue while doing the torch challenge where, despite using an Area2D and making sure Local To Scene is switched on, both torches switch on and off at the same time when clicked. Does anyone else have the same issue? 7 0 Jul. 30, 2024
  • Answer to Torch challengelazy-barracudaMay be I am not the sharpest tool in the shed and I didn`t use any hints, so my code became a lil bit stupid. BUT IT WORKS :D ```gdscript extends Node2D @onready var flame: Sprite2D = $Flame @onready var check_flame := true func _ready() -> void: # This parameter of the shader material gives each flame a slightly different look and randomized animation. flame.material.set("shader_parameter/offset", global_position * 0.1) func _input_event(viewport: Viewport, event: InputEvent, shape_index: int): var event_is_mouse_click: bool = ( event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT and event.is_pressed() ) if event_is_mouse_click: if check_flame == true: remove_child(flame) check_flame = false else: add_child(flame) check_flame = true ``` 1 0 Jul. 28, 2024
  • Tween execution orderploped00Hi all! I solved bird's challenge in a very similar way than GDQuest (see below), but I'm confused about the instructions I gave and the order in which Godot executes the tweens. Here are my doubts: - When I create a new tween using tween = create_tween() am I substituting the previous tween by the new one? - Why do the 2 tweens (pos X and pos Y) executes in parallel if I'm not using the set_parallel() method? - I've conclude that I can use the same tween to animate different properties but I've to reinitialize the tween when I animate different sub-properties as position:x and position:y, am I right? Thank you very much in advance! `var tween := create_tween()` ` tween.tween_property($Sprite2D, "position:x", random_movement.x, JUMP_TIME)` ` tween = create_tween()` ` tween.set_trans(Tween.TRANS_QUAD)` ` tween.tween_property($Sprite2D, "position:y", random_movement.y - jump_height, JUMP_TIME/2)` ` tween.tween_property($Sprite2D, "position:y", random_movement.y, JUMP_TIME/2)` ` shadow.position = random_movement + shadow_offset` 2 0 Jul. 22, 2024
  • Using AnimationPlayer and randomized Area2D Transform Parametersdelicious-frogI was trying to do this by creating a short hop animation using AnimationPlayer, but I was having the following issues: 1. Edit the transform parameters (rotation/orientation) of the animation, the parent Node2D, or the Sprite2D I was thinking that I could either change the angle and randomize a horizontal mirror of the node to force the animation to play the hop animation in a random direction. 1. Change the (x, y) position of the key frames of the animation editor. I'm not sure if it is something that can or should be done, but I saw the AnimationTrackKeyEdit (x, y) values and thought that I could modify their values to match randomized distance, height, and angle. 2. I was having an issue with the bird spawing either at (0, 0) of the mini_dungeon or slightly behind it. The issue fixed itself when I changed how I did the animation. I think that the bird is inhereting its position from the mini_dungeon scene or the AnimationPlayer was forcing its coordinates to (0, 0), but I didn't fix the issue so I can't say for sure. 2 0 Jul. 15, 2024
  • New defi because need trainingHazlarhi ! I had a hard time re-doing the challenge with the bird, and I would like to get revenge by giving myself another challenge which is that when I click on the bird, it stops its interpolation and I can move it, and that if I direct it towards the torch it gradually blackens and disappears (using an interpolation) or that if I release it it restarts its original interpolation. Is this a challenge that can be met with the knowledge taught so far? 10 0 Jul. 15, 2024
  • Getting lost in coordinate spaces for the bird challengeprofuse-otter```gdscript extends Area2D @onready var bird_sprite: Sprite2D = $"Bird Sprite" @onready var shadow: Sprite2D = $Shadow @onready var timer: Timer = $Timer func _ready() -> void: timer.timeout.connect(hop) func _process(delta: float) -> void: pass func hop() -> void: var random_angle := randf_range(0, 2 * PI) var random_direction := Vector2.from_angle(random_angle) var random_distance := randf_range(15.0, 30.0) var landing_position: Vector2 = random_direction * random_distance const HOP_DURATION := 0.6 # flip the bird sprite if bird is not facing the direction # adjust the position if it flips to move its feet back to the centre of the shadow if (random_angle < PI / 2 or random_angle > (3.0 * PI) / 2.0): if not bird_sprite.flip_h: bird_sprite.position.x -= 14 bird_sprite.flip_h = true elif bird_sprite.flip_h: bird_sprite.position.x += 14 bird_sprite.flip_h = false var tween := create_tween() tween.tween_property(bird_sprite, "position:x", landing_position.x + bird_sprite.position.x, HOP_DURATION) tween = create_tween() tween.tween_property(bird_sprite, "position:y", bird_sprite.position.y - 20, HOP_DURATION / 2) tween.tween_property(bird_sprite, "position:y", landing_position.y + bird_sprite.position.y, HOP_DURATION / 2) tween = create_tween() tween.tween_property(shadow, "position", landing_position + shadow.position, HOP_DURATION) tween = create_tween() const SHADOW_BASE_SCALE := Vector2(1.563, 0.977) #remap(bird_sprite.position.y - 20, ) tween.tween_property(shadow, "scale", SHADOW_BASE_SCALE * 1.4, HOP_DURATION / 2) tween.tween_property(shadow, "scale", SHADOW_BASE_SCALE, HOP_DURATION / 2) tween = create_tween() tween.tween_property(shadow, "modulate:a", 0.7, HOP_DURATION / 2) tween.tween_property(shadow, "modulate:a", 1.0, HOP_DURATION / 2) ``` Overall I'm quite happy with the result of the above code. The bird hops in a random direction, looks in the direction it is hopping, and the shadow's position remains in sync with it. I'm not so happy with the use of different (I think?) coordinate spaces in my solution. I think it started by trying to make the vertical jump animation look more consistent between when the landing position was above or below the origin (a byproduct of having to use the y-axis for both height and depth?) I'm not even sure how to phrase what I'm asking but it seems like there is a much more understandable solution that doesn't involve self-referencing positions in the tween? Another area I know has a less rigid solution is where I flip the bird sprite and adjust the position. I'm guessing the answer lies in the scene editor but I can't work it out, any suggestions? 3 0 Jul. 12, 2024
  • Input Events for key pressessteel_jokersAre the input events we are using only relevant to mouse input or can we capture an event that occurs when a user presses a key on their keyboard? For instance, if I wanted to capture that a body entered the area where the chest was and the user pressed a key, let's say 'o' for open, would it work? I looked up InputEventAction and thought I was maybe on the right track to achieve this, but I can't seem to get it working. I've tried a few things, but I'm not finding success: ```gdscript # Note: I've added an open action to my InputMap that corresponds to the 'o' key func _input_event(viewport, event, shape_idx): var keypress_event: bool = ( event is InputEventAction and event.action == "open" and event.is_action_pressed() ) # to check if it works, I'm printing the result to the console print("o key was pressed: ", keypress_event) ``` 2 0 Jul. 07, 2024
  • var tween - why can we reuse this X times in a script? snowm8nI'm reading through my code, trying to get a quick refresh and make sure I understand everything so far (I'm just about to turn off the torch). I noticed we reuse "var tween" several times, but we usually need to come up with a unique variable name. Is there an exception because it's a tween? This may be a(nother) rookie question but I wanted to ask :-) *ex. I would think we needed a unique variable name for each time its called in a single script:* ```gdscript var tween_mouse_entered var tween_mouse_exited var tween_spawn_random_item ``` 1 0 Jul. 05, 2024
  • Weird hopping movement, when the bird jumps downwardsLxVaiNI made a code for the hopping bird and im happy with it, for my personal skills, since its my first try on this, but one thing is weird. When the bird hops downwards, it does make a weird double wave motion instead of one continuous one. I couldnt figure out why. It's probably because the vectors add up in a weird way when the x coordinate is almost 0 and y > jump height. Here is my code, if someone wants a "challenge" and figure it out for me xD (i made the shadow and the sparrow sprite in one canvas group so they jump together if you are wondering) @onready var sprite = $CanvasGroup/Sparrow @onready var sparrow = $CanvasGroup func _ready() -> void: $Timer.timeout.connect(_on_timeout) func _on_timeout()->void: var random_direction = Vector2(50.0,0.0).rotated(randf_range(0.0,2*PI)) if random_direction.x > 0: sprite.flip_h = true elif random_direction.x < 0: sprite.flip_h = false var tween = create_tween().set_parallel() tween.tween_property(sparrow,"position:x",random_direction.x,0.4) tween = create_tween().set_ease(Tween.EASE_OUT).set_trans(Tween.TRANS_QUAD) tween.tween_property(sparrow,"position:y",random_direction.y - 20.0,0.2) tween.set_ease(Tween.EASE_IN) tween.tween_property(sparrow,"position:y",random_direction.y,0.2) 1 0 Jun. 29, 2024
  • Bird and shadow are disaligned at the first jumpbururezHi, thanks for your great work! I don't understand what is wrong in my code, in the first jump seems that shadows has different land position: ```gdscript extends Node2D @onready var birdSprite := $Sparrow @onready var birdShadowSprite := $Shadow @onready var timer := $Timer func _ready() -> void: timer.one_shot = true timer.wait_time = randf_range(1.0, 3.0) timer.timeout.connect(_on_timeout) timer.start() func _on_timeout() -> void: var random_direction := Vector2(1.0, 0.0).rotated(randf() * 2.0 * PI) var random_distance := randf_range(0.0, 30.0) var new_position := random_direction * random_distance _hop(new_position) func _hop(final_destination: Vector2) -> void: const hop_height := 16.0 const hop_time := 0.25 const half_hop_time := hop_time / 2.0 var tween := create_tween().set_parallel() tween.tween_property(birdSprite, 'position:x', final_destination.x, hop_time) tween.tween_property(birdShadowSprite, 'position', final_destination, hop_time) tween = create_tween().set_trans(Tween.TRANS_QUAD) tween.set_ease(Tween.EASE_OUT) tween.tween_property(birdSprite, 'position:y', final_destination.y - hop_height, half_hop_time) tween.set_ease(Tween.EASE_IN) tween.tween_property(birdSprite, 'position:y', final_destination.y, half_hop_time) timer.wait_time = randf_range(1.0, 3.0) tween.finished.connect(timer.start) ``` Could anyone help me to understand? Thanks 4 0 Jun. 29, 2024
  • Where should I attach the script?Nikita MyshkinPlease tell me which node the item script needs to be attached item.gd for the task "step 1: Detecting mouse clicks". Or do I still need to write in the script chest.gd? I tried to create separate scenes for items, as in the M5 module, but it doesn't work. `print("The condition is true")` is triggered only on new items, not on those in the chest. It seems to me that you need to create a new script and use the array, as in the script chest.gd. But I can't figure out where to attach it. 5 0 Jun. 27, 2024
  • How can I make it so the bird can't go through wallsFasionMagazineI want to make it so the birds can't go through walls or the chests. I was thinking I could the coordinates of where they can't go and check if the place they're going to land is in those coordinates and if so calculate a new landing place, but this seems convoluted. Is there a simpler solution? 2 0 Jun. 21, 2024
  • Am I Allowed To Look at Previous Projects?choodleCan I look at my other scripts to gain insights about how to solve this? I looked at chest.gd and item.gd and they helped a lot, however, if it would be better to do experiments like this without looking back please let me know. 3 0 Jun. 19, 2024
  • Torches on/off are synchronisedpuzzled-magpieHey, I couldn't find a solution to this. When I click one torch, both of them go on and off. The Local to Scene option in the shader was already on, so that wasn't it. Can someone give me a hint on this? 5 0 Jun. 14, 2024
  • A tip for anyone trying the UI item challengeInfiniteDazeI don't know if there's a more proper way to do it but you should look into how to create and pass signals from different scripts (especially instanced items). While it *is* technically similar to M5, I had to make the labels as part of the Main Dungeon scene, and it took a bit of document reading and googling to somehow stumble upon the right answer. Was there an easier method to doing this? Also the get_tree() is your best friend. 3 0 Jun. 13, 2024
  • Flame tweenp_dev_Hi there. I've written the following code to animate the flame so it shrinks before toggling it invisible, and grows when becoming visible again. While it works, I have a sense that something is off. How could I improve it? Thanks in advance. ```gdscript # ... if event_is_mouse_click: var tween = create_tween() if flame.visible: tween.tween_property(flame, "scale", Vector2(0.0, 0.0), 0.2) tween.finished.connect(change_flame_visibility) else: change_flame_visibility() tween.tween_property(flame, "scale", Vector2(0.28038, 0.28038), 0.2) func change_flame_visibility() -> void: flame.visible = not flame.visible ``` 3 0 Jun. 11, 2024
  • Bird double jumpProxerHi folks, I am struggling with the following, I have my bird animation working and the shadow moving along with an offset and things initially look good, however, every couple of jumps (randomly) the bird seems to do a double jump? or the jump height doesn't seem to be consistent even I have set a constant for the height? I have uploaded a video showing the issue here: [https://file.io/vFi84B9r4GPY](https://file.io/vFi84B9r4GPY) At seconds 04 and 10 is when the issue is clearly visible. At the moment the animation gets executed every 01 second through a timeout signal. Here's my scene script as well. ```gdscript extends Node2D @onready var bird_sprite: Sprite2D = $bird_sprite @onready var shadow: Sprite2D = $Shadow func _on_timer_timeout() -> void: const ANIMATION_LENGHT := 0.25 const ANIMATION_HALF_LENGHT := ANIMATION_LENGHT / 2.0 var radious := 30.0 var angle := randf_range(0.0, 2.0 * PI) var random_direction := Vector2(1.0, 0.0).rotated(angle) var random_distance := randf_range(20.0, radious) var landing_position := random_direction * random_distance var tween:= create_tween() tween.set_parallel() tween.tween_property(bird_sprite, "position:x", landing_position.x, ANIMATION_LENGHT) var position_for_shadow = landing_position position_for_shadow.y += 20 position_for_shadow.x -= 5 tween.tween_property(shadow, "position", position_for_shadow, ANIMATION_LENGHT) tween = create_tween() var height_jump := 16.0 tween.set_trans(Tween.TRANS_QUAD) tween.set_ease(Tween.EASE_OUT) tween.tween_property(bird_sprite, "position:y", landing_position.y - height_jump, ANIMATION_HALF_LENGHT) tween.set_ease(Tween.EASE_IN) tween.tween_property(bird_sprite, "position:y", landing_position.y, ANIMATION_HALF_LENGHT) ``` Thanks in advance 5 0 Jun. 10, 2024
  • Where do I put this line of codeAphexget_viewport().set_physics_object_picking_sort(true) get_viewport().set_physics_object_picking_first_only(true) I want to know how to make items disappear one at a time when they're on top of each other but wherever I put the lines, my game crashes. The error says Invalid call. Nonexistent function 'set_physics_object_picking_first_only' in base 'Window'. I don't see the lines of code in the solution scripts unless I missed them. Thanks in advance! 1 0 Jun. 05, 2024
  • How is the event_is_mouse_clicked variable returning a true or false bool?leafI don't understand how the `event_is_mouse_clicked` variable is being returned as a bool. Exactly where is a true or false value being returned within this variable? Currently I am receiving a false value when I click a chest, but I don't even understand where in the syntax it would even be registering as true or false. 1 0 May. 30, 2024
  • Question about an if/else statementA_Room_With_A_MooseThe code below produces an annoying bug where small movements along the x axis don't trigger my IF statement as expected: ```gdscript # flips the sparrow's sprite horizontally if random_direction.x > 0.0: sparrow.flip_h = true shadow.offset = Vector2(4.0, 18.0) else: sparrow.flip_h = false ``` My bird hops as expected for the most part, but with one caveat: small horizontal hops don't seem to trigger this statement, so if the bird takes small hops opposite the direction the sprite's currently facing (backward) it won't flip. Any idea why this might occur? 7 0 May. 29, 2024
  • Using randf() vs randf_range() in bird_completed.gd scriptA_Room_With_A_MooseI was wondering how these two statements yield the same results: ```gdscript (randf() * 2.0 * PI) #vs randf_range(0.0, 2.0 * PI) ``` According to the programmer's dictionary, randf() > Returns a pseudo-random float between 0.0 and 1.0 (inclusive). while randf_range() > Returns a pseudo-random float between from and to (inclusive). 5 0 May. 29, 2024
  • Question about _input_event()MuseDoesI noticed a couple of things while doing these experiments. Specifically with the input event functions in the chest and item scripts. In the chest.gd, the function is written like this: func _input_event(viewport: Node, event: InputEvent, shape_index: int) -> void: And in the item.gd it looks like this: func _input_event(viewport: Viewport, event: InputEvent, shape_idx: int) -> void: The arguments are different in both scripts. The viewport argument is declared as a Node and as a Viewport respectively. And the shape_index changed to shape_idx when you use autocompletion. I've tried switching the Viewport to Node and vice versa on both scripts. Nothing in particular seems to change. I used the Search Help, but I don't quite understand the entry: ---------------------------------------------------------------- void _input_event(viewport: Viewport, event: InputEvent, shape_idx: int) virtual Accepts unhandled InputEvents. shape_idx is the child index of the clicked Shape2D. Connect to input_event to easily pick up these events. Note: _input_event() requires input_pickable to be true and at least one collision_layer bit to be set. ---------------------------------------------------------------- I guess what I'm trying to ask is: Q1. What does changing the viewport argument from Viewport to Node really do? and Q2. Why does the shape_index return an int? (If I understand this one, it seems like there's an integer associated with all of the children nodes within a given scene. But I couldn't find any more info in the Search Help, so I'm a little lost here.) Q3. Why can the title for the argument for the shape_index be listed as both shape_index and shape_idx? Wouldn't changing the title of the argument give off an error normally? 2 0 May. 26, 2024
  • Error when trying to tween the torch flames right-cheetahI wanted to use a tween to animate the flames being extinguished instead of just turning its visibility off. And I did manage to get it to work, but when I first extinguish the flames, and then make the items from the chest disappear by clicking on them, I come across this error: Invalid get index 'queue_free' (on base: 'previously freed') Can I get an explanation on what is happening here? Here's my code for reference: (torch.gd) ```gdscript extends Area2D @onready var flame: Sprite2D = $Flame func _ready() -> void: # This parameter of the shader material gives each flame a slightly different look and randomized animation. flame.material.set("shader_parameter/offset", global_position * 0.1) func _input_event(Viewport: Node, event: InputEvent, shape_index: int) -> void: var event_is_mouse_click: bool = ( event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT and event.is_pressed() ) if event_is_mouse_click: disappear() func disappear() -> void: var tween = create_tween() tween.tween_property(flame, "scale", Vector2(0.0,0.0), 0.05) tween.finished.connect(flame.queue_free) ``` 1 0 May. 25, 2024
  • Collecting the top itemEcepHey Nathan, I've made it such that when you click on the collectible, it animates the collectible, adds to a player count for each type of collectible, and updates a UI element for each collectible type. However, one thing I'm struggling is making it so only the top-most collectible is collected in the case where they overlap. Right now I'm using: ```gdscript func _input_event(viewport: Viewport, event: InputEvent, shape_idx: int) -> void: if(event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT and event.is_pressed()): collect() viewport.set_input_as_handled() ``` However, this makes it so the bottom-most collectible is collected and not the top. I'm not really sure where to go from here. I can't seem to find an online resource covering it. Thanks in advance. 7 0 May. 24, 2024
  • Bird Challenge Tween the Node2D?opulent-boarHello, I enjoyed this section of the course and going through the challenges. After completing the bird challenge, I was thinking about why we tween the shadow instead of the root Node2D for the bird? That is what I initially tried, it just makes more sense in my head to move the transform of the root node... but I guess that might cause issues updating the root node and move the bird/Sprite2D up? What if we have a more complicated object with more pieces? Do we need to tween all the pieces individually? Thanks for the great course content. Looking forward to the next Lesson. 1 0 May. 15, 2024
  • General Q towards personal progressfledgerThus far I feel like I am doing pretty decently with some concepts, but for some I feel like they are not fully enforced yet. For example, I feel confident with some tween aspects, such as the properties and methods, but I get forgetful when it comes to the variable set up for the distance in a random radial direction. Also, I have had to peek at the solutions when it came to why my birds shadow was offset. I feel as if this is a good module for me to stop before going into 7 to practice more. Do you think it would be more beneficial to set up my own scenarios that are near identical to try to fully enforce these lessons? Or do you think repeating the lessons may be better to enforce the concepts? Either way, I am not sure if it is just me, but I have a bit of a guilty conscience when I feel like I have look at previous code. Is it normal for beginners to do this at this stage? Am I being too hard on myself or right in line? I know these questions are a bit subjective, but I was curious at what you all may think. I am loving the progress I have made so far and found these lessons very helpful! I think I just want to have these points packed in before continuing on! Thanks! 3 0 May. 14, 2024
  • Mouse exited signal triggering when entering a child‘s area HollowSo I decided to make a small complete game from the basis of what I learned up to this point, however I am facing an issue: I wanted to implement a small popup menu which appears when clicking on an item. The menu has two buttons and I wanted to have the menu disappear again when the player moves their mouse outside of the menu (area 2d)‘s collision polygon. The problem is that the mouse exited signal is also emitted when hovering over the buttons inside of the menu so the menu disappears when hovering over the buttons. How could I fix this so the buttons still work but do not trigger the menu‘s mouse exited signal? 9 0 Apr. 26, 2024
  • Bird hopping to 0,0 when trying final challenge with a mix of Animation Player and tween.TheKmankI am trying to mix the animation player (which is animating the sparrow sprite for the "jump") and a tween to move the bird in a random direction. However whenever I use start the scene, the bird's first jump will teleport it to 0,0 and I am sure why it is happening. Above is my code for the sparrow. ```gdscript extends Area2D @onready var sparrow: Sprite2D = $Sparrow @onready var shadow: Sprite2D = $Shadow #not used in code @onready var animation_player: AnimationPlayer = $AnimationPlayer func _ready() -> void: var hop_timer : Timer = Timer.new() hop_timer.wait_time = randf_range(1.0, 3.0) hop_timer.autostart = true hop_timer.one_shot = false hop_timer.timeout.connect(_on_timer_timeout) hop_timer.start() add_child(hop_timer) func jump(): var random_angle := randf_range(0.0, 2.0 * PI) var random_direction := Vector2(1.0, 0.0).rotated(random_angle) var random_distance := randf_range(10.0, 30.0) var land_position := random_direction * random_distance var tween := create_tween() tween.tween_property(self, "position", land_position, 0.2) animation_player.play("hop") func _on_timer_timeout(): jump() ``` 4 0 Apr. 25, 2024
  • Fireball shooting bird animation timing errorsHermundureWhile experimenting as my evening project, I placed both birds opposite to each other and attached a button for each bird. When this button is pressed, a Fireball.tscn, that has been dragged into the exported Array[PackedScene] is spawned. This Fireball is flying towards the enemy bird and collides with the collision shape of the bird. So far, so good. Everything works as expected but here the trouble starts (problems are described in the comments of the code section): ```gdscript extends Area2D @onready var animated_sprite_2d: AnimatedSprite2D = $AnimatedSprite2D var speed := 110 func _ready() -> void: area_entered.connect(_on_area_entered) animated_sprite_2d.animation_finished.connect(queue_free) func _process(delta: float) -> void: position.x += speed * delta animated_sprite_2d.play("flight") func _on_area_entered(area_that_entered: Area2D) -> void: # The next line is supposed to stop the fireball at the current position to prepare the "explode" animation to be played # in the place of impact. It does not work, the fireball keeps flying if I do not call queue_free() - how dangerous! position = position # The next line is supposed to change the "flight" animation to "explode" animation but by executing # the code, it does nothing. The fireball resists my wish to change its animation. animated_sprite_2d.play("explode") # The next line is supposed to give the "explode" animation time to play and delete the child afterwards. # It does not work, the fireball is deleted instantly when it hits the bird's collision shape. animated_sprite_2d.animation_finished.emit() # The next line is the only thing that works. It really prints it :-) print_debug("Hit!") ``` I also drew and animated my own bird, it has a fire breathing animation now. The Fireball is supposed to come out after the fire breathing animation has finished but again I run into the problem that I can not get the animation_finished issue, which I described in the code block to work. As a result, the fireball comes out as soon as the button is pressed.:-( 1 0 Apr. 21, 2024
  • Bird Hop Challenge InconsistencyJayV3DHad a lot of fun doing the challenges - just wanted to mention that there seems to be an inconsistency in wording with the bird hop challenge. In the challenge description, you mention to use the wait_time of the timer as the tween's duration: **Challenge:Create a bird scene and script to make the bird hop around. To make the bird hop at regular intervals, you'll need to synchronize tweens with a timer's duration. To do this, you can use a `Timer` node and its `wait_time` property as a tween's duration.** I'm not sure why you'd need to do this, unless you either wanted the bird to not wait between jumps, or if you wanted the jump to always be the same duration as the time it waited? The suggested solution also does not do this, which could be confusing if you were struggling? Just an observation! 1 0 Apr. 20, 2024
  • Using CanvasGroup for bird solution?BobbyDevI'm grouping the shadow and the bird sprite within CanvasGroup, similar to some of the previous lessons using the ship. Is setting the shadow position in the code and sprite_2d position using the tweens a better method or would these just be two different solutions? 1 0 Apr. 20, 2024
  • Bird tween not moving...I'm sure it's simple.BoomsquallyI just started the last challenge and was playing around with tweening, trying not to go back to previous lessons, but I compared my current code to the spawning function in L6 and I just can't get why the bird ain't moving. I know it's looking a little crap, but shouldn't it even show some crappy movement? extends Node2D @onready var sprite : Sprite2D = $Sparrow func _ready(): bird_hop() func bird_hop() -> void: var random_distance := randf_range(20.0, 40.0) var random_angle := randf_range(0.0, PI * 2.0) var random_direction := Vector2(1.0, 0.0).rotated(random_angle) var tween := create_tween() tween.tween_property(sprite, "position.y", -20.0, 1.0) tween.tween_property(sprite, "position.y", 0.0, 1.0) tween = create_tween() tween.tween_property(sprite, "position.x", random_direction * random_distance, 1.0) func _process(delta): pass 6 0 Apr. 19, 2024
  • Question about the solution code for hopping birdPJWhat is the purpose of creating a new tween object in line 24? 4 0 Apr. 10, 2024
  • Next stepsArtemaleThe whole course is amazing, Thank you! I've finally started to get clue with it. The next logical step seems to be building small games by my own. I've started a few with some help of Youtube. What I see clearly is that Godot 4 should have some version for html5 games as it was in 3.5 html5 games are ok to be simple and that's the place to actually let other people to play your games. Even if the game is not cool it's pretty much ok for a browser game to be released. It also let you get experience of people playing your games and in some cases even earn first money from game development. I am considering to use Godot 3 for some time just to release a few html games. But it's kind of pain to ignore great Godot 4 tools like new tilemap system. I know it migth not be the best place to write on it but I am just parasitizing on you guys actually read and answer these comments. Thank you! 4 0 Apr. 06, 2024
  • Input event processed on overlapping itemsSamukaveraIf I have two overlapping items and click on one of them, the two items will trigger the `_input_event()` function. I've added the `get_viewport().set_input_as_handled()` trying to stop the event propagation, but with this, the input is processed in the bottom item, behind the clicked item. I'm not finding an easy way to solve this... can you help me? 15 0 Apr. 04, 2024
  • Shared item.gd script doesn't work on different items. DargorSo I added code to the apple scene to make it shrink when clicking it. It worked, but when I clicked on the key and potion, nothing happened. I solved it by adding a new script to the potion and key, and using the exact same code. Maybe there's something about signals I'm not understanding. Any idea why this happened? 3 0 Apr. 03, 2024
  • bird shooChainSOVI wanted to program behaviour so that the bird jumps away from mouse cursor. So I connected the on_mouse_entered signal like this, but was having very weird behaviour, sometimes the bird didn't jump at all, sometimes it did. ```gdscript func _on_mouse_entered() -> void: var vel = Input.get_last_mouse_velocity() _jump(vel) ``` Noob eureka moment: your **jump function also needs to move the collision shape**, not only the sprite and shadow :-D The bird only jumped when I moved the mouse cursor over its original position by accident I still encounter some weirdness though, get_last_mouse_velocity sometimes returns different directions of mouse movement, even though I try to move my mouse steadily one direction :-O is there a better approach? Is there an option to read out InputEventMouseMotion.velocity inside my `_on_mouse_entered`function somehow? Or is it only possible inside `_input_event` ? I tried processing the logic in input_event, but only wanted it to do something if the signal mouse_entered fired, so I set some global variables in the signal function, but I feel like its a dirty hack and there should be a more elegant solution to this ```gdscript var mouse_entered_birdspace:bool = false var last_mouse_velocity:= Vector2(0.0,0.0) func _on_mouse_entered() -> void: mouse_entered_birdspace = true last_mouse_velocity = Input.get_last_mouse_velocity() ``` ```gdscript func _input_event(viewport: Node, event: InputEvent, shape_index: int) -> void: if not mouse_entered_birdspace: return if event is InputEventMouseMotion: mouse_entered_birdspace = false _jump(event.relative*30) ``` is there? both InputEventMouseMotion.relative, InputEventMouseMotion.velocity and Input.get_last_mouse_velocity() sometimes produce jumps toward the mouse pointer though, not sure how to fix that. here is how my jump looks like ```gdscript @onready var shadow: Sprite2D = $Shadow @onready var shadow_offset: Vector2 = shadow.position func _jump(land_position:Vector2) -> void: const HOP_DURATION := 0.25 const HALF_HOP_DURATION := HOP_DURATION / 2.0 var tween := create_tween().set_parallel() tween.tween_property(sprite_2d, "position:x", land_position.x, HOP_DURATION) tween.tween_property(shadow, "position", land_position + shadow_offset, HOP_DURATION) tween = create_tween() tween.set_trans(Tween.TRANS_QUAD) tween.set_ease(Tween.EASE_OUT) const JUMP_HEIGHT := 16.0 tween.tween_property(sprite_2d, "position:y", land_position.y - JUMP_HEIGHT, HALF_HOP_DURATION) tween.set_ease(Tween.EASE_IN) tween.tween_property(sprite_2d, "position:y", land_position.y, HALF_HOP_DURATION) collision_shape.position = land_position wait_timer.wait_time = randf_range(1.0, 3.0) tween.finished.connect(wait_timer.start) ``` does it make sense, to do something like ```gdscript collision_shape.disabled = true collision_shape.position = land_position collision_shape.disabled = false ``` while changing position to prevent any more events from firing? 6 0 Mar. 30, 2024
Site is in BETA!found a bug?