Walking on Sprites
This example sets up a simple sprite scene than uses the RayHitSprite function to position a 'character' on top them.
[pbcode]
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
[/pbcode]
Related Examples
Walking on Sprite Collision Map (http://www.underwaredesign.com/forums/index.php?topic=3339.0)
Platformer Pixel Collisions Via Ray Casting (http://www.underwaredesign.com/forums/index.php?topic=3163.0)
Advanced Platform Collision (Vector WORLD) (http://www.underwaredesign.com/forums/index.php?topic=1364.0)
nice exampale ;)
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
[pbcode]
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
[/pbcode]
thanks
mick :)
ground image im using attached
Quoteam i missing something
Yes, Ray intersection is for vector collision, not pixels..
Ok thanks Kevin
thats ashame , ile continue messing about with this for a little longer and see what happens
mick :)
If the target object doesn't need rotation, then you can get a reasonable approximation as follows.
[pbcode]
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#
[/pbcode]
Note: - Today i'd recommend using the RayToMap pixel collision functions
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 :)