BlitzSmashMax
SVN

Da das Projekt jetzt Open Source ist, habe ich auf SourceForge ein SVN-Repository angelegt.
Bitte steinigt mich nicht sofort aufgrund des hoch geladenen Codes. Ich habe an vielen Stellen der Einfachheit halber die prozedurale Syntax von BlitzBasic kopiert und in BlitzMax eingefügt. Außerdem hab ich die Codestruktur von 2009 erst Einmal so belassen. Ziel für die Nächsten Tage ist es, die Levels und Charaktere rüber zu ziehen. Danach ist Refactoring angesagt. Eine Ordnerstruktur würde dem Projekt auch ganz gut tun.
Bitte steinigt mich nicht sofort aufgrund des hoch geladenen Codes. Ich habe an vielen Stellen der Einfachheit halber die prozedurale Syntax von BlitzBasic kopiert und in BlitzMax eingefügt. Außerdem hab ich die Codestruktur von 2009 erst Einmal so belassen. Ziel für die Nächsten Tage ist es, die Levels und Charaktere rüber zu ziehen. Danach ist Refactoring angesagt. Eine Ordnerstruktur würde dem Projekt auch ganz gut tun.
Neuauflage

Ich habe gestern Abend angefangen den Code des alten BlitzSmash in Richtung BlitzMax zu konvertierten. Die ganzen Tricks mit Label2 werden dann der Vergangenheit angehören und es wird alles mit Vererbung gelöst werden können.
Dieses mal plane ich den Code komplett Open Source zu stellen und auf einem SVN zu managen.
Durch die lua-Bibliothek in bmax ist es vielleicht auch einfacher gescripte und nicht nur gecodete Charaktere einzubauen. Wäre cool wenn sich dann einige Coder finden würden, die Szenen oder Charaktere aus ihren (Blitz-)Spielen einbauen würden.
Dieses mal plane ich den Code komplett Open Source zu stellen und auf einem SVN zu managen.
Durch die lua-Bibliothek in bmax ist es vielleicht auch einfacher gescripte und nicht nur gecodete Charaktere einzubauen. Wäre cool wenn sich dann einige Coder finden würden, die Szenen oder Charaktere aus ihren (Blitz-)Spielen einbauen würden.
Der Kampf der Functions

