'3D World Game Engine v1.0
'by Ashish
'below element can be use to store data for any application. (additional data)
'objects
'dimension
'player starting position
'player destination position
'global directional light settings
light_amb
As vec3
'ambient color light_diff
As vec3
'diffuse color light_spec
As vec3
'specular color light_dir
As vec3
'direction of light
'For doors :-
'* d_2 specify the state of the door. 0=closed, 1=opening, 2=opened
'* d_1 specify which side of it is fixed. So, the door rotates from that side when being
' opened by the user. ±1=left ±2=right ±3=up ±4=down where sign (±) describe the direction of rotation when being open
'* d_3 specify the ID of the key from which it can be unlock and open
'* d_4 specify the angle of rotation when it is being open.
'For keys :-
'* d_1 specify its ID. Each key have a unique ID.
'* d_2 specify whether it has taken by the user or not. If taken, disable rendering of it.
'For traps :-
'* Type 1 [laser]
' * d_4 is used as clock variable in timer
' * d_2 is frequecncy of on/off of laser for every 4 seconds.
'Global Variables
ReDim Shared wallMap
(0) As map_element
, floorMap
(0) As map_element
, ceilingMap
(0) As map_element
ReDim Shared doorMap
(0) As map_element
, keyMap
(0) As map_element
, pointMap
(0) As map_element
Dim Shared worldTextures
(7, 15) As game_texture_type
'8 objects, each coming in maximum of 16 varities
Dim Shared game_state
, worldRotX
, worldRotY
, playerPos
As vec3
, playerFarPoint
ReDim Shared collisionMap
(0, 0, 1) As _Byte '2 layers, one for collision and second one for interaction with objects
'Local Variables
' dim preMouseX
_Title "3D World Game Engine v1.0" echo "3D World Game Engine v1.0"
echo "Preparing..."
'LOAD stuffs
loadResource
' for i = 0 to 15
' _putimage (0,0),worldTextures(0,i).img_handle
' sleep
' next
' worldTextures(0, 0).img_handle = _LOADIMAGE("Textures/wall/wall_1.jpg")
' worldTextures(1, 0).img_handle = _LOADIMAGE("Textures/floor/floor_1.jpg")
' worldTextures(2, 0).img_handle = _LOADIMAGE("Textures/ceiling/ceil_2.jpg")
' worldTextures(3, 0).img_handle = _LOADIMAGE("Textures/door/door_1.jpg")
' loadWorld "among_us_world.3dm"
playerPos.x = worldStats.px
playerPos.y = 0
playerPos.z = worldStats.py
playerFarPoint = 0.5
game_state = 1
worldRotX
= map
(_MouseY, 0, 600, 60, -60)
' if _MOUSEX >= _WIDTH - 1 then _mousemove 0,_mousey : preMouseX = 0
worldRotY
= worldRotY
+ (_MOUSEX - preMouseX
) ' worldRotY = _D2R(_MouseX)
check_key_input:
__x1
= near_int
(playerPos.x
+ 0.5 * Sin(_D2R(worldRotY
))) __y1
= near_int
(playerPos.z
- 0.5 * Cos(_D2R(worldRotY
))) ' If collisionMap(__x1, __y1, 1) = 1 Then echo "Ouch!!"
If collisionMap
(__x1
, __y1
, 0) = 0 Then playerPos.x
= playerPos.x
+ 0.08 * Sin(_D2R(worldRotY
)) playerPos.z
= playerPos.z
- 0.08 * Cos(_D2R(worldRotY
)) __x1
= near_int
(playerPos.x
- 0.5 * Sin(_D2R(worldRotY
))) __y1
= near_int
(playerPos.z
+ 0.5 * Cos(_D2R(worldRotY
))) ' If collisionMap(__x1, __y1, 1) = 1 Then echo "Ouch!!"
If collisionMap
(__x1
, __y1
, 0) = 0 Then playerPos.x
= playerPos.x
- 0.08 * Sin(_D2R(worldRotY
)) playerPos.z
= playerPos.z
+ 0.08 * Cos(_D2R(worldRotY
)) __x1
= near_int
(playerPos.x
- 0.5 * Sin(_D2R(worldRotY
+ 90))) __y1
= near_int
(playerPos.z
+ 0.5 * Cos(_D2R(worldRotY
+ 90))) ' If collisionMap(__x1, __y1, 1) = 1 Then echo "Ouch!!"
If collisionMap
(__x1
, __y1
, 0) = 0 Then playerPos.x
= playerPos.x
- 0.08 * Sin(_D2R(worldRotY
+ 90)) playerPos.z
= playerPos.z
+ 0.08 * Cos(_D2R(worldRotY
+ 90)) __x1
= near_int
(playerPos.x
+ 0.5 * Sin(_D2R(worldRotY
+ 90))) __y1
= near_int
(playerPos.z
- 0.5 * Cos(_D2R(worldRotY
+ 90))) ' If colslisionMap(__x1, __y1, 1) = 1 Then echo "Ouch!!" <--- temporarily commented
If collisionMap
(__x1
, __y1
, 0) = 0 Then playerPos.x
= playerPos.x
+ 0.08 * Sin(_D2R(worldRotY
+ 90)) playerPos.z
= playerPos.z
- 0.08 * Cos(_D2R(worldRotY
+ 90)) 'animation stuffs (khaaskar traps ke liye)
If worldStats.num_of_trap
> 0 Then For i
= 1 To worldStats.num_of_trap
If trapMap
(i
).typ
= 1 Then 'laser If (Timer - trapMap
(i
).d_4
) > (4 / trapMap
(i
).d_2
) Then trapMap(i).d_3 = 0
collisionMap(trapMap(i).x, trapMap(i).y, 1) = 0 'no damage
trapMap(i).d_3 = 1
collisionMap(trapMap(i).x, trapMap(i).y, 1) = 1 'damage
'interaction with objects
__x1 = near_int(playerPos.x): __y1 = near_int(playerPos.z)
__x2
= near_int
(playerPos.x
+ 0.5 * Sin(_D2R(worldRotY
))): __y2
= near_int
(playerPos.z
- 0.5 * Cos(_D2R(worldRotY
))) 'interaction with key
If collisionMap
(__x1
, __y1
, 1) = 3 Then 'find by which key user have interacted?
For i
= 1 To worldStats.num_of_key
If keyMap
(i
).x
= __x1
And keyMap
(i
).y
= __y1
Then keyMap(i).d_2 = 1 'disable rendering of the key as it is now taken by the user.
'interaction with door
If collisionMap
(__x2
, __y2
, 1) = 2 Then 'finding by which door user have interacted
doorFound = 0
For i
= 1 To worldStats.num_of_door
If doorMap
(i
).x
= __x2
And doorMap
(i
).y
= __y2
Then doorIndex = i
doorFound = 1
echo
"door is found at index : " + Str$(doorIndex
) 'checking if user has the key for this door
For i
= 1 To worldStats.num_of_key
If doorMap
(doorIndex
).d_3
= keyMap
(i
).d_1
Then 'okay, so the user do have the key for this door and the door is not yet opened.
'now, I change the state of this door from "closed" to "opening"
doorMap(doorIndex).d_2 = 1
echo "state of door is now changed."
echo "You don't have key for this door... Try it find it somewhere"
' for i = 1 to worldStats.num_of_wall
' pset (wallMap(i).x,wallMap(i).y)
' next
' for i = 1 to worldStats.num_of_floor
' pset (floorMap(i).x, floorMap(i).y), _RGB(255,0,0)
' next
' If tex_load_type > 4 Then
' For i = 0 To UBound(playerTextures)
' playerTextures(i).gl_handle = feedGLTexture(playerTextures(i).img_handle)
' _FreeImage playerTextures(i).img_handle
' Next
' game_state = game_state + 1
' initPlayerObject
' Exit Sub
' End If
If worldTextures
(tex_load_type
, i
).img_handle
< -1 Then worldTextures(tex_load_type, i).gl_handle = feedGLTexture(worldTextures(tex_load_type, i).img_handle)
_FreeImage worldTextures
(tex_load_type
, i
).img_handle
tex_load_type = tex_load_type + 1
if tex_load_type
>4 then game_state
= game_state
+ 1
If game_state
= 2 Then 'world rendering
'Global Light Settings of World
_glLightfv _GL_LIGHT0
, _GL_AMBIENT
, glVec4
(worldStats.light_amb.x
, worldStats.light_amb.y
, worldStats.light_amb.z
, 1) _glLightfv _GL_LIGHT0
, _GL_DIFFUSE
, glVec4
(worldStats.light_diff.x
, worldStats.light_diff.y
, worldStats.light_diff.z
, 1) _glLightfv _GL_LIGHT0
, _GL_SPECULAR
, glVec4
(worldStats.light_spec.x
, worldStats.light_spec.y
, worldStats.light_spec.z
, 1) _glLightfv _GL_LIGHT0
, _GL_POSITION
, glVec4
(worldStats.light_dir.x
, worldStats.light_dir.y
, worldStats.light_dir.z
, 1)
'_glTranslatef playerPos.x, 1, playerPos.z
' _glRotatef worldRotX, 1, 0, 0
' _glRotatef worldRotY+180, 0, 1, 0
gluLookAt playerPos.x , playerPos.y + 0.4, playerPos.z,_
playerPos.x
+ playerFarPoint
* Cos(_D2R(worldRotY
-90)), playerPos.y
+0.4*sin(_d2r(worldRotX
)) , playerPos.z
+ playerFarPoint
* Sin(_D2R(worldRotY
-90)),_
0, 1, 0
drawWalls
drawDoors
drawFloors
drawCeilings
drawKeys
drawBonusObj
drawTraps
n = 15
echo "------------In SUB loadResource()------------------"
echo "extracting map and textures"
extract_file_all "world_data.cdf", "./"
extract_file_all "wall.cdf", "./"
'wall textures
' worldTextures(0, i).img_handle = _LoadImage("Textures/wall/wall_" + _Trim$(Str$(i + 1)) + ".png")
echo "wall... DONE"
'floor textures
extract_file_all "floor.cdf", "./"
' worldTextures(1, i).img_handle = _LoadImage("Textures/floor/floor_" + _Trim$(Str$(i + 1)) + ".jpg")
echo "floor... DONE"
'ceiling textures
extract_file_all "ceil.cdf","./"
n = 2
' worldTextures(2, i).img_handle = _LoadImage("Textures/ceiling/ceil_" + _Trim$(Str$(i + 1)) + ".jpg")
echo "ceiling... DONE"
'door textures
extract_file_all "door.cdf", "./"
n = 6
' worldTextures(3, i).img_handle = _LoadImage("Textures/door/door_" + _Trim$(Str$(i + 1)) + ".jpg")
echo "door... DONE"
'key textures
extract_file_all "key.cdf", "./"
n = 7
' worldTextures(4, k).img_handle = _LoadImage("Textures/key/key_" + _Trim$(Str$(i + 1)) + "_" + _Trim$(Str$(j)) + ".png")
k = k + 1
echo "key... DONE"
echo ""
echo "Loading Map"
loadWorld "test.3dm"
For i
= 1 To worldStats.num_of_wall
selectTexture worldTextures(0, wallMap(i).typ - 1).gl_handle
' drawBox wallMap(i).x, 0, wallMap(i).y, 1, 2, 1
drawXYPlane wallMap(i).x, 0, wallMap(i).y - 0.5, 1, 2, -1 'front face
drawXYPlane wallMap(i).x, 0, wallMap(i).y + 0.5, 1, 2, 1 'back face
drawYZPlane wallMap(i).x - 0.5, 0, wallMap(i).y, 2, 1, -1 'left face
drawYZPlane wallMap(i).x + 0.5, 0, wallMap(i).y, 2, 1, 1 'right face
_glMaterialfv _GL_FRONT_AND_BACK
, _GL_SHININESS
, glVec4
(0.5 * 128, 0, 0, 0) For i
= 1 To worldStats.num_of_floor
selectTexture worldTextures(1, floorMap(i).typ - 1).gl_handle
drawXZPlane floorMap(i).x, -1, floorMap(i).y, 1, 1, 1
For i
= 1 To worldStats.num_of_ceiling
selectTexture worldTextures(2, ceilingMap(i).typ - 1).gl_handle
drawXZPlane ceilingMap(i).x, 1, ceilingMap(i).y, 1, 1, -1
'±1,±2,±3,,
For i
= 1 To worldStats.num_of_door
selectTexture worldTextures(3, doorMap(i).typ - 1).gl_handle
If doorMap
(i
).d_2
= 0 Then 'closed? 'it must be slim in XY depth
drawXYPlane doorMap(i).x, 0, doorMap(i).y - 0.1, 1, 2, -1 'front face
drawXYPlane doorMap(i).x, 0, doorMap(i).y + 0.1, 1, 2, 1 'back face
drawYZPlane doorMap(i).x - 0.5, 0, doorMap(i).y, 2, 0.2, -1 'left face
drawYZPlane doorMap(i).x + 0.5, 0, doorMap(i).y, 2, 0.2, 1 'right face
drawXYPlane doorMap(i).x, 0, doorMap(i).y - 0.5, 0.2, 2, -1 'front face
drawXYPlane doorMap(i).x, 0, doorMap(i).y + 0.5, 0.2, 2, 1 'back face
'it must be slim in YZ along X
drawYZPlane doorMap(i).x - 0.1, 0, doorMap(i).y, 2, 1, -1 'left face
drawYZPlane doorMap(i).x + 0.1, 0, doorMap(i).y, 2, 1, 1 'right face
If doorMap
(i
).d_4
= 90 * s
Then collisionMap
(doorMap
(i
).x
, doorMap
(i
).y
, 0) = 0 Else doorMap
(i
).d_4
= doorMap
(i
).d_4
+ 2 * s
drawXYPlane 0.5, 0, -0.1, 1, 2, -1 'front face
drawXYPlane 0.5, 0, 0.1, 1, 2, 1 'back face
drawYZPlane 0, 0, 0, 2, 0.2, -1 'left face
drawYZPlane 1, 0, 0, 2, 0.2, 1 'right face
If doorMap
(i
).d_4
= 90 * s
Then collisionMap
(doorMap
(i
).x
, doorMap
(i
).y
, 0) = 0 Else doorMap
(i
).d_4
= doorMap
(i
).d_4
+ 2 * s
drawXYPlane -0.5, 0, -0.1, 1, 2, -1 'front face
drawXYPlane -0.5, 0, 0.1, 1, 2, 1 'back face
drawYZPlane -1, 0, 0, 2, 0.2, -1 'left face
drawYZPlane 0, 0, 0, 2, 0.2, 1 'right face
If doorMap
(i
).d_4
= 90 * s
Then collisionMap
(doorMap
(i
).x
, doorMap
(i
).y
, 0) = 0 Else doorMap
(i
).d_4
= doorMap
(i
).d_4
+ 2 * s
drawXYPlane 0, 0, 0, 0.2, 2, -1 'front face
drawXYPlane 0, 0, 1, 0.2, 2, 1 'back face
drawYZPlane -0.1, 0, 0.5, 2, 1, -1 'left face
drawYZPlane 0.1, 0, 0.5, 2, 1, 1 'right face
If doorMap
(i
).d_4
= 90 * s
Then collisionMap
(doorMap
(i
).x
, doorMap
(i
).y
, 0) = 0 Else doorMap
(i
).d_4
= doorMap
(i
).d_4
+ 2 * s
drawXYPlane 0, 0, -1, 0.2, 2, -1 'front face
drawXYPlane 0, 0, 0, 0.2, 2, 1 'back face
drawYZPlane -0.1, 0, -0.5, 2, 1, -1 'left face
drawYZPlane 0.1, 0, -0.5, 2, 1, 1 'right face
keyRotY = keyRotY + 1
For i
= 1 To worldStats.num_of_key
If keyMap
(i
).d_2
= 0 Then 'd_2 store whether it has been taken by the user or not. selectTexture worldTextures(4, keyMap(i).typ - 1).gl_handle
drawXZPlane 0, 0, 0, .25, .15, 1
calc_done = 1
rotY = rotY + 2
r = 0.2: yOff = -0.6
For i
= 1 To worldStats.num_of_point
'down open pyramid
'upper open pyramid, combined together with to form a diamond like structure
If worldStats.num_of_trap
> 0 Then For i
= 1 To worldStats.num_of_trap
If trapMap
(i
).d_1
= 1 Then 'aage piche w.r.t. XY plane selectTexture 0
Else 'agal bagal w.r.t. XY Plane selectTexture 0
Sub drawBox
(x
, y
, z
, w
, h
, d
) '(x,y,z)->location to draw, w->width, h->height, d-depth of the box 'XY
drawXYPlane x, y, z - d / 2, w, h, -1
drawXYPlane x, y, z + d / 2, w, h, 1
'YZ
drawYZPlane x - w / 2, y, z, h, d, -1
drawYZPlane x + w / 2, y, z, h, d, 1
'XZ
drawXZPlane x, y - h / 2, z, w, d, -1
drawXZPlane x, y + h / 2, z, w, d, 1
Sub drawXZPlane
(x
, y
, z
, w
, d
, n
) '(x,z)->location to draw, w->width, d->depth of the plane, n->normal direction in Y direction
Sub drawXYPlane
(x
, y
, z
, w
, h
, n
) '(x,y)-> location to draw, w->width, h->height, n->normal direction in Z direction
Sub drawYZPlane
(x
, y
, z
, h
, d
, n
) '(y,z)->location to draw, h->height, d->depth, n->normal direction in X direction
echo "FUNCTION feedGlTexture&() : invalid image handle passed"
Sub loadWorld
(map_file$
) 'load the given .3dm world
If worldStats.signature
<> "3DM@QB64" Then echo
"SUB loadWorld() : Invalid Signature - " + map_file$:
Exit Sub
'show map info in debug mode
echo "SUB loadWorld() : Map file loaded - " + map_file$
echo
"World size : " + Str$(worldStats.mapW
) + "x" + Str$(worldStats.mapH
) echo
"Player initial position : " + Str$(worldStats.px
) + "," + Str$(worldStats.py
) echo
"Number of wall block(s) : " + Str$(worldStats.num_of_wall
) echo
"Number of floor block(s) : " + Str$(worldStats.num_of_floor
) echo
"Number of ceiling block(s) : " + Str$(worldStats.num_of_ceiling
) echo
"Number of door(s) : " + Str$(worldStats.num_of_door
) echo
"Number of key(s) : " + Str$(worldStats.num_of_key
) echo
"Number of point(s) : " + Str$(worldStats.num_of_point
) echo
"Number of detail(s)/interior(s) : " + Str$(worldStats.num_of_detail
) echo
"Number of trap(s) : " + Str$(worldStats.num_of_trap
) echo
"Player destination : " + Str$(worldStats.destX
) + "," + Str$(worldStats.destY
) echo "Global Light Settings :- "
echo
"Ambient Color : (" + Str$(worldStats.light_amb.x
) + "," + Str$(worldStats.light_amb.y
) + "," + Str$(worldStats.light_amb.z
) + ")" echo
"Diffuse Color : (" + Str$(worldStats.light_diff.x
) + "," + Str$(worldStats.light_diff.y
) + "," + Str$(worldStats.light_diff.z
) + ")" echo
"Specular Color : (" + Str$(worldStats.light_spec.x
) + "," + Str$(worldStats.light_spec.y
) + "," + Str$(worldStats.light_spec.z
) + ")" echo
"Direction : (" + Str$(worldStats.light_dir.x
) + "," + Str$(worldStats.light_dir.y
) + "," + Str$(worldStats.light_dir.z
) + ")" 'wall
If worldStats.num_of_wall
> 0 Then ReDim wallMap
(worldStats.num_of_wall
) As map_element
For i
= 1 To worldStats.num_of_wall
'floor
If worldStats.num_of_floor
> 0 Then ReDim floorMap
(worldStats.num_of_floor
) As map_element
For i
= 1 To worldStats.num_of_floor
'ceiling
If worldStats.num_of_ceiling
> 0 Then ReDim ceilingMap
(worldStats.num_of_ceiling
) As map_element
For i
= 1 To worldStats.num_of_ceiling
'door
If worldStats.num_of_door
> 0 Then ReDim doorMap
(worldStats.num_of_door
) As map_element
For i
= 1 To worldStats.num_of_door
'keys
If worldStats.num_of_key
> 0 Then ReDim keyMap
(worldStats.num_of_key
) As map_element
For i
= 1 To worldStats.num_of_key
'point
If worldStats.num_of_point
> 0 Then ReDim pointMap
(worldStats.num_of_point
) As map_element
For i
= 1 To worldStats.num_of_point
If worldStats.num_of_detail
> 0 Then ReDim detailMap
(worldStats.num_of_detail
) As map_element
For i
= 1 To worldStats.num_of_detail
If worldStats.num_of_trap
> 0 Then ReDim trapMap
(worldStats.num_of_trap
) As map_element
For i
= 1 To worldStats.num_of_trap
'generate new collision map
ReDim collisionMap
(worldStats.mapW
, worldStats.mapH
, 1) As _Byte For i
= 1 To worldStats.num_of_wall
collisionMap(wallMap(i).x, wallMap(i).y, 0) = 1
For i
= 1 To worldStats.num_of_door
collisionMap(doorMap(i).x, doorMap(i).y, 0) = 1
collisionMap(doorMap(i).x, doorMap(i).y, 1) = 2
For i
= 1 To worldStats.num_of_key
collisionMap(keyMap(i).x, keyMap(i).y, 1) = 3
internal_vec4(0) = x
internal_vec4(1) = y
internal_vec4(2) = z
internal_vec4(3) = w
glVec4%&
= _Offset(internal_vec4
())
Function map!
(value!
, minRange!
, maxRange!
, newMinRange!
, newMaxRange!
) map! = ((value! - minRange!) / (maxRange! - minRange!)) * (newMaxRange! - newMinRange!) + newMinRange!
'supportive functions
'##################################################################################
'syntax: extract_file_all cdf_file_name$, path_where_file_is_to_be_extracted$
'* extract all the files present in the given cdf file.
' path_where_file_is_to_be_extracted$ must end either with '/' or '\'
'##################################################################################
sub extract_file_all
(f_name$
, path$
) ' $CHECKING:OFF
DIM header
AS cdf_file_header
, element
AS cdf_file_element
IF header.signature
<> "cdf@qb64" THEN CLOSE #f: echo
"In SUB extract_file_all(): Invalid file - "+f_name$:
EXIT SUB 'verify if it is even a cdf_file or not. Then only proceed.
FOR i
= 1 TO header.num_of_files
a$
= SPACE$(element.compressed_bytes
) GET #f
, , a$
'get content fileToBeExtracted$
= _TRIM$(element.file_name
) IF _FILEEXISTS(path$
+ fileToBeExtracted$
) THEN KILL path$
+ fileToBeExtracted$
'delete if there already exists a file with the same name ea$
= _INFLATE$(a$
, element.original_bytes
) 'decompress echo path$+fileToBeExtracted$
OPEN path$
+ fileToBeExtracted$
FOR BINARY AS #ff
'create the file at the output path echo "In SUB extract_file_all(): File "+f_name$+" not found."
' $CHECKING:ON
'####################################################################################
'syntax: extract_file cdf_file_name$, name_of_file_To_Be_Extracted$, output_path$
'* extract the given file from cdf_file if it exists in it to the required
' output path. output_path$ must end with either '/' or '\'.
'#####################################################################################
SUB extract_file
(f_name$
, fileToBeExtracted$
, path$
) ' $CHECKING:OFF
DIM header
AS cdf_file_header
, element
AS cdf_file_element
IF header.signature
<> "cdf@qb64" THEN CLOSE #f: echo
"In SUB extract_file(): Invalid file - "+f_name$:
EXIT SUB 'verify if it is even a cdf_file or not. Then only proceed.
FOR i
= 1 TO header.num_of_files
IF RTRIM$(element.file_name
) = fileToBeExtracted$
THEN 'extract the file, if condition become true ' ?"ok"
a$
= SPACE$(element.compressed_bytes
) GET #f
, , a$
'get content IF _FILEEXISTS(path$
+ fileToBeExtracted$
) THEN KILL path$
+ fileToBeExtracted$
'delete if there already exists a file with the same name ea$
= _INFLATE$(a$
, element.original_bytes
) 'decompress OPEN path$
+ fileToBeExtracted$
FOR BINARY AS #ff
'create the file at the output path SEEK f
, SEEK(f
) + element.compressed_bytes
'file name is not one which user looking for, we just skip to next entry echo "In SUB extract_file(): File not found - "+f_name$
' $CHECKING:ON
SUB __internal_dummy_cdf_sub
() 'declare required types