Another attempt then. Still needs a bit of, er, fine tuning though :0
Edit(28/3). Improved it a bit.
Edit(29/3). Added use of a pivot so you can move/rotate it.
Edit(30/3). Load some geometrick models and put player movement in a function.
Edit(30/3). Allow you to specify grid resolution, object size and player size. Have not scaled movement though, so on a big grid it will move slower.
Graphics3D 640,480,0,2
Const keyLeftA=203, KeyRightA=205, KeyUpA=200, KeyDownA=208
Local GX#=4, GZ#=4 ; Grid Resolution
Local OX#=2.5, OY#=2.5, OZ#=2.5 ; Object Size
Local PX#=2, PY#=1, PZ#=3.5 ; Player Size
Type player
Field pxspd#,pzspd#,movex#,movez#
Field Entity,parent,move,moveovertime,CurrX,CurrZ
End Type
texture=CreateTexture(128,128)
ScaleTexture texture,16,16
SetBuffer TextureBuffer(texture)
Color 0,0,80 : Rect 0,0,128,128 : Color 0,0,150
For i=0 To 1000 : Plot Rand(0,127),Rand(0,127) : Next
SetBuffer BackBuffer()
plane=CreatePlane(10)
EntityTexture plane,texture
Dim grid(11,11)
arena=CreatePivot()
PositionEntity arena,0,OY,0
creategrid(arena, GX,GZ, OX,OY,OZ)
; create player entity and parent to arena
p1.player=New player
p1\entity = Loadamesh("fighter.3ds",arena) : p1\parent=arena
FitMesh p1\entity,-PX/2,-PY/2,-PZ/2, PX,PY,PZ
RotateMesh p1\entity,0,180,0 ; model specific tweak
;p1\entity=CreateCone(8,1,arena)
;EntityColor p1\entity,255,255,0
;RotateMesh p1\entity,90,0,0 ; Make the cone mesh point into the Z Axis
p1\CurrX=1 : p1\CurrZ=1 : p1\pxspd=0 : p1\pzspd=0 : p1\move=False
PositionEntity p1\entity, p1\CurrX * GX, 0, p1\CurrZ * GZ
light=CreateLight(2,p1\entity)
LightRange light,Sqr(GX*GZ)*5
PositionEntity light, 0 ,PY +10, 0
camera=CreateCamera(arena)
PositionEntity camera,5*GX,6*Sqr(GX*GZ),4.4*GZ
RotateEntity camera,90,0,0
CameraClsColor camera,50,50,160
HidePointer()
MoveMouse GraphicsWidth()/2, GraphicsHeight()/2
Repeat
; Acquire mouse speed
mxspd=MouseXSpeed()
myspd=MouseYSpeed()
MoveMouse GraphicsWidth()/2, GraphicsHeight()/2
; Uses arrow keys to rotate arena
Rotate(arena,1.0)
; Update player movement
moveplayer(p1,mxspd,myspd,GX#,GZ#)
RenderWorld
Showinfo(p1, 0,0)
Flip
Until KeyHit(1)
End
Function moveplayer(p.player, mxspd, myspd, GX#, GZ#)
; accelerate
p\pxspd=p\pxspd+mxspd*0.04
p\pzspd=p\pzspd-myspd*0.04
p\pxspd=p\pxspd*0.8 ; apply drag
p\pzspd=p\pzspd*0.8
If Abs(p\pxspd)<0.01 Then p\pxspd=0 ; set zero when small
If Abs(p\pzspd)<0.01 Then p\pzspd=0
If Abs(p\pxspd)>2.0 Then p\pxspd=2.0 * Sgn(p\pxspd) ; limit max spd
If Abs(p\pzspd)>2.0 Then p\pzspd=2.0 * Sgn(p\pzspd)
; Say movement has stopped if there is no mouse activity for 250ms to allow for deceleration.
If mxspd<>0 Or myspd<>0 Then
p\move=True
p\moveovertime=MilliSecs()+250
Else
If MilliSecs()>=p\moveovertime Then p\move=False
EndIf
; Check player movement
If p\move Then
If grid(p\currX,p\currZ+Sgn(p\pzspd))>0 And grid(p\currX,p\currZ+Sgn(p\pzspd))<5
p\CurrZ=Int((EntityZ(p\entity)+p\pzspd)/GZ) ; Current grid Z Position
Else ; Z direction is blocked - Cancel movement
p\pzspd=0 : PositionEntity p\entity,EntityX(p\entity),0,p\CurrZ * GZ
EndIf
If grid(p\currX+Sgn(p\pxspd),p\CurrZ)>0 And grid(p\currX+Sgn(p\pxspd),p\CurrZ)<5
p\CurrX=Int((EntityX(p\entity)+p\pxspd)/GX) ; Current Grid X Position
Else ; X direction is blocked - Cancel movement
p\pxspd=0 : PositionEntity p\entity,p\CurrX * GX,0,EntityZ(p\entity)
EndIf
TranslateEntity p\entity,p\pxspd,0,p\pzspd ; Apply movement
Else ; stopped moving - align to grid position.
p\movex#=(p\CurrX * GX - EntityX(p\entity))*0.2
p\movez#=(p\CurrZ * GZ - EntityZ(p\entity))*0.2
TranslateEntity p\entity,p\movex,0,p\movez
If Abs(p\movex)<0.1 And Abs(p\movez)<0.1 Then
PositionEntity p\entity,p\CurrX * GX, 0, p\CurrZ * GZ
EndIf
EndIf
; Rotate player based on grid value. Aligntovector works with world coords so...
Select grid(p\CurrX,p\CurrZ)
Case 1 TFormVector 0,0,1,p\parent,0
Case 2 TFormVector 1,0,0,p\parent,0
Case 3 TFormVector -1,0,0,p\parent,0
Case 4 TFormVector 0,0,-1,p\parent,0
End Select
; align the Z axis of the player object accordingly.
AlignToVector p\entity,TFormedX(),TFormedY(),TFormedZ(),3,0.2
End Function
Function rotate(entity,DEG#)
If KeyDown(keyLeftA) Then TurnEntity entity,0,-DEG,0
If KeyDown(keyRightA) Then TurnEntity entity,0,DEG,0
If KeyDown(keyUpA) Then TurnEntity entity,DEG,0,0
If KeyDown(keyDownA) Then TurnEntity entity,-DEG,0,0
End Function
Function creategrid(parent,GX#,GZ#, OX#,OY#,OZ#)
Readgriddata()
For countx = 1 To 11
For countz = 1 To 11
If grid(countx,countz)=9 Then
count=count+1
; If count=1 Then obj=CreateCube(pivot) Else obj=CopyEntity(obj,pivot)
If count=1 Then
obj=loadamesh("wcrate1.3ds",parent)
FitMesh obj,-OX/2,-OY/2,-OZ/2, OX,OY,OZ
Else
obj=CopyEntity(obj,parent)
EndIf
; EntityColor obj,100,0,50
PositionEntity obj,(countx) * GX, 0, (countz) * GZ
EndIf
Next
Next
End Function
Function readgriddata()
Read g$
While g$<>""
For x=1 To Len(g$)
grid(x-1,y)=Mid(g$,x,1)
Next
y=y+1
Read g$
Wend
End Function
Data "00000000000"
Data "01111111110"
Data "02999999930"
Data "02999999930"
Data "02999999930"
Data "02999999930"
Data "02999999930"
Data "02999999930"
Data "04444444440"
Data "00000000000"
Data ""
Function Showinfo(p1.player, SX,SY)
Color 127,127,127
Text SX,SY,EntityX(p1\entity)+" "+EntityZ(p1\entity)
Text SX,SY+12,"Move? "+p1\Move
Text SX,SY+24,"GRID X "+p1\CurrX+" Z "+p1\CurrZ+" VAL "+Grid(p1\CurrX,p1\CurrZ)
Text SX,SY+36,"Speed X "+p1\pxspd+" Z "+p1\pzspd
Text SX,SY+48,"Align X "+p1\moveX+" Z "+p1\moveZ
End Function
Function loadamesh(file$,parent=0)
entity=LoadMesh(file$,parent)
If entity=0 Then RuntimeError "Failed to load "+file$
Return entity
End Function