Why doesn't the player fall down? - game-development

I'm making my first mobile game on godot so I'm very inexperienced. It is a platformer. I would like the player, when he collides with the enemy, to fall down and die. I've been trying to do it for days, but it always gives me some different problem and I don't understand what I'm doing wrong. Could anyone help me please? I leave you the player code; in this way the player, despite having set velocity.y=.500, does not fall, but makes a sort of jump. What's wrong? Thank you all in advance.
PLAYER CODE:
extends KinematicBody2D
onready var rayS = get_node("rayL")
onready var rayD = get_node("rayR")
onready var sprite = get_node("AnimatedSprite")
var alive = true
signal dead
const WALK_FORCE = 600
const WALK_MAX_SPEED = 300
const STOP_FORCE = 1300
const JUMP_SPEED = 700
const gravity = 1100.0
var velocity = Vector2()
func _physics_process(delta):
var force = Vector2(0, gravity)
var walk_left = Input.is_action_pressed("move_left") and alive
var walk_right = Input.is_action_pressed("move_right") and alive
var jump = Input.is_action_pressed("jump") and alive
# Horizontal movement code. First, get the player's input.
var walk = WALK_FORCE * (Input.get_action_strength("move_right") - Input.get_action_strength("move_left"))
# Slow down the player if they're not trying to move.
if abs(walk) < WALK_FORCE * 0.2:
# The velocity, slowed down a bit, and then reassigned.
velocity.x = move_toward(velocity.x, 0, STOP_FORCE * delta)
else:
velocity.x += walk * delta
# Clamp to the maximum horizontal movement speed.
velocity.x = clamp(velocity.x, -WALK_MAX_SPEED, WALK_MAX_SPEED)
# Vertical movement code. Apply gravity.
velocity.y += gravity * delta
# Move based on the velocity and snap to the ground.
velocity = move_and_slide_with_snap(velocity, Vector2.DOWN, Vector2.UP)
# Check for jumping. is_on_floor() must be called after movement code.
if is_on_floor() and Input.is_action_just_pressed("jump"):
jumping()
var on_floor = rayL.is_colliding() or rayR.is_colliding()
if walk_right:
sprite.set_flip_h(false)
if walk_left:
sprite.set_flip_h(true)
if (walk_left or walk_right) and on_floor:
sprite.play()
elif (walk_left or walk_right):
sprite.stop()
sprite.set_frame(3)
else:
sprite.stop()
sprite.set_frame(1)
if position.y > 900: dying()
func _on_Area2D_body_entered(body):
if not alive: return
jumping()
body.destroy()
func jumping():
velocity.y = -JUMP_SPEED
func _on_Area2D2_body_entered(body):
if not alive: return
dying()
func dying():
if not alive: return
alive = false
velocity.y = -500
collision_mask -= 2
emit_signal("dead")

In 2D, moving UP direction is negative on the y axis. Said another way, the Y axis is pointing downwards.
Thus, setting the velocity like this:
velocity.y = -500
Will result in upward motion, not downwards.

Related

Parser Error: Expected "," or ")" after a "signal" parameter identifier

