Hello and thank you, Scel! So Oneirality is developed in Godot 3, but the bouncing bullet shells can work in Godot 4.
Essentially, each bullet casing is a KinematicBody2D (CharacterBody2D for G4) so that it makes use of that node's physics collisions. The casings run a function in the _physics_process that will move the casing downward if its global_position.y value is not less than bound, otherwise it will multiply its velocity by -0.75 so that it bounces up and multiplies velocity.x by 0.5 so it slows down horizontally. It also runs a check to see if its velocity is below a certain threshold to tell it to set_physics_process to false. There are other functions used, but for the main bouncing, this is it. I'll paste some of the code below:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
export (float) var bound = 0.0
export (int) var bound_rand = 4
export (int) var motion_rand = 150
export (float) var bound_stop = 0.75
var motion: Vector2 = Vector2(0, -200) # When instanced, the casing will move upward already. For G4, you can put this in the _ready function.
func _instantiate():
if not bound_rand == 0:
bound += (randi() % bound_rand + (bound_rand / 2))
motion.x += (randi() % motion_rand - (motion_rand / 2))
motion.y += (randi() % (motion_rand / 2))
func apply_bound(_delta):
# Should Fall
if global_position.y < bound:
motion = motion.move_toward(Vector2(motion.x, motion.y + 10.0), 10.0)
# Should bounce
else:
motion.y = -0.75 * motion.y
global_position.y -= 0.1
motion.x = 0.5 * motion.x
emit_signal("bound_contact")
# Stop physics to prevent performance issues
if motion.length() < bound_stop:
set_physics_process(false)
_bounce_stop() # This just rounds the casings global_position to be pixel perfect
emit_signal("bounce_stop")
motion = move_and_slide(motion)
Hope this helps!