Buchempfehlung
Windows System Programming
Windows System Programming
Das Kompendium liefert viele interessante Informationen zur Windows-Programmierung auf Englisch. [Mehr Infos...]
FreeBASIC-Chat
Es sind Benutzer im FreeBASIC-Chat online.
(Stand:  )
FreeBASIC bei Twitter
Twitter FreeBASIC-Nachrichten jetzt auch über Twitter erhalten. Follow us!

Tutorial

OpenGL und FreeBASIC - eine kleine Einführung - Teil 3 - Bewegen

von MitgliedEastler_dartSeite 3 von 3

mit Cursortasten Punkte bewegen

Und nun wollen wir nicht einfach so bewegen lassen, sondern der Anwender soll die Bewegung der Punkte bestimmen, und zwar auf der Tastatur, mit den Cursortasten. Klingt interessant, oder nicht?

Da müssen wir aber erst mal Grundlagen für die Tastaturabfrage schaffen.
Wir belassen es dabei, mit FreeBasic-INKEY zu arbeiten.
Damit bestücken wir ja bereits die Variable Tastendruck in der Hauptschleife.
Um deutlich zu programmieren, wollen wir nicht einfach mit Chr-Codes vergleichen, wir setzten zuerst die Chr-Codes der Pfeiltasten in Variablen mit aussagekräftigen Namen.
Klar, diese Variablen müssen erst gedimmt werden. wir schreiben also im DIM-Bereich des Hauptprogramms:

'-------------------------
'DIMs
'-------------------------
DIM SHARED AS STRING Tastendruck
DIM SHARED AS STRING Tlinks, Trechts, Tvor, Tzurueck, TCtrlHoch, TCtrlRunter
Tlinks      = CHR(255) & CHR( 75)  :' beim Drücken der Taste CursorLinks gibt die Tastatur CHR(255) & CHR( 75) zurück
Trechts     = CHR(255) & CHR( 77)  :' CursorRechts
Tvor        = CHR(255) & CHR( 72)  :' CursorHoch
Tzurueck    = CHR(255) & CHR( 80)  :' CursorRunter
DIM AS SINGLE XRichtg, YRichtg

In der Hauptschleife fragen wir jetzt die Tastencodes mit den hier definierten Werten ab,
das machen wir in einer Select-Case-Abfrage:

'-------------------------
'HAUPTTEIL
'---------------------------
DO UNTIL Tastendruck = CHR(27)                         :'die Schleife solange immer wiederholen, bis in der Variablen Tastendruck die Esc-Taste (chr(27) steht
   Tastendruck = INKEY                                 :'Jeder Tastendruck wird sofort in die Variable Tastendruck gespeichert
   glClear GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT  :'bisherig erstellte Objekte löschen, unsere 3D-Welt wieder von Neuem an erstellen
   glPushMatrix                                        :'aktuelle Position sichern (2.Zettel mit gleicher Pos auf PositionsSTACK)
   '---------------------------
   'ProgrammSchleife
   '---------------------------

   'JE NACH TASTENDRUCK DEN ENTSPRECHENDEN POSITIONSWERT VERÄNDERN
   SELECT CASE Tastendruck
      CASE Tlinks                 :'Falls die Taste "Cursor nach links" gedrückt wurde
         XRichtg = XRichtg - 0.04 :'um -0.01 in X-Richtung = 0.01 nach links
      CASE Trechts                :'Falls die Taste "Cursor nach rechts" gedrückt wurde
         XRichtg = XRichtg + 0.04 :'um +0.01 in X-Richtung = 0.01 nach links
      CASE Tvor                   :'Falls die Taste "Cursor hoch bzw vor" gedrückt wurde
         YRichtg = YRichtg + 0.04 :'um +0.01 in Y-Richtung = 0.01 nach oben
      CASE Tzurueck               :'Falls die Taste "Cursor runter bzw. zurück" gedrückt wurde
         YRichtg = YRichtg - 0.04 :'um -0.01 in Y-Richtung = 0.01 nach unten
   END SELECT
   'PRÜFEN, DASS DIE POSITIONSWERTE IN ALLEN DREI RICHTUNGEN ZWISCHEN -3 und +3 BLEIBEN
   IF XRichtg >  3 THEN XRichtg =  3  :'falls zu weit rechts, am Rand festnageln
   IF XRichtg < -3 THEN XRichtg = -3  :'falls zu weit links, am Rand festnageln
   IF YRichtg >  3 THEN YRichtg =  3  :'falls zu weit hoch, am Rand festnageln
   IF YRichtg < -3 THEN YRichtg = -3  :'falls zu weit runter, am Rand festnageln

    glPointSize(5)                         :' Punktgröße auf 5 = deutlich groß
    glColor3f 1.0,0.0,0.0                  :' Anzeigefarbe auf ROT setzen
    glTranslatef XRichtg, YRichtg, -6      :' Anzeigeposition auf neue Werte einstellen, Z auf -6 halten, für Abstand zw. Punkte und Kamera
    Objekt1()                              :' Sub Objekt1 aufrufen, in der zwei Punkte an der grad aktuellen Pos erstellt werden
    flip                                   :' liebes OpenGL, zeig alles, was in der Schleife für dich vornedran steht, auf Monitor an
   '---------------------------
   'Ende der Schleife
   '---------------------------
   glPopMatrix                             :' Aufgabe erledigt, den zweiten Zettel mit der geänderten Pos wegschmeißen, dann ist Alte Pos wieder aktuelle Pos
