概述:组合技,取消和连续技

接上一期Hitbox&hurtbox,这期我们来看看如何设置一个基本的连击系统。

同样,本文依旧面对新手。


作者:Nathan Ranney
翻译:highway★
原文:译文:GAMEMAKER STUDIO基础系列:组合技(COMBO)设置

接上一期Hitbox&hurtbox,这期我们来看看如何设置一个基本的连击系统。

同样,本文依旧面对新手。

在我们开始之前,我想指出有不同种类的组合技。一般来说,一个组合就是当一个攻击一个接一个地连接,你的敌人除了一直挨揍什么也干不了。但是,从第一次攻击到第二次攻击的方式可能会有所不同。

chain combo就是说你的第二次攻击中断或者取消当前的攻击。你的第一次攻击在它所在的位置停止,接着打出第二次攻击。

link combo是当你的第一次攻击完全结束,你的角色恢复到他们的中立状态时,你的对手仍然被击晕足够长的时间让你开始第二次攻击并击中他们。

译注:如果你是格斗游戏玩家,会对这些非常清楚,当然了,如果你在读这篇文章,我会假定你很喜欢动作格斗类游戏,咱们在这儿就不多啰嗦了。*

攻击精灵图

我们还是用之前hitbox那篇文章中的精灵图,不过要做一些修改,因为我们要做combo。

我们要加两个新的攻击动作。

sprPlayer_Attack_2

sprPlayer_Attack_3

这些有点小,但这是因为它们是游戏的原生分辨率。我还对之前的原始攻击动画做了一些更改。使用我们的新攻击有点太长了,所以我删除了一堆帧以使其适合我们的新精灵。

sprPlayer_Attack

导入精灵长带图(如果有疑问请看F1),将原点设为16x32

初始化新变量

打开oPlayer的create事件,加入下面代码:

currentAttack = attacks.right;
hitLanded = false; 

currentAttack将用于根据玩家当前正在进行的攻击来定义不同的行为和动画。 hitLanded将是我们的布尔值,我们用它来告诉我们可以取消当前攻击到下一次攻击。

打开enum_init脚本,让我们为新的攻击添加一些新的枚举。将此代码添加到脚本的底部。

enum attacks { 
    right, 
    left, 
    upper 
}

最后,我们需要扩展一下hitbox_create脚本,加一个参数。打开该脚本并将以下代码复制/粘贴到其上。

_hitbox = instance_create(x,y,oHitbox); 
_hitbox.owner = id; 
_hitbox.image_xscale = argument0; 
_hitbox.image_yscale = argument1; 
_hitbox.xOffset = argument2; 
_hitbox.yOffset = argument3; 
_hitbox.life = argument4; 
_hitbox.xHit = argument5; 
_hitbox.yHit = argument6; 
_hitbox.hitStun = argument7; 
return _hitbox; 

我们添加了_hitbox.yHit,这样做可以让我们把敌人打到浮空,而不是仅仅向后击退。

打开normal_state脚本,再最下面加入如下代码:

//reset attack 
currentAttack = attacks.right; 

这可以确保我们的攻击始终从攻击链中的第一次攻击开始。这就是初始化新变量和枚举的全部内容。

扩展switch语句

现在我们已经拥有了所有这些新攻击,我们需要为每个攻击设置动画。使用我们刚刚初始化的新枚举和嵌套的switch语句可以轻松实现这一点。打开animation_control脚本,让我们更改states.attack以包含新的精灵图。

case states.attack: 
switch(currentAttack){ 
    case attacks.right: 
    sprite = sprPlayer_Attack; 
    break; 
    case attacks.left: sprite = sprPlayer_Attack_2; 
    break; 
    case attacks.upper: 
    sprite = sprPlayer_Attack_3; 
    break; }
 break; 

attack_state脚本也要更改:

