FAQ: ImagesCollide & Memory Access Violation ?!

Übersicht BlitzBasic FAQ und Tutorials

Neue Antwort erstellen

 

BIG BUG

Betreff: FAQ: ImagesCollide & Memory Access Violation ?!

BeitragDo, Jan 31, 2008 22:23
Antworten mit Zitat
Benutzer-Profile anzeigen
ImagesCollide und ImageRectCollide kann trotz korrektem Aufruf zu einer MAV (MemoryAccessViolation) führen. Dieses Problem liegt an Inkompatibilitäten zu manchen Grafiktreiberversionen.
Es ist schwierig den Fehler nachzustellen, er tritt nicht bei jedem, und dann auch nur sporadisch auf. Bei animierten Bildern scheint es jedoch häufiger zur MAV zu kommen.

Dem Anwender in diesem Fall einfach zu sagen, er solle sich den neuesten Treiber herunterladen wie es gerne vorgeschlagen wird, ist lächerlich, da sich die Grafikhersteller kaum mehr mit DX7 rumschlagen und das Problem in der Vergangenheit immer wieder aufgetreten ist.

Auch wenn es schade ist, die Empfehlung lautet hier:

Verzichte komplett auf ImagesCollide und ImageRectCollide!


Im ersten Gedanken mag das vielleicht schmerzen, aber ImagesCollide ist vielleicht die einfachste Lösung, nicht unbedingt aber die beste.

Gehen wir mal die verschiedenen Anwendungsfälle durch:

-Mauscourser gegen Button (bei Anfängern)
Brrrr grausam.... da sag ich mal nix zu

-Spieler <> Gegner-Kollision
Hier ist selten Pixelgenauigkeit gefragt. Es empfehlen sich eigene Kollisionsboxen, die wohlgemerkt kleiner als die Original-Grafiken sind, da sich die Kollisionen dann fairer anfühlen. Die Kollisionsboxen können ja dann einfach mit RectsOverlap geprüft werden.

Beispiel
user posted image


-Spieler <> Map-Kollision
Bei Tilemaps sind die Kollisionen normalerweise ja recht einfach durch ein bisschen Mathematik durchzuführen.
Muß es dennoch pixelgenau sein(wie z.B. bei einer zerstörbaren Worms-Landschaft) reicht normalerweise ein ImageRectCollide Landschaftsgrafik <> SpielerKollisionsbox.
Doch Vorsicht! ImageRectCollide ist ebenfalls von den MAVs betroffen!
Daher habe ich hier mal zwei Routinen gebastelt, die statt ImageRectCollide benutzt werden können:

Code: [AUSKLAPPEN]

;Ersetzt ImageRectCollide, ist aber leider recht langsam
Function ImgRectCollide(image,xpos1, ypos1, xpos2, ypos2, width2, height2, mask=0)

   Local startx, starty, endx, endy, ix, iy

   Local width1  = ImageWidth(image)
   Local height1 = ImageHeight(image)

   xpos1   = xpos1 - ImageXHandle(image)
   ypos1   = ypos1 - ImageYHandle(image)

   startx = xpos2 - xpos1
   starty = ypos2 - ypos1
   endx   = startx + width2
   endy   = starty + height2

   If startx < 0       Then startx = 0
   If starty < 0       Then starty = 0
   If endx   > width1  Then endx   = width1
   If endy   > height1 Then endy   = height1

   endx = endx - 1
   endy = endy - 1

   If startx > endx Or starty > endy Then Return 0

   LockBuffer ImageBuffer(image)
   For ix = startx To endx
      For iy = starty To endy

         If mask <> (ReadPixelFast(ix, iy, ImageBuffer(image)) And $00FFFFFF) Then
            UnlockBuffer ImageBuffer(image)
            Return 1
         EndIf
      Next
   Next 
   UnlockBuffer ImageBuffer(image)

End Function