LOOP
END
'-------------------------

Schöne Spielerei oder? Mal eben mit den Cursortasten gleich 2 Punkte links, rechts, hoch oder runter schicken.

So, jetzt können wir Objekte verschieben, mit Push und Pop dafür sorgen, dass immer von der selben Position ausgegangen wird, sogar in Abhängigkeit von der Tastatur können wir Objekte bewegen.

Ich hoffe, Sie haben bisher alles gut verstanden.
Denn jetzt kommt alles in der Summe. Denn eigentlich wollten wir "bloß" die Kamera auf eine andere Position bringen.

Die Kamera bewegen

Die Kamera verschieben bedeutet doch das Gleiche, wie sämtliche Objekte verschieben.
Wenn ich restlos alles, was zu knipsen ist, nach links rücke, ist es das Gleiche, als ob ich mit der Kamera nach rechts rücke. Und genau so wird's auch gemacht.
Mit einem Verschiebebefehl, ganz am Anfang, wird ein Zettel mit der gewünschten Position auf den Stapel gelegt, auf den ja alle Anzeigelisten schauen, ab welcher Position die Befehle auszuführen sind.

Und wenn Sie jetzt ganz clever den Programmcode aus dem vorigen Beispiel untersuchen,
.. .. .. .. ja, genau dort haben wir es so gemacht.
Wir haben in der Hauptschleife das glTranslatef ausgeführt, danach die SUB objekt1() aufgerufen.
Wenn wir uns im vorigen Beispiel als Regel festgelegt hätten, "alle Anzeigebefehle kommen zwischen dem glTranslatef und flip", dann wären ja auch alle Anzeigen von dem glTranslatef beeinflusst = wir hätten damit sämtliche Objekte verschoben.
Und gleichzeitig haben wir in eben diesem vorigen Beispiel die Kamera sogar per Tastendruck vom Anwender verschieben lassen, ist doch super, oder?

Jetzt probieren Sie mal, in der Hauptschleife den SUB-Aufruf Objekt1() einfach durch den SUB-Aufruf Koordinatensystem("", "", 0, 0, 0) zu ersetzen.

Na? Zufrieden? Äh, wie jetzt "Nein"?
Ach, sie wollen sich dabei vorstellen, dass die Kamera sich bewegt, und nicht das Fadenkreuz? Na, da bin ich ja beruhigt, denn so soll es ja sein.
Wenn wir die Cursortasten drücken, stellen wir uns natürlich vor, dass wir die Kamera bewegen.
Und wenn wir halt "nach links" drücken, soll (virtuell) die Kamera nach links rücken, das Bild wandert also nach rechts.
In unserem Beispiel ist das noch falsch rum, das hatten wir ja so erstellt, um mit der Taste "nach links" die beiden Punke nach links rüber zu schicken.
Also drehen wir in der Select-Case-Auswertung die Reaktionen einfach um, dann sollte es passen.
Wir fügen aber noch ein Paar Variablen für die Z-Achse ein, genau so, wie wir es für X und Y gemacht hatten.
Glaube, ich brauch das nicht weiter erläutern, hier das komplette Listing, mit dem wir per Cursortasten mit der Kamera nach rechts, links, vor und zurück wandern, angezeigt wird dabei erst mal nur das Koordinatensystem:

