Seite 1 von 3

Prinzipieller Aufbau von Pong

Verfasst: 25.11.2007 20:17
von Zero_Cool
Hallo Zusammen,

Leider gehöre ich nicht zu den Profis im Umgang mit Pure Basic. Meine stärken liegen wohl eher im grafischen Bereich, dennoch wollte ich mich mal zum prinzipiellen Aufbau eines Spieles erkundigen.

Gehen wir davon aus, dass ich Pong nachprogrammieren möchte, eigentlich ein sehr „einfaches“ Spiel wenn man es nicht selber schreiben muss.

Im Grunde gehören nur ein Zähler, zwei Platten, ein Ball, zwei Wände und 2 Tore dazu.

http://www.gungfu.de/facts/uploads/pong.jpg

Wie bereits erwähnt, habe ich so was zuvor noch nie gemacht. Ich denke aber ein solches Projekt sollte auch für einen Anfänger durchaus machbar sein. (mit ein wenig Starthilfe :mrgreen: )

Welche grundsätzlichen Befehle benötige ich für das Programm? Soweit ich mich erkundigen konnte, benötige ich den Befehl „gosub“ für die Bewegung der meiner Platte. Da gibt es aber noch reichlich andere Funktionen die ich benötige, abprallen von der Wand, KI gesteuerte zweite Platte und so weiter… die ich nicht kenne.

Kann mir jemand einen Tipp geben welche Befehle respektive Zusammenhänge ich mir als erstes ansehen sollte?

Vielen Dank und ein schöner Abend,

Verfasst: 25.11.2007 20:54
von NicTheQuick
Ich denke zuerst solltest du dich in folgender Reihenfolge mit den Dingen
beschäftigen:
- Variablen, Typen, Operationen (+, -, *, /), Debug
- If
- Schleifen (Repeat, While, For-Next)
- OpenWindow(), OpenWindowedScreen(), OpenScreen(), KeyboardPushed()
- StartDrawing(), Line(), Plot(), Circle(), DrawText(), FlipBuffers()
- CreateSprite(), LoadSprite(), DrawSprite()
- MouseX(), MouseY()
- SpriteCollision(), SpritePixelCollision()
- Procedure

Weiteres folgt automatisch.

Also einfach mal von oben nach unten die Liste durchgehen und die
Beispiele in der Hilfe anschauen. Dadurch wirst du nach und nach
verstehen, wie alles zusammenhängt und funktioniert. Dabei wirst du dann
auch eigene Ideen entwickeln.
Denn beim Erlernen einer Programmiersprache muss man immer selbst
experimentieren. Eine fertige Anleitung zu Problemen wirst du
wahrscheinlich nie finden, sondern musst sie in deinem Kopf selbst
entwickeln und ausprobieren.
Der Debugger wird dir helfen alles zu verstehen, wenn du ihn richtig
einsetzt.

Verfasst: 26.11.2007 01:09
von Zero_Cool
Hallo,

Danke für die Antwort, genau so habe ich mir das vorgestellt. Die meisten Befehl habe ich zum Glück schon gekannt, daher bin ich innerhalb der kurzen Zeit, eigentlich schon ziemlich weit gekommen. (für meine bescheidenen Fähigkeiten natürlich :mrgreen:)

Code: Alles auswählen

; Initialisation

