Frage zu Inventar

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • Frage zu Inventar

    Hellö,

    ich hab mal ne Frage: Wie schwer ist es, ein Inventar (ohne Maus, nur Tastatur)für ein kleines RPG zu programmieren? Hier ist mal ein kleines Bildchen, wie das Inventar in etwa aussehen wird, sollte ich es schaffen:



    Mit den Pfeiltasten bewegt man den grünen Markierer. Wenn man ein Item markiert hat und dann D drückt, soll das Item verschwinden. Mit U kann man es benutzen und mit Esc beendet man das Inventory und geht zum Spiel zurück. Solange man im Inventory ist, wird das Spiel pausiert.

    Also, kann man sowas mit Drag&Drop machen oder müsste ich jemanden finden, der mir das proggen kann?
  • Ist also mit dem GM machbar? Ich hab noch ne Frage: Sagen wir mal das Inventar ist voll mit Items und ich benutze oder drop das dritte Item in der ersten Spalte. Kann man das machen, dass alle Items dann "nachrutschen"? Also, dass keine Lücke bleibt?
  • hmm ja das müsste gehn, du musst halt für jedes feld eine eigene variable machen und die auf 0 setzen wenn nichts drinnen ist und dann für jedes mögliche objekt einen anderen wert nehmen.. und dann musst du halt noch abfragen, ob die variable vom feld vorher belegt ist. in gml würde das etwa so aussehen:

    GML-Quellcode

    1. if (global.feld1>0)
    2. {global.feld2=global.gegenstand}

    du musst halt vorher noch die variable gegenstand so festlegen, dass sie den wert von dem objekt hat das du rein tun möchtest.

    Edit: 400. Beitrag ...

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von J@kob ()

  • Also, eigentlich ist alles andere als ein Array hier unsinnig. Ein Array ist die perfekte Datenstruktur um in viereckigen Feldern angeordnete Raster zu verwalten und lässt sich außerdem mit einigen einfachen Algorithmen auch sehr gut sortieren und man kann auch problemlos eben diesen "Nachrutsch-Effekt" machen, den Hellö hier machen will. Bevor man sich an sowas ranwagt, sollte man jedoch schon gewisse Erfahrung in GML gesammelt haben.
  • Wollte nur wissen, ob das geht. Die Erfahrung hab ich nicht. Bin zu faul. Ich denke, sobald ich das Konzept, die Grafiken und die Grundengine fertigstelle, such ich mir nen Experten, der mir das programmiert. Danke für die schnellen Antworten.
  • Wobei so ein Inventar eine ziemlich schöne Aufgabe ist sich mal die Zähne auszubeißen und sich da 2-3 Tage oder mehr dranzusetzen wenn man das noch nie gemacht hat. Später sagen zu können: "Das habe ich gemacht, und es funtkioniert" ist bei so einer Sache immer hinterher der größte Ansporn. Und voher, naja, da muss der wille da sein :)
  • Von Arrays würde ich abraten. Listen bieten sich hier super an. Da ist das "Nachrutschen" quasi schon integriert. Außerdem musste ich mich belehren lassen, dass Listen wesentlich schneller sind als Arrays. Eine recht simple Alternative wäre es, den Player selbst bestimmen zu lassen, in welches Feld er welches Item packen will. Damit würdest du das vollständig umgehen.

    @Dur'Rean: Du glaubst ernsthaft, dass du dafür 2-3 Tage brauchst? Es ist nicht so kompliziert, wie du dir das vorstellst. :)
    █████ ██ █ ████ everything ███ █████ is █████ ████ ████ fine ████ ███ █ ██████ love.
    █████ ███████ ███ your █████ ████ government.
  • Dazu muss man aber auch sagen, dass Listen und alle anderen Datenstrukturen nur für registrierte Nutzer des GMs benutzbar sind, Arrays aber nicht :P
    Und grundsätzlich zu diesen "Kann man sowas mit Game Maker machen?"-Fragen: Im Grunde ist alles möglich, nur der Aufwand ist unterschiedlich (sofern man reg./Pro hat).
  • F4LL0UT schrieb:

    Okay, stimmt. Gerade das Zusammenschieben im Falle einer Lücke ist bei dynamischen Datenstrukturen wie einer Liste besser und auch noch speicherfreundlicher. Ich persönlich würde für ein solches Inventar trotzdem die Vorzüge eines Array nutzen wollen, aber das ist hier wohl nicht gewünscht. ^^

    Wäre sinnlos. Nur weil das Inventar rechteckig dargestellt wird, heißt das nicht, dass es abstrakt genauso dargestellt werden sollte.

    Aber kurz zum Thema: Der GM ist für solche Datenbank-Kram nicht so furchtbar toll geeignet. Data Structures sind da zwar ne schöne Sache, aber leider sehr eindimensional.
    Um daher ein bischen vorzubeugen:
    Gebe jedem deiner Items eine id. Schreibe eine Funktion, die anhand der item ID Eigenschaften zurückgeben, wie z.b. get_item_info("name",21). In dieser Funktion selbst kannst du z.B. per switch statement schön die Infos über alle Items reinklatschen. Später möchtest du das bestimtm extern in eine Datei ablegen, aber so bleibt es einigermaßen sinvoll innerhalb des Game Makers und lässt sich einfach annehmbar verwalten.

    Das eigentliche Inventar ist dann nur noch eine Aufzählung von IDs. Das muss dann nur noch gedrawd werden - die eigentliche Arbeit am Ganzen. :D

    edit:
    Ok... es muss ein Array sein wenns der GM6 unregistered is... nein muss es nicht, es gibt einen anderen Trick, aber dann guckt ihr mich komisch an.
  • Beispiel mit Array:

    benötigte Grafiken (alle gleich groß mit Origin bei 0,0)
    - ein Sprite für ein leeres Feld: spr_field_empty
    - ein Sprite für ein ausgewähltes Feld: spr_field_selected
    - ein Sprite für ein Testobjekt (Trank): spr_potion

    benötigte Scripts:
    - ein Script das sämtliche Eigenschaften der möglichen Inventaritems enthält: scr_getItem

    GML-Quellcode

    1. item=argument0; // das angefragte Item
    2. request=argument1; // die angefragte Aktion
    3. switch(item)
    4. {
    5. case "empty": // im Fall eines leeren Feldes
    6. if (request=="name") return "leeres Feld";
    7. break;
    8. case "potion": // im Fall eines Trankes
    9. if (request=="sprite") return spr_potion; // gib das "Trank" Sprite zurück
    10. if (request=="name") return "Gesundheitstrank"; // gib den Namen des Tranks zurück
    11. if (request=="use") health+=10; // heile den Spieler
    12. break;
    13. }
    Alles anzeigen


    Benötigte Objekte:
    - ein Object für das Inventar: obj_inventar
    mit folgenden Codes in folgenden Events:
    Create:

    GML-Quellcode

    1. fields_h=6; // Anzahl der Spalten des Inventars
    2. fields_v=4; // Anzahl der Zeilen des Inventars
    3. fields_height=sprite_get_height(spr_field_empty);
    4. fields_width=sprite_get_width(spr_field_empty);
    5. // 2 ineinander verschachtelte for-Schleifen, die alle Inventarfelder durchlaufen...
    6. for (i=0;i<fields_h;i+=1)
    7. {
    8. for (j=0;j<fields_v;j+=1)
    9. {
    10. inventory[i,j]="empty"; // ...und auf "empty" setzt
    11. }
    12. }
    13. // aktuell ausgewähltes Feld:
    14. index_x=0;
    15. index_y=0;
    16. // drei Testobjekte ins Inventar:
    17. inventory[0,0]="potion";
    18. inventory[0,2]="potion";
    19. inventory[2,1]="potion";
    Alles anzeigen


    Step:

    GML-Quellcode

    1. // Aufrufen des Inventars mit der Taste i
    2. if (keyboard_check_pressed(ord('I'))) {
    3. instance_deactivate_all(true); // alle Objekte "pausieren"
    4. visible=true;
    5. }
    6. if (visible==true)
    7. {
    8. // Bewegung des selektierten Feldes
    9. if (keyboard_check_pressed(vk_right))
    10. {
    11. if(index_x<fields_h-1) index_x+=1;
    12. }
    13. if (keyboard_check_pressed(vk_left))
    14. {
    15. if(index_x>0) index_x-=1;
    16. }
    17. if (keyboard_check_pressed(vk_up))
    18. {
    19. if(index_y>0) index_y-=1;
    20. }
    21. if (keyboard_check_pressed(vk_down))
    22. {
    23. if(index_y<fields_v-1) index_y+=1;
    24. }
    25. // Benutzen des ausgewählten Objekts:
    26. if (keyboard_check_pressed(ord('U')))
    27. {
    28. scr_getItem(inventory[index_x,index_y],"use"); // Benutzen
    29. inventory[index_x,index_y]="empty"; // aus dem Inventar entfernen
    30. }
    31. // Droppen des ausgewählten Objekts:
    32. if (keyboard_check_pressed(ord('D')))
    33. {
    34. inventory[index_x,index_y]="empty"; // aus dem Inventar entfernen
    35. }
    36. //Verlassen des Inventars mit Space
    37. if (keyboard_check_pressed(vk_space))
    38. {
    39. instance_activate_all(); // alle Objekte wieder aktivieren
    40. visible=false;
    41. }
    42. }
    Alles anzeigen


    Draw:

    GML-Quellcode

    1. // 2 ineinander verschachtelte for-Schleifen, die alle Inventarfelder durchlaufen:
    2. for (i=0;i<fields_h;i+=1)
    3. {
    4. for (j=0;j<fields_v;j+=1)
    5. {
    6. // die leeren Felder zeichnen:
    7. draw_sprite(spr_field_empty,0,x+i*fields_width,y+j*fields_height);
    8. if (inventory[i,j]!="empty") // falls ein Objekt in dem Feld liegt
    9. {
    10. // Sprite zeichnen
    11. sprite=scr_getItem(inventory[i,j],"sprite");
    12. draw_sprite(sprite,
    13. 0,
    14. x+i*fields_width,
    15. y+j*fields_height
    16. );
    17. }
    18. }
    19. }
    20. // das Sprite für das ausgewählte Feld zeichnen:
    21. draw_sprite(spr_field_selected,
    22. 0,
    23. x+index_x*fields_width,
    24. y+index_y*fields_height
    25. );
    26. // Name zeichnen
    27. name=scr_getItem(inventory[index_x,index_y],"name"); // Name abfragen
    28. draw_text(x,y+fields_v*fields_height,name);
    Alles anzeigen

    Nun noch einen neuen room anlegen und das obj_inventory platzieren, dann kann das Spiel gestartet werden.
    Mit I wird das Inventar aufgerufen, mit den Pfeiltasten bewegst du den Cursor, mit D wirfst du ein Item weg, mit U benutzt du es. Das Inventar schließt sich mit Space (Ich hab Escape nicht genommen, da wir sonst noch einen Extra-Knopf zum Beenden des Spiels brauchen.)
    Um neue Objekte aufzusammeln, kannst du dir noch ein weiteres Script schreiben: scr_collect

    GML-Quellcode

    1. item=argument0;
    2. for (i=0;i<obj_inventory.fields_h;i+=1)
    3. {
    4. for (j=0;j<obj_inventory.fields_v;j+=1)
    5. {
    6. if (obj_inventory.inventory[i,j]=="empty")
    7. {
    8. obj_inventory.inventory[i,j]=item;
    9. return true;
    10. }
    11. }
    12. }
    13. return false;
    Alles anzeigen

    Wenn du einen Trank aufsammeln lassen willst gehst du so vor: Schreib beim obj_trank ins collision_event mit deinem Player Object:

    GML-Quellcode

    1. if (scr_collect("potion")==true) { // falls das Objekt eingesammelt werden konnte...
    2. instance_destroy(); // ...entferne es aus dem Spiel
    3. }
    Einige meiner Spiele:
  • Ich habe dieses Thema über der Suche gefunden und wollte für alle daraufhinweisen dass Spellmaker, nachdem ich ihn um Hilfe geboten hatte, einen Fehler in Interceptors Beitrag gefunden hat:

    Es heißt:

    GML-Quellcode

    1. if (inventory[i,j]!="leer") // falls ein Objekt in dem Feld liegt


    richtig wäre aber:

    GML-Quellcode

    1. if (scr_getItem(inventory[i,j],"name")!="leer") // falls ein Objekt in dem Feld liegt


    mfg frischi



  • äh...so geht's natürlich auch. Eigentlich müsste es aber heißen:

    GML-Quellcode

    1. if (inventory[i,j]!="empty") // falls ein Objekt in dem Feld liegt

    Hab aus Versehen von "empty" auf "leer" gewechselt... "leer" sollte nur im scr_getItem Script stehen, um darzustellen, dass der String nicht der gleiche sein muss, wie der, der im Inventar Array verwendet wird. Schöner (d.h. ressourcenschonender) wäre es sowieso, da nicht mit Strings zu arbeiten sondern mit Konstanten, die lassen sich in den Global Game Settings festlegen:
    EMPTY 0
    POTION 1
    GUN 2
    Gibt es eigentlich eine einfachere Variante Konstanten im Spiel festzulegen?

    EDIT: Nicht wundern, ich hab's in meinem oberen Beitrag ausgebessert.
    Einige meiner Spiele:
  • Ich würde eigentlich anstatt strings für die einzelnen Fälle lieber ne Variable deklarieren und ID's dafür drin speichern.

    Also im create z.B.

    name=0;
    bla=1;
    blubb=2;
    etc.

    Dann könnte man im switch trotzdem mit Wörtern arbeiten (was es ja immerhin leichter zu lesen macht.) und dennoch könnte man for-Schleifen verwenden um z.B. Alles abzufragen.
    So far, Schattenphoenix~
    _____________________________________________________________________________
    "Who needs a stairway to heaven...
    If there is an elevator to hell... ?
    "
    - Vergessen
    "Auch ein perfektes Chaos ist etwas vollkommenes."
    - Jean Genet
  • Gut mit Variablen kann man es natürlich machen, das kostet aber wieder Speicher.
    Konstanten wären eigentlich die beste Lösung, wenn sie nicht so umständlich implementiert wären. Die sollten nämlich beim "Komplilieren" des Spiels direkt in Zahlen umgewandelt werden und dadurch weniger Speicher belegen.
    Oder lieg ich da falsch und der GM regelt das anders?
    Einige meiner Spiele: