Animation plays only the first frame Godot - godot

Im making a simple platformer. I have 3 movements that the player can do, run, jump and walk. The walking and jumping functions run fine but I have a problem with the run function, it seems to work but the animation only plays the first frame, which does not happen for any other animation.
extends KinematicBody2D
var speed : int = 200
var jumpforce: int = 500
var gravity: int = 1000
var vel: Vector2 = Vector2()
onready var sprite: Sprite = get_node("Sprite")
onready var anim = get_node("AnimationPlayer").get_animation("walk")
onready var anim2 = get_node("AnimationPlayer").get_animation("run")
func _physics_process(delta):
vel.x = 0
#movement
if Input.is_action_pressed("move_left"):
vel.x -= speed
anim.set_loop(true)
get_node("AnimationPlayer").play("walk")
if Input.is_action_pressed("move_right"):
vel.x += speed
anim.set_loop(true)
get_node("AnimationPlayer").play("walk")
#return to idle
if Input.is_action_just_released("move_right") or Input.is_action_just_released("move_left"):
$AnimationPlayer.play("idle")
#run
if Input.is_action_pressed("move_left") and Input.is_action_pressed("shift"):
vel.x -= speed
anim2.set_loop(true)
get_node("AnimationPlayer").play("run")
if Input.is_action_pressed("move_right") and Input.is_action_pressed("shift"):
vel.x += speed
anim2.set_loop(true)
get_node("AnimationPlayer").play("run")
#physic and jump
vel.y += gravity * delta
if Input.is_action_pressed("jump") and is_on_floor():
vel.y -= jumpforce
vel = move_and_slide(vel, Vector2.UP)
if vel.x < 0:
sprite.flip_h = true
elif vel.x > 0:
sprite.flip_h = false

Hi Man i am not sure if you still need Help but here is my solution:
extends KinematicBody2D
var speed : int = 200
var jumpforce: int = 500
var gravity: int = 1000
var vel: Vector2 = Vector2()
onready var sprite: Sprite = get_node("Sprite")
func _physics_process(delta):
vel.x = 0
#movement
#run
if Input.is_action_pressed("move_left") and Input.is_action_pressed("shift"):
vel.x -= speed
$AnimationPlayer.play("run")
elif Input.is_action_pressed("move_right") and Input.is_action_pressed("shift"):
vel.x += speed
$AnimationPlayer.play("run")
elif Input.is_action_pressed("move_left"):
vel.x -= speed
$AnimationPlayer.play("walk")
elif Input.is_action_pressed("move_right"):
vel.x += speed
$AnimationPlayer.play("walk")
#return to idle
else:
$AnimationPlayer.play("idle")
#physic and jump
vel.y += gravity * delta
if Input.is_action_pressed("jump") and is_on_floor():
vel.y -= jumpforce
vel = move_and_slide(vel, Vector2.UP)
if vel.x < 0:
sprite.flip_h = true
elif vel.x > 0:
sprite.flip_h = false
The problem was that you had a bunch of if statements and every tick both the run and walk if statements were true. So for example you press left and shift. The walk left if statement is true and the animation gets set to walk. Then the run if statement is also true and your animation gets set to run. The next frame the walk animation if statement is true again which means it gets set to the walk animation again. Then the run animation is true which sets the animation to the run animation but because we are switching the animation it sets the frame to 0 and starts the animation again.

Related

Godot Dash Function

