Ein Pong Spiel - Was kann ich am Code verbessern?

Übersicht BlitzBasic Beginners-Corner

Neue Antwort erstellen

GearTechDE

ehemals 'KillerJo96'

Betreff: Ein Pong Spiel - Was kann ich am Code verbessern?

BeitragMo, Okt 17, 2011 18:36
Antworten mit Zitat
Benutzer-Profile anzeigen
Hallo,

ich habe mich von Netzwerk momentan ein wenig zurückgezogen, da es mich in letzter Zeit ziemlich (auch schulig) belastet. Ich habe eigentlich noch nie ein Projekt so richtig spielbar gemacht, doch als ich heute von der Schule kam, braucht ich erstmal ne Pause und hab mich rangesetzt und ein Pong Spiel programmiert.
Ich suchte im Internet nur nach einer kleinen Anleitung wie man Cosinus und Sinus benutzt. Naja das war auch nicht wirklich schwer. Jetzt hab ich mein Spiel fertig und funktioniert bis jetzt fehlerfrei. Ich wollte jetzt einfach mal die wirklichen Cracks hier fragen, was man an diesem Code noch hätte besser machen können.

Hier der Code:

BlitzBasic: [AUSKLAPPEN]

Local GraphicsX = 320
Local GraphicsY = 480

AppTitle "Pong zu Zweit by GearTech"
Graphics GraphicsX,GraphicsY,32,2
SetBuffer BackBuffer()

Local FrameTimer = CreateTimer(60)

Global BallX = 155,BallY = 235,IsMoving% = 0
Global Winkel%,Speed#
Global Player1X# = 60,Player2X# = 200,Player1Score%,Player2Score%
Global RandLinks% = 0,RandRechts% = 320,RandOben% = 40,RandUnten% = 480

Repeat
Cls

DrawStatusPlusField()
DrawBall(BallX,BallY)

Collision()

Player1(Player1X)
Player2(Player2X)

If KeyDown(205) Then Player1X = Player1X + 3
If KeyDown(203) Then Player1X = Player1X - 3
If KeyDown(32) Then Player2X = Player2X + 3
If KeyDown(30) Then Player2X = Player2X - 3

If KeyHit(57) Then

StartBall()
BallX = 155
BallY = 235
IsMoving = 1

End If

If IsMoving = 1 Then

BallX = BallX + Cos(Winkel) * Speed
BallY = BallY + Sin(Winkel) * - Speed

End If

Flip
WaitTimer(FrameTimer)
Until KeyHit(1)
End

Function DrawStatusPlusField()

Color 255,0,0
Rect 0,RandOben,320,RandUnten - 40,0
Oval 130,210,60,60,0
Line 0,240,480,240
Color 255,255,255

Text 50,15,"Player 1 | " + Player1Score + " : " + Player2Score + " | Player 2"

Color 129,129,129
Text 20,220,"Player 2"
Text 235,245,"Player 1"
Color 255,255,255

End Function

Function DrawBall(PosX,PosY)

Color 0,255,0
Oval PosX,PosY,10,10,1
Color 255,255,255

End Function

Function Player1(PosX)

Color 255,140,0
Line PosX,460,PosX + 60,460
Color 255,255,255

End Function

Function Player2(PosX)

Color 255,140,0
Line PosX,60,PosX + 60,60
Color 255,255,255

End Function

Function StartBall()

Winkel = Rand(0,360)
Speed = Rand(1,5)

End Function

Function MoveBall()

BallX = BallX + Cos(Winkel) * Speed
BallY = BallY + Sin(Winkel) * - Speed

End Function

Function Collision()

;Spieler Kollision
If ( BallX > Player1X) And ( BallX < Player1X + 60) Then
If ( BallY > 455) Then

Winkel = 360 - Winkel

EndIf
EndIf

If ( BallX > Player2X) And ( BallX < Player2X + 60) Then
If ( BallY < 60) Then

Winkel = 360 - Winkel

EndIf
EndIf
;Spieler Kollision

;Rand Kollision
If (BallX < RandLinks Or BallX > RandRechts - 5) Then

Winkel = 180 - Winkel

End If

If (BallY > RandUnten) Then