switch(currentAttack){ 
    case attacks.right: 
    //create hitbox on the right frame 
    if(floor(frame) == 1 && hitbox == -1){ 
        hitbox = hitbox_create(20 * facing,12,-3 * facing,-16,8,1 * facing,0,60); 
    } 
    //cancel into next attack 
    if(attack && hitLanded){ 
        currentAttack = attacks.left; 
        hitLanded = false; 
        hitbox = -1; 
        frame = 0; 
    } 
    break; 
    case attacks.left: 
    //create hitbox on the right frame 
    if(floor(frame) == 1 && hitbox == -1){
         hitbox = hitbox_create(20 * facing,12,-3 * facing,-16,8,1 * facing,0,45); 
        //also move forward 
        xSpeed = 3 * facing; 
    } 
    //cancel into next attack 
    if(attack && hitLanded){ 
        currentAttack = attacks.upper; 
        hitLanded = false; 
        hitbox = -1; 
        frame = 0; 
    } 
    break; 
    case attacks.upper: 
    //create hitbox on the right frame 
    if(floor(frame) == 1 && hitbox == -1){ 
        hitbox = hitbox_create(20 * facing,12,-3 * facing,-16,8,1 * facing,-4,45); 
        //also move forward 
        ySpeed = -3; 
    } 
    break; 
}

我在这里要解释一下。首先,我们完成了与animation_control脚本完全相同的操作,并加了一个switch语句,其中包含每种攻击类型的情况。 hitbox_create脚本已更新为包含我们的新yHit参数。这是倒数第二个值。你可能注意到前两次攻击已将其设置为零。那是因为我们不想在这些攻击中将敌人打到浮空。

其次,我添加了一个检查以允许取消进入下一次攻击。我们检查是否按下了攻击按钮并且hitLanded是否为true。如果满足两个条件,则更改为另一个攻击,将动画帧重置为零,并将hitbox设置为-1。如果hitbox变量未重置为-1,则在下一次攻击发生时不会创建新的hitbox。我们还将currentAttack设置为我们想要取消当前攻击后进入的下一次攻击。

最后,当在第二次和第三次攻击中创建了hitbox时,我们也会对玩家角色加点儿动势。您将看到正在设置xSpeed和ySpeed。在attacks.left情况下,这将使玩家向前移动一点,以确保在第一次攻击击退敌人后让下一击能够击中敌人。在attacks.upper案例中设置的ySpeed会将玩家打到空中,对,就等于是简化出招的隆的升龙拳。

Applying yHit

虽然我们将yHit添加到hitbox_create脚本中,但还没应用于敌人。在oEnemy对象中,打开end step事件,让我们加点儿东西。

//get hit 
if(hit){ 
    squash_stretch(1.3,1.3); 
    xSpeed = hitBy.xHit; 
    ySpeed = hitBy.yHit; 
    hitStun = hitBy.hitStun; 
    facing = hitBy.owner.facing * -1;
    hit = false;
    currentState = states.hit; 
} 

设置和重置hitLanded

最后一步,打开oPlayer的end step事件,当我们的hitbox打中敌人时,把hitLanded设为true:

//hitbox 
if(hitbox != -1){
    with(hitbox){
         x = other.x + xOffset; 
        y = other.y + yOffset; 
    //collision check 
    //checking the collision from the hurtbox object 
    with(oHurtbox){ 
        if(place_meeting(x,y,other) && other.owner != owner){
             //ignore check 
            //checking collision from the hitbox object 
            with(other){ 
                //check to see if your target is on the ignore list 
                //if it is on the ignore list, dont hit it again 
                for(i = 0; i < ds_list_size(ignoreList); i ++){ 
                    if(ignoreList[|i] = other.owner){ 
                        ignore = true; break; 
                    } 
                }
                     //if it is NOT on the ignore list, hit it, and add it to //the ignore list 
                    if(!ignore){
                     other.owner.hit = true; 
                    other.owner.hitBy = id; 
                    owner.hitLanded = true; 
                    ds_list_add(ignoreList,other.owner); 
                    } 
                } 
            } 
        } 
    } 
}

打开normal_state脚本并将其添加到脚本的末尾。

//reset hit landed 
hitLanded = false;

这将确保在攻击发生之前始终将hitLanded设置为false,因为我们的攻击始终从normal_state脚本启动。
运行游戏并开始打击你的对手!如果你用不同的按键对应3种攻击,你的角色应该执行一个由三种攻击组成的chain combo~

感谢阅读~

项目的工程文件点我下载

2021-04-28 15:14
Comments
Write a Comment