BlitzBasic-Community-Tutorial/ Wir programmieren einen 3D SpaceShooter

Einen Space-Shooter zu coden, ist an sich nicht so schwer. Die eigenen Vorstellungen sind oft das größere Hindernis. Wie bei allen Spielen werden auch hier Dinge benötigt, die aus verschiedenen Disziplinen stammen. Code, Musik, Grafik, Modelle, Geschichte. Da selten eine Person alle Disziplinen beherrscht, sind die zu erwartenden Ergebnisse von vornherein erheblich tiefer anzusetzen. Ausnahmen sind natürlich Teams. Aber davon gibt es nicht viele, die es über einen längeren Zeitraum zusammen schaffen. Ich gehe hier davon aus, dass der Leser schon ein wenig Erfahrung mit Blitz3D hat und alleine arbeitet. Es ist außerdem nützlich, über ein aktuelles Original zu verfügen.

Eine der wichtigsten Dinge, die man beim Coden berücksichtigen muss, ist die Disziplin. Bestimmte Dinge muss man sich einfach von vorne herein angewöhnen.

  1. Erstellung einer Variablenliste mit Kommentaren zur Funktion einer jeden Variable.
  2. Erstellung einer Liste, die Erklärungen zu Funktionen enthält.
  3. Ein Konzept für das Spiel (obwohl ein solches vor allem von Hobbyentwicklern selten erstellt wird).


Was soll es denn werden? Bearbeiten

Diese Frage muss man sich in jedem Fall stellen. Ansonsten wird es aus dem Projekt ganz schnell ein unendlich andauerndes Unterfangen.

Wir brauchen:

  • einen Ort in Form eines Sonnensystems
  • eine Station, in der man Parken kann
  • Gegner, die einen angreifen (z.B. Piraten)
  • Waffen und Raketen
  • Tolle Schiffe
  • variablen Schwierigkeitsgrad
  • eine Kollisionserkennung
  • fetzigen Sound und GFX
  • ein Startintro
  • eine Cockpit-Ansicht
  • Radar und sonstige Kontrollen

Sieht ganz nach einem ELITE-Klon aus... Aber eigentlich sind fast alle 3D-Weltraum-Spiele daran angelehnt.

Na dann mal los...

Programme, die wir brauchen Bearbeiten

Da ich davon ausgehe, dass der Leser alleine codet, sind hier vor allem Programme gefragt die man schnell und leicht bekommen und benutzen kann.

PaintShopPro 4       zum Zeichnen von Texturen und Sprites
DOGA L2              zum Erzeugen von 3D Objekten nach dem Lego Prinzip
Blitz3D              um alles als Code zusammenzubinden
Edit                 zum erstellen von Notizen , !!! ganz wichtig !!!

Die Grundstruktur Bearbeiten

Grundsätzlich sind diese bei allen Spielen gleich.

  1. Initialisierung
  2. Bildschirm öffnen
  3. 3D Umgebung einrichten
  4. Hauptschleife
  5. Funktionen
  6. Datas

Eine mögliche Grundstruktur könnte so aussehen:

;(1)-----------------------------------------------------------------
sx=600				; Screen x
sy=400				; Screen y
;(2)-----------------------------------------------------------------
Graphics3D sx,sy,32,2		; Bildschirm im Fenstermodus öffnen
SetBuffer BackBuffer()		; Das Doublebuffering aktivieren
;(3)-----------------------------------------------------------------
camp=CreatePivot()		; Ein Drehpunkt für die Kamera
cam=CreateCamera(camp)		; Eine Kamera einrichten
MoveEntity cam,0,0,-5		; Die Kamera vom Nullpunkt wegbewegen 
light=CreateLight(1)		; Eine Lichtquelle erzeugen
obj=CreateCube()		; Ein Objekt erzeugen
;(4)-----------------------------------------------------------------
Repeat				; die Hauptschleife

 If KeyHit(1) Then en=1	; auf ESC-Taste reagieren = Exit
	
 TurnEntity camp,.5,0,0	; Den Drehpunkt der Kamera drehen 	
 RenderWorld() 		; Szene zeichen
 Flip  			; Bildschirm wechseln mit WaitSysnc
	
Until en=1			; Exit wenn Taste ESC gedrückt wurde

End				; Programm Ende
;(5)----------------------------------------------------------------
;(6)----------------------------------------------------------------

Der Spieler Bearbeiten

Hier fehlen noch Inhalte! Bitte ergänzen!

