Objecte umranden lassen

  • GM 8

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

  • Objecte umranden lassen

    Hallo,

    Ich wollte mal wissen ob und wie es möglich ist,dass man ein beliebiges Object,oder eine Instanz besser gesagt mit einer linie umranden lassen kann,egal welche Form das Object hat.

    Nehmen wir mal an,die Instanz hat die Grafik eines Sterns,so soll darum eine Linie gezeichnet werden.Man sollte Farbe der Linie,breite der Linie und den Abstand zwischen Instanz und Linie bestimmen können.Gibt es eine möglichkeit dies zu tun,ohne für jedes Object,welches man umranden lassen will,eine extra Grafik zu machen in der es umrandet ist?
    Spoiler anzeigen
    So ähnlich wie es in Strategiespielen gemacht wird,wenn man eine Einheit auswählt,die sich irgendwo hin bewegen soll,dann werden die meistens auch mit ner Linie umrandet die einen Abstand vom Object hat

    Hoffe ihr versteht was ich meine :)

    mfg,domi
  • Soll das ganze in 2d oder 3d passieren
    In 3d denke ich wird das nix werden so ohne weiteres.
    Aber in 2d, ist ja klar, brauchst ja nur ein Sprite drüber legen.
    Meine Signatur hat kein Visum für das GM Forum erhalten.
  • Ja in 2D.Wie bereits gesagt,möchte ich aber nicht für jedes einzelne Object ein Grafik machen,vor allem weil dies nicht möglich ist,weil sich die Form zufällig verändern kann.Es müsste irgendwie eine Möglichkeit geben,das ein SCript oder ähnliches herausfindet wie das Sprite aussieht vom Object und dann darum eine Linie zeichnet.

    Hab oben in nen Spoiler mal ein Beispiel rein :)

    mfg,domi
  • Hier eine Methode die auch mit Animationen funktioniert.

    GML-Quellcode

    1. draw_self()
    2. draw_set_color(c_black)
    3. draw_sprite(sprite_index,image_index,x-Randbreite,y-Randbreite)
    4. draw_sprite(sprite_index,image_index,x+Randbreite,y+Randbreite)
    5. draw_sprite(sprite_index,image_index,x-Randbreite,y+Randbreite)
    6. draw_sprite(sprite_index,image_index,x+Randbreite,y-Randbreite)
    7. draw_set_color(c_white)



    Wenn du das Sprite des Objekts immer über sprite_index veränderst,
    dann ist das einzige, was du noch ändern musst "Randbreite", was
    die Breite des Rands angibt....

    Ich hoffe, ich konnte dir helfen. (:
  • Also irgendwie klappt das nicht.Hab mal ein simples Beispiel gemacht:
    :event_create:

    GML-Quellcode

    1. Randbreite = 10

    :event_draw:

    GML-Quellcode

    1. draw_set_color(c_white)
    2. draw_sprite(sprite_index,image_index,x,y)
    3. draw_set_color(c_black)
    4. draw_sprite(sprite_index,image_index,x-Randbreite,y-Randbreite)
    5. draw_sprite(sprite_index,image_index,x+Randbreite,y+Randbreite)
    6. draw_sprite(sprite_index,image_index,x-Randbreite,y+Randbreite)
    7. draw_sprite(sprite_index,image_index,x+Randbreite,y-Randbreite)
    8. draw_set_color(c_white)


    Vorher:



    Nachher:


    (Das der Hintergrund grau ist,liegt am GM Fenster,nicht an der Grafik oder am Code)
  • Eigentlich dachte ich, dass der GM so die Farbe auch ändern kann,
    aber wie es scheint musst du es mit dem hier probieren:

    GML-Quellcode

    1. draw_set_color(c_white)
    2. draw_sprite(sprite_index,image_index,x,y)
    3. draw_sprite_ext(sprite_index,image_index,x-Randbreite,y-Randbreite,1,1,0,c_black,1)
    4. draw_sprite_ext(sprite_index,image_index,x+Randbreite,y+Randbreite,1,1,0,c_black,1)
    5. draw_sprite_ext(sprite_index,image_index,x-Randbreite,y+Randbreite,1,1,0,c_black,1)
    6. draw_sprite_ext(sprite_index,image_index,x+Randbreite,y-Randbreite,1,1,0,c_black,1)
  • Jetzt siehts so aus:



    EDIT:

    So würde es zwar klappen:

    GML-Quellcode

    1. draw_set_color(c_white)
    2. draw_sprite_ext(sprite_index,image_index,x-Randbreite,y-Randbreite,1,1,0,c_black,1)
    3. draw_sprite_ext(sprite_index,image_index,x+Randbreite,y+Randbreite,1,1,0,c_black,1)
    4. draw_sprite_ext(sprite_index,image_index,x-Randbreite,y+Randbreite,1,1,0,c_black,1)
    5. draw_sprite_ext(sprite_index,image_index,x+Randbreite,y-Randbreite,1,1,0,c_black,1)
    6. draw_sprite_ext(sprite_index,image_index,x,y,1,1,0,c_red,1)

    allerdings ist dann die schwarze Linie direkt am Object dran und wenn ich die Randbreite größer mache,dann wird zwar irgendwann ein Abstand entstehen,allerdings wäre dann der Rand so groß wie das Sprite selbst
  • Tiefenprobleme ~_~

    GML-Quellcode

    1. draw_set_color(c_white)
    2. draw_sprite_ext(sprite_index,image_index,x-Randbreite,y-Randbreite,1,1,0,c_black,1)
    3. draw_sprite_ext(sprite_index,image_index,x+Randbreite,y+Randbreite,1,1,0,c_black,1)
    4. draw_sprite_ext(sprite_index,image_index,x-Randbreite,y+Randbreite,1,1,0,c_black,1)
    5. draw_sprite_ext(sprite_index,image_index,x+Randbreite,y-Randbreite,1,1,0,c_black,1)
    6. draw_sprite(sprite_index,image_index,x,y)
  • Wie schon oben gesagt,es würde so zwar gehn:

    aber dann gibts keinen Abstand(siehe oben)

    EDIT: Es besteht außerdem noch das Problem,wie du am Bild sehen kannst,dass bei den 3 äußeren Kreisen,die Linie die gezeichnet wird nicht rund ist,sondern die selbe Form hat wie das Sprite(im code wird ja einfach nur das Sprite verschoben)
  • Ach, das mit dem Abstand hab ich ganz überlesen.
    Kann schonmal um halb 2 passieren. Morgen (Heute, nach dem Schlafen) kann ich dir
    wahrscheinlich weiter helfen, denn das benötigt Surfacearbeit.

    Jedoch würden sich 5+ Surfaces auf die Performance stark auswirken,
    da wäre dann doch das zeichnen von extrasprites ratsamer.
  • Solche Methoden haben leider immer soclhe Probleme :/
    Wenn es dir nur um Konvexe Sprites geht, könnte man das Bild skalieren was relativ perfekte Ergebnisse liefern würde.

    Wenn du aber x-beliebige Formen hast, gibt es keine wirkliche Lösung. Bzw. im GM gibts die nicht. Der GM geht sehr schnell performancemäßig in die Knie. Wenn das nicht so wäre könnte man aber die Form der Sprites anhand seiner Kollisionsmaske erfassen und entsprechend etwas zeichnen.

    [EDIT:] Toll, bin wohl auch zu müde um alles zu lesen. So einen Abstand zwischen den Sprites zu realisieren ist wiederum schwierig. in der tat wären das Surfaces die Lösung. Aber mit größerer Liniendicke funktioniert auch da diese Verschiebemethode nicht sehr gut. Bei einem Kreis geht es ja noch, allerdings nicht wenn du zum Beispiel den Sprite eines Soldaten Mit Gewehr hast...

    Willst du auf diese Drachen und -eier klicken?
    Sie werden sich freuen ;)
  • Gibt es eventuell eine möglichkeit,transparent zu drawen,bzw. an einer stelle wo etwas gedrawed wird,nicht zu drawen,denn dann könnte man es ja so machen:
    :event_create:

    GML-Quellcode

    1. ab = 2
    2. dicke = 7
    3. Randbreite = ab + dicke

    :event_draw:

    GML-Quellcode

    1. draw_set_color(c_white)
    2. // Rahmen (ab + dicke = Randbreite)
    3. draw_sprite_ext(sprite_index,image_index,x-Randbreite,y-Randbreite,1,1,0,c_black,1)
    4. draw_sprite_ext(sprite_index,image_index,x+Randbreite,y+Randbreite,1,1,0,c_black,1)
    5. draw_sprite_ext(sprite_index,image_index,x-Randbreite,y+Randbreite,1,1,0,c_black,1)
    6. draw_sprite_ext(sprite_index,image_index,x+Randbreite,y-Randbreite,1,1,0,c_black,1)
    7. // Abstand (Transparent drawen oder diese Stelle löschen)
    8. draw_sprite_ext(sprite_index,image_index,x-ab,y-ab,1,1,0,c_black,1) // Mit dem dazu passenden Code ersetzen
    9. draw_sprite_ext(sprite_index,image_index,x+ab,y+ab,1,1,0,c_black,1) // Mit dem dazu passenden Code ersetzen
    10. draw_sprite_ext(sprite_index,image_index,x-ab,y+ab,1,1,0,c_black,1) // Mit dem dazu passenden Code ersetzen
    11. draw_sprite_ext(sprite_index,image_index,x+ab,y-ab,1,1,0,c_black,1) // Mit dem dazu passenden Code ersetzen
    12. // Eigenes Sprite
    13. draw_sprite(sprite_index,image_index,x,y)
    Alles anzeigen

    Vielleicht versteht ihr was ich meine,bin etz auch müde,bis morgen :)

    EDIT: Da immer nur eine Instanz gleichzeitig so umrandet werden soll,wäre die Performance mir dabei nicht so schlimm.Wenns also mit Surfaces gehen würde,wäre ich froh wenn ihr mir das erklären könntet.

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von derkimba ()

  • Nur mal so ne frage. ICh habe jetzt alle einträge mir angeschaut.
    Das bild wo die Roten Kreise mit dem Schwarzen umrandent werden , ist ja fast das was du willst.
    Warum macht ihr nicht statt 4 sprite zu zeichnene einfach nur einen der um ca 5-10% skaliert wird.
    Wenn der Sprite. zb ein Kreis ein durchmesser von 32 Pixeln hat. Machst du dahinter das selbe wie oben nur das nicht die x und y pos verschoben wird sondenr der scale wert
    =1+(%)
    So das der kreis dahinter zb 36 Pixel durchmesser hat.
    Meine Signatur hat kein Visum für das GM Forum erhalten.
  • Aber dann gibts ja trotzdem keinen Abstand^^
    das Problem mit den äußeren Kreisen wäre dann aber gelöst,allerdings müsste man dann ja das Sprite während des Spiels skalieren.

    EDIT: Habs mal ausprobiert.Leider ist es an manchen Stellen eine dickere Linie und an manchen eine dünnere,so soll es natürlich nicht sein^^

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von derkimba ()

  • Dies wäre eine elegantere Variante:

    GML-Quellcode

    1. width = 1;
    2. for(i = 0; i < 360; i += 90)
    3. {
    4. draw_sprite_ext(sprite_index, image_index, x+lengthdir_x(width, i), y+lengthdir_y(width, i),
    5. image_xscale, image_yscale, image_angle, c_black, image_alpha);
    6. }
    7. draw_sprite(sprite_index,image_index,x,y);


    Wenn du etwas mehr Genauigkeit erwünscht, (erkennbar an den runden/eckigen Kanten) einfach die Zahl der Iterationen der for - Schleife, durch die Verminderungen des Summanden wessen per Iteration der Variable i hinzugefügt wird, erhöhen.

    Von Vorteil wäre wahrscheinlich auch, das Ganze in ein Skript zu packen. ;)

    Einen Abstand zwischen dem Sprite und der Outline in einer zufriedenstellenden Qualität herzustellen ist meines Wissen nach ausschließlich mit Surfaces möglich.

    Hierzu ein schönes Skript, welches das Problem mit Surfaces löst:
    Spoiler anzeigen

    GML-Quellcode

    1. // sprite_create_outline(
    2. // source,
    3. // width,
    4. // margin,
    5. // precision
    6. // );
    7. var width, margin, sur_width, sur_height, n, i, j, spr_out;
    8. width = argument1;
    9. margin = argument2;
    10. sur_width = sprite_get_width(argument0) + width*2 + margin*2;
    11. sur_height = sprite_get_height(argument0) + width*2 + margin*2;
    12. n = surface_create(sur_width, sur_height);
    13. surface_set_target(n);
    14. for (i = 0; i < sprite_get_number(argument0); i += 1)
    15. {
    16. draw_clear_alpha(c_black, 0);
    17. draw_set_blend_mode(bm_normal);
    18. for (j = 0; j < 360; j += 90 div argument3)
    19. {
    20. draw_sprite_ext(argument0, i, lengthdir_x(width + margin, j),
    21. lengthdir_y(width + margin, j), 1, 1, 0, c_black, 1);
    22. }
    23. draw_set_blend_mode(bm_subtract);
    24. for (j = 0; j < 360; j += 90 div argument3)
    25. {
    26. draw_sprite_ext(argument0, i, lengthdir_x(margin, j),
    27. lengthdir_y(margin, j), 1, 1, 0, c_white, 1);
    28. }
    29. if (!i)
    30. spr_out = sprite_create_from_surface(n, 0, 0, sur_width, sur_height, false, false, 0, 0);
    31. else
    32. sprite_add_from_surface(spr_out, n, 0, 0, sur_width, sur_height, false, false);
    33. }
    34. draw_set_blend_mode(bm_normal);
    35. surface_reset_target();
    36. surface_free(n);
    37. return spr_out;
    Alles anzeigen

    Hinweis: Dem Parameter precision sollten nur die Zahlen 1, 2, 3 oder 5 (je höher, desto genauer) übergeben werden und bei Sprites mit Rändern, deren Alpha Wert unter 1 liegt, treten Artefakte auf.

    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von luky300 ()