Wie ein Spiel ala Pang programmieren?

Übersicht BlitzBasic Beginners-Corner

Neue Antwort erstellen

 

DaLeecher

Betreff: Wie ein Spiel ala Pang programmieren?

BeitragDi, März 22, 2011 3:37
Antworten mit Zitat
Benutzer-Profile anzeigen
Hallo!
Ich bin neu hier und dies ist mein erstes Posting! Ich bin 25 Jahre und komme aus dem Ruhrpott. Leider bin ich was Programmieren angeht noch ein Neuling, aber ich hoffe dass sich das mit eurer Hilfe bald ändert! Wink

Ich würde sehr gerne mein Lieblingsspiel Pang nachprogrammieren und habe auch schon ein paar Zeilen an lauffähigen Code hinbekommen. Keine Ahnung, ob dass bisher so richtig ist, was ich da versucht habe. Allerdings scheitere ich jetzt total an mehreren Sachen und komme nicht mehr weiter.

- Der Ball soll wie bei Pong springen aber wie?
- Wie kann ich einen oder sogar mehrere Schüsse gleichzeitig darstellen?
- Wie überprüfe ich, ob der Schuss einen Ball getroffen hat?
- Wie kann beim treffen eines Balls, daraus zwei kleinere machen die weiter herumspringen?

Da ich erst seit Samstag mit BlitzBasic arbeite, wäre ich für infos oder Beispiele sehr dankbar! Schöne Grüße.
Und hier nochmal schnell mein bisheriger Programmiercode.

Code: [AUSKLAPPEN]

entfernt, da veraltet
  • Zuletzt bearbeitet von DaLeecher am Di, März 22, 2011 22:12, insgesamt einmal bearbeitet

Midimaster

BeitragDi, März 22, 2011 4:03
Antworten mit Zitat
Benutzer-Profile anzeigen
Um mehrere gleichartige Spiel-Elemente (z.b. Bälle) zu verwenden sind TYPES ideal.

Allerdings weiss ich nicht, wie gut Du das schon checken wirst. Hier das passende Tutorial:

https://www.blitzforum.de/foru...hp?t=33551


Um den Ball hüpfen zu lassen, suche nach dem Begriff "Schwerkraft" oder "Gravitation" im Forum

Die Kollision von Objekten wird rein mathematisch erreicht. Oft genügt es die Randmaße (umgebende Rechtecke) mit RectsOverlap abzuchecken.

BladeRunner

Moderator

BeitragDi, März 22, 2011 7:34
Antworten mit Zitat
Benutzer-Profile anzeigen
~VERSCHOBEN~
Dieser Thread passte nicht in das Forum, in dem er ursprünglich gepostet wurde.


Willkommen im BBP.
Zu Diensten, Bürger.
Intel T2300, 2.5GB DDR 533, Mobility Radeon X1600 Win XP Home SP3
Intel T8400, 4GB DDR3, Nvidia GF9700M GTS Win 7/64
B3D BMax MaxGUI

Stolzer Gewinner des BAC#48, #52 & #92
 

DaLeecher

BeitragDi, März 22, 2011 17:48
Antworten mit Zitat
Benutzer-Profile anzeigen
Danke für die Infos. Habe mir das ganze einigemale durchgelesen und versucht umzusetzen. Allerdings weiß ich noch immer nicht, wie ich nun weitermachen soll! Nach wie vor die alten Probleme, wie ich oben genannte Punkte realisieren kann.

Schiesen kann man jetzt mit SPACE-Taste! Spiel stürtzt öfters einfach ab! Es kann wohl den Font nicht laden?

Ist der Code jetzt so richtig, wie du meintest?

Code: [AUSKLAPPEN]

entfernt, da veraltet
  • Zuletzt bearbeitet von DaLeecher am Di, März 22, 2011 22:11, insgesamt einmal bearbeitet
 

DaLeecher

BeitragDi, März 22, 2011 18:08
Antworten mit Zitat
Benutzer-Profile anzeigen
Cool, habe gerade ein Beispiel gefunden, wie man einen oder mehrere Schüsse realisieren kann und werde mir das mal genauer anschauen und versuchen in mein Spiel einzubinden. Quelle: https://www.blitzforum.de/foru...ght=schuss

Xeres

Moderator