So, the code I have for a dash function is not working correctly even though im positive the logic is correct. I suspected the problem was with the variable isdashing so I printed out the value for it and comes back false no matter what I do. Can anyone tell me what im doing wrong?
extends KinematicBody2D
export(int) var Jump_Height = -100
export(int) var Jump_Realese = -60
export(int) var gravity = 4
var velocity = Vector2.ZERO
var move_speed = 50
#Jump Stuff
var max_jump = 2
var jump_count = 0
# Dash Stuff
var dash_direction = Vector2(1,0)
var dashable = false
var isdashing = false
# Movement
func _physics_process(delta):
dash()
gravity_control()
if Input.is_action_pressed("ui_right"):
velocity.x = move_speed
elif Input.is_action_pressed("ui_left"):
velocity.x = -move_speed
else:
velocity.x = 0
if is_on_floor() and jump_count != 0:
jump_count = 0
if jump_count<max_jump:
if Input.is_action_just_pressed("ui_up"):
velocity.y = Jump_Height
jump_count += 1
else:
if Input.is_action_just_released("ui_up") and velocity.y < Jump_Realese:
velocity.y = Jump_Realese
velocity = move_and_slide(velocity, Vector2.UP)
func dash():
if is_on_floor():
dashable = true
if Input.is_action_pressed("ui_left"):
dash_direction = Vector2(-1,0)
if Input.is_action_pressed("ui_right"):
dash_direction = Vector2(1,0)
if Input.is_action_just_pressed("ui_Dash") and dashable:
velocity = dash_direction.normalized() * 7000
dashable = false
isdashing = true
yield(get_tree().create_timer(0.2), "timeout")
isdashing = false
It's likely that Input.is_action_just_pressed("ui_Dash") is false because dash() is being called in the physics_process function which doesn't run every frame (it runs 60 times a second).
What currently happens is -
During a game frame, the user presses the dash button. At this point Input.is_action_just_pressed("ui_Dash") is true but nothing has checked it.
A frame or two (or more) later, the dash function is called in the physics_process. This polls if the dash button was just pressed - but now it's false because it was "just pressed" a few frames ago, not on this frame.
The only way your current logic works is if the dash button was pressed in the EXACT frame that the physics_process runs.
You can get around this by using Input.is_action_pressed("ui_Dash") to capture the button press, setting a flag to prevent it being captured on the next physics frame and then enabling it again sometime later. E.g.
var can_dash: boolean = true
func dash():
if is_on_floor():
dashable = true
if Input.is_action_pressed("ui_left"):
dash_direction = Vector2(-1,0)
if Input.is_action_pressed("ui_right"):
dash_direction = Vector2(1,0)
if can_dash and Input.is_action_pressed("ui_Dash") and dashable:
can_dash = false;
velocity = dash_direction.normalized() * 7000
dashable = false
isdashing = true
yield(get_tree().create_timer(0.2), "timeout")
isdashing = false
can_dash = true
You are resetting your variables (especially velocity) before calling move_and_slide().
Solution: Call dash() immediately before calling move_and_slide().
This is the reset I'm referring to:
if Input.is_action_pressed("ui_right"):
velocity.x = move_speed
elif Input.is_action_pressed("ui_left"):
velocity.x = -move_speed
else:
velocity.x = 0

Godot player not walking in the direction

