The easiest way to code a 3d Platformer.

Source-code only - please, don't post questions here.
relsoft
Posts: 1765
Joined: May 27, 2005 10:34
Location: Philippines
Contact:

The easiest way to code a 3d Platformer.

Postby relsoft » Aug 17, 2012 2:24

Hi, This started of as a proof of concept for a DS game. It was a $#@$& to port to the DS though (-8 to +8 vertex coordinate limits) but I got it working. I thought I might share the FB versions here.

The idea is to be able to make a 3d engine using standard 2D screen coordinate system.

Update:

Textured version now up for grabs!

http://rel.phatcode.net/junk.php?id=126

Map is text based so you can edit the level from inside code.
Code is now heavily commented.

Also added:

Code: Select all

1. A way to texture the level using a tileset
2. 3 camera scrolling behaviors
3. Parallax Background
4. Sprites


Images by Marc Russel from gfx-lib fuzed

DS screen:
Image

1. Simple

Code: Select all

''*****************************************************************************
''
''   2.5D Engine
''   Relminator (Richard Eric M. Lope)
''    http://rel.phatcode.net
''
''    This is probably the easiest way to make a 3d game
''   Features:
''   * 1:1 ratio of 3D coords to Screen
''   * Collisions are in tilebased 2D
''   * Rendering can be camera based (uber fast)
''   * Any 2D tilebased game can be converted to this
''
''   Controls
''   
''   SPACE = Jump
''   ARROW KEYS = Move
''   F1 = Paper mario mode?
''   F2/F3 = Zoom
''
''*****************************************************************************

#include once "fbgfx.bi"
#include once "/gl/gl.bi"
#include once "/gl/glu.bi"   


''*****************************************************************************
declare sub GL_Screen_Init(byval screen_wid as integer, byval screen_hei as integer, byval flags as integer = 0)

'' Drawing stuff
''*****************************************************************************
declare sub DrawCube( x as single, y as single, z as single, Size as single, Red as single, Green as single, Blue as single )
declare sub DrawMap()


''*****************************************************************************
const as integer SCREEN_WIDTH = 640
const as integer SCREEN_HEIGHT = 480

const as integer TILE_SIZE = 32


const as integer MAP_WID = SCREEN_WIDTH\TILE_SIZE      '' 20
const as integer MAP_HEI = SCREEN_HEIGHT\TILE_SIZE      '' 15

const as integer FALSE = 0
const as integer TRUE = not FALSE

const as single Gravity = 0.75
const as single JumpHeight = 15


''*****************************************************************************
dim shared as integer Map(MAP_WID-1,MAP_HEI-1) =>_
{{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},_  ''1
{1,0,0,1,0,0,0,0,0,0,1,0,0,0,1},_   ''2
{1,0,0,1,0,0,0,0,0,0,1,0,0,0,1},_   ''3
{1,0,0,1,0,0,0,0,0,0,1,0,0,0,1},_   ''4
{1,0,0,1,0,0,0,0,0,0,1,0,0,0,1},_   ''5
{1,0,0,0,1,0,0,0,0,0,0,0,0,0,1},_   ''6
{1,0,0,0,0,0,0,0,0,0,1,0,0,0,1},_   ''7
{1,0,0,0,0,0,0,1,0,0,1,0,0,0,1},_   ''8
{1,0,0,0,0,1,0,0,0,0,0,0,0,0,1},_   ''9
{1,0,0,0,0,0,0,0,0,0,0,0,1,0,1},_   ''10
{1,0,0,0,0,1,0,0,0,0,0,0,1,0,1},_   ''11
{1,0,0,0,0,1,0,0,0,0,0,0,1,0,1},_   ''12
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,1},_   ''13
{1,0,0,0,0,0,1,0,0,0,0,0,1,0,1},_   ''14
{1,0,0,0,0,0,0,0,0,0,0,1,0,0,1},_   ''15
{1,0,0,0,0,0,1,0,0,0,0,1,0,0,1},_   ''16
{1,0,0,0,0,1,0,0,0,0,0,0,1,0,1},_   ''17
{1,0,0,0,0,1,0,0,0,0,0,0,0,0,1},_   ''18
{1,0,0,0,1,0,0,0,0,0,0,0,0,0,1},_   ''19
{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}}


''*****************************************************************************
''
''
''
''*****************************************************************************
type Player

   x      as single
   y      as single
   speed   as single
   xv      as single
   yv      as single
   wid      as integer
   hei      as integer
   
   CanJump as integer
   
   declare constructor()
   declare function CollideFloors(byval ix as integer, byval iy as integer, byref TileY as integer, Map() as integer ) as integer
   declare function CollideWalls(byval ix as integer, byval iy as integer, byref TileX as integer, Map() as integer ) as integer
   declare sub DoStuff()
   declare sub CollideOnMap( Map() as integer )
   declare sub Draw3D()
   
end type

constructor Player()
   x = 32 * 2
   y = 32 * 5
   speed = 4.5
   wid = 24
   hei = 48
   CanJump = false
End Constructor



function Player.CollideWalls(byval ix as integer, byval iy as integer, byref TileX as integer, Map() as integer ) as integer
   
   dim as integer TileYpixels = iy - (iy mod TILE_SIZE)   '' Pixel of the player's head snapped to map grid
   dim as integer TestEnd = iy + hei                  '' Foot of the player
   
   TileX = ix\TILE_SIZE                           '' Current X map coord the player is on + x-velocity(+ width when moving right)
   
   dim as integer TileY = TileYpixels\TILE_SIZE         '' Current Y map coord of the player's head
   
   '' Scan downwards from head to foot if we collided with a tile on the right or left
   while (TileYpixels <= TestEnd)
      if (Map(TileX, TileY))   then return true         '' Found a tile

      TileY += 1                                 '' Next tile downward
      TileYpixels +=TILE_SIZE                        '' Next tile pixel downward
      
   Wend
   
   return false
End Function

function Player.CollideFloors(byval ix as integer, byval iy as integer, byref TileY as integer, Map() as integer ) as integer
   
   dim as integer TileXpixels = ix - (ix mod TILE_SIZE)
   dim as integer TestEnd = ix + wid
   
   TileY = iy\TILE_SIZE
   
   dim as integer TileX = TileXpixels\TILE_SIZE
   
   while (TileXpixels <= TestEnd)
      if (Map(TileX, TileY))   then return true   

      TileX += 1
      TileXpixels +=TILE_SIZE
      
   Wend
   
   return false
End Function



sub Player.DoStuff()

   xv = 0
   
   if multikey(FB.SC_LEFT) then
      xv = -speed
   EndIf
   
    if multikey(FB.SC_RIGHT) then
       xv = speed
    EndIf
   
    if multikey(FB.SC_SPACE) then
       if( CanJump ) then
          yv = -JumpHeight
          CanJump = false
       end if
    EndIf
   
   
   
End Sub

sub Player.CollideOnMap( Map() as integer )
   
   dim as Integer TileX, TileY

   if( xv > 0 ) then
      
      if( CollideWalls( x + xv + wid, y, TileX, Map() ) ) then
         x = TileX * TILE_SIZE - wid - 1
      else
         x += xv
      EndIf
         
   elseif( xv < 0 ) then
      
      if( CollideWalls( x + xv, y, TileX, Map() ) ) then
         x = ( TileX + 1 ) * TILE_SIZE + 1
      else
         x += xv
      EndIf
      
   EndIf
   
   if( yv < 0 ) then
      
      if( CollideFloors( x, y + yv, TileY, Map() ) ) then   '' hit the roof
         y = ( TileY + 1 ) * TILE_SIZE + 1
         yv = 0   
      else
         y += yv
         yv += Gravity
      EndIf
         
   else
      
      if( CollideFloors( x, y + yv + hei, TileY, Map() ) ) then
         y = ( TileY ) * TILE_SIZE - hei - 1
         yv = 1
         if not multikey(FB.SC_SPACE) then CanJump = true
      else
         y += yv
         yv += Gravity
         CanJump = false
      EndIf
      
   EndIf
   
   
End Sub


sub Player.Draw3D()

   '' Draws the player in 3D   
   dim as single SizeX = Wid/2.0
   dim as single SizeY = Hei/2.0
   
   
   glColor4f( 1, 0, 1, 1 )
   glPushMatrix()
      glTranslatef( x + Wid/2, y + Hei/2.0, 0) '' Offset by Size/2 so that we draw from top-left at (0,0)
      glBegin(GL_QUADS)
         glVertex3f(-SizeX, -SizeY,  0)
         glVertex3f( SizeX, -SizeY,  0)
         glVertex3f( SizeX,  SizeY,  0)
         glVertex3f(-SizeX,  SizeY,  0)         
      glEnd()
   glPopMatrix()
   
   
end sub

   
''*****************************************************************************
''
''
''
''*****************************************************************************

Type Vector2D

   x as Single
   y as Single
   z as single
   
end type

Type Camera
   
   
   declare Constructor()
   declare sub Follow( x as single, y as single )
   declare sub Look()
   declare sub Look( value as single )
   declare sub Zoom( value as single )

   
   
   Position as Vector2D
   Target as Vector2D
   Up as Vector2D
   
   EyeDistanceFromScreen as integer

end type


constructor Camera()

   EyeDistanceFromScreen = TILE_SIZE * 18   '' Distance of player's eye from screen
   
   Position.x = 0
   Position.y = 0
   Position.z = EyeDistanceFromScreen       '' Yep we are drawing at z = 0 so pos should be positive
   
   Target.x = 0
   Target.y = 0
   Target.z = 0
   
   Up.x = 0
   Up.y = 1
   Up.z = 0
   
   
end constructor   

sub Camera.Follow( x as single, y as single )

   
   Position.x = x
   Position.y = y - TILE_SIZE * 1          '' offset a little above so we look a little down
   Position.z = EyeDistanceFromScreen      '' move zpos n units from screen to eye
   
   Target.x = x
   Target.y = y
   Target.z = 0
   
   Up.x = 0
   Up.y = 1
   Up.z = 0
   
end sub


sub Camera.Look()

   
   gluLookAt( Position.x, Position.y, Position.z,_    '' camera pos
            Target.x, Target.y, Target.z,_          '' camera target
               Up.x, Up.y, Up.z)

end sub



sub Camera.Zoom( value as single )

   EyeDistanceFromScreen +=value

end sub
   

''*****************************************************************************
sub main()
   
   
   dim as integer Frame = 0
   
   dim as Camera Cam
   dim as Player Mario
   
   GL_Screen_Init( SCREEN_WIDTH, SCREEN_HEIGHT )   ''Set up GL screen

   
   do
      
      Frame += 1

      Mario.DoStuff()     '' Do player movements
   
      Mario.CollideOnMap( Map() )      '' Do collisions in 2D
      
      
      '' Zoom if you want
      if( multikey(FB.SC_F2) ) then Cam.Zoom(1.62)
      if( multikey(FB.SC_F3) ) then Cam.Zoom(-1.62)
      
      
      
      glMatrixMode( GL_MODELVIEW )
      glLoadIdentity()
      glPolygonMode( GL_FRONT, GL_FILL )
      glPolygonMode( GL_BACK, GL_FILL )
      glEnable( GL_DEPTH_TEST )
      glDepthFunc( GL_LEQUAL )
      
      glDisable( GL_TEXTURE_2D )
   
      
      glColor4ub( 255, 255, 255, 255 )

      '' Move cam according to player's pos
      Cam.Follow( Mario.x, Mario.y )
      
      '' reverse y direction for oldskool coords(Easy GL2D = happy)
      glScalef( 1, -1, 1 )
      
      '' Look
      Cam.Look()
      
      '' Paper mario?
      if( multikey(FB.SC_F1) ) then glRotatef( 20, 0, 1, 0 )
      
      '' Clear screen
      glClear(GL_COLOR_BUFFER_BIT OR GL_DEPTH_BUFFER_BIT)

      '' Draw 3D stuff
      glPushMatrix()   
               
         DrawMap()
         Mario.Draw3D()

      glPopMatrix()   
      
      '' limit FPS
      dim as single TimeStart = timer
      while( (timer - TimeStart) < (1.0/60.0) )
         sleep 1,1
      wend
      
      
      flip
      
   Loop until multikey(FB.SC_ESCAPE)

   
   
End Sub



main()


end








''*****************************************************************************
'' Temp way to draw our 32x32 tiles
sub DrawCube( x as single, y as single, z as single, Size as single, Red as single, Green as single, Blue as single )

   glColor4f( Red, Green, Blue, 1 )
   
   glPushMatrix()
      glTranslatef( x + Size, y + Size, z)  '' Offset by Size so that we draw from top-left at (0,0)
   
      glBegin(GL_QUADS)
         '' Front Face
         glColor3f( 1, 0, 0)
         glVertex3f(-Size, -Size,  Size)
         glColor3f( 0, 1, 0)
         glVertex3f( Size, -Size,  Size)
         glColor3f( 0, 0, 1)
         glVertex3f( Size,  Size,  Size)
         glColor3f( 1, 1, 1)
         glVertex3f(-Size,  Size,  Size)
         
         glColor4f( 1, 1, 0, 1 )
   
         '' Back Face
         glVertex3f(-Size, -Size, -Size)
         glVertex3f(-Size,  Size, -Size)
         glVertex3f( Size,  Size, -Size)
         glVertex3f( Size, -Size, -Size)
         '' Top Face
         glVertex3f(-Size,  Size, -Size)
         glVertex3f(-Size,  Size,  Size)
         glVertex3f( Size,  Size,  Size)
         glVertex3f( Size,  Size, -Size)
         '' Bottom Face
         glVertex3f(-Size, -Size, -Size)
         glVertex3f( Size, -Size, -Size)
         glVertex3f( Size, -Size,  Size)
         glVertex3f(-Size, -Size,  Size)
         '' Right face
         glVertex3f( Size, -Size, -Size)
         glVertex3f( Size,  Size, -Size)
         glVertex3f( Size,  Size,  Size)
         glVertex3f( Size, -Size,  Size)
         '' Left Face
         glVertex3f(-Size, -Size, -Size)
         glVertex3f(-Size, -Size,  Size)
         glVertex3f(-Size,  Size,  Size)
         glVertex3f(-Size,  Size, -Size)
      glEnd()
   
   glPopMatrix()
   
   glColor4f( 1, 1, 1, 1 )
   
   
end sub


'' Draws the map in 3D
sub DrawMap()

   for y as integer = 0 to (MAP_HEI - 1)
      for x as integer = 0 to (MAP_WID - 1)
         if( Map(x,y) > 0 ) then         
            DrawCube( x * TILE_SIZE, y * TILE_SIZE, 0, TILE_SIZE/2, 0, 1, 0 )
         end if
      next x   
   next y
   
end sub


