Attribute VB_Name = "modCharSystem" '/-----------------------------------------\ '| File: modCharSystem.bas | '| Author: VBBR | '| Last Changed: 10/15/2004 | '| | '| Demonstrates the math used in 3rd | '| person games to move a character and a | '| camera in a 3D world using the keyboard | '| in conjunction with the mouse. | '\-----------------------------------------/ Option Explicit Public CharPosX As Single, CharPosZ As Single 'Horizontal plane Public CharRot As Single 'Y axis Public CamPosX As Single, CamPosY As Single, CamPosZ As Single Public CamRot As Single 'Y axis, relative to CharRot Public CamAng As Single 'Z axis rotation 'IMPORTANT: Be sure to initialize this somewhere or you may get REALLY weird results Public CamDist As Single 'Zoom 'You may change this to a variable so you can change it at run-time Public Const CAM_HEIGHT As Single = 1.5 'Camera height 'Angles Private pSine(359) As Single Private pCosine(359) As Single Private Const PI As Single = 3.141593 Private Const RAD As Single = 0.01745329 'Call this before anything else Public Sub InitMath() Dim i As Integer For i = 0 To 359 pSine(i) = Sin(i * RAD) pCosine(i) = Cos(i * RAD) Next i End Sub 'Returns the sine of an angle, in degrees Public Function Sine(ByVal Angle As Single) As Single Angle = ((Angle Mod 360) + 360) Mod 360 Sine = pSine(Angle) End Function 'Returns the cosine of an angle, in degrees Public Function CoSine(ByVal Angle As Single) As Single Angle = ((Angle Mod 360) + 360) Mod 360 CoSine = pCosine(Angle) End Function 'Call this every frame Public Sub Update() 'avoid overflow errors by limiting the angles' values CharRot = ((CharRot Mod 360) + 360) Mod 360 CamRot = ((CamRot Mod 360) + 360) Mod 360 'limit camera rotation on the Z axis If CamAng > 80 Then CamAng = 80 If CamAng < -70 Then CamAng = -70 'Set Camera position CamPosX = CharPosX + CoSine(CharRot + 180 + CamRot) * CamDist * CoSine(CamAng) CamPosZ = CharPosZ - Sine(CharRot + 180 + CamRot) * CamDist * CoSine(CamAng) CamPosY = CAM_HEIGHT + Sine(CamAng) * CamDist 'Avoid the camera from going below the ground 'Change this according to your floor level If CamPosY < 0.5 Then CamPosY = 0.5 ' The last thing to do is actually set the character and camera positions. ' This depends on which engine/wrapper/API you're using so I won't go into 'any specifics, just point out what goes where for your convenience. ' Set the character X and Y positions using CharPosX and CharPosZ. ' Set the Y position according to your world data. ' Set the character Y rotation to the value stored in CharRot. ' Set the camera position using the CamPos variables. ' Set the camera lookat point to (CharPosX, CAM_HEIGHT - 0.3, CharPosZ) 'or something like it. You can use just CAM_HEIGHT for the Y position but 'it looks a lot better when subtracting a small number. End Sub '******************************************************* '* NOTE on the following call: * '* modGraphics.ScaleValue * '* * '* This is an OUTSIDE method I used to convert the * '* speed from units/sec to units/frame according to * '* the frame rate. Change this according to the method * '* you use to control timed movements/animations; * '* or if you're using frame-based movement just * '* use units/frame in the Speed argument and delete * '* all the "Dim fMove" and "modGraphics.ScaleValue" * '* lines and use "Speed" in place of "fMode" in the * '* calculations below. * '******************************************************* Public Sub MoveForward(Speed As Single) 'Speed = units/sec Dim fMove As Single fMove = modGraphics.ScaleValue(Speed) CharPosZ = CharPosZ - Sine(CharRot) * fMove CharPosX = CharPosX + CoSine(CharRot) * fMove End Sub Public Sub MoveBackward(Speed As Single) 'Speed = units/sec Dim fMove As Single fMove = modGraphics.ScaleValue(-Speed) CharPosZ = CharPosZ - Sine(CharRot) * fMove CharPosX = CharPosX + CoSine(CharRot) * fMove End Sub Public Sub StrafeLeft(Speed As Single) 'Speed = units/sec Dim fMove As Single fMove = modGraphics.ScaleValue(Speed) CharPosZ = CharPosZ - Sine(CharRot - 90) * fMove CharPosX = CharPosX + CoSine(CharRot - 90) * fMove End Sub Public Sub StrafeRight(Speed As Single) 'Speed = units/sec Dim fMove As Single fMove = modGraphics.ScaleValue(Speed) CharPosZ = CharPosZ - Sine(CharRot + 90) * fMove CharPosX = CharPosX + CoSine(CharRot + 90) * fMove End Sub