I have a point and click game for which I'm adapting joypad controls. I want the mouse to move with thumbsticks and trigger mouse click with joystick A button.
I can move the mouse using get_viewport().warp_mouse(mouse_pos)
I can trigger mouse click creating new mousebuttonevent and parsing it
var left_click = InputEventMouseButton.new()
left_click.pressed = pressed
left_click.button_index = button_index
left_click.position = get_viewport().get_mouse_position()
print("emulated: ", left_click.as_text())
Input.parse_input_event(left_click)
But after I call Input.parse_input_event(left_click) and move thumsticks again it has reset the mouse position to 0, 0.
Here is the full code. I'm quite confused.
var mouse_pos
func _ready():
$ColorRect/Button.connect("pressed", self, "pressed")
func pressed():
print("button pressed")
func _input(event):
if event is InputEventMouseButton:
print("from _input: ", event.as_text())
elif event is InputEventJoypadButton:
if event.is_action_pressed("a_button"):
print("pressed A")
emulate_click(BUTTON_LEFT , true)
# elif event.is_action_released("ui_accept"):
# print("released A")
# emulate_click(BUTTON_LEFT, false)
func emulate_click(button_index, pressed):
var left_click = InputEventMouseButton.new()
left_click.pressed = pressed
left_click.button_index = button_index
left_click.position = get_viewport().get_mouse_position()
print("emulated: ", left_click.as_text())
Input.parse_input_event(left_click)
# get_viewport().warp_mouse(cached_mouse_pos)
# pointer.global_position = previous_mouse_pos
func _process(delta):
var direction: Vector2
direction.x = Input.get_action_strength ("t_right", true) - Input.get_action_strength ("t_left", true)
direction.y = Input.get_action_strength ("t_down", true) - Input.get_action_strength ("t_up", true)
if abs(direction.x) == 1 and abs(direction.y) == 1:
direction = direction.normalized()
var thumbstick_sensitivity = 1000
var movement = thumbstick_sensitivity * direction * delta
if (movement):
mouse_pos = get_viewport().get_mouse_position() + movement
print(mouse_pos)
get_viewport().warp_mouse(mouse_pos)```
Any ideas are super welcome!
You need to set the global position (global_pos) of the new InputEventMouseButton object.
This is due to the L332-L344 of input_default.cpp in Godot's source code, which read:
Ref<InputEventMouseButton> mb = p_event;
if (mb.is_valid()) {
if (mb->is_pressed()) {
mouse_button_mask |= (1 << (mb->get_button_index() - 1));
} else {
mouse_button_mask &= ~(1 << (mb->get_button_index() - 1));
}
Point2 pos = mb->get_global_position();
if (mouse_pos != pos) {
set_mouse_position(pos);
}
If you don't set the global position, it defaults to (0,0) which is why you're seeing this unexpected behaviour.
Related
im making my first 3d game for a jam and i was writing some code about the player state machine, it was all working, but when i put this code in the state_run(delta) func, it crashes:
if playerIsMoving == false:
initialize_idle()
it gives me the error invalid set intex z (base int) with value type of float.
Code:
extends KinematicBody
var sensitivity = 0.06
var speed = 10
var h_aceleration = 6
var gravity = 20
var direction = Vector3()
var h_velocity = Vector3()
var movement = Vector3()
var grav_vec = Vector3()
onready var head = $Head
enum STATES { IDLE, RUN, ATTACK, DEAD}
var state_cur : int
var state_nxt : int
var test = Vector3.ZERO
var playerIsMoving = false
func _ready():
Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
state_nxt = STATES.IDLE
func _input(event):
if event is InputEventMouseMotion:
rotate_y(deg2rad(-event.relative.x * sensitivity))
head.rotate_x(deg2rad(-event.relative.y * sensitivity))
head.rotation.x = clamp(head.rotation.x, deg2rad(-89), deg2rad(89))
func _physics_process(delta):
if state_nxt != state_cur:
state_cur = state_nxt
match state_cur:
STATES.IDLE:
state_idle(delta)
STATES.RUN:
state_run(delta)
STATES.ATTACK:
pass
STATES.DEAD:
pass
print(state_cur)
if Input.is_action_pressed("forward") or Input.is_action_pressed("backwards") or Input.is_action_pressed("left") or Input.is_action_pressed("right"):
playerIsMoving = true
else:
playerIsMoving = false
if not is_on_floor():
grav_vec += Vector3.DOWN * gravity * delta
else:
grav_vec = -get_floor_normal() * gravity
func initialize_idle():
state_nxt = STATES.IDLE
movement = 0
func state_idle(delta):
if Input.is_action_pressed("left") or Input.is_action_pressed("right") or Input.is_action_pressed("forward") or Input.is_action_pressed("backwards"):
initialize_run()
func initialize_run():
state_nxt = STATES.RUN
pass
func state_run(delta):
direction = Vector3()
if Input.is_action_pressed("forward"):
direction -= transform.basis.z
elif Input.is_action_pressed("backwards"):
direction += transform.basis.z
elif Input.is_action_pressed("left"):
direction -= transform.basis.x
elif Input.is_action_pressed("right"):
direction += transform.basis.x
else:
playerIsMoving = false
direction = direction.normalized()
h_velocity = h_velocity.linear_interpolate(direction * speed, h_aceleration * delta)
movement.z = h_velocity.z + grav_vec.z
movement.x = h_velocity.x + grav_vec.x
movement.y = grav_vec.y
move_and_slide(movement, Vector3.UP)
if playerIsMoving == false:
initialize_idle()
I alredy tried to round the value or use the int() but it isnt working, the code is giving error on the "movement.z = h_velocity.z + grav_vec.z"
Types.
Look, movement is a Variant, initialized to a Vector3:
var movement = Vector3()
And here you use it as a Vector3:
movement.z = h_velocity.z + grav_vec.z
movement.x = h_velocity.x + grav_vec.x
movement.y = grav_vec.y
move_and_slide(movement, Vector3.UP)
But here 0 is an int not a Vector3:
movement = 0
So after that movement... Continues to be a Variant, but now it has an int value. So when you use it as a Vector3 it fails. Because an int does not have x, y, z.
You can declare movement to be a Vector3 explicitly:
var movement:Vector3 = Vector3()
Or implicitly (inferred from the value you assigned):
var movement:= Vector3()
And then Godot will tell you that this line:
movement = 0
Is an error, because you are trying to set an int to a Vector3.
My guess is that you want to set movement to the zero vector, which is like this:
movement = Vector3(0.0, 0.0, 0.0)
Or like this:
movement = Vector3.ZERO
Or - similarly to how you initialized it - like this:
movement = Vector3()
I'm starting with the animations,
I have a character with movement animations for right, left and up
When uploading, the character performs the animation correctly, but on the console I get an error: "play: Animation not found: Run_Up"
error :"play: Animation not found: Idle_Up"
the error starts to come out, when I'm going up.
it stops when i go anywhere else
Error log
Error detail
Animations list
Scene
extends KinematicBody2D
var VELOCIDAD_MAXIMA = 100
var ACELERACION = 350
var FRICCION = 850
enum {
RUN,
PUSH
}
onready var animation_player = $AnimationPlayer
export var velocidad = Vector2.ZERO#(0, 0)
export var direccion_vector = Vector2.DOWN#(0, 1)
export var direccion = Vector2.ZERO#(0, 0)
export var push_finished = false
var estado = RUN
var targets = []
func run_state(delta):
var input_vector = Vector2.ZERO
input_vector.x = Input.get_action_strength("ui_right") - Input.get_action_strength("ui_left")
input_vector.y = Input.get_action_strength("ui_down") - Input.get_action_strength("ui_up")
input_vector = input_vector.normalized()
if input_vector != Vector2.ZERO:
direccion_vector = input_vector
velocidad = velocidad.move_toward(input_vector * VELOCIDAD_MAXIMA, ACELERACION * delta)
_play_animation("Run")
#Si el usuario no esta tocando al personaje
elif velocidad.length() == 0 && Input.is_action_pressed("action"):
_play_animation("Push")
if $RayCast2D.is_colliding():
push_finished = false
estado = PUSH
else:
velocidad = velocidad.move_toward(input_vector * VELOCIDAD_MAXIMA, FRICCION * delta)
_play_animation("Idle")
velocidad = move_and_slide(velocidad)
func push_state(_delta):
var collider = $RayCast2D.get_collider()
collider._on_interact($RayCast2D.rotation_degrees)
if collider:
estado = RUN
velocidad = move_and_slide(velocidad)
func animation_finished():
if !Input.is_action_pressed("action"):
estado = RUN
velocidad = Vector2.ZERO
func _physics_process(delta):
match estado:
RUN:
run_state(delta)
PUSH:
push_state(delta)
func _play_animation(animation_type: String) -> void:
var animation_name = animation_type + "_" + _get_direction_string(direccion_vector.angle())
if animation_name != animation_player.current_animation:
animation_player.stop(true)
animation_player.play(animation_name)
func _get_direction_string(angle: float) -> String:
var angle_deg = round(rad2deg(angle))
#glanced up
if angle_deg == -90:
$RayCast2D.rotation_degrees = 180
return "Up"
#glanced down
if angle_deg == 90:
$RayCast2D.rotation_degrees = 0
return "Right"
#glanced left
if angle_deg == 180:
$RayCast2D.rotation_degrees = 90
return "Left"
#glanced right
if angle_deg == 0:
$RayCast2D.rotation_degrees = -90
return "Right"
return "Right"
I was able to fix the error
apparently there was another character outside the scene that was causing conflict, since he had other types of animations
I deleted that character and it was solved
I want to make a 3D game on Godot with the player who can walk on walls and ceiling but I've tried to make this but it didn't work :(
This is the code of my Player First Person Controller:
extends KinematicBody
export var GravityDirection = Vector3(-9.8, 0, 0)
var held_object: Object
var velocity = Vector3.ZERO
var speed = 10
var MAX_SPEED = 30
var GravityStrength = 9.8
var throw_force: float = 200
var wall_one = Vector3(-9.8, 0, 0)
var wall_two = Vector3(0, 0, -9.8)
var wall_three = Vector3(9.8, 0, 0)
var wall_four = Vector3(0, 0, 9.8)
var ground = Vector3(0, -9.8, 0)
onready var ray = $"Camera/Hand/RayCast"
onready var hold_position = $"Camera/Hand/HoldPosition"
# Camera
onready var player_camera = $"Camera"
var spin = 0.1
export var mouse_sensitivity = 5
func _ready():
Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
func _physics_process(delta):
var Gravity = GravityStrength * GravityDirection
var Velocity = Gravity * delta
move_and_collide(Velocity)
var run_once = 0
while 1:
if run_once == 0:
if GravityDirection == wall_one:
rotate_x(90)
run_once = 1
player_camera.rotation_degrees.y = 180
player_camera.rotation_degrees.z = 0
if Input.is_action_just_pressed("player_fire"):
fire()
if not is_on_floor():
Velocity.y += -GravityStrength
movement(delta)
velocity = move_and_slide(velocity, Vector3.ZERO)
if Input.is_action_just_pressed("player_pick"):
if held_object:
held_object.mode = RigidBody.MODE_RIGID
held_object.collision_mask = 1
held_object = null
else:
if ray.get_collider():
held_object = ray.get_collider()
held_object.mode = RigidBody.MODE_KINEMATIC
held_object.collision_mask = 0
if held_object:
held_object.global_transform.origin = hold_position.global_transform.origin
#_process_input()
#_process_gravity()
# Mouvement
func movement(_delta):
var dir = Vector3.ZERO
var vel_y = velocity.y
velocity = Vector3.ZERO
# Movement forward and backward
if Input.is_action_pressed("player_forward"):
dir += transform.basis.z
elif Input.is_action_pressed("player_backward"):
dir -= transform.basis.z
# Movement Left and Right
if Input.is_action_pressed("player_left"):
dir += transform.basis.x
elif Input.is_action_pressed("player_right"):
dir -= transform.basis.x
velocity = dir.normalized() * speed
velocity.y = vel_y
func _input(event):
if event is InputEventMouseMotion and Input.get_mouse_mode() == Input.MOUSE_MODE_CAPTURED:
rotate_y(lerp(0, -spin, event.relative.x * (mouse_sensitivity * 0.01) ))
player_camera.rotate_x(lerp(0,spin, event.relative.y * (mouse_sensitivity * 0.01)) )
#Clamp vertical rotation
var curr_rot = player_camera.rotation_degrees
curr_rot.x = clamp(curr_rot.x, -60, 60)
player_camera.rotation_degrees = curr_rot
func fire():
print("fire")
if ray.get_collider() != null and ray.get_collider().is_in_group("enemy"):
print(ray.get_collider())
ray.get_collider().hp -= 10
Nodes Configuration
In the code, you can find fonctions for the camera and gravity system. Also, there is a fonction to pick up rigid bodies. I want to make a system where when the Gravity has a specific direction, the mesh rotate to 90°. I've made a "GlobalRay" with 6 RayCast to detect collisions (walls) and register face blablabla... you've understood but I don't know how to make a system like this!!!
I think there is a way to optimize the script, so, I need help :D
If you can perform my code it's nice! Have a nice code!
It looks like you're subtracting GravityStrength from the player's y velocity if they are not on the floor, while you should be adding the Velocity to the player's velocity. Otherwise, this question here is very general and could be implemented in a lot of ways. wall_one, wall_two, wall_three etc. I think would be better off with a magnitude of one so they could undergo the same GravityStrength modifier as everything else in later implementations, but that's just me.
I want to make a projectile weapon with GDScript but I am getting the error:
the function " _physics _process " already exists in this class (at line 35)
I cannot delete the line of code which has the error as if I do so I will not be able to make my FPS controller character move
here is the the code:
extends KinematicBody
var speed = 9
const ACCEL_DEFAULT = 7
const ACCEL_AIR = 1
onready var accel = ACCEL_DEFAULT
var gravity = 9.8
var jump = 4
var damage = 100
var cam_accel = 40
var mouse_sense = 0.1
var snap
var direction = Vector3()
var velocity = Vector3()
var gravity_vec = Vector3()
var movement = Vector3()
onready var head = $Head
onready var camera = $Head/Camera
onready var bullet = preload("res://player/world/bullet/bullet.tscn")
onready var muzzle = $Head/Gun/Muzzle
func _ready():
#hides the cursor
Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
func _input(event):
if event is InputEventMouseMotion:
rotate_y(deg2rad(-event.relative.x * mouse_sensitivity))
head.rotate_x(deg2rad(-event.relative.y * mouse_sensitivity))
head.rotation.x = clamp(head.rotation.x, deg2rad(-90), deg2rad(90))
func _physics_process(delta):
direction = Vector3()
if Input.is_action_just_pressed("fire"):
if aimcast.is_colliding():
var b = bullet.instance()
muzzle.add_child(b)
b.look_at(aimcast.get_collision_point(), Vector3.UP)
b.shoot = true
func _process(delta):
#camera physics interpolation to reduce physics jitter on high refresh-rate monitors
if Engine.get_frames_per_second() > Engine.iterations_per_second:
camera.set_as_toplevel(true)
camera.global_transform.origin = camera.global_transform.origin.linear_interpolate(head.global_transform.origin, cam_accel * delta)
camera.rotation.y = rotation.y
camera.rotation.x = head.rotation.x
else:
camera.set_as_toplevel(false)
camera.global_transform = head.global_transform
# this is the line of code which is causing the error
(
func _physics_process(delta):
#get keyboard input
direction = Vector3.ZERO
var h_rot = global_transform.basis.get_euler().y
var f_input = Input.get_action_strength("move_backwards") - Input.get_action_strength("move_forward")
var h_input = Input.get_action_strength("move_right") - Input.get_action_strength("move_left")
direction = Vector3(h_input, 0, f_input).rotated(Vector3.UP, h_rot).normalized()
#jumping and gravity
if is_on_floor():
snap = -get_floor_normal()
accel = ACCEL_DEFAULT
gravity_vec = Vector3.ZERO
else:
snap = Vector3.DOWN
accel = ACCEL_AIR
gravity_vec += Vector3.DOWN * gravity * delta
if Input.is_action_just_pressed("jump") and is_on_floor():
snap = Vector3.ZERO
gravity_vec = Vector3.UP * jump
#make it move
velocity = velocity.linear_interpolate(direction * speed, accel * delta)
movement = velocity + gravity_vec
move_and_slide_with_snap(movement, snap, Vector3.UP) )
The error:
"_physics_process" already exists in this class
Is telling you that you have _physics_process twice in your script. You can only have one.
This is the first one:
func _physics_process(delta):
direction = Vector3()
if Input.is_action_just_pressed("fire"):
if aimcast.is_colliding():
var b = bullet.instance()
muzzle.add_child(b)
b.look_at(aimcast.get_collision_point(), Vector3.UP)
b.shoot = true
This is the second one:
func _physics_process(delta):
#get keyboard input
direction = Vector3.ZERO
var h_rot = global_transform.basis.get_euler().y
var f_input = Input.get_action_strength("move_backwards") - Input.get_action_strength("move_forward")
var h_input = Input.get_action_strength("move_right") - Input.get_action_strength("move_left")
direction = Vector3(h_input, 0, f_input).rotated(Vector3.UP, h_rot).normalized()
#jumping and gravity
if is_on_floor():
snap = -get_floor_normal()
accel = ACCEL_DEFAULT
gravity_vec = Vector3.ZERO
else:
snap = Vector3.DOWN
accel = ACCEL_AIR
gravity_vec += Vector3.DOWN * gravity * delta
if Input.is_action_just_pressed("jump") and is_on_floor():
snap = Vector3.ZERO
gravity_vec = Vector3.UP * jump
#make it move
velocity = velocity.linear_interpolate(direction * speed, accel * delta)
movement = velocity + gravity_vec
move_and_slide_with_snap(movement, snap, Vector3.UP)
I'm guessing you want both. So merge them into a single one with the code from both:
func _physics_process(delta):
direction = Vector3()
if Input.is_action_just_pressed("fire"):
if aimcast.is_colliding():
var b = bullet.instance()
muzzle.add_child(b)
b.look_at(aimcast.get_collision_point(), Vector3.UP)
b.shoot = true
#get keyboard input
direction = Vector3.ZERO
var h_rot = global_transform.basis.get_euler().y
var f_input = Input.get_action_strength("move_backwards") - Input.get_action_strength("move_forward")
var h_input = Input.get_action_strength("move_right") - Input.get_action_strength("move_left")
direction = Vector3(h_input, 0, f_input).rotated(Vector3.UP, h_rot).normalized()
#jumping and gravity
if is_on_floor():
snap = -get_floor_normal()
accel = ACCEL_DEFAULT
gravity_vec = Vector3.ZERO
else:
snap = Vector3.DOWN
accel = ACCEL_AIR
gravity_vec += Vector3.DOWN * gravity * delta
if Input.is_action_just_pressed("jump") and is_on_floor():
snap = Vector3.ZERO
gravity_vec = Vector3.UP * jump
#make it move
velocity = velocity.linear_interpolate(direction * speed, accel * delta)
movement = velocity + gravity_vec
move_and_slide_with_snap(movement, snap, Vector3.UP)
That should solve the error at hand. I haven't look deeper into the code for any other possible problems.
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)