''=============================================================================
''
''    Sets up OpenGL for 2d mode
''
''=============================================================================
sub GL_Screen_Init(byval screen_wid as integer, byval screen_hei as integer, byval flags as integer = 0)
   
   if flags then
      screenres screen_wid, screen_hei, 32, 2, FB.GFX_OPENGL or flags
   else
      screenres screen_wid, screen_hei, 32, 2, FB.GFX_OPENGL
   endif
   
   
   'screen information
   dim w as integer, h as integer
   'OpenGL params for gluerspective
   dim FOVy as double            'Field of view angle in Y
   dim Aspect as double          'Aspect of screen
   dim znear as double           'z-near clip distance
   dim zfar as double            'z-far clip distance

   'using screen info w and h as params
   glViewport(0, 0, screen_wid, screen_hei)
   
   'Set current Mode to projection(ie: 3d)
   glMatrixMode(GL_PROJECTION)
   
   'Load identity matrix to projection matrix
   glLoadIdentity()

   'Set gluPerspective params
   FOVy = 90/2                                     '45 deg fovy
   Aspect = screen_wid / screen_hei
   znear = 1                                       'Near clip
   zfar = 1500                                     'far clip
   
   'use glu Perspective to set our 3d frustum dimension up
   gluPerspective(FOVy, aspect, znear, zfar)
   
   'Modelview mode
   'ie. Matrix that does things to anything we draw
   'as in lines, points, tris, etc.
   glMatrixMode(GL_MODELVIEW)
   'load identity(clean) matrix to modelview
   glLoadIdentity()
   
   glShadeModel(GL_SMOOTH)                 'set shading to smooth(try GL_FLAT)
   glClearColor(0.0, 0.0, 0.0, 1.0)        'set Clear color to BLACK
   glClearDepth(1.0)                       'Set Depth buffer to 1(z-Buffer)
   glEnable(GL_DEPTH_TEST)                 'Enable Depth Testing so that our z-buffer works
   
   'compare each incoming pixel z value with the z value present in the depth buffer
   'LEQUAL means than pixel is drawn if the incoming z value is less than
   'or equal to the stored z value
   glDepthFunc(GL_LEQUAL)
   
   'have one or more material parameters track the current color
   'Material is your 3d model
   glEnable(GL_COLOR_MATERIAL)


    'Enable Texturing
    glEnable(GL_TEXTURE_2D)
   

      'Tell openGL that we want the best possible perspective transform
   glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST)
   
   'Disable Backface culling
   glDisable (GL_CULL_FACE)
   
   glPolygonMode(GL_FRONT, GL_FILL)
   
   '' enable blending for transparency
   glEnable(GL_BLEND)          
   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
   
   glDisable( GL_DEPTH_TEST )
   
   glEnable( GL_ALPHA_TEST )
   glAlphaFunc(GL_GREATER, 0)


   glDisable(GL_STENCIL_TEST)
   glDisable(GL_TEXTURE_1D)
   glDisable(GL_LIGHTING)
   glDisable(GL_LOGIC_OP)
   glDisable(GL_DITHER)
   glDisable(GL_FOG)

   glHint(GL_POINT_SMOOTH_HINT, GL_FASTEST)
   glHint(GL_LINE_SMOOTH_HINT , GL_FASTEST)

   glPointSize( 1 )
   glLineWidth( 1 )
   
   
end sub






2. Dynamic Camera

Code: Select all

''*****************************************************************************
''
''   2.5D Engine (Dynamic camera)
''   Relminator (Richard Eric M. Lope)
''    http://rel.phatcode.net
''
''    This is probably the easiest way to make a 3d game
''   Features:
''   * 1:1 ratio of 3D coords to Screen
''   * Collisions are in tilebased 2D
''   * Rendering can be camera based (uber fast)
''   * Any 2D tilebased game can be converted to this
''
''   Controls
''   
''   SPACE = Jump
''   ARROW KEYS = Move
''   F1 = Paper mario mode?
''   F2/F3 = Zoom
''
''*****************************************************************************

#include once "fbgfx.bi"
#include once "/gl/gl.bi"
#include once "/gl/glu.bi"   


''*****************************************************************************
declare sub GL_Screen_Init(byval screen_wid as integer, byval screen_hei as integer, byval flags as integer = 0)

'' Drawing stuff
''*****************************************************************************
declare sub DrawCube( x as single, y as single, z as single, Size as single, Red as single, Green as single, Blue as single )
declare sub DrawMap()


''*****************************************************************************
const as integer SCREEN_WIDTH = 640
const as integer SCREEN_HEIGHT = 480

const as integer TILE_SIZE = 32


const as integer MAP_WID = SCREEN_WIDTH\TILE_SIZE      '' 20
const as integer MAP_HEI = SCREEN_HEIGHT\TILE_SIZE      '' 15

const as integer FALSE = 0
const as integer TRUE = not FALSE

const as single Gravity = 0.75
const as single JumpHeight = 15


''*****************************************************************************
dim shared as integer Map(MAP_WID-1,MAP_HEI-1) =>_
{{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},_  ''1
{1,0,0,1,0,0,0,0,0,0,1,0,0,0,1},_   ''2
{1,0,0,1,0,0,0,0,0,0,1,0,0,0,1},_   ''3
{1,0,0,1,0,0,0,0,0,0,1,0,0,0,1},_   ''4
{1,0,0,1,0,0,0,0,0,0,1,0,0,0,1},_   ''5
{1,0,0,0,1,0,0,0,0,0,0,0,0,0,1},_   ''6
{1,0,0,0,0,0,0,0,0,0,1,0,0,0,1},_   ''7
{1,0,0,0,0,0,0,1,0,0,1,0,0,0,1},_   ''8
{1,0,0,0,0,1,0,0,0,0,0,0,0,0,1},_   ''9
{1,0,0,0,0,0,0,0,0,0,0,0,1,0,1},_   ''10
{1,0,0,0,0,1,0,0,0,0,0,0,1,0,1},_   ''11
{1,0,0,0,0,1,0,0,0,0,0,0,1,0,1},_   ''12
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,1},_   ''13
{1,0,0,0,0,0,1,0,0,0,0,0,1,0,1},_   ''14
{1,0,0,0,0,0,0,0,0,0,0,1,0,0,1},_   ''15
{1,0,0,0,0,0,1,0,0,0,0,1,0,0,1},_   ''16
{1,0,0,0,0,1,0,0,0,0,0,0,1,0,1},_   ''17
{1,0,0,0,0,1,0,0,0,0,0,0,0,0,1},_   ''18
{1,0,0,0,1,0,0,0,0,0,0,0,0,0,1},_   ''19
{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}}


''*****************************************************************************
''
''
''
''*****************************************************************************
type Player

   x      as single
   y      as single
   speed   as single
   xv      as single
   yv      as single
   wid      as integer
   hei      as integer
   
   CanJump as integer
   
   declare constructor()
   declare function CollideFloors(byval ix as integer, byval iy as integer, byref TileY as integer, Map() as integer ) as integer
   declare function CollideWalls(byval ix as integer, byval iy as integer, byref TileX as integer, Map() as integer ) as integer
   declare sub DoStuff()
   declare sub CollideOnMap( Map() as integer )
   declare sub Draw3D()
   
end type

constructor Player()
   x = 32 * 2
   y = 32 * 5
   speed = 4.5
   wid = 24
   hei = 48
   CanJump = false
End Constructor



function Player.CollideWalls(byval ix as integer, byval iy as integer, byref TileX as integer, Map() as integer ) as integer
   
   dim as integer TileYpixels = iy - (iy mod TILE_SIZE)   '' Pixel of the player's head snapped to map grid
   dim as integer TestEnd = iy + hei                  '' Foot of the player
   
   TileX = ix\TILE_SIZE                           '' Current X map coord the player is on + x-velocity(+ width when moving right)
   
   dim as integer TileY = TileYpixels\TILE_SIZE         '' Current Y map coord of the player's head
   
   '' Scan downwards from head to foot if we collided with a tile on the right or left
   while (TileYpixels <= TestEnd)
      if (Map(TileX, TileY))   then return true         '' Found a tile

      TileY += 1                                 '' Next tile downward
      TileYpixels +=TILE_SIZE                        '' Next tile pixel downward
      
   Wend
   
   return false
End Function

function Player.CollideFloors(byval ix as integer, byval iy as integer, byref TileY as integer, Map() as integer ) as integer
   
   dim as integer TileXpixels = ix - (ix mod TILE_SIZE)
   dim as integer TestEnd = ix + wid
   
   TileY = iy\TILE_SIZE
   
   dim as integer TileX = TileXpixels\TILE_SIZE
   
   while (TileXpixels <= TestEnd)
      if (Map(TileX, TileY))   then return true   

      TileX += 1
      TileXpixels +=TILE_SIZE
      
   Wend
   
   return false
End Function



sub Player.DoStuff()

   xv = 0
   
   if multikey(FB.SC_LEFT) then
      xv = -speed
   EndIf
   
    if multikey(FB.SC_RIGHT) then
       xv = speed
    EndIf
   
    if multikey(FB.SC_SPACE) then
       if( CanJump ) then
          yv = -JumpHeight
          CanJump = false
       end if
    EndIf
   
   
   
End Sub

sub Player.CollideOnMap( Map() as integer )
   
   dim as Integer TileX, TileY

   if( xv > 0 ) then
      
      if( CollideWalls( x + xv + wid, y, TileX, Map() ) ) then
         x = TileX * TILE_SIZE - wid - 1
      else
         x += xv
      EndIf
         
   elseif( xv < 0 ) then
      
      if( CollideWalls( x + xv, y, TileX, Map() ) ) then
         x = ( TileX + 1 ) * TILE_SIZE + 1
      else
         x += xv
      EndIf
      
   EndIf
   
   if( yv < 0 ) then
      
      if( CollideFloors( x, y + yv, TileY, Map() ) ) then   '' hit the roof
         y = ( TileY + 1 ) * TILE_SIZE + 1
         yv = 0   
      else
         y += yv
         yv += Gravity
      EndIf
         
   else
      
      if( CollideFloors( x, y + yv + hei, TileY, Map() ) ) then
         y = ( TileY ) * TILE_SIZE - hei - 1
         yv = 1
         if not multikey(FB.SC_SPACE) then CanJump = true
      else
         y += yv
         yv += Gravity
         CanJump = false
      EndIf
      
   EndIf
   
   
End Sub


sub Player.Draw3D()

   '' Draws the player in 3D   
   dim as single SizeX = Wid/2.0
   dim as single SizeY = Hei/2.0
   
   
   glColor4f( 1, 0, 1, 1 )
   glPushMatrix()
      glTranslatef( x + Wid/2, y + Hei/2.0, 0) '' Offset by Size/2 so that we draw from top-left at (0,0)
      glBegin(GL_QUADS)
         glVertex3f(-SizeX, -SizeY,  0)
         glVertex3f( SizeX, -SizeY,  0)
         glVertex3f( SizeX,  SizeY,  0)
         glVertex3f(-SizeX,  SizeY,  0)         
      glEnd()
   glPopMatrix()
   
   
end sub

   
''*****************************************************************************
''
''
''
''*****************************************************************************

Type Vector2D

   x as Single
   y as Single
   z as single
   
end type

Type Camera
   
   
   declare Constructor()
   declare sub Follow( x as single, y as single )
   declare sub Follow( x as single, y as single, skew as integer )
   declare sub Look()
   declare sub Zoom( value as single )

   
   
   Position as Vector2D
   Target as Vector2D
   Up as Vector2D
   
   EyeDistanceFromScreen as integer

end type


constructor Camera()

   EyeDistanceFromScreen = TILE_SIZE * 18   '' Distance of player's eye from screen
   
   Position.x = 0
   Position.y = 0
   Position.z = EyeDistanceFromScreen       '' Yep we are drawing at z = 0 so pos should be positive
   
   Target.x = 0
   Target.y = 0
   Target.z = 0
   
   Up.x = 0
   Up.y = 1
   Up.z = 0
   
   
end constructor   

sub Camera.Follow( x as single, y as single )

   
   Position.x = x
   Position.y = y - TILE_SIZE * 1          '' offset a little above so we look a little down
   Position.z = EyeDistanceFromScreen      '' move zpos n units from screen to eye
   
   Target.x = x
   Target.y = y
   Target.z = 0
   
   Up.x = 0
   Up.y = 1
   Up.z = 0
   
end sub


sub Camera.Follow( x as single, y as single, skew as integer )

   static as single rot = 0
   if( skew > 0 ) then
      if( rot < 100 ) then rot += 5 
   elseif ( skew < 0 ) then
      if( rot > -100 ) then rot -= 5
   else  '' 0
      if( rot > 0 ) then rot -= 5
      if( rot < 0 ) then rot += 5
   end if
   
   Position.x = x - rot
   Position.y = y - TILE_SIZE * 1          '' offset a little above so we look a little down
   Position.z = EyeDistanceFromScreen      '' move zpos n units from screen to eye
   
   Target.x = x + rot
   Target.y = y
   Target.z = 0
   
   Up.x = 0
   Up.y = 1
   Up.z = 0
   
end sub


sub Camera.Look()

   
   gluLookAt( Position.x, Position.y, Position.z,_    '' camera pos
            Target.x, Target.y, Target.z,_          '' camera target
               Up.x, Up.y, Up.z)

end sub



sub Camera.Zoom( value as single )

   EyeDistanceFromScreen +=value

end sub
   

''*****************************************************************************
sub main()
   
   
   dim as integer Frame = 0
   
   dim as Camera Cam
   dim as Player Mario
   
   GL_Screen_Init( SCREEN_WIDTH, SCREEN_HEIGHT )   ''Set up GL screen

   
   do
      
      Frame += 1

      Mario.DoStuff()     '' Do player movements
   
      Mario.CollideOnMap( Map() )      '' Do collisions in 2D
      
      
      '' Zoom if you want
      if( multikey(FB.SC_F2) ) then Cam.Zoom(1.62)
      if( multikey(FB.SC_F3) ) then Cam.Zoom(-1.62)
      
      
      
      glMatrixMode( GL_MODELVIEW )
      glLoadIdentity()
      glPolygonMode( GL_FRONT, GL_FILL )
      glPolygonMode( GL_BACK, GL_FILL )
      glEnable( GL_DEPTH_TEST )
      glDepthFunc( GL_LEQUAL )
      
      glDisable( GL_TEXTURE_2D )
   
      
      glColor4ub( 255, 255, 255, 255 )

      '' Move cam according to player's pos
      'Cam.Follow( Mario.x, Mario.y )
      Cam.Follow( Mario.x, Mario.y,  sgn(Mario.xv)  )
      
      '' reverse y direction for oldskool coords(Easy GL2D = happy)
      glScalef( 1, -1, 1 )
      
      '' Look
      Cam.Look()
      
      '' Clear screen
      glClear(GL_COLOR_BUFFER_BIT OR GL_DEPTH_BUFFER_BIT)

      '' Draw 3D stuff
      glPushMatrix()   
               
         DrawMap()
         Mario.Draw3D()

      glPopMatrix()   
      
      '' limit FPS
      dim as single TimeStart = timer
      while( (timer - TimeStart) < (1.0/60.0) )
         sleep 1,1
      wend
      
      
      flip
      
   Loop until multikey(FB.SC_ESCAPE)

   
   
End Sub



main()


end








''*****************************************************************************
'' Temp way to draw our 32x32 tiles
sub DrawCube( x as single, y as single, z as single, Size as single, Red as single, Green as single, Blue as single )

   glColor4f( Red, Green, Blue, 1 )
   
   glPushMatrix()
      glTranslatef( x + Size, y + Size, z)  '' Offset by Size so that we draw from top-left at (0,0)
   
      glBegin(GL_QUADS)
         '' Front Face
         glColor3f( 1, 0, 0)
         glVertex3f(-Size, -Size,  Size)
         glColor3f( 0, 1, 0)
         glVertex3f( Size, -Size,  Size)
         glColor3f( 0, 0, 1)
         glVertex3f( Size,  Size,  Size)
         glColor3f( 1, 1, 1)
         glVertex3f(-Size,  Size,  Size)
         
         glColor4f( 1, 1, 0, 1 )
   
         '' Back Face
         glVertex3f(-Size, -Size, -Size)
         glVertex3f(-Size,  Size, -Size)
         glVertex3f( Size,  Size, -Size)
         glVertex3f( Size, -Size, -Size)
         '' Top Face
         glVertex3f(-Size,  Size, -Size)
         glVertex3f(-Size,  Size,  Size)
         glVertex3f( Size,  Size,  Size)
         glVertex3f( Size,  Size, -Size)
         '' Bottom Face
         glVertex3f(-Size, -Size, -Size)
         glVertex3f( Size, -Size, -Size)
         glVertex3f( Size, -Size,  Size)
         glVertex3f(-Size, -Size,  Size)
         '' Right face
         glVertex3f( Size, -Size, -Size)
         glVertex3f( Size,  Size, -Size)
         glVertex3f( Size,  Size,  Size)
         glVertex3f( Size, -Size,  Size)
         '' Left Face
         glVertex3f(-Size, -Size, -Size)
         glVertex3f(-Size, -Size,  Size)
         glVertex3f(-Size,  Size,  Size)
         glVertex3f(-Size,  Size, -Size)
      glEnd()
   
   glPopMatrix()
   
   glColor4f( 1, 1, 1, 1 )
   
   