IsMoving = 0
BallX = 155
BallY = 235
Player2Score = Player2Score + 1

End If

If (BallY < RandOben) Then

IsMoving = 0
BallX = 155
BallY = 235
Player1Score = Player1Score + 1

End If
;Rand Kollision

;Spieler Rand Kollision

If Player2X > 320 Then Player2X = 5
If Player2X + 60 < 1 Then Player2X = 260

If Player2X > 320 Then Player2X = 5
If Player2X + 60 < 1 Then Player2X = 260

;Spieler Rand Kollision
End Function


Ich hoffe ihr könnt mir ein paar Tipps geben.

Vielen Dank einfach schonmal im Voraus Wink
Mit freundlichen Grüßen: GearTechDE

Midimaster

BeitragMo, Okt 17, 2011 18:57
Antworten mit Zitat
Benutzer-Profile anzeigen
Zitat:
...jetzt einfach mal die wirklichen Cracks hier fragen...


und wer jetzt als erstes Anwort gilt als der ulitmative Mega-Angeber... Wink

Dann mach mal ich den Anfang:

1.
Eine Kurz-Anleitung auf F1 wäre wichtig. Noch ist ja der Code dabei und man kann "nachsehen" welche Scan-Codes du verwendest, aber...

2.
Etwas Sound würde auch nicht schaden....aber das geht unter BB glaub ich gar nicht, dass man den über DATA-Zeilen erzeugt... naja vielleicht später doch was externes über LoadSound() einbinden

3.
Wenn der Timer was bringen soll muss es FLIP 0 sein
Gewinner des BCC #53 mit "Gitarrist vs Fussballer" http://www.midimaster.de/downl...ssball.exe

aMul

Sieger des Minimalist Compo 01/13

BeitragMo, Okt 17, 2011 19:00
Antworten mit Zitat
Benutzer-Profile anzeigen
Zwei Sachen die mir aufgefallen sind:
1. Wenn der Ball hinter den Schläger kommt, dann bleibt er wackelnd hängen(Ich denke den "Fehler" hat schon jeder gesehen, der sich mal an Pong probiert hat Very Happy)
2. Der Ball kann zufällig im Winkel 0 oder 180 gestartet werden und bewegt sich dann nur waagerecht hin und her.

Ansonsten zum Code generell:
Für ein kleines Spiel finde ich die Struktur vernünftig. Du benutzt Funktionen in gutem Maß, deine Variablen haben beschreibende Namen, der Code ist übersichtlich.
Wenn du was größeres schreiben möchtest würde ich dir empfehlen auf Globalen zu verzichten soweit es geht. Was man in diesem Fall zum Beispiel tun kann ist einen Spieler-Type zu haben, und davon zwei Objekte zu erstellen, die dann immer an Funktionen mit übergeben werden. Die Spieler-Types könnten denn auch Fields haben in denen drin steht mit welchen Tasten sie kontrolliert werden, dann brauchst du dafür nicht immer eigene Abfragen schreiben. Das macht es dann auch sehr einfach neue Spieler hinzuzufügen(natürlich bei Pong nur begrenzt sinnvoll(mehrere Bälle vielleicht?), aber gilt ja auch generell).

Ansonsten könnte ich noch so Sachen bemeckern, wie dass du Englische und Deutsche Variablen-Namen vermischt, oder dass du bei Funktionen ohne Rückgabewert keine Klammern setzt. Aber das liegt wohl im Auge des Betrachters. Wink
Panic Pong - ultimate action mashup of Pong and Breakout <= aktives Spiele-Projekt, Downloads mit vielen bunten Farben!
advASCIIdraw - the advanced ASCII art program <= aktives nicht-Spiele-Projekt, must-have für ASCII/roguelike/dungeon-crawler fans!
Alter BB-Kram: ThroughTheAsteroidBelt - mit Quelltext! | RGB-Palette in 32²-Textur / Farbige Beleuchtung mit Dot3 | Stereoskopie in Blitz3D | Teleport-Animation Screensaver

GearTechDE

ehemals 'KillerJo96'

BeitragMo, Okt 17, 2011 19:05
Antworten mit Zitat
Benutzer-Profile anzeigen
Okey, danke... Wink