BeitragDi, März 22, 2011 18:10
Antworten mit Zitat
Benutzer-Profile anzeigen
Du lädst den Font in der Hauptschleife so ca. 60 mal die Sekunde, dass muss schief gehen.
Programme stürzen nie "so einfach" ab. Schalte den Debugger ein und gib neben Code auch die markierte Zeile & die Fehlermeldung an - das hilft den Leuten hier, dir zu helfen.
Win10 Prof.(x64)/Ubuntu 16.04|CPU 4x3Ghz (Intel i5-4590S)|RAM 8 GB|GeForce GTX 960
Wie man Fragen richtig stellt || "Es geht nicht" || Video-Tutorial: Sinus & Cosinus
T
HERE IS NO FAIR. THERE IS NO JUSTICE. THERE IS JUST ME. (Death, Discworld)

Midimaster

BeitragDi, März 22, 2011 19:49
Antworten mit Zitat
Benutzer-Profile anzeigen
Respekt!

Das sieht schon sehr gut aus so... Nun musst Du aber die TYPES anders verwenden lernen.

Ein einmal erstelltes Element lebt in einer Art Liste, die sich mit FOR/EACH ansprechen lässt. Dabei ist der Variablen-Name den es bei der NEW-Erstellung hatte nebensächlich:

BlitzBasic: [AUSKLAPPEN]
Ball1.TBall=New TBall
Ball1\X=123

For Local locBall.TBall Each TBall
Print locBall\X
Next


Damit kannst Du nun jederzeit neue Elemente hinzufügen, die bei der Erstellung jedesmal wieder Ball1 heißen dürfen und sich doch alle unter locBall wiederfinden lassen. Ideal für Schüsse oder Bälle.

In der Liste leben die Schüsse solange bis sie sich selbst töten, z.b. wenn sie auf einen Gegner treffen oder den Bildschirm verlassen haben. Wichtig dabei ist dass das Entfernen aus der Liste möglichst in einer der letzten Zeile vor dem NEXT steht. Oft passiert es, dass man noch eine Objekt-Eigenschaft abfragt, obwohl das Objekt gerade gelöscht wurde:

falsch:
BlitzBasic: [AUSKLAPPEN]
For s.schuss= Each schuss
Oval s\x,s\y,5,5,1s\y=s\y - 3
If s\y < 1 Then Delete s
If s\x < 1 Then Delete s
Next


richtig:
BlitzBasic: [AUSKLAPPEN]

For s.schuss= Each schuss
Local ToeteEs=0
Oval s\x,s\y,5,5,1s\y=s\y - 3
If s\y < 1 Then ToeteEs=1
If s\x < 1 Then ToeteEs=1

If ToeteEs=1 Then
Delete s
EndIf
Next
  • Zuletzt bearbeitet von Midimaster am Mi, März 23, 2011 9:31, insgesamt einmal bearbeitet
 

DaLeecher

BeitragDi, März 22, 2011 20:15
Antworten mit Zitat
Benutzer-Profile anzeigen
@Xeres:
Danke für die Fehlerquelle! Leider zeigt der Debugger nur kurz die Zeile an, in der ein Fehler ist - ohne Zeilennummer oder so... und wenn ich das Prgramm bzw die Debuggermeldung beende, springt der Cursor leider auch nicht an der entsprechenden Stelle bzw Zeile - ist echt etwas nervig.

Ich habe danke des guten Beispiels wie man Schüsse programmiert, versucht diese einzubinden und versucht, wenn der Ball getroffen wird, dass dann zwei neue Bälle erscheinen! Irgendwie scheine ich was falsch zu machen, weil die neuen Bälle werden nicht dargestellt - scheinen aber wohl unsichtbar vorhanden zu sein, weil man merkt bzw sieht, dass Kollisionen mit irgendetwas stattfinden.

Da ich leider was BlitzBasic angeht recht neu bin, wäre es schön, wenn ihr mir Infos geben könntet ob die Art, wie ich das ganze bisher programmiere, so okay ist oder ob man das besser grundlegend anders programmiern sollte! So langsam fällt es auch schwer den Überblick über den ganzen Programmiercode zu behalten. Für jede Hilfe und Tipp wäre ich sehr dankbar!

Bis jetzt war es kein leichter Weg für mich... aber ich bin froh, dass ich schon so weit bin! Auch wenn mein Spiel noch nicht so wirklich das tut was es soll Laughing

Code: [AUSKLAPPEN]

entfernt, da veraltet
  • Zuletzt bearbeitet von DaLeecher am Di, März 22, 2011 22:13, insgesamt einmal bearbeitet