end sub


'' Draws the map in 3D
sub DrawMap()

   for y as integer = 0 to (MAP_HEI - 1)
      for x as integer = 0 to (MAP_WID - 1)
         if( Map(x,y) > 0 ) then         
            DrawCube( x * TILE_SIZE, y * TILE_SIZE, 0, TILE_SIZE/2, 0, 1, 0 )
         end if
      next x   
   next y
   
end sub


''=============================================================================
''
''    Sets up OpenGL for 2d mode
''
''=============================================================================
sub GL_Screen_Init(byval screen_wid as integer, byval screen_hei as integer, byval flags as integer = 0)
   
   if flags then
      screenres screen_wid, screen_hei, 32, 2, FB.GFX_OPENGL or flags
   else
      screenres screen_wid, screen_hei, 32, 2, FB.GFX_OPENGL
   endif
   
   
   'screen information
   dim w as integer, h as integer
   'OpenGL params for gluerspective
   dim FOVy as double            'Field of view angle in Y
   dim Aspect as double          'Aspect of screen
   dim znear as double           'z-near clip distance
   dim zfar as double            'z-far clip distance

   'using screen info w and h as params
   glViewport(0, 0, screen_wid, screen_hei)
   
   'Set current Mode to projection(ie: 3d)
   glMatrixMode(GL_PROJECTION)
   
   'Load identity matrix to projection matrix
   glLoadIdentity()

   'Set gluPerspective params
   FOVy = 90/2                                     '45 deg fovy
   Aspect = screen_wid / screen_hei
   znear = 1                                       'Near clip
   zfar = 1500                                     'far clip
   
   'use glu Perspective to set our 3d frustum dimension up
   gluPerspective(FOVy, aspect, znear, zfar)
   
   'Modelview mode
   'ie. Matrix that does things to anything we draw
   'as in lines, points, tris, etc.
   glMatrixMode(GL_MODELVIEW)
   'load identity(clean) matrix to modelview
   glLoadIdentity()
   
   glShadeModel(GL_SMOOTH)                 'set shading to smooth(try GL_FLAT)
   glClearColor(0.0, 0.0, 0.0, 1.0)        'set Clear color to BLACK
   glClearDepth(1.0)                       'Set Depth buffer to 1(z-Buffer)
   glEnable(GL_DEPTH_TEST)                 'Enable Depth Testing so that our z-buffer works
   
   'compare each incoming pixel z value with the z value present in the depth buffer
   'LEQUAL means than pixel is drawn if the incoming z value is less than
   'or equal to the stored z value
   glDepthFunc(GL_LEQUAL)
   
   'have one or more material parameters track the current color
   'Material is your 3d model
   glEnable(GL_COLOR_MATERIAL)


    'Enable Texturing
    glEnable(GL_TEXTURE_2D)
   

      'Tell openGL that we want the best possible perspective transform
   glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST)
   
   'Disable Backface culling
   glDisable (GL_CULL_FACE)
   
   glPolygonMode(GL_FRONT, GL_FILL)
   
   '' enable blending for transparency
   glEnable(GL_BLEND)          
   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
   
   glDisable( GL_DEPTH_TEST )
   
   glEnable( GL_ALPHA_TEST )
   glAlphaFunc(GL_GREATER, 0)


   glDisable(GL_STENCIL_TEST)
   glDisable(GL_TEXTURE_1D)
   glDisable(GL_LIGHTING)
   glDisable(GL_LOGIC_OP)
   glDisable(GL_DITHER)
   glDisable(GL_FOG)

   glHint(GL_POINT_SMOOTH_HINT, GL_FASTEST)
   glHint(GL_LINE_SMOOTH_HINT , GL_FASTEST)

   glPointSize( 1 )
   glLineWidth( 1 )
   
   
end sub





Here's a zip with all the samples:
http://rel.phatcode.net/junk.php?id=123

Here's the DS version:
http://rel.phatcode.net/junk.php?id=122
Last edited by relsoft on Aug 27, 2012 6:50, edited 2 times in total.
relsoft
Posts: 1765
Joined: May 27, 2005 10:34
Location: Philippines
Contact:

Re: The easiest way to code a 3d Platformer.

Postby relsoft » Aug 17, 2012 2:29

3. Scrolling with selective tile drawing(very fast)

Code: Select all

''*****************************************************************************
''
''   2.5D Engine (Scrolling ala Super Mario)
''   Optimized draw
''   Only draws one screen worth of 3d tiles
''   See "DrawMap()" function for more details
''   Zoom out to see the optimization in action
''
''   Relminator (Richard Eric M. Lope)
''    http://rel.phatcode.net
''
''    This is probably the easiest way to make a 3d game
''   Features:
''   * 1:1 ratio of 3D coords to Screen
''   * Collisions are in tilebased 2D
''   * Rendering can be camera based (uber fast)
''   * Any 2D tilebased game can be converted to this
''
''   Controls
''   
''   SPACE = Jump
''   ARROW KEYS = Move
''   F1 = Paper mario mode?
''   F2/F3 = Zoom
''
''*****************************************************************************

#include once "fbgfx.bi"
#include once "/gl/gl.bi"
#include once "/gl/glu.bi"   


''*****************************************************************************
declare sub GL_Screen_Init(byval screen_wid as integer, byval screen_hei as integer, byval flags as integer = 0)

'' Drawing stuff
''*****************************************************************************
declare sub DrawCube( x as single, y as single, z as single, Size as single, Red as single, Green as single, Blue as single )
declare sub DrawMap( byval PlayerX as single, byval PlayerY as single )


''*****************************************************************************
const as integer SCREEN_WIDTH = 640
const as integer SCREEN_HEIGHT = 480

const as integer TILE_SIZE = 32


const as integer MAP_WID = (SCREEN_WIDTH\TILE_SIZE) * 4 '' 20 * 4 worth of tiles
const as integer MAP_HEI = SCREEN_HEIGHT\TILE_SIZE      '' 15

const as integer FALSE = 0
const as integer TRUE = not FALSE

const as single Gravity = 0.75
const as single JumpHeight = 15


''*****************************************************************************
dim shared as integer Map(MAP_WID-1,MAP_HEI-1) =>_
{{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},_  ''1
{1,0,0,1,0,0,0,0,0,0,1,0,0,0,1},_   ''2
{1,0,0,1,0,0,0,0,0,0,1,0,0,0,1},_   ''3
{1,0,0,1,0,0,0,0,0,0,1,0,0,0,1},_   ''4
{1,0,0,1,0,0,0,0,0,0,1,0,0,0,1},_   ''5
{1,0,0,0,1,0,0,0,0,0,0,0,0,0,1},_   ''6
{1,0,0,0,0,0,0,0,0,0,1,0,0,0,1},_   ''7
{1,0,0,0,0,0,0,1,0,0,1,0,0,0,1},_   ''8
{1,0,0,0,0,1,0,0,0,0,0,0,0,0,1},_   ''9
{1,0,0,0,0,0,0,0,0,0,0,0,1,0,1},_   ''10
{1,0,0,0,0,1,0,0,0,0,0,0,1,0,1},_   ''11
{1,0,0,0,0,1,0,0,0,0,0,0,1,0,1},_   ''12
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,1},_   ''13
{1,0,0,0,0,0,1,0,0,0,0,0,1,0,1},_   ''14
{1,0,0,0,0,0,0,0,0,0,0,1,0,0,1},_   ''15
{1,0,0,0,0,0,1,0,0,0,0,1,0,0,1},_   ''16
{1,0,0,0,0,1,0,0,0,0,0,0,1,0,1},_   ''17
{1,0,0,0,0,1,0,0,0,0,0,0,0,0,1},_   ''18
{1,0,0,0,1,0,0,0,0,0,0,0,0,0,1},_   ''19
{1,0,0,0,1,0,0,0,0,0,0,0,0,0,1},_   ''19
{1,0,0,0,1,0,0,0,0,0,0,0,0,0,1},_   ''19
{1,0,0,1,0,0,0,0,0,0,1,0,0,0,1},_   ''2
{1,0,0,1,0,0,0,0,0,0,1,0,0,0,1},_   ''3
{1,0,0,1,0,0,0,0,0,0,1,0,0,0,1},_   ''4
{1,0,0,1,0,0,0,0,0,0,1,0,0,0,1},_   ''5
{1,0,0,0,1,0,0,0,0,0,0,0,0,0,1},_   ''6
{1,0,0,0,0,0,0,0,0,0,1,0,0,0,1},_   ''7
{1,0,0,0,0,0,0,1,0,0,1,0,0,0,1},_   ''8
{1,0,0,0,0,1,0,0,0,0,0,0,0,0,1},_   ''9
{1,0,0,0,0,0,0,0,0,0,0,0,1,0,1},_   ''10
{1,0,0,0,0,1,0,0,0,0,0,0,1,0,1},_   ''11
{1,0,0,0,0,1,0,0,0,0,0,0,1,0,1},_   ''12
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,1},_   ''13
{1,0,0,0,0,0,1,0,0,0,0,0,1,0,1},_   ''14
{1,0,0,0,0,0,0,0,0,0,0,1,0,0,1},_   ''15
{1,0,0,0,0,0,1,0,0,0,0,1,0,0,1},_   ''16
{1,0,0,0,0,1,0,0,0,0,0,0,1,0,1},_   ''17
{1,0,0,0,0,1,0,0,0,0,0,0,0,0,1},_   ''18
{1,0,0,0,1,0,0,0,0,0,0,0,0,0,1},_   ''19
{1,0,0,0,1,0,0,0,0,0,0,0,0,0,1},_   ''19
{1,0,0,0,1,0,0,0,0,0,0,0,0,0,1},_   ''19
{1,0,0,1,0,0,0,0,0,0,1,0,0,0,1},_   ''2
{1,0,0,1,0,0,0,0,0,0,1,0,0,0,1},_   ''3
{1,0,0,1,0,0,0,0,0,0,1,0,0,0,1},_   ''4
{1,0,0,1,0,0,0,0,0,0,1,0,0,0,1},_   ''5
{1,0,0,0,1,0,0,0,0,0,0,0,0,0,1},_   ''6
{1,0,0,0,0,0,0,0,0,0,1,0,0,0,1},_   ''7
{1,0,0,0,0,0,0,1,0,0,1,0,0,0,1},_   ''8
{1,0,0,0,0,1,0,0,0,0,0,0,0,0,1},_   ''9
{1,0,0,0,0,0,0,0,0,0,0,0,1,0,1},_   ''10
{1,0,0,0,0,1,0,0,0,0,0,0,1,0,1},_   ''11
{1,0,0,0,0,1,0,0,0,0,0,0,1,0,1},_   ''12
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,1},_   ''13
{1,0,0,0,0,0,1,0,0,0,0,0,1,0,1},_   ''14
{1,0,0,0,0,0,0,0,0,0,0,1,0,0,1},_   ''15
{1,0,0,0,0,0,1,0,0,0,0,1,0,0,1},_   ''16
{1,0,0,0,0,1,0,0,0,0,0,0,1,0,1},_   ''17
{1,0,0,0,0,1,0,0,0,0,0,0,0,0,1},_   ''18
{1,0,0,0,1,0,0,0,0,0,0,0,0,0,1},_   ''19
{1,0,0,0,1,0,0,0,0,0,0,0,0,0,1},_   ''19
{1,0,0,0,1,0,0,0,0,0,0,0,0,0,1},_   ''19
{1,0,0,1,0,0,0,0,0,0,1,0,0,0,1},_   ''2
{1,0,0,1,0,0,0,0,0,0,1,0,0,0,1},_   ''3
{1,0,0,1,0,0,0,0,0,0,1,0,0,0,1},_   ''4
{1,0,0,1,0,0,0,0,0,0,1,0,0,0,1},_   ''5
{1,0,0,0,1,0,0,0,0,0,0,0,0,0,1},_   ''6
{1,0,0,0,0,0,0,0,0,0,1,0,0,0,1},_   ''7
{1,0,0,0,0,0,0,1,0,0,1,0,0,0,1},_   ''8
{1,0,0,0,0,1,0,0,0,0,0,0,0,0,1},_   ''9
{1,0,0,0,0,0,0,0,0,0,0,0,1,0,1},_   ''10
{1,0,0,0,0,1,0,0,0,0,0,0,1,0,1},_   ''11
{1,0,0,0,0,1,0,0,0,0,0,0,1,0,1},_   ''12
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,1},_   ''13
{1,0,0,0,0,0,1,0,0,0,0,0,1,0,1},_   ''14
{1,0,0,0,0,0,0,0,0,0,0,1,0,0,1},_   ''15
{1,0,0,0,0,0,1,0,0,0,0,1,0,0,1},_   ''16
{1,0,0,0,0,1,0,0,0,0,0,0,1,0,1},_   ''17
{1,0,0,0,0,1,0,0,0,0,0,0,0,0,1},_   ''18
{1,0,0,0,1,0,0,0,0,0,0,0,0,0,1},_   ''19
{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}}


''*****************************************************************************
''
''
''
''*****************************************************************************
type Player

   x      as single
   y      as single
   speed   as single
   xv      as single
   yv      as single
   wid      as integer
   hei      as integer
   
   CanJump  as integer
   
   declare constructor()
   declare function CollideFloors(byval ix as integer, byval iy as integer, byref TileY as integer, Map() as integer ) as integer
   declare function CollideWalls(byval ix as integer, byval iy as integer, byref TileX as integer, Map() as integer ) as integer
   declare sub DoStuff()
   declare sub CollideOnMap( Map() as integer )
   declare sub Draw3D()
   
end type

constructor Player()
   x = 32 * 2
   y = 32 * 5
   speed = 4.5
   wid = 24
   hei = 48
   CanJump = false
End Constructor



function Player.CollideWalls(byval ix as integer, byval iy as integer, byref TileX as integer, Map() as integer ) as integer
   
   dim as integer TileYpixels = iy - (iy mod TILE_SIZE)   '' Pixel of the player's head snapped to map grid
   dim as integer TestEnd = iy + hei                  '' Foot of the player
   
   TileX = ix\TILE_SIZE                           '' Current X map coord the player is on + x-velocity(+ width when moving right)
   
   dim as integer TileY = TileYpixels\TILE_SIZE         '' Current Y map coord of the player's head
   
   '' Scan downwards from head to foot if we collided with a tile on the right or left
   while (TileYpixels <= TestEnd)
      if (Map(TileX, TileY))   then return true         '' Found a tile

      TileY += 1                                 '' Next tile downward
      TileYpixels +=TILE_SIZE                        '' Next tile pixel downward
      
   Wend
   
   return false
End Function

function Player.CollideFloors(byval ix as integer, byval iy as integer, byref TileY as integer, Map() as integer ) as integer
   
   dim as integer TileXpixels = ix - (ix mod TILE_SIZE)
   dim as integer TestEnd = ix + wid
   
   TileY = iy\TILE_SIZE
   
   dim as integer TileX = TileXpixels\TILE_SIZE
   
   while (TileXpixels <= TestEnd)
      if (Map(TileX, TileY))   then return true   

      TileX += 1
      TileXpixels +=TILE_SIZE
      
   Wend
   
   return false
End Function



sub Player.DoStuff()

   xv = 0
   
   if multikey(FB.SC_LEFT) then
      xv = -speed
   EndIf
   
    if multikey(FB.SC_RIGHT) then
       xv = speed
    EndIf
   
    if multikey(FB.SC_SPACE) then
       if( CanJump ) then
          yv = -JumpHeight
          CanJump = false
       end if
    EndIf
   
   
   
