Quote: "I think I'll edit the entire code later today and post a redo on the example."
I lied. That code was just too daunting. It was messy (IMO) and it required media files and I was like "easier to rewrite". So I wrote my own example for you. It's neat and commented and covers everything that was covered in the original tutorial (except the FOG ON command - no big loss, you can look that up). I've tried to make it easy to understand and easy to play with. If there are glitches, I appologise but today's been hectic. Should run fine though. I tested it on my "weak machine" and it works on that one so it should work on anything then. Anyway, without further ado, here is your tutorial:
remstart
Dungeon Tutorial - nonZero version.
That last tut was hard to make sense of. Code wasn't formatted and it made references to files
I don't have and couldn't be bothered making.
I more or less get what was supposed to be going on here tough and I think I know the elements it was
trying to illustrate so:
remend
`I'm going to declare some constant here. This is in aprt to make the code read like English
`and in part for my own convenience. Constants are substitued at precompile - no memory loss.
#CONSTANT maincam 0 `Camera 0 is the default camera
#CONSTANT mainlight 0 `Light 0 is th default light
#CONSTANT texwall 1
#CONSTANT texfloor 2
#CONSTANT texceiling 3
#CONSTANT playerone 1000
`Arays and Variables
DIM wall(20, 20)
GLOBAL brickno
GLOBAL mapfile$ = "C:\Map.txt"
GLOBAL speed# = 0.5
GLOBAL StillWantsToPlay = 1
`Set up graphics
SET DISPLAY MODE DESKTOP WIDTH(), DESKTOP HEIGHT(), 32
BACKDROP ON: COLOR BACKDROP RGB(0,0,0)
AUTOCAM OFF
SYNC RATE 60
`Build Map and player
MakeTextures()
SetupLight()
GetMapData()
MakeMap(20, 20)
MakePlayer()
`Restore INK colour so that text displays correctly
INK RGB(200,200,200), RGB(0,0,0)
`The MAIN LOOP - This is important as essentially it's where everything happens - The program's CNS if you will. This is usually
`a conditional loop where the condition is whether the user chooses to keep playing or not. But how you go about it is up to you.
`Many use an "unconditional" DO-loop (DBPro's core is not truely unconditional in executing a DO-loop) and then use exit procedures.
WHILE StillWantsToPlay = 1
`Print some useless stats
TEXT 1, 20, "Ammo: 0%"
TEXT 1, 40, "Health: 0%"
TEXT 1, 60, "Coffee: 0% - Nooo!"
TEXT 1, 80, "Items: Pancake, Waffle (No Syrup), Paper Doll, Origami Crane, Beans x 10"
TEXT 1, 120, "Press ESC to quit!"
`Set the camera to follow the player - in this case there's a 0% follow distance as it's in 1st-person view mode
SET CAMERA TO FOLLOW maincam, OBJECT POSITION X(playerone), OBJECT POSITION Y(playerone), OBJECT POSITION Z(playerone), 0, 0, 0, 1, 0
`Ensure the camera faces the same direction as the player
ROTATE CAMERA maincam, OBJECT ANGLE X(playerone), OBJECT ANGLE Y(playerone), OBJECT ANGLE Z(playerone)
`Check for inputs and move player accordingly. Cheap trick for collisions - very bcrude example I'm afraid
IF UPKEY() = 1: MOVE OBJECT playerone, speed#: ENDIF
IF OBJECT COLLISION(playerone,0) > 0: MOVE OBJECT playerone, 0 - speed#: ENDIF
IF DOWNKEY() = 1: MOVE OBJECT playerone, 0 - speed#: ENDIF
IF OBJECT COLLISION(playerone,0) > 0: MOVE OBJECT playerone, speed#: ENDIF
IF RIGHTKEY() = 1: YROTATE OBJECT playerone, OBJECT ANGLE Y(playerone) + speed#: ENDIF
IF LEFTKEY() = 1: YROTATE OBJECT playerone, OBJECT ANGLE Y(playerone) - speed#: ENDIF
IF KEYSTATE(16) = 1: StillWantsToPlay = 0: ENDIF
`Like the camera, the light must follow the player and face the player's direction
POSITION LIGHT mainlight, OBJECT POSITION X(playerone), OBJECT POSITION Y(playerone), OBJECT POSITION Z(playerone)
ROTATE LIGHT mainlight, OBJECT ANGLE X(playerone), OBJECT ANGLE Y(playerone), OBJECT ANGLE Z(playerone)
ENDWHILE
`===================================================================================================================================
END ` <--- ALWAYS place FUNCTIONS below the END line. END terminates your program.
`===================================================================================================================================
Function GetMapData()
`Gets map data from file or generates its own
DIM result$(20)
`Check if the map file exists. If it does, try to load it
IF FILE EXIST(mapfile$) = 1
OPEN TO READ 1, MapFile$
FOR i = 1 TO 20
READ STRING 1, result$(i)
NEXT i
CLOSE FILE 1
ELSE
`If no map file exists, make a map
result$(1) = "11111111111111111111"
result$(2) = "10000000000000000001"
result$(3) = "10011111111111111001"
result$(4) = "10010000000000000001"
result$(5) = "10010111111111110001"
result$(6) = "10010000000001110011"
result$(7) = "10011111111001110111"
result$(8) = "10000000000001110111"
result$(9) = "11111111111000111011"
result$(10) = "10000000000001100011"
result$(11) = "10000000000001001111"
result$(12) = "10000000000001000001"
result$(13) = "10011111111111110001"
result$(14) = "10001111110000010001"
result$(15) = "10000011111000010001"
result$(16) = "10000000000011000001"
result$(17) = "11111100111111111101"
result$(18) = "10000000111111000001"
result$(19) = "10000000000000000001"
result$(20) = "11111111111111111111"
ENDIF
`Now we just use a nested FOR-loop to assign numeric values to the multi-dimensional array
FOR row = 1 TO 20
FOR col = 1 TO 20
temp$ = MID$(result$(row), col)
wall(row, col) = VAL(temp$)
NEXT col
NEXT row
`Wip the result$ array as we'll never use it again
UNDIM result$()
EndFunction
Function MakeMap(rows, cols)
`Places the bricks along the map
brickno = 0
bricksize = 15
FOR a = 1 TO rows
FOR b = 1 TO cols
IF wall(a, b) = 1
INC brickno
MAKE OBJECT BOX brickno, bricksize, 10, bricksize
POSITION OBJECT brickno, a * bricksize, 0, b * bricksize
TEXTURE OBJECT brickno, texwall
SET SHADOW SHADING ON brickno
ENDIF
NEXT b
NEXT a
`Make the floor: Size must match maze size, number is 1 greater than the last brick.
`Note, this is a shortcut. It is better to use proper terrain
thefloor = brickno + 1
MAKE OBJECT BOX thefloor, bricksize * cols, 1, bricksize * rows
POSITION OBJECT thefloor, OBJECT SIZE X(thefloor) / 2, -4.9, OBJECT SIZE X(thefloor) / 2
TEXTURE OBJECT thefloor, texfloor
`Make the ceiling - same as the floor but higher
theceil = thefloor + 1
MAKE OBJECT BOX theceil, bricksize * cols, 1, bricksize * rows
POSITION OBJECT theceil, OBJECT SIZE X(theceil) / 2, 5, OBJECT SIZE X(theceil) / 2
TEXTURE OBJECT theceil, texceiling
EndFunction
Function MakePlayer()
`Create a "player" and position them
MAKE OBJECT SPHERE playerone, 2
POSITION OBJECT playerone, 122, 0, 121
EndFunction
Function MakeTextures()
`Generate textures, eaier than attaching files
`Walls
CREATE BITMAP 32, 60, 60
SET CURRENT BITMAP 32
INK RGB(80,80,80), RGB(0,0,0)
BOX 0, 0, 60, 60
INK RGB(40,40,40), RGB(0,0,0)
FOR i = 1 TO 15
blen = RND(60) + 30
IF blen > 55: blen = 50: ENDIF
BOX 0, 1 + ((i - 1) * 5), blen / 2, i * 5
BOX (blen / 2) + 1, 1 + ((i - 1) * 5), 60, i * 5
NEXT i
INK RGB(80,80,80), RGB(0,0,0)
LOCK PIXELS
FOR i = 1 TO 500
DOT RND(59) + 1, RND(59) + 1
NEXT i
UNLOCK PIXELS
GET IMAGE texwall, 0, 0, 60, 60
CLS
SET CURRENT BITMAP 0: DELETE BITMAP 32
`Floor (badly done but still)
CREATE BITMAP 32, 1000, 1000
SET CURRENT BITMAP 32
INK RGB(95,95,80), RGB(0,0,0)
BOX 0, 0, 1000, 1000
INK RGB(1,1,1), RGB(0,0,0)
LOCK PIXELS
FOR i = 1 TO 500
CIRCLE RND(999) + 1, RND(999) + 1, RND(9) + 1
NEXT i
UNLOCK PIXELS
GET IMAGE texfloor, 0, 0, 1000, 1000
CLS
SET CURRENT BITMAP 0: DELETE BITMAP 32
`Cieling
CREATE BITMAP 32, 50, 50
SET CURRENT BITMAP 32
INK RGB(90,90,90), RGB(0,0,0)
BOX 0, 0, 50, 50
INK RGB(1,1,1), RGB(0,0,0)
LOCK PIXELS
FOR i = 1 TO 100
DOT RND(49) + 1, RND(49) + 1
NEXT i
UNLOCK PIXELS
GET IMAGE texceiling, 0, 0, 50, 50
SET CURRENT BITMAP 0: DELETE BITMAP 32
`Textures done
EndFunction
Function SetupLight()
`Setup light. Put it in a function to make it neat
SET AMBIENT LIGHT 10
SET POINT LIGHT 0, 0, 0, 0
COLOR LIGHT 0, 255, 255, 255
SET LIGHT RANGE mainlight, 60
EndFunction
Don't hesitate to ask questions if you don't understand something or want to know why I did something in a certain way