UnderwareDESIGN

PlayBASIC => Resources => Source Codes => Topic started by: kevin on July 06, 2005, 01:48:15 AM

Title: Sprite to world alignment
Post by: kevin on July 06, 2005, 01:48:15 AM
This example uses the world and ray to world intersection features
in PB1.08 to help position sprites on sloped ground  with rough
alignment to the terrain.

  There's a few bugs,like really movement and aligment should be handed
together.  but ya get that :)



[pbcode]


Constant ShowVectors=True


; create a Blue Block to represent a character
Constant Height=64
Cls 255
Getimage 1,0,0,32,Height
preparefximage 1

; create the players sprite
createsprite 1
spriteimage 1,1
spritedrawmode 1,2
centerspritehandle 1


; build a world with
MyWOrld=BuildWorld()


; create the camera
CreateCamera 1

; start of Main DO/Loop
Do
; Set PB to Capture all drawing operation to the scene buffer
   Capturetoscene
   clsscene


; Let the user Control the Sprite left/right
   speed=5
  mx=0   
   if LeftKey() then mx=-speed
   if RightKey() then mx=speed
   movesprite 1,mx,0


   PositionSpriteOnGround(1,myWorld,4)

   AlignSpriteToGround(1,myWorld)


; position camera at the sprite position
   positioncamera 1,GetSpriteX(1)-GetScreenwidth()/2,GetSpriteY(1)-GetScreenHeight()/2


 ; draw the world/scene   
   Cameragrabworld 1,myworld
  drawallsprites
   DRawcamera 1   

   SYnc   
loop



Function PositionSpriteOnGround(ThisSprite,ThisWorld,Speed)
   ; get the sprites Position
   x=getspritex(ThisSprite)
   y=getspritey(ThisSprite)+speed

   newy=y

   For Xoffset=-8 to 8 step 8
   ; cast a ray from the center of sprite downwards
 Flag=Rayintersectworld(ThisWorld,x+Xoffset,y-(height/2),x+Xoffset,y+(height*2))

 line x+Xoffset,y-(height/2),x+Xoffset,y+(height*2)

   ; check if the ray hit the world(ground in this example)
 if Flag
    ;get the height of the ground at this point
    groundY=GetIntersecty#(0)
 ; reposition the sprite if it's Y was lower than the ground
    if (newy+(Height/2))=>GroundY then newy=groundY-((height/2)-1)
 endif
   next
   

 ; position the sprite after collision   
   positionsprite ThisSprite,x,newy   

EndFunction

   
; =============================================================================
;  This function calc's a rough approximation of this sprite to the ground.
; =============================================================================


Function AlignSpriteToGround(ThisSprite,ThisWorld)
   Static OldAngle#

   ; get the sprites Position
   x=getspritex(ThisSprite)
   y=getspritey(ThisSprite)


   CurrentAngle#=GetSpriteAngle(ThisSprite)
;   CurrentAngle#=0
   GroundAngle#=0

; Project line from /through sprites base
;Calc points for LEFT Ray
   Left_rayx1#,Left_rayy1#=Rotate_Vertex(CurrentAngle#,-15,(height/2)*-1)
   Left_rayx2#,Left_rayy2#=Rotate_Vertex(CurrentAngle#,-15,(height*1.0))

   Left_rayx1#=Left_rayx1#+x
   Left_rayy1#=Left_rayy1#+y
   Left_rayx2#=Left_rayx2#+x
   Left_rayy2#=Left_rayy2#+y

 #if ShowVectors=true
 line Left_rayx1#,Left_rayy1#,Left_rayx2#,Left_rayy2#
   #endif
   
