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:
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.
- width = icon.width + text_rect.width
- 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.
- icon = RPG::Cache.icon("028-Herb04")
- text = "12x Herb"
- text_rect = icon.text_size(text)
- width = icon.width + text_rect.width
- height = [icon.height, text_rect.height].max
- sprite = Sprite.new
- sprite.bitmap = Bitmap.new(width,height)
- sprite.bitmap.blt(0,0,icon,icon.rect)
- 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.
- # The Sprite class for the loot animation
- class Loot_Sprite < Sprite
-
- # Ctor.
- # param icon_path Path to the icon file.
- # param name The icon name.
- # param viewport (optional) The sprite viewport.
- def initialize(icon_path,name,amount,viewport=nil)
- super(viewport)
- @icon = RPG::Cache.icon(icon_path)
- @text = "#{amount}x #{name}"
- @text_rect = @icon.text_size(@text)
- self.bitmap = Bitmap.new(@icon.width + @text_rect.width,[@icon.height, @text_rect.height].max)
- end
-
- # Update function.
- def update
- draw
- super()
- end
-
- private
- # Redraw content.
- def draw
- self.bitmap.clear
- self.bitmap.blt(0,0,@icon,@icon.rect)
- self.bitmap.draw_text(@icon.width,0,@text_rect.width,self.bitmap.height,@text,1)
- end
-
- # Restrict write access to the bitmap member.
- def bitmap=(bmp)
- super(bmp)
- end
- end
- # Timer Object class for async animation execution.
- class Loot_Timer
- # Ctor.
- # param tick_rate The rate to execute the timer operation in ms.
- def initialize(tick_rate=500)
- @tick_rate = tick_rate
- end
-
- # Sets the condition to stop the timer.
- # param proc Block parameter. Must return a boolean value.
- def condition(&proc)
- @condition = proc
- end
-
- # Code to be executed after timer finished.
- # param proc Block parameter.
- def on_finish(&proc)
- @finish = proc
- end
-
- # Executes the timer operation in a new green thread.
- # param proc The code to be executed on each tick.
- def exec(&proc)
- current = Time.now
- Thread.new do
- begin
- until @condition.call
- if (Time.now - current) * 1000 >= @tick_rate
- proc.call
- current = Time.now
- end
- end
- @finish.call unless @finish.nil?
- rescue Exception => e
- p e.message
- end
- end
- nil
- end
- end
- # The loot animation wrapper class.
- class Loot_Animation
- # Ctor.
- # param item_id The id of the item in the Game database.
- # param amount The amount of the item.
- # param tick_rate The timer tick rate.
- # raise RuntimeError If there is no Item for the given id.
- def initialize(item_id,amount,tick_rate)
- @item = $data_items[item_id]
- if @item.nil?
- raise("No such Item")
- end
- @tick_rate = tick_rate
- @amount = amount
- end
-
- # Executes the loot animation
- def exec
- sprite = Loot_Sprite.new(@item.icon_name,@item.name,@amount)
- sprite.x = $game_player.screen_x - (sprite.bitmap.width / 2)
- sprite.y = $game_player.screen_y - sprite.bitmap.height - 32
- sprite.opacity = 255
- timer = Loot_Timer.new(@tick_rate)
- timer.condition { sprite.opacity <= 0 }
- timer.on_finish { sprite.dispose }
- timer.exec do
- sprite.opacity -= 5
- sprite.y -= 1
- sprite.update
- end
- end
-
- end
- # Shortcut for call scripts.
- # Use "loot_animation(item_id,amount,tick_rate)" within a call script to execute an animation.
- class Interpreter
-
- # Constant for slow Timer tick rate.
- SLOW_TIMER = 50
- # Constant for medium Timer tick rate. (default)
- MEDIUM_TIMER = 10
- # Constant for fast Timer tick rate.
- FAST_TIMER = 1
-
- # Shortcut function for call scripts.
- # param id The item id from the Game database.
- # param amount The amount of the item.
- # param tick_rate (optional) The timer tick rate.
- def loot_animation(id,amount,tick_rate=MEDIUM_TIMER)
- Loot_Animation.new(id,amount,tick_rate).exec
- end
- end
Alles anzeigen