Ich werd sowieso noch etwas daran rumbasteln, da einige Kollisionen noch nicht so ganz sauber sind (glaube ich.) Muss das mal in Zeitlupe machen, dann kann ich genau sehen was Sache ist.

Aber danke für die Tipps. Very Happy
Mit freundlichen Grüßen: GearTechDE

Midimaster

BeitragMo, Okt 17, 2011 19:13
Antworten mit Zitat
Benutzer-Profile anzeigen
ab hier Korinthen-Kackerei:

4.
mehr CONST statt feste Werte im Programm

Beispiel:

BlitzBasic: [AUSKLAPPEN]
Graphics GraphicsX,GraphicsY,32,2
SetBuffer BackBuffer()
Const KEY_LEFT=205 , KEY_RIGHT=203 , ...
Const XADD=3 , SCHLAEGER_BREIT=60 , PLAYER_OFF_Y=25
.....

If KeyDown(KEY_LEFT) Then Player1X = Player1X + X_ADD

.....
;Spieler Kollision
If ( BallX > Player1X) And ( BallX < Player1X + SCHLAEGER_BREIT) Then
If ( BallY > GraphicsY-PLAYER_OFF_Y) Then

Winkel = 360 - Winkel

EndIf
EndIf


aber letzendlich so blöd nun auch wieder nicht. Ich geh ja sogar so weit (am Beispiel Farbe):

BlitzBasic: [AUSKLAPPEN]
Function DrawStatusPlusField()

SetColor ROT
Rect 0,RandOben,320,RandUnten - 40,0
Oval 130,210,60,60,0
Line 0,240,480,240
SetColor WEISS

Text 50,15,"Player 1 | " + Player1Score + " : " + Player2Score + " | Player 2"

SETCOLOR GRAU
Text 20,220,"Player 2"
Text 235,245,"Player 1"
SetColor WEISS
End Function


Function SetColor( Farbe%)
Select Color
Case ROT
Color 255,0,0
Case WEISS
Color 255,255,255
Case GRAU
Color 129,129,129
End Select
End Function
Gewinner des BCC #53 mit "Gitarrist vs Fussballer" http://www.midimaster.de/downl...ssball.exe

ZEVS

BeitragMo, Okt 17, 2011 19:48
Antworten mit Zitat
Benutzer-Profile anzeigen
Es gibt da noch ein paar Kleinigkeiten. Warte, ich gehe noch ein paar Korinthen kacken... So wieder da.
Zitat:
BlitzBasic: [AUSKLAPPEN]

StartBall()
BallX = 155
BallY = 235
IsMoving = 1

Wenn das der einzige Aufruf von StartBall ist, dann kannst du die Funktion noch um die drei anderen Codezeilen erweitern. Eventuell wäre es auch flexibler, BallX und BallY aus GraphicsX und GraphicsY zu berechnen.
Zitat:
BlitzBasic: [AUSKLAPPEN]

Function Player1(PosX)

Der Inhalt einer Funktion sollte sich aus dem Namen erschließen. Es ist hier unklar, was gatan wird. Besser: DrawPlayer1

Zitat:
BlitzBasic: [AUSKLAPPEN]
Text 20,220,"Player 2"

Es ist zwar irrelevant, aber ich möchte dich darauf hinweisen, dass Text wesentlich langsamer als DrawImage ist. Du kannst den Text einfach auf einen ImageBuffer zeichnen, das fällt dan zwar auf die Ladezeiten (etwa 1 msec), aber dafür wird das Spiel etwas schneller. Performance dürfte aber nicht dein Problem sein.

Zitat:
BlitzBasic: [AUSKLAPPEN]

;<mainloop>
BallX = BallX + Cos(Winkel) * Speed
BallY = BallY + Sin(Winkel) * - Speed
;</mainloop>
;...
Function MoveBall()

BallX = BallX + Cos(Winkel) * Speed
BallY = BallY + Sin(Winkel) * - Speed

End Function

Das ist wohl... ein Versehen.

Wenn du B+ benutzt, kannst du das Polling durch Events ersetzen.

Midimaster hat Folgendes geschrieben:
Wenn der Timer was bringen soll muss es FLIP 0 sein