The Player Script giving me the error.
extends KinematicBody2D
const FRICTION = 5000
const ACCELERATION = 5000
const MOVE_SPEED = 300
onready var animationPlayer = $AnimationPlayer
var velocity = Vector2.ZERO
var aim_direction: Vector2
var max_recoil: float
var current_recoil: float
# Declare the signal that will be used to add recoil to the player's aim
signal add_recoil(recoil: float)
func _ready():
aim_direction = Vector2(1, 0)
max_recoil = 20
current_recoil = 0
connect("add_recoil", self, "_on_add_recoil")
# Add recoil to the player's aim
func _on_add_recoil(recoil: float) -> void:
current_recoil += recoil
# Clamp the current recoil to the maximum recoil
current_recoil = clamp(current_recoil, 0, max_recoil)
func _physics_process(delta):
#--Local Variables--
var lerp_rate = FRICTION
#--Input Logic--
var input_vector = Vector2(Input.get_action_strength("ui_right") - Input.get_action_strength("ui_left"),
Input.get_action_strength("ui_down") - Input.get_action_strength("ui_up"))
if input_vector.y != 0: lerp_rate = ACCELERATION
#--Animation Logic--
if input_vector.y == -1:
animationPlayer.play("WalkUp")
elif input_vector.y == 1:
animationPlayer.play("WalkDown")
elif input_vector == Vector2.ZERO:
animationPlayer.stop()
#--Movement--
velocity = velocity.move_toward(MOVE_SPEED*input_vector, lerp_rate*delta)
velocity = move_and_slide(velocity)
# Slowly reduce the current recoil over time
current_recoil = lerp(current_recoil, 0, delta * 5)
# Rotate the aim direction by the current recoil
aim_direction = aim_direction.rotated(current_recoil)
The error is coming up on signal add_recoil(recoil: float)
It'll be great if any coding wises for the Godot engine could explain how to fix this.
It's supposed to receive the signal from the WeaponBaseClass script to the players aim.
The script in question:
extends KinematicBody2D
export (PackedScene) var Bullet
# Declare variables to store the properties of the weapon
export var weapon_name: String
export var recoil: float
export var damage: int
export var shooting_speed: float
export var magazine_capacity: int
export var reload_speed: float
export var attachments: Array
# Get a reference to the player kinematic node in the main scene
onready var player_node = get_node("/root/Main/Player")
# Declare a variable to store the speed of the bullets fired by the weapon
export var bullet_speed: float
onready var end_of_gun = $EndOfGun
# Declare variables to store the current state of the weapon
var current_magazine: int
var is_reloading: bool
# Initialize the weapon
func _ready():
current_magazine = magazine_capacity
is_reloading = false
func _process(delta: float) -> void:
look_at(get_global_mouse_position())
func _unhandled_input(event: InputEvent) -> void:
if event.is_action_released ("shoot"):
shoot()
if event.is_action_released ("reload"):
reload()
# Shoot the weapon
func shoot():
# Check if the weapon is reloading or out of ammo
if is_reloading or current_magazine <= 0:
return
# Decrement the magazine size
current_magazine -= 1
# Emit the "add_recoil" signal to tell the player to add recoil to their aim
EventBus.emit_signal("add_recoil", recoil)
# Send the add_recoil signal to the player
player_node.add_recoil(recoil)
# Play a shooting sound effect
#audio_play("shoot.wav")
# Spawn a bullet and apply damage to any enemies it hits
var bullet = preload("Bullet.tscn").instance()
# Set the bullet speed
#bullet.set_linear_velocity(Vector2(BULLET_SPEED, 0))
var target = get_global_mouse_position()
var direction_to_mouse = end_of_gun.global_position.direction_to(target).normalized()
bullet.rotation = get_global_transform().get_rotation()
EventBus.emit_signal("fired_bullet", bullet, end_of_gun.global_position, direction_to_mouse)
bullet.damage = damage
add_child(bullet)
# Reload the weapon
func reload():
# Check if the weapon is already reloading
if is_reloading:
return
# Set the reloading flag
is_reloading = true
# Play a reloading sound effect
#audio_play("reload.wav")
# Call the reload animation
$AnimationPlayer.play("reload")
# Wait for the reload time to elapse
yield(get_tree().create_timer(reload_speed), "timeout")
# Reset the reloading flag and refill the magazine
is_reloading = false
current_magazine = magazine_capacity
I also have an EventBus script if that helps:
extends Node
#Only holds signals
signal fired_bullet(bullet, position, direction)
GDScript in Godot 3 does not support specifying types for signal parameters. It would work in Godot 4.
So Godot 3 won't parse this:
signal add_recoil(recoil: float)
Instead you would have to drop the type:
signal add_recoil(recoil)

Model Shakes when moved long distance - Godot

