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
DS screen:
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