Momentanes Ziel ist es, mit seinem Gamemode auf verschiedene Ereignisse zu reagieren. So zum Beispiel auf den Tod einer Figur. Problem ist dann allerdings, dass aus der Funktion ins <main program> gesprungen werden müsste. Das geht auch soweit nur dass dann die Variable <main program>\a nicht mehr die gleiche ist wie Function\a. Das geht sogar so weit dass variablen die ich bei dem zugesprungenen Pointer abgefragt habe, weder die Werte aus <main program> noch aus der Funktion haben. Als ich versuchte das globale blitzarray player[4] mit 0 abzufragen kam bereits "array index out of bounds". Das ganze scheint also praktisch nicht möglich zu sein. Nun bleibt die Frage ob ich ein kleines Event system schreibe oder einfach soetwas wie eine Todesanimation (ähnlich wie im original).
Ideen, Kritik oder gar fertige Lösung nehme ich natürlich gerne an.
============================================
Außerdem gibt es Codetechnisch eine kleine Erleichterung:
Code: [AUSKLAPPEN]
Fasst also einige Zeilen zusammen und schrumpft den Standard Inittirungscode eines Spielers auf
Code: [AUSKLAPPEN]
wer also gerade einen Charakter erstellt und sich den Kopf über diese Zeilen zerbricht, dem sei Hiermit geholfen.
============================================
Das neue Gamemode-Konzept ist auch angefangen. Das heißt das Spiel kann dann auf verschiedene Aktionen der Spieler reagieren und evtl Einschreiten. Dazu gibt es 2 neue Funktionen:
Code: [AUSKLAPPEN]
Diese Ermöglichen es Spieler (zeitweise) aus dem Spiel zu entfernen. Denkbar wäre eine Art Völkerball mit Wiedereinstieg oder eben das simpelste, was ich dann als Beispiel-Gamemode raus bringen werde Last Man Standing.
Hierzu brauch ein Gamemode natürlich verschiedene Usereingaben, wie zB eine Zeit oder Leben. Dazu kann der Gamemode-Coder einem String-Field diese Eingaben in der Form "AnzeigeText1|Anzeigetext2..." angeben. Ein GUI soll diese dann alle beim User abfragen, momentan macht das noch Print und Input.
Schließlich muss der Gamemode noch angeben können wer Sieger und verlierer ist.
Falls jemand dazu ne Idee hat wäre ich ihm sehr dankbar, denn außer 4 Variabeln zu nutzen die dann im ganzen Spiel mitgeschleift werden fände ich nur dann sinnvoll wenn man den Gamemode dazu verpflichten würde diese Dauerhaft irgendwie darzustellen oder gar dass diese von der Engine immer angezeigt werden. Anregungen hierzu auch in die Comments oder in den Threat oder als PM an mich.
============================================
Viel Spaß noch am Coden und Ideen haben.
Ideen, Kritik oder gar fertige Lösung nehme ich natürlich gerne an.
============================================
Außerdem gibt es Codetechnisch eine kleine Erleichterung:
Code: [AUSKLAPPEN]
Function CreatePlayer.player(c.character)
Local p.player
p=New player
p\phx=New phxEntity
p\phx\entModel=CreatePivot()
;als Kollisions-Entity
p\c=c ;Dem Spieler den Charakter zuweisen
EntityType p\phx\entModel,COLLISION_PLAYER
EntityPickMode p\phx\entModel,1 ;} Wichtig für Attacken.
NameEntity p\phx\entModel,Handle(p) ;}
Return p
End Function
Local p.player
p=New player
p\phx=New phxEntity
p\phx\entModel=CreatePivot()
;als Kollisions-Entity
p\c=c ;Dem Spieler den Charakter zuweisen
EntityType p\phx\entModel,COLLISION_PLAYER
EntityPickMode p\phx\entModel,1 ;} Wichtig für Attacken.
NameEntity p\phx\entModel,Handle(p) ;}
Return p
End Function
Fasst also einige Zeilen zusammen und schrumpft den Standard Inittirungscode eines Spielers auf
Code: [AUSKLAPPEN]
p=CreatePlayer(c)
EntityRadius p\phx\entModel,RADIUS
EntityRadius p\phx\entModel,RADIUS
wer also gerade einen Charakter erstellt und sich den Kopf über diese Zeilen zerbricht, dem sei Hiermit geholfen.
============================================
Das neue Gamemode-Konzept ist auch angefangen. Das heißt das Spiel kann dann auf verschiedene Aktionen der Spieler reagieren und evtl Einschreiten. Dazu gibt es 2 neue Funktionen:
Code: [AUSKLAPPEN]
Function DisablePlayer(p.player)
p\devInput=-Abs(p\devInput) ;Das Eingabegerät wird gespeichert aber nicht mehr von der Abfrage erkannt
HideEntity p\phx\entModel ;Entfernt Kollision und Sichtbarkeit
End Function
Function EnablePlayer(p.player)
p\devInput=Abs(p\devInput)
ShowEntity p\phx\entModel
End Function
p\devInput=-Abs(p\devInput) ;Das Eingabegerät wird gespeichert aber nicht mehr von der Abfrage erkannt
HideEntity p\phx\entModel ;Entfernt Kollision und Sichtbarkeit
End Function
Function EnablePlayer(p.player)
p\devInput=Abs(p\devInput)
ShowEntity p\phx\entModel
End Function
Diese Ermöglichen es Spieler (zeitweise) aus dem Spiel zu entfernen. Denkbar wäre eine Art Völkerball mit Wiedereinstieg oder eben das simpelste, was ich dann als Beispiel-Gamemode raus bringen werde Last Man Standing.
Hierzu brauch ein Gamemode natürlich verschiedene Usereingaben, wie zB eine Zeit oder Leben. Dazu kann der Gamemode-Coder einem String-Field diese Eingaben in der Form "AnzeigeText1|Anzeigetext2..." angeben. Ein GUI soll diese dann alle beim User abfragen, momentan macht das noch Print und Input.
Schließlich muss der Gamemode noch angeben können wer Sieger und verlierer ist.
Falls jemand dazu ne Idee hat wäre ich ihm sehr dankbar, denn außer 4 Variabeln zu nutzen die dann im ganzen Spiel mitgeschleift werden fände ich nur dann sinnvoll wenn man den Gamemode dazu verpflichten würde diese Dauerhaft irgendwie darzustellen oder gar dass diese von der Engine immer angezeigt werden. Anregungen hierzu auch in die Comments oder in den Threat oder als PM an mich.
============================================
Viel Spaß noch am Coden und Ideen haben.
3. Release

So, auch wenn DAK noch nicht auf die allerletzte PM geantwortet hat gibt's einen Release.
Die Animation hinkt noch ein Bissl und es fehlen eindeutig sounds und effekte.
die dust.bb steht zwar schon aber die engine dahinter noch nicht ganz..
Wer lust hat und nicht so mit den gosubs durchsteigt kann auch ein Menü proggen. Ausgewählt werden muss nur das was schon per input abgefragt wird. Zur anzeige steht Graphics3D und die Draw3D zur Verfügung.
Download incl Sources Macht euch eure Codes nicht kaputt!
@DAK ich hab deinen Code etwas angepasst.
Die Animation hinkt noch ein Bissl und es fehlen eindeutig sounds und effekte.
die dust.bb steht zwar schon aber die engine dahinter noch nicht ganz..
Wer lust hat und nicht so mit den gosubs durchsteigt kann auch ein Menü proggen. Ausgewählt werden muss nur das was schon per input abgefragt wird. Zur anzeige steht Graphics3D und die Draw3D zur Verfügung.
Download incl Sources Macht euch eure Codes nicht kaputt!
@DAK ich hab deinen Code etwas angepasst.
Readme - Coder

