RayHitMapPixels
Collision = RayHitMapPixels(ThisMap, TheLevel, StartX, StartY, EndX, EndY)
 
Parameters:

    ThisMap = The Index of the map you query for a collision
    TheLevel = The level within the map to query
    StartX = The starting X coordinate of the ray
    StartY = The starting Y coordinate of the ray
    EndX = The ending X coordinate of the ray
    EndY = The ending Y coordinate of the ray
Returns:

    Collision = The collision state, It'll return True (1) in an impact occurs and false (0) if it didn't
 

      The RayHitMapPixels() function checks if a ray impacts upon map level at pixel level. The function uses a method known as ray casting, which is fancy way of saying the algorithm steps along the line looking for impacts upon any none transparent pixels within the map. So the ray is traced from the starting coordinate through to the end coordinate if no impact is found. When an impact occurs, the functions returns true (1) and the coordinate of that impact will be stored in vertex zero in GetIntersectX#(0) and GetIntersectY#(0).

      Detecting impacts on the map can be useful is number of different gaming situations, two that come to mind would be detecting line of sight and of course projectile impacts with the environment.


      Line of sight calculations are common in video game character AI, where we might want our character to only react to the player (or other characters) when they're clearly in view. For example, imagine our computer controlled character is meant to only fire towards the player when the player is in clear sight. If it fired just every time in the direction of the target, then it'd firing into walls other obstructions and the player would soon see the character isn't that smart. . It's precisely these types of situations why commands such as RayHitMapPixels are in PlayBASIC. Now assuming our game environment is constructed using a map, or we at least are using a map for collisions, we can detect if our character can see the player by casting a ray between the two character positions. To do this we use RayHitMapPixels giving the command the map & level, with the starting coordinate of the character wanting to fire and the destination coordinate of the character it want to fire at. If the ray hits the environment, the way is obstructed, if not, the way is clear. So our character can happily fire towards the player.


      Another situation where RayHitMapPixels can be very helpful, is when we plot the path of projectiles across a map. When we have fast moving objects in a game, the temptation is that we need to check for impacts between our moving object (like a bullet) and the game environment every time the projectile moves. There would no doubt be situations where that might well be the only solution, like when the game environment is changing every refresh, but that's generally not the case. In most games the game environment is static, what this allows to do is work out the projectiles complete flight path creation to potential impact with the game environment, when it's fired.. Now assuming we have the angle the project is going to be moving in, we can use COS / SIN to calculate the expected end point of the moving object. Once we've to end point, we use RayHitMapPixels to check for any impacts along the path.


      Regardless if it hits the world or not, we've gathered some important information about this projectile, namely it's life span. To calculate it's life span in frames, we take distance the object will be travel (GetDistance2D), and divide that by it's speed (number of pixel it's moving per frame). This gives us how many times the object will move before impacting the world. Knowing when it's hit the world up front, negates the need to check for impacts between the projectile and world while it's moving. What we're doing here, is swapping a constant overhead for a one time overhead. Which is generally a more efficient solution, the more projectiles you have.




FACTS:


      * RayHitMapPixels traces across the map pixel by pixel, so it's best used on maps with FX formatted blocks.

      * RayHitMapPixels is optimized for speed over accuracy, so the there's bound to be some inaccuracy when tracing long rays, or parts of map where the solid pixels are tiny.



 
Example Source: Download This Example
;     -----------------------------------------------------
;             --------->> SET UP <<------------
;     -----------------------------------------------------
  
  SetFPS 75
  
; create the random map from some circles
  Map,Level=Build_Random_Map(32,32)
  
  
; make a backdrop picture
  BackDrop=NewImage(800,600)
  RenderToImage Backdrop
  c1=RndRGB()
  c2=RndRGB()
  ShadeBox 0,0,800,600,c1,c1,c2,c2
  RenderToScreen
  
  
; create a camera to view the scene with
  Cam=NewCamera()
  CameraCls Cam,off
  
  
  
;     -----------------------------------------------------
;        --------->> MAIN LOOP OF PROGRAM <<------------
;     -----------------------------------------------------
  
  Do
     
   ; Get the camera current position
     CamX=GetCameraX(cam)
     CamY=GetCameraY(cam)
     
   ; Get the mouse position
     MX=MouseX()+CamX
     MY=MouseY()+CamY
     
     
   ; tell PB to capture the following drawing commands
     CaptureToScene
     
   ; clear the scene buffer so it's empty
     ClsScene
     
   ; set the capture depth of the next item to a depth of
   ; 100 units
     CaptureDepth 100
     DrawImage BackDrop,CamX,CamY,false
     
     
   ; draw the map level
     CaptureDepth 50
     DrawMap map,Level,0,0
     
     
   ; Check Rays to Map For intersection
     
     CheckRays(Map,Level,MX,MY,300,128)
     
     
   ; draw the scene with this camera
     DrawCamera cam
     
     
   ; check if the ENTER key was pressed
     If EnterKey()
      ; If so, toggle Debug mode on the map
        MapDebug Map,1-GetMapDebug(Map)
        FlushKeys
     EndIf
     
     
     
   ; check if the users wanted to move the camera
     If LeftKey()  Then     MoveCamera Cam,-2,0
     If RightKey() Then     MoveCamera Cam,2,0
     If UpKey()    Then     MoveCamera Cam,0,-2
     If DownKey()  Then     MoveCamera Cam,0,2
     
     SetCursor 0,0
     Ink $ffffff
     Print "RayHitMapPixels"
     Sync
  Loop
  
  
  
;     -----------------------------------------------------
;     ------------->> Check Rays To mape <<------------
;     -----------------------------------------------------
  
  
Function CheckRays(Map,Level,Xpos,Ypos,RAdius,Rays)
  AngleStep#=360.0/Rays
  CaptureDepth 20
  
  
  For lp=0 To rays-1
     angle#=lp*AngleStep#
     x2#=CosNewValue(xpos,Angle#,radius)
     y2#=SinNewValue(ypos,Angle#,radius)
     Collision=RayHitMapPixels(Map,Level,xpos,ypos,x2#,y2#)
     If Collision
        hitx#=GetIntersectX#(0)
        hity#=GetIntersectY#(0)
        Line xpos,ypos,hitx#,hity#
        CircleC hitx#,hity#,5,true,$00ff0000
     Else
        Line xpos,ypos,x2#,y2#
     EndIf
  Next
  
  
EndFunction
  
  
  
  
;     -----------------------------------------------------
;     ------------->> Build Random Map Scene <<------------
;     -----------------------------------------------------
  
  
Function Build_Random_Map(BlockWidth,BlockHeight)
  
  
  BackdropColour=$008f00
  
  screen=NewFXImage(2400,1600)
  RenderToImage screen
  Cls  BackdropColour
  CircleC 800,400,400,true,$8f8f8f
  CircleC 1700,400,400,true,$0f8faf
  
  For lp=0 To 150
     x=Rnd(2400)
     y=Rnd(1600)
     rx=RndRange(50,150)
     ry=RndRange(10,50)
     EllipseC x,y,rx,ry,true, BackdropColour
  Next
  
  
  Map=NewMap(50)
  
; Create 1024 FX BLocks for this map
  CreateMapGFX  Map,BlockWidth,BlockHeight,1024,BackdropColour,2
  
  BlocksX=GetSurfaceWidth()/BlockWidth
  BlocksY=GetSurfaceHeight()/BlockWidth
  
  Level=NewLevel(Map,BlocksX,BlocksY)
  LevelTransparent Map,Level,0
  GetMapBlk Map,Tile,0,0
  
  Tile=1
  For ylp=0 To GetLevelHeight(map,level)-1
     Ypos=ylp*BlockHeight
     If Ypos+BlockHeight<=GetSurfaceHeight()
        For xlp=0 To GetLevelWidth(map,level)-1
           Xpos=xlp*BlockWidth
           GetMapBlk Map,Tile,Xpos,ypos
           
           If GetMapBlockTransparent(Map,Tile)>-1
              PokeLevelTile Map,Level,xlp,ylp,tile
              tile++
           EndIf
           If Tile=>GetMapBlocks(Map) Then ExitFor ylp
        Next
     EndIf
  Next
  
  RenderToScreen
  
EndFunction Map,Level
  
  
  
  
 
Related Info: CircleHitMap | CircleHitMapPixels | CircleOccludeMap | GetMapBlockTransparent | QuadHitMap | QuadHitMapPixels | QuadOccludeMap | RectHitMap | ShapeHitMap | ShapeHitMapPixels | TriangleHitMap | TriangleHitMapPixels | TriangleOccludeMap :
 


(c) Copyright 2002 - 2024 - Kevin Picone - PlayBASIC.com