Main Menu

Walking on Sprites

Started by kevin, January 20, 2010, 11:15:15 AM

Previous topic - Next topic

kevin

 Walking on Sprites


  This example sets up a simple sprite scene than uses the RayHitSprite function to position a 'character' on top them.




PlayBASIC Code: [Select]
   setfps 75

// Make images

Image_FloorBlock=NewFxImage(2,10)
rendertoimage Image_FloorBlock
Box 0,0,100,100,true
rendertoscreen


// --------------------------------------------------------------------------------
// make a sprite scene, these will be a set of spirtes aligned along a sinus wave
// --------------------------------------------------------------------------------
AngleStep#=10
Xstep=20
Radius=60
Ypos=GetScreenHeight()/2

X1=0
Y1=Ypos+SinRadius(Angle#,Radius)

for xlp=Xstep to 2000 step XStep

Angle#=Angle#+AngleStep#
X2=Xlp
Y2=Ypos+SinRadius(Angle#,Radius)
Y2=Y2+CosRadius(Angle#*3,Radius/2)

ThisSprite=MakeAlignSpRiteToPOints(x1,y1,x2,y2,IMage_floorBlock)

x1=x2
y1=y2

next




// --------------------------------------------------------------------------------


; player variables
playerX#=300
PLayerY#=100
PLayerRadius#=25


; create camera to view the scene
CreateCamera 1


// --------------------------------------------------------------------------------
// Main Loop
// --------------------------------------------------------------------------------

Do


// init capture to scene mode
CaptureToScene

// clear the scene buffer of any old data
ClsScene

// capture the sprites to the scene
drawallsprites


// Run ray intersection against the entire sprite set
// now __obviously___ you wouldn''t do this is real life..

if leftkey() then playerx#=playerx#-2
if rightkey() then playerx#=playerx#+2


x1#=PLayerX#
y1#=PLayerY#
x2#=PLayerX#
y2#=PLayerY#+(PLayerRadius#*2)

capturedepth 2
linec x1#,y1#,x2#,y2#,rgb(0,255,0)

ThisSprite=GetFirstSprite()
Collision=False
While ThisSprite>0

if RayHitSprite(x1#,y1#,x2#,y2#,ThisSprite)
x2#=GetIntersectX#(2)
Y2#=GetIntersectY#(2)-1
circle x2#,y2#,5,false
Collision=true
endif

ThisSprite=GetNextSprite(ThisSprite)
EndWhile

if Collision=False
PlayerY#=PlayerY#+1
else
dist#=(y2#-y1#)
if Dist#>PLayerRadius#
PlayerY#=PlayerY#+1
else
PLayerY#=y2#-PlayerRadius#
endif
endif

circlec playerx#,playery#,playerradius#,true,$ff0000

PositionCamera 1,PLayerX#-GetScreenWidth()/2,PlayerY#-GetScreenHeight()/2


drawcamera 1

Sync

loop



Function MakeAlignSpriteToPOints(x1,y1,x2,y2,CollisionIMage)

ThisSprite=NewSprite(x1,y1,CollisionIMage)
SpriteDrawMode ThisSprite,2
positionSpriteZ ThisSprite,50

tw#=GetImageWidth(CollisionImage)
th#=GetImageHeight(CollisionImage)

dist#=GetDistance2d(x1,y1,x2,y2)
ScaleSpriteX ThisSprite,Dist#/tw#
angle#=getangle2d(x1,y1,x2,y2)
rotateSprite ThisSPrite,Angle#


SpriteCollisionMode 1,1 ;(collision mode is rotated rectangles)

EndFunction ThisSprite






Related Examples

  Walking on Sprite Collision Map
  Platformer Pixel Collisions Via Ray Casting
  Advanced Platform Collision (Vector WORLD)




ATLUS


micky4fun

#2
Hi Kevin

well been trying to muck about with this type of collision as i like the look of it ,
can you tell me why the code below works when spritecollisonmode is set to 1 , but line falls short of ground , so no good for pixel pefect
but when changing spritecollisonmode is set to 6 , pixel perfect it does not work , returns RayX2 and RayY2 as 0
am i missing something , or is there another easy way to do this as pixel perfect

PlayBASIC Code: [Select]
     loadfximage "ground.png",10

spr=getfreesprite()
CreateSprite Spr
PositionSprite Spr,0,600
SpriteImage Spr,10
SpriteCollisionMode Spr,1

; Init the Rays Starting Point
RayX1=100
RayY1=100

Do
Cls RGB(0,0,0)

RayX2=MouseX()
RayY2=MouseY()

If RayHitSprite(RayX1,RayY1,rayX2,rayY2,Spr)=true
RayX2=GetIntersectX#(0)
RayY2=GetIntersectY#(0)
EndIf

Line RayX1,RayY1,RayX2,RayY2
DrawAllSprites
Sync
Loop



thanks
mick :)

ground image im using attached

kevin


Quoteam i missing something

Yes, Ray intersection is for vector collision, not pixels.. 

micky4fun

Ok thanks Kevin

thats ashame , ile continue messing about with this for a little longer and see what happens

mick :)

kevin

#5
 
If the target object doesn't need rotation, then you can get a reasonable  approximation  as follows.


PlayBASIC Code: [Select]
   openscreen 1024,768,32,1

loadfximage "E:\Downloads\ground.png",10

spr=getfreesprite()
CreateSprite Spr
PositionSprite Spr,0,600
SpriteImage Spr,10
SpriteCollisionMode Spr,1

; Init the Rays Starting Point
RayX1=300
RayY1=300

Do
Cls RGB(0,0,0)

RayX2=MouseX()
RayY2=MouseY()

DrawAllSprites


If RayHitSprite(RayX1,RayY1,rayX2,rayY2,Spr)=true

ThisImage=getSpriteImage(Spr)
ImageXpos=GetSpritex(Spr)
ImageYpos=GetSpritey(Spr)

Collision,impactx#,impacty#=Plot_Ray_Over_image(Rayx1,Rayy1,Rayx2,Rayy2,ThisImage,ImageXpos,ImageYpos)

if Collision
rayx2=impactx#
rayy2=impacty#


Circle Rayx2,Rayy2,5,false
endif

; RayX2=GetIntersectX#(0)
; RayY2=GetIntersectY#(0)
EndIf

Line RayX1,RayY1,RayX2,RayY2
Sync
Loop




Function Plot_Ray_Over_image(Rayx1#,Rayy1#,Rayx2#,Rayy2#,ThisImage,ImageXpos,ImageYpos)

width =getimagewidth(Thisimage)
height =getimageheight(Thisimage)

Collision=False

Result=LineIntersectRect(Rayx1#,Rayy1#,Rayx2#,Rayy2#,ImageXpos,ImageYpos,ImageXpos+Width,ImageYpos+height)

if result>-1

if Result=1
Rayx1#=GetIntersectX#(0)
Rayy1#=GetIntersectY#(0)
Rayx2#=GetIntersectX#(1)
Rayy2#=GetIntersectY#(1)
endif

;linec Rayx1#,Rayy1#,Rayx2#,Rayy2#,255

dist#=getdistance2d(Rayx1#,Rayy1#,Rayx2#,Rayy2#)
dx#=Rayx2#-Rayx1#
dy#=Rayy2#-Rayy1#

if dist#<>0
nx#=dx#/dist#
ny#=dy#/dist#
else
nx#=0
ny#=0
endif

OldSurface=GetSurface()
rendertoimage ThisImage
lockbuffer

Transparentcolour=GetImageMaskCOlour(ThisImage)

for lp=0 To int(Dist#)

x#=rayx1#+(nx#*lp)
y#=rayy1#+(ny#*lp)

x#=x#-ImageXpos
y#=y#-ImageYpos
if point(X#,y#)<>Transparentcolour

Impactx#=x#+ImageXpos
Impacty#=y#+ImageYpos
Collision=true
exitfor
endif


next
unlockbuffer
rendertoimage OldSurface
endif


EndFunction Collision,ImpactX#,ImpactY#








    Note:  - Today i'd recommend using the RayToMap pixel collision functions

micky4fun

Hi Kevin

yes nice one , this looks good , will av a bit more time later today to get into this a bit deeper see what i can come up with

thanks
mick :)