I am making a space game in Godot and whenever my ship is a big distance away from (0,0,0) every time I move the camera or the ship, it shakes violently. Here is my code for moving the ship:
extends KinematicBody
export var default_speed = 500000
export var max_speed = 5000
export var acceleration = 100
export var pitch_speed = 1.5
export var roll_speed = 1.9
export var yaw_speed = 1.25
export var input_response = 8.0
var velocity = Vector3.ZERO
var forward_speed = 0
var vert_speed = 0
var pitch_input = 0
var roll_input = 0
var yaw_input = 0
var alt_input = 0
var system = "System1"
func _ready():
look_at(get_parent().get_node("Star").translation, Vector3.UP)
func get_input(delta):
if Input.is_action_pressed("boost"):
max_speed = 299792458
acceleration = 100
else:
max_speed = default_speed
acceleration = 100
if Input.is_action_pressed("throttle_up"):
forward_speed = lerp(forward_speed, max_speed, acceleration * delta)
if Input.is_action_pressed("throttle_down"):
forward_speed = lerp(forward_speed, 0, acceleration * delta)
pitch_input = lerp(pitch_input, Input.get_action_strength("pitch_up") - Input.get_action_strength("pitch_down"), input_response * delta)
roll_input = lerp(roll_input, Input.get_action_strength("roll_left") - Input.get_action_strength("roll_right"), input_response * delta)
yaw_input = lerp(yaw_input, Input.get_action_strength("yaw_left") - Input.get_action_strength("yaw_right"), input_response * delta)
func _physics_process(delta):
get_input(delta)
transform.basis = transform.basis.rotated(transform.basis.z, roll_input * roll_speed * delta)
transform.basis = transform.basis.rotated(transform.basis.x, pitch_input * pitch_speed * delta)
transform.basis = transform.basis.rotated(transform.basis.y, yaw_input * yaw_speed * delta)
transform.basis = transform.basis.orthonormalized()
velocity = -transform.basis.z * forward_speed * delta
move_and_collide(velocity * delta)
func _on_System1_area_entered(area):
print(area, area.name)
system = "E"
func _on_System2_area_entered(area):
print(area, area.name)
system = "System1"
Is there any way to prevent this from happening?
First of all, I want to point out, that this is not a problem unique to Godot. Although other engines have automatic fixes for it.
This happens because the precision of floating point numbers decreases as it goes away form the origin. In other words, the gap between one floating number and the next becomes wider.
The issue is covered in more detail over the game development sister site:
Why loss of floating point precision makes rendered objects vibrate?
Why does the resolution of floating point numbers decrease further from an origin?
What's the largest "relative" level I can make using float?
Why would a bigger game move the gameworld around the Player instead of just moving a player within a gameworld?
Moving player inside of moving spaceship?
Spatial Jitter problem in large unity project
Godot uses single precision. Support for double precision has been added in Godot 4, but that just reduces the problem, it does not eliminate it.
The general solution is to warp everything, in such way that the player is near the origin again. So, let us do that.
We will need a reference to the node we want to keep near the origin. I'm going to assume which node it is does not change during game play.
export var target_node_path:NodePath
onready var _target_node:Spatial = get_node(target_node_path)
And we will need a reference to the world we need to move. I'm also assuming it does not change. Furthermore, I'm also assuming the node we want to keep near the origin is a child of it, directly or indirectly.
export var world_node_path:NodePath
onready var _world_node:Node = get_node(target_node_path)
And we need a maximum distance at which we perform the shift:
export var max_distance_from_origin:float = 10000.0
We will not move the world itself, but its children.
func _process() -> void:
var target_origin := _target_node.global_transform.origin
if target_origin.length() < max_distance_from_origin:
return
for child in _world_node.get_children():
var spatial := child as Spatial
if spatial != null:
spatial.global_translate(-target_origin)
Now, something I have not seen discussed is what happens with physics objects. The concern is that The physics server might be trying to move them in the old position (in practice this is only a problem with RigidBody), and it will overwrite what we did.
So, if that is a problem… We can handle physic objects with a teleport. For example:
func _process() -> void:
var target_origin := _target_node.global_transform.origin
if target_origin.length() < max_distance_from_origin:
return
for child in _world_node.get_children():
var spatial := child as Spatial
if spatial != null:
var body_transform := physics_body.global_transform
var new_transform := Transform(
body_transform.basis,
body_transform.origin - target_origin
)
spatial.global_transform = new_transform
var physics_body := spatial as PhysicsBody # Check for RigidBody instead?
if physics_body != null:
PhysicsServer.body_set_state(
physics_body.get_rid(),
PhysicsServer.BODY_STATE_TRANSFORM,
new_transform
)
But be aware that the above code does not consider any physics objects deeper in the scene tree.

