Archiv verlassen und diese Seite im Standarddesign anzeigen : [VX-Ace] Mein versuch einer HitBox für ein Zelda KS
Da mir das ewige Variablen gestelle zu Zeitaufwendig wurde, fing ich an einfache RGSS Zeilen zu lernen und in den
Eventscriptbefehlen zu nutzen, leider war dies auch noch nicht gut genug, deshalb hab ich nun meinen ersten Prototypen
einer Eventbefehl "Script" Trefferabfragenbox für hunderte Gegner entworfen.
Was haltet ihr davon, wie würded ihr es machen? Eigentlich bin ich ja nur Eventer und kann noch nicht Scripten da ich die Sprachen nicht kann.
Benutzt wird es als Common Event ohne Trigger, das von Geschoss Events bei Bedarf aufgerufen wird. Dabei ist es egal welche Event ID so ein Geschoss hat.
Der Eventbefehl Script ist klasse seit sie mehr Zeilen möglich gemacht haben.
#----------------------------------------------
#Hit_Box Version1.0 16.06.2014 by Bex
#----------------------------------------------
evid_min = 1
evid_max = 10
#----------------------------------------------
until evid_min > evid_max
if $game_map.events[evid_min] != nil
if Math.sqrt(($game_map.events[evid_min].screen_x -
$game_map.events[@event_id].screen_x)**2 + ($game_map.events[evid_min].screen_y -
$game_map.events[@event_id].screen_y)**2) <= 20
if evid_min != @event_id
$game_self_switches[[$game_map.map_id, evid_min, 'A']] = true
end ; end ; end
evid_min += 1
end
angefangen hatte ich mit einen simplen Loop der schaut ob die Events existieren, damit das Spiel nicht abstürzt falls die mal nicht existent sind.
evid_min = 1
evid_max = 10
until evid_min > evid_max
if $game_map.events[evid_min] != nil
$game_message.add("This Event exist")
else
$game_message.add("This Event isnt existing")
end
evid_min += 1
end
_______________________________________________________
ToDo:
+Verschieden grosse Geschosse und Gegner ermöglichen
Den Umweg über Wurzel und Potenz musst du denke ich gar nicht gehen, es reicht auch:
($game_map.events[evid_min].screen_x - $game_map.events[@event_id].screen_x).abs
abs bildet den Absolutwert der Zahl.
Ja da hasst du völlig recht. Ich hatte die Kreisform genommen, falls ich später flächenschaden einbauen will,so das der dann rund ist und nicht quadratisch.^^
Mir gefiel halt das das jeweilige Event das das Comon Event aufruft automatisch als Geschoss eingeordnet wird.
Was genau soll das Script tun? Es wäre sehr nützlich falls du das zuerst beschreiben würdest.
Das Script schaut ob eines der Events mit der ID 1 bis z.B 200 von dem aufrufenden Event getroffen wurde.
In der Regel bewegt man sein Event ganz schnell über die Karte und ruft nach jedem Schritt einmal das Common Event auf, das schaut
ob ein Event getroffen wurde, auf dem Map Tile. Nur halt mit Pixelkoordianten, damit die trefferabfrage auch reibungslos funktioniert.
Die Frage ist jedoch was "getroffen" bedeutet.
Wie ist "getroffen" definiert? Über die Größe der verwendeten Character-Grafiken? Über die Tiles auf der Map? Über irgendeine arbiträre Nummer?
Ah ok,
also als getroffen gilt jedes abgefragte Event das sich im Radius von 20Pixeln auf der Pixelkoordinate des sich bewegenden 32x32 Charsets befindet zum Zeitpunkt des aufrufs.
Wenn das Event also nicht NIL ist und es sich im angegebenen Eventradius befindet und es nicht selber das Geschoss ist, dann wird das Event als getroffen makiert
und der Self SwitchA aktiviert vom getroffenen Event.
Sobald das System wächst müssen je nach Aufbau weitere Abfragen und Werte ergänzt werden.
Edit1: Sollte ich z.B charsets grösser als VX standard grösse abfragen wollen, so müsste ich die Trefferbox anpassen.
Edit2: Ja grössere Gegner wären schon cool, werde es wohl nochmal anpassen sobald ich ein Self Variablen Script einfüge.
Das ist schoneinmal ein wenig näher, aber immer noch nicht ganz genau.
Immerhin wird das Geschoss wohl auch eine Größe besitzen; wenn du sagst "innerhalb von 20 Pixeln", dann muss klar sein ob du damit meinst, ob der Mittelpunkt des Geschosses sich nicht mehr als 20 Pixel von einer der Kanten des Ziels befindet, oder ob sich die nächstliegende Kante des Geschosses nicht mehr als 20 Pixel von einer der Kanten des Ziels entfernt ist.
Immerhin sind beide Events ja nicht Punkte sondern Quadrate.
Es stellt sich natürlich die Frage, ob es auf dem Ace überhaupt einen Unterschied macht, ob man die Event-Koordinaten oder deren Umrechnung in Pixelkoordinaten nimmt. Das hängt maßgeblich davon ab, wie und wann die Pixelkoordinaten bestimmt werden. Auf den alten Makern sollen die Pixelkoordinaten schon nach "halben" Schritten bestimmt werden, d. h. sie sind etwas genauer als die Event-Koordinaten. Aber ist das auf dem Ace genauso?
@Cornix
Ich gehe mal davon aus, dass Bex, so wie es auf den alten Makern üblich war, nur von Events spricht. D. h. Geschosse und Ziele haben alle eine 32x32-Hitbox, sprich das Tile, das sie einnehmen.
Es werden die Bildmittelpunkte verrechnet und die entfernung zueinander als abstand abgefragt..
Die Gegner haben bei dieser Rechnung nur ihre Bildmitte. Oder du kannst dir aussauchen ob das Geschoss oder das Event eine Kugel mit Radius 20Pixel ist und das andere nur ein Punkt.
Ich glaube ich weiss worauf du hinaus willst, aber dafür kenne ich glaube ich noch nicht die Formel zwei unterschielich grosse rechtecke zu vergleichen.
Das bisherige funktioniert wunderbar für das 32x32 Tilegrid. 2x .abs rechtecke wären gut für XP grösse.
Wie ich nun aber beiden eine grösse gebe und sie vergleiche? Wäre cool wenn du mir die Lösung sagst.
EDIT:
MAP X und Y springen um sobald ein Movecommand gegeben wurde, das heisst die Figur befindet sich optisch auf einem Feld obwohl sie es nichtmehr ist und umgekehrt. Screenvariablen verhindern diesen umstand. Bei sich schnell bewegenden Events immer Screenvariablen nehmen.Ansonsten frustest du deine Spieler mit Bugs.
Bei statischen objekten ruhig map x und y nehmen.
Edit: Kelven hat recht mit der Hitbox. (abstand 20 Pixel klappt am besten) Grössere Gegner die flach und lang oder hoch sind wäre natürlich noch wünschenswerter. Habe ja erst angefangen damit. Mal sehen wie man das System am besten erweitert.
ToDo
+Verschieden grosse Gegner und Geschosse
Es könnte aber sein, dass auch die Pixelkoordinaten auf dem Ace sofort springen.
Das weiss ich nicht ist aber irrelevant, da ein pixel und ein Tile(32Pixel) ja schon ein grösserer unterschied sind.
Auf jedenfall tritt der Bug das ein geschoss durch einen gegner fliegt und nicht trifft nur bei mapkoordianten auf, bei pixelkoordinaten
funktioniert es einwandfrei. (wurde auch schon von anderen mit dem selben ergebniss getestet--Info also bestätigt in vielen Tests^^)
Ich glaube ich muss dem Geschoss und dem Event eine Range geben, wie vergleiche ich die dann aber am besten?
bzw wie macht man das mit den quadraten, erster gedanke klingt noch sehr simpel, aber wie rechnet man das ohne ein Dutzend Conditional branches für die grössen? Weiss das wer von euch? (Keine lust im übertragenen sinne den Pytagoras neu auszurechnen^^)
Wie wäre es hiermit:
class Game_Interpreter
attr_accessor :dist
# Überprüft die Distanz zwischen 2 Events und speichert das Ergebnis in der Variable "dist" ab.
# Falls keine Argumente übergeben werden wird einfach die Distanz zwischen dem aufrufenden Event und der Spielerfigur genommen.
def getDist(event_a=getEvent, event_b=$game_player)
x1 = getX(event_a)
y1 = getY(event_a)
x2 = getX(event_b)
y2 = getY(event_b)
self.dist = Math.hypot(x1 - x2, y1 - y2)
end
# Gibt die X-Koordinate eines Events in Pixeln zurück.
# Falls kein Argument übergeben wird, wird die X-Position des aufrufenden Events verwendet.
def getX(event=getEvent)
return event.real_x * 32
end
# Gibt die Y-Koordinate eines Events in Pixeln zurück.
# Falls kein Argument übergeben wird, wird die Y-Position des aufrufenden Events verwendet.
def getY(event=getEvent)
return event.real_y * 32
end
# Gibt das Event mit der entsprechenden ID zurück.
# Falls kein Argument übergeben wird, wird dieses Event zurückgegeben.
def getEvent(id = self.event_id)
return $game_map.events[id]
end
end
Dieses Script oberhalb von Main einfügen.
Dann kannst du folgendes Event (am besten als Parallel Process) schreiben:
20563
Damit wird überprüft ob der Held innerhalb von 64-Pixeln zum aufrufenden Event ist.
Falls ja wird "HIT !!!" auf die Konsole geschrieben.
Vielleicht hilft dir das ja weiter.
Damit kannst du übrigens die Entfernung zu jedem beliebigen anderen Event abfragen.
Den Befehl Math.hypot finde ich sehr gut da er mir das quadrieren und wurzelziehen ersparren würde.
Gibt es irgendwo eine Auflistung mit den ganzen Math. befehlen die im Maker funktionieren?
Dein Script ist gut, da gucke ich mir gleich noch einiges ab.
Ich hatte aber die hoffnung das indem ich nun gleich aufeinmal z.B 200 bis 300 Gegner in einer Schleife durchlaufe in einem einzigen Scriptcall das das performance schonender ist als den Maker
200bis 300 mal im selben Frame den Scriptcall ausführen zu lassen. (So hab ich nur einen Scriptcall direkt vom Maker. Bei den Events fing er an einzubrechen wenn man dann noch nen Tint Screen nutzte oder etwas mehr Bewegung drin war. Hatte deshalb den Befehl schon nichtmehr jeden Frame aufrufen lassen, sondern nur wenn es nötig ist einmal wenn es sich bewegt hat oder vieleicht nochmal irgendwie dazwischen jenachdem wie schnell das geschoss ist.
Deshalb jetzt meine rangehensweise mit der "Hit Box".
Auf eine gute Performance solltest du sowieso nicht hoffen. 200 könnte bereits eng werden, bewegt sich aber wahrscheinlich noch im Bereich des Möglichen.
Idealerweise solltest du alle Events die als Projektile fungieren in einer globalen Liste abspeichern und dann periodisch über die Einträge dieser Liste iterieren.
Eine weitere Frage ist, ob nur der Spieler treffbar sein sollte oder mehrere Events auf der Karte.
Falls es mehrere Events gibt, welche getroffen werden können, und KEIN friendly-fire existiert könnte es sich auch lohnen separate Listen für Geschosse vom Spieler und Geschosse von Feinden zu führen.
MOGs Anti Animation Lag (Kein Anti Lag Script, da hat er nen extra, was ich aber nicht nutze)
ist genial es behebt den fehler das bei normalen Animationen der Held oder Events stottern und lagen oder das 2oder mehr Animationen auch schon laggen.
Diesen Fehler behebt das Script. (Glaube Enterbrain hat das immer noch nicht gefixed)
Zusätzlich erlaubt es auch mehr als die normal möglichen 200 sich bewegenden Events ohne Lag zu haben +Tintscreen und Animationen gleichzeitig.
Frames gehen etwas runter aber alles läuft trotzdem flüssig. (GeilesTeil^^kann ich nur empfehlen) Ist aber momentan nicht eingebaut, kommt sobald es an die Trefferanimationen geht.
Deshalb auch die frei einstellbare anzahl der GegnerIDs die geprüft werden.
Ich will keine festen Gegner einbauen, ich will ein Self Variablen Script nutzen und für jeden Gegner eine Initialisierungseventseite festlegen auf paralell prozess, die einmalig im spiel abläuft. Beim Makern soll der User oder Ich halt dort die Werte für die Gegner eingeben können (HP,MP,Stärke,Def,Elemtgedöns vieleicht,Schwächen etc...),all diese Werte werden in Self Variablen gespeichert die Hit Box teilt dann gleich den Schaden mit aus.(Edit: Ich weiss eine extra Seite pro Event ist nicht so toll für die performance wenn ich ans Limit will, ich wollte aber damit leben und ich glaube die eventseiten werden eh von hinten nach vorne abgefragt, wo es dann keinen unterschied macht ob es die seite gibt oder nicht).
Sprich man hat 1xCommon Event 1xEvent Gegnervorlage ?xBeispielgegner Viel Spass beim Gegner erstellen. (Da muss aber noch sovieeeel bedacht werden^^ deshalb auch der Ansatz mit diesem einem Thread erstmal, wollte diese AKS version sozusagen diesmal mit der Hit Box beginnen)
Kein Script der Welt wird dir helfen, dass Ruby eine interpretierte Sprache ist und von Natur aus langsamer als kompilierte Sprachen sein wird.
Natürlich, es gibt Scripte um all die vielen Fehler von Enterbrain auszubessern, aber dennoch wirst du ab einem gewissen Punkt um die Performance kämpfen müssen solange du nicht das ganze System umschreibst.
Was ich mit der Liste meinte war sicher nicht gemeint, dass die Gegneranzahl fest ist. Ich meine damit lediglich eine globale Liste, in welche alle Geschosse nach ihrer Erstellung eingefügt werden.
Anstatt dann über alle Events iterieren zu müssen kannst du sofort über alle Geschosse iterieren und die Performance dadurch möglicherweise stark verbessern (abhängig von der Anzahl von Nicht-Geschoss-Events auf deiner Karte).
Dafür bin ich dann aber doch wieder zu Sprachunkundig und sollte erstmal einige Ruby Kurse Lesen^^.
Oder ich mach erstmal weiter mit den mitteln die ich habe und schaue was ich von eurem Begreife und abschauen kann, hab ich momentan am meisten lust und motivation zu.
Mir fehlt noch das wissen -Ranges(1..10)- funktionierend einzubauen(das gelang mir schon einmal bei einer Sache)oder halt wie ich teile des event namens
auslese um bestimmen zu können welches event was ist und um das dann irgendwie in den string oder heisst es float? einzufügen.
Und schon könnte man richtig Scripten was man will. ^^Was ich aber noch nicht kann und auch nicht werde in nächster Zeit.Deshalb kann ich deinen Vorschlag nicht umsetzen.
Und ich versuch dann lieber mit euer hilfe was zu bauen als euch nach fertiglösungen zufragen wo ich/andere bei jeder kleinen Änderung hilfe brauchen,.
Deshalb ist es praktisch die dinge die ich will mit diesem event script misch masch zu erstellen. so bin ich sehr flexibel wenn ich was ändern will oder ergänzen möchte.
Edit: Ich will später wohl um die 50 Gegner. Wenn mehr laufen wären 100 auch toll. Wenn man weiss 200-400 würden auch laufen, so hat man
bei 50 Gegnern noch etwas performance Reserve. (Und ein gutes Gefühl weil man es ausprobiert hat wo die Grenzen liegen bei den einzelnen performance fressern, auch kann man dann je nach effekten auf den maps variieren mit der anzahl).
Du kannst einfach folgende Zeile verwenden:
getEvent.getName
um den Namen eines Events abzufragen. Das kannst du so in einem Script im Event-Code verwenden.
Zum Beispiel:
getEvent.getName.include?("[Bullet]")
könnte in einem Conditional-Branch verwendet werden um zu testen ob "[Bullet]" als Teilstück in dem Namen des Events vorkommt.
Bevor du dies aber verwenden kannst musst du noch folgendes Script oberhalb von Main einfügen:
class Game_Event < Game_Character
def getName
return @event.name
end
end
Cool Danke, das kann ich gut brauchen. (Wenn nicht fürs AKS dann bestimmt woanders für)
Ich müsste nun aber beim Map Start all jene Events in einen Float packen wenn die den Namen haben, oder? (ev1, ev3, ev5) Wie würde das gehen, magst es mir verraten wo du mich nun neugierig gemacht hast? :)
Edit: Was bedeuted das?
class Game_Event < Game_Character
Wieso muss die kleiner sein? Warum überhaupt? Kannst du mir das erklären was es da mit der Klasse auf sich hat?
Edit: Bestimmt eine der dümmsten fragen^^ aber ich wills wissen, hab mich schon so oft im scriptordner über sowas gewundert :)
Edit2:
Dein Entfernungsscript was du oben gepostet hattest, enthält keine Varierbare grösse für Geschoss und Event.
Ich hab mir überlegt bisher hatte nur das Geschoss eine Range von 20 Pixeln, Wenn jetzt ein char auch aus mehr als dem mittelpunkt bestehen soll
(erstmal auch rund wie das geschoss) dann brauch der auch ne Range wie das Geschoss. Nur wie verrechne ich die nochmal, hab grad ne Blockade
und komme nicht drauf.
Edit: Die Event Range auf die Range des Geschosses drauf rechnen? Ok das erklärt runde objekte.
Edit2: Wie handhabe ich dann rechtwinklige (nicht immer quadratische) geschosse mit width und height?
Also wie macht man da fehlerfrei/bugfrei dann die Abfrage mit den Ranges oder Schnittpunkten? (Das würde mich sehr interessieren)
Cool Danke, das kann ich gut brauchen. (Wenn nicht fürs AKS dann bestimmt woanders für)
Ich müsste nun aber beim Map Start all jene Events in einen Float packen wenn die den Namen haben, oder? (ev1, ev3, ev5) Wie würde das gehen, magst es mir verraten wo du mich nun neugierig gemacht hast? :)
Ich glaube du verwechselst etwas.
Als "Float" bezeichnet man eine Kommazahl. Das ist eine Abkürzung für "Floating Point Number", also den englischen Begriff für Fließkommazahl. (Nur am Rande: das gegenstück dazu ist eine Fixkommazahl)
Wahrscheinlich willst du Events in eine Liste packen nehme ich an.
Eine Liste wird in Ruby folgendermaßen definiert:
$someList = [a, b, c]
wobei "someList" der Name der Liste ist und a, b und c irgendwelche Objekte wären.
Das Dollarzeichen ($) gibt an, dass die Liste global sichtbar ist, also überall benutzt werden kann. Kein guter Programmierstil, aber für einen Anfänger am einfachsten.
Wenn du zum Beispiel alle Objekte, welche im Namen den Teilstring "" enthalten in eine Liste ablegen willst kannst du folgendes tun:
$someList = []
for event in $game_map.events
if event[1].getName.include?("[Bullet]")
$someList.push(event[1])
end
end
Das könntest du, zum Beispiel, in ein Auto-Start Event stecken.
Mit diesem Script kannst du dann die Liste ausgeben lassen:
for event in $someList
p(event.getName)
end
[B]
Edit: Was bedeuted das?
class Game_Event < Game_Character
Wieso muss die kleiner sein? Warum überhaupt? Kannst du mir das erklären was es da mit der Klasse auf sich hat?
In Ruby bedeutet dies, dass die Klasse Game_Event von der Klasse Game_Character erbt.
Polymorphismus nennt man das Konzept dahinter und es ist ein wichtiger Grundbaustein der Programmierung, allerdings nicht trivial zu verstehen für einen Anfänger.
Du wirst das nicht brauchen denke ich, aber falls du es dennoch lernen willst dann suche im Internet nach "Vererbung" oder "Polymorphie" im Zusammenhang mit Programmierung.
Edit2:
Dein Entfernungsscript was du oben gepostet hattest, enthält keine Varierbare grösse für Geschoss und Event.
Ich hab mir überlegt bisher hatte nur das Geschoss eine Range von 20 Pixeln, Wenn jetzt ein char auch aus mehr als dem mittelpunkt bestehen soll
(erstmal auch rund wie das geschoss) dann brauch der auch ne Range wie das Geschoss. Nur wie verrechne ich die nochmal, hab grad ne Blockade
und komme nicht drauf.
Edit: Die Event Range auf die Range des Geschosses drauf rechnen?
Das Entfernungsscript verwendet keine Entfernung, völlig richtig. Die Entfernung habe ich im Event verwendet, und zwar wie folgt:
getDist
@size = 64
if dist < @size
damit wird überprüft ob die Entfernung zwischen Event und Spieler kleiner ist als 64 Pixel.
Du kannst hier jeden beliebigen Wert verwenden, und zwar für jedes Event etwas anderes.
Alternativ kannst du auch eine Methode definieren um die Größe direkt zu vergleichen:
def isWithinRange(size)
getDist
return dist < size
end
Dann kannst du im Event, innerhalb des Conditiona-Branch, einfach
isWithinRange(64)
schreiben wenn du willst, dass eine Entfernung von mindestens 64 Pixeln überprüft werden soll.
Ist jetzt zwar nicht wirklich hilfreich, aber ich finde den Java-Einfluss in Cornix' Code gerade unerträglich :D
Ruby besitzt so genannte Iteratoren, mit denen sich "for x in y" (das intern meines Wissens sowieso nur Enumerator#each aufruft) und oft auch while-Schleifen ersetzen lassen:
Wenn du zum Beispiel alle Objekte, welche im Namen den Teilstring "[Bullet]" enthalten in eine Liste ablegen willst kannst du folgendes tun:
$someList = []
for event in $game_map.events
if event[1].getName.include?("[Bullet]")
$someList.push(event[1])
end
end
könnte man in "schönem Ruby" beispielsweise auch so schreiben:
$someList = $game_map.events.select { |key, value|
value.getName.include?("[Bullet]")
}.values
Danke für die schnelle Antwort, da hab ich nächstes mal viel zu testen und nachzulesen. Wo man nun langsam die Grundbegriffe kennt sollte ich vieleicht doch mal mit den Ruby Kursen nebenbei anfangen.
Gibt ja die in der Science Wiki beim Studio einige sowie Codecademy aber kennst du ein noch besseres Tutorial für Ruby simpel einfach schnell lernen von 0 auf 100?
Danke nochmal für die ganzen Informationen.
Edit: Cepanks, du machst mich neugierig, wo und wie lernt man so eine saubere Ruby Sprache?
(Ich hatte bisher auch die for und until methode genommen weil ich mit den schreibweisen (wann/warum) der { } klammern noch nicht ganz bescheid weiss)
könnte man in "schönem Ruby" beispielsweise auch so schreiben
Das ist aber kein Clean Code! (besonders nicht für jemanden, der Ruby kaum kennt)
@Cepanks:
Man kann sich wahrscheinlich darüber streiten ob das wirklich schöner ist.
Alles Geschmackssache. Meiner Meinung nach war meine Variante für einen Anfänger einfacher zu verstehen weil mehr "Wörter" und weniger kryptische Symbole verwendet werden.
Cornix code ist leichter zu lesen, dafür versteht man bei ihm meist nicht warum er diese abfragen mit dem "kleiner als" auch so im code unterbringt.
getDist
@size = 64
if dist < @size
da kann doch die letzte Zeile einfach gelöscht werden oder? Oder ist das kein vergleich sondern wieder so ein vererbungs dingens?
Sollte ich wohl wirklich mal nachlesen. Aber wieso sieht es wie ein kleiner vergleich aus?
Nein, das ist dort tatsächlich ein Vergleich.
In Ruby wird das Symbol "<" für mehrere Dinge verwendet. Man sagt der <-Operator ist "überladen".
Jup ich brauch einen Awsome Ruby Kurs^^ Das klingt wie Chinesisch für meine Ohren :)
Ruby ist vielleicht auch nicht die einfachste Sprache zum anfangen.
Meiner Meinung nach gibt es zu viele Alternativen, wie man bereits in Cepanks Beitrag gesehen hat.
Du kannst den selben Effekt mit dutzenden verschiedenen Operatoren durchführen.
Für einen erfahrenen Programmierer ist das sicher sehr angenehm, für einen Anfänger aber sicher sehr verwirrend kann ich mir vorstellen.
Hallo, ich habe nun angefangen mich durch den Thread zu arbeiten.
Ich konnte dank euch nun nicht nur eine Range sondern auch gleich noch erfolgreich eine Liste einfügen.
Wobei ich euch wohl rund um die Liste eventuell die Tage noch etwas mit fragen zum verständniss löchern werde.
Ranges sind mir zwar noch viel vertrauter aber da ihr bisher so freundlich ward, begebe ich mich mal auf neues land und spiele mit der liste rum.
Ohne gross auf einfache einstellbarkeit zu achten habe ich folgenden stand nun:
for evid_min in [1,2,3].each #1,2,3 will ich durch die liste der jeweiligen map tauschen
if $game_map.events[evid_min] != nil
if Math.hypot($game_map.events[evid_min].screen_x -
$game_map.events[@event_id].screen_x , $game_map.events[evid_min].screen_y -
$game_map.events[@event_id].screen_y) <= 32
if evid_min != @event_id
$game_self_switches[[$game_map.map_id, evid_min, 'A']] = true
end ; end ; end
end
Wahrscheinlich willst du Events in eine Liste packen nehme ich an.
Eine Liste wird in Ruby folgendermaßen definiert:
$someList = [a, b, c]
wobei "someList" der Name der Liste ist und a, b und c irgendwelche Objekte wären.
Das Dollarzeichen ($) gibt an, dass die Liste global sichtbar ist, also überall benutzt werden kann. Kein guter Programmierstil, aber für einen Anfänger am einfachsten.
Ich hatte nun vor beim erstmaligen betreten der jeweiligen map die Initialisierungsseiten der einzelnen Gegner einmalig ablaufen zu lassen, damit die ihre werte in das self variablen script speichern.(Das sollte ohne probleme klappen)
Frage: Wie würde der Eventscriptbefehl ausschauen damit sich das event selber in die liste mit der id der aktuellen map ablegt, ohne einen Tag im namen zu verwenden und also mehrere listen für jede map id eine? (Das Event führt sich ja selber aus müsste also sowas wie: Gegnerlistevon"game map id"[].include this [@event.id]. (Erschlag mich nicht,das ist brainstorming^^und kein code)
Und zweitens, wie kann ich das Event wieder aus jener Liste entfernen? Bräuchte einmal den self befehl fürs event und interessanterhalber wie ich es von ausserhalb manipulliere.
Du sagst das mit dem Dollarzeichen ist unsauber, brauche ich das aber nicht um von ausserhalb drauf zu greifen zu können?
Und noch viel wichtiger bleibt diese Liste nach dem Speichern und neuladen des Spiels erhalten?
Und noch viel wichtiger bleibt diese Liste nach dem Speichern und neuladen des Spiels erhalten?
Die einfachste Lösung wäre, sie bei einer bestehenden Klasse als Variable einzutragen. Ich benutze auf dem XP dafür immer Game_Party. Das ist zwar nicht die sauberste Lösung, aber egal. ;)
Ah verstehe, also das $ Zeichen allein macht nicht das sie im maker mit gespeichert wird beim spiel speichern?
Die Variable muss also definiert sein und niedergeschrieben vorher im Scripteditor um gespeichert werden zu können beim Spiel Safe.
Wobei ich euch wohl rund um die Liste eventuell die Tage noch etwas mit fragen zum verständniss löchern werde.
Du kannst dir auch die Dokumentation in der Hilfe-Datei des Makers durchlesen.
Fälschlicherweise werden Listen in Ruby als Array bezeichnet, auch wenn sie keine Arrays im klassischen Sinne sind.
Ich hatte nun vor beim erstmaligen betreten der jeweiligen map die Initialisierungsseiten der einzelnen Gegner einmalig ablaufen zu lassen, damit die ihre werte in das self variablen script speichern.(Das sollte ohne probleme klappen)
Frage: Wie würde der Eventscriptbefehl ausschauen damit sich das event selber in die liste mit der id der aktuellen map ablegt, ohne einen Tag im namen zu verwenden und also mehrere listen für jede map id eine? (Das Event führt sich ja selber aus müsste also sowas wie: Gegnerlistevon"game map id"[].include this [@event.id]. (Erschlag mich nicht,das ist brainstorming^^und kein code)
Und zweitens, wie kann ich das Event wieder aus jener Liste entfernen? Bräuchte einmal den self befehl fürs event und interessanterhalber wie ich es von ausserhalb manipulliere.
Falls du eine globale Liste verwendest, zum Beispiel $someList, dann kannst du einfach folgendes Script in jedes Geschoss-Event auf der Karte packen und als Auto-Start (oder ähnliches) zu Beginn laufen lassen:
$someList.push(getEvent)
Damit wird das Event hinten an der Liste angehängt.
Du sagst das mit dem Dollarzeichen ist unsauber, brauche ich das aber nicht um von ausserhalb drauf zu greifen zu können?
Das Dollarzeichen macht die Variable zu einer globalen Variable. Wenn du es verwendest kannst du immer und überall darauf zugreifen und die Variable jederzeit manipulieren.
Globale Variablen werden in der Programmierung größtenteils verpönt und verachtet, weil sie als schlechter Programmierstil gelten. Sie sind zwar nützlich und effektiv, aber stellen ein schlechtes Design dar.
Wenn jemand eine globale Variable verwendet ist es ein Anzeichen dafür, dass diese Person das Grundgerüst seiner Applikation nicht ganz durchdacht hat.
Natürlich kennst du das Grundgerüst deiner Applikation (dem RPG-Maker Ace) nicht, weil es nicht dein Code ist. Idealerweise würdest du ersteinmal 2 Monate lang den gesamten Code rauf und runter lesen und verstehen und danach planen wie du die Kommunikation idealerweise implementieren kannst ohne globale Variablen verwenden zu müssen.
Aber bei einem Projekt wie diesem hier ist das völlig übertrieben und nicht nötig. Man braucht keinen sauberen Stil um ein kleines Spielchen nebenher zu bauen.
Und noch viel wichtiger bleibt diese Liste nach dem Speichern und neuladen des Spiels erhalten?
Nein. Die Liste wird nicht mit gespeichert außer du änderst entweder die Speicherroutine oder machst die Liste zum Teil einer der Klassen, welche der Maker speichert (so wie Kelven es gesagt hat).
Wenn du die Liste jedoch zu einem Teil einer anderen Klasse machst (wie zum Beispiel Game_Party, Game_Player, etc) dann kannst du keine globale Liste mehr verwenden.
Wenn du die Liste jedoch zu einem Teil einer anderen Klasse machst (wie zum Beispiel Game_Party, Game_Player, etc) dann kannst du keine globale Liste mehr verwenden.
Ach so, der Ace macht das anders als der XP? Beim XP ist die Instanz von Game_Party global. Oder ich missverstehe dich gerade.
1.
Hmm unsauberer stil verstehe ich, sehr hack anfällig die globalen variablen.
2.
Wie würde ich denn ein bereits zugefügtes objekt wieder aus der Liste entfernen?
3.
Das sie nicht gespeichert werden, ist blöd. Nicht global in gameplayer? das wäre ungut oder? würde mir dann wohl wenig nützen.
4.
Ich hatte vor ein Self Variablen Script einzufügen. Wenn eine Liste auch eine Variable ist, könnte ich die listen als self variable des event1 auf map id 1 anlegen und die mapid als namen wählen. ? Wäre jetzt meine Hoffnung.
http://rpgmaker-vx-ace.de/board9-rpg-maker-vx-ace-lite/board18-scripts-rgss3-ace/board62-script-datenbank/120-einfaches-self-variables-script/#post611 Best Script Ever^^
class Game_System
def self_variables(map_id, event_id)
if map_id > 0 and event_id > 0
# Erstelle Self-Variables-Hash wenn noch nicht vorhanden:
@self_variables ||= Hash.new
@self_variables[map_id] ||= Hash.new
@self_variables[map_id][event_id] ||= Hash.new(0)
else
# Bei ungültiger Map-/Event-ID gebe einen leeren Hash zurück:
Hash.new(0)
end
end
end
class Game_Interpreter
def self_variables(event_id = @event_id)
$game_system.self_variables(@map_id, event_id)
end
end
class Game_Event
def self_variables
$game_system.self_variables(@map_id, @id)
end
end
Ach so, der Ace macht das anders als der XP? Beim XP ist die Instanz von Game_Party global. Oder ich missverstehe dich gerade.
Die Game_Party ist eine globale Variable, die Liste wäre dann jedoch keine mehr.
Natürlich kann man die Liste zu einem öffentichen Attribut der Game_Player Klasse erklären und dann über die globale Game_Player Instanz auf eine Liste zugreifen.
Effektiv wäre es so, als ob man eine globale Liste hätte, aber technisch gesehen ist es nicht das selbe.
Mögt ihr mir noch schnell verraten welchen Befehl ich nutzen muss um ein Event wieder aus der Liste zu entfernen?
Ich würde dir für solche Probleme empfehlen einfach die Hilfe-Datei zu öffnen und nach "Array" zu suchen.
Dort findest du dann eine ausgiebige Dokumentation mit allen Methoden, welche zur Verfügung stehen.
Unter anderem die Methode "delete" mit der ein Element aus einer Liste gelöscht werden kann.
Eine abschliessende Frage noch^^.
Könnte es im Maker für mich einen merkbaren Performanceuntertschied geben zwischen den beiden Möglichkeiten:
1.Einfach die IDs 1bis 500 durchrattern zu lassen und nach treffern zu fragen?
oder
2.Bei jedem aufruf den Namen der Events 1 bis 500 abzufragen , sie in eine Liste zu packen und dann nach treffern zu fragen?
Wenn es keinen merkbaren unterschied macht wäre 2 cooler für mich.
Du erwähntest aber das Ruby wohl nicht der schnellste im interpretieren ist. und da ich nicht weiss wie krass die unterschiede bei den einzelnen befehlen sind ....
Das nennt man "premature optimization". Normalerweise implementiert man zuerst und macht sich um Performance erst dann Gedanken, wenn man merkt, dass es zu langsam ist.
Natürlich ist es gut schon im Vorfeld ein gutes Ziel an zu streben, aber für Kleinigkeiten wie diese solltest du ersteinmal testen und danach prüfen wo das Bottleneck liegt.
Ganz allgemein gesagt: Computer sind immer gut darin mit Zahlen zu arbeiten und Dinge nacheinander aus zu führen.
Aber wenn es für dich angenehmer ist mit Text zu arbeiten dann solltest du das bevorzugen und nicht den eigenen Komfort für ein kleines bisschen Performance opfern.
Powered by vBulletin® Version 4.2.3 Copyright ©2025 Adduco Digital e.K. und vBulletin Solutions, Inc. Alle Rechte vorbehalten.