Godot 2D WASD Movement - godot

I have a trouble with a 2D Godot Project.
I wrote the following code in the KinematicBody2D script:
extends KinematicBody2D
export var speed = 250
var motion = Vector2()
func _physics_process(delta):
motion = Vector2.ZERO
if Input.is_action_just_pressed("ui_left"):
motion.x = -speed
if Input.is_action_just_pressed("ui_right"):
motion.x = speed
if Input.is_action_just_pressed("ui_up"):
motion.y = -speed
if Input.is_action_just_pressed("ui_down"):
motion.y = speed
motion = move_and_slide(motion)
pass # Replace with function body.
The problem is that my player is only moving a few pixels and stops while I'm pressing the W, A, S, D or the arrow keys.
What I've done wrong?
Thank you all!

The function is_action_just_pressed tells you if the named action※ was just pressed. It will not continue returning true if the action is held.
This, combined with the fact that you are erasing motion each physic frame motion = Vector2.ZERO, result in the object moving one physics frame and then it stops.
If you want to know if the action is currently pressed - independently of when it began being pressed - use is_action_pressed instead.
※: The actions you can use with these functions are configured in the Project Settings. You will find them on the "Input Map" tab.

Related

Godot - Enemy does not move to player when player is on the left

The enemy in my game will not move towards the left when player is on the left but will move to the right. Then when the player is on the right the enemy will move to the player.
code for enemy:
extends KinematicBody2D
var run_speed = 100
var velocity = Vector2.ZERO
var collider = null
func _physics_process(delta):
velocity = Vector2.ZERO
if collider:
velocity = position.direction_to(collider.position) * run_speed
velocity = move_and_slide(velocity)
func _on_DetectRadius_body_entered(body):
collider = body
func _on_DetectRadius_body_exited(body):
collider = null
I suspect you are using an Area2D and it is detecting something other than the player character. I remind you can use collision_mask and collision_layer to narrow what objects are detected. For example, are you sure the Area2D is not detecting the enemy itself? For a quick check you can have Godot print the collider to double check it is what you expect.
Furthermore, notice that wen an object leaves the Area2D it will set collider to null regardless if there is still some object inside the Area2D or not. I remind you that an alternative approach is using get_overlapping_bodies.
And, of course, you can query each body you get to see if it is the player character (for example by checking its node group, name, class, etc...). I go over filtering in more detail in another answer.
If you are getting the player character, there is another possible source of problems: position vs global_position. The code you have like this:
position.direction_to(collider.position)
Is correct if both the enemy and the collider it got have the same parent. In that case their positions are in the same space. Otherwise, you may want to either work on global coordinates:
global_position.direction_to(collider.global_position)
Or you can bring the collider position to local coordinates:
position.direction_to(to_local(collider.global_position))
And of course, double check that the Area2D is positioned correctly. You can enable "Visible Collision Shapes" on the "Debug" menu, which will show it when running the game from the editor.

Godot 3.3.2 - Changing child variables from the parent without them being reset

I'm new to godot and I was trying to make a asteriods type game. But i'm having trouble getting my space ship to shoot.
The issue is that I can't get the bullet to fire in direction of the ship. I set an 'angle' variable in the ship and assign it to the bullet once it has been instanced, but i'm not sure how to use it in the bullet. The bullet will just move right no matter the angle of the ship.
Ship Firing Code:
func _process(_delta):
if Input.is_action_just_pressed("action_fire"):
var Bullet_Instance = Bullet.instance()
Bullet_Instance.angle = angle
owner.add_child(Bullet_Instance)
Bullet Code:
extends KinematicBody2D
var angle = 0
var direction = Vector2(cos(angle), sin(angle))
func _physics_process(_delta):
move_and_slide(direction*500)
I'm pretty sure that the angle variable is being reset to 0 in the bullet code after it has been set in the ship code, but i'm not sure how to fix this. Thanks.
The angle variable is not being reset. The direction variable is not being updated when you set angle.
When the scene is instanced, here:
var Bullet_Instance = Bullet.instance()
These variables get their value:
var angle = 0
var direction = Vector2(cos(angle), sin(angle))
Then you set angle, here:
Bullet_Instance.angle = angle
But you don't use angle anymore, instead, you use direction:
func _physics_process(_delta):
move_and_slide(direction*500)
I'll give a few ways to solve this:
If you want direction to update every time you set angle, you could make a setter with setget. Like this:
var angle = 0 setget set_angle
func set_angle(new_value) -> void:
angle = new_value
direction = Vector2(cos(angle), sin(angle))
You could write direction directly from your other script, and not have the angle variable at all. In fact, you could set a velocity, and save tha multiplication by 500 every time.
You could compute the vector on _physics_process (you are already doing a vector scaling operation anyway):
func _physics_process(_delta):
move_and_slide(Vector2(cos(angle)*500, sin(angle)*500))
There likely are more ways to go about it. It is up to you.