'-------------------------
'DIMs
'-------------------------
DIM SHARED AS STRING Tastendruck
DIM SHARED AS STRING Tlinks, Trechts, Tvor, Tzurueck, TCtrlVor, TCtrlZurueck
Tlinks       = CHR(255) & CHR( 75)  :' beim Drücken der Taste CursorLinks gibt die Tastatur CHR(255) & CHR( 75) zurück
Trechts      = CHR(255) & CHR( 77)  :' CursorRechts
Tvor         = CHR(255) & CHR( 72)  :' CursorHoch
Tzurueck     = CHR(255) & CHR( 80)  :' CursorRunter
TCtrlVor     = CHR(255) & CHR(141)  :'Ctrl oder STRG zusammen mit CursorHoch
TCtrlZurueck = CHR(255) & CHR(145)  :'Ctrl oder STRG zusammen mit CursorRunter
DIM AS SINGLE XRichtg, YRichtg, ZRichtg
'-------------------------
'Includes
'-------------------------
#include "fbgfx.bi"
#include once "GL/gl.bi"
#include once "GL/glu.bi"

'-------------------------
'Declarationen
'-------------------------
DECLARE SUB Koordinatensystem(was AS STRING, TxtPara AS STRING, Para1 AS SINGLE, Para2 AS SINGLE, Para3 AS SINGLE)
DECLARE SUB Objekt1()
DECLARE SUB Manfredsobjekt()
DECLARE SUB Kamera()
DECLARE SUB BewegtePunkte()
'-------------------------
' das Fenster öffnen
'-------------------------
screen 19, 16, , 2

'-------------------------
' Open-GL Init
'-------------------------
glViewport 0, 0, 800, 600                      ' den Current Viewport auf eine Ausgangsposition setzen
glMatrixMode GL_PROJECTION                     ' Den Matrix-Modus Projection wählen
glLoadIdentity                                 ' Diesen Modus auf Anfangswerte setzen
gluPerspective 45.0, 800.0/600.0, 0.1, 100.0   ' Grundeinstellungen des Anezeigefensters festlegen
glMatrixMode GL_MODELVIEW                      ' Auf den Matrix-Modus Modelview schalten
glLoadIdentity                                 ' und auch diesen auf Anfangswerte setzen
glClearColor 0.5, 0.5, 0.50, 0.0               ' Setze Farbe für löschen auf Mittelgrau
glClearDepth 1.0                               ' Depth-Buffer Löschen erlauben
glEnable GL_DEPTH_TEST                         ' den Tiefentest GL_DEPTH_TEST einschalten
glClear GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT  'Tiefen- und Farbpufferbits löschen
'---------------------------
'HAUPTTEIL
'---------------------------
DO UNTIL Tastendruck = CHR(27)                         :'die Schleife solange immer wiederholen, bis in der Variablen Tastendruck die Esc-Taste (chr(27) steht
   Tastendruck = INKEY                                 :'Jeder Tastendruck wird sofort in die Variable Tastendruck gespeichert
   glClear GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT  :'bisherig erstellte Objekte löschen, unsere 3D-Welt wieder von Neuem an erstellen
   glPushMatrix                                        :'aktuelle Position sichern (2.Zettel mit gleicher Pos auf PositionsSTACK)
   '---------------------------
   'ProgrammSchleife
   '---------------------------

   'JE NACH TASTENDRUCK DEN ENTSPRECHENDEN POSITIONSWERT VERÄNDERN
   SELECT CASE Tastendruck
      CASE Trechts                :'Falls die Taste "Cursor nach rechts" gedrückt wurde
         XRichtg = XRichtg - 0.04 :'um -0.01 in X-Richtung = 0.01 nach links
      CASE Tlinks                 :'Falls die Taste "Cursor nach links" gedrückt wurde
         XRichtg = XRichtg + 0.04 :'um +0.01 in X-Richtung = 0.01 nach links
      CASE Tzurueck               :'Falls die Taste "Cursor runter bzw. zurück" gedrückt wurde
         YRichtg = YRichtg + 0.04 :'um +0.01 in Y-Richtung = 0.01 nach oben
      CASE Tvor                   :'Falls die Taste "Cursor hoch bzw vor" gedrückt wurde
         YRichtg = YRichtg - 0.04 :'um -0.01 in Y-Richtung = 0.01 nach unten
      CASE TCtrlZurueck
         ZRichtg = ZRichtg - 0.04 :'um -0.01 in Y-Richtung = 0.01 nach unten
      CASE TCtrlVor
         ZRichtg = ZRichtg + 0.04 :'um -0.01 in Y-Richtung = 0.01 nach unten
   END SELECT
   'PRÜFEN, DASS DIE POSITIONSWERTE IN ALLEN DREI RICHTUNGEN ZWISCHEN -3 und +3 BLEIBEN
   IF XRichtg >  6 THEN XRichtg =  6           :'falls zu weit rechts, bei  6 festnageln
   IF XRichtg < -6 THEN XRichtg = -6           :'falls zu weit links,  bei -6 festnageln
   IF YRichtg >  6 THEN YRichtg =  6           :'falls zu weit hoch,   bei  6festnageln
   IF YRichtg < -6 THEN YRichtg = -6           :'falls zu weit runter, bei -6 festnageln
   IF ZRichtg >  5 THEN ZRichtg =  5           :'falls zu weit zurück, bei 10 festnageln
   IF ZRichtg < -10 THEN ZRichtg = -10           :'falls zu weit vor,    bei -6 festnageln
    glTranslatef XRichtg, YRichtg, ZRichtg    :' Anzeigeposition auf neue Werte einstellen

    glPointSize(5)                             :' Punktgröße auf 5 = deutlich groß
    glColor3f 1.0,0.0,0.0                      :' Anzeigefarbe auf ROT setzen
