Version 2.0!
Features
Tutorials
Files
Glossary
Projects
Contact
Links
Message Board
Extras
LuckyCam
Old News
Sign Guestbook
View Guestbook
VB Horoscope
VB Photo Album
.
ATTENTION READERS! Lucky's VB Gaming Site is no longer active. For updated game programming information and tutorials, please visit The Game Programming Wiki!

Basic Flocking

Hast du dir jemals gewünscht, du könntest eine Gruppe von Objekten dazu bringen sich gerade so zu bewegen, als ob sie einem kollektiven Willen unterworfen wären; ähnlich wie ein Fischschwarm oder einer Herde Büffel? Vielleicht hast Du bemerkt, daß dies ein Herdenproblem (flockingproblem) ist! Witz/Metapher: I'll show you the flocking solution to the whole flocking thing! Ok, crude joke, I know :)

Es gibt mehrere Wege um das hinzukriegen, aber im Wesentlichen, sind dies hier die Regeln damit eine Herde (flock) überzeugend dargestellt werden kann:

- Objekte müssen sich relativ gegenüber dem Zentrum der Gruppe bewegen
- Objekte müssen einen gewissen Mindestabstand und Geschwindigkeit zwischen sich selbst und anderen einhalten
- Objekte müssen sich in einer Geschwindigkeit realtiv zu der gesamten Herde bewegen

Das erweckt den Anschein von intuitiver Bewegung... denkt an eine Herde Zebras in Afrika. Die sichersten Zebras sind die in der Mitte, aber sie müssen eine Distanz zwischen sich und jedem anderen einhalten, und auch die Geschwindigkeit (oder sie werden zurückbleiben) beibehalten. Die Zebras an der Außenseite streben nach innen (so daß sie so weit wie nur möglich von Löwen etc. weg sind!), aber werden das nicht machen, in dem sie über andere Zebras trampeln.

Der Weg wie Du diese Regeln einbindest ist wirklich nicht wichtig, aber ich werde dir zeigen, wie ich es trotzdessen gemacht habe, ein Beispiel:

Little Bo-Peep has lost her sheep

Wir nennen unsere Objekte "sheep" (weil ich Schafe einfach witzig finde). Jetzt weisen wir den "sheep"-Startpositionen zufällige Werte zu, wie es im oberen Bild bereits zu erkennen ist.

Private Type SHEEPTYPE
    sngX As Single
    sngY As Single
    sngXSpeed As Single
    sngYSpeed As Single
End Type
Dim mudtSheep() As SHEEPTYPE

Const NUM_SHEEP = 19
Const MIN_SEPERATION = 15

Dim i As Integer
Dim j As Integer
Dim blnSeperation As Boolean

    ReDim mudtSheep(NUM_SHEEP - 1)

    Randomize
    For i = 0 To UBound(mudtSheep)
        blnSeperation = False
        Do While Not (blnSeperation)
            mudtSheep(i).sngX = Rnd() * frmFlock.ScaleWidth
            mudtSheep(i).sngY = Rnd() * frmFlock.ScaleHeight
            blnSeperation = True
            For j = 0 To i - 1
                If CalcDist(i, j) <= MIN_SEPERATION Then
                    blnSeperation = False
                    Exit For
                End If
            Next j
        Loop
    Next i

Eine ganze Menge Code, nur um ein paar Schafe (sheep) zu verteilen. Als erstes stellen wir die UDT (User Defined Type) für unsere sheep Daten ein, dann erstellen wir ein "dynamic array", und legen seine Größe entsprechend des Wertes der NUM_SHEEP Variablen-Konstante ein. Einfach, nicht? Dann nehmen wir uns jedes sheep vor; verpassen ihm eine For loop Schleife, und weisen ihm noch eine zufällige Position zu. Es ist wichtig, daß sich die Schafe (sheep) in keiner Weise überlappen, also brauchen wir eine ANDERE For loop Schleife, die das für uns prüft. Der ganze Vorgang findet innerhalb einer While loop Schleife statt, bis ein Erfolg verzeichnet wurde.

Sheep of a feather flock together

Ohhhh! Nun sind sie alle in einem Klump zusammengepfercht! Wie konnte das passieren? Es sieht so aus, als ob noch ein wenig Code folgen muß!

Private Function CalcDist(intIndex1 As Integer, intIndex2 As Integer) As Single

    CalcDist = Sqr((mudtSheep(intIndex1).sngX - mudtSheep(intIndex2).sngX) ^ 2 + (mudtSheep(intIndex1).sngY - mudtSheep(intIndex2).sngY) ^ 2)

End Function

Diese nützliche, kleine Funktion (function) liefert die Entfernung zwischen jedem "Zweierschaf" (sheep) zurück (identifiziert durch ihren Indexwert innerhalb des Arrays). Damit können wir den nächsten Nachbarn bestimmen (indem wir loops benutzen, die denen der zufälligen Startpositionskreierung ähneln), und seine Geschwindigkeit überprüfen. Nicht vergessen, wir müssen die Geschwindigkeit jedes einzelnen Schafes (sheep) ähnlich dem der Herde selbst halten!

Const MAX_NOISE = 250

Dim sngXSum As Single
Dim sngYSum As Single
Dim sngXAvg As Single
Dim sngYAvg As Single

    For j = 0 To UBound(mudtSheep)
        sngXSum = sngXSum + mudtSheep(j).sngX
        sngYSum = sngYSum + mudtSheep(j).sngY
    Next j

    sngXAvg = (sngXSum / NUM_SHEEP) + (Rnd() * MAX_NOISE) - (MAX_NOISE / 2)
    sngYAvg = (sngYSum / NUM_SHEEP) + (Rnd() * MAX_NOISE) - (MAX_NOISE / 2)

Dieser Code findet den Mittelpunkt der Herde in dem er den Durchschnitt der X und Y Werte aller sheep ermittelt. Er fügt auch ein paar Störungen hinzu, so daß die sheep den Anschein einer Drängellei erwecken. Der Grund für die Subtraktion von (MAX_NOISE / 2) ist der, das die Störung entweder positiv oder negativ sein kann. Im Grunde fügen wir einen zufälligen Wert zwischen -125 und 125 hinzu.

Alles was übrig bleibt, ist, daß die sheep sich gegenüber dem "Zentrum" bewegen; entsprechend ihrer X und Y Geschwindigkeits-Werte. Außerdem: Falls die Bewegung ein sheep dazu bringt gegen die MIN_SEPERATION zu verstoßen, dann solltest du die gesamte Bewegung zum Abbruch bringen. Sieh dir diesen source code an, wenn du ein "Schäfer für einen Tag" sein möchtest.

Witz/Metapher: I hope you've had some flocking fun! ;)