390 lines
11 KiB
Text
390 lines
11 KiB
Text
|
' Gambas module file
|
||
|
|
||
|
'tutorial based on tutorial from NeHe Productions site at http://nehe.gamedev.net/
|
||
|
'visit the page for more info on OpenGL
|
||
|
'
|
||
|
'This tutorial shows how to build 3D world using textured block and defining the building in world.txt file
|
||
|
'To get continuous movement we use timer() and keypress() - keyrelease() functions.
|
||
|
'No collision implemented yet.
|
||
|
|
||
|
' Gambas module file
|
||
|
Const world_x_size As Integer = 16
|
||
|
Const world_y_size As Integer = 16
|
||
|
Const piover180 As Float = 0.0174532925
|
||
|
Private screen As New Window(True) As "Screen"
|
||
|
Private xrot As Float 'X Rotation( NEW )
|
||
|
Private yrot As Float 'Y Rotation( NEW )
|
||
|
Private xspeed As Float 'x rotation speed
|
||
|
Private yspeed As Float 'y rotation speed
|
||
|
' [GB2:ARRD] Private texture As Integer[3] 'storage FOR one texture
|
||
|
Private texture As New Integer[3] 'storage FOR one texture
|
||
|
Private LightAmbient As Float[]
|
||
|
Private LightDiffuse As Float[]
|
||
|
Private LightPosition As Float[]
|
||
|
Private filter As Integer = 0
|
||
|
Private light As Integer = 0
|
||
|
Private blend As Integer = 0
|
||
|
Private walkbias As Float = 0.0
|
||
|
Private walkbiasangle As Float = 0.0
|
||
|
Private lookupdown As Float = 0.0
|
||
|
Private heading As Float
|
||
|
Private xpos As Float
|
||
|
Private zpos As Float
|
||
|
Private mypos_x As Float = 0
|
||
|
Private mypos_z As Float = 20
|
||
|
Private camx As Float = 0.0
|
||
|
Private camy As Float = 0.0
|
||
|
Private camz As Float = 0.0
|
||
|
Private therotate As Float
|
||
|
Private z As Float = - world_x_size - 20.0 'depth into the screen.
|
||
|
Private lp As Integer = 0
|
||
|
Private objlists As Integer
|
||
|
' [GB2:ARRD] Private world As Integer[world_x_size, world_y_size] 'world size 8x8 cube places
|
||
|
Private world As New Integer[world_x_size, world_y_size] 'world size 8x8 cube places
|
||
|
Private up_pressed As Boolean
|
||
|
Private down_pressed As Boolean
|
||
|
Private left_pressed As Boolean
|
||
|
Private right_pressed As Boolean
|
||
|
Private hTimer As New Timer As "Timer1"
|
||
|
Private CTime As Float
|
||
|
|
||
|
Public Sub Main()
|
||
|
|
||
|
Dim i, j As Integer
|
||
|
|
||
|
For i = 0 To world_x_size - 1
|
||
|
For j = 0 To world_y_size - 1
|
||
|
world[i, j] = 0
|
||
|
Next
|
||
|
Next
|
||
|
|
||
|
With screen
|
||
|
.Width = 800
|
||
|
.Height = 600
|
||
|
.Title = MMain.Title
|
||
|
.Show()
|
||
|
End With
|
||
|
|
||
|
CTime = Timer()
|
||
|
hTimer.Delay = 100
|
||
|
hTimer.Enabled = True
|
||
|
|
||
|
End
|
||
|
|
||
|
Public Sub Screen_Open()
|
||
|
|
||
|
LightAmbient = [0.5, 0.5, 0.5, 1.0]
|
||
|
LightDiffuse = [1.0, 1.0, 1.0, 1.0]
|
||
|
LightPosition = [0.0, 0.0, 2.0, 1.0]
|
||
|
|
||
|
Gl.ClearDepth(100.0) 'Enables Clearing Of The Depth Buffer
|
||
|
gl.ClearColor(0.0, 0.0, 0.0, 0.0) 'This Will Clear The Background Color To Black
|
||
|
gl.DepthFunc(gl.LESS) 'The Type Of Depth Test To Do
|
||
|
gl.Enable(gl.DEPTH_TEST) 'Enables Depth Testing
|
||
|
gl.ShadeModel(gl.SMOOTH) 'Enables Smooth Color Shading
|
||
|
init()
|
||
|
|
||
|
End
|
||
|
|
||
|
Public Sub Screen_resize()
|
||
|
|
||
|
Gl.Viewport(0, 0, Screen.Width, Screen.Height)
|
||
|
|
||
|
Gl.MatrixMode(Gl.PROJECTION)
|
||
|
Gl.LoadIdentity() 'Reset The Projection Matrix
|
||
|
glu.Perspective(45.0, screen.Width / screen.Height, 0.1, 100.0) 'Calculate The Aspect Ratio Of The Window
|
||
|
Gl.MatrixMode(Gl.MODELVIEW)
|
||
|
|
||
|
End
|
||
|
|
||
|
Public Sub load_world()
|
||
|
|
||
|
Dim world_file As File
|
||
|
Dim brick As String
|
||
|
Dim wall As String
|
||
|
Dim i, j, k As Integer
|
||
|
|
||
|
world_file = Open "world.txt" For Read
|
||
|
For i = 0 To world_x_size - 2
|
||
|
Read #world_file, wall, world_x_size + 1
|
||
|
For j = 1 To world_y_size
|
||
|
brick = Mid$(wall, j, 1)
|
||
|
If brick = "#" Then world[i, j - 1] = 1
|
||
|
Next
|
||
|
Next
|
||
|
Read #world_file, wall, world_x_size
|
||
|
For j = 1 To world_y_size
|
||
|
brick = Mid$(wall, j, 1)
|
||
|
If brick = "#" Then world[world_x_size - 1, j - 1] = 1
|
||
|
Next
|
||
|
world_file.Close
|
||
|
|
||
|
End
|
||
|
|
||
|
Public Sub load_texture()
|
||
|
|
||
|
Dim wall As Image
|
||
|
Dim floor1 As Image
|
||
|
Dim ceiling As Image
|
||
|
Dim egs As Boolean
|
||
|
|
||
|
gl.Enable(gl.TEXTURE_2D) ' Enable Texture Mapping
|
||
|
texture = Gl.GenTextures(3)
|
||
|
wall = Image.Load("wall.jpeg")
|
||
|
Gl.BindTexture(Gl.TEXTURE_2D, texture[0])
|
||
|
Gl.TexImage2D(wall)
|
||
|
Glu.Build2DMipmaps(wall)
|
||
|
|
||
|
floor1 = Image.Load("floor.png")
|
||
|
Gl.BindTexture(Gl.TEXTURE_2D, texture[1])
|
||
|
Gl.TexImage2D(Floor1)
|
||
|
Glu.Build2DMipmaps(Floor1)
|
||
|
|
||
|
ceiling = Image.Load("ceiling.png")
|
||
|
Gl.BindTexture(Gl.TEXTURE_2D, texture[2])
|
||
|
Gl.TexImage2D(ceiling)
|
||
|
Glu.Build2DMipmaps(ceiling)
|
||
|
|
||
|
Gl.TexParameteri(Gl.TEXTURE_2D, Gl.TEXTURE_MIN_FILTER, Gl.LINEAR_MIPMAP_NEAREST)
|
||
|
Gl.TexParameteri(Gl.TEXTURE_2D, Gl.TEXTURE_MAG_FILTER, Gl.LINEAR)
|
||
|
|
||
|
End
|
||
|
|
||
|
Public Sub init()
|
||
|
|
||
|
load_world()
|
||
|
load_texture()
|
||
|
gl.Enable(gl.TEXTURE_2D) ' Enable Texture Mapping( NEW )
|
||
|
gl.ShadeModel(gl.SMOOTH) ' Enable Smooth Shading
|
||
|
gl.ClearColor(0.0, 0.0, 0.0, 0.0) ' Black Background
|
||
|
gl.ClearDepth(2.0) ' Depth Buffer Setup
|
||
|
gl.Enable(gl.DEPTH_TEST) ' Enables Depth Testing
|
||
|
gl.DepthFunc(gl.LESS) ' The Type OF Depth Testing TO DO
|
||
|
gl.MatrixMode(gl.PROJECTION)
|
||
|
gl.LoadIdentity() 'Reset The Projection Matrix
|
||
|
glu.Perspective(45.0, screen.Width / screen.Height, 0.1, 100.0) 'Calculate The Aspect Ratio Of The Window
|
||
|
gl.MatrixMode(gl.MODELVIEW)
|
||
|
gl.Lightfv(gl.LIGHT1, gl.AMBIENT, LightAmbient) ' add lighting.(ambient)
|
||
|
gl.Lightfv(gl.LIGHT1, gl.DIFFUSE, LightDiffuse) ' add lighting.(diffuse).
|
||
|
gl.Lightfv(gl.LIGHT1, gl.POSITION, LightPosition) ' set light position.
|
||
|
gl.Enable(gl.LIGHT1)
|
||
|
objlists = Gl.GenLists(3)
|
||
|
|
||
|
Gl.NewList(objlists, Gl.COMPILE)
|
||
|
|
||
|
gl.BindTexture(gl.TEXTURE_2D, texture[0]) ' SELECT Our Texture
|
||
|
Gl.Begin(Gl.QUADS)
|
||
|
gl.Normal3f(0.0, 0.0, 1.0) 'front face
|
||
|
Gl.TexCoordf(0.0, 1.0)
|
||
|
Gl.Vertexf(-1.0, 0.0, 1.0)
|
||
|
Gl.TexCoordf(1.0, 1.0)
|
||
|
Gl.Vertexf(1.0, 0.0, 1.0)
|
||
|
Gl.TexCoordf(1.0, 0.0)
|
||
|
Gl.Vertexf(1.0, 4.0, 1.0)
|
||
|
Gl.TexCoordf(0.0, 0.0)
|
||
|
Gl.Vertexf(-1.0, 4.0, 1.0)
|
||
|
gl.Normal3f(0.0, 0.0, -1.0) 'back face
|
||
|
Gl.TexCoordf(1.0, 1.0)
|
||
|
Gl.Vertexf(-1.0, 0.0, -1.0)
|
||
|
Gl.TexCoordf(1.0, 0.0)
|
||
|
Gl.Vertexf(-1.0, 4.0, -1.0)
|
||
|
Gl.TexCoordf(0.0, 0.0)
|
||
|
Gl.Vertexf(1.0, 4.0, -1.0)
|
||
|
Gl.TexCoordf(0.0, 1.0)
|
||
|
Gl.Vertexf(1.0, 0.0, -1.0)
|
||
|
gl.Normal3f(0.0, 1.0, 0.0) ' top face - no need for texture
|
||
|
Gl.Vertexf(-1.0, 4.0, -1.0)
|
||
|
Gl.Vertexf(-1.0, 4.0, 1.0)
|
||
|
Gl.Vertexf(1.0, 4.0, 1.0)
|
||
|
Gl.Vertexf(1.0, 4.0, -1.0)
|
||
|
gl.Normal3f(0.0, 0.0, 0.0) 'bottom face - no textutre
|
||
|
Gl.Vertexf(-1.0, 0.0, -1.0)
|
||
|
Gl.Vertexf(1.0, 0.0, -1.0)
|
||
|
Gl.Vertexf(1.0, 0.0, 1.0)
|
||
|
Gl.Vertexf(-1.0, 0.0, 1.0)
|
||
|
gl.Normal3f(1.0, 0.0, 0.0) 'right face
|
||
|
Gl.TexCoordf(1.0, 1.0)
|
||
|
Gl.Vertexf(1.0, 0.0, -1.0)
|
||
|
Gl.TexCoordf(1.0, 0.0)
|
||
|
Gl.Vertexf(1.0, 4.0, -1.0)
|
||
|
Gl.TexCoordf(0.0, 0.0)
|
||
|
Gl.Vertexf(1.0, 4.0, 1.0)
|
||
|
Gl.TexCoordf(0.0, 1.0)
|
||
|
Gl.Vertexf(1.0, 0.0, 1.0)
|
||
|
gl.Normal3f(-1.0, 0.0, 0.0) 'left face
|
||
|
Gl.TexCoordf(0.0, 1.0)
|
||
|
Gl.Vertexf(-1.0, 0.0, -1.0)
|
||
|
Gl.TexCoordf(1.0, 1.0)
|
||
|
Gl.Vertexf(-1.0, 0.0, 1.0)
|
||
|
Gl.TexCoordf(1.0, 0.0)
|
||
|
Gl.Vertexf(-1.0, 4.0, 1.0)
|
||
|
Gl.TexCoordf(0.0, 0.0)
|
||
|
Gl.Vertexf(-1.0, 4.0, -1.0)
|
||
|
Gl.End()
|
||
|
|
||
|
gl.EndList()
|
||
|
|
||
|
Gl.NewList(objlists + 1, Gl.COMPILE)
|
||
|
|
||
|
gl.BindTexture(gl.TEXTURE_2D, texture[1]) ' SELECT Our Texture
|
||
|
gl.Begin(gl.QUADS)
|
||
|
Gl.TexCoordf(0.0, 1.0)
|
||
|
gl.Vertex3f(-1, 0, world_y_size * 2 - 1)
|
||
|
Gl.TexCoordf(1.0, 1.0)
|
||
|
gl.Vertex3f(world_x_size * 2 - 1, 0, world_y_size * 2 - 1)
|
||
|
Gl.TexCoordf(1.0, 0.0)
|
||
|
gl.Vertex3f(world_x_size * 2 - 1, 0, 1)
|
||
|
Gl.TexCoordf(0.0, 0.0)
|
||
|
gl.Vertex3f(-1, 0, 1)
|
||
|
gl.End()
|
||
|
|
||
|
Gl.EndList()
|
||
|
|
||
|
Gl.NewList(objlists + 2, Gl.COMPILE)
|
||
|
|
||
|
gl.BindTexture(gl.TEXTURE_2D, texture[2]) ' SELECT Our Texture
|
||
|
gl.Begin(gl.QUADS)
|
||
|
Gl.TexCoordf(0.0, 0.0)
|
||
|
gl.Vertex3f(-1, 4, 1)
|
||
|
Gl.TexCoordf(0.0, 1.0)
|
||
|
gl.Vertex3f(world_x_size * 2 - 1, 4, 1)
|
||
|
Gl.TexCoordf(1.0, 1.0)
|
||
|
gl.Vertex3f(world_x_size * 2 - 1, 4, world_y_size * 2 - 1)
|
||
|
Gl.TexCoordf(1.0, 0.0)
|
||
|
gl.Vertex3f(-1, 4, world_y_size * 2 - 1)
|
||
|
gl.End()
|
||
|
|
||
|
Gl.EndList()
|
||
|
|
||
|
End
|
||
|
|
||
|
Public Sub Screen_draw()
|
||
|
|
||
|
Dim i, j, k As Integer
|
||
|
Dim x_m, y_m, z_m, u_m, v_m As Float
|
||
|
Dim xtrans, ztrans, ytrans As Float
|
||
|
Dim sceneroty As Float
|
||
|
|
||
|
xtrans = - xpos
|
||
|
ztrans = - zpos
|
||
|
ytrans = - walkbias - 0.25
|
||
|
sceneroty = 360.0 - yrot
|
||
|
|
||
|
gl.LoadIdentity()
|
||
|
gl.Clear(gl.COLOR_BUFFER_BIT Or gl.DEPTH_BUFFER_BIT) ' Clear Screen AND Depth Buffer
|
||
|
|
||
|
For i = 0 To world_x_size - 1
|
||
|
For j = 0 To world_y_size - 1
|
||
|
k = 0
|
||
|
k = world[i, j]
|
||
|
gl.LoadIdentity()
|
||
|
gl.Rotatef(camy, 0, 1, 0)
|
||
|
gl.Rotatef(camz, 1, 0, 0)
|
||
|
gl.Rotatef(lookupdown, 1.0, 0, 0)
|
||
|
gl.Rotatef(sceneroty, 0, 1.0, 0)
|
||
|
gl.Translatef(xtrans, ytrans, z + ztrans)
|
||
|
|
||
|
gl.Translatef(j * 2, -2.5, i * 2)
|
||
|
If k = 1 Then Gl.CallList(objlists)
|
||
|
Next
|
||
|
Next
|
||
|
|
||
|
gl.LoadIdentity()
|
||
|
gl.Rotatef(camy, 0, 1, 0)
|
||
|
gl.Rotatef(camz, 1, 0, 0)
|
||
|
gl.Rotatef(lookupdown, 1.0, 0, 0)
|
||
|
gl.Rotatef(sceneroty, 0, 1.0, 0)
|
||
|
gl.Translatef(xtrans, ytrans - 2.5, z + ztrans)
|
||
|
gl.CallList(objlists + 1)
|
||
|
|
||
|
gl.LoadIdentity()
|
||
|
gl.Rotatef(camy, 0, 1, 0)
|
||
|
gl.Rotatef(camz, 1, 0, 0)
|
||
|
gl.Rotatef(lookupdown, 1.0, 0, 0)
|
||
|
gl.Rotatef(sceneroty, 0, 1.0, 0)
|
||
|
|
||
|
gl.Translatef(xtrans, ytrans - 2.5, z + ztrans)
|
||
|
gl.CallList(objlists + 2)
|
||
|
|
||
|
End
|
||
|
|
||
|
Public Sub screen_KeyRelease()
|
||
|
|
||
|
up_pressed = False
|
||
|
down_pressed = False
|
||
|
left_pressed = False
|
||
|
right_pressed = False
|
||
|
|
||
|
End
|
||
|
|
||
|
Public Sub Screen_keyPress()
|
||
|
|
||
|
If (key.code = key.F1) Then screen.Fullscreen = Not screen.Fullscreen
|
||
|
If (key.Code = key.Esc) Then Screen.Close()
|
||
|
If (key.text = "l" Or key.Text = "L") Then
|
||
|
If lp = 0 Then gl.Enable(gl.LIGHTing)
|
||
|
If lp = 1 Then gl.Disable(gl.LIGHTing)
|
||
|
lp = 1 - lp
|
||
|
Endif
|
||
|
If (key.code = key.PageUp) Then
|
||
|
z -= 0.2
|
||
|
mypos_z = +0.2
|
||
|
lookupdown -= 0.2
|
||
|
Endif
|
||
|
|
||
|
If (key.code = key.Pagedown) Then
|
||
|
z += 0.2
|
||
|
mypos_z -= 0.2
|
||
|
lookupdown += 1.0
|
||
|
Endif
|
||
|
If (key.code = key.UP) Then up_pressed = True
|
||
|
If (key.code = key.DOWN) Then down_pressed = True
|
||
|
If (key.code = key.LEFT) Then left_pressed = True
|
||
|
If (key.code = key.RIGHT) Then right_pressed = True
|
||
|
|
||
|
End
|
||
|
|
||
|
Public Sub Timer1_Timer()
|
||
|
|
||
|
If up_pressed = True Then
|
||
|
'IF (world[Round(mypos_x + 0.2), Round(mypos_z + 0.2)] = 0) THEN
|
||
|
xpos -= Sin(yrot * piover180) '* 0.5
|
||
|
'mypos_x += Sin(yrot * piover180) * 0.5
|
||
|
zpos -= Cos(yrot * piover180) '* 0.5
|
||
|
'mypos_z += Cos(yrot * piover180) * 0.5
|
||
|
If (walkbiasangle >= 359.0) Then
|
||
|
walkbiasangle = 0.0
|
||
|
Else
|
||
|
walkbiasangle += 10
|
||
|
Endif
|
||
|
walkbias = Sin(walkbiasangle * piover180) / 20.0
|
||
|
'ENDIF
|
||
|
Endif
|
||
|
|
||
|
If down_pressed = True Then
|
||
|
'IF (world[Round(mypos_x + 0.2), Round(mypos_z + 0.2)] = 0) THEN
|
||
|
xpos += Sin(yrot * piover180) '* 0.5
|
||
|
' mypos_x -= Sin(yrot * piover180) * 0.5
|
||
|
zpos += Cos(yrot * piover180) '* 0.5
|
||
|
'mypos_z -= Cos(yrot * piover180) * 0.5
|
||
|
If (walkbiasangle <= 1.0) Then
|
||
|
walkbiasangle = 359.0
|
||
|
Else
|
||
|
walkbiasangle -= 10
|
||
|
Endif
|
||
|
walkbias = Sin(walkbiasangle * piover180) / 20.0
|
||
|
'ENDIF
|
||
|
Endif
|
||
|
|
||
|
If left_pressed = True Then yrot += 3.5
|
||
|
If right_pressed = True Then yrot -= 3.5
|
||
|
|
||
|
End
|
||
|
|
||
|
'PUBLIC SUB Screen_MouseMove()
|
||
|
|
||
|
'camy += Mouse.Relativex
|
||
|
'camz += Mouse.RelativeY
|
||
|
|
||
|
' END
|