So zur besseren Erklärung gibts heute ein Readme für Coder. Es ist auch in der nächsten upload-Version enthalten.
Enthalten sind teilweise Codeschnippsel, die einfach kopiert werden können, damit jeder mal versuchen kann einen Player oder ein Level zu gestalten.
Viel Spaß damit =)
Code: [AUSKLAPPEN]
Enthalten sind teilweise Codeschnippsel, die einfach kopiert werden können, damit jeder mal versuchen kann einen Player oder ein Level zu gestalten.
Viel Spaß damit =)
Code: [AUSKLAPPEN]
==============
BlitzSmash
==============
1. Grundverhalten
=================
Wütet nicht wild in den einzelnen Dateien herum, jeder Datei ist eine bestimmte Funktion zugeteilt:
Grundlegender Spielablauf
main.bb
titlescreen.bb
Types:
attack.bb
dust.bb
level.bb
player.bb
Engine:
camera.bb
Draw3D.bb by hectic
physics.bb
Data (selbstgemachte Levels, Spieler etc):
attackdata.bb
leveldata.bb
playerdata.bb
Alle Dateien sind im <main program> includet und können Const und Function enthalten. Man sollte es möglichst vermeiden Lokale oder Globale Variablen zu definieren, sondern sollte mittels Const auf die bnkInfo des Types, den man bearbeitet zugreifen. Die Banks möglichst spät erstellen, sodass man nicht eine 200er Bank im Spiel hat, die nicht genutzt wird.
2. Label2 und GoSub2
====================
Die Funktionszeiger.dll von Noobody macht es möglich Labels in Variablen zu speichern.
Einen Label definiert man wie folgt:
tmp=Label2()
If proginit
lblVariable=tmp
Else
<CODE>
Return
EndIf
Die Variable proginit ist vor den Includes 1 und danach 0. Das führt dazu, dass die Variable lblVariable beim Include gesetzt wird aber <CODE> nicht ausgeführt wird. Wird später im Code folgendes ausgeführt:
GoSub2 lblVariable
Dann springt der Code an diese Stelle:
tmp=<---
Das heißt tmp erhällt irgendeinen Wert, weil Label2 nicht ausgeführt wird. Deshalb darf lblVariable nur während proginit=1 ist gesetzt werden, da es sonst mit diesem Wert überschrieben werden würde. Da die GoSub2 erst in der Hauptschleife ausgeführt werden ist proginit=0 und es wird <CODE> ausgeführt und mit Return zurückgesprungen.
3. Einen Player erstellen
=========================
in der Datei playerdata.bb ist folgendes einzugeben:
;<NAME DES CHARAKTÄRS>
Const PLAYER_NAME_Variable=0;=Bankoffset
c.character=New character
c\name="<NAME DES CHARAKTÄRS>"
tmp=Label2();input: c.character ;output:p.player
If proginit
c\lblInit=tmp
Else
;lblInit wird bei der Charakterwahl ausgeführt. Ein Level l ist
;noch nicht gesetzt. Aufgabe der lblInit eines Charaktärs ist es
;einen p.player zu erstellen und ihn spielbereit zu laden.
;Der folgede Teil ist immer gleich
p=New player
p\bnkInfo=CreateBank(4) ;/!\ Die Bankgröße nach Bedarf anpassen
;Dran denken: Ein Handle (zB von Models)
;ist 4 Byte groß.
p\phx=New phxEntity ;Hier wird Der Spieler als Physikalisches
;Objekt erstellt, dass der Schwerkraft
;unterliegt und sterben kann.
p\phx\entModel=CreatePivot()
;Dieser Pivot ist Pflicht und dient
;als Kollisions-Entity
p\c=c ;Dem Spieler den Charakter zuweisen
EntityType p\phx\entModel,COLLISION_PLAYER
EntityPickMode p\phx\entModel,1 ;} Wichtig für Attacken.
NameEntity p\phx\entModel,Handle(p) ;}
;Beispiel für das Aussehen des Players
PokeInt p\bnkInfo,PLAYER_NAME_Variable,CreateCube(p\phx\entModel)
;Anstelle von Variable=CreateCube(p\phx\entModel)
EntityColor PeekInt(p\bnkInfo,PLAYER_NAME_Variable),255,0,0
;Anstelle von EntityColor Variable,255,0,0
Return
EndIf
tmp=Label2();input: btnRight,btnLeft,btnUp,btnDown,btnAtt1,btnAtt2,btnSmash,p.player
If proginit
c\lblMovement=tmp
Else
;lblMovement wird in der Hauptschleife für jeden teilnehmenden
;Spieler ausgeführt. Die Buttons Right und Left sind durch Downs
;und alle anderen nur durch Hits abgefragt.
If btnRight
p\phx\ax=p\phx\ax+0.7;Den Spieler beschleunigen
RotateEntity p\phx\entModel,0,-90,0 ;Den Spieler Drehen,
;sodass er in die
;Laufrichtugn schaut
;Beispiel für Animationssteuerung der Meshs beim Laufen.
;If Not Animating(PeekInt(p\bnkInfo,PLAYER_PLAYER_NAME_ANIM))
; Animate PeekInt(p\bnkInfo,PLAYER_NAME_ANIM),1,0.5
;EndIf
EndIf
If btnLeft
p\phx\ax=p\phx\ax-0.7;Den Spieler beschleunigen
RotateEntity p\phx\entModel,0,90,0 ;Den Spieler Drehen,
;sodass er in die
;Laufrichtugn schaut
;Beispiel für Animationssteuerung der Meshs beim Laufen.
;If Not Animating(PeekInt(p\bnkInfo,PLAYER_PLAYER_NAME_ANIM))
; Animate PeekInt(p\bnkInfo,PLAYER_NAME_ANIM),1,0.5
;EndIf
EndIf
If btnUp
p\phx\ay=p\phx\ay+10;Nach oben beschleunigen
EndIf
If btnDown
p\phx\ay=p\phx\ay-10;Nach unten beschleunigen
EndIf
If btnAtt1 ;Beispiel-Atacke: Kick
If EntityYaw(p\phx\entModel)>0 ;je nachdem wohin man schaut
ATTACK_KICK_Damage(p,-Reichweite,Schaden,-xBeschl,yBeschl)
Else
ATTACK_KICK_Damage(p,-Reichweite,Schaden,+xBeschl,yBeschl)
EndIf
p\tmeStoned=MilliSecs()+50 ;Für 50 Millisec ist der ;Spieler blockiert.
EndIf
If btnAtt2
;Auch eine Attacke
EndIf
If btnSmash
;Auch eine Attacke
EndIf
;Hier kann noch anderer Code, wie Attacken-Bewegungen etc hin.
;Beispiel für Animationssteuerung
;If p\tmeStoned<MilliSecs()
; If Not(btnRight Or btnLeft)
; Animate PeekInt(p\bnkInfo,PLAYER_NAME_ANIM),0
; EndIf
;EndIf
Return
EndIf
4. Ein Level erstellen
======================
In der Datei leveldata.bb ist folgendes einzugeben:
;<Level-Name>
Const LEVEL_NAME_Variable=0;Bank-Offset
l.level=New level
l\maxx=600 ;Beispielmaße
l\minx=-600 ;für
l\maxy=200 ;ein
l\miny=-100 ;Level
l\name="<Level-Name>"
tmp=Label2()
If proginit
l\lblInit=tmp
Else
;lblInit wird einmalig vor der Hauptschleife ausgeführt nachdem
;alle Spieler dem Spiel beigetreten sind.
l\bnkInfo=CreateBank(4);/!\Bankgröße anpassen
;Mindestens ein Gegenstand sollte es geben mit dem der Spieler ;mittels Kugel-Poly-Kollision Kollidieren kann.
PokeInt l\bnkInfo,LEVEL_NAME_Variable,CreateCube()
EntityType PeekInt(l\bnkInfo,LEVEL_NAME_Variable),COLLISION_LEVEL EntityScale PeekInt(l\bnkInfo,LEVEL_NAME_Variable),100,10,10
;Wichtig ist, dass alle 4 Spawnpunkte so Initialisiert werden.
;Man könnte auch mehr als 4 Spawnpunkte erstellen.
spawn[0] = New SpawnPoint
spawn[0]\x=-200
spawn[0]\y=100
spawn[1] = New SpawnPoint
spawn[1]\x=-100
spawn[1]\y=100
spawn[2] = New SpawnPoint
spawn[2]\x=100
spawn[2]\y=100
spawn[3] = New SpawnPoint
spawn[3]\x=200
spawn[3]\y=100
Return
EndIf
tmp=Label2()
If proginit
l\lblLevel=tmp
Else
;lblLevel wird in der Hauptschleife nach lblMovement ausgeführt.
;l und currentlevel enthalten die Level-Variable. Hier kann man
;Code schreiben, sodass sich das Level bewegt oder interagiert.
Return
EndIf
5. Attacken erstellen
=====================
in der ersten Zeile der attackdata.bb steht:
Global ATTACK_KICK.AttackType,...
Hier die eigene Attacke in der Form ATTACK_NAME hinzufügen.
Dann ans Ende der Datei
;<Attacken-Name>
Const ATTACK_NAME_Variable=0;Bank-Offset
ATTACK_NAME=New Attacktype;wurde bei Global schon eingeführt
;ATTACK_NAME\bnkInfo=CreateBank(0)
;Evtl können hier schon Texturen oder Entitys für eine solche Attacke
;geladen werden. Diese sollten aber zunächst unsichtbar sein.
tmp=Label2()
If proginit
ATTACK_KICK\lblMovement=tmp
Else
;lblMovement wird ausgeführt wenn ein Spieler eine Attacke
;ausführt. *Wenn die Attacke beendet wird muss sie sich selbst
;löschen.*
;Tipps:
;Reichweite in einem Byte Speichern
tmp=PeekByte(a\bnkInfos,ATTACK_NAME_DISTANCE)
If tmp>128 Then tmp=tmp-256;unsinged Byte->signed byte
;Einfach mit PokeByte reinschreiben und so auslesen
;Einen Gegner finden:
;Am einfachsten geht das mit einer Pick-Methode, da jeder
;Charakter mit seinem Kollisions-Entity Pickbar ist und seine
;player-Handle als Namen dieses Models trägt
;Beispiel:
LinePick x,y,0,distancex,distancey,0,radius
If PickedEntity()<>0
p.player=Object.player(EntityName(PickedEntity()));p=Ziel
If p<>Null
Damage(p,prozent,xBeschl,yBeschl)
EndIf
EndIf
Delete a ;Nach Beendigung der Attacke muss sie sich löschen.
;Eine Attacke kann natürlich auch mehrere Frames
;andauern.
Return
EndIf
;Hilfsfunktionen können nützlich sein um Banks zu füllen etc.
;Hier zB die Hilfsfunkiton zu KICK. Innerhalb von Hilfsfunktionen sind ;lokale Variablen erlaubt.
Function ATTACK_KICK_Damage(p.player,distance,percent,ax#,ay#)
Local a.Attack
a=New Attack
a\at=ATTACK_KICK
a\bnkInfos=CreateBank(ATTACK_KICK_SIZE)
PokeFloat a\bnkInfos,ATTACK_KICK_X,EntityX(p\phx\entModel)
PokeFloat a\bnkInfos,ATTACK_KICK_Y,EntityY(p\phx\entModel)
PokeByte a\bnkInfos,ATTACK_KICK_DISTANCE,distance
PokeByte a\bnkInfos,ATTACK_KICK_PERCENT,percent
PokeFloat a\bnkInfos,ATTACK_KICK_AX,ax
PokeFloat a\bnkInfos,ATTACK_KICK_AY,ay
End Function
BlitzSmash
==============
1. Grundverhalten
=================
Wütet nicht wild in den einzelnen Dateien herum, jeder Datei ist eine bestimmte Funktion zugeteilt:
Grundlegender Spielablauf
main.bb
titlescreen.bb
Types:
attack.bb
dust.bb
level.bb
player.bb
Engine:
camera.bb
Draw3D.bb by hectic
physics.bb
Data (selbstgemachte Levels, Spieler etc):
attackdata.bb
leveldata.bb
playerdata.bb
Alle Dateien sind im <main program> includet und können Const und Function enthalten. Man sollte es möglichst vermeiden Lokale oder Globale Variablen zu definieren, sondern sollte mittels Const auf die bnkInfo des Types, den man bearbeitet zugreifen. Die Banks möglichst spät erstellen, sodass man nicht eine 200er Bank im Spiel hat, die nicht genutzt wird.
2. Label2 und GoSub2
====================
Die Funktionszeiger.dll von Noobody macht es möglich Labels in Variablen zu speichern.
Einen Label definiert man wie folgt:
tmp=Label2()
If proginit
lblVariable=tmp
Else
<CODE>
Return
EndIf
Die Variable proginit ist vor den Includes 1 und danach 0. Das führt dazu, dass die Variable lblVariable beim Include gesetzt wird aber <CODE> nicht ausgeführt wird. Wird später im Code folgendes ausgeführt:
GoSub2 lblVariable
Dann springt der Code an diese Stelle:
tmp=<---
Das heißt tmp erhällt irgendeinen Wert, weil Label2 nicht ausgeführt wird. Deshalb darf lblVariable nur während proginit=1 ist gesetzt werden, da es sonst mit diesem Wert überschrieben werden würde. Da die GoSub2 erst in der Hauptschleife ausgeführt werden ist proginit=0 und es wird <CODE> ausgeführt und mit Return zurückgesprungen.
3. Einen Player erstellen
=========================
in der Datei playerdata.bb ist folgendes einzugeben:
;<NAME DES CHARAKTÄRS>
Const PLAYER_NAME_Variable=0;=Bankoffset
c.character=New character
c\name="<NAME DES CHARAKTÄRS>"
tmp=Label2();input: c.character ;output:p.player
If proginit
c\lblInit=tmp
Else
;lblInit wird bei der Charakterwahl ausgeführt. Ein Level l ist
;noch nicht gesetzt. Aufgabe der lblInit eines Charaktärs ist es
;einen p.player zu erstellen und ihn spielbereit zu laden.
;Der folgede Teil ist immer gleich
p=New player
p\bnkInfo=CreateBank(4) ;/!\ Die Bankgröße nach Bedarf anpassen
;Dran denken: Ein Handle (zB von Models)
;ist 4 Byte groß.
p\phx=New phxEntity ;Hier wird Der Spieler als Physikalisches
;Objekt erstellt, dass der Schwerkraft
;unterliegt und sterben kann.
p\phx\entModel=CreatePivot()
;Dieser Pivot ist Pflicht und dient
;als Kollisions-Entity
p\c=c ;Dem Spieler den Charakter zuweisen
EntityType p\phx\entModel,COLLISION_PLAYER
EntityPickMode p\phx\entModel,1 ;} Wichtig für Attacken.
NameEntity p\phx\entModel,Handle(p) ;}
;Beispiel für das Aussehen des Players
PokeInt p\bnkInfo,PLAYER_NAME_Variable,CreateCube(p\phx\entModel)
;Anstelle von Variable=CreateCube(p\phx\entModel)
EntityColor PeekInt(p\bnkInfo,PLAYER_NAME_Variable),255,0,0
;Anstelle von EntityColor Variable,255,0,0
Return
EndIf
tmp=Label2();input: btnRight,btnLeft,btnUp,btnDown,btnAtt1,btnAtt2,btnSmash,p.player
If proginit
c\lblMovement=tmp
Else
;lblMovement wird in der Hauptschleife für jeden teilnehmenden
;Spieler ausgeführt. Die Buttons Right und Left sind durch Downs
;und alle anderen nur durch Hits abgefragt.
If btnRight
p\phx\ax=p\phx\ax+0.7;Den Spieler beschleunigen
RotateEntity p\phx\entModel,0,-90,0 ;Den Spieler Drehen,
;sodass er in die
;Laufrichtugn schaut
;Beispiel für Animationssteuerung der Meshs beim Laufen.
;If Not Animating(PeekInt(p\bnkInfo,PLAYER_PLAYER_NAME_ANIM))
; Animate PeekInt(p\bnkInfo,PLAYER_NAME_ANIM),1,0.5
;EndIf
EndIf
If btnLeft
p\phx\ax=p\phx\ax-0.7;Den Spieler beschleunigen
RotateEntity p\phx\entModel,0,90,0 ;Den Spieler Drehen,
;sodass er in die
;Laufrichtugn schaut
;Beispiel für Animationssteuerung der Meshs beim Laufen.
;If Not Animating(PeekInt(p\bnkInfo,PLAYER_PLAYER_NAME_ANIM))
; Animate PeekInt(p\bnkInfo,PLAYER_NAME_ANIM),1,0.5
;EndIf
EndIf
If btnUp
p\phx\ay=p\phx\ay+10;Nach oben beschleunigen
EndIf
If btnDown
p\phx\ay=p\phx\ay-10;Nach unten beschleunigen
EndIf
If btnAtt1 ;Beispiel-Atacke: Kick
If EntityYaw(p\phx\entModel)>0 ;je nachdem wohin man schaut
ATTACK_KICK_Damage(p,-Reichweite,Schaden,-xBeschl,yBeschl)
Else
ATTACK_KICK_Damage(p,-Reichweite,Schaden,+xBeschl,yBeschl)
EndIf
p\tmeStoned=MilliSecs()+50 ;Für 50 Millisec ist der ;Spieler blockiert.
EndIf
If btnAtt2
;Auch eine Attacke
EndIf
If btnSmash
;Auch eine Attacke
EndIf
;Hier kann noch anderer Code, wie Attacken-Bewegungen etc hin.
;Beispiel für Animationssteuerung
;If p\tmeStoned<MilliSecs()
; If Not(btnRight Or btnLeft)
; Animate PeekInt(p\bnkInfo,PLAYER_NAME_ANIM),0
; EndIf
;EndIf
Return
EndIf
4. Ein Level erstellen
======================
In der Datei leveldata.bb ist folgendes einzugeben:
;<Level-Name>
Const LEVEL_NAME_Variable=0;Bank-Offset
l.level=New level
l\maxx=600 ;Beispielmaße
l\minx=-600 ;für
l\maxy=200 ;ein
l\miny=-100 ;Level
l\name="<Level-Name>"
tmp=Label2()
If proginit
l\lblInit=tmp
Else
;lblInit wird einmalig vor der Hauptschleife ausgeführt nachdem
;alle Spieler dem Spiel beigetreten sind.
l\bnkInfo=CreateBank(4);/!\Bankgröße anpassen
;Mindestens ein Gegenstand sollte es geben mit dem der Spieler ;mittels Kugel-Poly-Kollision Kollidieren kann.
PokeInt l\bnkInfo,LEVEL_NAME_Variable,CreateCube()
EntityType PeekInt(l\bnkInfo,LEVEL_NAME_Variable),COLLISION_LEVEL EntityScale PeekInt(l\bnkInfo,LEVEL_NAME_Variable),100,10,10
;Wichtig ist, dass alle 4 Spawnpunkte so Initialisiert werden.
;Man könnte auch mehr als 4 Spawnpunkte erstellen.
spawn[0] = New SpawnPoint
spawn[0]\x=-200
spawn[0]\y=100
spawn[1] = New SpawnPoint
spawn[1]\x=-100
spawn[1]\y=100
spawn[2] = New SpawnPoint
spawn[2]\x=100
spawn[2]\y=100
spawn[3] = New SpawnPoint
spawn[3]\x=200
spawn[3]\y=100
Return
EndIf
tmp=Label2()
If proginit
l\lblLevel=tmp
Else
;lblLevel wird in der Hauptschleife nach lblMovement ausgeführt.
;l und currentlevel enthalten die Level-Variable. Hier kann man
;Code schreiben, sodass sich das Level bewegt oder interagiert.
Return
EndIf
5. Attacken erstellen
=====================
in der ersten Zeile der attackdata.bb steht:
Global ATTACK_KICK.AttackType,...
Hier die eigene Attacke in der Form ATTACK_NAME hinzufügen.
Dann ans Ende der Datei
;<Attacken-Name>
Const ATTACK_NAME_Variable=0;Bank-Offset
ATTACK_NAME=New Attacktype;wurde bei Global schon eingeführt
;ATTACK_NAME\bnkInfo=CreateBank(0)
;Evtl können hier schon Texturen oder Entitys für eine solche Attacke
;geladen werden. Diese sollten aber zunächst unsichtbar sein.
tmp=Label2()
If proginit
ATTACK_KICK\lblMovement=tmp
Else
;lblMovement wird ausgeführt wenn ein Spieler eine Attacke
;ausführt. *Wenn die Attacke beendet wird muss sie sich selbst
;löschen.*
;Tipps:
;Reichweite in einem Byte Speichern
tmp=PeekByte(a\bnkInfos,ATTACK_NAME_DISTANCE)
If tmp>128 Then tmp=tmp-256;unsinged Byte->signed byte
;Einfach mit PokeByte reinschreiben und so auslesen
;Einen Gegner finden:
;Am einfachsten geht das mit einer Pick-Methode, da jeder
;Charakter mit seinem Kollisions-Entity Pickbar ist und seine
;player-Handle als Namen dieses Models trägt
;Beispiel:
LinePick x,y,0,distancex,distancey,0,radius
If PickedEntity()<>0
p.player=Object.player(EntityName(PickedEntity()));p=Ziel
If p<>Null
Damage(p,prozent,xBeschl,yBeschl)
EndIf
EndIf
Delete a ;Nach Beendigung der Attacke muss sie sich löschen.
;Eine Attacke kann natürlich auch mehrere Frames
;andauern.
Return
EndIf
;Hilfsfunktionen können nützlich sein um Banks zu füllen etc.
;Hier zB die Hilfsfunkiton zu KICK. Innerhalb von Hilfsfunktionen sind ;lokale Variablen erlaubt.
Function ATTACK_KICK_Damage(p.player,distance,percent,ax#,ay#)
Local a.Attack
a=New Attack
a\at=ATTACK_KICK
a\bnkInfos=CreateBank(ATTACK_KICK_SIZE)
PokeFloat a\bnkInfos,ATTACK_KICK_X,EntityX(p\phx\entModel)
PokeFloat a\bnkInfos,ATTACK_KICK_Y,EntityY(p\phx\entModel)
PokeByte a\bnkInfos,ATTACK_KICK_DISTANCE,distance
PokeByte a\bnkInfos,ATTACK_KICK_PERCENT,percent
PokeFloat a\bnkInfos,ATTACK_KICK_AX,ax
PokeFloat a\bnkInfos,ATTACK_KICK_AY,ay
End Function
Neues Level & Mario Animationen

Ich hab bei dem Spieler Magic-Mario eine Dreheung bei dem Sekundär-Attacken-Sprung eingebaut. Der rechte macht das gerade. Während der Drehung ist man "stoned" Das heißt man kann sich nicht Bewegen. Die Funktion war zunächst zwar für angegriffene gedacht aber hier scheint sie auch für den Angreifer sinnvoll. Smash-Attacke ist mir noch keine eingefallen... könnt ja eine schreiben oder zumindest die Idee mir schicken.
Außerdem gibt es ein zweites Level. Es stammt aus dem Spiel "Parcour", das ich zum BCC 3 entworfen habe und nutzt als erstes Level den lblLevel. Das heißt das Level ist in der Schleife interaktiv.
Im Code selbst hab ich in der Main verändert dass lblMovement nun auch wenn man stoned ist aufgerufen wird. Das macht solche Späße wie Animationen während einer Attacke möglich bei gleichzeitiger Blockierung der Attacke mittels tmeStoned. Während man stoned ist sind natürlich alle Tasten auf False
Download incl. Sources - Macht euch nicht eure Codes kaputt!
Momentane Arbeiten

Ich bin Offen für Ideen und allerlei Grafik und Programmiercodes. Bis sich jemand erbarmt, werde ich wohl mit meinen bescheidenen Charakteren und Levels zu tun haben.
Tatsächlich arbeite ich momentan an der Animation Marios, sodass dieser mal etwas interessanter aussieht als auf dem Foto. Ideen etc sind gerne gesehen...
Tatsächlich arbeite ich momentan an der Animation Marios, sodass dieser mal etwas interessanter aussieht als auf dem Foto. Ideen etc sind gerne gesehen...
Beginn des Worklogs

BlitzSmash V0.1
Dies soll ein SuperSmashBrothers Clon werden. Nur eben nicht mit Nintendo-Charakteren, sondern mit welchem aus diesem Forum. Da ich nicht das Recht (und die Zeit) alle oder zumindest einen Teil der Projekte der Comunity zu durchforsten um dann die Charaktere daraus nachzuprogrammieren habe ich zumindest mal die Engine und einen Charakter aus einem Spiel von mir Eingebaut. Auch Karten fehlen noch, aber auch die sollen noch folgen.
Insgesamt fehlt noch ziemlich viel, weswegen ich die Comunity in diesem Thread auffordere an dem Spiel aktiv mitzuarbeiten.
Steuerung:
Hier noch ein Screenshot der momentanen Version:
______________________________________________________________________________
Soviel also zum ehemaligen Projektthread.
Wie das bei meinen Auftritten hier im Forum schon immer so war hab ich mal wieder die Hälfte vergessen... Der Download unvollständig, keine Readme etc... Nunja nun gibt es eben hier immer die neusten Versionen
eben hier.
Die hoffentlich endlich lauffähige Version gibts nun sammt sources im Komplettpaket hier
Dies soll ein SuperSmashBrothers Clon werden. Nur eben nicht mit Nintendo-Charakteren, sondern mit welchem aus diesem Forum. Da ich nicht das Recht (und die Zeit) alle oder zumindest einen Teil der Projekte der Comunity zu durchforsten um dann die Charaktere daraus nachzuprogrammieren habe ich zumindest mal die Engine und einen Charakter aus einem Spiel von mir Eingebaut. Auch Karten fehlen noch, aber auch die sollen noch folgen.
Insgesamt fehlt noch ziemlich viel, weswegen ich die Comunity in diesem Thread auffordere an dem Spiel aktiv mitzuarbeiten.
Steuerung:
- Keyboard Left:
Sprung: W
Schnell fallen: S
Rechts: D
Links: A
Attacke 1: Umschalt links
Attacke 2: Leerzeichen - Keyboard Right:
Sprung: Pfeil Hoch
Schnell fallen: Pfeil Runter
Rechts: Pfeil Rechts
Links: Pfeil Links
Attacke 1: STRG Rechts
Attacke 2: Numpad 0 - Maus:
Sprung: Hoch
Schnell fallen: Runter
Rechts: Rechts
Links: Links
Attacke 1: Linksklick
Attacke 2: Rechtsklick - Joystick:
Sprung: Hoch
Schnell fallen: Runter
Rechts: Rechts
Links: Links
Attacke 1: Firebutton 1 (ggf suchen)
Attacke 2: Firebutton 2 (ggf suchen)
Hier noch ein Screenshot der momentanen Version:
______________________________________________________________________________
Soviel also zum ehemaligen Projektthread.
Wie das bei meinen Auftritten hier im Forum schon immer so war hab ich mal wieder die Hälfte vergessen... Der Download unvollständig, keine Readme etc... Nunja nun gibt es eben hier immer die neusten Versionen
eben hier.
Die hoffentlich endlich lauffähige Version gibts nun sammt sources im Komplettpaket hier