Godot - How do you make Player and Enemy bounce when damaged

In my game I want it so when either the player or the enemy gets damaged they bounce but i do not know how to do so.
code for player:
extends KinematicBody2D
var speed = 200 # speed in pixels/sec
var velocity = Vector2.ZERO
var hasDagger = false
func get_input():
velocity = Vector2.ZERO
if Input.is_action_pressed('right'):
velocity.x += 1
if Input.is_action_pressed('left'):
velocity.x -= 1
if Input.is_action_pressed('down'):
velocity.y += 1
if Input.is_action_pressed('up'):
velocity.y -= 1
if Input.is_action_just_pressed("sprint"):
speed += 100
if Input.is_action_just_released("sprint"):
speed -= 100
# Make sure diagonal movement isn't faster
velocity = velocity.normalized() * speed
func _physics_process(delta):
get_input()
velocity = move_and_slide(velocity)
enemy code:
extends KinematicBody2D
var run_speed = 201
var velocity = Vector2.ZERO
var collider = null
var health = 3
func _physics_process(delta):
velocity = Vector2.ZERO
if collider:
#print(collider)
velocity = global_position.direction_to(collider.global_position) * run_speed
velocity = move_and_slide(velocity)
func _on_DetectRadius_body_entered(body):
collider = body
func _on_DetectRadius_body_exited(body):
collider = null
func _on_hit_box_body_entered(body):
health -= 1
if health == 0:
get_tree().change_scene("res://scenes/game over.tscn")
the health you see in the enemy script is for the player
the player is a kinematicbody2D with a colilistionshape2D and the enemy is the same as that
What I'm going to show is not the only way to go about this - In fact, we should be talking about animations and states - instead it is just one way to tackle this.
I'll define a variable target. I'll leave it without specifying a type, so it is variant. However, I'll have it be Vector2. The reason I leave it variant, is so it can be null. If I could, I'd type it as a nullable Vector2, but Godot does not support that.
The idea is to have the KinematicBody2D go to the target position if it is a Vector2. But if it isn't, let the regular movement continue. Something like this:
export var speed:float
var velocity := Vector2.ZERO
var target = null
func _physics_process(_delta:float) -> void:
if target != null:
velocity = global_position.direction_to(target) * speed
else:
# call get_input or whatever
pass
velocity = move_and_slide(velocity)
I'll add a method for this, it will make things easier:
export var speed:float
var velocity := Vector2.ZERO
var target = null
func _physics_process(_delta:float) -> void:
if not advance_to_target():
# call get_input or whatever
pass
velocity = move_and_slide(velocity)
func advance_to_target() -> bool:
if target == null:
return false
velocity = global_position.direction_to(target) * speed
return true
Well, we should clear target when we reach it, and we should not overshoot. Let us fix that:
export var speed:float
var velocity := Vector2.ZERO
var target = null
func _physics_process(_delta:float) -> void:
if not advance_to_target():
target = null
# call get_input or whatever
velocity = move_and_slide(velocity)
func advance_to_target() -> bool:
if target == null:
return false
var displacement := target - global_position
var distance := displacement.length()
if is_zero_approx(distance):
return false
var time := get_physics_process_delta_time()
var max_speed := distance / time
var direction := displacement / distance
velocity = direction * min(speed, max_speed)
return true
Here we are computing max_speed, which is the speed at which the KinematicBody2D would have to move to reach the target in the current physics frame. Any faster than that, and it would overshoot. So we use min(speed, max_speed) to make sure the actual speed is capped at that.
And when the target is reached we would have found that the distance is zero. Well, almost zero. Because of rounding errors we cannot rely on it hitting zero exactly. That is why I use is_zero_approx(distance). This also avoids a division by zero at displacement / distance.
For the enemy we can co-opt this system to chase the collider… Let us refactor to make that easier:
export var speed:float
var velocity := Vector2.ZERO
var target = null
var collider = null
func _physics_process(_delta:float) -> void:
var target_position = null
if target != null:
target_position = target
elif collider != null:
target_position = collider.global_position
if not advance_to(target_position):
target = null
velocity = move_and_slide(velocity)
func advance_to(target_position) -> bool:
if target_position == null:
return false
var displacement := position - global_position
var distance := displacement.length()
if is_zero_approx(distance):
return false
var time := get_physics_process_delta_time()
var max_speed := distance / time
var direction := displacement / distance
velocity = direction * min(speed, max_speed)
return true
Or we can add get_input into it:
export var speed:float
var velocity := Vector2.ZERO
var target = null
func _physics_process(_delta:float) -> void:
if not advance_to(target):
target = null
get_input()
velocity = move_and_slide(velocity)
func advance_to(target_position) -> bool:
if target_position == null:
return false
var displacement := position - global_position
var distance := displacement.length()
if is_zero_approx(distance):
return false
var time := get_physics_process_delta_time()
var max_speed := distance / time
var direction := displacement / distance
velocity = direction * min(speed, max_speed)
return true
func get_input():
velocity = Vector2.ZERO
if Input.is_action_pressed('right'):
velocity.x += 1
if Input.is_action_pressed('left'):
velocity.x -= 1
if Input.is_action_pressed('down'):
velocity.y += 1
if Input.is_action_pressed('up'):
velocity.y -= 1
if Input.is_action_just_pressed("sprint"):
speed += 100
if Input.is_action_just_released("sprint"):
speed -= 100
# Make sure diagonal movement isn't faster
velocity = velocity.normalized() * speed
Ah, yes, the damage. We are going to set a target when we register the collision. Something like this:
export var push_back_distance:float
func _on_hit_box_body_entered(body):
var direction := global_position.direction_to(body.global_position)
target = global_position - direction * push_back_distance
# the rest of the code here
That should make the KinematicBody2D move away from whatever it collided with.

