+1 vote

Im using Godot v2.1.5, im trying to make a simple fighting game (dont mean i used swords and guns, characters use punch, so ive created multiple shapes and sprites for punching), area2D does not work as i expected, after several days of struggling, I found that if i hit R/T button which are used for punching, when i press the key and hold it and go to the opponent, opponent area2D feels the punch and print it in output. but i didnt find any thing to solve this, it seems this engine design for simple collision (i mean when a shape entering or crossing from border of another shape), ik im a beginner in coding, specially in developing game, but i dont understand why a simple task should be so hard to put it in game...

extends KinematicBody2D
const speed = 600
var velocity = Vector2()
onready var sprite0 = get_node("Idle")
onready var sprite1 = get_node("RightFist")
onready var sprite2 = get_node("LeftFist")
onready var sprite3 = get_node("Hurt")
onready var shape0 = get_node("IdleShape")
onready var shape1 = get_node("RightFistShape")
onready var shape2 = get_node("LeftFistShape")
func _ready():
     set_fixed_process(true)
func _fixed_process(delta):
     velocity = Vector2()
     if Input.is_key_pressed(KEY_PERIOD):
        sprite1.show()
        shape1.set_trigger ( false )
        sprite0.hide()
        sprite2.hide()
        sprite3.hide()
        shape0.set_trigger ( true )
        shape2.set_trigger ( true )
     elif Input.is_key_pressed(KEY_COLON):
        sprite2.show()
        shape2.set_trigger ( false )
        sprite0.hide()
        sprite1.hide()
        sprite3.hide()
        shape0.set_trigger ( true )
        shape1.set_trigger ( true )
     else:
        sprite0.show()
        shape0.set_trigger ( false )
        sprite1.hide()
        sprite2.hide()
        sprite3.hide()
        shape1.set_trigger ( true )
        shape2.set_trigger ( true )
     if Input.is_action_pressed("ui_right"):
        velocity.x += 1
     if Input.is_action_pressed("ui_left"):
        velocity.x -= 1
     if Input.is_action_pressed("ui_down"):
        velocity.y += 1
     if Input.is_action_pressed("ui_up"):
        velocity.y -= 1
     if velocity.length() > 0:
        velocity = velocity.normalized() * speed
     var motion = move(velocity * delta)
     if (is_colliding()):
        var n = get_collision_normal()
        motion = n.slide(motion)
        velocity = n.slide(velocity)
        move(motion)
func _on_Head02_body_enter( body ):
     shape0.set_trigger ( false )
     shape1.set_trigger ( true )
     shape2.set_trigger ( true )
     if (Input.is_key_pressed(KEY_PERIOD) || Input.is_key_pressed(KEY_COLON)):
        print(get_name())
asked Sep 3, 2018 in Engine by mdswamp (75 points)
edited Sep 15, 2018 by mdswamp

Maybe all you need is some time management coding - add a timer to the punch so that it will work only in certain amount of time and after that even if you detect collision, You will simply ignore it, because punch timed out.

Making games is hard and fighting games are particularly hard, so be patient and try to develop a state system to simplify your logic as some recommended.

Using nodes may not be the best either but since you are starting, try to keep your mechanics simple until you get more experience to use better methods (like shape casting).

2 Answers

+1 vote

you need a STATE:
var is_punching = false
once you press the PUNCH button, your state changes:

if !is_punching && Input.is_key_pressed(KEY_PERIOD):
    is_punching = true
    # start timer

than after this you can check for damage:

if is_punching:
    # check collision / deal damage

once timer times out you can set is_punching back to false and punch again.

answered Sep 4, 2018 by luckyNyaNya (41 points)
edited Sep 4, 2018 by luckyNyaNya

Hi luckyNyaNya,
thank you for response. i have Q about timer.
think that one of player hit the punch button consecutively. how i should set the timer to work with every condition? beside i dont want when i hold punch button, player punch after specific time. i use a timer script but i cant make it to work with my characters. im using godot 2.1... i saw a method calls (Input.isactionjust_pressed) in godot3 which i think it suit me, there isnt any in godot 2.1 (i dindnt find anything), on the other hand i found this code to emulate this method. but the problem is that when i put it in script and when i run the game and hit punch button, punching happens so fast and i can see idle sprite and punch sprite at the same time. i put sprites in animatesprites and test it again, but result is the same. can you help me to fix this function? maybe it fixes with timer, but i dont know how? thank you :)

https://godotengine.org/qa/16520/is_action_just_pressed-is-gone-what-to-use-now

var pressed = {}

func is_action_just_pressed(action):

    if Input.is_action_pressed(action):
        if not pressed.has(action) or not pressed[action]:
            pressed[action] = true
            return true
    else:
        pressed[action] = false
    return false

func _process(delta):

    if is_action_just_pressed("ui_select"):
        ## done once when the key is pressed

Before you proceed, I would recommend reading about state management or state machine / state design pattern. Because fighting game is very complex, I just gave you very simple example.

think that one of player hit the punch button consecutively

that's why you need is_punching variable. I just realized that can_punch would be a better name :) or even both: is_punching for STATE and can_punch for cooldown. While is_punching == true your character is in PUNCH STATE, during that time you check for damage/collision, if can_punch == false, nothing happens when player hit punch key consecutively.

i dont want when i hold punch button, player punch after specific time

that's why you need a timer. It's a COOLDOWN timer.

here is my updated example:

is_punching = false # state of your character
can_punch = true

func _process(delta):
    if can_punch && Input.is_key_pressed(PUNCH_KEY):
        can_punch = false
        is_punching = true
        # start COOLDOWN timer
    #...
    if is_punching:
        # check collision / damage

func _on_Animation_finished(anim):
    is_punching = false

func _on_Timer_timeout():
    can_punch = true

i hope it helps.

hi again luckyNyaNya
thank U for your guidance. yesterday think about this project and i found what to do. i used tween and placed punching code at input event, so when i press hit button, after 2 punching it stop and i should press the key again, i think maybe i should use timer for solving this problem and make it to hit once per one key press. but about collision, i use collision shapes in a wrong way. thank you again :)

0 votes

well. you should first learn the basics of animations and collision.

A punch should be just another animation of the character so it must have a specific duration. It also should have a hitbox (Area2d) that appears only during a certain part of the animation.

answered Sep 5, 2018 by golpebaixo (34 points)
Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.