Sir Gauss der III

BeitragDi, März 22, 2011 20:40
Antworten mit Zitat
Benutzer-Profile anzeigen
hm, du könntest bestimmte Teile in eine Function auslagern.

Das ist nichts anderes wie ein Programmblock, der auserhalb deines Hauptprogramms steht und eine eigene bezeichnung hat. Ähnlich wie ein Befehl.

Code: [AUSKLAPPEN]
Function Name()
   
   Code
   
End Function


den darin enthaltenen Code kannst du nun durch einfaches einsetzten des Functionsname, in dem Fall "name()" in dein Hauptprogramm einfügen. bsp:

Code: [AUSKLAPPEN]

Graphics 800, 600, 32

; Double Buffer um flackern zu verhindern

SetBuffer BackBuffer()
...........

; Hauptschleife

Repeat
   Cls
   
    ; Jeden Ball bewegen und darstellen

    For Ball1.TBall = Each TBall
        Color 255, 255, 255
        ......

    ; Jeden Ball auf Kollision mit Spieler überprüfen
   
;Functionscode im HP aufrufen
   ballcolli()

   ......

    Flip

Until KeyDown(1)   ; Escape



;Die Function mit darin enthaltenem Code

Function ballcolli()
; Jeden Ball auf Kollision mit Spieler überprüfen
   
   For Ball1.TBall = Each TBall   
        If RectsOverlap(Ball1\posX, Ball1\posY, Ball1\size, Ball1\size,    Player1\posX, Player1\posY, playerWidth, playerHeight)   
          Player1\lives = Player1\lives -1
         Player1\posX = 400
         Player1\posY = 500
         Ball1\posX = 400
         Ball1\posY = 100   
       EndIf
    Next
   
End Function



Das wäre zumindest mal ein Weg, der recht simpel ist.


Edit: hatte ich vergessen: wenn du Functionen einsetzt musst du deine Variablen und neu erstellten Typen (das erste mal!) als Globale definieren:

Code: [AUSKLAPPEN]

Global Player1.TPlayer = New TPlayer
Player1\posX = 400
Player1\posY = 500
player1\speed = 4
Player1\lives = 3

....

Global playerWidth = 60
Global playerHeight = 100