Nein! Flip verwendet Polling, WaitTimer übergibt die Kontrolle an das System. Natürlich ist es mit Flip 0 besser, aber auch ohne hat man Vorteile.

ZEVS

Xeres

Moderator

BeitragMo, Okt 17, 2011 22:12
Antworten mit Zitat
Benutzer-Profile anzeigen
ZEVS hat Folgendes geschrieben:
Nein! Flip verwendet Polling, WaitTimer übergibt die Kontrolle an das System. Natürlich ist es mit Flip 0 besser, aber auch ohne hat man Vorteile.
Nein! - *räusper* - Jain! Flip(1) wartet in einer Endlosschleife bis das Bild 100%ig fertig ist auf kosten der CPU-Belastung.
Standardwerk zum Thema Arrow Hurra, 100 % Auslastung
Der einzige Grund vsync ein zu schalten ist, dass der Nutzer störende Grafikartefakte o.ä. sieht. Dazu kann man die Möglichkeit im Optionsmenü geben - Standard sollte Flip(0) sein.

@Killerjo96:
Die Auslagerung in Konstanten/Variablen macht besonders Sinn, wenn man die Werte von einander Ableitet.
Code: [AUSKLAPPEN]
RandRechts% = GraphicsX
BallX = GraphicsX * 0.5
BallY = GraphicsY * 0.5

Allein die Änderung der Auflösung passt den Rest auf diese Auflösung an.

Wenn alles Problemlos läuft, tausche doch mal den Ball gegen einen Ball-Type aus, und schau, wie du damit zu recht kommst.

Spieltechnischer Vorschlag:
Code: [AUSKLAPPEN]
Winkel = Rand(0,360)
Speed = Rand(1,5)
Mit niedriger Geschwindigkeit und einem Parallelem Winkel zu den Schlägern sorgt das für genervte Spieler. Der Ball sollte immer hauptsächlich Richtung Spieler starten - wenn du dich mit Winkeln schon gut auskennst, sollte das kein Problem sein.
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)

GearTechDE

ehemals 'KillerJo96'

BeitragDi, Okt 18, 2011 16:56
Antworten mit Zitat
Benutzer-Profile anzeigen
Ne, ist mein erstes Test Spiel mit Winkeln ^^ Obwohl ich es sofort damit geschafft habe, haben dieses Thema (Cosinus und Sinus) momentan in Mathematik ^^
Mit freundlichen Grüßen: GearTechDE

Johannes´

BeitragMi, Okt 19, 2011 16:36
Antworten mit Zitat
Benutzer-Profile anzeigen
Ist es wirklich nötig, einen Timer mit 60 Programmabläufen pro Sekunde zu benutzen? (Das soll nicht so rhetorisch sein, wie es klingt.)
Ich meine, dass das Auge nur bis 20-30 FPS einzelne Bilder unterscheidet. Angeblich gibt es Unterschiede auch noch zu schnelleren Bildwiederholungen, jedoch habe ich das selbst bisher nicht probiert oder festgestellt. Außerdem denke ich, dass es in diesem Fall nicht zu einem Unterschied kommt.

Ich bin bisher gut damit klargekommen, meine Spiele mit 30 FPS laufen zu lassen, was ja der Beanspruchung des Computers zugute kommen sollte.

aMul

Sieger des Minimalist Compo 01/13

BeitragMi, Okt 19, 2011 17:45
Antworten mit Zitat
Benutzer-Profile anzeigen
Du hast insofern Recht, dass für die meisten Sachen, inklusive den meisten Spielen, 30 Frames pro Sekunde völlig ausreichen. Ist auch meine Standard-Framerate.
In Action-lastigen Spielen merkt man den unterschied zwischen 30 und 50/60 allerdings schon. Gerade dann wenn es temporäre Einbrüche gibt, weil gerade besonders fordernde Effekte oder ähnliches angezeigt werden. Es macht für solche Spiele deshalb durchaus Sinn eine höhere Framerate anzuvisieren.