End Sub

sub Player.CollideOnMap( Map() as integer )
   
   dim as Integer TileX, TileY

   if( xv > 0 ) then
      
      if( CollideWalls( x + xv + wid, y, TileX, Map() ) ) then
         x = TileX * TILE_SIZE - wid - 1
      else
         x += xv
      EndIf
         
   elseif( xv < 0 ) then
      
      if( CollideWalls( x + xv, y, TileX, Map() ) ) then
         x = ( TileX + 1 ) * TILE_SIZE + 1
      else
         x += xv
      EndIf
      
   EndIf
   
   if( yv < 0 ) then
      
      if( CollideFloors( x, y + yv, TileY, Map() ) ) then   '' hit the roof
         y = ( TileY + 1 ) * TILE_SIZE + 1
         yv = 0   
      else
         y += yv
         yv += Gravity
      EndIf
         
   else
      
      if( CollideFloors( x, y + yv + hei, TileY, Map() ) ) then
         y = ( TileY ) * TILE_SIZE - hei - 1
         yv = 1
         if not multikey(FB.SC_SPACE) then CanJump = true
      else
         y += yv
         yv += Gravity
         CanJump = false
      EndIf
      
   EndIf
   
   
End Sub


sub Player.Draw3D()

   '' Draws the player in 3D   
   dim as single SizeX = Wid/2.0
   dim as single SizeY = Hei/2.0
   
   
   glColor4f( 1, 0, 1, 1 )
   glPushMatrix()
      glTranslatef( x + Wid/2, y + Hei/2.0, 0) '' Offset by Size/2 so that we draw from top-left at (0,0)
      glBegin(GL_QUADS)
         glVertex3f(-SizeX, -SizeY,  0)
         glVertex3f( SizeX, -SizeY,  0)
         glVertex3f( SizeX,  SizeY,  0)
         glVertex3f(-SizeX,  SizeY,  0)         
      glEnd()
   glPopMatrix()
   
   
end sub

   
''*****************************************************************************
''
''
''
''*****************************************************************************

Type Vector2D

   x as Single
   y as Single
   z as single
   
end type

Type Camera
   
   
   declare Constructor()
   declare sub Follow( x as single, y as single )
   declare sub Follow( x as single, y as single, skew as integer )
   declare sub Look()
   declare sub Look( value as single )
   declare sub Zoom( value as single )

   
   
   Position as Vector2D
   Target as Vector2D
   Up as Vector2D
   
   EyeDistanceFromScreen as integer

end type


constructor Camera()

   EyeDistanceFromScreen = TILE_SIZE * 15   '' Distance of player's eye from screen
   
   Position.x = 0
   Position.y = 0
   Position.z = EyeDistanceFromScreen       '' Yep we are drawing at z = 0 so pos should be positive
   
   Target.x = 0
   Target.y = 0
   Target.z = 0
   
   Up.x = 0
   Up.y = 1
   Up.z = 0
   
   
end constructor   

sub Camera.Follow( x as single, y as single )

   
   Position.x = x
   Position.y = y - TILE_SIZE * 1          '' offset a little above so we look a little down
   Position.z = EyeDistanceFromScreen      '' move zpos n units from screen to eye
   
   Target.x = x
   Target.y = y
   Target.z = 0
   
   Up.x = 0
   Up.y = 1
   Up.z = 0
   
end sub

sub Camera.Follow( x as single, y as single, skew as integer )

   static as single rot = 0
   if( skew > 0 ) then
      if( rot < 100 ) then rot += 5 
   elseif ( skew < 0 ) then
      if( rot > -100 ) then rot -= 5
   else  '' 0
      if( rot > 0 ) then rot -= 5
      if( rot < 0 ) then rot += 5
   end if
   
   Position.x = x - rot
   Position.y = y - TILE_SIZE * 1          '' offset a little above so we look a little down
   Position.z = EyeDistanceFromScreen      '' move zpos n units from screen to eye
   
   Target.x = x + rot
   Target.y = y
   Target.z = 0
   
   Up.x = 0
   Up.y = 1
   Up.z = 0
   
end sub



sub Camera.Look()

   
   gluLookAt( Position.x, Position.y, Position.z,_    '' camera pos
            Target.x, Target.y, Target.z,_          '' camera target
               Up.x, Up.y, Up.z)

end sub



sub Camera.Zoom( value as single )

   EyeDistanceFromScreen +=value

end sub
   

''*****************************************************************************
sub main()
   
   
   dim as integer Frame = 0
   
   dim as Camera Cam
   dim as Player Mario
   
   GL_Screen_Init( SCREEN_WIDTH, SCREEN_HEIGHT )   ''Set up GL screen

   
   do
      
      Frame += 1

      Mario.DoStuff()     '' Do player movements
   
      Mario.CollideOnMap( Map() )      '' Do collisions in 2D
      
      
      '' Zoom if you want
      if( multikey(FB.SC_F2) ) then Cam.Zoom(1.62)
      if( multikey(FB.SC_F3) ) then Cam.Zoom(-1.62)
      
      
      
      glMatrixMode( GL_MODELVIEW )
      glLoadIdentity()
      glPolygonMode( GL_FRONT, GL_FILL )
      glPolygonMode( GL_BACK, GL_FILL )
      glEnable( GL_DEPTH_TEST )
      glDepthFunc( GL_LEQUAL )
      
      glDisable( GL_TEXTURE_2D )
   
      
      glColor4ub( 255, 255, 255, 255 )

      '' Move cam according to player's pos
      Cam.Follow( Mario.x, Mario.y )
      
      '' reverse y direction for oldskool coords(Easy GL2D = happy)
      glScalef( 1, -1, 1 )
      
      '' Look
      Cam.Look()
      
      '' Paper mario?
      if( multikey(FB.SC_F1) ) then glRotatef( 20, 0, 1, 0 )
      
      '' Clear screen
      glClear(GL_COLOR_BUFFER_BIT OR GL_DEPTH_BUFFER_BIT)

      '' Draw 3D stuff
      glPushMatrix()   
               
         DrawMap( Mario.x, Mario.y )
         Mario.Draw3D()

      glPopMatrix()   
      
      '' limit FPS
      dim as single TimeStart = timer
      while( (timer - TimeStart) < (1.0/60.0) )
         sleep 1,1
      wend
      
      
      flip
      
   Loop until multikey(FB.SC_ESCAPE)

   
   
End Sub



main()


end








''*****************************************************************************
'' Temp way to draw our 32x32 tiles
sub DrawCube( x as single, y as single, z as single, Size as single, Red as single, Green as single, Blue as single )

   glColor4f( Red, Green, Blue, 1 )
   
   glPushMatrix()
      glTranslatef( x + Size, y + Size, z)  '' Offset by Size so that we draw from top-left at (0,0)
   
      glBegin(GL_QUADS)
         '' Front Face
         glColor3f( 1, 0, 0)
         glVertex3f(-Size, -Size,  Size)
         glColor3f( 0, 1, 0)
         glVertex3f( Size, -Size,  Size)
         glColor3f( 0, 0, 1)
         glVertex3f( Size,  Size,  Size)
         glColor3f( 1, 1, 1)
         glVertex3f(-Size,  Size,  Size)
         
         glColor4f( 1, 1, 0, 1 )
   
         '' Back Face
         glVertex3f(-Size, -Size, -Size)
         glVertex3f(-Size,  Size, -Size)
         glVertex3f( Size,  Size, -Size)
         glVertex3f( Size, -Size, -Size)
         '' Top Face
         glVertex3f(-Size,  Size, -Size)
         glVertex3f(-Size,  Size,  Size)
         glVertex3f( Size,  Size,  Size)
         glVertex3f( Size,  Size, -Size)
         '' Bottom Face
         glVertex3f(-Size, -Size, -Size)
         glVertex3f( Size, -Size, -Size)
         glVertex3f( Size, -Size,  Size)
         glVertex3f(-Size, -Size,  Size)
         '' Right face
         glVertex3f( Size, -Size, -Size)
         glVertex3f( Size,  Size, -Size)
         glVertex3f( Size,  Size,  Size)
         glVertex3f( Size, -Size,  Size)
         '' Left Face
         glVertex3f(-Size, -Size, -Size)
         glVertex3f(-Size, -Size,  Size)
         glVertex3f(-Size,  Size,  Size)
         glVertex3f(-Size,  Size, -Size)
      glEnd()
   
   glPopMatrix()
   
   glColor4f( 1, 1, 1, 1 )
   
   
end sub


'' Draws the map in 3D
'' Fast selective tile drawing
sub DrawMap( byval PlayerX as single, byval PlayerY as single )
   
   '' Number of Tiles we draw at one time ( Just a screenfull of it)
   const as integer ScreenTilesX = SCREEN_WIDTH \ TILE_SIZE
   const as integer ScreenTilesY = SCREEN_HEIGHT \ TILE_SIZE
   
   '' Starting tiles = (Player - Halfscreen) \ TileSize
   dim as integer TileX = ( PlayerX - SCREEN_WIDTH \ 2 ) \ TILE_SIZE
   dim as integer TileY = ( PlayerY - SCREEN_HEIGHT \ 2 ) \ TILE_SIZE
   
   '' Limit left-top
   if( TileX < 0 ) then TileX = 0
   if( TileY < 0 ) then TileY = 0
   
   '' Limit right = (Player - Halfscreen) \ TileSize
   dim as integer MaxX = MAP_WID - (SCREEN_WIDTH\TILE_SIZE)
   if( TileX > MaxX ) then TileX = MaxX
   
   '' Limit bottom
   dim as integer MaxY = MAP_HEI - (SCREEN_HEIGHT\TILE_SIZE)
   if( TileY > MaxY ) then TileY = MaxY
   
   '' Draw
   for y as integer = TileY to  (TileY + (ScreenTilesY - 1))
      for x as integer = TileX to (TileX + (ScreenTilesX - 1))
         if( Map(x,y) > 0 ) then         
            DrawCube( x * TILE_SIZE, y * TILE_SIZE, 0, TILE_SIZE/2, 0, 1, 0 )
         end if
      next x   
   next y
   
end sub


''=============================================================================
''
''    Sets up OpenGL for 2d mode
''
''=============================================================================
sub GL_Screen_Init(byval screen_wid as integer, byval screen_hei as integer, byval flags as integer = 0)
   
   if flags then
      screenres screen_wid, screen_hei, 32, 2, FB.GFX_OPENGL or flags
   else
      screenres screen_wid, screen_hei, 32, 2, FB.GFX_OPENGL
   endif
   
   
   'screen information
   dim w as integer, h as integer
   'OpenGL params for gluerspective
   dim FOVy as double            'Field of view angle in Y
   dim Aspect as double          'Aspect of screen
   dim znear as double           'z-near clip distance
   dim zfar as double            'z-far clip distance

   'using screen info w and h as params
   glViewport(0, 0, screen_wid, screen_hei)
   
   'Set current Mode to projection(ie: 3d)
   glMatrixMode(GL_PROJECTION)
   
   'Load identity matrix to projection matrix
   glLoadIdentity()

   'Set gluPerspective params
   FOVy = 90/2                                     '45 deg fovy
   Aspect = screen_wid / screen_hei
   znear = 1                                       'Near clip
   zfar = 1500                                     'far clip
   
   'use glu Perspective to set our 3d frustum dimension up
   gluPerspective(FOVy, aspect, znear, zfar)
   
   'Modelview mode
   'ie. Matrix that does things to anything we draw
   'as in lines, points, tris, etc.
   glMatrixMode(GL_MODELVIEW)
   'load identity(clean) matrix to modelview
   glLoadIdentity()
   
   glShadeModel(GL_SMOOTH)                 'set shading to smooth(try GL_FLAT)
   glClearColor(0.0, 0.0, 0.0, 1.0)        'set Clear color to BLACK
   glClearDepth(1.0)                       'Set Depth buffer to 1(z-Buffer)
   glEnable(GL_DEPTH_TEST)                 'Enable Depth Testing so that our z-buffer works
   
   'compare each incoming pixel z value with the z value present in the depth buffer
   'LEQUAL means than pixel is drawn if the incoming z value is less than
   'or equal to the stored z value
   glDepthFunc(GL_LEQUAL)
   
   'have one or more material parameters track the current color
   'Material is your 3d model
   glEnable(GL_COLOR_MATERIAL)


    'Enable Texturing
    glEnable(GL_TEXTURE_2D)
   

      'Tell openGL that we want the best possible perspective transform
   glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST)
   
   'Disable Backface culling
   glDisable (GL_CULL_FACE)
   
   glPolygonMode(GL_FRONT, GL_FILL)
   
   '' enable blending for transparency
   glEnable(GL_BLEND)          
   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
   
   glDisable( GL_DEPTH_TEST )
   
   glEnable( GL_ALPHA_TEST )
   glAlphaFunc(GL_GREATER, 0)


   glDisable(GL_STENCIL_TEST)
   glDisable(GL_TEXTURE_1D)
   glDisable(GL_LIGHTING)
   glDisable(GL_LOGIC_OP)
   glDisable(GL_DITHER)
   glDisable(GL_FOG)

   glHint(GL_POINT_SMOOTH_HINT, GL_FASTEST)
   glHint(GL_LINE_SMOOTH_HINT , GL_FASTEST)

   glPointSize( 1 )
   glLineWidth( 1 )
   
   
end sub






4. Delta time version (I know Lachie will like this)

Code: Select all

''*****************************************************************************
''
''   2.5D Engine (DeltaTime Version )
''   Relminator (Richard Eric M. Lope)
''    http://rel.phatcode.net
''
''    This is probably the easiest way to make a 3d game
''   Features:
''   * 1:1 ratio of 3D coords to Screen
''   * Collisions are in tilebased 2D
''   * Rendering can be camera based (uber fast)
''   * Any 2D tilebased game can be converted to this
''
''   Controls
''   
''   SPACE = Jump
''   ARROW KEYS = Move
''   F1 = Paper mario mode?
''   F2/F3 = Zoom
''
''*****************************************************************************

#include once "fbgfx.bi"
#include once "/gl/gl.bi"
#include once "/gl/glu.bi"   


declare function GetDeltaTime( byref FPS as single, byval TimerInSeconds as single) as single


''*****************************************************************************
declare sub GL_Screen_Init(byval screen_wid as integer, byval screen_hei as integer, byval flags as integer = 0)

'' Drawing stuff
''*****************************************************************************
declare sub DrawCube( x as single, y as single, z as single, Size as single, Red as single, Green as single, Blue as single )
declare sub DrawMap()


''*****************************************************************************
const as integer SCREEN_WIDTH = 640
const as integer SCREEN_HEIGHT = 480

const as integer TILE_SIZE = 32


const as integer MAP_WID = SCREEN_WIDTH\TILE_SIZE      '' 20
const as integer MAP_HEI = SCREEN_HEIGHT\TILE_SIZE      '' 15

const as integer FALSE = 0
const as integer TRUE = not FALSE

const as single Gravity = 1400   '' 35 pixels a second
const as single JumpHeight = 600


''*****************************************************************************
dim shared as integer Map(MAP_WID-1,MAP_HEI-1) =>_
{{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},_  ''1
{1,0,0,1,0,0,0,0,0,0,1,0,0,0,1},_   ''2
{1,0,0,1,0,0,0,0,0,0,1,0,0,0,1},_   ''3
{1,0,0,1,0,0,0,0,0,0,1,0,0,0,1},_   ''4
{1,0,0,1,0,0,0,0,0,0,1,0,0,0,1},_   ''5
{1,0,0,0,1,0,0,0,0,0,0,0,0,0,1},_   ''6
{1,0,0,0,0,0,0,0,0,0,1,0,0,0,1},_   ''7
{1,0,0,0,0,0,0,1,0,0,1,0,0,0,1},_   ''8
{1,0,0,0,0,1,0,0,0,0,0,0,0,0,1},_   ''9
{1,0,0,0,0,0,0,0,0,0,0,0,1,0,1},_   ''10
{1,0,0,0,0,1,0,0,0,0,0,0,1,0,1},_   ''11
{1,0,0,0,0,1,0,0,0,0,0,0,1,0,1},_   ''12
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,1},_   ''13
{1,0,0,0,0,0,1,0,0,0,0,0,1,0,1},_   ''14
{1,0,0,0,0,0,0,0,0,0,0,1,0,0,1},_   ''15
{1,0,0,0,0,0,1,0,0,0,0,1,0,0,1},_   ''16
{1,0,0,0,0,1,0,0,0,0,0,0,1,0,1},_   ''17
{1,0,0,0,0,1,0,0,0,0,0,0,0,0,1},_   ''18
{1,0,0,0,1,0,0,0,0,0,0,0,0,0,1},_   ''19
{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}}


''*****************************************************************************
''
''
''
''*****************************************************************************
type Player

   x      as single
   y      as single
   speed   as single
   xv      as single
   yv      as single
   wid      as integer
   hei      as integer
   
   CanJump as Integer
   
   declare constructor()
   declare function CollideFloors(byval ix as integer, byval iy as integer, byref TileY as integer, Map() as integer ) as integer
   declare function CollideWalls(byval ix as integer, byval iy as integer, byref TileX as integer, Map() as integer ) as integer
   declare sub DoStuff( byval dt as single )
   declare sub CollideOnMap( Map() as integer, byval dt as single )
   declare sub Draw3D()
   
end type

constructor Player()

   x = 32 * 2
   y = 32 * 5
   speed = 180   '' pixels a second
   wid = 24
   hei = 48
   CanJump = false
   
End Constructor



function Player.CollideWalls(byval ix as integer, byval iy as integer, byref TileX as integer, Map() as integer ) as integer
   
   dim as integer TileYpixels = iy - (iy mod TILE_SIZE)   '' Pixel of the player's head snapped to map grid
   dim as integer TestEnd = iy + hei                  '' Foot of the player
   
   TileX = ix\TILE_SIZE                           '' Current X map coord the player is on + x-velocity(+ width when moving right)
   
   dim as integer TileY = TileYpixels\TILE_SIZE         '' Current Y map coord of the player's head
   
   '' Scan downwards from head to foot if we collided with a tile on the right or left
   while (TileYpixels <= TestEnd)
      if (Map(TileX, TileY))   then return true         '' Found a tile

      TileY += 1                                 '' Next tile downward
      TileYpixels +=TILE_SIZE                        '' Next tile pixel downward
      
   Wend
   
   return false
End Function

function Player.CollideFloors(byval ix as integer, byval iy as integer, byref TileY as integer, Map() as integer ) as integer
   
   dim as integer TileXpixels = ix - (ix mod TILE_SIZE)
   dim as integer TestEnd = ix + wid
   
   TileY = iy\TILE_SIZE
   
   dim as integer TileX = TileXpixels\TILE_SIZE
   
   while (TileXpixels <= TestEnd)
      if (Map(TileX, TileY))   then return true   

      TileX += 1
      TileXpixels +=TILE_SIZE
      
   Wend
   
   return false
End Function



sub Player.DoStuff( byval dt as single )

   xv = 0
   
   if multikey(FB.SC_LEFT) then
      xv = -speed * dt
   EndIf
   
    if multikey(FB.SC_RIGHT) then
       xv = speed * dt
    EndIf
   
    if multikey(FB.SC_SPACE) then
       if( CanJump ) then
          yv = -JumpHeight
          CanJump = false
       end if
    EndIf
   
   
   
End Sub

sub Player.CollideOnMap( Map() as integer, byval dt as single  )
   
   dim as Integer TileX, TileY
   
   if( xv > 0 ) then
      
      if( CollideWalls( x + xv + wid, y, TileX, Map() ) ) then
         x = TileX * TILE_SIZE - wid - 1
      else
         x += xv
      EndIf
         
   elseif( xv < 0 ) then
      
      if( CollideWalls( x + xv, y, TileX, Map() ) ) then
         x = ( TileX + 1 ) * TILE_SIZE + 1
      else
         x += xv
      EndIf
      
   EndIf
   
   if( yv < 0 ) then
      
      if( CollideFloors( x, y + (yv * dt), TileY, Map() ) ) then   '' hit the roof
         y = ( TileY + 1 ) * TILE_SIZE + 1
         yv = 0   
      else
         y += yv * dt
         yv += Gravity * dt
      EndIf
         
   else
      
      if( CollideFloors( x, y + (yv * dt) + hei, TileY, Map() ) ) then   '' hit the floor
         y = ( TileY ) * TILE_SIZE - hei - 1
         yv = 150   '' bigger values
         if multikey(FB.SC_SPACE) then CanJump = true
      else
         y += yv * dt
         yv += Gravity * dt
         CanJump = false
      EndIf
      
   EndIf
   
   
End Sub


sub Player.Draw3D()

   '' Draws the player in 3D   
   dim as single SizeX = Wid/2.0
   dim as single SizeY = Hei/2.0
   
   
   glColor4f( 1, 0, 1, 1 )
   glPushMatrix()
      glTranslatef( x + Wid/2, y + Hei/2.0, 0) '' Offset by Size/2 so that we draw from top-left at (0,0)
      glBegin(GL_QUADS)
         glVertex3f(-SizeX, -SizeY,  0)
         glVertex3f( SizeX, -SizeY,  0)
         glVertex3f( SizeX,  SizeY,  0)
         glVertex3f(-SizeX,  SizeY,  0)         
      glEnd()
   glPopMatrix()
   
   
end sub

   
''*****************************************************************************
''
''
''
''*****************************************************************************

Type Vector2D

   x as Single
   y as Single
   z as single
   
end type

Type Camera
   
   
   declare Constructor()
   declare sub Follow( x as single, y as single )
   declare sub Look()
   declare sub Look( value as single )
   declare sub Zoom( value as single )

   
   
   Position as Vector2D
   Target as Vector2D
   Up as Vector2D
   
   EyeDistanceFromScreen as integer

end type


constructor Camera()

   EyeDistanceFromScreen = TILE_SIZE * 18   '' Distance of player's eye from screen
   
   Position.x = 0
   Position.y = 0
   Position.z = EyeDistanceFromScreen       '' Yep we are drawing at z = 0 so pos should be positive
   
   Target.x = 0
   Target.y = 0
   Target.z = 0
   
   Up.x = 0
   Up.y = 1
   Up.z = 0
   
   
end constructor   

sub Camera.Follow( x as single, y as single )

   
   Position.x = x
   Position.y = y - TILE_SIZE * 1          '' offset a little above so we look a little down
   Position.z = EyeDistanceFromScreen      '' move zpos n units from screen to eye
   
   Target.x = x
   Target.y = y
   Target.z = 0
   
   Up.x = 0
   Up.y = 1
   Up.z = 0
   
end sub


sub Camera.Look()

   
   gluLookAt( Position.x, Position.y, Position.z,_    '' camera pos
            Target.x, Target.y, Target.z,_          '' camera target
               Up.x, Up.y, Up.z)

end sub



sub Camera.Zoom( value as single )

   EyeDistanceFromScreen +=value

end sub
   

''*****************************************************************************
sub main()
   
   dim as single FPS
   dim as integer Frame = 0
   
   dim as Camera Cam
   dim as Player Mario
   
   GL_Screen_Init( SCREEN_WIDTH, SCREEN_HEIGHT )   ''Set up GL screen

   dim as single dt = GetDeltaTime( FPS, Timer )
   
   
   do
      
      Frame += 1

      dt = GetDeltaTime( FPS, Timer )
   
      Mario.DoStuff( dt )     '' Do player movements
   
      Mario.CollideOnMap( Map(), dt )      '' Do collisions in 2D
      
      
      '' Zoom if you want
      if( multikey(FB.SC_F2) ) then Cam.Zoom(1.62)
      if( multikey(FB.SC_F3) ) then Cam.Zoom(-1.62)
      
      
      
      glMatrixMode( GL_MODELVIEW )
      glLoadIdentity()
      glPolygonMode( GL_FRONT, GL_FILL )
      glPolygonMode( GL_BACK, GL_FILL )
      glEnable( GL_DEPTH_TEST )
      glDepthFunc( GL_LEQUAL )
      
      glDisable( GL_TEXTURE_2D )
   
      
      glColor4ub( 255, 255, 255, 255 )

      '' Move cam according to player's pos
      Cam.Follow( Mario.x, Mario.y )
      
      '' reverse y direction for oldskool coords(Easy GL2D = happy)
      glScalef( 1, -1, 1 )
      
      '' Look
      Cam.Look()
      
      '' Paper mario?
      if( multikey(FB.SC_F1) ) then glRotatef( 20, 0, 1, 0 )
      
      '' Clear screen
      glClear(GL_COLOR_BUFFER_BIT OR GL_DEPTH_BUFFER_BIT)

      '' Draw 3D stuff
      glPushMatrix()   
               
         DrawMap()
         Mario.Draw3D()

      glPopMatrix()   
      
      'screensync   
      flip
      
      sleep 10,1
      
   Loop until multikey(FB.SC_ESCAPE)

   
End Sub



main()


end








''*****************************************************************************
'' Temp way to draw our 32x32 tiles
sub DrawCube( x as single, y as single, z as single, Size as single, Red as single, Green as single, Blue as single )

   glColor4f( Red, Green, Blue, 1 )
   
   glPushMatrix()
      glTranslatef( x + Size, y + Size, z)  '' Offset by Size so that we draw from top-left at (0,0)
      
      glBegin(GL_QUADS)
         '' Front Face
         glColor3f( 1, 0, 0)
         glVertex3f(-Size, -Size,  Size)
         glColor3f( 0, 1, 0)
         glVertex3f( Size, -Size,  Size)
         glColor3f( 0, 0, 1)
         glVertex3f( Size,  Size,  Size)
         glColor3f( 1, 1, 1)
         glVertex3f(-Size,  Size,  Size)
         
         glColor4f( 1, 1, 0, 1 )
   
         '' Back Face
         glVertex3f(-Size, -Size, -Size)
         glVertex3f(-Size,  Size, -Size)
         glVertex3f( Size,  Size, -Size)
         glVertex3f( Size, -Size, -Size)
         '' Top Face
         glVertex3f(-Size,  Size, -Size)
         glVertex3f(-Size,  Size,  Size)
         glVertex3f( Size,  Size,  Size)
         glVertex3f( Size,  Size, -Size)
         '' Bottom Face
         glVertex3f(-Size, -Size, -Size)
         glVertex3f( Size, -Size, -Size)
         glVertex3f( Size, -Size,  Size)
         glVertex3f(-Size, -Size,  Size)
         '' Right face
         glVertex3f( Size, -Size, -Size)
         glVertex3f( Size,  Size, -Size)
         glVertex3f( Size,  Size,  Size)
         glVertex3f( Size, -Size,  Size)
         '' Left Face
         glVertex3f(-Size, -Size, -Size)
         glVertex3f(-Size, -Size,  Size)
         glVertex3f(-Size,  Size,  Size)
         glVertex3f(-Size,  Size, -Size)
      glEnd()
   
   glPopMatrix()
   
   glColor4f( 1, 1, 1, 1 )
   
   
end sub


'' Draws the map in 3D
sub DrawMap()

   for y as integer = 0 to (MAP_HEI - 1)
      for x as integer = 0 to (MAP_WID - 1)
         if( Map(x,y) > 0 ) then         
            DrawCube( x * TILE_SIZE, y * TILE_SIZE, 0, TILE_SIZE/2, 0, 1, 0 )
         end if
      next x   
   next y
   
end sub


''=============================================================================
''
''    Sets up OpenGL for 2d mode
''
''=============================================================================
sub GL_Screen_Init(byval screen_wid as integer, byval screen_hei as integer, byval flags as integer = 0)
   
   if flags then
      screenres screen_wid, screen_hei, 32, 2, FB.GFX_OPENGL or flags
   else
      screenres screen_wid, screen_hei, 32, 2, FB.GFX_OPENGL
   endif
   
   
   'screen information
   dim w as integer, h as integer
   'OpenGL params for gluerspective
   dim FOVy as double            'Field of view angle in Y
   dim Aspect as double          'Aspect of screen
   dim znear as double           'z-near clip distance
   dim zfar as double            'z-far clip distance

   'using screen info w and h as params
   glViewport(0, 0, screen_wid, screen_hei)
   
   'Set current Mode to projection(ie: 3d)
   glMatrixMode(GL_PROJECTION)
   
   'Load identity matrix to projection matrix
   glLoadIdentity()

   'Set gluPerspective params
   FOVy = 90/2                                     '45 deg fovy
   Aspect = screen_wid / screen_hei
   znear = 1                                       'Near clip
   zfar = 1500                                     'far clip
   
   'use glu Perspective to set our 3d frustum dimension up
   gluPerspective(FOVy, aspect, znear, zfar)
   
   'Modelview mode
   'ie. Matrix that does things to anything we draw
   'as in lines, points, tris, etc.
   glMatrixMode(GL_MODELVIEW)
   'load identity(clean) matrix to modelview
   glLoadIdentity()
   
   glShadeModel(GL_SMOOTH)                 'set shading to smooth(try GL_FLAT)
   glClearColor(0.0, 0.0, 0.0, 1.0)        'set Clear color to BLACK
   glClearDepth(1.0)                       'Set Depth buffer to 1(z-Buffer)
   glEnable(GL_DEPTH_TEST)                 'Enable Depth Testing so that our z-buffer works
   
   'compare each incoming pixel z value with the z value present in the depth buffer
   'LEQUAL means than pixel is drawn if the incoming z value is less than
   'or equal to the stored z value
   glDepthFunc(GL_LEQUAL)
   
   'have one or more material parameters track the current color
   'Material is your 3d model
   glEnable(GL_COLOR_MATERIAL)


    'Enable Texturing
    glEnable(GL_TEXTURE_2D)
   

      'Tell openGL that we want the best possible perspective transform
   glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST)
   
   'Disable Backface culling
   glDisable (GL_CULL_FACE)
   
   glPolygonMode(GL_FRONT, GL_FILL)
   
   '' enable blending for transparency
   glEnable(GL_BLEND)          
   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
   
   glDisable( GL_DEPTH_TEST )
   
   glEnable( GL_ALPHA_TEST )
   glAlphaFunc(GL_GREATER, 0)


   glDisable(GL_STENCIL_TEST)
   glDisable(GL_TEXTURE_1D)
   glDisable(GL_LIGHTING)
   glDisable(GL_LOGIC_OP)
   glDisable(GL_DITHER)
   glDisable(GL_FOG)

   glHint(GL_POINT_SMOOTH_HINT, GL_FASTEST)
   glHint(GL_LINE_SMOOTH_HINT , GL_FASTEST)

   glPointSize( 1 )
   glLineWidth( 1 )
   
   
end sub



function GetDeltaTime( byref FPS as single, byval TimerInSeconds as single) as single
   
   '' vars to be used in calculating FPS
   static as single FramesPerSecond = 0.0
   static as single PreviousTime = 0
   
   '' var to save our last time for comparing
   static as single OldTime = 0.0

   '' Get the current time in seconds
   dim as single CurrentTime = TimerInSeconds             
   
   '' Time interval between frames
   dim as single ElapsedTime = CurrentTime - OldTime
   
   
   '' Save the current time for comparing the next frame time
   OldTime = CurrentTime
   
   '' Increase the frame counter
   FramesPerSecond += 1
   
   '' Calculate FPS
   if( (CurrentTime - PreviousTime) > 1.0  ) then
   
      '' Save old_time
       PreviousTime = CurrentTime

      '' duh?      
      FPS = FramesPerSecond
      
      '' Reset the frames counter since 1 second has already elapsed
       FramesPerSecond = 0
   end if 
   
   return ElapsedTime
   
end function

