TGC Codebase Backup



Raycast fake 3d shapes the easy way. by Cliff Mellangard 3DEGS

28th May 2012 12:44
Summary

A simple demostration on how to make fake 3d shapes in agk.



Description

Do we nead an long description :)
Its fake 3d.
You will nead an image file named circle.png that have an plain circle shape.



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#