Du bist nicht angemeldet.
Monkey X - Tutorial 2
Vorbetrachtung:
Falls noch keine Grundlagen in der Programmierung bestehen, bitte Tutorial 1 durchlesen.
Bevor wir uns nun ins Getuemmel muessen noch ein paar Dinge geklaert werden.
Ihr koennt Euch ja sicher vorstellen, dass der Quellcode im Laufe der Entwicklung immer groesser wird. Immer mehr Funktionen, Variablen und hoffentlich auch Kommentare (dies hilft ungemein!).
Damit man aber Dinge voneinander abkapseln kann, also "logisch trennen", bietet Monkey eine Importfunktion an. Mit dem Schluesselwort import kann man dem Compiler mitteilen, dass Code von anderer Stelle nachgeladen werden soll.
Dies koennte im Code so aussehen:
Import mojo
Import meine_andere_datei
Hmm, was ist dieses mojo? Mojo ist Modul was von Monkey bereitgestellt wird, es bietet Dinge wie Zeichenfunktionen und anderes. "meine_andere_datei" hingegen besagt, dass entweder ein Modul "meine_andere_datei" bereitstuende - oder aber im gleichen Verzeichnis wie unser Quellcode eine Datei "meine_andere_datei.monkey" herumliegt. Das System ist nicht ganz eindeutig geloest und bedarf etwas mehr Gewoehnung als es bei BlitzMax der Fall war (da gibt es Module und Dateien die man importieren kann, hier ist alles das Gleiche: eine Importierte Datei).
Fuer den Anfang reicht es, wenn wir uns merken: Import mojo brauchen wir, sobald wir eine grafische App entwickeln wollen.
Neben der Importfunktion, beschaeftigt sich dieses Tutorial auch mit Klassen. Klassen sind das was Funktionen fuer Anweisungen sind: eine Gruppierung. Eine Klasse beherbergt aber nicht nur verschiedene Funktionen, nein sie kann auch Variablen speichern. Das Besondere an Klassen ist aber nun, dass Instanzen dieser Klassen erzeugt werden koennen. Waere "Tagebuch" eine Klasse, dann waere "Maries Tagebuch" aber auch "Pauls Tagebuch" (der sicher nicht will, dass jeder weiss, dass er ein Tagebuch schreibt ;D) waeren Instanzen. Klassen koennen Variablen so einrichten, dass sie sowohl von Paul als auch von Marie abgerufen werden koennen, aber auch, dass jeder seine eigen Variablen besitzt. Und was fuer Variablen geht, das klappt auch mit Funktionen. Diese instanzbezogenen Funktionen heissen Methoden - prima, da laesst sich sowas ja gut auseinanderhalten. Wichtig ist hier nun: wenn etwas instanzbezogen ist, kann es auf die allgemeinen Variablen zugreifen, etwas allgemeines aber nicht auf instanzbezogene Daten.
Ein kleines Beispiel gefaellig?
Class Tagebuch
Field besitzer:String
Method New(besitzer:String = "")
Self.besitzer = besitzer
End Method
Method gehoert:String()
Return besitzer
End Method
End
Function Main()
Local MariesTagebuch:Tagebuch = New Tagebuch("Marie")
Local PaulsTagebuch:Tagebuch = New Tagebuch("Susi")
'hab mich geirrt, es gehoert Paul
PaulsTagebuch.besitzer = "Paul"
Print "Maries Tagebuch gehoert "+MariesTagebuch.gehoert()
Print "Pauls Tagebuch gehoert "+PaulsTagebuch.gehoert()
End Function
Statt "local" fuer eine lokale Variable, definieren wir die Instanzeneigenschaften als "Field". Interessant ist hier noch die Method New, die kann prima genutzt werden, um neue Instanzen einer Klasse anzulegen. Monkey ruft diese Methode automatisch auf, versucht man mit New Klassenname eine neue Instanz zu erzeugen. Weiterhin gibt es die Method gehoert, sie liefert an den Nachfrager einen Text zurueck (string) und erwartet als Aufrufparameter einen Text. Gibt man diesen nicht an, wird ein leerer Text ("") angenommen, dass schimpft sich dann Standardwert.
Will man auf eine Eigenschaft einer Instanz von aussen zugreifen, so macht man dies mittels dem Variablennamen der die Instanz beherbergt, und dem mittels "." (Punkt) verknuepften Namen des "Fields". Gleichermassen verfaehrt man, will man Funktionen/Methoden einer Klasse aufrufen.
Genug geplaudert...
Los gehts:
Fangt im Editor eine neue Datei an: Schritt2.monkey und fuegt folgenden Inhalt ein:
Import mojo
Class MyApp Extends App
Method OnCreate()
'wird aufgerufen sobald die App fertiggeladen hat
'Setzt die UpdateRate auf 15 Hertz.
'15x pro Sekunde wird dadurch OnUpdate() aufgerufen
'Diese muss unbedingt gesetzt werden, sonst passiert nix
SetUpdateRate(15)
End
Method OnRender()
'Einsprungspunkt für alle Darstellungen (zeichnen)
End
Method OnUpdate()
'wird aller "UpdateRate"-Hertz aufgerufen
'(in unserem Fall aller 15x pro Sek)
End
End
'die Main() wird automatisch aufgerufen - hier definieren wir was
'beim Ausfuehren des Programmes gemacht wird
'"App" definiert, dass OnRender/OnUpdate usw ausgefuehrt werden - da
'wir unsere MyApp von "App" erweitern, uebernehmen wir dieses Verhalten
Function Main()
New MyApp
End Function
Puhh, wenigstens unsere alte bekannte Funktion "Main()" ist noch dabei (ganz unten), aber was ist da nun der Inhalt?
Statt irgendwelcher If-then-Bedingungen steht da New MyApp. Wir wissen ja nun, dass damit eine neue Instanz der Klasse "MyApp" erzeugt wird. Warum diese nicht in einer Variable gespeichert wird? Hmm, da wir MyApp selbst nicht verwenden oder irgendwie von aussen darauf zugreifen, ist dies einfach in dem Moment nicht noetig. MyApp hat aber doch gar keine New-Methode? Hat sie doch! Denn mittels dem Schluesselwort "extends" haben wir in der Klassendefinition festgelegt, dass "MyApp" alle Eigenschaften, Funktionen usw. von der Klasse "App" erbt. Diese App-Klasse wird von Monkey bereitgestellt. Die New-Methode von App kuemmert sich darum, dass bestimmte Methoden aufgerufen werden (beispielsweise "OnRender()" -damit auch immer fein der Bildschirm unserer App gezeichnet wird, oder "OnCreate()" sobald alles notwendige geladen worden ist).
Jetzt, wo sicher so mancher schon die Rakete gestartet hat: zu sehen ist hier ersteinmal noch nix, auch wenn die Funktionen "OnRender()" und "OnUpdate()" ja schonmal da sind. Aber wofuer ist denn "OnUpdate()"? Wie es sich fuer ordentliche Programmierer gehoert, trennen wir "Logik" und "Grafik". Das Zeichnen eines Autos ist also an anderer Stelle zu realisieren, als die Bewegung dieses (und vorallem die Kontrolle, ob er gegen eine Wand gefahren ist). Warum? Zeichnen ist oft um Welten langsamer als das die Spiellogik (Schach ausgenommen!).
Da alte Hardware nicht soviele Zeichnungen pro Sekunde fertigstellen kann, wir aber sicherstellen muessen, dass uns zwischen den Zeichnungen kein Autocrash durch die Lappen geht, koennen wir auf diese Art die Logik haeufiger pro Sekunde Berechnungen durchfuehren lassen, als Zeichnungen. So kann es sein, dass 10x pro Sekunde das Auto gezeichnet wird (nach 1m, nach 3, nach 7, nach 11m), aber 40x pro Sekunde bewegt (1, 1.1, 1.2, ... 11m).
So, nun wollen wir aber was zeichnen, weg von diesem ganzen Theoriekram: das Aequivalent zur Konsolenausgabe mittels "Print" ist "DrawText". Da wir nun aber nicht mehr einfach Zeile fuer Zeile ausgeben koennen, bedarf es noch einer Koordinatenangabe. Waehrend Systeme wie OpenGL die verfuegbare Zeichenflaeche in 0,0-1,1 aufteilen (0.5, 0.5 waere also die Mitte) ist Monkey da netter (was nicht gleichzusetzen mit "besser" ist!) und erwartet Pixelangaben: ein 10,10 sagt also, von oben links gehst du 10 pixel nach rechts und 10 nach unten.
Worauf wartest Du noch? Hier ist der naechste Code (ueberschreibe ruhig den alten)
Import mojo
Class MyApp Extends App
Field meinName:String = "Paul"
'die derzeitige Position unseres "Mein Name ist"-Textes
Field ausgabeX:Int = 0
Method OnCreate()
'wird aufgerufen sobald die App fertiggeladen hat
'Setzt die UpdateRate auf 15 Hertz.
'15x pro Sekunde wird dadurch OnUpdate() aufgerufen
'Diese muss unbedingt gesetzt werden, sonst passiert nix
SetUpdateRate(15)
End Method
Method OnRender()
'Bildschirm leeren, einfarbige Flaeche
Cls
'Farbe setzen
SetColor(0, 0, 255)
DrawText("Hello World!", 0, 0)
DrawText("Mein Name ist:" + Self.meinName, ausgabeX, 15)
End Method
Method OnUpdate()
'wird aller "UpdateRate"-Hertz aufgerufen
'(in unserem Fall aller 15x pro Sek)
'pro UpdateRate erhoehen wir um 1, macht 15 Pixel pro Sekunde
ausgabeX = ausgabeX + 1
'nach 100 Pixeln wieder nach 0
If ausgabeX >= 100 Then ausgabeX = 0
End Method
End Class
'die Main() wird automatisch aufgerufen - hier definieren wir was
'beim Ausfuehren des Programmes gemacht wird
'"App" definiert, dass OnRender/OnUpdate usw ausgefuehrt werden - da
'wir unsere MyApp von "App" erweitern, uebernehmen wir dieses Verhalten
Function Main()
New MyApp
End Function
Nun sind OnRender() und OnUpdate() endlich mit Inhalt gefuellt. Mittels Cls loeschen wir etwaigen Datenmuell vom Grafikspeicher (malen eine leere Flaeche ueber Pixelmuell) und dann geben wir auch schon den Text aus. Schoen ist hier auch zu sehen, wie wir Logik (Bewegung des Textes) und Grafik (Zeichnen des Textes) trennen. Ach und eine Kleinigkeit habe ich noch geaendert: statt alle Methoden, Klassen immer mit "End" abzuschliessen, bevorzuge ich es, etwas aussagekraeftigere Varianten zu nutzen (End Class, End Method, ...).
Wer nun noch weiter ueben will: Es gibt noch andere "Primitive" zum Zeichnen:
DrawRect(x,y,w,h)
DrawOval(x,y,w,h)
Uebung: Damit (und mit SetColor) muesste sich doch ein "blockiges Auto" zeichnen lassen oder?
bye
Ron
Offline
Hier mein erstes Auto:
Import mojo
Class MyApp Extends App
Method OnCreate()
'wird aufgerufen sobald die App fertiggeladen hat
'Setzt die UpdateRate auf 15 Hertz.
'15x pro Sekunde wird dadurch OnUpdate() aufgerufen
'Diese muss unbedingt gesetzt werden, sonst passiert nix
SetUpdateRate(15)
End Method
Method OnRender()
'Bildschirm leeren, einfarbige Flaeche
Cls
'Farbe setzen
SetColor(0, 0, 255)
'Karosse
DrawRect(160, 170, 180, 50)
DrawRect(210, 130, 100, 40)
'Räder
SetColor(0, 0, 388)
DrawOval(180, 200, 40, 40)
DrawOval(290, 200, 40, 40)
SetColor(0, 0, 588)
DrawOval(185, 205, 30, 30)
DrawOval(295, 205, 30, 30)
End Method
End Class
'die Main() wird automatisch aufgerufen - hier definieren wir was
'beim Ausfuehren des Programmes gemacht wird
'"App" definiert, dass OnRender/OnUpdate usw ausgefuehrt werden - da
'wir unsere MyApp von "App" erweitern, uebernehmen wir dieses Verhalten
Function Main()
New MyApp
End Function
Eigentlich habe ich versucht, das Teil auch noch zu bewegen. ähnlich der Schrift.
Wußte aber nicht, wie ich das definieren sollte.
Bis Field bin ich noch gekommen...
Beitrag geändert von Gast2 (24.07.2014 03:33)
Offline
Zum Bewegen:
In dem Beispiel mit dem bewegenden Text benutze ich eine Variable um den Text versetzt zu positionieren. Wir haben also ein eine dynamische Koordinate, statt "10" nutzen wir die Variable "ausgabeX".
Jederzeit koennten wir aber auch beim Zeichnen hinschreiben "ausgabe X + 10", dass nenne ich dann "lokalen Offset" (also eine Verschiebung).
Du zeichnest deine schicke Karre aber immer an fixen Punkten (x = 160, x = 210, ...) besser waere es aber, wenn sich diese Zahlen veraendern wuerden -> Stichwort: Variable.
Eventuell denkst Du nun, fuer jedes Bauteil eine Variable zu nutzen, aber nein, alle koennen die gleiche Variable nutzen - bspweise den "linkesten Punkt". Die Reifen sind dann "linkerPunkt + 100" oder "linkerPunkt + 200" versetzt.
Stell Dir einfach vor, Du hast dir aus Papier was gebaut und zusammengeheftet - nun verschiebst du einfach mit dem Zeigefinger auf einem Teil des Autos alle Teile in einem Rutsch - so aehnlich laeuft es hier ab.
Da ich nun aber schon viel erklaert habe eine neue Uebung: Das Auto soll aus dem Bildschirm herausfahren und dann auf der anderen Seite wieder herauskommen:
- finde durch probieren heraus wie breit der Bildschirm ist (dafuer gibt es eine Funktion, aber finde die Zahl halt raus)
- lasse die Autoposition bis zu dieser Zahl erhoehen, setze sie dann so ins negative, dass die andere Seite des Autos noch nicht auf der anderen Seite zu sehen waere (- Autobreite)
Damit muesste dein Auto schoen von links nach rechts tuckern.
Wenn Du willst kannst du Dir auch ueberlegen, wie man es machen muesste, dass das Auto nicht erst verschwindet und dann auf der anderen Seite auftaucht, sondern die verschwindende Spitze bereits auf der anderen Seite wieder zu sehen ist.
bye
Ron
Offline
Mal eine Zwischenfrage:
Ich wollte heute weitermachen. Habe hier den Schritt eins im Monkey geöffnet und der Funktioniert, wie es soll.
Habe dann neu geöffnet und schreibe den Kram so rein. Aber erstens verfärbt sich der Text nicht so fein. Und dann wird die Rakete nicht interaktiv.
Habe ich was vergessen?
Ich habe aber auch die Übung mit dem Auto reinkopiert. Da wird Raketchen a net bunt....
Import mojo
Class MyApp Extends App
Method OnCreate()
'wird aufgerufen sobald die App fertiggeladen hat
'Setzt die UpdateRate auf 15 Hertz.
'15x pro Sekunde wird dadurch OnUpdate() aufgerufen
'Diese muss unbedingt gesetzt werden, sonst passiert nix
SetUpdateRate(15)
End Method
Method OnRender()
'Bildschirm leeren, einfarbige Flaeche
Cls
'Farbe setzen
SetColor(0, 0, 255)
'Karosse
DrawRect(ausgabeX, 170, 180, 50)
DrawRect(ausgabeX + 50, 130, 100, 40)
'Räder
SetColor(0, 0, 388)
DrawOval(ausgabeX + 20, 200, 40, 40)
DrawOval(ausgabeX + 130, 200, 40, 40)
SetColor(0, 0, 588)
DrawOval(ausgabeX + 5, 205, 30, 30)
DrawOval(ausgabeX + 115, 205, 30, 30)
End Method
End Class
Function Main()
New MyApp
End Function
Offline
Hast Du darauf geachtet, die Datei mit der Endung ".monkey" zuspeichern?
Bei Linux kann man Dateien ja nennen wie man will, aber "TED" braucht unbedingt die .monkey-Endung.
PS: eine andere kostenlose IDE fuer Monkey:
https://github.com/engor/Jentos_IDE
http://fingerdev.com/apps/jentos/
brauchst nur diese Datei herunterladen:
https://drive.google.com/uc?id=0Bx2zoIlA6GzKR1JKc0Jpbmpfb0k
Die schiebst Du dann in Dein Monkeyverzeichnis neben die "Monkey"-Datei - und dann haettest Du einen anderen Editor (der meines Erachtens "mehr" kann - hilfreiche Dinge halt).
@Uebung
ja so muesste es geloest werden (freilich konntest Du nun nicht testen und bemerken,dass du "ausgabeX" nicht deklariert hast ) - nun noch ein paar Gedanken dazu, wie man den Teil links sichtbar machen koennte, der rechts schon rausgefahren ist. Nein, ich rede nicht von speziellen Befehlen. Ein ganz einfacher "Trick".
bye
Ron
Offline
NICHT LESEN
wenn du noch an der "links rein- und rechts noch rausfahrend"-Sache ueberlegst.
Hier nun mal eine erweiterte Fassung - die Dein Auto zeichnet (ich glaube die Radkappen willst du nochmal ueberarbeiten):
Import mojo
Class MyApp Extends App
Field autoA:TAuto
Field autoB:TAuto
Method OnCreate()
'wird aufgerufen sobald die App fertiggeladen hat
'Setzt die UpdateRate auf 15 Hertz.
'15x pro Sekunde wird dadurch OnUpdate() aufgerufen
'Diese muss unbedingt gesetzt werden, sonst passiert nix
SetUpdateRate(20)
'erzeuge die Autos
autoA = New TAuto(-200, 200)
autoB = New TAuto
End Method
Method OnUpdate()
'Autos bewegen
autoA.Update()
autoB.Update()
End Method
Method OnRender()
'Bildschirm leeren, einfarbige Flaeche
Cls
'Autos zeichnen
autoA.Draw()
autoB.Draw()
End Method
End Class
Class TAuto
'Eigenschaften einer jeden Instanz von TAuto
Field x:Int, y:Int
Field breite:Int = 180
'Geschwindigkeit horizontal/vertikal
Field dx:Int = 3, dy:Int = 0
Field farbeR:Int, farbeG:Int, farbeB:Int
'wenn man "new TAuto(x,y)" aufruft:
Method New(x:Int, y:Int)
Self.x = x
Self.y = y
'setze die farben jeweils zufaellig rot = 100-255, gruen ... blau ...
SetzeFarbe(Rnd(100, 255), Rnd(100, 255), Rnd(100, 255))
End Method
'wenn man "new TAuto()" aufruft:
Method New()
x = 0
'eine zufaellige Zahl raussuchen
y = Rnd(100, 200)
'setze die farben jeweils zufaellig rot = 100-255, gruen ... blau ...
SetzeFarbe(Rnd(100, 255), Rnd(100, 255), Rnd(100, 255))
End Method
Method SetzeFarbe(r:Int, g:Int, b:Int)
Self.farbeR = r
Self.farbeG = g
Self.farbeB = b
End Method
Method Update()
'um die geschwindigkeit "pro update" erhoehen
x = x + dx
y = y + dy
'links wieder anfangen wenn komplett verschwunden
'da wir das "zweite Stueck" Auto schon zeichnen, koennen
'wir direkt bei 0 anfangen
If x > DeviceWidth() Then x = 0
End Method
'allgemeine Zeichenmethode
Method Draw()
DrawCar(x, y)
'falls das Auto schon rechts raus verschwindet, zeichnen
'wir es links schon ein wenig neu
If x + breite > DeviceWidth()
'800 - x = der schon nicht mehr sichtbare teil
DrawCar (-(DeviceWidth()-x), y)
Endif
End Method
'unsere spezielle Zeichenmethode
'dadurch koennen wir prima "halbe Autos" zeichnen
Method DrawCar(x:Int, y:Int)
'Farbe setzen - Werte gehen von 0-255
SetColor(farbeR, farbeG, farbeB)
'Karosse
DrawRect(x, y + 40, 180, 50)
DrawRect(x + 50, y, 100, 40)
'Räder
SetColor(farbeR - 50, farbeG - 50, farbeB - 50)
DrawOval(x + 20, y + 70, 40, 40)
DrawOval(x + 130, y + 70, 40, 40)
SetColor(farbeR - 80, farbeG - 80, farbeB - 80)
DrawOval(x + 5, y + 75, 30, 30)
DrawOval(x + 115, y + 75, 30, 30)
End Method
End Class
Function Main()
New MyApp
End Function
Neu ist hier "Rnd" - fuer "Random", also Zufall, die Parameter die wir nutzen sind "Minima" und "Maxima" des Zufallswertes.
Des Weiteren nutzen wir "DeviceWidth()" um die Bildschirmbreite zurueckgeben zu lassen.
Auch zeigt sich hier schon wie man mit Monkey Funktionen "ueberlaedt" (mehrere Varianten mit abweichenden Parametern ...das geht mit BlitzMax noch nicht). Dazu sage ich aber spaeter noch was.
Viel Spass beim anpassen und herumbasteln.
bye
Ron
Offline
Nein, freilich habe ich das monkey vergessen. Das war noch voll unfertig. Wunderte mich nur, warum da nix passierte.
.monkey, .monkey, punktmonkey -> merken
Danke. Kann ich weiterwurschteln.
Hab auch nicht weitergelesen.
Offline
So, hier mein fahrendes Auto;)
Import mojo
Class MyApp Extends App
Field ausgabeX:Int = 100
Method OnCreate()
'wird aufgerufen sobald die App fertiggeladen hat
'Setzt die UpdateRate auf 15 Hertz.
'15x pro Sekunde wird dadurch OnUpdate() aufgerufen
'Diese muss unbedingt gesetzt werden, sonst passiert nix
SetUpdateRate(15)
End Method
Method OnRender()
'Bildschirm leeren, einfarbige Flaeche
Cls
'Farbe setzen
SetColor(0, 0, 255)
'Karosse
DrawRect(ausgabeX, 170, 180, 50)
DrawRect(ausgabeX + 50, 130, 100, 40)
'Räder
SetColor(0, 0, 388)
DrawOval(ausgabeX + 20, 200, 40, 40)
DrawOval(ausgabeX + 130, 200, 40, 40)
SetColor(0, 0, 588)
DrawOval(ausgabeX + 25, 205, 30, 30)
DrawOval(ausgabeX + 135, 205, 30, 30)
End Method
Method OnUpdate()
'wird aller "UpdateRate"-Hertz aufgerufen
'(in unserem Fall aller 15x pro Sek)
'pro UpdateRate erhoehen wir um 1, macht 15 Pixel pro Sekunde
ausgabeX = ausgabeX + 3
'nach 100 Pixeln wieder nach 0
If ausgabeX >= 640 Then ausgabeX = -180
End Method
End Class
Function Main()
New MyApp
End Function Ich habe mal kopiert, was mit dem Installationswerkzeug entfernt, aufgefrischt und zugefügt wird:
@andere kostenlose IDE fuer Monkey
Ich habe die angegebene Datei ins Verzeichnis kopiert.
Was nun?
Muß ich das öffnen? Nutzt monkey das einfach mit?
Beitrag geändert von Gast2 (26.07.2014 12:50)
Offline
das ist eine andere ausfuehrbare Datei ... halt eine andere ".exe" sozusagen.
Function Main()
New MyApp
End Function Ich habe mal kopiert, was mit dem Installationswerkzeug entfernt, aufgefrischt und zugefügt wird:
?? wie meinen?
bye
Ron
Offline
Hmmm
ronny@RonnyPC ~/Arbeit/Programmieren/MonkeyX77a $ ldd jentos_v1.1_linux
linux-vdso.so.1 => (0x00007fff653fe000)
libQt5WebKitWidgets.so.5 => /usr/lib/x86_64-linux-gnu/libQt5WebKitWidgets.so.5 (0x00007f8578597000)
libQt5WebKit.so.5 => /usr/lib/x86_64-linux-gnu/libQt5WebKit.so.5 (0x00007f85762cc000)
libQt5Widgets.so.5 => /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5 (0x00007f8575ac4000)
libQt5Network.so.5 => /usr/lib/x86_64-linux-gnu/libQt5Network.so.5 (0x00007f8575782000)
libQt5Gui.so.5 => /usr/lib/x86_64-linux-gnu/libQt5Gui.so.5 (0x00007f85751b5000)
libQt5Core.so.5 => /usr/lib/x86_64-linux-gnu/libQt5Core.so.5 (0x00007f8574ba1000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f8574984000)
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f8574680000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f8574469000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f85740a1000)
libQt5OpenGL.so.5 => /usr/lib/x86_64-linux-gnu/libQt5OpenGL.so.5 (0x00007f8573e37000)
libQt5PrintSupport.so.5 => /usr/lib/x86_64-linux-gnu/libQt5PrintSupport.so.5 (0x00007f8573be0000)
libQt5Sensors.so.5 => /usr/lib/x86_64-linux-gnu/libQt5Sensors.so.5 (0x00007f85739a7000)
librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007f857379f000)
libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007f8573585000)
libXrender.so.1 => /usr/lib/x86_64-linux-gnu/libXrender.so.1 (0x00007f857337b000)
libXcomposite.so.1 => /usr/lib/x86_64-linux-gnu/libXcomposite.so.1 (0x00007f8573178000)
libjpeg.so.8 => /usr/lib/x86_64-linux-gnu/libjpeg.so.8 (0x00007f8572f22000)
libpng12.so.0 => /lib/x86_64-linux-gnu/libpng12.so.0 (0x00007f8572cfc000)
libicui18n.so.48 => /usr/lib/x86_64-linux-gnu/libicui18n.so.48 (0x00007f8572934000)
libicuuc.so.48 => /usr/lib/x86_64-linux-gnu/libicuuc.so.48 (0x00007f85725c7000)
libX11.so.6 => /usr/lib/x86_64-linux-gnu/libX11.so.6 (0x00007f8572292000)
libxslt.so.1 => /usr/lib/x86_64-linux-gnu/libxslt.so.1 (0x00007f8572055000)
libxml2.so.2 => /usr/lib/x86_64-linux-gnu/libxml2.so.2 (0x00007f8571cee000)
libglib-2.0.so.0 => /lib/x86_64-linux-gnu/libglib-2.0.so.0 (0x00007f85719ed000)
libgobject-2.0.so.0 => /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0 (0x00007f857179c000)
libgstreamer-1.0.so.0 => /usr/lib/x86_64-linux-gnu/libgstreamer-1.0.so.0 (0x00007f8571499000)
libgstapp-1.0.so.0 => /usr/lib/x86_64-linux-gnu/libgstapp-1.0.so.0 (0x00007f857128d000)
libgstbase-1.0.so.0 => /usr/lib/x86_64-linux-gnu/libgstbase-1.0.so.0 (0x00007f8571036000)
libgstpbutils-1.0.so.0 => /usr/lib/x86_64-linux-gnu/libgstpbutils-1.0.so.0 (0x00007f8570e0f000)
libgstvideo-1.0.so.0 => /usr/lib/x86_64-linux-gnu/libgstvideo-1.0.so.0 (0x00007f8570bcd000)
libgstaudio-1.0.so.0 => /usr/lib/x86_64-linux-gnu/libgstaudio-1.0.so.0 (0x00007f8570987000)
libsqlite3.so.0 => /usr/lib/x86_64-linux-gnu/libsqlite3.so.0 (0x00007f85706d3000)
libQt5Quick.so.5 => /usr/lib/x86_64-linux-gnu/libQt5Quick.so.5 (0x00007f8570178000)
libQt5Qml.so.5 => /usr/lib/x86_64-linux-gnu/libQt5Qml.so.5 (0x00007f856fd3b000)
libQt5Sql.so.5 => /usr/lib/x86_64-linux-gnu/libQt5Sql.so.5 (0x00007f856fafc000)
libQt5Location.so.5 => /usr/lib/x86_64-linux-gnu/libQt5Location.so.5 (0x00007f856f85a000)
libGL.so.1 => /usr/lib/fglrx/libGL.so.1 (0x00007f856f64e000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f856f349000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f856f145000)
/lib64/ld-linux-x86-64.so.2 (0x00007f8578801000)
libicudata.so.48 => /usr/lib/x86_64-linux-gnu/libicudata.so.48 (0x00007f856ddd4000)
libxcb.so.1 => /usr/lib/x86_64-linux-gnu/libxcb.so.1 (0x00007f856dbb6000)
liblzma.so.5 => /lib/x86_64-linux-gnu/liblzma.so.5 (0x00007f856d993000)
libpcre.so.3 => /lib/x86_64-linux-gnu/libpcre.so.3 (0x00007f856d754000)
libffi.so.6 => /usr/lib/x86_64-linux-gnu/libffi.so.6 (0x00007f856d54c000)
libgmodule-2.0.so.0 => /usr/lib/x86_64-linux-gnu/libgmodule-2.0.so.0 (0x00007f856d347000)
libgsttag-1.0.so.0 => /usr/lib/x86_64-linux-gnu/libgsttag-1.0.so.0 (0x00007f856d10f000)
libQt5V8.so.5 => /usr/lib/x86_64-linux-gnu/libQt5V8.so.5 (0x00007f856cac4000)
libQt53D.so.5 => /usr/lib/x86_64-linux-gnu/libQt53D.so.5 (0x00007f856c588000)
libXext.so.6 => /usr/lib/x86_64-linux-gnu/libXext.so.6 (0x00007f856c375000)
libatiuki.so.1 => /usr/lib/fglrx/libatiuki.so.1 (0x00007f856c25a000)
libXau.so.6 => /usr/lib/x86_64-linux-gnu/libXau.so.6 (0x00007f856c056000)
libXdmcp.so.6 => /usr/lib/x86_64-linux-gnu/libXdmcp.so.6 (0x00007f856be4f000)
Klingt nach "es braucht die QT 5 Bibiotheken".
Aaaaber... ich habs jetzt mal bei Knoppix probiert: kann es sein dass Du eine 32Bit-Variante installiert hast - die Binaerdatei ist ja fuer 64Bit gemacht.
$ objdump -f jentos_v1.1_linux
jentos_v1.1_linux: file format elf64-x86-64
architecture: i386:x86-64, flags 0x00000112:
EXEC_P, HAS_SYMS, D_PAGED
start address 0x000000000041b675
Lass dich davon aber nicht abhalten: man kann zwar selbst das Programm kompilieren (Code ist verfuegbar) aber "lerne erstmal" die Grundzuege mit Monkey/Ted.
bye
Ron
Offline
... aber "lerne erstmal" die Grundzuege mit Monkey/Ted.
Hmm. Halte ich auch für besser;)
Also vorwärts!
Hast Du eigentlich irgendwo eine Tabelle mit den Befehlen verfügbar?
Sonst suche ich mir die selber zusammen, immer so, wie es hier vorwärtsgeht. Ist vielleicht sogar besser wegen der Einprägung.
Offline
Die Befehle sind "Funktionen" von Modulen. Es gibt so Logiksachen wie unsere "if ... then ... else... endif". Dinge wie "Print" sind aber Funktionen die generell zur Verfuegung stehen (also nicht nur innerhalb einer Klasse).
Im naechsten Tutorial geht es dann eh um "LoadImage/DrawImage" und wir nutzen "import" um eine eigene, zweite Datei, zu importieren.
bye
Ron
Offline
Paar Fragen. Mußt sie nicht ausschweifend beantworten, Stichpunkte reichen sicher, da ich glaube, das Prinzip zu verstehen, aber auch Namen dafür möchte;)
Field autoA:TAuto
Field autoB:TAuto
Was ist der genaue Prozess, der hier abläuft bzw. beschrieben wird?
'erzeuge die Autos
autoA = New TAuto(-200, 200)
autoB = New TAuto
Die vorher im Field benannten Autos werden jetzt erst erzeugt?
Method OnUpdate()
'Autos bewegen
autoA.Update()
autoB.Update()
End Method
Warum wird hier nicht gleich die Updaterate eingetragen?
Weil dies eine Klasse für sich ist, die insgesamt beschreibt, was passieren soll? Die genaue Ausführung sind dann eigenen Klassen?
Class TAuto
'Eigenschaften einer jeden Instanz von TAuto
Field x:Int, y:Int
Field breite:Int = 180
'Geschwindigkeit horizontal/vertikal
Field dx:Int = 3, dy:Int = 0
Field farbeR:Int, farbeG:Int, farbeB:Int
Was meint hier jeweils das Int? Initiiere?
'wenn man "new TAuto(x,y)" aufruft:
Method New(x:Int, y:Int)
Self.x = x
Self.y = y
'setze die farben jeweils zufaellig rot = 100-255, gruen ... blau ...
SetzeFarbe(Rnd(100, 255), Rnd(100, 255), Rnd(100, 255))
End Method
Was meint das Self.?
Warum „setze“? Also deutsch? Hast Du das selber definiert?
Alles in allem verstehe ich das.
Aber ob ich das jetzt umsetzen könnte?
Na, vielleicht denke ich mir mal eine Aufgabe aus.
Oder hast Du eine parat?
Offline
Field autoA:TAuto
Hier teilen wir dem Kompiler (und Leser) mit, dass die umstehende Klasse eine Eigenschaft "autoA" hat... und diese ist vom Typ "TAuto" (sie koennte auch vom Typ "Int" oder "String" sein). Dadurch hat dann jede Instanz der Klasse die Eigenschaft "autoA" und kann auf die Eigenschaften von TAuto (und den spezifischen Eigenschaften von autoA) zugreifen.
Wir koennten schon dort die Autos erzeugen, also
Field autoA:TAuto = new TAuto(-200, 00)
Manchmal erzeugt dies auch mehr Uebersicht, manchmal aber ist ein zentraler Ort (vorallem, wenn man von einer anderen Klasse "erbt", also "class TMeinTyp extends TAndererTyp") die bessere Loesung. Notwendig ist es, wenn bei den Parametern Variablen genutzt werden (bspweise "jedes Auto ist 10 Pixel weiter rechts als das zuvor").
Warum wird hier nicht gleich die Updaterate eingetragen?
Du meinst, warum ich nicht autoA.Update(x) aufrufe, um der Methode "Update()" von autoA mitzuteilen mit welchem Wert es zu arbeiten hat?
Falls ja:
Man kann alle "Update()"-Methoden so schreiben, dass sie einen "delta"-Parameter erwarten (delta = Zeit seit letztem Update als Bruchteil der Updatefrequenz: 1.0 = eine komplette Zeit zwischen zwei Updates) oder andere Werte. Oder aber man laesst sie - so wie du richtig erkannt hast - "allgemeingefasst" und laesst die Methode selbst Dinge herausfinden.
Bei TVTower bspweise kann man mittels "GetDeltaTimer().GetDelta()" von ueberall den gerade gueltigen Deltawert ermitteln. Ein Vorteil ist es, weil wir nicht immer davon ausgehen koennen, dass wir Methoden veraendern koennen, wenn wir von anderen Klassen vererben. Bei BlitzMax muss die vererbte Klasse den gleichen "Funktionskopf" besitzen wie das Original. Wenn also "Fahrzeug" die Methode "Update(x:int, y:int)" haette, muesste die "Auto extends Fahrzeug"-Klasse auch "Update(x:int, y:int)" haben und duerfte nicht einfach einen neuen Parameter hinzufuegen. Bei Monkey koennte dies dank "Ueberladung" aber funktionieren. Eindeutig macht es dies aber in dem Fall nicht. Ich persoenlich finde die Ueberladung nur bei "Settern" (also Funktionen die Werte setzen) richtig praktisch, da man da bequem fuer Dritte Sachen bereitstellen kann (SetPos(point), SetPos(x,y), SetPos(rect), ...).
-
Falls Du aber meintest, wieso ich dort nicht den Befehl "SetUpdateRate(15)" ausfuehre?
Das jedes mal zu machen, wuerde einen ziemlichen Rattenschwanz mit sich ziehen. Auch wissen wir ja nicht, ob sich da nicht intern ein Zaehler 0 setzt, oder was da noch passiert. Das ist eher ein Befehl um etwas zu Initialisieren, aehnlich einem "StarteGrafikModus()"-Befehl.
@Was meint das Int.
Ich dachte das haette ich erwaehnt. Int steht fuer "Integer".
Int ... Integer, Ganzzahlen (-5, 3, 0 ...)
Float ... Fliesskomma (1.11012, -121.22, 0.0)
Double ... groessere Fliesskommazahlen (13423423432.2342)
Long ... groessere Ganzzahlen
String ... Textzeilen ("abc", "dadgtt r g dfgd~n~n" - letzteres sind zwei "Zeilenumbrueche")
Das sind alles von der Sache her "Klassen" (aber etwas anders umgesetzt, aus Geschwindigkeitsgruenden) die Funktionen haben (strings bspweise "ToInt()" ... ein "5".ToInt() erzeugt einen Integer mit dem Wert 5).
@self
Self sagt (das habe ich auch erklaert), dass die folgende Eigenschaft sich auf die der Instanz bezieht.
Global meineVariable:Int = 5
'ich schreibe immer "T" vor den Typ, auch wenn er hier "Class" heisst
'und man da auch ein "CAuto" drauss machen koennte :p.
'Notwendig ist das nicht.
Class TAuto
Field meineVariable:Int = 10
'Void besagt: es wird nix zurueckgegeben
Method Run:Void()
local meineVariable:Int = 20
Print "meineVariable: " + self.meineVariable
Print "meineVariable: " + meineVariable
Print "meineVariable: " + .meineVariable
End Method
End Class
Function Main()
Local auto:TAuto = New TAuto()
auto.Run()
End Function
@Warum "SetzeFarbe"
Ja wir haben ja die Methode "SetzeFarbe" selbst angelegt ... also selber definiert.
@Aufgabe
Erweitere das Autobeispiel um eine Klasse "TStrasse" - die kann sich ja sogar auch bewegen (wenn wir die Strassenmarkierung "bewegen"). also: graues Rechteck von links nach rechts, eigener "abstandX" fuer den Markierungsstart.
Das dient einfach dazu, dass du ein wenig mit den Klassen in Beruehrung kommst.
bye
Ron
Offline
Ups. Tschuldige, wenn ich Sachen frage, die wohl schonmal erklärt waren.
Irgend ist das wie mit Mathetexten, wenn mir die Gleichungen nicht schlüssig waren, verlor sich selbst normaler Text dann im diffusen.
Wenn ich jetzt Deine ersten Beispiele nochmal anschaue, ist mir da manches klarer, als zu Beginn.
Und manches bracuhe ich wohl auch einfach überdeutlich;)
Offline
Da fällt mir ein: Bin zwar wegen der Spielanleitung nicht mehr zu gekommen. Aber ich werde einfach 2 Bälle machen, die von den Bildschirmrändern zurückprallen und deren Geschwindigkeit sich beim Aufprall ändert.
Offline