Last edited by relsoft on Aug 17, 2012 2:40, edited 1 time in total.
relsoft
Posts: 1765
Joined: May 27, 2005 10:34
Location: Philippines
Contact:

Re: The easiest way to code a 3d Platformer.

Postby relsoft » Aug 17, 2012 2:32

5. Fixed cam for puzzlers

Code: Select all

''*****************************************************************************
''
''   2.5D Engine (Fixed Camera)
''   Relminator (Richard Eric M. Lope)
''    http://rel.phatcode.net
''
''    This is probably the easiest way to make a 3d game
''   Features:
''   * 1:1 ratio of 3D coords to Screen
''   * Collisions are in tilebased 2D
''   * Rendering can be camera based (uber fast)
''   * Any 2D tilebased game can be converted to this
''
''   Controls
''   
''   SPACE = Jump
''   ARROW KEYS = Move
''   F1 = Paper mario mode?
''   F2/F3 = Zoom
''
''*****************************************************************************

#include once "fbgfx.bi"
#include once "/gl/gl.bi"
#include once "/gl/glu.bi"   


''*****************************************************************************
declare sub GL_Screen_Init(byval screen_wid as integer, byval screen_hei as integer, byval flags as integer = 0)

'' Drawing stuff
''*****************************************************************************
declare sub DrawCube( x as single, y as single, z as single, Size as single, Red as single, Green as single, Blue as single )
declare sub DrawMap()


''*****************************************************************************
const as integer SCREEN_WIDTH = 640
const as integer SCREEN_HEIGHT = 480

const as integer TILE_SIZE = 32


const as integer MAP_WID = SCREEN_WIDTH\TILE_SIZE      '' 20
const as integer MAP_HEI = SCREEN_HEIGHT\TILE_SIZE      '' 15

const as integer FALSE = 0
const as integer TRUE = not FALSE

const as single Gravity = 0.75
const as single JumpHeight = 15


''*****************************************************************************
dim shared as integer Map(MAP_WID-1,MAP_HEI-1) =>_
{{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},_  ''1
{1,0,0,1,0,0,0,0,0,0,1,0,0,0,1},_   ''2
{1,0,0,1,0,0,0,0,0,0,1,0,0,0,1},_   ''3
{1,0,0,1,0,0,0,0,0,0,1,0,0,0,1},_   ''4
{1,0,0,1,0,0,0,0,0,0,1,0,0,0,1},_   ''5
{1,0,0,0,1,0,0,0,0,0,0,0,0,0,1},_   ''6
{1,0,0,0,0,0,0,0,0,0,1,0,0,0,1},_   ''7
{1,0,0,0,0,0,0,1,0,0,1,0,0,0,1},_   ''8
{1,0,0,0,0,1,0,0,0,0,0,0,0,0,1},_   ''9
{1,0,0,0,0,0,0,0,0,0,0,0,1,0,1},_   ''10
{1,0,0,0,0,1,0,0,0,0,0,0,1,0,1},_   ''11
{1,0,0,0,0,1,0,0,0,0,0,0,1,0,1},_   ''12
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,1},_   ''13
{1,0,0,0,0,0,1,0,0,0,0,0,1,0,1},_   ''14
{1,0,0,0,0,0,0,0,0,0,0,1,0,0,1},_   ''15
{1,0,0,0,0,0,1,0,0,0,0,1,0,0,1},_   ''16
{1,0,0,0,0,1,0,0,0,0,0,0,1,0,1},_   ''17
{1,0,0,0,0,1,0,0,0,0,0,0,0,0,1},_   ''18
{1,0,0,0,1,0,0,0,0,0,0,0,0,0,1},_   ''19
{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}}


''*****************************************************************************
''
''
''
''*****************************************************************************
type Player

   x      as single
   y      as single
   speed   as single
   xv      as single
   yv      as single
   wid      as integer
   hei      as integer
   
   CanJump as integer
   
   declare constructor()
   declare function CollideFloors(byval ix as integer, byval iy as integer, byref TileY as integer, Map() as integer ) as integer
   declare function CollideWalls(byval ix as integer, byval iy as integer, byref TileX as integer, Map() as integer ) as integer
   declare sub DoStuff()
   declare sub CollideOnMap( Map() as integer )
   declare sub Draw3D()
   
end type

constructor Player()
   x = 32 * 2
   y = 32 * 5
   speed = 4.5
   wid = 24
   hei = 48
   CanJump = false
End Constructor



function Player.CollideWalls(byval ix as integer, byval iy as integer, byref TileX as integer, Map() as integer ) as integer
   
   dim as integer TileYpixels = iy - (iy mod TILE_SIZE)   '' Pixel of the player's head snapped to map grid
   dim as integer TestEnd = iy + hei                  '' Foot of the player
   
   TileX = ix\TILE_SIZE                           '' Current X map coord the player is on + x-velocity(+ width when moving right)
   
   dim as integer TileY = TileYpixels\TILE_SIZE         '' Current Y map coord of the player's head
   
   '' Scan downwards from head to foot if we collided with a tile on the right or left
   while (TileYpixels <= TestEnd)
      if (Map(TileX, TileY))   then return true         '' Found a tile

      TileY += 1                                 '' Next tile downward
      TileYpixels +=TILE_SIZE                        '' Next tile pixel downward
      
   Wend
   
   return false
End Function

function Player.CollideFloors(byval ix as integer, byval iy as integer, byref TileY as integer, Map() as integer ) as integer
   
   dim as integer TileXpixels = ix - (ix mod TILE_SIZE)
   dim as integer TestEnd = ix + wid
   
   TileY = iy\TILE_SIZE
   
   dim as integer TileX = TileXpixels\TILE_SIZE
   
   while (TileXpixels <= TestEnd)
      if (Map(TileX, TileY))   then return true   

      TileX += 1
      TileXpixels +=TILE_SIZE
      
   Wend
   
   return false
End Function



sub Player.DoStuff()

   xv = 0
   
   if multikey(FB.SC_LEFT) then
      xv = -speed
   EndIf
   
    if multikey(FB.SC_RIGHT) then
       xv = speed
    EndIf
   
    if multikey(FB.SC_SPACE) then
       if( CanJump ) then
          yv = -JumpHeight
          CanJump = false
       end if
    EndIf
   
   
   
End Sub

sub Player.CollideOnMap( Map() as integer )
   
   dim as Integer TileX, TileY

   if( xv > 0 ) then
      
      if( CollideWalls( x + xv + wid, y, TileX, Map() ) ) then
         x = TileX * TILE_SIZE - wid - 1
      else
         x += xv
      EndIf
         
   elseif( xv < 0 ) then
      
      if( CollideWalls( x + xv, y, TileX, Map() ) ) then
         x = ( TileX + 1 ) * TILE_SIZE + 1
      else
         x += xv
      EndIf
      
   EndIf
   
   if( yv < 0 ) then
      
      if( CollideFloors( x, y + yv, TileY, Map() ) ) then   '' hit the roof
         y = ( TileY + 1 ) * TILE_SIZE + 1
         yv = 0   
      else
         y += yv
         yv += Gravity
      EndIf
         
   else
      
      if( CollideFloors( x, y + yv + hei, TileY, Map() ) ) then
         y = ( TileY ) * TILE_SIZE - hei - 1
         yv = 1
         if not multikey(FB.SC_SPACE) then CanJump = true
      else
         y += yv
         yv += Gravity
         CanJump = false
      EndIf
      
   EndIf
   
   
End Sub


sub Player.Draw3D()

   '' Draws the player in 3D   
   dim as single SizeX = Wid/2.0
   dim as single SizeY = Hei/2.0
   
   
   glColor4f( 1, 0, 1, 1 )
   glPushMatrix()
      glTranslatef( x + Wid/2, y + Hei/2.0, 0) '' Offset by Size/2 so that we draw from top-left at (0,0)
      glBegin(GL_QUADS)
         glVertex3f(-SizeX, -SizeY,  0)
         glVertex3f( SizeX, -SizeY,  0)
         glVertex3f( SizeX,  SizeY,  0)
         glVertex3f(-SizeX,  SizeY,  0)         
      glEnd()
   glPopMatrix()
   
   
end sub

   
''*****************************************************************************
''
''
''
''*****************************************************************************

Type Vector2D

   x as Single
   y as Single
   z as single
   
end type

Type Camera
   
   
   declare Constructor()
   declare sub Follow( x as single, y as single )
   declare sub Look()
   declare sub Look( value as single )
   declare sub Zoom( value as single )

   
   
   Position as Vector2D
   Target as Vector2D
   Up as Vector2D
   
   EyeDistanceFromScreen as integer

end type


constructor Camera()

   EyeDistanceFromScreen = TILE_SIZE * 18   '' Distance of player's eye from screen
   
   Position.x = 0
   Position.y = 0
   Position.z = EyeDistanceFromScreen       '' Yep we are drawing at z = 0 so pos should be positive
   
   Target.x = 0
   Target.y = 0
   Target.z = 0
   
   Up.x = 0
   Up.y = 1
   Up.z = 0
   
   
end constructor   

sub Camera.Follow( x as single, y as single )

   
   Position.x = x
   Position.y = y - TILE_SIZE * 1          '' offset a little above so we look a little down
   Position.z = EyeDistanceFromScreen      '' move zpos n units from screen to eye
   
   Target.x = x
   Target.y = y
   Target.z = 0
   
   Up.x = 0
   Up.y = 1
   Up.z = 0
   
end sub


sub Camera.Look()

   
   gluLookAt( Position.x, Position.y, Position.z,_    '' camera pos
            Target.x, Target.y, Target.z,_          '' camera target
               Up.x, Up.y, Up.z)

end sub



sub Camera.Zoom( value as single )

   EyeDistanceFromScreen +=value

end sub
   

''*****************************************************************************
sub main()
   
   
   dim as integer Frame = 0
   
   dim as Camera Cam
   dim as Player Mario
   
   GL_Screen_Init( SCREEN_WIDTH, SCREEN_HEIGHT )   ''Set up GL screen

   
   do
      
      Frame += 1

      Mario.DoStuff()     '' Do player movements
   
      Mario.CollideOnMap( Map() )      '' Do collisions in 2D
      
      
      '' Zoom if you want
      if( multikey(FB.SC_F2) ) then Cam.Zoom(1.62)
      if( multikey(FB.SC_F3) ) then Cam.Zoom(-1.62)
      
      
      
      glMatrixMode( GL_MODELVIEW )
      glLoadIdentity()
      glPolygonMode( GL_FRONT, GL_FILL )
      glPolygonMode( GL_BACK, GL_FILL )
      glEnable( GL_DEPTH_TEST )
      glDepthFunc( GL_LEQUAL )
      
      glDisable( GL_TEXTURE_2D )
   
      
      glColor4ub( 255, 255, 255, 255 )

      '' Just fix the camera to the center of the screen
      Cam.Follow( SCREEN_WIDTH\2, SCREEN_HEIGHT\2 )
      
      '' reverse y direction for oldskool coords(Easy GL2D = happy)
      glScalef( 1, -1, 1 )
      
      '' Look
      Cam.Look()
      
      '' Paper mario?
      if( multikey(FB.SC_F1) ) then glRotatef( 20, 0, 1, 0 )
      
      '' Clear screen
      glClear(GL_COLOR_BUFFER_BIT OR GL_DEPTH_BUFFER_BIT)

      '' Draw 3D stuff
      glPushMatrix()   
               
         DrawMap()
         Mario.Draw3D()

      glPopMatrix()   
      
      '' limit FPS
      dim as single TimeStart = timer
      while( (timer - TimeStart) < (1.0/60.0) )
         sleep 1,1
      wend
      
      
      flip
      
   Loop until multikey(FB.SC_ESCAPE)

   
   
End Sub



main()


end








''*****************************************************************************
'' Temp way to draw our 32x32 tiles
sub DrawCube( x as single, y as single, z as single, Size as single, Red as single, Green as single, Blue as single )

   glColor4f( Red, Green, Blue, 1 )
   
   glPushMatrix()
      glTranslatef( x + Size, y + Size, z)  '' Offset by Size so that we draw from top-left at (0,0)
   
      glBegin(GL_QUADS)
         '' Front Face
         glColor3f( 1, 0, 0)
         glVertex3f(-Size, -Size,  Size)
         glColor3f( 0, 1, 0)
         glVertex3f( Size, -Size,  Size)
         glColor3f( 0, 0, 1)
         glVertex3f( Size,  Size,  Size)
         glColor3f( 1, 1, 1)
         glVertex3f(-Size,  Size,  Size)
         
         glColor4f( 1, 1, 0, 1 )
   
         '' Back Face
         glVertex3f(-Size, -Size, -Size)
         glVertex3f(-Size,  Size, -Size)
         glVertex3f( Size,  Size, -Size)
         glVertex3f( Size, -Size, -Size)
         '' Top Face
         glVertex3f(-Size,  Size, -Size)
         glVertex3f(-Size,  Size,  Size)
         glVertex3f( Size,  Size,  Size)
         glVertex3f( Size,  Size, -Size)
         '' Bottom Face
         glVertex3f(-Size, -Size, -Size)
         glVertex3f( Size, -Size, -Size)
         glVertex3f( Size, -Size,  Size)
         glVertex3f(-Size, -Size,  Size)
         '' Right face
         glVertex3f( Size, -Size, -Size)
         glVertex3f( Size,  Size, -Size)
         glVertex3f( Size,  Size,  Size)
         glVertex3f( Size, -Size,  Size)
         '' Left Face
         glVertex3f(-Size, -Size, -Size)
         glVertex3f(-Size, -Size,  Size)
         glVertex3f(-Size,  Size,  Size)
         glVertex3f(-Size,  Size, -Size)
      glEnd()
   
   glPopMatrix()
   
   glColor4f( 1, 1, 1, 1 )
   
   
end sub


'' Draws the map in 3D
sub DrawMap()

   for y as integer = 0 to (MAP_HEI - 1)
      for x as integer = 0 to (MAP_WID - 1)
         if( Map(x,y) > 0 ) then         
            DrawCube( x * TILE_SIZE, y * TILE_SIZE, 0, TILE_SIZE/2, 0, 1, 0 )
         end if
      next x   
   next y
   
end sub


''=============================================================================
''
''    Sets up OpenGL for 2d mode
''
''=============================================================================
sub GL_Screen_Init(byval screen_wid as integer, byval screen_hei as integer, byval flags as integer = 0)
   
   if flags then
      screenres screen_wid, screen_hei, 32, 2, FB.GFX_OPENGL or flags
   else
      screenres screen_wid, screen_hei, 32, 2, FB.GFX_OPENGL
   endif
   
   
   'screen information
   dim w as integer, h as integer
   'OpenGL params for gluerspective
   dim FOVy as double            'Field of view angle in Y
   dim Aspect as double          'Aspect of screen
   dim znear as double           'z-near clip distance
   dim zfar as double            'z-far clip distance

   'using screen info w and h as params
   glViewport(0, 0, screen_wid, screen_hei)
   
   'Set current Mode to projection(ie: 3d)
   glMatrixMode(GL_PROJECTION)
   
   'Load identity matrix to projection matrix
   glLoadIdentity()

   'Set gluPerspective params
   FOVy = 90/2                                     '45 deg fovy
   Aspect = screen_wid / screen_hei
   znear = 1                                       'Near clip
   zfar = 1500                                     'far clip
   
   'use glu Perspective to set our 3d frustum dimension up
   gluPerspective(FOVy, aspect, znear, zfar)
   
   'Modelview mode
   'ie. Matrix that does things to anything we draw
   'as in lines, points, tris, etc.
   glMatrixMode(GL_MODELVIEW)
   'load identity(clean) matrix to modelview
   glLoadIdentity()
   
   glShadeModel(GL_SMOOTH)                 'set shading to smooth(try GL_FLAT)
   glClearColor(0.0, 0.0, 0.0, 1.0)        'set Clear color to BLACK
   glClearDepth(1.0)                       'Set Depth buffer to 1(z-Buffer)
   glEnable(GL_DEPTH_TEST)                 'Enable Depth Testing so that our z-buffer works
   
   'compare each incoming pixel z value with the z value present in the depth buffer
   'LEQUAL means than pixel is drawn if the incoming z value is less than
   'or equal to the stored z value
   glDepthFunc(GL_LEQUAL)
   
   'have one or more material parameters track the current color
   'Material is your 3d model
   glEnable(GL_COLOR_MATERIAL)


    'Enable Texturing
    glEnable(GL_TEXTURE_2D)
   

      'Tell openGL that we want the best possible perspective transform
   glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST)
   
   'Disable Backface culling
   glDisable (GL_CULL_FACE)
   
   glPolygonMode(GL_FRONT, GL_FILL)
   
   '' enable blending for transparency
   glEnable(GL_BLEND)          
   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
   
   glDisable( GL_DEPTH_TEST )
   
   glEnable( GL_ALPHA_TEST )
   glAlphaFunc(GL_GREATER, 0)


   glDisable(GL_STENCIL_TEST)
   glDisable(GL_TEXTURE_1D)
   glDisable(GL_LIGHTING)
   glDisable(GL_LOGIC_OP)
   glDisable(GL_DITHER)
   glDisable(GL_FOG)

   glHint(GL_POINT_SMOOTH_HINT, GL_FASTEST)
   glHint(GL_LINE_SMOOTH_HINT , GL_FASTEST)

   glPointSize( 1 )
   glLineWidth( 1 )
   
   
