PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Quick und Dirty Pong-Spiel auf einem KS0108-GrafikLCD



Thomas E.
07.10.2012, 12:17
Um mich etwas in ein KS0108-GLCD einzuarbeiten entstand aus einer "Drauf-los-Programmiererei" ein kleines Pong-Spiel.

Der Hintergrund dazu: Eigentlich wird aus der ganzen Sache mal ein Datenlogger mit USB-Stick, da ich aber bisher nur T6963C-Displays verwendet habe und dieses Projekt erstmal ein KS0108-GLCD verwendet habe ich mich mal in der Ansteuerung versucht. Grundsätzlich besitzt dieses Display einige Tücken. So muss zum Beispiel ein Grafik-Befehl in einem Rutsch ausgeführt werden und darf keinesfalls unterbrochen werden (z. B. durch einen Interrupt). Während das T6963C-Display bei Unterbrechung gemütlich gewartet hat, bis der Befehl vollständig übertragen wurde, führt das KS0108 den angebrochenen Befehl sofort aus - mit interessanten Folgen. Anschließend stimmt nichts mehr und jeder darauffolgende Befehl wird völlig falsch ausgeführt. Ebenfalls tödlich ist das Beschreiben außerhalb der Display-Position: Das T6963C-Display hat den Befehl dann einfach ignoriert während das KS0108-Display quasi überläuft und eine exestierende Position nimmt, ähnlich wie wenn man einer Bytevariable mit dem Wert null den Wert eins abzieht, was den Wert 255 als Ergebnis liefert.

Zum Programm: Es ist eine Quick'n'Dirty-Lösung, die rein aus dem Bauch heraus entstand. Wenn ich mich dazu motivieren kann werde ich den Code vielleicht noch umschreiben und erweitern, damit was schönes dabei rauskommt. Trotzdem funktioniert die Sache bereits tadellos.
Wird der Ball mit dem Schläger getroffen gibt es einen Punkt, verfehlt man den Ball wird ein Punkt abgezogen. Weniger wie null Punkte gibts nicht.

Vielleicht hat ja jemand Spaß daran und entwickelt es weiter oder spielt einfach nur ein paar Runden. :)


'#########
'## EDT ##
'#########
'---------
'KS0108-Ansteuerung
'V1.0
'07.10.2012
'BASCOM 2.0.7.5
'---------
'schaltplan_ks0108ans_v1_0.dsn
'---------
'DEMO- und Testprogramm zur Ansteuerung eines GLCDs mit KS0108-Controller.
'Mit optional angeschlossenen Tastern an Pind.0 und Pind.1 kann das Spiel gespielt werden.
'---------


$regfile = "m32def.dat" 'AtMega32
$crystal = 1000000 '1Mhz
$hwstack = 32 'nicht optimiert
$swstack = 8 'nicht optimiert
$framesize = 32 'nicht optimiert


Config Pind.0 = Input
Config Pind.1 = Input
Config Pind.2 = Input
Config Pind.3 = Input
Portd.0 = 1
Portd.1 = 1
Portd.2 = 1
Portd.3 = 1

'KONFIGURATION TIMER0
Config Timer0 = Timer , Prescale = 256 '65,5ms
On Timer0 Isr_timer0
Enable Timer0
Start Timer0

'VARIABLEN
Dim X As Byte 'X-Pos. des Balls
Dim Y As Byte 'Y-Pos. des Balls
Dim X_dir As Bit 'Horizontale Laufrichtung 1=rechts, 0=links
Dim Y_dir As Bit 'Vertikale Laufrichtung 1=unten, 0=oben
Dim X_bar As Byte 'X-Position des Schlägers (linkes Ende)
Dim X_bar_offset As Byte 'X-Position des Schlägers (rechtes Ende)
Dim X_bar_temp As Byte 'Schlägerposition zum Rechnen
Dim Y_bar As Byte 'Y-Postion des Schlägers
Dim Point As Byte 'Punktestand
Dim Timer_flag As Bit 'Timer Flag
Dim I As Byte 'Indexvariable für For-Schleife

'INITIALISIEREN DER VARIABLEN
X = 20 'X-Pos. des Balls am Start
Y = 20 'Y-Pos. des Balls am Start
Y_bar = 60 'X-Pos. des Schlägers am Start
X_bar = 20 'Y_Pos. des Schlägers