'    Objekt1()                                  :' Sub Objekt1 aufrufen, in der zwei Punkte an der grad aktuellen Pos erstellt werden
    Koordinatensystem("", "", 0, 0, 0)

    flip                                               :'liebes OpenGL, zeig alles, was in der Schleife für dich vornedran steht, auf Monitor an
   '---------------------------
   'Ende der Schleife
   '---------------------------
   glPopMatrix                                         :' Aufgabe erledigt, den zweiten Zettel mit der geänderten Pos wegschmeißen, dann ist Alte Pos wieder aktuelle Pos
LOOP

END

'-------------------------
SUB BewegtePunkte()
   STATIC AS SINGLE Seite, Hoehe, Tiefe  'Static, damit die Vars beim nächsten Aufruf der Schleife immer noch den Wert haben
   Seite=Seite + 0.01
   IF Seite > 2 THEN Seite = -2     :'damit halten wir den Wert von Seite zwischen -3 und +3
   glTranslatef Seite, 0, -6        :'wir Positionieren die Anzeige fest auf -6 der Z-Achse = im Kamerabereich und beweglich auf der X-Achse
   Objekt1()
END SUB
'-------------------------
SUB Objekt1()
  glBegin GL_POINTS        'Beschreibungsliste für Punkte beginnen
     glVertex3f   1,  1, 0 'einen Punkt auf 1/1/0
     glVertex3f  -1, -1, 0 'noch einen Punkt, dieser auf -1/-1/0
  glEnd                    'Ende der Beschreibungsliste (hier für Punkte)
END SUB
'--------------------------------
SUB Koordinatensystem(was AS STRING, TxtPara AS STRING, Para1 AS SINGLE, Para2 AS SINGLE, Para3 AS SINGLE)
   DIM AS INTEGER Zaehler
