Im a newbie here, I was wondering how I could make an attack system

Godot Version

4.2.2

Question

Ive been trying to implement a attack system in my code for a while now and every YouTube tutorial doesnt work out… Here’s my character body code:

extends CharacterBody2D

const SPEED = 280.0
const JUMP_VELOCITY = -399.0

@onready var sprite_2d = $AnimatedSprite2D
var gravity = ProjectSettings.get_setting(“physics/2d/default_gravity”)
@onready var attacking = false

func _process(delta):
if Input.is_action_just_pressed(“attack”):
attack()

func attack():
var overlapping_objects = $AttackArea.get_overlapping_areas()
for area in overlapping_objects:
var parent = area.get_parent()
print(parent.name)

attacking = true
sprite_2d.animation = "Attack"
sprite_2d.play()  # Added play() to ensure attack animation plays

func _physics_process(delta):
# Handle jump.
if is_on_floor() and Input.is_action_just_pressed(“jump”):
velocity.y = JUMP_VELOCITY
sprite_2d.animation = “jump”
sprite_2d.play()

# Add gravity.
if not is_on_floor():
	velocity.y += gravity * delta
	# Only set the jump animation if it's not already playing
	if sprite_2d.animation != "jump":
		sprite_2d.animation = "jump"
		sprite_2d.play()

# Check horizontal movement for running animation.
if is_on_floor():
	if abs(velocity.x) > 1:
		sprite_2d.animation = "Run"
		sprite_2d.play()
	else:
		sprite_2d.animation = "Idle"
		sprite_2d.play()

# Get the input direction and handle the movement/deceleration.
var direction = Input.get_action_strength("right") - Input.get_action_strength("left")
velocity.x = direction * SPEED

move_and_slide()

# Update sprite flip based on movement direction.
if direction != 0:
	sprite_2d.flip_h = direction < 0
1 Like

It would help if you defined what your attack system should be capable of. Requesting an “attack system” is rather abstract and has many solutions depending on what you’re looking to achieve.

1 Like

I just want a typical attack system, like a melee one.

Melee systems are a large topic, and can’t be summarized in a short posting. The ten-thousand-foot overview is:

You need to break down your system requirements into bite-sized chunks, and decide how you are going to implement each chunk.

2 Likes

This bit of your code seems 99% of the way there

func attack():
    var overlapping_objects = $AttackArea.get_overlapping_areas()
    for area in overlapping_objects:
        var parent = area.get_parent()
        print(parent.name)

Instead of printing the attack should deal damage no? Maybe an use and if to determine the class_name of what is overlapped i.e.

if parent is EnemyBase:
    parent.take_damage(10)

where the EnemyBase is defined like so

extends Node2D
class_name EnemyBase

var health: int = 100

func take_damage(amount: int) -> void:
    health -= amount
    if health <= 0:
        queue_free()
3 Likes

Ah I still dont get it, this code is probably right but its not working for me here’s my code;
extends CharacterBody2D
class_name Player

const SPEED = 280.0
const JUMP_VELOCITY = -399.0

@onready var sprite_2d = $AnimatedSprite2D
@onready var attack_area = $AttackArea
var gravity = ProjectSettings.get_setting(“physics/2d/default_gravity”)
var attacking = false

func _process(delta):
if Input.is_action_just_pressed(“attack”) and not attacking:
attack()

func attack():
print(“Player attacks”)
var overlapping_objects = attack_area.get_overlapping_areas()
for area in overlapping_objects:
var parent = area.get_parent()
if parent is Enemy:
parent.take_damage(10)

attacking = true
sprite_2d.animation = "Attack"
sprite_2d.play()  # Ensure the attack animation plays

func _physics_process(delta):
# Handle jump.
if is_on_floor() and Input.is_action_just_pressed(“jump”):
velocity.y = JUMP_VELOCITY
sprite_2d.animation = “jump”
sprite_2d.play()

# Add gravity.
if not is_on_floor():
	velocity.y += gravity * delta
	if sprite_2d.animation != "jump":
		sprite_2d.animation = "jump"
		sprite_2d.play()

# Check horizontal movement for running animation.
if is_on_floor():
	if abs(velocity.x) > 1:
		sprite_2d.animation = "Run"
		sprite_2d.play()
	else:
		sprite_2d.animation = "Idle"
		sprite_2d.play()

# Get the input direction and handle the movement/deceleration.
var direction = Input.get_action_strength("right") - Input.get_action_strength("left")
velocity.x = direction * SPEED

move_and_slide()

# Update sprite flip based on movement direction.
if direction != 0:
	sprite_2d.flip_h = direction < 0

# Reset attacking flag at the end of the process loop.
if attacking and sprite_2d.animation_finished():
	attacking = false

and here’s the enemy code;

extends CharacterBody2D
class_name Enemy

var health: int = 100
var speed: float = 100.0
var direction = Vector2(-1, 0) # Moving to the left initially

@onready var sprite_2d = $AnimatedSprite2D # Adjust based on your node structure

Function to handle taking damage

func take_damage(amount: int) → void:
health -= amount
print("Enemy took damage. Health remaining: ", health)
if health <= 0:
queue_free() # Remove the enemy from the scene when health is 0 or less.
print(“Enemy defeated!”)

Function to handle enemy movement (simple left-right movement in this case)

func _process(delta: float) → void:
move_and_slide()

Optional: Function to handle collision with player or other objects

func _on_Enemy_body_entered(body):
if body is Player:
body.take_damage(10)
The enemy doesnt move at all and when I click the player doesnt attack…Also just so you know this is for a school project haha.

make sure to use code formatting for scripts, on a new line the </> button will make three ticks for you to paste code into like so

```
type or paste code here
```

Make sure you are being specific. What is “not working” requires me to know what you expected to happen, and what actually happened. Did any of the prints, print?

you are using attack_area.get_overlapping_areas() does your enemy use a Area2D for it’s hurtbox or does it use a physics body like CharacterBody2D? What does it’s scene tree look like, your enemy script would have to be a parent of the hurtbox. Something like this:

2024-05-19-112750_274x225_scrot

1 Like

So basically, when I run the game and put the enemy near the player it doesnt move or do anything, I want it to move towards the player and start attack like a typical enemy right? and this is my enemy setup:
Screenshot 2024-05-21 at 2.23.40 PM
And I want my player to start his melee animation and attack yk my player setup is the same as the above image… and the code hasn’t changed from before. Anyways in conclusion I want the player to start his attack on click and the enemy to move to the player and hit him. Thanks a lot for helping lol, if you want we can talk on discord

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