;Schneller als ImgRectCollide, es werden jedoch nur Eck- und Mittelpunkte geprüft
Function ImgRectCollideFast(image,xpos1, ypos1, xpos2, ypos2, width2, height2, mask=0)

   Local startx, starty, endx, endy, ix, iy, x[3], y[3]

   Local width1  = ImageWidth(image)
   Local height1 = ImageHeight(image)

   xpos1   = xpos1 - ImageXHandle(image)
   ypos1   = ypos1 - ImageYHandle(image)

   startx = xpos2 - xpos1
   starty = ypos2 - ypos1
   endx   = startx + width2
   endy   = starty + height2

   If startx < 0       Then startx = 0
   If starty < 0       Then starty = 0
   If endx   > width1  Then endx   = width1
   If endy   > height1 Then endy   = height1

   endx = endx - 1
   endy = endy - 1

   If startx > endx Or starty > endy Then Return 0

   x[0] = startx
   y[0] = starty
   x[1] = (startx + endx) Shr 1
   y[1] = (starty + endy) Shr 1
   x[2] = endx
   y[2] = endy

   LockBuffer ImageBuffer(image)
   For ix = 0 To 2
      For iy = 0 To 2   
         If mask <> (ReadPixelFast(x[ix], y[iy], ImageBuffer(image)) And $00FFFFFF) Then
            UnlockBuffer ImageBuffer(image)
            Return 1
         EndIf
      Next
   Next
   UnlockBuffer ImageBuffer(image)

End Function


Es gibt sicherlich noch andere Fälle, aber generell kann man gerade dadurch, dass man nur ausgewählte Punkte mit ReadPixel einliest, trotzdem eine hohe Geschwindigkeit erreichen.
B3D-Exporter für Cinema4D!(V1.4)
MD2-Exporter für Cinema4D!(final)
 

da_poller

BeitragSo, Sep 14, 2008 22:17
Antworten mit Zitat
Benutzer-Profile anzeigen
hier vielleicht eine kleine funktion meinerseits die ich mir nach lesen dieses beitrags geschrieben habe (vielleicht kann es ja jemand brauchen):

Code: [AUSKLAPPEN]
Function rectposcollide(posx,posy,rectx,recty,width,height)

   If posx>rectx And posy>recty And posx<(rectx+width) And posy<(recty+height)
        Return 1
   EndIf
        Return 0

End Function


