02-08-2026, 06:36 AM
(This post was last modified: 02-10-2026, 01:29 AM by Unseen Machine.)
Extract the file to your Qb64 folder (i.e it should look like C:\QB64\GDK)
Quake 1 BSP
Chess Using the shapes lib
Terrain with torch demo (WASD AND MOUSE)
For now TITAN GDK supports,
mdl, md2, md3, prm (Re Volt models (not finalised on placing springs and axles yet!)), stl and obj will follow soon but I've still not finished it!
Terrain from heightmaps (gonna add erosion methods and change the smoothing to be optional soon)
bsp(quake 1) maps
a simple 3d shapes library
PLEASE NOTE : ONLY WINDOWS COMPATIABLE ATM! (Though as the current dev is only legacy GL the features that aren't window/input based should be usable in native QB64 without much modification (please let me know if this is something you guys would like and ill make it happen).
It is still very much a work in progress but its getting there! Any comments, ideas or feedback (and negative is fine!) is welcomed! (For those not in the know, this is a culmination of like 15 years of dev work, learning and failing over and over, but now finally I think I'm on the right track!)
As always, happy coding folks!
Unseen
Quake 1 BSP
Code: (Select All)
'//////////////////////////////////////////////////////////////////////////////////////////////////////
'// TITAN - by Unseen Machine
'//////////////////////////////////////////////////////////////////////////////////////////////////////
'$INCLUDE:'TitanGDK.bi'
'///////////////////////////////////////////////////////////////////////////////////////////////
' --- CAMERA STATE ---
DIM CamX#, CamY#, CamZ#
DIM Yaw#, Pitch#
DIM MoveSpeed#: MoveSpeed# = 4.0
DIM Sensitivity#: Sensitivity# = 0.2
' Start at a reasonable spot in the map
CamX# = 0: CamY# = 50: CamZ# = 0
' --- SETUP ---
IF GDK_Boot(800, 600, "TITAN GDK 2026 | BSP Maps", GDK_MODE_LEGACY) = 0 THEN END
GDK_Scene_Clear .6, .6, .6, 1 '// Set the mabient lighting colour and brightness
MapID& = GDK_Map_Load("GDK\resources\e1m1.bsp" + CHR$(0)) '// Load a BSP map
Plyr& = GDK_Model_Load("GDK\Resources\Player.mdl", "" + CHR$(0)) '// Load the player model
GDK_BSP_DEBUG MapID&, -1 '// Draw collision boxes for entities (doors, buttons etc)
GDK_Model_Debug 1 '// draw model collision boxes (are done based on current frame)
GDK_MouseLock 1 '// Hide mouse pointer and lock mouse to screen center
' --- MAIN LOOP ---
DO
_LIMIT 60
GDK_UpdateSystem '// Timer, input data etc
GDK_Clear 0.1, 0.1, 0.15 '// CLS
GDK_Scene_Apply '// Lighting
'// Mouse
Yaw# = Yaw# + GDK_MouseDX! * Sensitivity#
Pitch# = Pitch# + GDK_MouseDY! * Sensitivity#
' Clamp Pitch to avoid gimble lock
IF Pitch# > 89 THEN Pitch# = 89
IF Pitch# < -89 THEN Pitch# = -89
'// KEYBOARD
RadYaw# = Yaw# * 0.01745329
ForwardX# = SIN(RadYaw#)
ForwardZ# = COS(RadYaw#)
RightX# = SIN(RadYaw# - 1.5708)
RightZ# = COS(RadYaw# - 1.5708)
IF GDK_Key(ASC("W")) THEN CamX# = CamX# + ForwardX# * MoveSpeed#: CamZ# = CamZ# - ForwardZ# * MoveSpeed#
IF GDK_Key(ASC("S")) THEN CamX# = CamX# - ForwardX# * MoveSpeed#: CamZ# = CamZ# + ForwardZ# * MoveSpeed#
IF GDK_Key(ASC("A")) THEN CamX# = CamX# - RightX# * MoveSpeed#: CamZ# = CamZ# + RightZ# * MoveSpeed#
IF GDK_Key(ASC("D")) THEN CamX# = CamX# + RightX# * MoveSpeed#: CamZ# = CamZ# - RightZ# * MoveSpeed#
IF GDK_Key(ASC("Q")) THEN CamY# = CamY# + MoveSpeed#
IF GDK_Key(ASC("E")) THEN CamY# = CamY# - MoveSpeed#
'// GAME LOGIC HERE
'// ALL GFX BELOW
' 3. RENDER SETUP
glMatrixMode GL_PROJECTION
GDK_Perspective 75, 0.1, 8000
glMatrixMode GL_MODELVIEW
glLoadIdentity
'// Draw the player model
glPushMatrix
glTranslatef 0, -20, -60
glRotatef 90, 0, 1, 0
GDK_Model_Draw Plyr&, 1, 0
glPopMatrix
'// Render the BSP map
'glPushMatrix
glRotatef Pitch#, 1, 0, 0
glRotatef Yaw#, 0, 1, 0
glTranslatef -CamX#, -CamY#, -CamZ#
GDK_Map_Draw MapID&
'glPopMatrix
GDK_Display '// Update the buffer
LOOP UNTIL GDK_Quit OR GDK_Key(27)
SYSTEM
Chess Using the shapes lib
Code: (Select All)
'//////////////////////////////////////////////////////////////////////////////////////////////////////
'// TITAN - by Unseen Machine
'//////////////////////////////////////////////////////////////////////////////////////////////////////
'$INCLUDE:'TitanGDK.bi'
'///////////////////////////////////////////////////////////////////////////////////////////////
' --- GDK 2026 CHESS ENGINE CORE ---
CONST P_EMPTY = 0: CONST P_PAWN = 1: CONST P_ROOK = 2: CONST P_KNIGHT = 3
CONST P_BISHOP = 4: CONST P_QUEEN = 5: CONST P_KING = 6
CONST T_WHITE = 0: CONST T_BLACK = 1
TYPE ChessPiece
id AS INTEGER
team AS INTEGER
END TYPE
TYPE GameArbiter
Turn AS INTEGER ' 0: White, 1: Black
SelectedX AS INTEGER ' -1 for none
SelectedZ AS INTEGER ' -1 for none
IsActive AS INTEGER ' 1 if a piece is selected
Timer AS SINGLE ' Used for the "Bounce" animation
PlayerTeam AS INTEGER ' 0 or 1 (Randomized at start)
' Future AI Agro/Difficulty metrics could go here
END TYPE
' --- EXPLICIT SHARED HANDLES & VARS ---
DIM SHARED Board(7, 7) AS ChessPiece
DIM SHARED AS LONG ListBoard, PieceLists(1, 6)
DIM SHARED Arbiter AS GameArbiter
DIM SHARED ValidMoves(7, 7) AS INTEGER ' 1 if square is a valid target
DIM SHARED AS INTEGER hoverX, hoverZ
' --- SETUP ---
IF GDK_Boot(800, 600, "TITAN GDK 2026 | 3D Chess", GDK_MODE_LEGACY) = 0 THEN END
Bake '// Build the board and pieces as gllists
Setup_Board '// setup the piece positions
' Initialize the Arbiter State
Arbiter.SelectedX = -1
Arbiter.SelectedZ = -1
Arbiter.IsActive = 0
Arbiter.Turn = 0 ' White always starts in Chess
Arbiter.PlayerTeam = 0 ' INT(RND * 2) ' Start as White Human player for testing
'///////////////////////////////////////////////////////////////////////////////////////////////
GDK_Scene_Clear 0.8, 0.8, 0.8, .8 '// Set ambient light
' --- MAIN LOOP ---
DO
GDK_UpdateSystem '// Updates input handlers screen etc
'// Logic
Get_Grid_Hack ' 1. Map mouse to board - Hecked version - need to make raycasting work to do it right!
Handle_Selection_Interaction ' 2. Process clicks and piece bounces
' --- RENDER SCENE SETUP ---
GDK_Clear 0.1, 0.1, 0.15 '// CLS but with background colour values
GDK_Perspective 70, 0.1, 200 '// gluperspective clone but GLM based
glLoadIdentity '// reset us to 0,0,0 '// Note - non legacy mode will require GDK_ functions
GDK_LookAt 0, 30, 10, 0, 0, 0 '// gluLookAt clone but using the glm lib which is way better
GDK_Scene_Apply '// Apply ambient light, camera etc
' --- RENDER ---
glCallList ListBoard '// Draw chess board
Render_Highlights '// if piece is selected by himan player then moves are highlighted
Render_Pieces '// Draw the chess pieces
Debug_Info '// Mouse data
GDK_Display '// Swaps the buffers so you can see whats happend - same as _DISPLAY functions but for our custom window
LOOP UNTIL GDK_Quit OR GDK_Key(27)
SYSTEM
'///////////////////////////////////////////////////////////////////////////////////////////////
SUB Render_Pieces
' Renders all pieces, including the "bounce" effect on the selected piece
FOR x = 0 TO 7: FOR z = 0 TO 7
IF Board(x, z).id <> P_EMPTY THEN
y_off! = 0
IF x = Arbiter.SelectedX AND z = Arbiter.SelectedZ THEN y_off! = ABS(SIN(TIMER * 6)) * 1.2
glPushMatrix
glTranslatef (x * 4) - 14, y_off!, (z * 4) - 14
DrawPiece Board(x, z).team, Board(x, z).id
glPopMatrix
END IF
NEXT: NEXT
END SUB
'///////////////////////////////////////////////////////////////////////////////////////////////
'// resets the board to deafults
SUB Setup_Board
FOR x = 0 TO 7: FOR z = 0 TO 7: Board(x, z).id = P_EMPTY: NEXT: NEXT
FOR i = 0 TO 7
Board(i, 1).id = P_PAWN: Board(i, 1).team = T_WHITE
Board(i, 6).id = P_PAWN: Board(i, 6).team = T_BLACK
NEXT
FOR t = 0 TO 1
IF t = 0 THEN rw = 0: tm = T_WHITE ELSE rw = 7: tm = T_BLACK
Board(0, rw).id = P_ROOK: Board(0, rw).team = tm
Board(7, rw).id = P_ROOK: Board(7, rw).team = tm
Board(1, rw).id = P_KNIGHT: Board(1, rw).team = tm
Board(6, rw).id = P_KNIGHT: Board(6, rw).team = tm
Board(2, rw).id = P_BISHOP: Board(2, rw).team = tm
Board(5, rw).id = P_BISHOP: Board(5, rw).team = tm
Board(3, rw).id = P_QUEEN: Board(3, rw).team = tm
Board(4, rw).id = P_KING: Board(4, rw).team = tm
NEXT
END SUB
'///////////////////////////////////////////////////////////////////////////////////////////////
SUB Bake '// Converts all the pieces and the board into gllists (fastest way 1.x can handle) .0001 msecs(so quite fast!)
ListBoard = glGenLists(1)
glNewList ListBoard, &H1300
FOR x = 0 TO 7: FOR z = 0 TO 7
glPushMatrix
glTranslatef (x * 4) - 14, -0.01, (z * 4) - 14
IF (x + z) MOD 2 = 0 THEN GDK_Quad_Clr 0.9, 0.9, 0.8, 1, 4, 4 ELSE GDK_Quad_Clr 0.2, 0.3, 0.2, 1, 4, 4
glPopMatrix
NEXT: NEXT
glEndList
FOR t = 0 TO 1
IF t = T_WHITE THEN r_team! = 1.0: g_team! = 1.0: b_team! = 1.0 ELSE r_team! = 0.8: g_team! = 0.1: b_team! = 0.1
FOR i = P_PAWN TO P_KING
PieceLists(t, i) = glGenLists(1)
glNewList PieceLists(t, i), &H1300
glColor4f r_team!, g_team!, b_team!, 1.0
SELECT CASE i
CASE P_PAWN
GDK_Cone_Clr r_team!, g_team!, b_team!, 1, 0.8, 2.2, 16
glPushMatrix: glTranslatef 0, 2.2, 0: GDK_Sphere_Clr r_team!, g_team!, b_team!, 1, 0.6, 12: glPopMatrix
CASE P_ROOK
GDK_Cylinder_Clr r_team!, g_team!, b_team!, 1, 1.2, 3.5, 20
CASE P_KNIGHT
GDK_Cone_Clr r_team!, g_team!, b_team!, 1, 0.7, 4.5, 16
glPushMatrix: glTranslatef 0, 2.8, 0: glRotatef 90, 0, 0, 1: GDK_Torus_Clr r_team!, g_team!, b_team!, 1, 1.1, 0.2, 12, 8: glPopMatrix
CASE P_BISHOP
glPushMatrix: glTranslatef 0, 2.25, 0: GDK_Box_Clr r_team!, g_team!, b_team!, 1, 1.2, 4.5, 0.6: glPopMatrix
CASE P_QUEEN
GDK_Pyramid_Clr r_team!, g_team!, b_team!, 1, 1.4, 5.5, 4
glPushMatrix: glTranslatef 0, 5.5, 0: GDK_Sphere_Clr r_team!, g_team!, b_team!, 1, 0.6, 12: glPopMatrix
CASE P_KING
GDK_Pyramid_Clr r_team!, g_team!, b_team!, 1, 1.6, 6.5, 3
END SELECT
glEndList
NEXT i
NEXT t
END SUB
'///////////////////////////////////////////////////////////////////////////////////////////////
'// Draws a single piece via index using the gllist handle
SUB DrawPiece (team AS INTEGER, id AS INTEGER)
glCallList PieceLists(team, id)
END SUB
'///////////////////////////////////////////////////////////////////////////////////////////////
'// Uses Qb64 screen for mouse and grid settings/info
SUB Debug_Info
'// Get_Grid_Hack - This gets called in the main loop so no need for second call
CLS
PRINT "Raw Mouse: "; GDK_MouseX; ","; GDK_MouseY
IF hoverX <> -1 THEN '// over a specific cell on the board
PRINT "Grid: ["; hoverX; ","; hoverZ; "]"
ELSE
PRINT "Grid: [OUT OF BOUNDS]"
END IF
PRINT "--------------------------------"
PRINT "FPS : "; GDK_GetFPS
_DISPLAY
END SUB
'///////////////////////////////////////////////////////////////////////////////////////////////
'// A workaround to detect what cell the mouse is over - Not perfect but good enough - need to fix raycasting stuff to make perfect
SUB Get_Grid_Hack
mx! = GDK_MouseX: my! = GDK_MouseY
' --- AXIS TWEAKERS ---
' Row_Bias: If the "hit" is too high on the board, decrease this (e.g., 0.9)
' Row_Squish: Higher numbers (1.2+) stretch the back rows more.
Row_Bias! = 1.0
Row_Squish! = 1
' --- VERTICAL (ROW) CALC ---
' Target: Screen Y range 109 to 508
y_range! = 508 - 109
raw_v! = (my! - 109) / y_range!
' Crash protection for the exponent
IF raw_v! < 0 THEN raw_v! = 0
IF raw_v! > 1 THEN raw_v! = 1
' Non-linear row correction
v_factor! = (raw_v! * Row_Bias!) ^ Row_Squish!
' --- HORIZONTAL (COL) CALC ---
' Width-Top: 372 (578-206), Width-Bottom: 504 (644-140)
' Left-Top: 206, Left-Bottom: 140
width_at_y! = 372 + (v_factor! * (504 - 372))
left_x_at_y! = 206 + (v_factor! * (140 - 206))
h_factor! = (mx! - left_x_at_y!) / width_at_y!
' --- GRID MAPPING (0-7) ---
hoverX = INT(h_factor! * 8)
hoverZ = INT(v_factor! * 8)
IF hoverX < 0 OR hoverX > 7 OR hoverZ < 0 OR hoverZ > 7 THEN
hoverX = -1: hoverZ = -1
END IF
END SUB
'///////////////////////////////////////////////////////////////////////////////////////////////
'// Either sets ir unsets a selected piece - selected pieces bounce and should eventually highlight their possible routes
SUB Handle_Selection_Interaction
' 1. Check for Left Mouse Hit (GDK_MouseHit(1))
IF GDK_MouseClicked(1) = 0 THEN EXIT SUB
' 2. Ensure we are actually over a board tile
IF hoverX = -1 OR hoverZ = -1 THEN EXIT SUB
' 3. Check current board state at hover location
clicked_piece_id = Board(hoverX, hoverZ).id
clicked_piece_team = Board(hoverX, hoverZ).team
' 4. LOGIC: Selection Toggle
IF Arbiter.IsActive THEN
' If clicking the SAME piece again, deselect it
IF hoverX = Arbiter.SelectedX AND hoverZ = Arbiter.SelectedZ THEN
Arbiter.IsActive = 0
Arbiter.SelectedX = -1: Arbiter.SelectedZ = -1
ELSE
' If clicking a DIFFERENT piece belonging to you, switch selection
IF clicked_piece_id <> P_EMPTY AND clicked_piece_team = Arbiter.PlayerTeam THEN
Arbiter.SelectedX = hoverX
Arbiter.SelectedZ = hoverZ
END IF
' (Future logic: If clicking an empty square or enemy, try to MOVE)
END IF
ELSE
' If nothing is active, select the piece if it belongs to you
IF clicked_piece_id <> P_EMPTY AND clicked_piece_team = Arbiter.PlayerTeam THEN
Arbiter.IsActive = 1
Arbiter.SelectedX = hoverX
Arbiter.SelectedZ = hoverZ
END IF
END IF
END SUB
'///////////////////////////////////////////////////////////////////////////////////////////////
'// When a piece is chosen this function will highlight the places it can move too
SUB Render_Highlights
' Renders blue highlight tiles if a human player is active
IF Arbiter.IsActive AND Arbiter.Turn = Arbiter.PlayerTeam THEN
FOR x = 0 TO 7: FOR z = 0 TO 7
IF ValidMoves(x, z) = 1 THEN
glPushMatrix
glTranslatef (x * 4) - 14, 0.5, (z * 4) - 14
GDK_Quad_Clr 0.1, 0.3, 0.8, 0.5, 4, 4 ' Cool blue highlight
glPopMatrix
END IF
NEXT: NEXT
END IF
END SUB
'///////////////////////////////////////////////////////////////////////////////////////////////
'///////////////////////////////////////////////////////////////////////////////////////////////
'///////////////////////////////////////////////////////////////////////////////////////////////
'///////////////////////////////////////////////////////////////////////////////////////////////
'///////////////////////////////////////////////////////////////////////////////////////////////
'///////////////////////////////////////////////////////////////////////////////////////////////
Terrain with torch demo (WASD AND MOUSE)
Code: (Select All)
'//////////////////////////////////////////////////////////////////////////////////////////////////////
'// TITAN - by Unseen Machine
'//////////////////////////////////////////////////////////////////////////////////////////////////////
'$INCLUDE:'TitanGDK.bi'
'///////////////////////////////////////////////////////////////////////////////////////////////
' --- SETUP ---
IF GDK_Boot(800, 600, "TITAN GDK 2026 | S-Tier Terrain Demo", 0) = 0 THEN END
' Handle for the terrain
DIM myTerrain AS LONG
myTerrain = GDK_LoadTerrain("gdk\resources\Hill_hmap.png" + CHR$(0), "gdk\resources\hill_texture.png" + CHR$(0), 15.0, 50.0)
' Camera and Movement Variables
camX = 100.0
camZ = 500.0
speed = 120.0
rad = 0.01745329
' Standard Dusk Ambient (Light 0)
GDK_Scene_Clear 0.1, 0.1, 0.2, 1
GDK_MouseLock 1
' --- MAIN LOOP ---
DO
GDK_UpdateSystem
' Capture Delta Time once for all movement harmony
dt = GDK_GetDT
' --- LOGIC: FPS Camera ---
camYaw = camYaw + GDK_MouseDX * 0.6
camPitch = camPitch - GDK_MouseDY * 0.6
' Clamp pitch to stop cartwheels
IF camPitch > 89.0 THEN camPitch = 89.0
IF camPitch < -89.0 THEN camPitch = -89.0
' Movement Vectors (Yaw Only)
fX = SIN(camYaw * rad)
fZ = -COS(camYaw * rad)
' Use the captured DT variable for all physics
IF GDK_Key(ASC("W")) OR GDK_Key(ASC("w")) THEN
camX = camX + fX * dt * speed
camZ = camZ + fZ * dt * speed
END IF
IF GDK_Key(ASC("S")) OR GDK_Key(ASC("s")) THEN
camX = camX - fX * dt * speed
camZ = camZ - fZ * dt * speed
END IF
' Height tracking
groundY = GDK_GetTerrainHeight(myTerrain, camX, camZ) + 20.0
' --- TEST THE TORCH SYSTEM ---
' Parameters: lightIndex, posX, posY, posZ, dirX, dirY, dirZ
' In Eye Space (after LookAt), 0,0,0 is the camera eye.
GDK_Torch_Test 1, camX, groundY, camZ, fX, SIN(camPitch * rad), fZ
' --- RENDER ---
GDK_Clear 0.01, 0.01, 0.02
GDK_Perspective 75, 0.1, 10000
' Calculate Stable Look Vector
lx = fX * COS(camPitch * rad)
ly = SIN(camPitch * rad)
lz = fZ * COS(camPitch * rad)
GDK_LookAt camX, groundY, camZ, camX + lx, groundY + ly, camZ + lz
GDK_Scene_Apply
GDK_RenderTerrain myTerrain
GDK_Display
LOOP UNTIL GDK_Quit OR GDK_Key(27)
GDK_MouseLock 0
SYSTEM
' --- GDK LIGHTING SUBS ---
SUB Light_Type
TYPE GDKLightPreset
PositionX AS SINGLE
PositionY AS SINGLE
PositionZ AS SINGLE
Power AS SINGLE
ColorR AS SINGLE
ColorG AS SINGLE
ColorB AS SINGLE
Ambient AS SINGLE
DirX AS SINGLE
DirY AS SINGLE
DirZ AS SINGLE
LightType AS LONG
Enabled AS LONG
Range AS SINGLE
InnerCutoff AS SINGLE
OuterCutoff AS SINGLE
END TYPE
END SUB
SUB GDK_Torch_Test (index, x, y, z, dx, dy, dz)
' This single SUB handles the UDT setup and the API calls
DIM tPreset AS GDKLightPreset
tPreset.LightType = 1 ' Spotlight
tPreset.ColorR = 1.0
tPreset.ColorG = 0.95
tPreset.ColorB = 0.8
tPreset.Power = .5
tPreset.Range = 10.0
tPreset.InnerCutoff = 0
tPreset.OuterCutoff = 90
' Position and Direction passed from the main loop
tPreset.PositionX = x
tPreset.PositionY = y
tPreset.PositionZ = z
tPreset.DirX = dx
tPreset.DirY = dy
tPreset.DirZ = dz
' Commit to the GDK Indexed Light System
GDK_Light_SetType index, tPreset.LightType
GDK_Light_SetColor index, tPreset.ColorR, tPreset.ColorG, tPreset.ColorB, tPreset.Power
GDK_Light_SetRange index, tPreset.Range
GDK_Light_SetSpot index, tPreset.InnerCutoff, tPreset.OuterCutoff
GDK_Light_SetPos index, tPreset.PositionX, tPreset.PositionY, tPreset.PositionZ
GDK_Light_SetDir index, tPreset.DirX, tPreset.DirY, tPreset.DirZ
END SUB
For now TITAN GDK supports,
mdl, md2, md3, prm (Re Volt models (not finalised on placing springs and axles yet!)), stl and obj will follow soon but I've still not finished it!
Terrain from heightmaps (gonna add erosion methods and change the smoothing to be optional soon)
bsp(quake 1) maps
a simple 3d shapes library
PLEASE NOTE : ONLY WINDOWS COMPATIABLE ATM! (Though as the current dev is only legacy GL the features that aren't window/input based should be usable in native QB64 without much modification (please let me know if this is something you guys would like and ill make it happen).
It is still very much a work in progress but its getting there! Any comments, ideas or feedback (and negative is fine!) is welcomed! (For those not in the know, this is a culmination of like 15 years of dev work, learning and failing over and over, but now finally I think I'm on the right track!)
As always, happy coding folks!
Unseen


![[Image: Racing.png]](https://i.ibb.co/fGrm5d2F/Racing.png)