KinematicBody2D not moving in Godot

I wrote some code for basic movement of a square character and it doesn’t seem to work, there were no errors and I did the indentation of the if statements correct it think, here’s the code:
Extends KinematicBody2D
var movespeed = 500
func _ready():
pass # Replace with function body.
func _physics_process(delta):
var motion = Vector2()
if Input.is_action_pressed("up"):
motion.y -= 1
if Input.is_action_pressed("down"):
motion.y += 1
if Input.is_action_pressed("left"):
motion.x += 1
if Input.is_action_pressed("right"):
motion.x -= 1
motion = motion.normalized()
motion = move_and_slide(motion * movespeed)
You code works, but you need to make sure that "up" "down" "left" "right" is present in your inputmap, without that, the code will run, but the character won't move.
Todo this, menu top left press "Project" then "Project Settings", then select Input Map tab.
You need add actions, so up, down, left right, and then once you add them, find them at the bottom of that list, and assign the key on your keyboard you wish to control the character. This is what I had to do with your code to get it working.
Firstly, Your indentation for the third if statement is wrong, it should be left one tab.
Secondly, if you add a ui_ to the front of "up", "down", etc. it should work assuming you haven't changed the settings as suggested by Stephen. These are mapped to the arrow keys by default.
Having created a blank project, the following code works in place of your existing statements:
if Input.is_action_pressed("ui_up"):
motion.y -= 1
if Input.is_action_pressed("ui_down"):
motion.y += 1
if Input.is_action_pressed("ui_left"):
motion.x += 1
if Input.is_action_pressed("ui_right"):
motion.x -= 1
Lastly, the Extends at the beginning is definitely wrong and will throw an error, it should be extends.

How to make godot infinite background scroll

In godot i have ParallaxLayer
extends ParallaxLayer
var motion = Vector2(-50, 0)
var start_pos = Vector2()
var speed = -50
# Called when the node enters the scene tree for the first time.
func _ready():
set_mirroring(motion)
pass
func _process(delta):
speed -= 5
set_motion_offset(motion+Vector2(speed,0))
this code make the background scroll but not infinite
I dont know what to do when scrolling to end
the official document say i should use set_mirroring
can somebody tell me how to use this function?
or where should i go for more information?
Mirroring expects a Vector2 value, which is the XY coordinates of the "offset" of the mirror. Typically this value would be the height or width of the image you are using as a background (which usually corresponds with the window size), depending on what direction you want to mirror. The example code below assumes a window size of 1080x1920, with the ParallaxLayer being mirrored on the Y axis.
extends ParallaxLayer
func _ready():
set_mirroring(motion_mirroring)
func _process(delta):
motion_mirroring = Vector2(0,1920)

Why does this variable keep changing to false in gdscript?

I'm trying to make this script make the ground still. When the player jumps it is supposed to make the ground and start moving and not stop. But, it is only moving when the player jumps.
My Code:
extends Area2D
#Script-Purpose: move and delete ground
#Ground moving speed
const SPEED = -150
#a vector2 to change the speed of the ground
var velocity = Vector2()
#to check if you have jumped yet
var Jumped=false
#calls Physics
func _physics_process(delta):
#left-click=jump
if Input.is_action_pressed("ui_jump"):
Jumped=true
#make the velocity.x equal to speed accounted with delta time
if Jumped==true:
print(Jumped)
velocity.x = SPEED * delta
translate(velocity)
else:
#this is here so I can check if the Jumped var is false
print(Jumped)
Jumped is false half the time and true for the other half.

Resources