am besten definierst du gleich am Beginn deines Programmes alle Variablen die du verwendest als Global. (wenn eine Variable nur innerhalb einer Function gelten soll wird sie zu beginn als Local definiert.
 

DaLeecher

BeitragDi, März 22, 2011 22:10
Antworten mit Zitat
Benutzer-Profile anzeigen
@MidiMaster
Danke! Ich habe mal versucht dein Beispiel anzuwenden und zu verstehen. Ich verstehe noch nicht so ganz, warum oder wofür der : zwischen localBall und TBall steht. Den Befehl EachIn versteht mein BlitzBasic nicht. Dein Beispiel kann ich nicht ausführen. Die Sache mit dem ToeteEs ist auch eingebaut, jedoch funktioniert das ganze noch immer nicht.

Code: [AUSKLAPPEN]

Ball1.TBall=New TBall
Ball1\X=123

For Local locBall:TBall EachIn TBall
     Print locBall\X
Next




@Sir Gauss der III
Vielen Dank, die Sache mit Function ist ja echt super! Hat zwar nicht alles sofort geklappt aber habe dann doch noch den Dreh rausbekommen. Für mich ist der Programmiercode jetzt etwas übersichtlicher... Für Kritik und Verbesserungen bin ich sehr dankbar!



@alle
Leider besteht nach wie vor noch das Problem, dass wenn ein Ball getroffen wird, die neuen nicht angezeigt werden und sich das ganze Spiel merkwürdig verhällt. Ich Kopf raucht inzwischen und ich habe noch keine Idee, was ich falsch mache.

Code: [AUSKLAPPEN]

entfernt, da veraltet
  • Zuletzt bearbeitet von DaLeecher am Di, März 22, 2011 22:53, insgesamt einmal bearbeitet

Sir Gauss der III

BeitragDi, März 22, 2011 22:24
Antworten mit Zitat
Benutzer-Profile anzeigen
habe etwas im Code gewurstelt und dabei auch den Fehler entdeckt.


Zwei Sachen zur Übersichtlichkeit:
- verwende um Einrücken den Taubulator, (weiß nicht ob das nur am Forum hängt
- vermeide die Befehlstrennung ":", lieber die Befehle in eine neue Zeile


Der Fehler liegt in bei der Erstellung der neuen, kleineren Bälle. Dort fehlen einige Angaben.
Tipp:
Code: [AUSKLAPPEN]
sizealt=Ball1\size

If sizealt>=50 Then
   Ball1.TBall = New TBall
   ...
   Ball1\size = sizealt/2
   
   Ball1.TBall = New TBall
   ...
   Ball1\size = sizealt/2
EndIf

Erstellt Pro großen Ball zuerst 2 kleine, und für die zwei nochmal jeweils zwei ganz kleine, danach aber nichts mehr.

Edit: Und noch eine kleinigkeit. manchmal fragst du ein Type ab, obwohl es gelöscht wurde. Am besten erstellst du noch ein Field Leben für Ball1 und Tshoot. dem gibst du dann bei Kollision den Wert 1, und erst in einer extraschleife (für jeden Type eine eigene) löscht du dann alle Objekte deren Leben=1 ist.
 

DaLeecher

BeitragDi, März 22, 2011 22:52
Antworten mit Zitat
Benutzer-Profile anzeigen
Danke für den Tip! Bin nun ein kleines Stück weiter... Auch wenn das ganze noch immer sehr chaotisch bzw kaputt wirkt. Ich muß mir einfallen lassen, wie beim dürcken der SPACE-Taste nur ein Schuß abgegeben wird und nicht x-viele, wie es im moment leider noch der Fall ist. Auch muß ich schauen, wie ich die alten (getroffenen) Bälle entferne - mit Delete geht es hier bei mir so nicht.

Bin zumindest mit eurer HIlfe schon ein ganzes Stück weitergekommen und mein Kopf raucht jetzt erstmal Laughing

Code: [AUSKLAPPEN]


; Version vom 22.03.2011  21:50

Graphics 800, 600, 32

; Double Buffer um flackern zu verhindern

SetBuffer BackBuffer()

; Felder für TPlayer, TBall und TShoot

Type TPlayer
Field posX
Field posY
Field speed
Field lives
End Type

Type TBall
Field posX
Field posY
Field speedX
Field speedY
Field directionX
Field directionY
Field size
End Type

Type TShoot
Field posX
Field posY
Field speed
Field weapon
End Type

; Neue Objekte erstellen und Werte zuweisen

Global Player1.TPlayer = New TPlayer
Player1\posX = 400
Player1\posY = 500
player1\speed = 4
Player1\lives = 3

Global Ball1.TBall = New TBall
Ball1\posX = 400
Ball1\posY = 100
Ball1\speedX = 2
Ball1\speedY = 2
Ball1\directionX = 2
Ball1\directionY = 4
Ball1\size = 100

Global playerWidth = 60
Global playerHeight = 100

Global meinFont = LoadFont("Arial", 36)

; ---------------------------------------------------------------

Repeat
    Cls
   
    ; Jeden Ball bewegen und darstellen
   
    MoveAndDrawBalls()
   
    ; Bewege Spieler und darstellen
   
    MoveAndDrawPlayers()
   
    ; Schuss hinzufügen
   
    If KeyDown(57) ; SPACE
        Shoot1.TShoot = New TShoot
        Shoot1\posX = Player1\posX
        Shoot1\posY = Player1\posY
    EndIf
   
    ; Jeden Schuss darstellen
   
    MoveAndDrawShoots()
   
    ; Jeden Ball auf Kollision mit Schuss überprüfen
   
    CheckShootCollisionWithBalls()
   
    ; Jeden Ball auf Kollision mit Spieler überprüfen
   
    CheckPlayerCollisionWithBalls()
   
    ; Textausgabe
   
    ShowOutput()
   
    Flip
   
Until KeyDown(1)   ; Escape

; ---------------------------------------------------------------

Function MoveAndDrawBalls()

   ;    For Local locBall:TBall Eachin TBall
   
   For Ball1.TBall = Each TBall
       Ball1\posX = Ball1\posX + Ball1\directionX
       Ball1\posY = Ball1\posY + Ball1\directionY
      
       If Ball1\posX > 800-Ball1\size Or Ball1\posX < 0
           Ball1\directionX = -Ball1\directionX
       EndIf
      
       If Ball1\posY > 600-Ball1\size Or Ball1\posY < 0
           Ball1\directionY = -Ball1\directionY
       EndIf
      
       Color 255, 255, 255
       Oval Ball1\posX, Ball1\posY, Ball1\size, Ball1\size, 1
   Next

End Function

; ---------------------------------------------------------------

Function MoveAndDrawPlayers()

   If KeyDown(203)    ; Cursor Left
       Player1\posX = Player1\posX - Player1\speed
       If Player1\posX < 0
         Player1\posX = 0
      EndIf
   EndIf
   
   If KeyDown(205)    ; Cursor Right
       Player1\posX = Player1\posX + Player1\speed
       If Player1\posX > 800-playerWidth
         Player1\posX = 800-playerWidth
      EndIf
   EndIf
   
   ; Zeichne Spieler
   
   Color 0, 0, 255
   Rect Player1\posX, player1\posY, playerWidth, playerHeight, 1

End Function

; ---------------------------------------------------------------

Function MoveAndDrawShoots()

   For Shoot1.TShoot = Each TShoot
   
       Local ToeteEs = 0
      
       Color 255, 0, 0
       Rect Shoot1\posX, Shoot1\posY, 10, 40, 1
       Shoot1\speed = 3 
       Shoot1\posY = Shoot1\posY - Shoot1\speed
      
       ; Schuss nicht mehr sichtbar und entfernen
      
      If Shoot1\posY < 1 Then ToeteEs = 1
       
        If ToeteEs = 1
            Delete Shoot1
        EndIf
       
    Next
   
End Function
   
; ---------------------------------------------------------------
   
Function CheckPlayerCollisionWithBalls()
   
    For Ball1.TBall = Each TBall   
        If RectsOverlap(Ball1\posX, Ball1\posY, Ball1\size, Ball1\size,    Player1\posX, Player1\posY, playerWidth, playerHeight)   
            Player1\lives = Player1\lives -1
            Player1\posX = 400
            Player1\posY = 500
            Ball1\posX = 400
            Ball1\posY = 100   
        EndIf
    Next
   
End Function
   
; ---------------------------------------------------------------
   
Function CheckShootCollisionWithBalls()
   
    For Ball1.TBall = Each TBall
        For Shoot1.TShoot = Each TShoot
            If RectsOverlap(Ball1\posX, Ball1\posY, Ball1\size, Ball1\size,    Shoot1\posX, Shoot1\posY, 10, 40)   
               
                ; Entferne getroffenen Ball und Schuss
               
                oldPosX = Ball1\posX
                oldPosY = Ball1\posY
               
                Delete Shoot1
               
                ; Erstelle zwei neue Bälle
               
                sizealt=Ball1\size
               
                If sizealt>=50 Then
                    Ball1.TBall = New TBall
                    Ball1\posX = oldPosX
                    Ball1\posY = oldPosY
                    Ball1\directionX = 2
                    Ball1\directionY = 4
                    Ball1\size = sizealt / 2
                   
                    Ball1.TBall = New TBall
                    Ball1\posX = oldPosX
                    Ball1\posY = oldPosY
                    Ball1\directionX = -2
                    Ball1\directionY = 4
                    Ball1\size = sizealt / 2
                EndIf     
               
            EndIf
        Next
    Next
   
End Function
   
; ---------------------------------------------------------------
   
Function ShowOutput()
   
    Color 255,255,255
    SetFont meinFont
    Text 20,20, "Lives: " + Str(Player1\lives)
   
End Function


Zitat:

Am besten erstellst du noch ein Field Leben für Ball1 und Tshoot. dem gibst du dann bei Kollision den Wert 1, und erst in einer extraschleife (für jeden Type eine eigene) löscht du dann alle Objekte deren Leben=1 ist.


Das mit dem Leben hab ich noch nicht so ganz verstanden was du meinst. Werde gleich erstmal eine Pause machen, evtl. verstehe ich es danach ^^

Sir Gauss der III

BeitragDi, März 22, 2011 23:28
Antworten mit Zitat
Benutzer-Profile anzeigen
Das mit dem Leben:

Du fragst in deiner Collisionsschleife ab ob ein ball mit Schuss1, schuss2, schuss3.... zusammentrift. berührt er nun schuss1, so wird er gelöscht. Die Collision wird aber weiter für schuss2, schuss3 ... geprüft -> es kommt zu einem Programmfehler.

Es ist daher besser, in der Prüfschleife erst mal zu vermerken, das der Schuss und der ball gelöscht werden sollen. Weitere Prüfungen sind nun möglich, denn beide Objekte existieren noch.

in einer neuen Schleife für TBall1 wird nun lediglich jeder ball gelöscht der einen Vermerk "löschen" in seiner lebensvariable hat.
Das selbe für die Schüsse. Außer dem Prüfvorgang der Lebensvariable (hier "Ball1\tot") und dem löschvorgang findet in den Schleifen keine Abfrage mehr statt. somit umgehst du oben genannten Fehler.

Code: [AUSKLAPPEN]
   For Shoot1.TShoot = Each TShoot
   
      For Ball1.TBall = Each TBall
      
         If RectsOverlap(Ball1\posX, Ball1\posY, Ball1\size, Ball1\size,   Shoot1\posX, Shoot1\posY, 10, 40)   
         
         ; Entferne getroffenen Ball und Schuss
         
         oldPosX = Ball1\posX
         oldPosY = Ball1\posY
         gralt=Ball1\size
         Ball1\tot=1
         Shoot1\tot=1
         .........
         EndIf
      Next
   Next

;Ball1 und tshoot in der ersten Schleife nicht löschen, sondern in den zwei neuen:

   For Shoot1.TShoot = Each TShoot
      If Shoot1\tot=1 Then Delete Shoot1
   Next
   
   For Ball1.TBall = Each TBall
         
      If Ball1\tot=1 Then Delete Ball1
   Next


für die Schüsse:
* vermerke, wie viele Schüsse aktuell abgefeuert wurden (z.B. in Schussvorhanden) -> bei zuviel existierenden können keine neuen abgefeuert werden.

* setze einen Zähler, den du nach jedem Feuern hoch setzt (z.B. laden=100) und dann in jedem
schleifendurchgang weniger werden lässt. nur wenn laden=0 dann schießen lassen.

*schau dir dazu mal createtimer und waittimer an. Damit begrenzt du die bildschirmaufbaurate auf ein bestimmtes Maß.

Edit:
*weitere Möglichkeit wäre die Zeit abzufragen und bei einem Schuss zwischen zu speichern. erst wenn die Zeit größer als die gewollte wartezeit ist, kann ein neuer schuss erstellt werden. Schau hierzu Millisecs (dafür am besten) oder currenttime(nicht so gut dafür) an

Midimaster

BeitragMi, März 23, 2011 9:39
Antworten mit Zitat
Benutzer-Profile anzeigen
Embarassed Sorry, da hab ich mal wieder BMax-Code und BB-Code durcheinandergebracht: Es muss natürlich kein Doppelpunkt sondern ein Punkt sein Ball1.TBall und auch das EachIn heißt natürlich Each.


Das "Deleten" von Objekten aus einer For/Each-Schleife musst du mit äußersten Vorsicht durchführen.

Du kannst sie schon direkt in den For/Each-Schleifen töten aber achte immer auf den Grundsatz es erst unmittelbar vor dem NEXT zu tun:
BlitzBasic: [AUSKLAPPEN]
Function CheckShootCollisionWithBalls()
Local ToeteEs%=0
For Ball1.TBall = Each TBall
For Shoot1.TShoot = Each TShoot
ToeteEs=0
If RectsOverlap(Ball1\posX, Ball1\posY, Ball1\size, Ball1\size, Shoot1\posX, Shoot1\posY, 10, 40)


; Erstelle zwei neue Bälle
sizealt=Ball1\size
If sizealt>=50 Then
oldPosX = Ball1\posX
oldPosY = Ball1\posY
; Erstelle neue Bälle
....
EndIf

Delete Shoot1
Exit

EndIf
Next
If ToeteEs=1 Then
Delete Ball1
EndIf
Next
End Function


Hier siehtst Du, wie dein DELETE SHOOT1 an das Ende der Schleife gewandert ist. Das nachfolgende EXIT sorgt dafür, dass die anderen Schüsse bei diesem Ball gar nicht mehr kontrolliert werden müssen. Der Ball ist eh schon getroffen.

Dadurch, dass jetzt die Variable ToeteEs auf 1 gesetzt ist, kannst Du auch den Ball DELETEN, aber eben erst am Ende SEINER Schleife.

Noch ein Tipp zu der Erstellung der zwei neuen Bälle:

der Name Ball1 steht ja gerade für ein Element der äußeren FOR/EACH-Schleife. Man sagt auch er "referenziert" das Element. Diesen Namen nun bei der Erstellung weiterer Bälle zu verwenden ist schon erlaubt, aber Du verlierst damit die Referenz zum ursprünglichen Ball. Ein Delete am Ende der äußeren Schliefe würde scheitern und stattdessen den zweiten der neuen Bälle zerstören. Mach es besser so:

BlitzBasic: [AUSKLAPPEN]
                ; Erstelle zwei neue Bälle  

sizealt=Ball1\size

If sizealt>=50 Then
oldPosX = Ball1\posX
oldPosY = Ball1\posY

BallNeu.TBall = New TBall
BallNeu\posX = oldPosX
BallNeu\posY = oldPosY
BallNeu\directionX = 2
BallNeu\directionY = 4
BallNeu\size = sizealt / 2

BallNeu.TBall = New TBall
BallNeu\posX = oldPosX
BallNeu\posY = oldPosY
BallNeu\directionX = -2
BallNeu\directionY = 4
BallNeu\size = sizealt / 2
EndIf


....oder noch schöner mit dem Befehl Function, den SirGauss vorgeschlagen hat:
BlitzBasic: [AUSKLAPPEN]
Function CheckShootCollisionWithBalls()
Local ToeteEs%, X%, Y%, S%

For Ball.TBall = Each TBall
X = Ball\posX
Y = Ball\posY
S = Ball\size
For Shoot.TShoot = Each TShoot
ToeteEs=0
If RectsOverlap(X, Y, S, S, Shoot\posX, Shoot\posY, 10, 40)

; Erstelle zwei neue Bälle

If sizealt>=50 Then
NeuerBall X, Y, S/2, 2
NeuerBall X, Y, S/2, -2
EndIf

Delete Shoot
Exit

EndIf
Next

If ToeteEs=1 Then
Delete Ball
EndIf
Next
End Function


Function NeuerBall(X%,Y%,S%,D%)
Neu.TBall = New TBall
Neu\posX = X
Neu\posY = Y
Neu\directionX = D
Neu\directionY = 4
Neu\size = S
End Function


In diesem Beispiel siehst Du auch, dass ich immer gerne häufig benötigete Werte wie wie Ball1\X in der oberen Funktion in eine kurznamige lokale Variable X umwandle und wie sich dann die Lesbarkeit erhöht.
Außerdem ist es verwirrend die Bälle Ball1 zu nennen. Es handelt sich ja nicht nur um den ersten Ball. Also genügt Ball!
So wird aus:

BlitzBasic: [AUSKLAPPEN]
If RectsOverlap(Ball1\posX, Ball1\posY, Ball1\size, Ball1\size,    Shoot1\posX, Shoot1\posY, 10, 40)
....
NeuerBall Ball1\posX, Ball1\posY, Ball1\size/2, 2

...dann...
BlitzBasic: [AUSKLAPPEN]
If RectsOverlap(X, Y, S, S, Shoot\posX, Shoot\posY, 10, 40)
....
NeuerBall X, Y, S/2, 2

...aber das ist natürlich Dir überlassen.
 

DaLeecher

BeitragMi, März 23, 2011 22:05
Antworten mit Zitat
Benutzer-Profile anzeigen
@Sir Gauss der III

Zitat:

Du fragst in deiner Collisionsschleife ab ob ein ball mit Schuss1, schuss2, schuss3.... zusammentrift. berührt er nun schuss1, so wird er gelöscht. Die Collision wird aber weiter für schuss2, schuss3 ... geprüft -> es kommt zu einem Programmfehler.

Es ist daher besser, in der Prüfschleife erst mal zu vermerken, das der Schuss und der ball gelöscht werden sollen. Weitere Prüfungen sind nun möglich, denn beide Objekte existieren noch.


Vielen Dank für die gut verständliche bzw nachvollziehbare Erklärung und Hilfe mit Programmiercode! Also wenn ich das jetzt richtig verstehe, sollte ich mir am besten als Faustregel merken, zu entfernende Objekte IMMER in einem seperaten loop zu entfernen um Programmierfehler zu vermeiden und die zu entfernenden Objekte vorher einfach nur fürs löschen vormerken, ja?

Zitat:

in einer neuen Schleife für TBall1 wird nun lediglich jeder ball gelöscht der einen Vermerk "löschen" in seiner lebensvariable hat.
Das selbe für die Schüsse. Außer dem Prüfvorgang der Lebensvariable (hier "Ball1\tot") und dem löschvorgang findet in den Schleifen keine Abfrage mehr statt. somit umgehst du oben genannten Fehler.


Echt super verständlich und selbst für einen Anfänger wie mich, sehr gut nachvollziehbar! Habe es Danke deiner Hilfe und Beispiel umgesetzt. Es funktioniert einwandfrei! Danke! Smile

Bezüglich deinen Tips für Schüsse und Zeittähler bin ich noch dabei, mich in dieser Materie etwas einzulesen / einzuarbeiten und zu verstehen um es für mein Spiel umsetzen zu können. Muß noch ein klein wenig Brainstorming betreiben ^^



@Midimaster
Hehe, kein Problem... muß dich doch deswegen nicht entschuldigen Wink

Zitat:

Das "Deleten" von Objekten aus einer For/Each-Schleife musst du mit äußersten Vorsicht durchführen.


Ja, ich denke ich werde es so handhaben wie Sir Gauss schon geraten hat. Am besten Objekte immer nach erfolgter Prüfung zum löschen markieren und in einer seperaten Schleife löschen - denke dass ist genau dass, was du auch meinst oder?

Zitat:

Du kannst sie schon direkt in den For/Each-Schleifen töten aber achte immer auf den Grundsatz es erst unmittelbar vor dem NEXT zu tun:


Darf ich mal vorsichtig fragen, welche Vor- und Nachteile deine Variante zu der von Sir Gauss hat? Außer dass bei deiner Variante weniger Durchläufe für einen möglichen Treffer nötig sind, sofern ich das richtig sehe und verstehe? Hat dieses Exit irgendwelche Vor/Nachteile oder dass ich dabei etwas zu beachten habe?

Momentan benutze ich in meine Spiel folgenden Aufbau:
Code: [AUSKLAPPEN]

    For Shoot1.TShoot = Each TShoot
        For Ball1.TBall = Each TBall

anstatt wie in deinem Beispiel:
Code: [AUSKLAPPEN]

    For Ball1.TBall = Each TBall
        For Shoot1.TShoot = Each TShoot

Die Schleifen sind vertauscht... Ist dieses egal oder gibt es hier irgendetwas zu beachten oder so? Bin da gerade ein klein wenig irritiert.

Zitat:

der Name Ball1 steht ja gerade für ein Element der äußeren FOR/EACH-Schleife. Man sagt auch er "referenziert" das Element. Diesen Namen nun bei der Erstellung weiterer Bälle zu verwenden ist schon erlaubt, aber Du verlierst damit die Referenz zum ursprünglichen Ball. Ein Delete am Ende der äußeren Schliefe würde scheitern und stattdessen den zweiten der neuen Bälle zerstören. Mach es besser so:


Das muß ich mir nochmal mehrmals durchlesen und deinen source mit meinem aktuellen vergleichen um evtl. genauer zu verstehen was gemeint ist. Ich denke, wenn ich mir das noch 3 oder 4 mal durchlese und genauer anschaue, wird der Groschen bei mir gefallen sein.

Zitat:

In diesem Beispiel siehst Du auch, dass ich immer gerne häufig benötigete Werte wie wie Ball1\X in der oberen Funktion in eine kurznamige lokale Variable X umwandle und wie sich dann die Lesbarkeit erhöht.


Ja das sieht auf jedenfalll Übersichtlicher aus... Habe versucht das an anderer Stelle im Source einzubinden bzw so umzusetzen... Hatte allerdings erhebliche Probleme, das sich Sachen plötzlich nicht mehr bewegt haben usw! Bin erst nach längerem Kopfzerbrechen dahintergestiegen warum es nicht so funktionierte wie es sollte. Wenn ich z.b. x = Y nehmen würde, so würde zwar x den aktuellen Wert von Y enthalten, jedoch nicht die eigentliche Balls\posX Variable. Ich denke wenn man aufpasst, ist das ein super übersichtliches system... Für mich jedoch als Anfänger ist das noch sehr fehleranfällig. Liegt aber bestimmt an mir, da ich irgendwas nicht beachtet habe bzw falsch gemacht habe. Werde mir das System aber im Hinterkopf behalten, da es wirklich sehr übersichtlich wirkt. Danke für den Tip!



So, werde nun versuchen das eine oder andere von euren Tips umzusetzen, damit es wieder etwas weiter vorwärts geht Smile Vielen Dank an dieser Stelle!

Neue Antwort erstellen


Übersicht BlitzBasic Beginners-Corner

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group