Game Engine Kollision Bitmask ... Warum 0x01 usw.?

8

Als ich diese Situation sowohl im Sprite-Kit (iOS-Entwicklung) als auch in Cocos2d-x (von dem ich weiß, dass es Sprite Kit inspiriert hat, weshalb sie viele der gleichen Tools verwenden) entdeckte, entschied ich mich schließlich dafür warum das passiert:

Wenn ich eine Physik-Engine verwende, erstelle ich ein Sprite und füge ein physicsBody hinzu. Zum größten Teil verstehe ich, wie man die Kategorien-, Kollisions-und Kontakt-Bitmasken einstellt und wie sie funktionieren. Das Problem ist die tatsächliche Bitmaskennummer:

SpriteKit:

%Vor%

Cocos2D-X:

%Vor%

Ich bin total verwirrt, warum ich 0x01 oder 0x1 & lt; & lt; In beiden Fällen 0. Ich verstehe, dass sie hex verwenden, und es hat etwas mit 32-Bit-Ganzzahlen zu tun. Und soweit ich googlen konnte, ist 0x01 0001 in binär, was 1 in Dezimal ist. Und 0x02 ist 0010 in binär, was 2 in Dezimal ist. Okay, also gibt es diese Konvertierungen, aber warum in der Welt würde ich sie für einfache Kategorien verwenden?

Was meine Logik angeht, wenn ich sagen kann, eine Spielerkategorie, eine Feindkategorie, eine Raketenkategorie und eine Wandkategorie, dann sind das nur vier Kategorien. Warum nicht Zeichenfolgen für die Kategorie verwenden? Oder auch nur Binärzahlen, die jeder Nicht-CS-Mensch wie 0,1,2 und 3 verstehen würde?

Und schließlich bin ich verwirrt, warum es 32 verschiedene Kategorien gibt? Ich dachte, eine 32-Bit-Ganzzahl hätte Zahlen von 0 - einige Milliarden (natürlich ohne Vorzeichen). Warum habe ich also keine Milliarden verschiedener Kategorien?

Gibt es eine Art von Optimierung, die ich nicht verstehe? Oder das ist nur eine alte Konvention, die sie verwenden, aber nicht benötigt wird? Oder ist da etwas los, dass jemand mit nur 2 Semestern CS-Ausbildung nicht verstehen würde?

    
Kjell 20.01.2016, 15:52
quelle

3 Antworten

8

Der Grund für die Bitmasken ist, dass Sie / das Programm leicht und sehr schnell berechnen können, ob eine Kollision zwischen zwei Objekten auftritt oder nicht. Daher: ja ist es eine Art Optimierung.

Angenommen wir haben die drei Kategorien

  • Rakete 0x1 << 0
  • Spieler 0x1 << 1
  • Wand 0x1 << 2

Jetzt haben wir eine Player Instanz, deren Kategorie auf player gesetzt ist. Seine Kollisions-Bitmaske ist auf missile | player | wall ( + anstatt | funktioniert auch) eingestellt, da wir mit allen drei Typen kollidieren wollen: anderen Spielern, den Ebenenwänden und den herumfliegenden Geschossen.

Jetzt haben wir Missile mit Kategorie auf missile und Kollisions-Bitmaske auf player | wall gesetzt: Es kollidiert nicht mit anderen Raketen, sondern trifft Spieler und Mauern.

Wenn wir nun auswerten wollen, ob zwei Objekte miteinander kollidieren können, nehmen wir die Kategorie Bitmaske des ersten und die Kollisions-Bitmaske des zweiten Wunsches und einfach & sie:

Das oben beschriebene Setup sieht im Code wie folgt aus:

%Vor%

Die nachfolgende Argumentation ist im Grunde:

%Vor%

