zoomsprite & spritepixelcollision

Just starting out? Need help? Post your questions and find answers here.
User avatar
[blendman]
Enthusiast
Enthusiast
Posts: 297
Joined: Thu Apr 07, 2011 1:14 pm
Location: 3 arks
Contact:

zoomsprite & spritepixelcollision

Post by [blendman] »

Hi

i would how to get correct collision with zoomsprite() & spritepixelcollision().

Here is my test code :

Code: Select all

If InitSprite() = 0 Or InitKeyboard() = 0 Or InitMouse() = 0
  MessageRequester("Error", "Can't open the sprite system", 0)
  End
EndIf

flag = #PB_Window_ScreenCentered|#PB_Window_SystemMenu
If OpenWindow(0,0,0,1024,768,"SetSpriteImage", flag)=0 Or OpenWindowedScreen(WindowID(0),0,0,1024,768)=0
  MessageRequester("Error", "Can't open the sprite system", 0)
  End
EndIf

UsePNGImageDecoder()

Procedure SetSpriteImage(sprite, image)
  
  ; change the image on a sprite
  Shared w1, h1
  
  w = ImageWidth(image)
  h = ImageHeight(image)
  
  If StartDrawing(SpriteOutput(sprite))
    ; erase the sprite
    DrawingMode(#PB_2DDrawing_AllChannels)
    Box(0, 0, OutputWidth(), OutputHeight(),RGBA(0,0,0,0))
    
    DrawingMode(#PB_2DDrawing_AlphaBlend)
    DrawImage(ImageID(image), 0, 0, w1, h1)
    StopDrawing()
  EndIf
  
  ZoomSprite(sprite, w, h)
  
EndProcedure

Procedure AddSprite()
  
  Shared w1, h1
  
  w1 = ImageWidth(0)
  h1 = ImageHeight(0)

  CreateSprite(1, w1, h1,#PB_Sprite_AlphaBlending|#PB_Sprite_PixelCollision)
  SetSpriteImage(1,0)
  
EndProcedure

Procedure SetSpriteSize(sprite, width, height)
  
  ZoomSprite(sprite, width, height)
  
EndProcedure

KeyboardMode(#PB_Keyboard_International)

LoadImage(0,#PB_Compiler_Home + "Examples\Sources\Data\GeeBee2.bmp") 

LoadImage(1,#PB_Compiler_Home + "Examples\Sources\Data\world.png") 
w2 = ImageWidth(1)
h2 = ImageHeight(1)

AddSprite()

SetSpriteImage(1, 1)
w.d = SpriteWidth(1)
h.d = SpriteHeight(1)
SetSpriteSize(1, w*20, h*20)


#SpriteMouse = 2
CreateSprite(#SpriteMouse, 16, 16, #PB_Sprite_AlphaBlending|#PB_Sprite_PixelCollision)
If StartDrawing(SpriteOutput(#SpriteMouse))
  Box(0, 0, OutputWidth(), OutputHeight(),RGB(50,0,255))
  StopDrawing()
EndIf

SpriteQuality(0)



Repeat
  
  Repeat
    
    event = WaitWindowEvent(1)
    
    Select event
      Case #PB_Event_CloseWindow
        quit = 1
    EndSelect
        
  Until event = 0 Or quit = 1
  
  x = WindowMouseX(0)
  y = WindowMouseY(0)
  
  ExamineKeyboard()
  
  If KeyboardReleased(#PB_Key_A)
    image= 1 - image
    SetSpriteImage(1, image)
    w = SpriteWidth(1)
    h = SpriteHeight(1)
  EndIf
  
  If KeyboardPushed(#PB_Key_Up)
    w *(1.01)
    h *(1.01)
    SetSpriteSize(1, w, h)
  EndIf 
  If KeyboardPushed(#PB_Key_Down)
    w *(0.99)
    h *(0.99)
    SetSpriteSize(1, w, h)
  EndIf
  
  FlipBuffers()
  ClearScreen(RGB(50,50,50))
  
  ; display the sprite   
  DisplayTransparentSprite(1, 200, 200)
  DisplayTransparentSprite(#SpriteMouse, x, y)
  
  If SpritePixelCollision(1, 200, 200, #SpriteMouse, x, y) 
    Debug "collision : " + x + " / " + y
  EndIf
  ; draw the bounding box for the sprite
  If StartDrawing(ScreenOutput())
    DrawingMode(#PB_2DDrawing_Outlined)
    Box(200, 200, SpriteWidth(1),SpriteHeight(1), RGB(255,0,0))
    StopDrawing()
  EndIf
  
Until quit = 1 Or KeyboardReleased(#PB_Key_Escape)

CloseScreen()
End
I don't have the collision if the mouse is inside the sprite, but near the top or bottom, or right or left.

So is it a bug or is my code wrong ?

Thanks for your answer ;)
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8425
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Re: zoomsprite & spritepixelcollision

Post by netmaestro »

I think your code itself is fine. I also think that SpritePixelCollision is working right. There are two ways to make the code "appear" to work perfectly: 1) Remove the #PB_Sprite_AlphaBlending flag; or 2) Don't zoom. Both of these changes accomplish one thing: they increase the intensity of the alpha layer on the target sprite, particularly around the edges where antialiasing is in place. The flag removal simply forces the alpha level of every pixel in the sprite to be 255, while the zoom removal greatly decreases the displayed size of the sprite so that accurate collision testing looks accurate to the human eye.

The cause of the difficulty here, if one can call it that, is that the collision is being observed at such a magnification that it appears to be wrong when in fact it's right. The collision algo will of necessity have some tolerance for pixels with low alpha values and that's what we're seeing in this example.

The command is supported to work with zoomed sprites, but it can't be absolutely perfect and still look accurate in all cases. 20x is simply too much zoom for a sprite with an antialiased edge if you want it to look perfect. Your solution would be to use a larger image for the sprite and zoom it smaller using negative values if you need it tiny sometimes.
BERESHEIT
Post Reply