ich habe bei Gamedev.net dieses Tutorial gefunden: LINK. Es ist eigentlich für die Leadwerks Engine, aber ich wollte mal schauen ob man das umsetzen kann. In dem Tutorial kann man sich alle Grafik und Sonddateien, sowie den Sourcecode (für Leadwerks) herunterladen.
Hier ist der Code und ich denke er funktioniert ganz gut in Purebasic mit der OGRE Engine.
Code: Alles auswählen
EnableExplicit
;--- includes
UsePNGImageDecoder()
UseOGGSoundDecoder()
InitEngine3D()
InitSprite()
InitKeyboard()
InitMouse()
InitSound()
Define.b FullScreen = #False
OpenWindow(0,0,0,1200,768,"3D-Test",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)
OpenWindowedScreen(WindowID(0), 0, 0, 1200, 768, 0, 0, 0, #PB_Screen_NoSynchronization)
;--- constants
#SLASH = "\"
#STANDARDFPS = 60
#Mask_Entity_Level = 1 << 31
Enumeration 1
#Entity_Level
#Light_Sun_Level
EndEnumeration
Enumeration
#PlayerCollide_Nothing
#PlayerCollide_Bottom
#PlayerCollide_Knee
#PlayerCollide_Crouch
#PlayerCollide_BottomKnee
#PlayerCollide_BottomCrouch
#PlayerCollide_KneeCrouch
#PlayerCollide_BottomKneeCrouch
EndEnumeration
;--- structures
Structure iVector2
x.i
y.i
EndStructure
Structure fVector3
x.f
y.f
z.f
EndStructure
Structure iKeys
forward.i
backward.i
strafe_left.i
strafe_right.i
run.i
jump.i
crouch.i
EndStructure
Structure structPlayer
camera.i
mesh.i
entity.i
entityScaleFactor.f
entityRotationCorrector.i
crosshair.i
elapsedTime.i
elapsedTimeLastFrame.f
standHeight.f
crouchHeight.f
kneeHeight.f
cameraHeight.f
move.f
strafe.f
movementSpeed.f
currentSpeed.f
maxAcceleration.f
sensitivity.f
smoothedCameraPositionY.f
cameraYPositionSmoothing.f
cameraLookSmoothing.f
runBoost.f
jump.f
jumpForce.f
jumpBoost.f
lastYPos.f
currentJump.f
footstepWalkFrequency.i
footstepRunFrequency.i
footstepTimer.l
running.b
crouched.b
jumping.b
landing.b
walking.b
MouseSpeed.iVector2
NormalizedMovement.fVector3
CameraPosition.fVector3
PlayerRotation.fVector3
Keys.iKeys
Array FootstepSound.i(4)
Array LandSound.i(4)
Array JumpSound.i(1)
EndStructure
;--- variables
Define.structPlayer Player
Define.i WindowEvt, TimeSinceLastFrame
Define.b DoLoop
;--- declarations
Declare Player_Create()
Declare Player_Destroy()
Declare Player_Update()
;--- player
Player_Create()
;--- main loop
MouseLocate(ScreenWidth()/2, ScreenHeight()/2)
DoLoop = #True
Repeat
;--- catch all window events
If FullScreen = #False
Repeat
WindowEvt = WindowEvent()
Select WindowEvt
Case #PB_Event_CloseWindow
DoLoop = #False
EndSelect
SetWindowTitle(0, "3D-Test" + " - " + StrF(Engine3DFrameRate(#PB_Engine3D_Current),1))
Until WindowEvt = 0
EndIf
;--- player
Player_Update()
;--- render
Player\elapsedTimeLastFrame = RenderWorld()
If IsSprite(Player\crosshair)
DisplayTransparentSprite(Player\crosshair, ScreenWidth()/2-3, ScreenHeight()/2-3)
EndIf
FlipBuffers()
Until DoLoop = #False
;--- end
End
;--- macros
Macro PrintV3(V)
CompilerIf #PB_Compiler_Debugger
Debug "x:"+StrF(V\x,6)+"; y:"+StrF(V\y,6)+"; z:"+StrF(V\z,6)
CompilerEndIf
EndMacro
;--- procedures
Procedure.f Clamp(value.f, min.f=0.0, max.f=1.0)
If value < min
value = min
Else
If value > max
value = max
EndIf
EndIf
ProcedureReturn value
EndProcedure
Procedure.f Curve(newvalue.f, oldvalue.f, increments.f)
If increments > 1
oldvalue = oldvalue-(oldvalue-newvalue)/increments
Else
oldvalue = newvalue
EndIf
ProcedureReturn oldvalue
EndProcedure
Procedure.f Inc(targetvalue.f, currentvalue.f, increments.f)
If targetvalue > currentvalue
ProcedureReturn currentvalue + increments
ElseIf targetvalue < currentvalue
ProcedureReturn currentvalue - increments
Else
ProcedureReturn targetvalue
EndIf
EndProcedure
Procedure.f fMin(value1.f, value2.f)
If value1 > value2
ProcedureReturn value2
ElseIf value1 < value2
ProcedureReturn value1
ElseIf value1 = value2
ProcedureReturn value1
EndIf
EndProcedure
Procedure.f fMax(value1.f, value2.f)
If value1 > value2
ProcedureReturn value1
ElseIf value1 < value2
ProcedureReturn value2
ElseIf value1 = value2
ProcedureReturn value1
EndIf
EndProcedure
Procedure PlayerCamera_SetFOV(FOV.i)
Shared Player
CameraFOV(Player\camera, FOV)
EndProcedure
Procedure PlayerCamera_SetPosition(x.f, y.f, z.f)
Shared Player
MoveCamera(Player\camera, x, y, z, #PB_Absolute)
EndProcedure
Procedure PlayerCamera_GetPosition(*V.fVector3)
Shared Player
*V\x = CameraX(Player\camera)
*V\y = CameraY(Player\camera)
*V\z = CameraZ(Player\camera)
EndProcedure
Procedure Player_SetPhysicsMode(PhysicsMode.i, Mass.f=1.0)
Shared Player
EntityPhysicBody(Player\entity, PhysicsMode, Mass, 0.45, 0)
EndProcedure
Procedure Player_SetPosition(x.f, y.f, z.f)
Shared Player
MoveEntity(Player\entity, x, y, z, #PB_Absolute)
EndProcedure
Procedure Player_GetPosition(*V.fVector3)
Shared Player
*V\x = EntityX(Player\entity)
*V\y = EntityY(Player\entity)
*V\z = EntityZ(Player\entity)
EndProcedure
Procedure Player_GetVelocity(*V.fVector3)
Shared Player
*V\x = GetEntityAttribute(Player\entity, #PB_Entity_VelocityX)
*V\y = GetEntityAttribute(Player\entity, #PB_Entity_VelocityY)
*V\z = GetEntityAttribute(Player\entity, #PB_Entity_VelocityZ)
EndProcedure
Procedure.i Player_OnGround()
Shared Player
ProcedureReturn RayCollide(EntityX(Player\entity), EntityY(Player\entity), EntityZ(Player\entity), EntityX(Player\entity), EntityY(Player\entity)-0.2, EntityZ(Player\entity))
;ProcedureReturn RayCast(EntityX(Player\entity), EntityY(Player\entity), EntityZ(Player\entity), EntityX(Player\entity), EntityY(Player\entity)-0.2, EntityZ(Player\entity), #Mask_Entity_Level)
EndProcedure
Procedure.i Player_CollideForward(DirectionX.f, DirectionZ.f)
Shared Player
Static.f newx, newz
Protected.f x, y, z
Protected.i raybottom, rayknee, raycrouch, result
If DirectionX <> 0 : newx = DirectionX * #STANDARDFPS/10 : EndIf
If DirectionZ <> 0 : newz = DirectionZ * #STANDARDFPS/10 : EndIf
x = EntityX(Player\entity) + DirectionX
y = EntityY(Player\entity)
z = EntityZ(Player\entity) + DirectionZ
raybottom = RayCollide(x, y + 0.1, z, x + newx, y + 0.1, z + newz)
rayknee = RayCollide(x, y + Player\kneeHeight, z, x + newx, y + Player\kneeHeight, z + newz)
raycrouch = RayCollide(x, y + Player\crouchHeight, z, x + newx, y + Player\crouchHeight, z + newz)
CreateLine3D(99, x, y+0.1, z, RGB(255,0,0), x + newx, y+0.1, z + newz, RGB(255,0,0))
CreateLine3D(98, x, y + Player\kneeHeight, z, RGB(255,0,0), x + newx, y + Player\kneeHeight, z + newz, RGB(255,0,0))
CreateLine3D(97, x, y + Player\crouchHeight, z, RGB(255,0,0), x + newx, y + Player\crouchHeight, z + newz, RGB(255,0,0))
If raybottom = 0 And rayknee = 0 And raycrouch = 0
result = #PlayerCollide_Nothing
ElseIf raybottom <> 0 And rayknee <> 0 And raycrouch <> 0
result = #PlayerCollide_BottomKneeCrouch
ElseIf raybottom = 0 And rayknee <> 0 And raycrouch <> 0
result = #PlayerCollide_KneeCrouch
ElseIf raybottom <> 0 And rayknee = 0 And raycrouch <> 0
result = #PlayerCollide_BottomCrouch
ElseIf raybottom <> 0 And rayknee <> 0 And raycrouch = 0
result = #PlayerCollide_BottomKnee
ElseIf raybottom = 0 And rayknee = 0 And raycrouch <> 0
result = #PlayerCollide_Crouch
ElseIf raybottom = 0 And rayknee <> 0 And raycrouch = 0
result = #PlayerCollide_Knee
ElseIf raybottom <> 0 And rayknee = 0 And raycrouch = 0
result = #PlayerCollide_Bottom
EndIf
ProcedureReturn result
EndProcedure
Procedure Player_CreateHitbox()
; EntityBoneX() delivers equal values every time and with all different bones ... ?
EndProcedure
Procedure Player_Create()
Shared Player
Protected.i tempTexture, tempMaterial, i
; create temp material for help entity
tempTexture = CreateTexture(#PB_Any, 1, 1)
StartDrawing(TextureOutput(tempTexture))
Plot(0, 0, RGB(0, 0, 255))
StopDrawing()
tempMaterial = CreateMaterial(#PB_Any, TextureID(tempTexture))
With Player
; initialize values
\standheight = 1.8
\crouchheight = 1.2
\kneeHeight = \crouchheight / 2
\cameraheight = \standheight
\move = 0.0
\strafe = 0.0
\cameraYPositionSmoothing = 3.0
\maxAcceleration = 0.5
\movementSpeed = 3.0
\walking = #False
\sensitivity = 1.0
\cameraLookSmoothing = 2.0
\cameraYPositionSmoothing = 3.0
\smoothedCameraPositionY = 0
\running = #False
\runBoost = 2.0
\jump = 0.0
\jumpforce = 6.0
\jumpboost = 2.0
\jumping = #False
\crouched = #False
\landing = #False
\footstepTimer = 0
\footstepWalkFrequency = 400
\footstepRunFrequency = 320
; keyboard settings
\Keys\forward = #PB_Key_W
\Keys\backward = #PB_Key_S
\Keys\strafe_left = #PB_Key_A
\Keys\strafe_right = #PB_Key_D
\Keys\run = #PB_Key_LeftShift
\Keys\jump = #PB_Key_Space
\Keys\crouch = #PB_Key_C
; create the player camera
\camera = CreateCamera(#PB_Any, 0, 0, 100, 100)
PlayerCamera_SetFOV(70)
PlayerCamera_SetPosition(0, \cameraHeight, 0)
; set up player model and physics
\entityScaleFactor = 0.01
\entityRotationCorrector = 90
\mesh = CreateCylinder(#PB_Any, \standHeight/4, \standHeight)
\entity = CreateEntity(#PB_Any, MeshID(\mesh), MaterialID(tempMaterial))
Player_SetPhysicsMode(#PB_Entity_ConvexHullBody, 10.0)
Player_SetPosition(0, 1, -5)
; load sound files
For i = 0 To 3
\FootstepSound(i) = LoadSound(#PB_Any, "sounds" + #SLASH + "footstep_shoe_sand_0"+Str(i+1)+".ogg")
Next
For i = 0 To 3
;\LandSound(i) = LoadSound(#PB_Any, "sounds" + #SLASH + "footstep_shoe-softsole_metal_jump_0"+Str(i+1)+".ogg")
Next
For i = 0 To 0
\JumpSound(i) = LoadSound(#PB_Any, "sounds" + #SLASH + "jump_shoe_sand_0"+Str(i+1)+".ogg")
Next
\crosshair = CreateSprite(#PB_Any, 6, 6)
StartDrawing(SpriteOutput(\crosshair))
Box(0,0,6,6,RGB(0,0,0))
Box(1,1,4,4,RGB(192,192,0))
Box(2,0,2,6,RGB(255,255,0))
Box(0,2,6,2,RGB(255,255,0))
StopDrawing()
EndWith
; create hitbox for entity
;Player_CreateHitbox()
; destroy the temp material
FreeMaterial(tempMaterial)
FreeTexture(tempTexture)
EndProcedure
Procedure Player_Destroy()
Shared Player
FreeSprite(Player\crosshair)
FreeEntity(Player\entity)
FreeMesh(Player\mesh)
FreeCamera(Player\camera)
Player\crosshair = #Null
Player\entity = #Null
Player\mesh = #Null
Player\camera = #Null
EndProcedure
Procedure.b Player_UpdateControls()
Shared Player
Shared DoLoop
Protected.f sx, sy, dx, dy
Protected.b result = #True
Protected.fVector3 mouseposition
; get inputs from the keyboard
If ExamineKeyboard()
If KeyboardReleased(#PB_Key_Escape)
DoLoop = #False
EndIf
With Player
If KeyboardPushed(\Keys\forward)
\move = -1
ElseIf KeyboardPushed(\Keys\backward)
\move = 1
Else
\move = 0
EndIf
If KeyboardPushed(\Keys\strafe_left)
\strafe = -1
ElseIf KeyboardPushed(\Keys\strafe_right)
\strafe = 1
Else
\strafe = 0
EndIf
If KeyboardPushed(\Keys\run)
\running = #True
Else
\running = #False
EndIf
If Player_OnGround()
If KeyboardReleased(\Keys\jump)
\jump = 1 * \jumpForce
\jumping = #True
EndIf
If KeyboardPushed(\Keys\crouch) And \jumping = #False
\crouched = #True
Else
\crouched = #False
EndIf
EndIf
EndWith
Else
result = #False
EndIf
; get inputs from the mouse
If ExamineMouse()
; get screen center
sx = ScreenWidth() / 2
sy = ScreenHeight() / 2
; get mouse position
mouseposition\x = MouseX()
mouseposition\y = MouseY()
; move mouse to the center of the screen
MouseLocate(sx, sy)
; get change in mouse position
dx = mouseposition\x - sx
dy = mouseposition\y - sy
With Player
; mouse smoothing
\MouseSpeed\x = Curve(dx, \MouseSpeed\x, \cameraLookSmoothing)
\MouseSpeed\y = Curve(dy, \MouseSpeed\y, \cameraLookSmoothing)
; adjust and set the camera rotation
\PlayerRotation\x - \MouseSpeed\y * \sensitivity / 10.0
\PlayerRotation\y - \MouseSpeed\x * \sensitivity / 10.0
; prevent inhuman looking angles
\Playerrotation\x = Clamp(\PlayerRotation\x, -90, 90)
EndWith
Else
result = #False
EndIf
ProcedureReturn result
EndProcedure
Procedure Player_Update()
Shared Player
Static.b playerblocked
Protected.fVector3 velocity
Protected.f maxaccel = Player\maxAcceleration
Protected.f frametimer = Player\elapsedTimeLastFrame / 1000 * #STANDARDFPS
Protected.f groundspeed, movespeed, length, radianangle, newx, newz, newy
Protected.i playercollide, onground = Player_OnGround()
With Player
\elapsedTime + \elapsedTimeLastFrame
EndWith
Player_UpdateControls()
; ; get players velocity, doesn't work in purebasic ?
; Player_GetVelocity(velocity)
; With velocity
; groundspeed = Sqr((\x * \x) + (\z * \z))
; EndWith
; check if player is crouching
With Player
If \crouched
\cameraHeight = Inc(\crouchHeight, \cameraHeight, 0.1 * frametimer)
Else
\cameraHeight = Inc(\standHeight, \cameraHeight, 0.1 * frametimer)
EndIf
EndWith
; normalize movement
With Player\NormalizedMovement
\x = Player\strafe
\z = Player\move
length = Sqr((\x * \x) + (\y * \y) + (\z * \z))
If length > 0
\x = \x / length
\y = \y / length
\z = \z / length
EndIf
EndWith
; check if player is jumping
With Player
If \landing
newy = -maxaccel * frametimer
If onground
\landing = #False
\currentJump = 0
newy + maxaccel
;PlaySound(\LandSound(Random(3,0)))
EndIf
EndIf
If \jumping
If onground
PlaySound(\JumpSound(0))
StartEntityAnimation(\entity, "Jump")
EndIf
\currentJump + maxaccel / 1.5 * frametimer
newy = maxaccel / 1.5 * frametimer
If \currentJump > \jump
\jump = 0
\jumping = #False
\landing = #True
EndIf
EndIf
EndWith
; run if shift key is pressed
If Player\running
maxaccel * 2.0
EndIf
; accelerate player and play animation
With Player
If \move <> 0 Or \strafe <> 0 Or \jump <> 0
If \running And \jumping
movespeed = fMin(\movementSpeed * \runBoost, \movementSpeed * \jumpBoost)
\currentSpeed = Inc(movespeed, \currentSpeed, maxaccel * frametimer)
ElseIf \running And Not \jumping
\currentSpeed = Inc(\movementSpeed * \runBoost, \currentSpeed, maxaccel * frametimer)
ElseIf Not \running And \jumping
\currentSpeed = Inc(\movementSpeed * \jumpBoost, \currentSpeed, maxaccel * frametimer)
ElseIf Not \running And Not \jumping
If \crouched
\currentSpeed = Inc(\movementSpeed / 3, \currentSpeed, maxaccel * frametimer)
Else
\currentSpeed = Inc(\movementSpeed, \currentSpeed, maxaccel * frametimer)
EndIf
EndIf
Else
\currentSpeed = Inc(0, \currentSpeed, maxaccel * frametimer)
EndIf
If \currentSpeed > 0
If \walking = #False
StartEntityAnimation(\entity, "Walk")
\walking = #True
EndIf
Else
If \walking = #True
StopEntityAnimation(\entity, "Walk")
\walking = #False
EndIf
EndIf
EndWith
; play footsteps
With Player
If \elapsedTime > \footstepTimer And length > 0.0 And onground
PlaySound(\FootstepSound(Random(3,0)))
If \currentSpeed > \movementSpeed
\footstepTimer = \elapsedTime + \footstepRunFrequency
Else
\footstepTimer = \elapsedTime + \footstepWalkFrequency
EndIf
EndIf
EndWith
; rotate player camera
With Player\PlayerRotation
RotateCamera(Player\camera, \x, \y, 0, #PB_Absolute)
EndWith
; check if player still on ground or must walk up
With Player
If Not \jumping And Not \landing And Not onground
If \walking Or \running
newy-0.05:Debug"DOWN"
EndIf
EndIf
EndWith
; move and rotate player entity
With Player
radianangle = Radian(CameraYaw(\camera))
;\currentSpeed * frametimer
If \move <> 0 And \strafe = 0
newx = Sin(Radian(CameraYaw(\camera))) * \move * \currentSpeed
newz = Cos(Radian(CameraYaw(\camera))) * \move * \currentSpeed
ElseIf \move = 0 And \strafe <> 0
newx = Sin(Radian(CameraYaw(\camera) + \strafe * 90)) * \currentSpeed
newz = Cos(Radian(CameraYaw(\camera) + \strafe * 90)) * \currentSpeed
ElseIf \move <> 0 And \strafe <> 0
newx = Sin(Radian(CameraYaw(\camera) + \strafe * -45)) * \NormalizedMovement\z * \currentSpeed
newz = Cos(Radian(CameraYaw(\camera) + \strafe * -45)) * \NormalizedMovement\z * \currentSpeed
EndIf
newx * frametimer / 2
;newy * frametimer
newz * frametimer / 2
playercollide = Player_CollideForward(newx, newz)
If playercollide = #PlayerCollide_Bottom ; for height differences
newy+0.15 : Debug "UP:bottom"
ElseIf playercollide = #PlayerCollide_BottomKnee Or playercollide = #PlayerCollide_Knee ; for stairs
newy+0.40 : Debug "UP:bottom_knee"
ElseIf playercollide = #PlayerCollide_BottomKneeCrouch ; collide with map buildings, so don't move
newy+0.15 : Debug "UP:bottom_knee_crouch"
playerblocked = #True
ElseIf playercollide = #PlayerCollide_KneeCrouch Or playercollide = #PlayerCollide_Crouch
playerblocked = #True : Debug "UP:knee_crouch"
ElseIf playercollide = #PlayerCollide_Nothing
playerblocked = #False
EndIf
If playerblocked = #False
MoveEntity(\entity, EntityX(\entity) + newx, EntityY(\entity) + newy, EntityZ(\entity) + newz, #PB_Absolute)
EndIf
EndWith
With Player\PlayerRotation
RotateEntity(Player\entity, 0, \y + Player\entityRotationCorrector, 0, #PB_Absolute)
EndWith
; move and smooth player camera
With Player
Player_GetPosition(\CameraPosition)
If \CameraPosition\y > \smoothedCameraPositionY
\smoothedCameraPositionY = Curve(\CameraPosition\y, \smoothedCameraPositionY, \cameraYPositionSmoothing)
\CameraPosition\y = \smoothedCameraPositionY
Else
\smoothedCameraPositionY = \CameraPosition\y
EndIf
MoveCamera(Player\camera, \CameraPosition\x, \CameraPosition\y + \cameraHeight, \CameraPosition\z, #PB_Absolute)
EndWith
EndProcedure
Viel Spass beim Testen.