Wir verwenden hier einige Bit-Arithmetik, jedes Bit repräsentiert eine Kategorie. Sie könnten einfach die Bitmasken 1,2,3,4,5 aufzählen ... aber dann konnten Sie keine Mathematik auf ihnen tun. Weil Sie nicht wissen, ob eine Bitmaske der Kategorie 5 wirklich eine Kategorie 5 oder ein Objekt der Kategorien 1 und 4 ist.

Aber nur mit Bits können wir genau das tun: die einzige Darstellung in Bezug auf Potenzen von 2 einer 7 ist 4 + 2 + 1: daher kollidiert jedes Objekt, das Kollisions-Bitmaske 7 besitzt, mit Kategorie 4, 2 und 1. Und Eine mit Bitmaske 5 ist genau und nur eine Kombination aus Kategorie 1 und 4 - es gibt keinen anderen Weg.

Da wir jetzt nicht aufzählen - jede Kategorie verwendet ein Bit und die reguläre ganze Zahl nur 32 (oder 64) Bits, können wir nur 32 (oder 64) Kategorien haben.

Sehen Sie sich den folgenden und etwas umfangreicheren Code an, der zeigt, wie die Masken in einem allgemeineren Begriff verwendet werden:

%Vor%

Der wichtige Teil hier ist, dass die Methode canTwoObjectsCollide sich nicht um den Typ der Objekte kümmert oder um wie viele Kategorien es sich handelt. Solange Sie bei den Bitmasken bleiben, brauchen Sie nur zu bestimmen, ob zwei Objekte theoretisch kollidieren können (ignorieren ihre Positionen, was eine Aufgabe für einen anderen Tag ist).

    
luk2302 20.01.2016, 16:20
quelle
7

Die Antwort von luk2302 ist großartig, aber nur um ein bisschen weiter und in andere Richtungen zu gehen ...

Warum Hexadezimalschreibweise? ( 0x1 << 2 usw.)

Sobald Sie wissen, dass Bit Positionen der wichtigste Teil sind, ist es (wie in Kommentaren erwähnt) nur eine Frage des Stils / der Lesbarkeit. Du könntest genauso gut tun:

%Vor%

Aber binäre Literale wie diese sind (für Apple-Tools) neu in Swift und nicht in ObjC verfügbar.

Sie könnten auch tun:

%Vor%

oder:

%Vor% Aus historischen / kulturellen Gründen ist es unter Programmierern jedoch üblich geworden, hexadezimale Schreibweisen zu verwenden, um sich / andere Leser Ihres Codes daran zu erinnern, dass ein bestimmtes Ganzzahl-Literal für sein Bitmuster signifikant mehr ist als sein absoluter Wert. (Für das zweite C-Beispiel müssen Sie sich auch daran erinnern, welches Bit welchen Stellenwert hat, während Sie mit << operator oder binary literals die Position hervorheben können.)

Warum Bitmuster? Warum nicht

rickster 20.01.2016 22:29
quelle
2

Um Ihre spezifische Frage zu beantworten

  

"Warum gibt es 32 verschiedene Kategorien? Ich dachte ein 32-Bit   Integer hatte Zahlen von 0 bis einige Milliarden (natürlich nicht signiert). Warum also   habe ich nicht Milliarden verschiedener Kategorien? "

Die Antwort ist, dass die Kategorie immer als eine 32-stellige Bitmaske behandelt wird, für die NUR EINS gesetzt werden sollte. Das sind also die gültigen Werte:

%Vor%

Also gibt es 32 verschiedene Kategorien. Ihre CategoryBitMask kann jedoch mehrere Bits enthalten, so dass in der Tat jede Zahl von 1 bis zu dem Maximum von UInt32 sein kann. In einem Arcade-Spiel haben Sie beispielsweise Kategorien wie:

%Vor%

also könnte ein menschlicher Zivilist eine Kategorie habenBitMask 1, ein menschlicher Soldat 5 (1 + 4), ein außerirdischer Offizier 6, eine normale Kugel 16, eine Rakete 80 (16 + 64), Megatodstrahl 96 usw. .

    
Steve Ives 12.04.2016 08:28
quelle

Tags und Links