Basic movement 3D code not working properly

I wrote some code down for a kinematic character and only the W key(forward) worked, when I pressed w and d or a that's` when it starts moving but slowly goes left or right. Does anybody know how to fix this?
extends KinematicBody
var gravity =Vector3.DOWN * 12
var speed = 4
var jump_speed = 6
var spin = 0.1
var velocity = Vector3()
func _physics_process(delta):
velocity += gravity * delta
get_input()
velocity = move_and_slide(velocity,Vector3.UP)
func get_input():
velocity.x = 0
velocity.z = 0
if Input.is_action_pressed("move_UP"):
velocity.z -= speed
if Input.is_action_pressed("move_DOWN"):
velocity.x -= speed
if Input.is_action_pressed("strafe_Right"):
velocity.x -= speed
if Input.is_action_pressed("strafe_Left"):
velocity.z -= speed
func _unhandled_input(event):
if event is InputEventMouseMotion:
rotate_y(-lerp(0, spin, event.relative.x/10))
Um. Python code? Blocks are controlled by indentation. You've indented all your motion conditionals after move_UP so that they can only be executed if move_UP is active and executed first. Unindent the three "If" statements under the move_UP statement...

BabylonJS - Remove smooth animation on the camera

I'm using BabylonJS to make a little game.
I'm using this code to build a camera :
this.cam = new BABYLON.FreeCamera("playerCamera", new BABYLON.Vector3(x, y, z), s);
this.cam.checkCollisions = true;
this.cam.applyGravity = false;
this.cam.keysUp = [90]; // Z
this.cam.keysDown = [83]; // S
this.cam.keysLeft = [81]; // Q
this.cam.keysRight = [68]; // D
this.cam.speed = v;
this.cam.ellipsoid = new BABYLON.Vector3(1, h, 1);
this.cam.angularSensibility = a;
And it works, i have a camera, i can move around ect ...
But my problem is here : by default they are a smooth animation when a move and when i change the orientation of the camera.
Let me explain : When i move with my arrow keys (aproximately 20 pixels to the left) it will go to 25 pixels (20 pixels + 5 smooths pixels).
I don't want it :/ Do you know how o disable it ? (To move and change orientation of the camera).
This is due to the inertia defined in the free camera.
To remove this "smooth" movements, simply disable inertia:
this.cam.inertia = 0;