OK. Here's the code:
;;Barebones 3D Dungeon V.013.2 01-08-2006
Graphics3D 800,600
caps= GfxDriverCaps3D() ; 110 means it supports cube face mapping
If caps<110 Then RuntimeError "Sorry, but you need a 3D capable video card to play this game."
SetBuffer BackBuffer()
Dim map(width,height)
Const width=20,height=20
Const closed=1, opened=2
Const wall=2, door=3, port=4, emptydoorframe=5
Type entity ;a type to tell us what entity category we're looking at
Field parent
Field entity
Field child
Field kind ;wall, portcullis, door, fountian
Field state ;closed=1, opened=2
Field seq
End Type
;camera stuff
pcam=CreatePivot()
camera=CreateCamera(pcam)
EntityRadius pcam,1.45 ;doors are 3.2 wide, this is diameter 2.9, so can go through doorways
EntityType pcam,1
PositionEntity pcam,6.0,.25,6.0
CameraFogMode camera,1
Const fogrange# = 30
CameraFogRange camera,1,fogrange
;light stuff
AmbientLight 0,0,0 ;dungeon to be dark, except for torch (local) lighting
light=CreateLight(2,pcam)
LightRange light,5
;image stuff
t_mag=LoadImage("data/magnifier.png")
cursor=CreateImage(11,19)
SetBuffer ImageBuffer(cursor)
;create cursor arrow by colors and lines
Color 128,128,128: Line 0,1,0,13: Line 4,12,4,13: Line 5,14,5,15: Line 6,16,6,17
Color 192,192,192: Line 1,2,1,12: Line 2,3,2,11: Line 3,4,3,10: Line 4,5,4,9
Line 5,6,5,9: Line 6,7,6,9: Line 7,8,7,9: Line 7,14,7,17: Plot 5,11
Line 6,12,6,13: Plot 8,9: Line 8,16,8,17
Color 255,255,255: Line 1,4,1,11: Line 2,6,2,10: Line 4,11,7,16: Line 3,8,3,9
SetBuffer BackBuffer()
t_door = LoadTexture("data/cdoor_no_hinge.png")
t_stone = LoadTexture("data/stone.png")
t_ceil = LoadTexture("data/mouldy concrete.png")
t_stone2 = LoadTexture("data/stone2.png")
t_port = LoadTexture("data/metalrusty.png",1+4)
;plane stuff
plane=CreatePlane()
NameEntity plane,"Ground"
EntityPickMode plane,2 ;make ground pickable
EntityTexture plane,t_stone
MoveEntity plane,0,-1.5,0
ceiling=CreatePlane()
NameEntity ceiling, "Ceiling"
EntityPickMode ceiling,2
EntityTexture ceiling,t_ceil
RotateEntity ceiling,180,0,0
MoveEntity ceiling,0,-2.5,0
.mainloop
Gosub DrawMap
snake=False
Global dm#=2, d#=0, doormove#=0.0
While Not KeyDown(1) ;ESCape key
ClearCollisions
For e.entity = Each entity
Next
strafe=False:dir#=0
If KeyDown(205) ;turn right
If KeyDown(56) Or KeyDown(184) ;either ALT key
strafe=True
dir=0.1
Else
cam_y=cam_y-2
EndIf
Else If KeyDown(203) ;turn left
If KeyDown(56) Or KeyDown(184) ;either ALT key
strafe=True
dir=-0.1
Else
cam_y=cam_y+2
EndIf
EndIf
cam_z#=0
If KeyDown(200) ;Up arrow, go forward
If KeyDown(42) Or KeyDown(54) ;either Shift key
cam_z = .3 ;running
Else
cam_z = .1
EndIf
Else If KeyDown(208) ;Down arrow, go back
If KeyDown(42) Or KeyDown(54) ;either Shift key
cam_z = -.3 ;running
Else
cam_z = -.1
EndIf
EndIf
If strafe
MoveEntity pcam,dir,0,0 ;go left or right
Else
RotateEntity pcam,0,cam_y,0 ;turn to left or right
MoveEntity pcam,0,0,cam_z ;go foward or back
EndIf
FlushKeys
Collisions 1,2,2,2 ;Camera collision with objects, slide from point of collision
If snake=True
PositionEntity pcam,EntityX(pcam),-1.15,EntityZ(pcam)
Else
PositionEntity pcam,EntityX(pcam),.25,EntityZ(pcam)
EndIf
UpdateWorld
RenderWorld
DrawImage cursor,MouseX(),MouseY()
If MouseDown(1)=True
CameraPick(camera,MouseX(),MouseY())
message$="PickedEntity is "
pe=PickedEntity()
px# = (EntityX(pcam)-PickedX#())
pz# = (EntityZ(pcam)-PickedZ#())
seerange# = Sqr((px*px)+(pz*pz))
If pe = 0
message$ = message$+"nothing."
ElseIf seerange => fogrange-3
message$ = message$+"Out of Range"
Else
message$ = message$+EntityName$(pe)+"."
For e.entity = Each entity
If e\entity=pe
If seerange <4.5
If e\kind = door
If Animating(e\entity) = False ;if door is not moving
If e\state=closed
Animate e\entity,3,.5
e\state = opened
ElseIf e\state = opened
Animate e\entity,3,-.5
e\state = closed
EndIf
EndIf
ElseIf e\kind = port
If Animating(e\entity) = False
If e\state=closed
Animate e\entity,3,.5 ;play animationm forward (ie raise port)
e\state = opened
ElseIf e\state = opened
Animate e\entity,3,-.5
e\state = closed
EndIf
EndIf
EndIf
Else
Text 0,220,"Too far to operate!"
EndIf
EndIf
Next
EndIf
picked$="PickedX: "+PickedX#()
picked$=picked$+" PickedY: "+PickedY#()
picked$=picked$+" PickedZ: "+PickedZ#()
Text 0, 200, message$ ;text here, so that renderworld does not overwrite it
EndIf
cam$="Camera X: "+EntityX(pcam)+" Camera Y: "+EntityY(pcam)+" Camera Z: "+EntityZ(pcam)
Text 0,100,cam$
Text 0,120, picked$
Text 0,140,"See Range = "+seerange
Flip
Wend
End
.createdoor
e.entity = New entity ;create a new instance of the entity type variable
e\parent=CreatePivot()
e\entity=CreateCube(e\parent)
NameEntity e\entity,"Door"
EntityPickMode e\entity,2
PositionMesh e\entity,1,1,1 ;move "door" so that it hinges on left side
ScaleMesh e\entity,1.6,1.8,.125 ;reshape cube to look like door (flatten, etc)
EntityTexture e\entity,t_door ;paint the door to look like one
EntityType e\entity,2
If EastWest=False Then RotateEntity e\entity,0,90,0
epitch= EntityPitch(e\entity)
eyaw = EntityYaw(e\entity)
eroll = EntityRoll(e\entity)
For frame=1 To 45
TurnEntity e\entity,0,2.0,0 ;turn door on its hinges
SetAnimKey e\entity,frame
Next
e\seq = AddAnimSeq(e\entity,frame-1) ;minus 1 because For-Next loops end 1 too many
e\kind = door
e\state = closed
RotateEntity e\entity,epitch,eyaw,eroll ;undo the positioning done by the animation
Return
.createdoorframe
e.entity = New entity ;create a new instance of the entity type variable
e\entity=CreateCube() ;store entity handle in the Type variable
NameEntity e\entity,"Door Frame"
ScaleMesh e\entity,0.2,2.0,0.4 ;reshape it into a doorpost column
PositionMesh e\entity,0,.5,0
EntityPickMode e\entity,2
topframe = CreateCube(e\entity)
ScaleMesh topframe,1.6,0.2,0.4
PositionMesh topframe,1.8,2.3,0
doorframe2 = CopyMesh(e\entity,e\entity) ;copy the doorpost column
PositionMesh doorframe2,3.6,0,0
AddMesh topframe,e\entity
AddMesh doorframe2,e\entity
EntityTexture e\entity,t_stone ;paint doorframe with concrete pic
EntityType e\entity,2
FreeEntity topframe
FreeEntity doorframe2
Return
.createportcullis ;for now, just re-using code for vertical door opening
Const slatspace#=.291
e.entity = New entity ;create a new instance of the entity type variable
e\parent=CreatePivot()
e\entity=CreateCube(e\parent)
NameEntity e\entity,"Portcullis"
ScaleMesh e\entity,.16,1.8,.05 ;reshape cube to look like port slat (flatten, etc)
PositionMesh e\entity,.4,1.8,.1 ;move "portcullis"
EntityPickMode e\entity,2
EntityTexture e\entity,t_port ;paint the port slat to look like one
bar1=CreateCube(e\entity)
ScaleMesh bar1,1.6,.16,.05
PositionMesh bar1,1.6,3.2,0
EntityTexture bar1,t_port ;paint the port slat to look like one
bar2=CreateCube(e\entity)
ScaleMesh bar2,1.6,.16,.05
PositionMesh bar2,1.6,3.2-slatspace*2,0
EntityTexture bar2,t_port ;paint the port slat to look like one
bar3=CreateCube(e\entity)
ScaleMesh bar3,1.6,.16,.05
PositionMesh bar3,1.6,3.2-slatspace*4,0
EntityTexture bar3,t_port ;paint the port slat to look like one
bar4=CreateCube(e\entity)
ScaleMesh bar4,1.6,.16,.05
PositionMesh bar4,1.6,3.2-slatspace*6,0
EntityTexture bar4,t_port ;paint the port slat to look like one
bar5=CreateCube(e\entity)
ScaleMesh bar5,1.6,.16,.05
PositionMesh bar5,1.6,3.2-slatspace*8,0
EntityTexture bar5,t_port ;paint the port slat to look like one
bar6=CreateCube(e\entity)
ScaleMesh bar6,1.6,.16,.05
PositionMesh bar6,1.6,3.2-slatspace*10,0
EntityTexture bar6,t_port ;paint the port slat to look like one
slat1=CreateCube(e\entity)
ScaleMesh slat1,.16,1.8,.05 ;reshape cube to look like port slat (flatten, etc)
PositionMesh slat1,.4+slatspace*2,1.8,.1 ;move "portcullis"
EntityTexture slat1,t_port ;paint the port slat to look like one
slat2=CreateCube(e\entity)
ScaleMesh slat2,.16,1.8,.05 ;reshape cube to look like port slat (flatten, etc)
PositionMesh slat2,.4+slatspace*4,1.8,.1 ;move "portcullis"
EntityTexture slat2,t_port ;paint the port slat to look like one
slat3=CreateCube(e\entity)
ScaleMesh slat3,.16,1.8,.05 ;reshape cube to look like port slat (flatten, etc)
PositionMesh slat3,.4+slatspace*6,1.8,.1 ;move "portcullis"
EntityTexture slat3,t_port ;paint the port slat to look like one
slat4=CreateCube(e\entity)
ScaleMesh slat4,.16,1.8,.05 ;reshape cube to look like port slat (flatten, etc)
PositionMesh slat4,.4+slatspace*8,1.8,.1 ;move "portcullis"
EntityTexture slat4,t_port ;paint the port slat to look like one
AddMesh bar1,e\entity : FreeEntity bar1
AddMesh bar2,e\entity : FreeEntity bar2
AddMesh bar3,e\entity : FreeEntity bar3
AddMesh bar4,e\entity : FreeEntity bar4
AddMesh bar5,e\entity : FreeEntity bar5
AddMesh bar6,e\entity : FreeEntity bar6
AddMesh slat1,e\entity: FreeEntity slat1
AddMesh slat2,e\entity: FreeEntity slat2
AddMesh slat3,e\entity: FreeEntity slat3
AddMesh slat4,e\entity: FreeEntity slat4
EntityType e\entity,2
EntityTexture e\entity,t_port
If EastWest=False Then RotateEntity e\entity,0,90,0
ex=EntityX(e\entity)
ey=EntityY(e\entity)
ez=EntityZ(e\entity)
d=0.05
For frame=1 To 68
MoveEntity e\entity,0,d,0 ;for vertical portcullis effect
SetAnimKey e\entity,frame
Next
e\seq = AddAnimSeq(e\entity,frame-1) ;minus 1 because For-Next loops end 1 too many
e\kind = port
e\state = closed
PositionEntity e\entity,ex,ey,ez ;undo the positioning done by the animation
Return
.DrawMap ;put map out onto 3d field
Restore mapdata
For z=0 To height
For x=0 To width
Read map(x,z)
Select map(x,z) ;can be from 0 (nothing) to 999
Case 1
e.entity = New entity ;create a new instance of the entity type variable
e\entity=CreateCube() ;store entity handle in the Type variable
e\kind = wall ;store what kind of entity it is (my own system)
NameEntity e\entity,"Wall" ;give it a name
EntityType e\entity,2 ;camera is 1, everything else is type 2 (for now)
ScaleMesh e\entity,2,2,2
EntityTexture e\entity,t_stone
PositionEntity e\entity,x*4,.5,z*4
EntityPickMode e\entity,2
Case 2 ;empty doorframe - running East-West
Gosub createdoorframe
PositionEntity e\entity,x*4-1.8,0,z*4
Case 3 ;empty doorframe - running North-South
Gosub createdoorframe
RotateEntity e\entity,0,90,0
PositionEntity e\entity,x*4,0,z*4-1.8
Case 4 ;doorframe and door - running East-West
Gosub createdoorframe
PositionEntity e\entity,x*4-1.8,0,z*4
EastWest=True:Gosub createdoor
PositionEntity e\parent,x*4-1.6,-1.5,z*4-.1
Case 5 ;doorframe and door - running North-South
Gosub createdoorframe
RotateEntity e\entity,0,90,0
PositionEntity e\entity,x*4,0,z*4-1.8
EastWest=False:Gosub createdoor
PositionEntity e\parent,x*4+0.14,-1.5,z*4-1.6
Case 6 ;doorframe and portcullis - running East-West
Gosub createdoorframe
PositionEntity e\entity,x*4-1.8,0,z*4
EastWest=True :Gosub createportcullis
PositionEntity e\parent,x*4-1.6,-1.5,z*4-.14
Case 7 ;doorframe and portcullis - running North-South
Gosub createdoorframe
RotateEntity e\entity,0,90,0
PositionEntity e\entity,x*4,0,z*4-1.8
EastWest=False:Gosub createportcullis
PositionEntity e\parent,x*4+0.14,-1.5,z*4-1.6
End Select
Next
Next
UpdateWorld
PositionEntity pcam,6.0,.25,6.0
Return
.mapdata
Data 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
Data 1,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1
Data 1,0,0,1,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,1
Data 1,2,1,1,2,6,1,0,0,0,0,0,0,0,7,0,0,0,0,0,1
Data 1,0,1,0,0,0,1,0,0,0,0,0,0,0,1,6,1,1,1,6,1
Data 1,2,1,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,1
Data 1,0,1,0,0,0,1,0,1,1,1,1,1,1,0,0,0,0,0,0,1
Data 1,2,1,0,0,0,1,0,1,0,0,5,0,1,0,0,0,0,0,0,1
Data 1,0,1,1,1,1,1,0,1,4,1,1,1,1,0,0,0,0,0,0,1
Data 1,2,1,0,0,0,5,0,1,0,0,0,0,3,0,0,0,0,0,0,1
Data 1,0,1,1,1,1,1,4,1,4,1,1,2,1,0,0,0,0,0,0,1
Data 1,2,1,0,0,0,0,0,1,0,1,0,0,1,0,0,0,0,0,0,1
Data 1,0,1,0,0,0,0,0,1,0,1,0,0,1,0,0,0,0,0,0,1
Data 1,2,1,1,1,1,1,0,1,1,1,1,1,1,0,0,0,0,0,0,1
Data 1,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
Data 1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
Data 1,2,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
Data 1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
Data 1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
Data 1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
Data 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
You can see that, early on in the code where the camera is created (pcam), PositionEntity is OK for small initial x,y,z values. If I increase x or z values to large (say, 50, etc), then I get the weird 4-point-something instead of 50 for the X, etc.
Movement around the dungeon is via the cursor keys. Hit ALT with left/right to strafe, and use SHIFT ro run instead of walk. Doors, etc, are opened by merely clicking on them with the mouse.
|