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


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.