Einige Menschen denken, dass weil Fernsehen mit 24 Bildern pro Sekunde läuft, Videos und Spiele am Computer auch nicht mehr nötig haben.
Das ist allerdings nicht korrekt. Gefilmte Videos haben immer eine leichte Unschärfe bei schnellen Bewegungen(auf Grund der Belichtungszeit für das einzelne Bild), was die geringere BIlderanzahl "verschleiert".
Bei Spielen oder digital generierten Videos gibt es diese Unschärfe meistens nicht, was dazu führt, dass sich bewegende Objekte jeden Frame von ihrer alten zu ihrer neuen Position springen, sind diese Sprünge zu groß(zum Beispiel deutlich größer als die Größe des Objektes selbst), aufgrund geringer Frameraten oder zu schnellen Bewegungen, fällt dies deutlich negativ auf.
Moderne Spiele, insbesondere Shooter und Rennspiele, also gerade die Spiele wo schnelle Bewegungen auftreten, haben mittlerweile allerdings oft Bewegungsunschärfe-Effekte eingebaut, was schnelle Bewegungen dort besser aussehen und flüssiger erscheinen lässt.

Das "erwähnt" stimme ich dir aber zu, dass bei dem gezeigten Spiel auch 30 Frames gereicht hätten.
Allerdings macht das hier keinen großen Unterschied, da das Spiel wirklich keine nennenswerte Leistung verbraucht(zumindest mit Flip(0) Wink.
Generell ist es allerdings besser sein Spiel so zu programmieren, dass unterschiedliche Framerates keinen Effekt auf die Spielgeschwindigkeit haben(wer will schon ein Rennspiel spielen, das jedes mal in Zeitlupe geht, wenn der Rechner gerade ein bisschen hart am werkeln ist). Das Stichwort hier ist Frameunabhängigkeit, wozu sich mit der Suche, und bestimmt auch bei den Tutorials was finden lässt.
Panic Pong - ultimate action mashup of Pong and Breakout <= aktives Spiele-Projekt, Downloads mit vielen bunten Farben!
advASCIIdraw - the advanced ASCII art program <= aktives nicht-Spiele-Projekt, must-have für ASCII/roguelike/dungeon-crawler fans!
Alter BB-Kram: ThroughTheAsteroidBelt - mit Quelltext! | RGB-Palette in 32²-Textur / Farbige Beleuchtung mit Dot3 | Stereoskopie in Blitz3D | Teleport-Animation Screensaver
 

PacMani

BeitragMi, Okt 19, 2011 18:40
Antworten mit Zitat
Benutzer-Profile anzeigen
Und ihr glaubt ja wohl nicht wirklich, dass 25 FPS genau mit den Augen synchron ablaufen? Von daher ist erst bei doppelter Rate ein wirklich flüssiges Bild möglich. => Gleich 60Hz nehmen, weil die meisten TFTs damit heute laufen.

Midimaster

BeitragMi, Okt 19, 2011 18:55
Antworten mit Zitat
Benutzer-Profile anzeigen
also ich halt es immer so:

In einer Actionspielumgebung mit 60Hz die Mainschleife abchecken, die Grafiksachen aber nur aktualisieren, wenn es nötig ist: https://www.blitzforum.de/foru...hp?t=37737

In einem Editor oder textbasierenden Spiel genügt auch 30Hz oder 10Hz. Es kommt halt darauf an, wie oft der zeitkritischte Vorgang wiederholt werden muss.

Mein Rhytmus-Trainer läuft mit 200Hz, da sich sonst zu den ohnehin zu erwartenden Audio-Latenzen gleich nochmal unnötige weitere (bis zu) 32 msec zwischen Audio-Ereignis und eigentlich simultanem User-Input addieren könnten.

Beispiel:

Zitat:
Audio Out bei 1000 msec geplant
Timer kommt aber bei 1015 erst in die schleife, gibt Signal aus.
Tastenabfrage bei 1016
User spielt bei 1017 seinen Ton
Timer kommt aber erst bei 1031 wieder in die Schleife
Tastenabfrage bei 1032 bemerkt erst jetzt den User
Gewinner des BCC #53 mit "Gitarrist vs Fussballer" http://www.midimaster.de/downl...ssball.exe

Neue Antwort erstellen


Übersicht BlitzBasic Beginners-Corner

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group