'glPushMatrix
         glBegin GL_LINES:' Ja, wir beginnen mit der Beschreibungsliste fuer Linien
         'und zwar zuerst die positiven Bereiche jeder Achse
         glColor3f 1.0, 1.0, 1.0        :' Positives Maß = weiße Teilstriche (Rot 1.0, blau 1.0, grün 1.0 = weiß)
         FOR Zaehler = 1 TO 6 :'fuer die Maßeinheitspositionen 1, 2 und 3 Striche Ziehen
            'X-ACHSE
               'senkrechter Strich (wie Y-Achse)
            glVertex3f  Zaehler+Para1,  0.2+Para2,  0.0+Para3 :' Anfangspunkt auf XAchse-Maßpunkt, 0.2 Einheiten drüber(+Y), Tiefe = 0
            glVertex3f  Zaehler+Para1, -0.2+Para2,  0.0+Para3 :' Endpunkt auf XAchse-Maßpunkt, 0.2 Einheiten drunter(-Y), Tiefe = 0
               'waagerechter Strich (wie Z-Achse)
            glVertex3f  Zaehler+Para1,  0.0+Para2,  0.2+Para3 :' Anfangspunkt auf XAchse-Maßpunkt, 0.2 Einheiten drüber(+Y), Tiefe = 0
            glVertex3f  Zaehler+Para1,  0.0+Para2, -0.2+Para3 :' Endpunkt auf XAchse-Maßpunkt, 0.2 Einheiten drunter(-Y), Tiefe = 0
            'Y-ACHSE
               'Strich wie X-Achse
            glVertex3f  0.2+Para1, Zaehler+Para2,  0.0+Para3 :' Anfangspunkt auf YAchse-Maßpunkt, 0.2 Einheiten nach +X, Tiefe = 0
            glVertex3f -0.2+Para1, Zaehler+Para2,  0.0+Para3 :' Endpunkt auf YAchse-Maßpunkt, 0.2 Einheiten nach -X, Tiefe = 0
               'Strich wie Z-Achse
            glVertex3f  0.0+Para1, Zaehler+Para2,  0.2+Para3 :' Anfangspunkt auf YAchse-Maßpunkt, 0.2 Einheiten nach vorne/+Z, Seite (X) = 0
            glVertex3f  0.0+Para1, Zaehler+Para2, -0.2+Para3 :' Endpunkt auf YAchse-Maßpunkt, 0.2 Einheiten nach hinten/-Z, Seite (X) = 0
            'Z-ACHSE
               'Strich waagerecht (X)
            glVertex3f  0.2+Para1,  0.0+Para2, Zaehler+Para3 :' Anfangspunkt auf ZAchse-Maßpunkt, 0.2 Einheiten nach rechts +X, Hoehe = 0
            glVertex3f -0.2+Para1,  0.0+Para2, Zaehler+Para3 :' Endpunkt auf ZAchse-Maßpunkt, 0.2 Einheiten nach links -X, Hoehe = 0
               'Strich senkreicht (Y)
            glVertex3f  0.0+Para1,  0.2+Para2,  Zaehler+Para3 :' Anfangspunkt auf ZAchse-Maßpunkt, 0.2 Einheiten nach oben +Y, Seite = 0
            glVertex3f  0.0+Para1, -0.2+Para2,  Zaehler+Para3 :' Endpunkt auf ZAchse-Maßpunkt, 0.2 Einheiten nach unten -Y, Seite = 0
         NEXT Zaehler
         glColor3f 0.0, 0.0, 0.0        :' Negatives Maß = schwrze Teilstriche (alles auf 0)
         FOR Zaehler = -6 TO -1 :'fuer die Maßeinheitspositionen -3, -2 und -1 Striche Ziehen
         'X-ACHSE
            'senkrechter Strich (wie Y-Achse)
            glVertex3f  Zaehler+Para1,  0.2+Para2,  0.0+Para3 :' Anfangspunkt auf XAchse-Maßpunkt, 0.2 Einheiten drüber(+Y), Tiefe = 0
            glVertex3f  Zaehler+Para1, -0.2+Para2,  0.0+Para3 :' Endpunkt auf XAchse-Maßpunkt, 0.2 Einheiten drunter(-Y), Tiefe = 0
            'waagerechter Strich (wie Z-Achse)
            glVertex3f  Zaehler+Para1,  0.0+Para2,  0.2+Para3 :' Anfangspunkt auf XAchse-Maßpunkt, 0.2 Einheiten drüber(+Y), Tiefe = 0
            glVertex3f  Zaehler+Para1,  0.0+Para2, -0.2+Para3 :' Endpunkt auf XAchse-Maßpunkt, 0.2 Einheiten drunter(-Y), Tiefe = 0
            'Y-ACHSE
               'Strich wie X-Achse
            glVertex3f  0.2+Para1, Zaehler+Para2,  0.0+Para3 :' Anfangspunkt auf YAchse-Maßpunkt, 0.2 Einheiten nach +X, Tiefe = 0
            glVertex3f -0.2+Para1, Zaehler+Para2,  0.0+Para3 :' Endpunkt auf YAchse-Maßpunkt, 0.2 Einheiten nach -X, Tiefe = 0
               'Strich wie Z-Achse
            glVertex3f  0.0+Para1, Zaehler+Para2,  0.2+Para3 :' Anfangspunkt auf YAchse-Maßpunkt, 0.2 Einheiten nach vorne/+Z, Seite (X) = 0
            glVertex3f  0.0+Para1, Zaehler+Para2, -0.2+Para3 :' Endpunkt auf YAchse-Maßpunkt, 0.2 Einheiten nach hinten/-Z, Seite (X) = 0
            'Z-ACHSE
               'Strich waagerecht (X)
            glVertex3f  0.2+Para1,  0.0+Para2, Zaehler+Para3 :' Anfangspunkt auf ZAchse-Maßpunkt, 0.2 Einheiten nach rechts +X, Hoehe = 0
            glVertex3f -0.2+Para1,  0.0+Para2, Zaehler+Para3 :' Endpunkt auf ZAchse-Maßpunkt, 0.2 Einheiten nach links -X, Hoehe = 0
               'Strich senkreicht (Y)
            glVertex3f  0.0+Para1,  0.2+Para2,  Zaehler+Para3 :' Anfangspunkt auf ZAchse-Maßpunkt, 0.2 Einheiten nach oben +Y, Seite = 0
            glVertex3f  0.0+Para1, -0.2+Para2,  Zaehler+Para3 :' Endpunkt auf ZAchse-Maßpunkt, 0.2 Einheiten nach unten -Y, Seite = 0
         NEXT Zaehler
         'UND NUN DIE DREI ACHSEN SELBST:
         'X-ACHSE
         glColor3f 1.0, 0.0, 0.0        :' Xachse = rot
         glVertex3f  -6.0+Para1, 0+Para2, 0+Para3
         glVertex3f  +6.0+Para1, 0+Para2, 0+Para3
         'Y-ACHSE
         glColor3f 0.0, 1.0, 0.0        :' Yachse = grün
         glVertex3f  0+Para1, -6.0+Para2, 0+Para3
         glVertex3f  0+Para1, +6.0+Para2, 0+Para3
         'Z-ACHSE
         glColor3f 0.0, 0.0, 1.0        :' Zachse = blau
         glVertex3f  0+Para1, 0+Para2, -6.0+Para3
         glVertex3f  0+Para1, 0+Para2, +6.0+Para3
      glEnd