So I am new to godot and I was having a problem. The players body doesnt follow the camera when the camera moves When I look around with the camera the players body stays the same e.g. if i use wasd if i turn to the right it would be aswd. the player movement is hard but i got help. if you could help that will be super cool, i am just trying to learn coding. this is hard for me.
p.s sorry for the bad grammar
extends KinematicBody
signal hit
# How fast the player moves in meters per second.
export var speed = 14
# The downward acceleration when in the air, in meters per second squared.
export var fall_acceleration = 50
# Vertical impulse applied to the character upon jumping in meters per second.
export var jump_impulse = 30
# Vertical impulse applied to the character upon bouncing over a mob in meters per second.
export var bounce_impulse = 16
# stats
var curHP : int = 10
var maxHP : int = 10
var ammo : int = 15
var score : int = 0
# cam look
var minLookAngle : float = -90.0
var maxLookAngle : float = 90.0
var lookSensitivity : float = 10.0
# vectors
var vel : Vector3 = Vector3()
var mouseDelta : Vector2 = Vector2()
# components
onready var camera : Camera = get_node("Camera")
onready var muzzle : Spatial = get_node("Camera/Muzzle")
# Emitted when a mob hit the player.
var velocity = Vector3.ZERO
func _physics_process(delta):
var direction = Vector3.ZERO
if Input.is_action_pressed("move_right"):
direction.x += 1
if Input.is_action_pressed("move_left"):
direction.x -= 1
if Input.is_action_pressed("move_back"):
direction.z += 1
if Input.is_action_pressed("move_forward"):
direction.z -= 1
#sprinting
if Input.is_action_pressed("move_sprint"):
speed = 50
if Input.is_action_just_released("move_sprint"):
speed = 14
velocity.x = direction.x * speed
velocity.z = direction.z * speed
# Jumping.
if is_on_floor() and Input.is_action_just_pressed("move_jump"):
velocity.y += jump_impulse
velocity.y -= fall_acceleration * delta
velocity = move_and_slide(velocity, Vector3.UP)
func _ready():
# hide and lock the mouse cursor
Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
func _process(delta):
# rotate the camera along the x axis
camera.rotation_degrees.x -= mouseDelta.y * lookSensitivity * delta
# clamp camera x rotation axis
camera.rotation_degrees.x = clamp(camera.rotation_degrees.x, minLookAngle, maxLookAngle)
# rotate the player along their y-axis
rotation_degrees.y -= mouseDelta.x * lookSensitivity * delta
# reset the mouseDelta vector
mouseDelta = Vector2()
func _input(event):
if event is InputEventMouseMotion:
mouseDelta = event.relative
If you want the movement to be based on the orientation of camera...
Then base the movement:
var direction = Vector3.ZERO
if Input.is_action_pressed("move_right"):
direction.x += 1
if Input.is_action_pressed("move_left"):
direction.x -= 1
if Input.is_action_pressed("move_back"):
direction.z += 1
if Input.is_action_pressed("move_forward"):
direction.z -= 1
On the orientation of the camera.
We will use camera.global_transform.basis. The basis of a transform gives us a set of vectors that are aligned to the axis of the transformed space.
Using camera.transform instead of camera.global_transform will NOT work, because the Camera is a child of the KinematicBody.
Then your code ends up like this:
var direction = Vector3.ZERO
var camera_x = camera.global_transform.basis.x
var camera_z = camera.global_transform.basis.z
if Input.is_action_pressed("move_right"):
direction += camera_x
if Input.is_action_pressed("move_left"):
direction -= camera_x
if Input.is_action_pressed("move_back"):
direction += camera_z
if Input.is_action_pressed("move_forward"):
direction -= camera_z
Complete script on OP request:
extends KinematicBody
#signal hit
# How fast the player moves in meters per second.
export var speed = 14
# The downward acceleration when in the air, in meters per second squared.
export var fall_acceleration = 50
# Vertical impulse applied to the character upon jumping in meters per second.
export var jump_impulse = 30
# Vertical impulse applied to the character upon bouncing over a mob in meters per second.
# export var bounce_impulse = 16
# stats
# var curHP : int = 10
# var maxHP : int = 10
# var ammo : int = 15
# var score : int = 0
# cam look
var minLookAngle : float = -90.0
var maxLookAngle : float = 90.0
var lookSensitivity : float = 10.0
# vectors
# var vel : Vector3 = Vector3()
var mouseDelta : Vector2 = Vector2()
# components
onready var camera : Camera = get_node("Camera")
# onready var muzzle : Spatial = get_node("Camera/Muzzle")
# Emitted when a mob hit the player.
var velocity = Vector3.ZERO
func _physics_process(delta):
var direction = Vector3.ZERO
var camera_x = camera.global_transform.basis.x
var camera_z = camera.global_transform.basis.z
if Input.is_action_pressed("move_right"):
direction += camera_x
if Input.is_action_pressed("move_left"):
direction -= camera_x
if Input.is_action_pressed("move_back"):
direction += camera_z
if Input.is_action_pressed("move_forward"):
direction -= camera_z
#sprinting
if Input.is_action_pressed("move_sprint"):
speed = 50
if Input.is_action_just_released("move_sprint"):
speed = 14
velocity.x = direction.x * speed
velocity.z = direction.z * speed
# Jumping.
if is_on_floor() and Input.is_action_just_pressed("move_jump"):
velocity.y += jump_impulse
velocity.y -= fall_acceleration * delta
velocity = move_and_slide(velocity, Vector3.UP)
func _ready():
# hide and lock the mouse cursor
Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
func _process(delta):
# rotate the camera along the x axis
camera.rotation_degrees.x -= mouseDelta.y * lookSensitivity * delta
# clamp camera x rotation axis
camera.rotation_degrees.x = clamp(camera.rotation_degrees.x, minLookAngle, maxLookAngle)
# rotate the player along their y-axis
rotation_degrees.y -= mouseDelta.x * lookSensitivity * delta
# reset the mouseDelta vector
mouseDelta = Vector2()
func _input(event):
if event is InputEventMouseMotion:
mouseDelta = event.relative

