Help with top-down 2d shooter in godot

Godot Version

4.2.2 Stable

Question

I am making a small topdown 2d shooter, but I have got 2 issues with my game: 1. It seems like the “Player” cannot move. The player just slides up, or down etc… but returns to its original position after you release the controls. 2. Whenever I try to shoot the shotgun, (btw, I am using a different scene for the shotgun-pellets than for the rest of the guns) the pellets seem to come from anywhere but the player. I suspect that the “ShootingPoint” which is a marker2d, is moved but the player is not. The other guns work perfectly well. (I have made the function move_away_from_cursor() to simulate recoil). Help is highly appreciated as I just can’t figure it out.

extends CharacterBody2D

@export var speed = 3000
@onready var animated_sprite = $AnimatedSprite2D
@onready var shoot_timer = $Revolver
@onready var shooting_point = %ShootingPoint
@onready var shotgun_timer = $Shotgun

var target_position: Vector2
var gun_select = "no_gun"
var can_shoot = true

func move_shootingpoint():
	
	var mouse_x = get_global_mouse_position()
	
	if gun_select == "minigun":
		if mouse_x.x > position.x:
			shooting_point.position = Vector2(16, 10.5)
		else:
			shooting_point.position = Vector2(-16, 10.5)
	elif gun_select == "ak":
		if mouse_x.x > position.x:
			shooting_point.position = Vector2(12, 4.5)
		else:
			shooting_point.position = Vector2(-12, 4.5)
	elif gun_select == "revolver":
		if mouse_x.x > position.x:
			shooting_point.position = Vector2(2, 3.5)
		else:
			shooting_point.position = Vector2(-2, 3.5)
	elif gun_select == "shotgun":
		if mouse_x.x > position.x:
			shooting_point.position = Vector2(4, 3.5)
		else:
			shooting_point.position = Vector2(-4, 3.5)

func _process(delta):
	var direction = Vector2.ZERO
	
	#select gun
	if Input.is_action_just_pressed("1"):
		gun_select = "no_gun"
	elif Input.is_action_just_pressed("2"):
		gun_select = "shotgun"
	elif Input.is_action_just_pressed("3"):
		gun_select = "revolver"
	elif Input.is_action_just_pressed("4"):
		gun_select = "ak"
	elif Input.is_action_just_pressed("5"):
		gun_select = "minigun"
	
	Global.gun_select = gun_select
	
	move_shootingpoint()
	
	var dir = Input.get_axis("move_left", "move_right")
	var up_down = Input.get_axis("move_up", "move_down")
	
	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_down"):
		direction.y += 1
	if Input.is_action_pressed("move_up"):
		direction.y -= 1
	
	if Input.is_action_just_pressed("ui_cancel"):
		get_tree().quit()
	
	
	if direction != Vector2.ZERO:
		direction = direction.normalized()
	
	# Play animations
	
	if dir == 0 and up_down == 0:
		if gun_select == "shotgun":
			animated_sprite.play("IdleShotgun")
		elif gun_select == "revolver":
			animated_sprite.play("IdleRevolver")
		elif gun_select == "ak":
			animated_sprite.play("IdleAK")
		elif gun_select == "minigun":
			animated_sprite.play("IdleMinigun")
		else:
			animated_sprite.play("Idle")
	elif gun_select == "shotgun":
		animated_sprite.play("Shotgun")
	elif gun_select == "revolver":
		animated_sprite.play("Revolver")
	elif gun_select == "ak":
		animated_sprite.play("AK")
	elif gun_select == "minigun":
		animated_sprite.play("Minigun")
	else:
		animated_sprite.play("Run")
	
	global_position = global_position.lerp(target_position, 0.1)
	
	var mouse_x = get_global_mouse_position()
	
	if mouse_x.x > position.x:
		animated_sprite.flip_h = false
	elif mouse_x.x < position.x:
		animated_sprite.flip_h = true
	
	velocity = direction * speed * delta
	move_and_slide()

func _input(event):
	# Check for left mouse button press
	if gun_select == "revolver":
		if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT and event.pressed:
			if can_shoot:
				shoot()
	elif gun_select == "shotgun":
		if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT and event.pressed:
			if can_shoot:
				shoot_shotgun()
				shoot_shotgun()
				shoot_shotgun()
				shoot_shotgun()
				shoot_shotgun()
				shoot_shotgun()
				can_shoot = false
				shotgun_timer.start()
				
func _ready():
	target_position = global_position

func shoot():
	const BULLET = preload("res://scenes/bullet.tscn")
	var new_bullet = BULLET.instantiate()
	new_bullet.global_position = %ShootingPoint.global_position
	%ShootingPoint.add_child(new_bullet)
		
	# Move the player away from the mouse cursor
	move_player_away_from_cursor()
	
	# Set can_shoot to false and start the timer
	can_shoot = false
	shoot_timer.start()

func shoot_shotgun():
	const BULLET = preload("res://scenes/pellet.tscn")
	var new_bullet = BULLET.instantiate()

	# Ensure ShootingPoint node is correctly referenced
	var shooting_point = $AnimatedSprite2D/ShootingPoint
	if shooting_point == null:
		print("Error: ShootingPoint node not found")
		return

	print("ShootingPoint global position: ", shooting_point.global_position)
	new_bullet.global_position = shooting_point.global_position
	shooting_point.add_child(new_bullet)



func move_player_away_from_cursor():
	var mouse_position = get_global_mouse_position()
	var direction_to_mouse = (mouse_position - global_position).normalized()
	var move_away_vector = -direction_to_mouse * 10  # Adjust the multiplier as needed
	
	# Update the target position instead of the player's position directly
	target_position = global_position + move_away_vector

func _on_minigun_timeout():
	if Input.is_action_pressed("shoot") and gun_select == "minigun":
		shoot()

func _on_ak_timeout():
	if Input.is_action_pressed("shoot") and gun_select == "ak":
		shoot()

func _on_revolver_timeout():
	can_shoot = true

func _on_shotgun_timeout():
	can_shoot = true

  1. Remove this line, it will solve player movement issue:
global_position = global_position.lerp(target_position, 0.1)
  1. Remove this line, it will solve the shotgun glitch:
new_bullet.global_position = shooting_point.global_position
  1. This solution worked! Thx alot. 2. I found out I had forgot to turn on “Top level” under visibility in the “pellet.tscn” inspector.
1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.