'glPopMatrix
END SUB


Neu ist jetzt, dass Sie sich mit den Tasten STRG bzw. CTRL, je nach Tastaturbeschriftung zusammen mit einer der Tasten Hoch oder Runter in Ihrer kleinen 3D-Welt vor und zurück bewegen können.
Beim Programmstart steht ja die Kamera auf 0,0,0 drum sieht es erst mal ein bisschen komisch aus.
Drücken Sie ein paar mal CTRL mit Cursor runter, dann wird klar, was abläuft.

So, Zeit für eine Pause.

Im Moment können wir also uns eine kleine 3D-Welt erschaffen und in dieser mittels Bewegung von vorwärts/rückwärts, links/rechts und hoch/runter schon ein wenig spazieren gehen.
Was noch fehlt, ist, dass wir uns drehen oder dass Objekte sich drehen.
Um dieses optisch schöner darzustellen, braucht man Anhaltspunkte in der 3D-Welt, deshalb werden wir im nächsten Kapitel erst mal einen Boden unter die Füße kriegen, mal sehen, vielleicht drehen wir uns dann schon darauf.

 

Gehe zu Seite Gehe zu Seite  1  2  3  
Zusätzliche Informationen und Funktionen
  • Das Tutorial wurde am 06.08.2008 von MitgliedEastler_dart angelegt.
  • Die aktuellste Version wurde am 01.10.2008 von MitgliedEastler_dart gespeichert.
  Bearbeiten Bearbeiten  

  Versionen Versionen