end sub





6. Debug( Just to show you the relationship between 2D and 3D )

Code: Select all

''*****************************************************************************
''
''   2.5D Engine (Added a 2d mode so that 1:1 ratio can be verified)
''   Relminator (Richard Eric M. Lope)
''    http://rel.phatcode.net
''
''    This is probably the easiest way to make a 3d game
''   Features:
''   * 1:1 ratio of 3D coords to Screen
''   * Collisions are in tilebased 2D
''   * Rendering can be camera based (uber fast)
''   * Any 2D tilebased game can be converted to this
''
''   Controls
''   
''   SPACE = Jump
''   ARROW KEYS = Move
''   F1 = Paper mario mode?
''   F2/F3 = Zoom
''
''*****************************************************************************

#include once "fbgfx.bi"
#include once "/gl/gl.bi"
#include once "/gl/glu.bi"   


''*****************************************************************************
'' Easy GL2D stuff (needed for printing and debugging)
#define ARGB_A(u) (((u) shr 24) and &H000000FF)
#define ARGB_R(u) (((u) shr 16) and &H000000FF)
#define ARGB_G(u) (((u) shr 8)  and &H000000FF)
#define ARGB_B(u) (((u) shr 0)  and &H000000FF)
#define ARGB( r, g, b, a )   rgba( (b), (g), (r), (a) )
#define GL2D_RGBA( r, g, b, a )   rgba( (b), (g), (r), (a) )

dim shared as GLuint current_texture = 0
dim shared as GLuint font_list_base = 0
dim shared as GLuint font_textureID = 0

declare sub GL2D_Screen_Init(byval screen_wid as integer, byval screen_hei as integer, byval flags as integer = 0)
declare sub GL2D_Clear_Screen()
declare sub GL2D_Begin2D(byval wid as integer, byval hei as integer)
declare sub GL2D_End2D() 
declare sub GL2D_Print_Scale(byval x as integer, byval y as integer, byval scale as single, byref text as const string)
declare sub GL2D_Box( byval x1 as integer, byval y1 as integer, byval x2 as integer, byval y2 as integer, byval gl2dcolor as GLuint )
declare sub GL2D_Box_Filled( byval x1 as integer, byval y1 as integer, byval x2 as integer, byval y2 as integer, byval gl2dcolor as GLuint )
declare sub GL2D_VsyncOn()

'' Drawing stuff
''*****************************************************************************
declare sub DrawCube( x as single, y as single, z as single, Size as single, Red as single, Green as single, Blue as single )
declare sub DrawMap()
declare sub DrawMap2D()


''*****************************************************************************
const as integer SCREEN_WIDTH = 640
const as integer SCREEN_HEIGHT = 480

const as integer TILE_SIZE = 32


const as integer MAP_WID = SCREEN_WIDTH\TILE_SIZE      '' 20
const as integer MAP_HEI = SCREEN_HEIGHT\TILE_SIZE      '' 15

const as integer FALSE = 0
const as integer TRUE = not FALSE

const as single Gravity = 0.75
const as single JumpHeight = 15


''*****************************************************************************
dim shared as integer Map(MAP_WID-1,MAP_HEI-1) =>_
{{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},_  ''1
{1,0,0,1,0,0,0,0,0,0,1,0,0,0,1},_   ''2
{1,0,0,1,0,0,0,0,0,0,1,0,0,0,1},_   ''3
{1,0,0,1,0,0,0,0,0,0,1,0,0,0,1},_   ''4
{1,0,0,1,0,0,0,0,0,0,1,0,0,0,1},_   ''5
{1,0,0,0,1,0,0,0,0,0,0,0,0,0,1},_   ''6
{1,0,0,0,0,0,0,0,0,0,1,0,0,0,1},_   ''7
{1,0,0,0,0,0,0,1,0,0,1,0,0,0,1},_   ''8
{1,0,0,0,0,1,0,0,0,0,0,0,0,0,1},_   ''9
{1,0,0,0,0,0,0,0,0,0,0,0,1,0,1},_   ''10
{1,0,0,0,0,1,0,0,0,0,0,0,1,0,1},_   ''11
{1,0,0,0,0,1,0,0,0,0,0,0,1,0,1},_   ''12
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,1},_   ''13
{1,0,0,0,0,0,1,0,0,0,0,0,1,0,1},_   ''14
{1,0,0,0,0,0,0,0,0,0,0,1,0,0,1},_   ''15
{1,0,0,0,0,0,1,0,0,0,0,1,0,0,1},_   ''16
{1,0,0,0,0,1,0,0,0,0,0,0,1,0,1},_   ''17
{1,0,0,0,0,1,0,0,0,0,0,0,0,0,1},_   ''18
{1,0,0,0,1,0,0,0,0,0,0,0,0,0,1},_   ''19
{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}}


''*****************************************************************************
''
''
''
''*****************************************************************************
type Player

   x      as single
   y      as single
   speed   as single
   xv      as single
   yv      as single
   wid      as integer
   hei      as integer
   
   CanJump as integer
   
   declare constructor()
   declare function CollideFloors(byval ix as integer, byval iy as integer, byref TileY as integer, Map() as integer ) as integer
   declare function CollideWalls(byval ix as integer, byval iy as integer, byref TileX as integer, Map() as integer ) as integer
   declare sub DoStuff()
   declare sub CollideOnMap( Map() as integer )
   declare sub Draw3D()
   declare sub Draw2D()
   
end type

constructor Player()
   x = 32 * 2
   y = 32 * 5
   speed = 4.5
   wid = 24
   hei = 48
   CanJump = false
End Constructor



function Player.CollideWalls(byval ix as integer, byval iy as integer, byref TileX as integer, Map() as integer ) as integer
   
   dim as integer TileYpixels = iy - (iy mod TILE_SIZE)   '' Pixel of the player's head snapped to map grid
   dim as integer TestEnd = iy + hei                  '' Foot of the player
   
   TileX = ix\TILE_SIZE                           '' Current X map coord the player is on + x-velocity(+ width when moving right)
   
   dim as integer TileY = TileYpixels\TILE_SIZE         '' Current Y map coord of the player's head
   
   '' Scan downwards from head to foot if we collided with a tile on the right or left
   while (TileYpixels <= TestEnd)
      if (Map(TileX, TileY))   then return true         '' Found a tile

      TileY += 1                                 '' Next tile downward
      TileYpixels +=TILE_SIZE                        '' Next tile pixel downward
      
   Wend
   
   return false
End Function

function Player.CollideFloors(byval ix as integer, byval iy as integer, byref TileY as integer, Map() as integer ) as integer
   
   dim as integer TileXpixels = ix - (ix mod TILE_SIZE)
   dim as integer TestEnd = ix + wid
   
   TileY = iy\TILE_SIZE
   
   dim as integer TileX = TileXpixels\TILE_SIZE
   
   while (TileXpixels <= TestEnd)
      if (Map(TileX, TileY))   then return true   

      TileX += 1
      TileXpixels +=TILE_SIZE
      
   Wend
   
   return false
End Function



sub Player.DoStuff()

   xv = 0
   
   if multikey(FB.SC_LEFT) then
      xv = -speed
   EndIf
   
    if multikey(FB.SC_RIGHT) then
       xv = speed
    EndIf
   
    if multikey(FB.SC_SPACE) then
       if( CanJump ) then
          yv = -JumpHeight
          CanJump = false
       end if
    EndIf
   
   
   
End Sub

sub Player.CollideOnMap( Map() as integer )
   
   dim as Integer TileX, TileY

   if( xv > 0 ) then
      
      if( CollideWalls( x + xv + wid, y, TileX, Map() ) ) then
         x = TileX * TILE_SIZE - wid - 1
      else
         x += xv
      EndIf
         
   elseif( xv < 0 ) then
      
      if( CollideWalls( x + xv, y, TileX, Map() ) ) then
         x = ( TileX + 1 ) * TILE_SIZE + 1
      else
         x += xv
      EndIf
      
   EndIf
   
   if( yv < 0 ) then
      
      if( CollideFloors( x, y + yv, TileY, Map() ) ) then   '' hit the roof
         y = ( TileY + 1 ) * TILE_SIZE + 1
         yv = 0   
      else
         y += yv
         yv += Gravity
      EndIf
         
   else
      
      if( CollideFloors( x, y + yv + hei, TileY, Map() ) ) then
         y = ( TileY ) * TILE_SIZE - hei - 1
         yv = 1
         if not multikey(FB.SC_SPACE) then CanJump = true
      else
         y += yv
         yv += Gravity
         CanJump = false
      EndIf
      
   EndIf
   
   
End Sub


sub Player.Draw3D()

   '' Draws the player in 3D   
   dim as single SizeX = Wid/2.0
   dim as single SizeY = Hei/2.0
   
   
   glColor4f( 1, 0, 1, 1 )
   glPushMatrix()
      glTranslatef( x + Wid/2, y + Hei/2.0, 0) '' Offset by Size/2 so that we draw from top-left at (0,0)
      glBegin(GL_QUADS)
         glVertex3f(-SizeX, -SizeY,  0)
         glVertex3f( SizeX, -SizeY,  0)
         glVertex3f( SizeX,  SizeY,  0)
         glVertex3f(-SizeX,  SizeY,  0)         
      glEnd()
   glPopMatrix()
   
   
end sub

sub Player.Draw2D()
   
   '' 2D mode for debugging
   GL2D_Box( x, y, x + Wid, y + Hei, GL2D_RGBA(255,0,255, 255) )
   
end sub
   
''*****************************************************************************
''
''
''
''*****************************************************************************

Type Vector2D

   x as Single
   y as Single
   z as single
   
end type

Type Camera
   
   
   declare Constructor()
   declare sub Follow( x as single, y as single )
   declare sub Look()
   declare sub Zoom( value as single )

   
   
   Position as Vector2D
   Target as Vector2D
   Up as Vector2D
   
   EyeDistanceFromScreen as integer

end type


constructor Camera()

   EyeDistanceFromScreen = TILE_SIZE * 18   '' Distance of player's eye from screen
   
   Position.x = 0
   Position.y = 0
   Position.z = EyeDistanceFromScreen       '' Yep we are drawing at z = 0 so pos should be positive
   
   Target.x = 0
   Target.y = 0
   Target.z = 0
   
   Up.x = 0
   Up.y = 1
   Up.z = 0
   
   
end constructor   

sub Camera.Follow( x as single, y as single )

   
   Position.x = x
   Position.y = y - TILE_SIZE * 1          '' offset a little above so we look a little down
   Position.z = EyeDistanceFromScreen      '' move zpos n units from screen to eye
   
   Target.x = x
   Target.y = y
   Target.z = 0
   
   Up.x = 0
   Up.y = 1
   Up.z = 0
   
end sub


sub Camera.Look()

   
   gluLookAt( Position.x, Position.y, Position.z,_    '' camera pos
            Target.x, Target.y, Target.z,_          '' camera target
               Up.x, Up.y, Up.z)

end sub

sub Camera.Zoom( value as single )

   EyeDistanceFromScreen +=value

end sub
   

''*****************************************************************************
sub main()
   
   
   dim as integer Frame = 0
   
   dim as Camera Cam
   dim as Player Mario
   
   GL2D_Screen_Init( SCREEN_WIDTH, SCREEN_HEIGHT )   ''Set up GL screen

   
   do
      
      Frame += 1

      Mario.DoStuff()     '' Do player movements
   
      Mario.CollideOnMap( Map() )      '' Do collisions in 2D
      
      
      '' Zoom if you want
      if( multikey(FB.SC_F2) ) then Cam.Zoom(1.62)
      if( multikey(FB.SC_F3) ) then Cam.Zoom(-1.62)
      
      
      
      glMatrixMode( GL_MODELVIEW )
      glLoadIdentity()
      glPolygonMode( GL_FRONT, GL_FILL )
      glPolygonMode( GL_BACK, GL_FILL )
      glEnable( GL_DEPTH_TEST )
      glDepthFunc( GL_LEQUAL )
      
      glDisable( GL_TEXTURE_2D )
   
      
      glColor4ub( 255, 255, 255, 255 )

      '' Move cam according to player's pos
      Cam.Follow( Mario.x, Mario.y )
      
      '' reverse y direction for oldskool coords(Easy GL2D = happy)
      glScalef( 1, -1, 1 )
      
      '' Look
      Cam.Look()
      
      '' Paper mario?
      if( multikey(FB.SC_F1) ) then glRotatef( 20, 0, 1, 0 )
      
      '' Clear screen
      GL2D_Clear_Screen()

      '' Draw 3D stuff
      glPushMatrix()   
               
         DrawMap()
         Mario.Draw3D()

      glPopMatrix()   
      
      '' 2D mode
      GL2D_Begin2D( SCREEN_WIDTH, SCREEN_HEIGHT )
      
         glEnable( GL_TEXTURE_2D )
         
         DrawMap2D()
         Mario.Draw2D()
         
         glColor4ub(255,255,255,255)  '' no transluceny
         GL2D_Print_Scale(0,  0, 1, "TileX = " & Mario.x\TILE_SIZE )
         GL2D_Print_Scale(0, 10, 1, "TileY = " & Mario.y\TILE_SIZE )
         
         GL2D_Print_Scale(0, 30, 1, "Controls:")
         GL2D_Print_Scale(0, 40, 1, "SPACE = Jump" )
         GL2D_Print_Scale(0, 50, 1, "F1 = Skew cam" )
         GL2D_Print_Scale(0, 60, 1, "F2/F3 = zoom/pan cam" )
         
         
         
      GL2D_End2D()
      
      '' limit FPS
      dim as single TimeStart = timer
      while( (timer - TimeStart) < (1.0/60.0) )
         sleep 1,1
      wend
      
      
      flip
      
   Loop until multikey(FB.SC_ESCAPE)

   
   
End Sub



main()


end