Animation bug. Using godot game engine

I am working on a game and for some reason when I try to call the hit_check() function it won't animate the sprite. all of the other animations have worked perfectly which is why I'm confused.
Heres my script:
extends KinematicBody2D
var motion = Vector2(0,0)
const SPEED = 130
const GRAVITY = 15
const UP = Vector2(0,-1)
const JUMP_SPEED = 350
func _physics_process(delta):
apply_gravity()
hit_check()
jump_check()
move_check()
move_and_slide(motion, UP)
func apply_gravity():
if not is_on_floor():
motion.y += GRAVITY
else:
motion.y = 0
func jump_check():
if Input.is_action_pressed("jump") and is_on_floor():
motion.y -= JUMP_SPEED
func move_check():
if Input.is_action_pressed('left'):
$PlayerAnimation.flip_h = true
$PlayerAnimation.play("walk")
motion.x = -SPEED
elif Input.is_action_pressed('right'):
$PlayerAnimation.flip_h = false
$PlayerAnimation.play("walk")
motion.x = SPEED
else:
motion.x = 0
$PlayerAnimation.play("idle")
func hit_check():
if Input.is_action_pressed("hit"):
$PlayerAnimation.play("hit")
jump_check and move_check functions are called after hit_check function, and move_check function always overrides the current animation of the node because there is an animation specified in both if and else blocks.

i was making a Godot platformer with the help of a video on Youtube I've done everything same as him but my character refuses to move left

I'm trying to make a 2d platformer in godot with help from one of the the videos. video link: https://www.youtube.com/watch?v=PG0tfoPraE4. I have very little experience working with Godot.
I'm stuck and am not sure what to do, I've tried looking at some more videos as a last resort but all of them use another way of movement.
Here is the code
GDSCRIPT
extends KinematicBody2D
const MOVESPEED = 70
const JUMPFORCE = -200
const GRAVITY = 600
var motion = Vector2()
func _physics_process(delta):
if is_on_floor():
if Input.is_action_just_pressed("ui_up"):
motion.y = JUMPFORCE
if Input.is_action_pressed("ui_left"):
motion.x = -MOVESPEED
$Sprite.flip_h = true
$AnimationPlayer.play("walk")
if Input.is_action_pressed("ui_right"):
motion.x = MOVESPEED
$Sprite.flip_h = false
$AnimationPlayer.play("walk")
else:
motion.x = 0
$AnimationPlayer.stop()
motion.y += GRAVITY * delta
motion = move_and_slide(motion, Vector2(0,-1))
Your code path is falling into the else clause of the right movement. So preventing it to move.
Just add and else to the right if, like:
if Input.is_action_pressed("ui_left"):
motion.x = -MOVESPEED
$Sprite.flip_h = true
$AnimationPlayer.play("walk")
elif Input.is_action_pressed("ui_right"):
motion.x = MOVESPEED
$Sprite.flip_h = false
$AnimationPlayer.play("walk")
else:
motion.x = 0
$AnimationPlayer.stop()

How can I make the player and enemies fall to the ground when they die?