; cast a ray from the center of sprite downwards
   LeftFlag=Rayintersectworld(ThisWorld,Left_rayx1#,Left_rayy1#,Left_rayx2#,Left_rayy2#)

; check if the ray hit the world(ground in this example)
   if LeftFlag
   ;get point where the ray impact the ground (on the left side)
      LeftGroundX#=GetIntersectX#(0)
 LeftGroundY#=GetIntersectY#(0)
 LeftGroundNX#=GetnormalX#(0)
 LeftGroundNY#=GetnormalY#(0)
;  LeftDist#=getdistance2d(left_rayx1#,Left_rayy1#,LeftGroundX#,LeftGroundY#)

    #if ShowVectors=true
    x2#=LeftGroundX#+(LeftGroundNX#*50)
    y2#=LeftGroundY#+(LeftGroundNY#*50)
    line LeftGroundX#,LeftGroundY#,x2#,y2#
 #endif
   endif



;Calc points for LEFT Ray
   right_rayx1#,Right_rayy1#=Rotate_Vertex(CurrentAngle#,13,(height/2)*-1)
   Right_rayx2#,Right_rayy2#=Rotate_Vertex(CurrentAngle#,13,(height*1.0))

   right_rayx1#=right_rayx1#+x
   right_rayy1#=right_rayy1#+y
   right_rayx2#=right_rayx2#+x
   right_rayy2#=right_rayy2#+y

 #if ShowVectors=true
 line right_rayx1#,right_rayy1#,right_rayx2#,right_rayy2#
   #endif
   
; cast a ray from the center of sprite downwards
   RightFlag=Rayintersectworld(ThisWorld,right_rayx1#,Right_rayy1#,right_rayx2#,Right_rayy2#)

; check if the ray hit the world(ground in this example)
   if RightFlag
   ;get point where the ray impact the ground (on the left side)
    RightGroundX#=GetIntersectX#(0)
 RightGroundY#=GetIntersectY#(0)
 RightGroundNX#=GetnormalX#(0)
 RightGroundNY#=GetnormalY#(0)
;  RightDist#=getdistance2d(right_rayx1#,Right_rayy1#,Rightgroundx#,Rightgroundy#)

    #if ShowVectors=true
    x2#=RightGroundX#+(RightGroundNX#*50)
    y2#=RightGroundY#+(RightGroundNY#*50)
    line RightGroundX#,RightGroundY#,x2#,y2#
 #endif
   endif


   
; If both rays hit the ground.
   if RightFlag=true and LeftFlag=true

   ; Calc the average of the two grond normals
 AverageNx#=(RightGroundNX#+LeftGroundNX#)/2    
 AverageNy#=(RightGroundNy#+LeftGroundNy#)/2    
   
   ; get the angle of the averaged normal  
 GroundAngle#=atanfull(AverageNy#,AverageNx#)    
 
   ; project a ray to show the direction
    #if ShowVectors=true
    x2#=X+cos(GroundAngle#)*250
    y2#=Y+sin(GroundAngle#)*250
    line X,Y,x2#,y2#
 #endif  
   else
 currentangle#=270
 groundangle#=270
 
   endif
 
   
   Currentangle#=curveangle(groundangle#,OldAngle#,10)

   RotateSprite Thissprite,CurrentAngle#+90

   Oldangle#=currentangle#

EndFunction


Function Rotate_Vertex(Angle#,X#,y#)
 newx#=((cos(Angle#)*x#)-(sin(Angle#)*y#))
 newy#=((cos(Angle#)*y#)+(sin(Angle#)*x#))
Endfunction newx#,newy#


Function BuildWorld()
   MyWOrld=GetFreeWorld()
   
   CReateWOrld MyWorld
   Capturetoworld Myworld

   Xpos=-500
   ypos=0
   sh=getscreenheight()/2
   
   repeat
 xpos2=xpos+rndrange(25,100)
 ypos2=sh+sinradius(xpos,70+rnd(10))

 line xpos2,ypos2,xpos,ypos  
 
 xpos=xpos2
 ypos=ypos2
   until xpos>10000
   
; Partition  The world up into 100*100 pixel regions
   PartitionWorld MyWorld,48
; restore drawing to normal mode
   drawgfximmediate
    
EndFunction MyWorld


[/pbcode]

Title: Sprite to world alignment
Post by: Draco9898 on July 06, 2005, 04:21:52 AM
Very nice, thanks alot