我该如何使好人攻击只击中坏人,反之亦然?


11

我的游戏有许多不同类型的好人和许多不同类型的坏人。他们都将向对方发射弹丸,但我不希望任何对准都会发生意外附带损害。因此,坏人不应该打/伤害其他坏人,好人不应该打/伤害其他好人。

我想解决此问题的方法是通过使其Unit实例(这是javascript,btw)具有alignment可以为goodor 的属性bad。而且我只会让碰撞发生

class Attack

    boolean didAttackCollideWithTarget(target)
        return attack.source.alignment != target.alignment and collisionDetected(attack.source, target)

当然,这是伪代码。

但是我之所以问这个问题,是因为我觉得除了在Unit类中添加另一个属性之外,还有一种更优雅的方法来设计它。


5
过滤是此处的典型方法。本质上就是您所描述的。也有层。两层,坏层和好层。坏人的弹丸被射入好层,反之亦然。
MichaelHouse

@ Byte56您能详细说明这个“层”概念吗?或至少链接到有关它的东西?我以前从未听说过。
Daniel Kaplan 2013年

本质上,它们是不同的“世界”。一层中的所有对象彼此交互,但不与其他任何层交互。这可以通过标签(例如过滤)来完成,也可以通过每一层完全不同的数据集来完成。
MichaelHouse

3
总之,它是分组。分组好子弹,仅检查是否与坏人发生冲突。Flixel有这样的概念。
ashes999

3
一则挑剔的设计说明:您是要击打 “友军射击” 但不造成伤害,还是希望它们完全忽略盟友,而可能通过它们来打击敌人?
史蒂文·斯塔德尼基

Answers:


6

碰撞过滤

扩展到多个层的更健壮的情况是使用过滤,这与分组不同。

通过为每个对象提供2个位掩码,可以达到最佳效果

Category
Mask

并且仅在满足以下条件时触发碰撞。

(filterA.maskBits & filterB.categoryBits) != 0 &&
(filterA.categoryBits & filterB.maskBits) != 0;

最简单的方法是将Mask设置为0xFFFF,这会使它与所有内容发生冲突。并将“类别”默认为0x0001。对象与其他遮罩中的类别碰撞时将发生碰撞。

另一种思考方式是,每个对象都有一个类型以及可以与之碰撞的所有类型的列表。仅当两个对象都彼此碰撞时才发生碰撞。使用枚举列表而不是掩码可能会具有相同的行为,但是掩码的速度要快一个数量级。

您描述的场景

我喜欢在这种情况下利用枚举。

所以说我们有。

enum Categories {
    GoodGuy =           0x0001,
    BadGuy =            0x0002,
    Bullet =            0x0004,
    GlassWall =         0x0008,
    Lazer =             0x0010,
    All =               0xFFFF
};

一个好人射击的子弹

 Category = Bullet
 Mask = BadGuy | GlassWall

好人

 Category = GoodGuy
 Mask = All

坏人

 Category = BadGuy
 Mask = All

当好人的子弹击中另一个好人时,结果显示在下面。

(All & GoodGuy) != 0 && <-- Passes
(GoodGuy & (BadGuy | GlassWall)) != 0; <-- This would fail

但这会打击坏人。

(All & BadGuy) != 0 && <- Passes
(BadGuy & (BadGuy | GlassWall)) != 0; <-- Passes

您介意在概念上进行解释而不是在位算术的低级细节进行解释吗?
Daniel Kaplan 2013年

@tieTYT确保在5分钟内再次检查
ClassicThunder

2

我在当前项目中(使用Java)遇到了同样的问题。经过几次尝试,通过创建四个列表解决了该问题。该解决方案是用Java和2D游戏创建的,但也应该以类似的方式在JavaScript中工作

public static main (String [] args)
{
    private List<Bullets> bullets_GoodGuys = new LinkedList <Bullet>(); //List of all bullets fired by good guys
    private List<Bullets> bullets_BadGuys  = new LinkedList <Bullet>(); //List of all bullets fired by bad guys
    private List<Guys> goodGuys  = new LinkedList <Guys>(); //List of all good guys
    private List<Guys> badGuys  = new LinkedList <Guys>();  //List of all good guys

    init();
    ...
    while(game_is_running)
    {
        ... 
        for(int i=0;i>=goodGuys.length;i++)
        {
            for(int j=0;j>=bullets_BadGuys.length;i++)
            {
                if(goodGuys.get(i).getBounding().interacts(bullets_BadGuys.get(i).getBounding()))
                {// If a good guy was hit by a bullet from a bad guy
                    goodGuys.get(i).getDamage();
                    bullets_BadGuys.remove((bullets_BadGuys.get(i));
         }   }   }
       for(...) //same for the bad guys
       {...}
}

伪码

class Guys
{
   private float xkoordinate;
   private float ykoordinate;
   private BufferedImage look;
   private Rectangle bounding = new Rectangle(xkoordinate,ykoordinate,look.getWith(),look.getHight())
   ...
}

伪代码,与类项目符号相同

这可能不是最佳或最快的解决方案,但此刻会为您提供帮助。抱歉,我无法为您提供JavaScript解决方案,但希望能为您提供帮助

顺便说一句,我的英语不是最好,但我希望你能按照我的解释

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.