ist vielleciht nicht die idealste lösung aber funktioniert(gibt es für den fall eine einfachere lösung die ich evtl übersehen habe? fals ja BITTE per pn bescheid sagen ...

edit: dank meines nachposters zeilen gespaart und return0 eingefügt viel spaß damit Smile
  • Zuletzt bearbeitet von da_poller am Mo, Sep 15, 2008 15:27, insgesamt einmal bearbeitet

Goodjee

BeitragSo, Sep 14, 2008 22:29
Antworten mit Zitat
Benutzer-Profile anzeigen
warum nich alles in eine zeile und eventuell ein return 0 ans ende, aber ansonsten kann man es nich anders machen Wink
"Ideen sind keine Coladosen, man kann sie nicht recyclen"-Dr. House
http://deeebian.redio.de/ http://goodjee.redio.de/

mabox

BeitragSo, Sep 14, 2008 22:29
Antworten mit Zitat
Benutzer-Profile anzeigen
kommt es bei ImagesOverlap nicht zu solchen problemen?
Fujitsu-Siemens Laptop, 2Ghz Intel Core2Duo Prozessor, 2GB Ram, 120GB Festplatte, ATI Mobility Radeon X1400, Windows Vista Ultimate
www.mausoft.de.tl
Dönerfresser Homepage
 

BIG BUG

BeitragMo, Sep 15, 2008 0:58
Antworten mit Zitat
Benutzer-Profile anzeigen
Nein, ImagesOverlap funktioniert, da hier nur ein Koordinatenvergleich stattfindet.
B3D-Exporter für Cinema4D!(V1.4)
MD2-Exporter für Cinema4D!(final)
 

BIG BUG

BeitragFr, März 27, 2009 17:17
Antworten mit Zitat
Benutzer-Profile anzeigen
Habe mal zwischenzeitlich auch echtes ImagesCollide benötigt. Daher hier auch noch eine Funktion um ImagesCollide direkt zu ersetzen. Wenn sich große Teile der Bilder überlappen wird diese aber langsam. Mit Banken könnte man das zumindest für statische Bilder noch wesentlich beschleunigen.
Code: [AUSKLAPPEN]

;replaces ImagesCollide because of MAV bug
Function ImgCollide(image1,xpos1, ypos1, frame1, image2, xpos2, ypos2, frame2=0, mask=0)

   Local startx, starty, endx, endy, ix, iy

   Local width1  = ImageWidth(image1)
   Local height1 = ImageHeight(image1)
   Local width2  = ImageWidth(image2)
   Local height2 = ImageHeight(image2)

   xpos1   = xpos1 - ImageXHandle(image1)
   ypos1   = ypos1 - ImageYHandle(image1)
   xpos2   = xpos2 - ImageXHandle(image2)
   ypos2   = ypos2 - ImageYHandle(image2)

   startx = xpos2 - xpos1
   starty = ypos2 - ypos1
   start2x = startx
   start2y = starty

   endx   = startx + width2
   endy   = starty + height2

   If startx < 0       Then startx = 0
   If starty < 0       Then starty = 0
   If endx   > width1  Then endx   = width1
   If endy   > height1 Then endy   = height1

   endx = endx - 1
   endy = endy - 1

   If startx > endx Or starty > endy Then Return 0

   LockBuffer ImageBuffer(image1, frame1)
   LockBuffer ImageBuffer(image2, frame2)
   For ix = startx To endx
      For iy = starty To endy

         If mask <> (ReadPixelFast(ix, iy, ImageBuffer(image1, frame1)) And $00FFFFFF) Then
         If mask <> (ReadPixelFast(ix-start2x, iy-start2y, ImageBuffer(image2, frame2)) And $00FFFFFF) Then
            UnlockBuffer ImageBuffer(image1, frame1)
               UnlockBuffer ImageBuffer(image2, frame2)
               Return 1
         EndIf
         EndIf
      Next
   Next
   UnlockBuffer ImageBuffer(image1, frame1)
   UnlockBuffer ImageBuffer(image2, frame2)

End Function
B3D-Exporter für Cinema4D!(V1.4)
MD2-Exporter für Cinema4D!(final)

Silver_Knee

BeitragSa, März 28, 2009 20:02
Antworten mit Zitat
Benutzer-Profile anzeigen
Hey du kannst die Funktion ruhig guten gewissens imagesCollide nenne. damit überschreibst du dann die blitz-interne funktion. Das funktioniert halt nur solange du in deiner ImagesCollide-Funktion nicht imageCollides verwendest. Das tust du nicht. Also mach es den coder einfacher: Die fügen die Function am ende des codes ein und brauchen sonst keine Zeile zu ändern

M0rgenstern

BeitragMo, Apr 06, 2009 13:37
Antworten mit Zitat
Benutzer-Profile anzeigen
Also ich hatte das Problem mit ImagesCollide auch.
Ich habe jetzt mal BigBugs Lösung probiert und diese funktioniert perfekt.

Eine Frage nur: Darf man die in eigenen Programmen benutzen?

LG, M0rgenstern
 

FWeinb

ehemals "ich"

BeitragMo, Apr 06, 2009 13:48
Antworten mit Zitat
Benutzer-Profile anzeigen
Ein Tutorial ist zur Erklärung da der Autor Versucht damit Typische "noob" Fehler zu erklären und daher denke ich das du den Code so verwenden darfst.

mfg

ich
"Wenn die Menschen nur über das sprächen, was sie begreifen, dann würde es sehr still auf der Welt sein." Albert Einstein (1879-1955)
"If you live each day as if it was your last, someday you'll most certainly be right." Steve Jobs

Neue Antwort erstellen


Übersicht BlitzBasic FAQ und Tutorials

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group