Convert Map To Collision Worlds

Started by kevin, August 31, 2005, 10:19:13 AM

Previous topic - Next topic

kevin

  This example shows how you could build a collision world from a level Map. The benefit of this is that once created,you can use the sprites built in sliding collision, ray intersection, nearest colliders etc etc on this world.    

This example last tested in PB1.63w

PlayBASIC Code: [Select]
   Setfps 100

MyMap =NewMap(1)

;
TileWidth=48
TileHeight=48
Number_of_tiles = 5

; Loop through and draw a series of randomly coloured Boxes to the screen
For lp=1 To Number_of_tiles
xpos=lp*tileWidth
BoxC Xpos,0,Xpos+TileWidth,TileHeight,1,RndRGB()
Next

; Grab the box graphics that we've just drawn as image.
TempImage=GetFreeImage()
GetImage TempImage,0,0,xpos+TIleWidth,Tileheight


; Import this image into our previously defined Map.
MakeMapGFX MyMAP,TempImage,TileWidth,TileHeight,Number_Of_Tiles,RGB(0,0,0)



; =======================================================
; Read the Level in from the data statements bellow
; =======================================================

Read_Level(1,1)

Leveltransparent 1,1,0


; Draw the Level to the screen at Xpos 0 and Ypos 0
Xpos=0
Ypos=0


; Create the Collision world
MyCollisionWorld=NewWorld()
CaptureToWorld MyCollisionWorld
MakeCollisionWorldFromMap(MyMap,1,xpos,ypos)
PartitionWorld MyCollisionWorld,64

; restore drawing back to immediate mode
drawgfximmediate


PLayerSize = 32

; Create an image of a circle (for something to look at)
Cls 0
Size=PLayerSize/2
Circlec Size,Size,Size,1,$00ff00
GetImage 10,0,0,PLayerSize,PLayerSize
preparefximage 10


; create a sprite
CreateSprite 1
autocenterspritehandle 1,true
SpriteImage 1,10
spriteCollision 1,true
; Set collision mode to World
SpriteCollisionMode 1,4
SpriteCollisionWorld 1,MyCollisionWorld

; Set the Sprites Collision Circle to just smaller than then players
; image. In this example the players image is also a circle.
SpriteCollisionRadius 1,(PlayerSize/2)-2
; SpriteCollisionDebug 1,true

PositionSprite 1,150,150

; Create a Camera
CreateCamera 1


Do
CaptureToScene
ClsScene

Capturedepth 100
DrawMap MyMap,1,0,0


; MOve the Sprite around (8 way movement)
Speed=5

Xspeed=0
Yspeed=0
if LeftKey() then Xspeed=-Speed
if RightKey() then Xspeed=Speed
if UpKey() then Yspeed=-Speed
if DownKey() then Yspeed=Speed

if Xspeed<>0 or Yspeed<>0
; MOve the sprite, this will auto slide the sprite
; off any wall it hits in the Collision World
MoveSprite 1,xspeed,yspeed
endif

DrawAllSprites

;POsition the camera over the sprite
Xpos=GetSpriteX(1)-(GetScreenWidth()/2)
Ypos=GetSpriteY(1)-(GetScreenHeight()/2)
POsitionCamera 1,Xpos,Ypos

; Tell the camera to draw whats in viwe
Drawcamera 1

Sync
loop


end





; =============================================================================
; This Function converts a map Level into collision world, which is nothing
; more than drawing lines around the bounding area around of the tiles. It
; considers tile zero to be transparent (which is soft). Everything else is
; think is hard
;
; once the map is a collision world you can run ray interest on it, sliding
; collision among other things..
; =============================================================================


Acreset
Constant EdgeState_Searching =ac(1)
Constant EdgeState_FoundStart =ac(1)


Function MakeCollisionWorldFromMap(thisMap,Thislevel,xpos,ypos)

LevelWidth =GetLevelWidth(Thismap,thislevel)
LevelHeight =GetLevelHeight(Thismap,thislevel)

BlockWidth=GetMapBLockWidth(ThisMap)
BlockHeight=GetMapBLockHeight(ThisMap)

; ====================================================================
; #1 first Pass over the level looking for blocks running Left to Right
Login required to view complete source code


thaaks

QuoteThis example shows how you could build a collision world from a level Map. The benefit of this is that once created,you can use the sprites built in sliding collision, ray intersection, nearest colliders etc etc on this world.
Wooohoooo!
Will test this tonight at home - seems I'll have to buy now  :D

Kevin, that really rocks! Thanks for the great support!

Tommy

kevin

no worries, no rush... have fun :)

mindsafe

#3
Yes thank you! :-)

My name is Marco and I'm all new to PlayBasic, but I do really love it as it remindes me about the old AMOS on Amiga ;-)

I have tryed the very same with PlayMapper, but I can't get it to work properly.
Create a rather big map with Playmapper, change the filename so you load that map instead and I would like to move my box or other sprite around in that world with collisioncheck on certain obstecles and than you must also scroll around the screen.

Then I did try to use this code below, but the camera wont follow my sprite: (What am I doing wrong?): (If this code is to messy please overwrite it and create a new one that easy shows how to make this work).

PlayBASIC Code: [Select]
OpenScreen 640, 480, 32, 2

map = loadPlayMapperProfile( "Plattform1.map", 0 )

// loading the actual map
loadPlayMapperMap( "Plattform1.map", map )

// setting camera variables
x=0
y=0
thismaplevel=1

CreateCamera 1
CameraCls 1,On
LimitCamera 1,True
LimitCameraBounds 1,-100,-100,2000, 2000 //GetLevelABSWidth( Map,thismaplevel)-40,GetLevelABSHeight(Map,thismaplevel)-40
CameraViewPort 1,0,0,GetLevelABSHeight( map, thismaplevel) , GetLevelABSHeight(map, thismaplevel)
; Define some variables For a PLayer

PlayerX = 50
PlayerY = 50

PlayerWidth = 20
PlayerHeight = 20

Speed=2

DrawGFXImmediate
// main Loop
Do
CaptureToScene
ClsScene

DrawCamera 1 //If I move this line before SYNC I will not see my box as sprite.... // why?
PositionCamera 1, PlayerX, PlayerY

` ======================
` Send the map the Scene Que
` ======================

// drawing the map
For t=0 To GetMapLevels(map)-1
// DrawMap map,t,x,y
DrawMap map,t,0,0
Next t

PLayerNewX=PlayerX
PLayerNewY=PlayerY

// updating the animation (If any) on the map
UpdateMapAnims map

; Handle the players Movement
If UpKey() Then PlayerNewY=PLayerY-Speed
If DownKey() Then PlayerNewY=PLayerY+Speed
If LeftKey() Then PlayerNewX=PLayerX-Speed
If RightKey() Then PlayerNewX=PLayerX+Speed

If CheckMapImpact( Map,thismaplevel,PlayerX,playerY,PlayerNewX,PlayerNewY,PLayerWidth,PlayerHeight)
; If there was impact with the map, Then read our
; new position back.
PlayerX=GetMapImpactX()
PlayerY=GetMapImpactY()
Else
; No Collision, Then set the current players
; position To it's new position
PlayerX=PlayerNewX
PlayerY=PlayerNewY
EndIf


; draw the player (Box) To the screen
X2=playerX+PlayerWidth
Y2=playerY+PlayerHeight

//Should this be an sprite instead??
Box playerX,playerY,x2,y2,1

ThisKey=ScanCode()

Sync
Loop
DeleteLevel map, 1
DeleteAllCameras
DeleteAllImages
DeleteAllMaps





kevin

#4
Here's a quick (without testing) hack of your code.


PlayBASIC Code: [Select]
OpenScreen 640, 480, 32, 2

map = loadPlayMapperProfile( "Plattform1.map", 0 )

// loading the actual map
loadPlayMapperMap( "Plattform1.map", map )

// setting camera variables
x=0
y=0
thismaplevel=1

CreateCamera 1
CameraCls 1,On
LimitCamera 1,True
LimitCameraBounds 1,-100,-100,2000, 2000 //GetLevelABSWidth( Map,thismaplevel)-40,GetLevelABSHeight(Map,thismaplevel)-40


` ================================================
` >> Here your attempting to set the Camera Viewport to the WORLD size.. The camera views a 'screen' sized portion of the world.

` by default when you create a camera it attaches to the current surface (in this case is the screen). When it attaches it sets it's viewport to be the size of the parent surface. So if the Screen is 640/480, the camera will adopt this size..
` ================================================

` >>.CameraViewPort 1,0,0,GetLevelABSHeight( map, thismaplevel) , GetLevelABSHeight(map, thismaplevel)


; Define some variables For a PLayer

PlayerX = 50
PlayerY = 50

PlayerWidth = 20
PlayerHeight = 20

Speed=2

DrawGFXImmediate
// main Loop
Do
CaptureToScene
ClsScene


` ======================
` Send the map the Scene Que
` ======================


CurrentDepth=100

// drawing the map
For t=0 To GetMapLevels(map)-1

; set the cupture depth for the follow gfx commands
CaptureDepth CurrentDepth

// DrawMap map,t,x,y
DrawMap map,t,0,0

; Bring each layer closer to the camera. as items with a higher depth (z) are drawn first.. then the others are drawn over that..
CurrentDepth=CurrentDepth-10
Next t

// updating the animation (If any) on the map
UpdateMapAnims map


PLayerNewX=PlayerX
PLayerNewY=PlayerY

; Handle the players Movement
If UpKey() Then PlayerNewY=PLayerY-Speed
If DownKey() Then PlayerNewY=PLayerY+Speed
If LeftKey() Then PlayerNewX=PLayerX-Speed
If RightKey() Then PlayerNewX=PLayerX+Speed

If CheckMapImpact( Map,thismaplevel,PlayerX,playerY,PlayerNewX,PlayerNewY,PLayerWidth,PlayerHeight)

; If there was impact with the map, Then read our
; new position back.
PlayerX=GetMapImpactX()
PlayerY=GetMapImpactY()
Else
; No Collision, Then set the current players
; position To it's new position
PlayerX=PlayerNewX
PlayerY=PlayerNewY
EndIf


; draw the player (Box) To the screen
X2=playerX+PlayerWidth
Y2=playerY+PlayerHeight

//Should this be an sprite instead??
` You haven't told
` set teh capture depth for the following gfx commands
CaptureDepth 10
Box playerX,playerY,x2,y2,1


sw=getscreenwidth()

; center the camera aroudn the players point..
PositionCamera 1, PlayerX-(sw/2), PlayerY-(sh/2)

; process the captured items in the scene que to the screen.
DrawCamera 1




ThisKey=ScanCode()

Sync
Loop
DeleteLevel map, 1
DeleteAllCameras
DeleteAllImages
DeleteAllMaps




mindsafe

#5
Man you are quick! Yes, now it's working like a charm...
I do have to studdy the source a little bit more to get
it going with PlayBasic!

This line did a better job:
LimitCameraBounds 1,0,0,GetLevelABSWidth( Map,thismaplevel)+10,GetLevelABSHeight(Map,thismaplevel)+10

I also changed this line:
PositionCamera 1, PlayerX-(sw/2), PlayerY-(sh/2)-100

Now its like I want it to be...

THANK YOU and also thank you for creating Playbasic! :-)