4.9.1 |
Pacmans
Ereignisse |
[ Top ]
|
Die erste
untergeordnete Ereignisprozedur ist OBJ_EVENT_PACMAN. Diese
Prozedur verwaltet nur PACMAN selbst, die "essbaren"
Punkte und die Flagge. |
Der
Prozedurkopf ist relativ simpel und auch eigentlich schon
bekannt. Es werden wieder die gleichen Variablen wie bei
OBJ_EVENT übergeben. Anschließend öffnen wir einen SELECT-CASE-Block, in dem wir den Typ des übergebenen
Objekts auswählen.
|
|
|
Sub
USER_EVENT_PACMAN (Self As
ObjType,MESSAGE,Other As ObjType, _
Par1, Par2)
Select Case
Self.T
|
|
|
Nun kommt der
Teil für Pacman. Hier wählen wir wieder per SELECT CASE
das aufgetretene Ereignis aus:
|
|
|
Case
NR_PACMAN: 'Pacman
Select Case MESSAGE
|
|
|
Jetzt kommt
als erstes das DRAW-Ereignis. Das Einrücken müssen Sie in
diesem Fall selbst noch korrekt erledigen, da sonst fast
alle Zeilen länger gewesen wären als die Seitenbreite. |
|
|
Case
ID_DRAW
|
|
|
Am Anfang
verwenden wir OBJ_ANIMATE um die Reservewerte R1 und R2 als
Spritezähler zu verwenden. R1 wird solange erhöht, bis es
den Wert 3 hat. Dann wird es zurückgesetzt und R2
wird erhöht. Wenn R2 den Wert 3 erreicht, wird es auf 0
gesetzt. Damit haben wir in R2 die Animationsphase (zwischen
0 und 3), die sich alle vier Durchgänge ändert. So bekommt
man einfach langsamere Animationen hin. Dann werden noch R3
auf 0 gesetzt und V (Sichtbar) auf 1.
|
|
|
OBJ_ANIMATE
Self.R1, 3, Self.R2, 3
Self.R3 = 0
Self.V = 1
|
|
|
Nun wird überprüft,
ob PACMAN irgendwelche Extras bei sicht hat. Zuerst schauen
wir nach, ob er das COOL-Item hat (Zeit bleibt stehen) und
die Energie dieses Items größer als Null ist. Wenn ja,
verringern wir die "Energie" dieses Items, und R3 wird auf 12 gesetzt. Der Reservewert R3
wird bei Pacman dazu verwendet, zu bestimmen, in welchem
Modus sich Pacman befindet. Dieser Wert wird immer zur
Spritenummer hinzuaddiert. Da das COOL-Item die Zeit
anhalten soll, so lange es wirkt, setzten wir alle anderen
Objekte außer Pacman auf die letzte Position zurück. Ist
das Item dann leer, wird es per OBJ_ITEM_DROP aus dem
Inventar gestrichen.
|
|
|
If
OBJ_ITEM_HAVE(Self, NR_ITEM_COOL) Then
Energy = OBJ_ITEM_ENERGY_GET(Self, NR_ITEM_COOL)
If
Energy > 0 Then
OBJ_ITEM_ENERGY_SET Self, NR_ITEM_COOL, Energy - 1
Self.R3 = 12
For
M = 0 To UBound(Obj)
If
Obj(M).T <> NR_PACMAN Then
Obj(M).X = Obj(M).OX
Obj(M).Y = Obj(M).OY
End If
Next
M
Else
OBJ_ITEM_DROP Self, NR_ITEM_COOL
End If
End If
|
|
|
Etwas
einfacher ist es bei dem Unsichbar-Item. Hier gilt zwar das
gleiche System mit der Energie, jedoch wird als Auswirkung
einfach nur Self.V auf 0 gesetzt, das Pacman für alle
Monster unsichtbar macht. Außerdem haben wir hier einen
anderen Wert für R3, damit Pacman auch auf dem Spielfeld
unsichtbar erscheint.
|
|
|
If
OBJ_ITEM_HAVE(Self, NR_ITEM_INVISIBLE) Then
Energy =
OBJ_ITEM_ENERGY_GET(Self, NR_ITEM_INVISIBLE)
If
Energy > 0 Then
OBJ_ITEM_ENERGY_SET Self, NR_ITEM_INVISIBLE, Energy - 1
Self.R3 = 8
Self.V = 0
Else
OBJ_ITEM_DROP Self, NR_ITEM_INVISIBLE
End If
End If
|
|
|
Bei dem
Terminator-Item wird R3 auf 4 gesetzt und die
Pacman-Geschwindigkeit mit 1,5 multipliziert. Die
Auswirkungen werden an einer anderen Stelle berücksichtigt.
|
|
|
If
OBJ_ITEM_HAVE(Self, NR_ITEM_TERMINATOR) Then
Energy =
OBJ_ITEM_ENERGY_GET(Self, NR_ITEM_TERMINATOR)
If
Energy > 0 Then
OBJ_ITEM_ENERGY_SET Self, NR_ITEM_TERMINATOR, Energy - 1
Self.R3 = 4
Self.SX = Self.SX * 1.5
Self.SY = Self.SY * 1.5
Else
OBJ_ITEM_DROP Self, NR_ITEM_TERMINATOR
End If
End If
|
|
|
Zum Schluss wird dann der FRAME aus der ID + dem Reservewert R3
errechnet. Zusätzlich wird geprüft, in welche Richtung
Pacman sieht. Schaut er nach oben wird PACMAN_UP als
Grundnummer benutzt usw.
|
|
|
Self.FRAME =
Spr(ID_PACMAN_DOWN + Self.R3)
If
Self.SY<0 Then
Self.FRAME=Spr(ID_PACMAN_UP+Self.R2 + Self.R3)
If
Self.SY>0 Then
Self.FRAME=Spr(ID_PACMAN_DOWN+Self.R2+Self.R3)
If
Self.SX>0 Then
Self.FRAME=Spr(ID_PACMAN_RIGHT+Self.R2+Self.R3)
If
Self.SX<0 Then
Self.FRAME=Spr(ID_PACMAN_LEFT+Self.R2+Self.R3)
|
|
|
Das war auch
schon das komplette Ereignis zum Anzeigen von PACMAN in
allen Lebenslagen. Jetzt fehlen uns noch andere wichtige
Ereignisse: ID_MOVE gibt an, dass sich das Objekt bewegen
soll, und zwar um die übergebenen Werte Par1 (=X-Bewegung)
und Par2 (=Y-Bewegung). Vorher wird hier, wie bei den
Monstern auch, die Position gespeichert, damit sie später
wieder geladen werden kann. Nach der Bewegung wird
OBJ_COLL_FIELD aufgerufen, um zu prüfen, ob PACMAN immer
noch auf einem leeren Feld steht.
|
|
|
Case
ID_MOVE
Self.OX = Self.X
Self.OY = Self.Y
Self.X = Self.X + Par1
Self.Y = Self.Y + Par2
OBJ_COLL_FIELD Self
|
|
|
Ist dies
nicht der Fall, ruft die Routine OBJ_COLL_FIELD das Ereignis
ID_COLL_FIELD auf. Dieses sieht bei den Akteuren immer
gleich aus:
|
|
|
Case
ID_COLL_WALL
Self.X = Self.OX
Self.Y = Self.OY
Self.SX = Self.SX / 2
Self.SY = Self.SY / 2
OBJ_EVENT Self, ID_MOVE, ObjDummy, Self.SX, Self.SY
|
|
|
Die Position wird zurückgesetzt
und die Geschwindigkeit halbiert. Anschließend wird noch
einmal ID_MOVE aufgerufen, um zu testen, ob sich das Objekt
wenigstens etwas weiterbewegen kann.
|
Damit wäre PACMAN selbst auch
schon abgehandelt. Das war doch nicht so schwer, oder?
|
Nun zu den
"essbaren" Punkten, die PACMAN während des Spiels
einsammeln muss:
|
|
|
Case
NR_DOT: 'Punkte
Select Case
MESSAGE
|
|
|
Bei einer
Kollision wird geprüft, ob PACMAN der Auslöser war. In dem
Fall sucht die Routine, ob PACMAN bereits über ein Item
NR_DOT verfügt. Wenn ja wird der Wert eingelesen, erhöht
und dann wieder zurückgeschrieben. Wenn nein, wird dieses
Item nun mit der "Energie" (was ja nicht unbedingt
für Energie im herkömmlichen Sinne steht, sondern in
diesem Fall eher Quantität bedeutet) 1 angelegt. Anschließend
bekommt PACMAN noch 5 Punkte, und eine WAVE-Datei wird abgespielt. Am Ende wird das Objekt gelöscht, damit der
Punkt nicht noch einmal eingesammelt werden kann.
|
|
|
Case
ID_COLL
If
Other.T = NR_PACMAN Then
Dots = OBJ_ITEM_ENERGY_GET(Other, NR_DOT) + 1
OBJ_ITEM_ENERGY_SET Other, NR_DOT, Dots
OBJ_CLEAR Self
LEVEL_SCORE = LEVEL_SCORE + 5
WAV_PLAYBACK Pfad$ + "DOT.WAV"
End If
|
|
|
Das Zeichnen
verläuft denkbar einfach. Wir haben auch wieder einen
Animationszähler (R2 nimmt Werte zwischen 0 und 3 an) und
addieren den zu ID_DOT, was ja die Position der Punkte im
Sprite-Datenfeld ist. Nun wird der Frame aktualisiert.
|
|
|
Case
ID_DRAW
OBJ_ANIMATE Self.R1, 0, Self.R2, 3
Self.FRAME = Spr(ID_DOT + Self.R2)
End Select
|
|
|
Die Flagge,
die das Ziel markiert, ist auch nicht mehr schwer zu
realisieren:
|
|
|
Case
NR_FLAG: 'Flagge
Select Case
MESSAGE
|
|
|
Bei einer
Kollision mit der Flagge wird geprüft, ob Pacman das Item
NR_DOT bei sich hat und ob dessen "Energie"
genauso groß ist, wie die Anzahl der Punkte insgesamt. In
diesem Fall bekommt er 50 Punkte und LEVEL_NEXT wird auf 1
gesetzt, um dem Hauptprogramm mitzuteilen, dass das Level
erledigt ist.
|
|
|
Case
ID_COLL
If
Other.T = NR_PACMAN Then
If
COUNT_DOTS=OBJ_ITEM_ENERGY_GET(Other, NR_DOT) Then
LEVEL_NEXT = 1
LEVEL_SCORE = LEVEL_SCORE + 50
End If
End If
|
|
|
Beim Zeichnen
werden zwei Fälle unterschieden: Wenn alle Punkte gesammelt
worden sind bewegt sich die Flagge, wird also per
Animationszähler verändert, Wenn nicht, wird nur das erste
Bild angezeigt. Daran kann der Spieler dann schon immer
sehen, ob er sich zum Ausgang begeben kann oder nicht.
|
|
|
Case
ID_DRAW
If
COUNT_DOTS = OBJ_ITEM_ENERGY_GET(Obj(0), NR_DOT) Then
OBJ_ANIMATE Self.R1, 1, Self.R2, 9
Self.FRAME = Spr(ID_FLAG + Self.R2)
Else
Self.FRAME = Spr(ID_FLAG)
End If
End Select
|
|
|
Und nun das
letzte Objekt aus USER_EVENT_PACMAN: Der Animator. Dieses
Objekt dient dazu, eine Animation darzustellen. Das Objekt
agiert und reagiert nicht. Es wird z.B. benutzt, wenn ein
Monster stirbt, die "Überreste" darzustellen ohne
einen eigenen Typ zu definieren. Das Objekt stellt immer
eine Animation zwischen R3+0 und R3+3 dar. Darum muss der
Wert R3 gesetzt werden, bevor man ein solches Objekt
erstellt.
|
|
|
Case
NR_ANIMATOR:
Select Case
MESSAGE
Case
ID_DRAW
OBJ_ANIMATE Self.R1, 0, Self.R2, 3
Self.FRAME = Spr(Self.R3 + Self.R2)
End Select
|
|
|