''*****************************************************************************
'' Temp way to draw our 32x32 tiles
sub DrawCube( x as single, y as single, z as single, Size as single, Red as single, Green as single, Blue as single )

   glColor4f( Red, Green, Blue, 1 )
   
   glPushMatrix()
      glTranslatef( x + Size, y + Size, z)  '' Offset by Size so that we draw from top-left at (0,0)
   
      glBegin(GL_QUADS)
         '' Front Face
         glColor3f( 1, 0, 0)
         glVertex3f(-Size, -Size,  Size)
         glColor3f( 0, 1, 0)
         glVertex3f( Size, -Size,  Size)
         glColor3f( 0, 0, 1)
         glVertex3f( Size,  Size,  Size)
         glColor3f( 1, 1, 1)
         glVertex3f(-Size,  Size,  Size)
         
         glColor4f( 1, 1, 0, 1 )
   
         '' Back Face
         glVertex3f(-Size, -Size, -Size)
         glVertex3f(-Size,  Size, -Size)
         glVertex3f( Size,  Size, -Size)
         glVertex3f( Size, -Size, -Size)
         '' Top Face
         glVertex3f(-Size,  Size, -Size)
         glVertex3f(-Size,  Size,  Size)
         glVertex3f( Size,  Size,  Size)
         glVertex3f( Size,  Size, -Size)
         '' Bottom Face
         glVertex3f(-Size, -Size, -Size)
         glVertex3f( Size, -Size, -Size)
         glVertex3f( Size, -Size,  Size)
         glVertex3f(-Size, -Size,  Size)
         '' Right face
         glVertex3f( Size, -Size, -Size)
         glVertex3f( Size,  Size, -Size)
         glVertex3f( Size,  Size,  Size)
         glVertex3f( Size, -Size,  Size)
         '' Left Face
         glVertex3f(-Size, -Size, -Size)
         glVertex3f(-Size, -Size,  Size)
         glVertex3f(-Size,  Size,  Size)
         glVertex3f(-Size,  Size, -Size)
      glEnd()
   
   glPopMatrix()
   
   glColor4f( 1, 1, 1, 1 )
   
   
end sub


'' Draws the map in 3D
sub DrawMap()

   for y as integer = 0 to (MAP_HEI - 1)
      for x as integer = 0 to (MAP_WID - 1)
         if( Map(x,y) > 0 ) then         
            DrawCube( x * TILE_SIZE, y * TILE_SIZE, 0, TILE_SIZE/2, 0, 1, 0 )
         end if
      next x   
   next y
   
end sub

'' Draws the map in 2D
sub DrawMap2D()

   for y as integer = 0 to (MAP_HEI - 1)
      for x as integer = 0 to (MAP_WID - 1)
         if( Map(x,y) > 0 ) then         
            GL2D_Box( x * TILE_SIZE, y * TILE_SIZE, x * TILE_SIZE + TILE_SIZE, y * TILE_SIZE + TILE_SIZE, GL2D_RGBA(255,0,0, 255) )
         end if
      next x   
   next y
   
end sub



''*****************************************************************************
'' Easy GL2D stuff (needed for printing and debugging)
sub GL2D_VsyncOn()
   
   dim swapinterval as function(byval interval as integer) as integer
   dim extensions as string
   
   '' setup opengl and retrieve supported extensions
   screencontrol FB.GET_GL_EXTENSIONS, extensions
   
   if (instr(extensions, "WGL_EXT_swap_control") <> 0) then
       '' extension supported, retrieve proc address
       swapinterval = ScreenGLProc("wglSwapIntervalEXT")
   else
      swapinterval = ScreenGLProc("glXSwapIntervalSGI")
   end if

    if (swapinterval <> 0) then
        '' ok, we got it. set opengl to wait for vertical sync on buffer swaps
        swapinterval(1)
    end if

end sub


sub GL2D_Begin2D(byval wid as integer, byval hei as integer)
   
    glMatrixMode(GL_PROJECTION)   
    glPushMatrix()
    glLoadIdentity()
    glOrtho(0, wid, hei, 0, -1, 1)
    glMatrixMode(GL_MODELVIEW)
    glPushMatrix()
    glLoadIdentity()
    glTranslatef(0.375, 0.375, 0)   '' magic trick
   
end sub

sub GL2D_End2D() 
   
    glMatrixMode(GL_PROJECTION)
    glPopMatrix()
    glMatrixMode(GL_MODELVIEW)
    glPopMatrix()
   
end sub


function GL2D_Load_Image_24bit_Alpha( byval spr as any ptr, byval filter_mode as GLuint = GL_NEAREST ) as GLuint
   
        dim as GLuint TextureID
         dim as ubyte r, g, b, a
         dim As FB.IMAGE ptr temp = spr
         
         for y as integer = 0 to temp->height-1
          dim as uinteger ptr p = cast(uinteger ptr,(spr + sizeof (FB.IMAGE)) + y * temp->pitch)      
          for x as integer = 0 to temp->width-1
             a = argb_a(p[x])
             r = argb_r(p[x])
             g = argb_g(p[x])
             b = argb_b(p[x])
             '' check for transparency
            if ( g = 0 ) then
               if ( (r = 255) and (b = 255) ) then
                  p[x] = rgba(r,g,b,0)
               endif
            endif
          next x
         next y
         
         
         glEnable( GL_TEXTURE_2D )
        glGenTextures(1, @TextureID)
        glBindTexture(GL_TEXTURE_2D, TextureID)
       
         glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT )
        glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT )
        glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter_mode )
        glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter_mode )
        glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE )
               
        glTexImage2d( GL_TEXTURE_2D, 0, GL_RGBA, temp->width, temp->height,_
                   0, GL_BGRA, GL_UNSIGNED_BYTE, spr + sizeof(FB.IMAGE) )
        glBindTexture(GL_TEXTURE_2D, 0)
       
       
        return TextureID
       
end function


sub GL2D_Font_Init()

   
    dim as any ptr image = imagecreate(128,128,RGBA(255,0,255,0))
   
    for x as integer = 0 to 15
        for y as integer = 0 to 15
           draw string image, (x * 8, y * 8), chr( x + y * 16)
        next
    next

   
   font_textureID = GL2D_Load_Image_24bit_Alpha( image )
   

    imagedestroy( image )


    font_list_base = glGenLists(256)
    dim as single scale = 1/128
    dim as single w = 8 * scale
    dim as single h = 8 * scale

    glPushMatrix()
    glLoadIdentity()
    for font_loop as integer = 0 to 255
      
       dim as single x = (font_loop mod 16) * w
       dim as single y = fix(font_loop / 16) * h
      
       glNewList( font_list_base + font_loop, GL_COMPILE )
       glBegin( GL_QUADS )
               glTexCoord2f( x, y + h)
               glVertex2i( 0, 8 )
              
               glTexCoord2f( x + w, y + h )
               glVertex2i( 8, 8 )
              
               glTexCoord2f( x + w,y )
               glVertex2i( 8, 0 )
              
               glTexCoord2f( x, y )
               glVertex2i( 0, 0 )
       glEnd()
      
       glTranslatef( 8,0,0 )
       glEndList()
      
    next font_loop

   glPopMatrix()
   
end sub

''=============================================================================
''
''    Sets up OpenGL for 2d mode
''
''=============================================================================
sub GL2D_Screen_Init(byval screen_wid as integer, byval screen_hei as integer, byval flags as integer = 0)
   
   if flags then
      screenres screen_wid, screen_hei, 32, 2, FB.GFX_OPENGL or flags
   else
      screenres screen_wid, screen_hei, 32, 2, FB.GFX_OPENGL
   endif
   
   
   'screen information
   dim w as integer, h as integer
   'OpenGL params for gluerspective
   dim FOVy as double            'Field of view angle in Y
   dim Aspect as double          'Aspect of screen
   dim znear as double           'z-near clip distance
   dim zfar as double            'z-far clip distance

   'using screen info w and h as params
   glViewport(0, 0, screen_wid, screen_hei)
   
   'Set current Mode to projection(ie: 3d)
   glMatrixMode(GL_PROJECTION)
   
   'Load identity matrix to projection matrix
   glLoadIdentity()

   'Set gluPerspective params
   FOVy = 90/2                                     '45 deg fovy
   Aspect = screen_wid / screen_hei
   znear = 1                                       'Near clip
   zfar = 1500                                     'far clip
   
   'use glu Perspective to set our 3d frustum dimension up
   gluPerspective(FOVy, aspect, znear, zfar)
   
   'Modelview mode
   'ie. Matrix that does things to anything we draw
   'as in lines, points, tris, etc.
   glMatrixMode(GL_MODELVIEW)
   'load identity(clean) matrix to modelview
   glLoadIdentity()
   
   glShadeModel(GL_SMOOTH)                 'set shading to smooth(try GL_FLAT)
   glClearColor(0.0, 0.0, 0.0, 1.0)        'set Clear color to BLACK
   glClearDepth(1.0)                       'Set Depth buffer to 1(z-Buffer)
   glDisable(GL_DEPTH_TEST)                'Disable Depth Testing so that our z-buffer works
   
   'compare each incoming pixel z value with the z value present in the depth buffer
   'LEQUAL means than pixel is drawn if the incoming z value is less than
   'or equal to the stored z value
   glDepthFunc(GL_LEQUAL)
   
   'have one or more material parameters track the current color
   'Material is your 3d model
   glEnable(GL_COLOR_MATERIAL)


    'Enable Texturing
    glEnable(GL_TEXTURE_2D)
   

      'Tell openGL that we want the best possible perspective transform
   glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST)
   
   'Disable Backface culling
   glDisable (GL_CULL_FACE)
   
   glPolygonMode(GL_FRONT, GL_FILL)
   
   '' enable blending for transparency
   glEnable(GL_BLEND)          
   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
   
   glDisable( GL_DEPTH_TEST )
   
   glEnable( GL_ALPHA_TEST )
   glAlphaFunc(GL_GREATER, 0)


   glDisable(GL_STENCIL_TEST)
   glDisable(GL_TEXTURE_1D)
   glDisable(GL_LIGHTING)
   glDisable(GL_LOGIC_OP)
   glDisable(GL_DITHER)
   glDisable(GL_FOG)

   glHint(GL_POINT_SMOOTH_HINT, GL_FASTEST)
   glHint(GL_LINE_SMOOTH_HINT , GL_FASTEST)

   glPointSize( 1 )
   glLineWidth( 1 )
   
   '' set up the font system
   GL2D_Font_Init()

end sub

sub GL2D_Clear_Screen()
   
   glClear(GL_COLOR_BUFFER_BIT OR GL_DEPTH_BUFFER_BIT)

end sub

sub GL2D_Box( byval x1 as integer, byval y1 as integer, byval x2 as integer, byval y2 as integer, byval gl2dcolor as GLuint )

   glDisable( GL_TEXTURE_2D )
   glColor4ubv( cast( GLubyte ptr, @gl2dcolor ) )
   
   
   glBegin( GL_LINE_STRIP )
      glVertex2i( x1, y1 )
      glVertex2i( x2, y1 )
      glVertex2i( x2, y2 )
      glVertex2i( x1, y2 )
      glVertex2i( x1, y1 )
   glEnd()
   
   
   glEnable( GL_TEXTURE_2D )
   
   glColor4ub(255,255,255,255)
   
end sub


sub GL2D_Box_Filled( byval x1 as integer, byval y1 as integer, byval x2 as integer, byval y2 as integer, byval gl2dcolor as GLuint )

   glDisable( GL_TEXTURE_2D )
   glColor4ubv( cast( GLubyte ptr, @gl2dcolor ) )
   
    x2 += 1
    y2 += 1
   
   glBegin(GL_QUADS)
      
      glVertex2i   (x1,y1)
      glVertex2i   (x1,y2)
      glVertex2i   (x2,y2)
      glVertex2i   (x2,y1)
      
   glEnd()
   
   glEnable( GL_TEXTURE_2D )
   
   glColor4ub(255,255,255,255)
   
end sub


sub GL2D_Print_Scale(byval x as integer, byval y as integer, byval scale as single, byref text as const string)

   
   '' Only change active texture when there is a need
   '' Speeds up the rendering by batching textures
   if ( font_textureID <> current_texture ) then
      glBindTexture(GL_TEXTURE_2D, font_textureID)
      current_texture = font_textureID
   endif
      
    glPushMatrix()
    glLoadIdentity()
    glTranslatef( x, y, 0 )
    glScalef(scale, scale, 1)
    glListBase( font_list_base )
        for i as integer = 0 to len(text) - 1
           glCallList( font_list_base + text[i] )
        next i
    glPopMatrix()

end sub




VANYA
Posts: 1245
Joined: Oct 24, 2010 15:16
Location: Ярославль
Contact:

Re: The easiest way to code a 3d Platformer.

Postby VANYA » Aug 17, 2012 3:29

Super!
Lachie Dazdarian
Posts: 2230
Joined: May 31, 2005 9:59
Location: Croatia
Contact:

Re: The easiest way to code a 3d Platformer.

Postby Lachie Dazdarian » Aug 19, 2012 22:09

Wow! This is awesome! Thanks relsoft.

Would be great if you would take some time to present this in a form of a tutorial. Maybe add some code that enables easier level building. Like a map maker which is like any other 2D map maker (tile graphics is the front box texture), with one more option for each tile, and that is the background color or texture. Some of us are not good even with simple boxes in OpenGL.
relsoft
Posts: 1765
Joined: May 27, 2005 10:34
Location: Philippines
Contact:

Re: The easiest way to code a 3d Platformer.

Postby relsoft » Aug 20, 2012 3:07

I'll try but almost all my free time is taken over by the DS side of coding and working out. ;*(
Lachie Dazdarian
Posts: 2230
Joined: May 31, 2005 9:59
Location: Croatia
Contact:

Re: The easiest way to code a 3d Platformer.

Postby Lachie Dazdarian » Aug 20, 2012 6:54

Maybe if you can only show me how to assign a texture to a specific cube in the engine and front and back/side planes (or just change the color of back/side planes).

I can take care of the map editor then.
relsoft
Posts: 1765
Joined: May 27, 2005 10:34
Location: Philippines
Contact:

Re: The easiest way to code a 3d Platformer.

Postby relsoft » Aug 27, 2012 6:47

Lachie Dazdarian wrote:Maybe if you can only show me how to assign a texture to a specific cube in the engine and front and back/side planes (or just change the color of back/side planes).

I can take care of the map editor then.


Here ya go:

http://rel.phatcode.net/junk.php?id=126

Map is text based so you can edit the level from inside code.
Code is now heavily commented.

Also added:

Code: Select all

1. A way to texture the level using a tileset
2. 3 camera scrolling behaviors
3. Parallax Background
4. Sprites


Images by Marc Russel from gfx-lib fuzed

DS screen:
Image
Lachie Dazdarian
Posts: 2230
Joined: May 31, 2005 9:59
Location: Croatia
Contact:

Re: The easiest way to code a 3d Platformer.

Postby Lachie Dazdarian » Aug 27, 2012 23:43

Thanks a lot relsoft. This is really cool. Hopefully I'll be able to make something out of it.

Now about that GL2D.... :)

EDIT:

BTW, how do you distribute textures onto blocks in this version?
relsoft
Posts: 1765
Joined: May 27, 2005 10:34
Location: Philippines
Contact:

Re: The easiest way to code a 3d Platformer.

Postby relsoft » Aug 28, 2012 2:32

Lachie Dazdarian wrote:Thanks a lot relsoft. This is really cool. Hopefully I'll be able to make something out of it.

Now about that GL2D.... :)

EDIT:

BTW, how do you distribute textures onto blocks in this version?


With the functions I ripped from Easy GL2D of course.

see:
Inittextures()
DrawMap()
ConvertMap()
VANYA
Posts: 1245
Joined: Oct 24, 2010 15:16
Location: Ярославль
Contact:

Re: The easiest way to code a 3d Platformer.

Postby VANYA » Aug 28, 2012 2:43

Thank you. A great project!
relsoft
Posts: 1765
Joined: May 27, 2005 10:34
Location: Philippines
Contact:

Re: The easiest way to code a 3d Platformer.

Postby relsoft » Aug 28, 2012 3:00

VANYA wrote:Thank you. A great project!


Thanks!
This can be anyone's project actually. I just shared it to the FB community.

Return to “Tips and Tricks”

Who is online

Users browsing this forum: No registered users and 1 guest