sprite outline

Advanced game related topics
pythagoras_156
User
User
Posts: 13
Joined: Wed Aug 20, 2003 11:08 am

sprite outline

Post by pythagoras_156 »

Here is a procedure i wrote to create an outline for a sprite. It can be useful for example if you want to highlight a selected sprite object. The idea is to scan the sprite in four directions (left to right, right to left, top to bottom, bottom to top) and to write a specified outline color at the sprite boundaries. By excluding the transparent color it allows for a near-perfect outline. I say near-perfect because due to the scan loop breaking each time a boundary is met, a few boundaries pixels are not taken in account.
Although, it is already quite fast, i wonder if it can be accelerated even more or if anyone has a better idea to get a perfect outline.

Code: Select all


#GFX_OUTLINE = 1

Procedure DisplaySpriteOutline(sprite_id.l,x.l,y.l,transparent_color.l,outline_color.l)
  
  CopySprite(sprite_id,#GFX_OUTLINE)
 
  ; From left to right - top to bottom
  StartDrawing(SpriteOutput(#GFX_OUTLINE)) 
    adr=DrawingBuffer() 
    add=DrawingBufferPitch() 
  StopDrawing() 
  For j=0 To SpriteHeight(#GFX_OUTLINE)-1 
    *adr2 =adr 
    For i=0 To SpriteWidth(#GFX_OUTLINE)-1
      color.l = PeekL(*adr2)
      If color <> transparent_color : PokeL(*adr2,outline_color) : break : EndIf
      *adr2+4
    Next
    adr+add 
  Next 
  
  ; From right to left - top to bottom
  StartDrawing(SpriteOutput(#GFX_OUTLINE)) 
    adr=DrawingBuffer() 
    add=DrawingBufferPitch() 
  StopDrawing()
  For j=0 To SpriteHeight(#GFX_OUTLINE)-1 
    *adr2 =adr + (4*(SpriteWidth(#GFX_OUTLINE)-1))
    For i=0 To SpriteWidth(#GFX_OUTLINE)-1
      color.l = PeekL(*adr2)
      If color <> transparent_color : PokeL(*adr2,outline_color) : break : EndIf
      *adr2-4
    Next
    adr+add 
  Next 
  
  ; From top to bottom - left to Right
  StartDrawing(SpriteOutput(#GFX_OUTLINE)) 
    adr=DrawingBuffer() 
    add=DrawingBufferPitch() 
  StopDrawing() 
  For i=0 To SpriteWidth(#GFX_OUTLINE)-1
    *adr2 = adr
    For j=0 To SpriteHeight(#GFX_OUTLINE)-1 
      color.l = PeekL(*adr2)
      If color <> transparent_color : PokeL(*adr2,outline_color) : break : EndIf
      *adr2+add 
    Next 
    adr+4
  Next
  
  ; From bottom to top - left to Right
  StartDrawing(SpriteOutput(#GFX_OUTLINE)) 
    adr=DrawingBuffer() 
    add=DrawingBufferPitch() 
  StopDrawing() 
  For i=0 To SpriteWidth(#GFX_OUTLINE)-1
    *adr2 = adr +(add*(SpriteHeight(#GFX_OUTLINE)-1))
    For j=0 To SpriteHeight(#GFX_OUTLINE)-1 
      color.l = PeekL(*adr2)
      If color <> transparent_color : PokeL(*adr2,outline_color) : break : EndIf
      *adr2-add 
    Next 
    adr+4
  Next
   
  TransparentSpriteColor(#GFX_OUTLINE,Red(transparent_color),Green(transparent_color),Blue(transparent_color))
  DisplayTransparentSprite(#GFX_OUTLINE,x,y)
  FreeSprite(#GFX_OUTLINE)
EndProcedure 

; TEST PROGRAM
InitSprite()
OpenWindow(1,100,100,100,#PB_Window_SystemMenu,"Outline")
OpenWindowedScreen(WindowID(),0,0,100,100,0,0,0)
; Load the sprite you want to test the procedure with and set the correct transparent color.
LoadSprite(2,"test.bmp") : TransparentSpriteColor(252,252,252)

Repeat 
  FlipBuffers()
  ClearScreen(0,0,0)
  DisplayTransparentSprite(2,50,50)
  DisplaySpriteOutline(2,50,50,$FCFCFC,$FF0000)
Until EventID = #PB_EventCloseWindow 

Pythagoras