I'm making my first game in Godot.
No matter what I try, if the player/enemies die while in the air, they stay there. I want them to fall to the ground when they die. Help?
While at it if you have any pointers based on what you can see from my code, I'll really appreciate it. Especially when it comes to player movement and such. Currently, very few actions feel smooth; a lot of stuff feels rather rigid and wonky (jumping, falling from edges, and the enemy's collision shape somehow displaces itself as the enemy moves).
PLAYER CODE:
var motion = Vector2 ()
var is_in_attack = false
var fireball_power = 1
var is_dead = false
var is_jumping = false
func _physics_process(delta):
if is_dead == false:
motion.y += GRAVITY
var friction = false
if Input.is_action_pressed("ui_right"):
if is_in_attack == false || is_on_floor() == false:
motion.x = min(motion.x+ACCELERATION, MAX_SPEED)
if is_in_attack == false:
$Sprite.flip_h = false
$Sprite.play("run")
if sign($FireballPosition2D.position.x) == -1:
$FireballPosition2D.position.x *= -1
if sign($FireballPosition2D2.position.x) == -1:
$FireballPosition2D2.position.x *= -1
if sign($ArrowPosition2D.position.x) == -1:
$ArrowPosition2D.position.x *= -1
elif Input.is_action_pressed("ui_left"):
if is_in_attack == false || is_on_floor() == false:
motion.x = max(motion.x-ACCELERATION, -MAX_SPEED)
if is_in_attack == false:
$Sprite.flip_h = true
$Sprite.play("run")
if sign($FireballPosition2D.position.x) == 1:
$FireballPosition2D.position.x *= -1
if sign($FireballPosition2D2.position.x) == 1:
$FireballPosition2D2.position.x *= -1
if sign($ArrowPosition2D.position.x) == 1:
$ArrowPosition2D.position.x *= -1
else:
if is_in_attack == false:
$Sprite.play("idle")
friction = true
var snap = Vector2.DOWN *32 if !is_jumping else Vector2.ZERO
motion = move_and_slide_with_snap(motion,snap, UP)
pass
if get_slide_count() > 0:
for i in range(get_slide_count()):
if "Enemy" in get_slide_collision(i).collider.name:
dead()
for i in get_slide_count():
var collision = get_slide_collision(i)
if collision.collider.has_method("collide_with"):
collision.collider.collide_with(collision, self)
func dead():
is_dead = true
motion = Vector2(0,0)
$CollisionShape2D.set_deferred("disabled", true)
$Sprite.play("dead")
$Timer.start()
PlayerData.deaths += 1
func _on_attackarea_body_entered(body):
if "Enemy" in body.name:
body.dead(1)
ENEMY CODE:
const UP = Vector2 (0, -1)
const GRAVITY = 20
const ACCELERATION = 50
const JUMP_HEIGHT = -500
var motion = Vector2 ()
var direction = 1
var is_dead = false
export(int) var speed = 50
export(int) var hp = 1
export(Vector2) var size = Vector2(1, 1)
export var score: = 100
func _ready():
scale = size
pass
func dead(damage):
hp = hp -damage
if hp <=0:
is_dead = true
motion = Vector2(0,0)
$AnimatedSprite.play("dead")
$CollisionShape2D.set_deferred("disabled", true)
$Timer.start()
PlayerData.score += score
#calling the screenshake for large enemies
if scale > Vector2(1.6, 1.6):
get_parent().get_node("ScreenShake").screen_shake(1, 10, 100)
func _physics_process(delta):
if is_dead == false:
motion.x = speed * direction
if direction == 1:
$AnimatedSprite.flip_h = false
$CollisionShape2D.position.x = 1
else:
$AnimatedSprite.flip_h = true
$CollisionShape2D.position.x = -1
$AnimatedSprite.play("walk")
motion.y += GRAVITY
motion = move_and_slide(motion, UP)
if is_on_wall():
direction = direction * -1
if get_slide_count() > 0:
for i in range (get_slide_count()):
if "Player" in get_slide_collision(i).collider.name:
get_slide_collision(i).collider.dead()
Since it worked, I will add it as an official answer:
you only move the character in your physics_process as long as he is still alive:
func _physics_process(delta):
if is_dead == false:
# all the gravity code is in here.
Add an else statement for 'if is_dead == false' which moves the node on y direction as long as its not on the ground. Something like that should work:
func _physics_process(delta):
if is_dead == false:
# your code
else:
if not is_on_floor():
motion.y += GRAVITY
motion = move_and_slide(motion, UP)

Resources