Gegner kommen ins Spiel Bearbeiten

Gegner definieren Bearbeiten

Für Gegner sollte man am besten Types verwenden da man bei einem Type sehr einfach viele Gegner erstellen kann.

TYPE enemy
   FIELD xpos
   FIELD ypos 
   FIELD health 
   FIELD name 
END TYPE

Mit diesem Code wird ein neuer Type erstellt mit dem Namen Enemy und den ganzen Daten die ein Gegner haben sollte.

Natürlich könnte man auch einen Array anlegen und darin die Daten lagern aber so etwas geht vielleicht bei einem Pac-Man Spiel wo es immer 4 Gegner gibt. Bei unserem Shooter jedoch sollen es viele sein und mit Array ist das schwer zu machen deswegen werde ich auch nicht weiter auf diesen Lösungsweg weiter eingehen.

Gegner anzeigen und dann wieder löschen Bearbeiten

Natürlich muss der Gegner sich bewegen, und dazu immer als erst gezeichnet, dann wieder gelöscht und dann wieder gezeichnet usw. werden.

Dazu sollte man sich eine extra Funktion Schreiben in der alle Gegner angezeigt werden. Das Löschen macht man am Besten in einer For: Next Schleife in der auch Sachen wie die Kollision überprüft werden.

Eine recht simple Funktion zum Anzeigen aller Gegner sieht wie folgt aus:

FUNCTION enemy_draw
FOR enemy.enemy = EACH enemy
 DRAWIMAGE gegnergrafik,enemy\xpos,enemy\ypos 
NEXT
END FUNCTION

Schüsse Bearbeiten

So... Wer noch keine Ahnung von Types hat, sollte sich erst einmal ein kleines Tutorial dazu anschauen, oder sich einfach hieran versuchen (Grundwissen wird hier vorausgesetzt). Schüsse sollten immer mit Types (oder zur Not auch Dims) realisiert werden und ungefähr so aussehen:

Type Schuss        ; unser Type heißt "Schuss", so kann man auf ihn zugreifen
 Field Photon      ; Spaceshooter-Schiffe schießen immer mit Photonen ;-)
 Field objektdauer ; wie lange unsere Schüsse im Spiel sein sollen
End Type           ; "beendet" den Type

... Bravo! Unser Type ist im Spiel. Er bringt nur noch nicht viel! Wie wäre es denn, wenn man durch Drücken der linken Maustaste den Schuss abfeuern könnte? Dafür setzen wir Folgendes in die Hauptschleife:

If MouseHit(1) Then FeuerSchuss()

... FeuerSchuss() ist eine Funktion (siehe dazu andere Tutorials), die wir jetzt benennen müssen (natürlich außerhalb der Schleife ;-) ):

Function FeuerSchuss()      ;benennt unsere Funktion

 s.Schuss = New Schuss                  ;ein neuer Type wird mit allem drum und dran erstellt
 s\photon = CreateSphere()              ;s\ zeigt, im welchem Type wir uns befinden

 EntityParent Photon,0          ;kein Parameter
 PositionEntity s\photon,EntityX(Spieler),EntityY(Spieler),EntityZ(Spieler)+3 ;sollte klar sein
 s\objektdauer = 100
End Function 


Super! Unser Photon existiert nun! Nun soll es etwas machen. Funktionen helfen uns dabei:

In der Schleife:

For s.Schuss = Each Schuss       ; für jeden Schuss mach das und das...
 UpdateSchuss(s)
Next

Außerhalb der Schleife:

Function UpdateSchuss(s.Schuss)
 MoveEntity p\obj,0,0,100 
 RotateSprite p\obj,Rnd(310)
 If CountCollisions(p\obj) Then 
  If EntityCollided(p\obj, TYPE_TERRAIN) Then
  EmitSound Explo, p\obj
  einschlagX# = EntityX(p\obj)
  einschlagY# = EntityY(p\obj)
  einschlagZ# = EntityZ(p\obj)
  TFormPoint(einschlagX#, EinschlagY#, EinschlagZ#,0,terrain)
  hoehe = TerrainHeight( terrain, TFormedY(),TFormedZ() ) 
  If hoehe>0
   hoehe=hoehe-2:If hoehe<0 Then hi=0
   ModifyTerrain terrain,TFormedY(),TFormedZ(),hoehe,True
  EndIf
 Explosion ( p )

 FreeEntity p\obj
 Delete p
 Return 
  End If 
 End If 
  
End Function