If OpenWindow(0, 0, 0, 800, 600, "Pong", #PB_Window_ScreenCentered | #PB_Window_BorderLess ) And InitKeyboard() And InitSprite()

; Fenster öffnen

If OpenWindowedScreen(WindowID(0), 0, 0, 800, 600, 0, 0, 0)

; Konstante
x = 250

; Endlose Schleife

Repeat    

ExamineKeyboard() ; Aktualisiert den Tastatur-Status
FlipBuffers()
ClearScreen(RGB(0, 0, 0))
LoadFont(0, "Verdana", 30) 

; Inhalt

CreateSprite(0, 20, 100)
If StartDrawing(SpriteOutput(0))
Box(0, 0, 20, 100, $FFFFFF)
StopDrawing()
EndIf

If KeyboardPushed(#PB_Key_Up)
x+3
EndIf

If KeyboardPushed(#PB_Key_Down)
x-3
EndIf

DisplaySprite(0, 0, x)

StartDrawing(ScreenOutput())
DrawingFont(FontID(0)) 
DrawingMode(#PB_2DDrawing_Transparent)
DrawText(400,300,"Pong",$FFFFFF) 
StopDrawing()

Until KeyboardReleased(#PB_Key_Escape)

EndIf
EndIf
Stimmt dieser Ansatz in den Grundzügen? Nur die Sache mit der vom Computer gesteuerten zweiten Platte (der Gegner) ist mir noch nicht so ganz klar?

Gute nacht, gruss Phil

Verfasst: 26.11.2007 09:17
von NicTheQuick
Du hast noch ein paar kleiner Fehler drin. Zum Beispiel erstellst du bei jedem
Schleifendurchlauf das Sprite neu und lädst die Schriftart neu. Das darf
natürlich nicht sein.
Außerdem vergisst du, die WindowEvents abzuarbeiten. Auch wenn du sie
nicht brauchst, musst du 'WindowEvent()' aufrufen, bis es Null zurückgibt.
Sonst denkt Windows, dein Programm reagiert nicht mehr.

Hier also die verbesserte Version. Ich war so frei und hab noch eine
Begrenzung für den Schläger eingebaut.

Code: Alles auswählen

;- Initialisierung
Global width.l, height.l
width = 800
height = 600

If Not OpenWindow(0, 0, 0, width, height, "Pong", #PB_Window_ScreenCentered | #PB_Window_BorderLess)
  ;Konnte Fenster nicht öffnen
  End
EndIf

If Not (InitKeyboard() And InitSprite())
  ;Konnte DirectX nicht initialisieren
  End
EndIf

If Not OpenWindowedScreen(WindowID(0), 0, 0, width, height, 0, 0, 0)
  ;Konnte Screen nicht öffnen
  End
EndIf

If Not LoadFont(0, "Verdana", 30)
  ;Konnte Schrift nicht laden
  End
EndIf

If Not CreateSprite(0, 20, 100)
  ;Konnte Sprite nicht erstellen
  End
EndIf

If StartDrawing(SpriteOutput(0))
  Box(0, 0, 20, 100, $FFFFFF)
  StopDrawing()
EndIf

;- Hauptschleife

Define y.l = (height - 100) / 2 ;Position des Schlägers
Repeat   
  
  ExamineKeyboard() ; Aktualisiert den Tastatur-Status
  
  ClearScreen(RGB(0, 0, 0))
  
  ; Inhalt
  If KeyboardPushed(#PB_Key_Up)
    If y <= 0 ;wenn der Schläger oben ist
      y = 0
    Else
      y - 3
    EndIf
  EndIf
  
  If KeyboardPushed(#PB_Key_Down)
    If y => height - 100 ;wenn der Schläger unten ist
      y = height - 100
    Else
      y + 3
    EndIf
  EndIf
  
  DisplaySprite(0, 0, y)
  
  StartDrawing(ScreenOutput())
    DrawingFont(FontID(0))
    DrawingMode(#PB_2DDrawing_Transparent)
    DrawText(400, 300, "Pong", $FFFFFF)
  StopDrawing()
  
  FlipBuffers()
  
  ;Window-Events abarbeiten
  While WindowEvent() : Wend
Until KeyboardReleased(#PB_Key_Escape)

Verfasst: 26.11.2007 19:56
von lassma-asma
guck dir ma mein multipong an ... hab ich letzte week online gestellt ...

wenn du willst schreib mir doch ma ne pn , dann könnte ich dir jo den quellcode schicken ...
mfg lassma-asma

LINK : http://www.purearea.net/pb/showcase/sho ... 467274847b

Verfasst: 26.11.2007 20:46
von Zaphod
Und lass die Finger von gosub... gosub macht man nicht... ist wie Nase popeln und gleichzeitig Arsch kratzen während man furzt.
Programmgliederung macht man mit Prozeduren... gosub ist ein relikt aus einer Zeit, als Nase popeln und gleichzeitig Arsch kratzen während man furzt noch als hinnehmbares Verhalten galt.

Verfasst: 27.11.2007 00:39
von Zero_Cool
Abend,

Stimmt, das Problem hatte ich tatsächlich. Windows hat immer gemeldet, dass vom Programm keine Rückmeldung vorhanden ist.

Vielen Dank für den Angepassten Code und die Hilfe, der aktuelle Code sieht nun wie folgt aus, besser?

Code: Alles auswählen

;- Konstante 

width = 800 
height = 600 

;- Initialisation 

If Not OpenWindow(0, 0, 0, width, height, "Pong", #PB_Window_ScreenCentered) 
End 
EndIf 

If Not (InitKeyboard() And InitSprite()) 
End 
EndIf 

If Not OpenWindowedScreen(WindowID(0), 0, 0, width, height, 0, 0, 0) 
End 
EndIf 

;- Schriftart

If Not LoadFont(0, "OCR A Std", 80) 
End 
EndIf 

;-Sprites

If Not CreateSprite(0, 20, 100) 
End 
EndIf 

If StartDrawing(SpriteOutput(0)) 
Box(0, 0, 20, 100, $FFFFFF) 
StopDrawing() 
EndIf 

; Sprite Rechts

If Not CreateSprite(1, 20, 100) 
End 
EndIf 

If StartDrawing(SpriteOutput(1)) 
Box(0, 0, 20, 100, $FFFFFF) 
StopDrawing() 
EndIf 

; Sprite Oben

If Not CreateSprite(2, 800, 10) 
End 
EndIf 

If StartDrawing(SpriteOutput(2)) 
Box(0, 0, 800, 10, $FFFFFF) 
StopDrawing() 
EndIf 

; Sprite Unten

If Not CreateSprite(3, 800, 10) 
End 
EndIf 

If StartDrawing(SpriteOutput(3)) 
Box(0, 0, 800, 10, $FFFFFF) 
StopDrawing() 
EndIf 

; Sprite Mitte

If Not CreateSprite(4, 10, 560) 
End 
EndIf 

If StartDrawing(SpriteOutput(4)) 
Box(0, 0, 10, 600, $FFFFFF) 
StopDrawing() 
EndIf 

; Sprite Ball

If Not CreateSprite(5, 10, 10) 
End 
EndIf 

If StartDrawing(SpriteOutput(5)) 
Box(0, 0, 10, 10, $FFFFFF) 
StopDrawing() 
EndIf 

; Sprite Links (Goal)

If Not CreateSprite(6, 10, 560) 
End 
EndIf 

If StartDrawing(SpriteOutput(6)) 
Box(0, 0, 10, 560, $000000) 
StopDrawing() 
EndIf 

; Sprite Rechts (Goal)

If Not CreateSprite(7, 10, 560) 
End 
EndIf 

If StartDrawing(SpriteOutput(7)) 
Box(0, 0, 10, 560, $000000) 
StopDrawing() 
EndIf 

;- Endlose Schleife 

Define y = (height - 100) / 2
Repeat    
  
ExamineKeyboard() ; Aktualisiert den Tastatur-Status 
ClearScreen(RGB(0, 0, 0)) 
  
; Inhalt 
If KeyboardPushed(#PB_Key_Up) 
If y <= 20
y = 20 
Else 
y - 3 
EndIf 
EndIf 
  
If KeyboardPushed(#PB_Key_Down) 
If y => height - 120
y = height - 120 
Else 
y + 3 
EndIf 
EndIf 
  
DisplaySprite(0, 10, y) ; Spieler Links
DisplaySprite(1, 770, y) ; Spieler Rechts
DisplaySprite(2, 0, 10)  ; Sprite Oben
DisplaySprite(3, 0, 580) ; Sprite Unten
DisplaySprite(4, 395, 20) ; Sprite Mitte
DisplaySprite(5, 200, 50) ; Sprite Ball
DisplaySprite(6, 0, 20) ; Goal Links
DisplaySprite(7, 790, 20) ; Goal Rechts

;-Counter
StartDrawing(ScreenOutput()) 
DrawingFont(FontID(0)) 
DrawingMode(#PB_2DDrawing_Transparent) 
DrawText(310, 15, "0", $FFFFFF) 
StopDrawing() 

StartDrawing(ScreenOutput()) 
DrawingFont(FontID(0)) 
DrawingMode(#PB_2DDrawing_Transparent) 
DrawText(430, 15, "0", $FFFFFF) 
StopDrawing()
  
FlipBuffers() 
  
; Window-Events abarbeiten 

While WindowEvent()
Wend 

Until KeyboardReleased(#PB_Key_Escape) 
@ lassma-asma
Vielen Dank für das Angebot. Werde gerne zu einem späteren Zeitpunkt darauf zurückkomen. Ich möchte das Spiel mehr oder weniger selber schreiben und nicht kopieren! Multi Pong ist sowas wie mein Ziel, tolles Programm.

@ Zaphod
Ich werde nie mehr Nase popeln, gleichzeitig Arsch kratzen und furtzen! Danke :mrgreen:

Gerne würde ich die durchgezogenen Linien in Weiss (Rand und Netz), abwechselnd durch einen weissen dan durch einen schwarzen Block ersetzten. Wie im original Pong. Wie genau kriege ich das hin?

Bild

Desweitern frage ich mich, wie das genau mit den Winkeln klappt, ich meine der Ball prallt jeweils mit unterschiedlichen Winkeln an Wand und Schläger ab. Ich denke ich werde Standard-Mässig einen 45 Grad Winkel verwenden.

Eine Lösung für den Ki gesteuerten Schläger habe ich auch gefunden. Ich werde einfach die y Position des Balles ermitteln und den Computerschläger anweisen die Differenz zwischen Y-Ball und Y-Ki-Schläger möglichst gering zu halten.

Schöner Abend

Verfasst: 27.11.2007 11:13
von 50-Pfennig
Ich habe auch schon ein Pong programmiert...

Sieh die Bahnen des Balls als eine Gerade an, deren Steigung du berechnen kannst.
Da "Einfallswinkel=Ausfallswinkel" gilt, musst du für den Rückprall die orthogonalsteigung berechnen, und die Flugrichtung negieren.

Also:

m orthogonal=(-m normal)^-1

Also in PureBasic:

Code: Alles auswählen

m=Pow(-m, -1)
So hat es bei mir jedenfalls funktioniert... :wink:

Verfasst: 27.11.2007 15:38
von Kaeru Gaman
Zero_Cool hat geschrieben:Gerne würde ich die durchgezogenen Linien in Weiss (Rand und Netz), abwechselnd durch einen weissen dan durch einen schwarzen Block ersetzten. Wie im original Pong. Wie genau kriege ich das hin?
indem du das zeichnen der einzelnen box durch das zeichnen von mehreren boxen in einer schleife ersetzt...

z.B.:

Code: Alles auswählen

; Sprite Mitte

If Not CreateSprite(4, 10, 560) 
  End 
EndIf 

If StartDrawing(SpriteOutput(4)) 
  For n=0 to 600 Step 20
    Box(0, n-5, 10, 10, $FFFFFF) 
  Next
StopDrawing() 
EndIf 

Verfasst: 27.11.2007 20:34
von 50-Pfennig
Mir ist gerade bei meinen Geschichtshausaufgaben (ich weiß nicht, warum gerade dabei :lol: ) aufgefallen, dass ich einen Fehler gemacht habe, denn wenn man bei Abprallen die Orthogonalsteigung verwendet, ist der Winkel zwischen Einfallsgeraden und "Abprall"-Geraden immer 90°, was natürlich Blödsinn ist, es sei denn du verwendest immer einen 45° Winkel, denn dann stimmt es ja...

Im endeffekt muss es also heißen:

Code: Alles auswählen

m=-m
Ganz einfach, denn wenn man das Ergebnis mit -1 potenziert, erhält man den Kehrbruch, und das ist ja nicht erwünscht...Das heißt aus einer Steigung von 2 wird plötzlich -(1/2), und damit bricht man alle physikalischen gesetze... :lol:

Also, wenn dein Ball in einem Winkel von bsp. 60° auftrifft (Steigung also m~1.73) wird die Steigung zu m=-1.73^-1~-0.58. Daraus resultiert dann ein Winkel von genau 90°-60°=30°.... Also Einfallswinkel ist nicht gleich Ausfallswinkel...

Ich hoffe ich konnte das richtig erklären...Du musst dann natürlich noch die Richtung (also Werte verringern bzw. erhöhen) verändern, damit er in die andere Richtung abprallt... :mrgreen: