Raycast fake 3d shapes the easy way. by Cliff Mellangard 3DEGS28th May 2012 12:44
|
---|
Summary A simple demostration on how to make fake 3d shapes in agk. Description Do we nead an long description :) Code ` This code was downloaded from The Game Creators ` It is reproduced here with full permission ` http://www.thegamecreators.com rem rem AGK Application rem rem Landscape App setorientationallowed(0,0,1,0) #Constant FALSE 0 #Constant TRUE 1 Rem // We set the syncrate to be locked at 60 so pc and mobile device speeds are as close as possible REM // i get frame rates around 200-400 on pc and 20-30 on android wich give an huge differrence even on timed movement! SetSyncRate ( 0 , 0 ) SetVirtualResolution ( 320, 240 ) Global Circle Circle=LoadImage( "circle.png" ) REM // This is the scale that everything is created in #Constant World_Scale 64 type sRaycast Column As Integer Column_Width As Integer Projection As Integer Angle As Float Width As Integer Angle_In_Fov As Float Angle_In_World As Float endtype Global Raycaster As sRaycast REM // Here do we set how wide the raycaster should be. REM // If we use the half actual screen width will we gain almost the double framerate. REM /////////////////////////////////////////////////////////////////////////////////// Raycaster.Width = GetvirtualWidth()/2 REM // How much to move the screen column sideways when rendering and its size REM ////////////////////////////////////////////////////////////////////////// Raycaster.Column_Width = GetvirtualWidth()/ Raycaster.Width REM // This is the amount we increase the angle when we cast our rays REM // This is 60/Screen width because the field of view have 60 degrees,30 on each side of the player. REM ///////////////////////////////////////////////////////////////////////////////////////////////// Raycaster.Angle=60.0/Raycaster.Width REM // Distance to the projection Plane REM /////////////////////////////////// Raycaster.Projection=277 REM // This sprite will we use to draw our fake 3d visuals Raycaster.Column = CreateSprite ( 0 ) SetSpriteSize ( Raycaster.Column , Raycaster.Column_Width , GetVirtualHeight() ) SetSpriteVisible(Raycaster.Column,0) type sPlayer ID as integer X as float Y as float Angle as float dir as integer rot as float speed as integer moveSpeed as float rotSpeed as float endtype global Player as sPlayer REM // how far (in World units) does the player move each step/update( its this number * frame time ) Player.moveSpeed = 60.0 Player.rotSpeed = 60.0 REM // This time do we do it simple and use an sprite Player.ID = CreateSprite ( 0 ) player.X=10 player.Y=110 SetSpritePositionByOffset(Player.ID,player.X,player.Y) REM // Shapes used by the raycaster Global RC_Cube_Collider RC_Cube_Collider = CreateSprite ( 0 ) SetSpriteSize ( RC_Cube_Collider , World_Scale , World_Scale ) REM // 0=no shape, 1=circle, 2=box, 3=polygon SetSpriteShape(RC_Cube_Collider,2) SetSpritePositionByOffset(RC_Cube_Collider,260,90) Global RC_Sphere_Collider RC_Sphere_Collider = CreateSprite ( 0 ) SetSpriteSize ( RC_Sphere_Collider , World_Scale , World_Scale ) SetSpriteImage(RC_Sphere_Collider,Circle) REM // 0=no shape, 1=circle, 2=box, 3=polygon SetSpriteShape(RC_Sphere_Collider,1) SetSpritePositionByOffset(RC_Sphere_Collider,260,160) rem A Wizard Did It! global GFT# do GFT# = GetFrameTime() Move_Player() Raycaster.Angle_In_World = Player.Angle-30.0 Raycaster.Angle_In_Fov = 0.0 For t=0 to Raycaster.Width X# = player.X + ( cos( Raycaster.Angle_In_World ) * 400.0 ) Y# = player.Y + ( Sin( Raycaster.Angle_In_World ) * 400.0 ) if SpriteRayCast( GetSpriteX(Player.ID), GetSpriteY(Player.ID) , X# , Y# ) Then Draw_Screen_Column(t) REM // Increase the angle in world space for the next ray Raycaster.Angle_In_World = Raycaster.Angle_In_World + Raycaster.Angle REM // Increase the angle inside the field of view Raycaster.Angle_In_Fov = Raycaster.Angle_In_Fov + Raycaster.Angle next t Print(str( Screenfps() )) REM // Exit game / escape on computer and back button on device if GetRawKeyState(27) = 1 then end Sync() loop Function Draw_Screen_Column(X_Pixel) SetSpriteVisible(Raycaster.Column,1) dist=( ( World_Scale / ( GetDistance( player.X, player.Y, GetRayCastX() , GetRayCastY() )*cos( 30.0 - Raycaster.Angle_In_Fov )))*Raycaster.Projection ) SetSpriteSize ( Raycaster.Column , Raycaster.Column_Width , dist ) SetSpritePositionByOffset(Raycaster.Column,X_Pixel*Raycaster.Column_Width,GetvirtualHeight()/2) SetSpriteColor ( Raycaster.Column , dist , dist , dist , 255 ) DrawSprite(Raycaster.Column) SetSpriteVisible(Raycaster.Column,0) Endfunction Function Move_Player() if GetRawKeyState(39) // Turn Right Player.Angle = GetSpriteAngle(Player.ID)+ (Player.rotSpeed*GFT#) SetSpriteAngle( Player.ID , Player.Angle ) endif if GetRawKeyState(37) // Turn Left Player.Angle = GetSpriteAngle(Player.ID)- (Player.rotSpeed*GFT#) SetSpriteAngle( Player.ID , Player.Angle ) endif Player.speed = 0 if GetRawKeyState(38) then Player.speed = 1 if GetRawKeyState(40) then Player.speed = -1 if Player.speed<>0 // player will move this far along the current direction vector move# = player.speed * (player.moveSpeed*GFT#) player.X = player.X + ( cos(Player.Angle) * move# ) player.Y = player.Y + ( Sin(Player.Angle) * move# ) SetSpritePositionByOffset( Player.ID , player.X , player.Y ) endif Endfunction Function GetDistance( x#, y#, x2#, y2#) d# = sqrt( ((x# - x2#)^2) + ((y# - y2#)^2) ) Endfunction d# |