$lib "glcdKS108.lbx" 'Lib für das Display

Config Graphlcd = 128 * 64sed , Dataport = Portc , Controlport = Porta , Ce = 4 , Ce2 = 3 , Cd = 0 , Rd = 1 , Reset = 5 , Enable = 2
Cls 'LCD-löschen

Setfont My6_8

Lcdat 1 , 1 , "GLCD-DEMO" , 0
Lcdat 2 , 1 , "----------" , 0
Lcdat 4 , 1 , "KS0108-GLCD 128x64" , 0
Lcdat 5 , 1 , "AtMega32 @1Mhz" , 0
Lcdat 6 , 1 , "EDT 2012" , 0
Wait 1
Cls

Enable Interrupts

'### HAUPTSCHLEIFE ###
Do

If Timer_flag = 1 Then
Pset X , Y , 0 'Ball löschen
If X_dir = 1 Then Incr X Else Decr X 'Ballbewegung X-Ache
If Y_dir = 1 Then Incr Y Else Decr Y 'Ballbewegung Y-Achse
If X = 127 Then X_dir = 0 'Richtungswechsel X-Achse
If Y = 63 Then 'Verzweigung wenn Ball am unteren Spielrand
Y_dir = 0 'Richtungswechsel Y-Achse
If Point > 0 Then Decr Point 'Punktestand dekrementieren
End If
If X = 1 Then X_dir = 1 'Richtungswechsel X-Achse
If Y = 1 Then Y_dir = 1 'Richtungswechsel Y-Achse
X_bar_temp = X_bar 'Temporäre Variable zum Rechnen mit der aktuellen Schlägerpos. füllen
For I = 1 To 10 'For-Schleife mit 10 Durchläufen
If Y = 60 And X = X_bar_temp And Y_dir = 1 Then 'Abfrage ob Ball die Schlägerposition erreicht hat
Incr Point 'wenn ja, Punktestand inkrementieren
Toggle Y_dir 'und Richtungswechsel Y-Achse
End If
Incr X_bar_temp 'Temporäre Variable mit Schlägerposition um eins erhöhen
Next
Pset X , Y , 1 'Ball zeichnen

If Pind.0 = 0 Then
X_bar_offset = X_bar + 10
Line(x_bar , Y_bar) -(x_bar_offset , Y_bar) , 0 'Schläger löschen
If X_bar > 10 Then Decr X_bar 'Schlägerposition dekrementieren
X_bar_offset = X_bar + 10 'Rechtes Schlägerende neu berechnen
Line(x_bar , Y_bar) -(x_bar_offset , Y_bar) , 1 'Schläger zeichnen
End If

If Pind.1 = 0 Then
X_bar_offset = X_bar + 10
Line(x_bar , Y_bar) -(x_bar_offset , Y_bar) , 0
If X_bar < 100 Then Incr X_bar
X_bar_offset = X_bar + 10
Line(x_bar , Y_bar) -(x_bar_offset , Y_bar) , 1
End If

Lcdat 1 , 1 , Point , 0 'Punktestand zeichnen

Reset Timer_flag
End If

Loop

'### ISR ###
Isr_timer0:

Set Timer_flag

Return


End

$include "my6_8.font"

for_ro
07.10.2012, 14:54
Hallo Thomas,
solange dein Programm genau so aussieht, ist es vollkommen überflüssig, die Zeit in einem Timer Interrupt zu verschwenden. Da du nichts anderes machst, als das Flag zu setzen, das du dann in der Hauptschleife wieder abfragst, kannst du auch gleich das Interrupt Flag des Timers abfragen.
Die Schleife würde dann so aussehen:


Do
If TIFR.TOV0 = 1
...
Set TIFR.TOV0
Loop

Das ändert an dem Ablauf nichts, nur hast du die Zeit zum Aufruf und Verlassen der ISR gespart.
Damit kann dann auch kein Interrrupt deine LCD Kommandos unterbrechen.
Ist allerdings dann nicht mehr so leicht übertragbar auf andere Hardware, weil dort die Register evtl. anders heißen.

Thomas E.
07.10.2012, 15:40
Hallo for_ro!


Danke für deinen Hinweis. An diese Variante habe ich gar nicht gedacht. :)