Beute anzeigen - Animation über RGSS (Oder: Wie lerne ich am Besten Ruby?)

  • Hallo zusammen,


    Kennt ihr das auch? Diese Lust nach langer Abstinenz wiedereinmal den Maker anzurühren? Genau so ging es mir und es macht schon wieder mächtig Spaß :)

    Soviel zur Einleitung. Ich möchte diesen Anfall von Kreativität und Schaffenslust dieses mal nutzen, um nachhaltig etwas dabei zu lernen.


    Wovor ich mich schon länger drücke ist dabei das Scripten mit Ruby. Grundsätzlich habe ich mal "programmieren" gelernt, im Studium etwas C und Java. Grundsätzlich verstehe ich damit auch den Ablauf einer objektorientierten Programmierung.

    Bei Skripten in Ruby komme ich aktuell allerdings auf keinen grünen Zweig, wohl auch dem geschuldet, dass ich seit mehreren Jahren nur noch VBA-Makros für Excel schreiben muss :D.


    Damit komme ich zu meinem Anliegen. Mein Ziel ist es, während ich an einem Spielchen bastele möglichst viel dabei zu lernen.


    Das geplante, erste "Skript" soll folgendes tun:

    Beim Aufrufen wird ein Text angezeigt, bestehend aus einer Zahl, einem Icon und einem Item Name.

    Dieser taucht an einer gewissen Position auf, steigt nach oben und blendet dabei aus, quasi eine kleine Animation beim looten, statt einer Messagebox.


    So könnte das z.B. aussehen


    zIeof9Thttps://imgur.com/zIeof9T


    Der "Ablaufplan" dabei:

    Bei Aufruf sollen drei Parameter übergeben werden : Anzahl, ItemID, sowie ein Variable zur Unterscheidung von Item, Weapon oder Armor.

    Über die ItemID wird der Name und das Icon aus der class item bzw. weapon oder armor abgefragt.


    Schlussendlich wird dann ein Window erzeugt (ohne Windowskin?), mit dem Text bestehen aus "Anzahl & "x" & ItemIcon & ItemName.

    Dieser wird bewegt und dabei die opacity verringert.


    Fertig.


    In meinem Kopf klingt das schlüssig, nur an der Umsetzung hapert es. da ich nichtmal richtig weiß. wie ich die Parameter übergebe, wie ich es sinnvollerweise aufrufen soll, etc. etc....


    Meine Bitte wäre nun:


    Kann mir jemand anhand dieses Beispiels etwas beibringen? Die Einträge in der Scientia kenne ich, aber ich weiß nicht so recht wie ich da sinnvollerweise an die Sache rangehe.

    Gerne auch in "Partnerarbeit", also durch schrittweises erarbeiten, ich will ja dabei was lernen:thumbup:


    Danke und Grüße

    noodelz

  • Heyey,

    also ich kann dir getrost sagen, dass du auf Scientia zum Teil verzichten kannst, da dieses leider nicht mehr weiter geführt wird (zumindest mein Stand) und du da auch nicht wirklich viel finden wirst. Da ist die Maker-Hilfe umfangreicher und weitaus Hilfreicher als Scientia^^"


    Zu deinem Problem(chen):


    Am einfachsten wäre es, wenn du das ganze über den Game_Interpreter und dessen Command fürs Ändern von Items laufen lässt, denn dort hast du alle nötigen Angaben (Object Item/Weapon/Armor und Anzahl). Dort musst du dann nur mehr dein eigenes Window (vermute ich mal dass du es so lösen willst) aufrufst, bzw. die Parameter übergibst um es dann aufgerufen zu bekommen.


    Falls du da weitere Hilfe brauchst, melde dich einfach bei mir hier im Thread, im Discord-Chat oder sonst per PN (:

    lg flipy

    Was für ne Signatur? Ich putz hier nur!

  • Welchen Maker verwendest du denn?
    ich habe ein Skript, das ich selbst benutze für mein Game und deinen Anforderungen gerecht werden könnte, sofern du den VX Ace benutzt

    10206480_m-1-1kopie_zpsf64aecc.png

    "No matter if you're mad, you're crazy or unwell.
    You might have noticed I'm not all there myself"

  • Hallo ihr beiden,


    Zunächst, ja ich verwende den RMXP, der ist mir von der Grafik immer noch der sympatischste.


    @FlipelyFlip : Ich habe mal versucht etwas in der Richtung zusammenzuschustern, allerdings nicht mit Window sondern per Bitmap.

    Ich stell das jetzt einfach mal hier rein und sage "Dat Ding macht ja garnix".


    Immerhin wird der Code ausgeführt ohne Fehlermeldung, es passiert nur einfach nichts.

    Wie gesagt, ich stehe da wirklich am Anfang und bin über jede Hilfe dankbar.


    Danke und Grüße

    noodelz

  • Der Post ist zwar schon etwas älter, aber da ich neu hier bin, ich aber in grauer vorzeit mal mein eigenes UI Framework für den RMXP gebaut hatte, kann ich einige Erkenntnisse zum Thema "Animation" beisteuern.


    Also zunächst mal: Was ist aus Sicht eines potentiellen Scripts eine "Animation"?


    Im Endeffeckt zeichnet das Programm Frame für Frame das zu rendernde Bild auf deinen Bildschirm. Der Maker geht dabei zyklisch vor. Das bedeutet, dass ein Animations-Script pro Rechenzyklus des Makers die Informationen zum Zeichnen deiner Erweiterung berechnen muss. Du programmierst also nicht die Animation selbst, sondern die zyklische Abweichung der Position und Sichtbarkeit deines Objektes. Der Maker selbst nennt die Steuerung dieser Zyklen "Scene". Die Scene wiederum enthält unter anderem sog. Sprites. Das sind komplexe Zeichenanweisungen, wenn du so willst. Aus Computergrafik Sicht würde man sagen, es handelt sich dabei um die Geometrie Daten deines Programms. Die Bitmap ist dann als Teil dieser Datenstruktur dein Zeichenblock. Sie enthällt also die Information der einzelnen Farbpunkte der zu zeichnenden Grafik.


    Warum erklärst du diesen Käse?


    Für das Erstellen einer Animantion ist es absolut kriegsentscheidend das Rendering Verhalten der gewünschten Zielplattform zu kennen, da gerade bei bewegten Bildern das Timing extrem wichtig ist.


    Wie sollte ich mein Animations-Script aufbaun?


    Zunächst musst du dir klar werden, welche Szene deine Animation bedienen soll, also, wenn du so willst, in welchen update Zyklus du dich reinhängen musst. In deinem Fall ist das trivial: Dein Spieler sammelt auf der Map ein Item. Also ist deine Scene "Scene_Map". Jetzt musst du deine Scene so erweitern, dass sie über Animationswünsche informierbar ist, sprich irgendeine schnittstelle erhällt, die die Objekte (Icon, Name, Anzahl) und ein von bis erhält, in etwa (in form von psoido code)#animate("Potion.png","Trank",1,{:y => 255, :opacity => 255},{:y => 0, :opacity => 0})

    Deine Scene sollte dann aus diesen Informationen ein Sprite erstellen und sich merken. (Es reicht ein Sprite, du kannst alle Bildpunkte in das eine Bitmap zeichen und so kannst du auch alles als ein Bild verschieben und/oder ausblenden)


    Hat sich deine Scene deinen Antrag gemerkt soll diese nun im update Zyklus den gewünschten Unterschied der Werte berechnen und an das erstellte Sprite übergeben. (Den Sprite#update Aufruf nach der Werteübergabe nicht vergessen). Wenn du das genau so machst, kommst du schnell an den Punkt, an dem dein Bild viel zu schnell verschwindet. Was macht man dagegen? Man verzögert. Sagen wir mal, du machst dir einen Timer, der nur alle n Zyklen die Werte inkrementiert/dekrementiert. Dann wäre "n" dein Stellrad für die Animationsgeschwindigkeit. Ich beforzuge im Maker jedoch eine Lösung, die mich eher das Zeitverhalten steuern lässt. Das geschieht mit Hilfe von in etwa Graphics.frame_count / Graphics.frame_rate Dies gibt dir die ungefähre Anzahl an Sekunden, die dein Spiel seit dem Start gelaufen ist. Wenn dir die Einheit "Sekunden" zu groß ist, kammst du beispielsweise auch durch die halbe Frame-Rate teilen, u.s.w. Wie dem auch sei, deine Scene Updated jetzt nicht mehr das Sprite direkt, sondern einen Timer und wenn der entscheiden "Jetzt ist es an der Zeit", dann ändert dieser das Sprite. Sobald dein Sprite die gewünschten werte hat, kannst dus löschen (Sprite#dispose) und deiner Scene mitteilen "Das gibts nicht mehr".


    "Kleiner" Ausschnitt


    Zur kleinen Hilfestellung häng ich mal den Kern der Animationen aus meinem alten Framework an. ACHTUNG! Das ist kein vollständiges Copy/Paste Script, sondern nur ein Ausschnitt eines sehr viel komplexeren Scripts und soll lediglich der Orientierung dienen. (Btw. ist das wirklch alt. Kann also sein, dass der Code nicht der schönste ist)


    LG

    Agy

  • Hallo agenty,


    Vielen Dank für deine Erklärung, ich denke so grob habe ich auch verstanden wo ich da einhaken muss.

    Syntaxtechnisch wird's für mich aber dann schwieriger. Für meine ersten Gehversuche in Ruby muss die Verbindung mit der Scene_Map noch garnicht bestehen, ich würde gerne erstmal lernen wie ich auch in einem überhaupt leeren Projekt etwas anzeigen kann (Einfachstes Beispiel, ein Icon oder ein Picture auf einer beliebigen Stelle des Bildschirms).


    Erste Schritte wären also:

    -Erstelle ein neues Spite, von der Größe so, dass alles hinheinpasst

    -Für den Text, der die dazugehörige Bitmap füllt brauche ich eine draw_text function

    -Für das Icon muss ich irgendwie an die Bilddaten kommen


    Wenn ich die Tage nochmal dazukomme, versuche ich an dem Thema weiterzumachen, ich lerne hier gerne dazu, stehe aber wirklich (wirklich!) noch am Anfang. Deswegen lieber einen Schritt früher noch erklären.


    Danke und Grüße


    noodelz

  • Sehr löblich von dir, dass du selbst lernen willst wies geht, ich geb dir gerne eine kleine Starthilfe für dein erstes Script =)


    Also als erstes solltest du dir das mal durchlesen:

    https://www.ruby-lang.org/de/documentation/quickstart/

    Das ist zwar für eine erheblich neuere Ruby Version als im maker, aber das feeling bei der Syntax bleibt das selbe.


    Dann: Der Maker hat ein Hilfe File, i.d.R. kannste das mit F1 aufrufen. Da haste dann ein Suchfeld, da kannste die Namen der Klassen eintippen, für die du Methoden suchst.

    Bei dir sind das:


    • RPG::Cache
    • Sprite
    • Bitmap

    Für deine ersten Schritte:


    Sagen wir mal du hast ein Icon in dem Icon-Ordner deines Spiels, oder nimmst eines aus dem RTP. Dann ist RPG::Cache.icon dein Freund. Lass und mal eines aus dem RTP nehmen. Zunächst speichern wir das in einer variablen und erhalten dafür eine Instanz der Bitmap Klasse. Das brauchen wir, weil wir ja mit der Höhe und der Breite weiter rechnen wollen.

    icon = RPG::Cache.icon("028-Herb04")


    Als nächstes machen wir das selbe mit dem Text, erstmal als einfacher String. text = "12x Herb". So nun wollen wir auch dafür den Platzbedarf bestimmen. Jetzt könnten wir natürlich hergehen, die Zeichen zählen und anhand der Font-Größe das ganze ausrechnen. Gut nur, dass die Klasse Bitmap bereits eine Methode genau dafür hat. Aber wo bekommen wir jetzt ein Bitmap Objekt her? Ah, wir haben doch das Icon als Bitmap vorliegen.

    Nutzen wir doch das, um ein sog. Rect zu erhalten, in dem unter anderem die Breite und die Höhe des Platzbedarfs drin stehen. text_rect = icon.text_size(text)


    So, jetzt haben wir den Platzbedarf für das Icon und für den Text. Jetzt gehts daran, den gesamten Platzbedarf zu bestimmen. In unserem Fall soll der Text rechts neben dem Icon stehen. Das bedeutet, dass wir als Gesamtbreite die Summe beider Breitenangaben brauchen. Die Höhe dagegen ist was anderes. Wir haben nur eine "Zeile". Da jetzt aber Icon und Text unterschiedlich groß sein können, müssen wir hier das Maximum der beiden Höhen nehmen.

    Code
    1. width = icon.width + text_rect.width
    2. height = [icon.height, text_rect.height].max

    Jetzt haben wir endlich den gesamten Platzbedarf dessen, was wir zeichnen möchten. Daher können wir uns nun daran machen, das Sprite zu erstellen. sprite = Sprite.newDieses Sprite braucht als erstes ein Bitmap, auf dem wir malen können. Wie groß unsere Zeichenfläche ist, haben wir ja bereits berechnet. sprite.bitmap = Bitmap.new(width,height)

    Zwischenstand: Wir haben ein Sprite mit einer Zeichenfläche, die so groß ist, wie unser Platzbedarf. Was fehlt noch? Das Einzeichnen des Icons und des Textes. Fangen wir mal mit dem Icon an. Dazu nutzen wir die Methode "blt" aus der Bitmap Klasse. Das Icon steht ganz links (x = 0, y = 0) und benötigt ein Rechteck, das so Groß ist, wie der eigene Platzbedarf. Nur gut, dass wir das Icon als Bitmap haben, da können wir das Rechteck einfach anfordern.sprite.bitmap.blt(0,0,icon,icon.rect)Jetzt nur noch den text malen und wir sind durch! Aber auch dazu hat Bitmap eine eigene Methode, nämlich "draw_text". Beim Icon war die Positionierung ganz einfach, da wir das ganz links oben einzeichnen. Wo kommt jetzt der Text hin? In X-Richtung an die Stelle, wo das Icon aufhört, in Y-Richtung an die Stelle 0. Dadurch erscheint der Text rechts neben dem Icon. Aber wieviel Platz reservieren wir dafür? In der Breite ist das klar, so viel wie unser Text halt braucht, in der Höhe nehmen wir einfach die Gesamt-Höhe unserer Zeile. Wir wollen nämlich den Text noch so ausrichten, dass er vertikal und horizontal zentriert wird. Horizontal passiert ja schon dadurch, dass wir nicht mehr Breite als Platzbedarf zur Verfügung stellen, vertikal ergibt sich das daraus, dass wir dem Zeichenbefehl mitgeben "Text bitte zentrieren". Das ist einfach eine 1 als letzter Parameter. So viel zu den Überlegungen. Jetzt wissen wir, was wir machen wollen, lass es uns noch umsetzen. sprite.bitmap.draw_text(icon.width,0,text_rect.width,height,text,1)


    Und schon haben wir das Dingens gemalt. Jetzt schauen wir uns doch nochmal den ganzen Code an. Das war sehr viel Geschwafel von mir, für sehr wenig Code. Daran sehen wir dann auch, dass das Ganze eigentlich nach den reichlichen Überlegungen recht simpel ist.

    Code
    1. icon = RPG::Cache.icon("028-Herb04")
    2. text = "12x Herb"
    3. text_rect = icon.text_size(text)
    4. width = icon.width + text_rect.width
    5. height = [icon.height, text_rect.height].max
    6. sprite = Sprite.new
    7. sprite.bitmap = Bitmap.new(width,height)
    8. sprite.bitmap.blt(0,0,icon,icon.rect)
    9. sprite.bitmap.draw_text(icon.width,0,text_rect.width,height,text,1)

    Ich hoffe die Anleitung war verständlich genug, wenn nicht, frag ruhig nach.


    LG

    Agy


    P.S.: Nachtrag


    Ich hab mal zum Spaß kurz deine ganze Anforderung in ein Script "gehackt". Das ist aus vieler lei Sicht nicht schön, aber vor allem, weils an dem Maker Konzept mit den Szenen und synchronen update Zyklen vorbei schifft. Dafür braucht man aber Scene_Map nicht anfassen. Ich empfehle, dass dus erstmal zu lernzwecken selber versuchst, aber wenn du garnicht weiter kommst, dann hast du was zum spicken.


    Dieser Beitrag wurde bereits 5 Mal editiert, zuletzt von agenty ()

  • Hallo agenty,


    Vielen Dank für deine ausführlichen Beitrag. Bin leider nicht eher dazu gekommen am RGSS zu üben, dickes Sorry dafür (Pixeln üben ging vor ?()

    Den Code hab ich folgendermaßen ausgeführt:

    Der Befehl sprite.bitmap.blt ist mir allerdings nicht ganz klar. Sobald ich die x/y Werte darin zu groß einstelle wird gar nix angezeigt, bei z.B x=y=10 sehe ich, dass Icon und Text ein Stück nach unten gerutscht sind, jedoch abgehackt werden. Könntest du mir den Befehl nochmal genauer erklären? Die Maker-Hilfe dazu war leider auch nicht sehr aussagekräftig.


    Desweiteren verschwindet das Icon und der Text nach kurzer Zeit, ich nehme an das hängt irgendwie mit der Speicherverwaltung des Rpgmakers zusammen?


    Ich würde mich als nächste Aufgabe mal daran versuchen die Bitmap durch die Gegend zu schieben.


    Danke dir und Grüße


    noodelz

  • Also erstmal:


    Dein Bitmap hat eine eingestellte Breite, in deinem Fall "width". Die entspricht der Bildbreite plus der berechneten Textbreite. Sowie eine Höhe (der max Wert). Stell dir das wie deinen Zeichenblock vor. Wenn du da zu weit links malst, dann malst du auch deinen Tisch an, aber in deinem Bild wird das nicht zu sehen sein. So verhält sich das auch mit deinem Bitmap. Du malst der Reihe nach Farbpunkte rein. Wenn du an eine Stelle, an der schon was ist, einen neuen Farbwert setzt, hast dus überschriebn.


    Zu Bitmap#blt


    blt malt ein bild in ein anderes rein, oder noch genauer:


    Die Farbwerte des angegebenen ausschnitts (x,y,witdht,height) (in deinem Fall icon.rect) des einzuzeichnenden Bitmaps (in deinem Fall icon) werden beginnend an der stelle (x, y) (in deinem Fall (0,0)) in die Zielbitmap übernommen.


    Jetzt haben wir aber die ganzen dimensionen so berechnet, dass es ein genauer match ist, wir wollen also garnicht die einzelnen Teile rumschieben, sondern das ganze.

    Selbe Analogie zum Zeichenblock: Du hast ein Bild gemalt, da ist ein Baum und eine Katze drauf. Das Bild ist ganz toll geworden und du hast es aufgehängt. Du trittst einen Schritt zurück und schaust es dir an und entscheidest "das Bild hängt zuweit Oben". Würdest du die Katze und den Baum aus dem Bild ausschneiden und tiefer wieder ankleben, oder würdest du den Nagel rausziehn und tiefer erneut einschlagen?


    Kurz um: Willst du das ganze Ding verschieben, packste die Koordinaten von sprite an, da gibts auch n x und n y.


    Zum mystischen Verschwinden


    Der Maker berechnet zyklisch die auf den Bildschirm zu übertragenden Bilder. Wenn jetzt dein Sprite nicht regelmäßig sagt "hallo, ich bin auch noch da!" dann wirds weggeräumt. Darum hat das Ding ne update methode.

    Und genau desswegen habe ich dir am 17.03.2018 den Rendering zyklus nahegelegt ^^.


    LG

    agy