Як зробити так, щоб напади хороших хлопців вдарили тільки поганих хлопців і навпаки?


11

У моїй грі є багато різних типів хороших хлопців і багато різних типів поганих хлопців. Усі вони будуть стріляти снарядами один на одного, але я не хочу, щоб будь-яке побічне пошкодження відбувалося для будь-якого вирівнювання. Тож погані хлопці не повинні мати можливість вдарити / пошкодити інших поганих хлопців, а хороші хлопці не повинні мати змогу вдарити / пошкодити інших хороших хлопців.

Я думаю, що це вирішити, це зробити так, щоб Unitекземпляр (це JavaScript, btw) мав alignmentвластивість, яка може бути goodабо bad. І я дозволю зіткнення лише тоді, коли

class Attack

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

Це, звичайно, псевдокод.

Але я задаю це питання, тому що я розумію, що може бути набагато більш елегантний спосіб розробити це, окрім додавання ще одного властивості до мого Unitкласу.


5
Фільтрування тут є типовим підходом. По суті це те, що ви описали. Також є шари. Два шари, поганий і хороший шар. Снаряди поганих хлопців вистрілюються в хороший шар і навпаки.
MichaelHouse

@ Byte56 Чи можете ви детальніше розглянути цю концепцію "шару"? Або хоча б посилання на щось про це? Я ніколи про це не чув.
Даніель Каплан

По суті вони різні "світи". Усі об'єкти в шарі взаємодіють один з одним, але не взаємодіють з будь-яким іншим шаром. Це можна зробити за допомогою тегів (наприклад, фільтрування) або абсолютно різних наборів даних для кожного шару.
MichaelHouse

3
Словом, це групування. Згрупуйте хороші кулі і перевіряйте лише на зіткнення з поганими хлопцями. У Flixel таке поняття.
ashes999

3
Один примхливий дизайнерський зауваження: ви хочете, щоб удари «дружнього вогню» вражали, але не завдавали шкоди, чи ви хочете, щоб вони повністю ігнорували союзників, можливо, проходячи через них, щоб замість них завдати удару по ворогах?
Стівен Стадницький

Відповіді:


6

Фільтрування зіткнень

Більш надійною ситуацією, яка розширюється на багато шарів, є використання фільтрації, що не те саме, що групування.

Це найкраще працює, надаючи кожному об’єкту по 2 бітових маски .

Category
Mask

І зіткнення викликає лише те, що наведено нижче.

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

Найпростіше за замовчуванням маску до 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

Ви б не проти пояснити це концептуально замість того, щоб пояснювати це на низькому рівні деталі бітної арифметики?
Даніель Каплан

@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())
   ...
}

псевдо-код, те саме для класу Bullets

Це може бути не найкращим чи найшвидшим рішенням, але воно допоможе тобі в даний момент. Вибачте, що не можу дати вам рішення в JavaScript, але сподіваюся, що можу вам допомогти

До речі, моя англійська мова не найкраща, але я сподіваюся, що ви можете наслідувати моє пояснення

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.