Verschieben der x und y Koordinaten flüssig wiedergeben bei mehr als 1 Pixel pro Step

    • GM 8

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

    • Verschieben der x und y Koordinaten flüssig wiedergeben bei mehr als 1 Pixel pro Step

      Guten Abend zusammen,

      ich bastel momentan an einer kleinen Engine für ein nicht weiter wichtiges Projekt.
      Die Engine ist im Grunde eine kleine Top-Down Engine.

      Bedeutet die Spielfigur wird aus einer "fast" Vogelperspektive gesteuert.

      Egal, ich verscuhe mal das Problem zu schildern:

      Der Spieler hat verschiedene Waffen, eine Waffe definiert sich aus 18 Variablen.
      Einer der Variablen gibt an wie stark der recoil/Rückstoß durch die Waffe ist.

      Wenn ich einen Rückstoß von einem Pixel habe dann ist dies generell kein Problem.
      Der Rückstoß beginnt, es wird auf Collision hin geprüft und dann werden die Koordinaten der Instanz angepasst.

      Wenn der Rückstoß-Wert allerdings größer als 2 ist so werden innerhalb eines Steps entsprechend viele Pixel übersprungen... dies sieht sehr unschön aus und ich würde dann lieber zwar den Rückstoß von der stärker her beibehalten, aber den Rückstoß flüssiger ausgeben... am besten soll der gesamte Rückstoß innerhalb von in etwa room_speed/2 stattfinden... also eine halbe Sekunde für das flüssige Darstellen des Rückstoßes.

      Der Rückstoß selber wird derzeit innerhalb des Global Mouse Left Button Events aktiviert.
      Hier wird dann folgendes Skript aufgerufen:

      GML-Quellcode

      1. /*
      2. Moves a object due to recoil effect after shooting
      3. argument0 = Object to get the recoil
      4. argument1 = Recoil strength
      5. argument2 = Recoil direction
      6. argument3 = bbox_top_offset
      7. */
      8. var _targetid, _xincr, _yincr, _rep;
      9. argument0.input = false
      10. if (argument1 > 1)
      11. _rep = room_speed/2
      12. else
      13. _rep = 1
      14. repeat(ceil(argument1))
      15. {
      16. //If the recoil strength is above 1 it will look cut-off..so we reduce the actual recoil strength
      17. //and instead increase the repeat
      18. _xincr = 1 / _rep
      19. _yincr = 1 / _rep
      20. //Check in what direction the recoil will push the object
      21. _xincr *= scr_direction_to_xincrement(argument2)
      22. _yincr *= scr_direction_to_yincrement(argument2)
      23. repeat(_rep)
      24. {
      25. _targetid = collision_rectangle(argument0.bbox_left+_xincr,argument0.bbox_top+_yincr+argument3,argument0.bbox_right+_xincr,argument0.bbox_bottom+_yincr,par_block,false,false)
      26. if !(_targetid)
      27. _targetid = collision_rectangle(argument0.bbox_left+_xincr,argument0.bbox_top+_yincr+argument3,argument0.bbox_right+_xincr,argument0.bbox_bottom+_yincr,par_target,false,false)
      28. if !(_targetid)
      29. {
      30. argument0.x += _xincr
      31. argument0.y += _yincr
      32. }
      33. }
      34. }
      35. argument0.input = true
      Alles anzeigen


      Das Problem besteht leider weiterhin.
      Ich hab nun schon mehrere Jahre nichts mehr wirklich mti GM gemacht und hänge daher an diesem evtl. bescheuertem Problem fest.

      Ich hatte gehofft dass ich durch das äußere repeat() das Verschieben der Koordinaten auf eine halbe Sekunde (room_speed/2) strecken kann...aber wie mir scheint klappt dies nicht
      wirklich und die Aktion an sich erfolgt weiterhin innerhalb eines Steps.

      Wie wäre denn nun die genaue Vorgehensweise für eine derartige Problematik?

      Danke im Vorraus

      Edit:
      Generell ist mir klar wo das Problem liegt. Das Script wird innerhalb eines Steps ausgeführt, was ich bräuchte wäre ein step pro Schleifen-Durchlauf (repeat-schleife).
      Momentan sehe ich keine Möglichkeit dies umzusetzen ohne größeren Aufwand betreiben zu müssen.

      Edit:
      Okay, sorry, das war dann einfach.
      Des Rätsels Lösung ist einfach nur die Funktion screen_redraw.

      Die Aktionen in der Schleife werden ja definitiv durchgeführt, nur da es noch immer derselbe Step ist wird es nciht visualisiert. Die screen_redraw Funktion erzwingt dies.

      Am Ende sieht das ganze nun so aus:

      GML-Quellcode

      1. /*
      2. Moves a object due to recoil effect after shooting
      3. argument0 = Object to get the recoil
      4. argument1 = Recoil strength
      5. argument2 = Recoil direction
      6. argument3 = bbox_top_offset
      7. */
      8. var _targetid, _xincr, _yincr, _rep;
      9. argument0.input = false
      10. //If the recoil strength is above 1 it will look cut-off..so we reduce the actual recoil strength
      11. //and instead increase the repeat
      12. _xincr = argument1 / (room_speed/2)
      13. _yincr = argument1 / (room_speed/2)
      14. //Check in what direction the recoil will push the object
      15. _xincr *= scr_direction_to_xincrement(argument2)
      16. _yincr *= scr_direction_to_yincrement(argument2)
      17. //The complete recoil will be done within half a second (room_speed/2)
      18. repeat(room_speed/2)
      19. {
      20. _targetid = collision_rectangle(argument0.bbox_left+_xincr,argument0.bbox_top+_yincr+argument3,argument0.bbox_right+_xincr,argument0.bbox_bottom+_yincr,par_block,false,false)
      21. if !(_targetid)
      22. _targetid = collision_rectangle(argument0.bbox_left+_xincr,argument0.bbox_top+_yincr+argument3,argument0.bbox_right+_xincr,argument0.bbox_bottom+_yincr,par_target,false,false)
      23. if !(_targetid)
      24. {
      25. argument0.x += _xincr
      26. argument0.y += _yincr
      27. screen_redraw()
      28. }
      29. else
      30. break;
      31. }
      32. argument0.input = true
      Alles anzeigen

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

    • Hi BlaXun

      Ich würde einfach eine Counter-Variable cnt_recoil oder so einfügen, welche beim Mouse-Button-Event auf den Wert des Rückstoses gesetzt wird. Im Step-Event überprüfst Du nun, ob cnt_recoil größer null ist. Ist dies der Fall, kanns Du deine Spielfigur ein Stück (in Deinem Fall RecoilStrength/(room_speed/2)) verschieben und den Counter um den gleichen Wert verkleinern. Ist dieser kleiner gleich null, machst du einfach nichts.

      So müsste die Figur nach loslassen der Maustaste noch eine halbe Sekunde weiterbewegt werden.
      "Es gibt nie ein glückliches Ende, denn es endet nichts." - Schmendrick
    • Du kannst natürlich auch mit screen_redraw arbeiten, das ist genauso performant, nur steht dann logischerweise alles andere im Spiel während des Rückstoßes still, da es ja dann eine zeit lang nur das step-event von deiner Spielfigur abarbeitet.
    • screen_redraw und screen_refresh sind bad practise, imho.
      Solange nicht die GM-Engine rumzickt (ich erinnere mich dunkel, dass beim Raumwechseln manchmal etwas komisches passiert) gibt es keinen Grund, diese Funktionen zu benutzen.

      Wie schon oben geschrieben solltest du eher eine Variable benutzen, die in einem Step-Event "abgearbeitet" wird, bis sie 0 ist aber dabei um nie mehr als xyz pro Step verringert wird.

      Spätestens damit hast du natürlich Befehle aus verschiedenen Events, die alle das gleiche tun: Nämlich den Spieler verschieben.
      Das kann wiederum zu ganz anderen Problemen führen, da diese Events in einer bestimmten Reihenfolge abgearbeitet werden (s. "Order of Events" in der Help).
      Da ich mich damit ungern rumärgere, habe ich sämtliche Tasten-/Maus-Inputs ins Step- bzw. End-Step-Event verlagert und verzichte auf die entsprechenden Events. Ist auch einfacher, wenn man dem Spieler die Möglichkeit gibt, die Tasten anders zu belegen.
    • Ich weiss, dass ist jetzt ziemlich Offtopic, aber woher hast du die Information?

      Ich wäre nicht wirklich glücklich darüber dass die Funktion abgeschafft wird. Ich nutze sie ziemlich oft in Verbindung mit der View in fast allen meinen rojekten.
      Dadurch kann ich mir z.B: ein ein eigenes Motion Blur zusammenscripten dass Performant aber auch optisch extremst gut ausschaut.

      Das wichtigste ist aber die Kontrolle über den Zeitpunkt des Zeichnens. Ich deaktiviere in meinen meisten Projekten das automatische Zeichnen, und führe screen_redraw in einem Objekt aus. Dadurch habe ich die komplette Kontrolle, wann was gezeichnet werden soll.
      Ohne dieser Funktion verliert man 1. die Kontrolle und 2. kann man dann Kameraeffekte nicht mehr so leicht bzw. gar nicht mehr "nachprogrammieren". (Wie gesagt: Motion blur, Farbspielereien,Zoom-effekte,etc...)
      Wie gesagt, ich wäre da eher unglücklich wenn dies der Fall wäre :(
    • bugs.yoyogames.com/view.php?id=2708

      (0004670)
      mike (administrator)
      2011-10-06 20:14

      Sorry, screen_redraw is no longer supported. This is becuase you can not control the draw loop in a browser as you can in windows. However... This function will not be supported at all going forward, so you should try and find other ways of doing things.


      (0004689)
      mike (administrator)
      2011-10-07 14:34

      Functions like this are really bad. They take over the whole program loop, and really cause issues with anything "smart" you're trying to do. Mobile devices, web browsers, and even some PCs don't allow this. You MUST return to the OS for it to do updates.

      Going forward we will be supporting command which can be supported cross platform, and ones which are more dangerous like registry access, will be removed. We will still support "some" platform specific commands, those that everyone would implement anyway (other platforms just won't do anything), but command such as screen_redraw() are just a bad way of doing things, very "old school", lazy, and sometime, just plain dangerous, and will be dropped.

      sorry.
    • Benutzer online 1

      1 Besucher