Can someone walk me through creating third person camera movement with mouse?

Started by William, May 07, 2023, 17:24:37

Previous topic - Next topic

Midimaster

Here is the code related to my video

CameraFollow.gif
 
SuperStrict

Import openb3d.b3dglgraphics

Graphics3D 800,600,0,2

' world
Local Floor:TEntity = CreatePlane()
EntityColor  Floor, 0, 99, 0

SeedRnd MilliSecs()
For Local  i%=0 To 30
Local c:TEntity = CreateCylinder()
ScaleEntity c, 0.2,10,0.2
    PositionEntity c, -10,-2,-100 + i*10

Next
For Local  i%=0 To 10
Local c:TEntity = CreateCube()
EntityColor  c, Rand(255),Rand(255),Rand(255)
ScaleEntity c, 2 , 4, 2
    PositionEntity c, Rand(-60,60),1, Rand(-60,60)
    TurnEntity c, 0, Rand(360),0
Next


' light
Global Light:TLight = CreateLight(1)
LightRange Light,1000
PositionEntity Light, 10,50,20


' man
Global Pivot:TEntity = CreatePivot()
Global Man:TEntity = CreateCubicMan()
EntityParent Man, pivot
PositionEntity Man,0,0.75,0

' camera
Global Camera:TCamera = CreateCamera(Pivot)
PositionEntity( Camera, 0.3, 2, -2.5 )
CameraRange( Camera, 0.1, 100 )


Repeat
Movements

Cls
UpdateWorld
RenderWorld
Flip 1
Until KeyHit(1)


Function Movements()
If KeyDown(KEY_UP) MoveEntity Pivot, 0, 0   , 0.1
If KeyDown(KEY_RIGHT) TurnEntity Pivot, 0, -1 , 0
If KeyDown(KEY_LEFT) TurnEntity Pivot, 0, +1 , 0
End Function


Function CreateCubicMan:Tentity()
Local mesh:TEntity = Createpivot()

Local head:TMesh  = CreateSphere(32)
ScaleMesh    head, 0.25, 0.30, 0.25
PositionMesh head, 0, 0.92, 0
EntityColor  head, 255,155,111
EntityParent head, Mesh


Local chest:TMesh = CreateCube()
ScaleMesh    chest, 0.24, 0.3, 0.1
PositionMesh chest, 0, 0.27, 0
EntityColor  chest, 255,0,111
EntityParent chest, Mesh


Local arms:TMesh = CreateCube()
ScaleMesh    arms, 0.85, 0.08, 0.08
PositionMesh arms, 0, 0.6, 0
EntityColor  arms, 255,0,111
EntityParent arms, Mesh

Local hips:TMesh = CreateCube()
ScaleMesh    hips, 0.26, 0.15, 0.11
PositionMesh hips, 0, 0, 0
EntityColor  hips, 255,255,0
EntityParent hips, Mesh


Local leg1:TMesh = CreateCylinder()
ScaleMesh    leg1, 0.08, 0.4, 0.08
PositionMesh leg1, -0.15, -0.4, 0
EntityColor  leg1, 255,155,111
EntityParent leg1, Mesh

Local leg2:TMesh = CreateCylinder()
ScaleMesh    leg2, 0.08, 0.4, 0.08
PositionMesh leg2, +0.15, -0.4, 0
EntityColor  leg2, 255,155,111
EntityParent leg2, Mesh

Return mesh
End Function
...back from Egypt

William

alright so movemouse function fixes the mouse to the same position and the camera  isn't moving/moves back to the same position and its necessary so the mouse doesn't hit the edge of the screen or go outside the window.
im still interested in oldschool app/gamedev

William

'main program
Strict

Framework openb3d.b3dglgraphics
Import brl.randomdefault
Graphics3D 800,600, 0, 3

HideMouse()

SeedRnd(MilliSecs()) 

Const CFirstPerson% = 1
Const CThirdPerson% = 2
Global ViewMode% = CFirstPerson

Const GroupEnvironment% = 1
Const GroupCharacters% = 2

Global Camera:TCamera = CreateCamera() 
CameraRange(Camera,0.1,1000)
CameraClsColor(Camera,000,000,000)  

Local Origine:TMesh = CreateCube() 
ScaleMesh(Origine,0.1/2,1000.0,0.1/2)
EntityColor(Origine,255,000,000)
EntityFX(Origine,1)

Local GroundMesh:TMesh  = CreateCube()
ScaleMesh(GroundMesh,100.0/2,0.1/2,100.0/2)
PositionMesh(GroundMesh,100.0/2,-0.1/2,100.0/2)
EntityColor(GroundMesh,000,125,000)
EntityType(GroundMesh,GroupEnvironment)

Local PlayerCollider:TPivot = CreatePivot() 
PositionEntity(PlayerCollider,0,0,0) 
EntityRadius(PlayerCollider,0.25)
EntityType(PlayerCollider,GroupCharacters)

Local PlayerEyes:TPivot = CreatePivot()
PositionEntity(PlayerEyes,EntityX(PlayerCollider,True),EntityY(PlayerCollider,True)+1.6-0.25,EntityZ(PlayerCollider,True)+0.25)
EntityParent(PlayerEyes,PlayerCollider,True)

Local PlayerMesh:TMesh = CreateCube() 
ScaleMesh(PlayerMesh,0.5/2,1.7/2,0.25/2) 
PositionMesh(PlayerMesh,0,1.7/2,0) 
EntityColor(PlayerMesh,000,000,125) 
PositionEntity(PlayerMesh,EntityX(PlayerCollider,True),EntityY(PlayerCollider,True)-0.25,EntityZ(PlayerCollider,True)) 
EntityParent(PlayerMesh,PlayerCollider,True) 

ViewMode = CFirstPerson

PositionEntity(PlayerCollider,5,0.25+0.01,5)

Local PlayerColliderYaw:Float = 0
Local PlayerEyesPitch:Float = 0
Local PlayerIsOnGround:Int = 0

Local PlayerVX:Float = 0
Local PlayerVZ:Float = 0
Local PlayerVY:Float = 0
Local PlayerOldX:Float = 0
Local PlayerOldZ:Float = 0
Local PlayerNewX:Float = 0
Local PlayerNewZ:Float = 0
Local x_speed:Int
Local y_speed:Int
Local DirectLight:TLight = CreateLight(1) 
LightColor(DirectLight,125,125,125) 
PositionEntity(DirectLight,0,128.0,-128.0) 
RotateEntity(DirectLight,45,0,0) 
AmbientLight(063,063,063)

Collisions(GroupCharacters,GroupEnvironment,2,3)

While(Not KeyHit(KEY_ESCAPE) Or AppTerminate())  

 Local MXSpeed:Float = MouseXSpeed() 
 Local MYSpeed:Float = MouseYSpeed()  

    x_speed=((MouseX()-320)-x_speed)/8+x_speed
    y_speed=((MouseY()-240)-y_speed)/8+y_speed
 MoveMouse(320,240)'GraphicsWidth()/2,GraphicsHeight()/2) 
 PlayerEyesPitch = PlayerEyesPitch+y_speed
 If(PlayerEyesPitch > 89)
  PlayerEyesPitch = 89
 EndIf
 If(PlayerEyesPitch < -89)
  PlayerEyesPitch = -89
 EndIf
 PlayerColliderYaw = PlayerColliderYaw-x_speed
 RotateEntity(PlayerEyes,PlayerEyesPitch,0,0)
 RotateEntity(PlayerCollider,0,PlayerColliderYaw,0)  

 Local CollidedCollidable:TEntity = EntityCollided(PlayerCollider,GroupEnvironment)
If( Not CollidedCollidable )
  PlayerIsOnGround = False
 Else'If( CollidedCollidable <> 0 )
  PlayerIsOnGround = True
 EndIf

 If( PlayerIsOnGround = False )
  'PlayerVY = PlayerVY - 0.0025
  TranslateEntity(PlayerCollider,PlayerVX,PlayerVY,PlayerVZ) 
  If(KeyDown(KEY_W)>0)
   MoveEntity(PlayerCollider,0,0,0.01) 
  Else If(KeyDown(KEY_A)>0) 
   MoveEntity(PlayerCollider,0,0,-0.01) 
  EndIf 
  If(KeyDown(KEY_S)>0) 
   MoveEntity(PlayerCollider,-0.01,0,0) 
  Else If(KeyDown(KEY_D)>0) 
   MoveEntity(PlayerCollider,0.01,0,0) 
  EndIf
 ElseIf( PlayerIsOnGround = True )
  PlayerOldX = EntityX(PlayerCollider,True)
  PlayerOldZ = EntityZ(PlayerCollider,True)
  PlayerVY = 0 
  If(KeyDown(1)>0)
   MoveEntity(PlayerCollider,0,0,0.1) 
  Else If(KeyDown(31)>0) 
   MoveEntity(PlayerCollider,0,0,-0.1) 
  EndIf 
  If(KeyDown(2)>0) 
   MoveEntity(PlayerCollider,-0.1,0,0) 
  Else If(KeyDown(32)>0) 
   MoveEntity(PlayerCollider,0.1,0,0) 
  EndIf 
  If(KeyDown(KEY_SPACE)>0)
   PlayerVY# = 0.1
  EndIf
  PlayerNewX = EntityX(PlayerCollider,True)
  PlayerNewZ = EntityZ(PlayerCollider,True)
  PlayerVX = PlayerNewX - PlayerOldX
  PlayerVZ = PlayerNewZ - PlayerOldZ 
 EndIf

 UpdateWorld()

 If(KeyHit(KEY_TAB)>0)
  If( ViewMode = CFirstPerson )
   ViewMode = CThirdPerson
  ElseIf( ViewMode = CThirdPerson )
   ViewMode = CFirstPerson
  EndIf
 EndIf

 If( ViewMode = CFirstPerson )
  PositionEntity(Camera,EntityX(PlayerEyes,True),EntityY(PlayerEyes,True),EntityZ(PlayerEyes,True))
  RotateEntity(Camera,EntityPitch(PlayerEyes,True),EntityYaw(PlayerEyes,True),EntityRoll(PlayerEyes,True))
  MoveEntity(Camera,0,0,0.0)
 ElseIf( ViewMode = CThirdPerson )
  PositionEntity(Camera,EntityX(PlayerEyes,True),EntityY(PlayerEyes,True),EntityZ(PlayerEyes,True))
  RotateEntity(Camera,EntityPitch(PlayerEyes,True),EntityYaw(PlayerEyes,True),EntityRoll(PlayerEyes,True))
  MoveEntity(Camera,0,0,-3.0)
 EndIf

 If(KeyDown(2)>0) 
  Wireframe(True) 
 Else 
  Wireframe(False) 
 EndIf 

 'SetBuffer(BackBuffer())
 RenderWorld() 

 Flip(1) 

Wend

End
doing it this way the it spins the camera.

does anyone know how to resolve this?
im still interested in oldschool app/gamedev

Midimaster

What the hell are you trying to do? You need a ton of codelines (which you do not understand) to get non-results like this above....

Your Mouse is nowhere connected to the camera. The strange behavior you can observe, does not come from MxSpeed. You do not use this variable in context of entities or camera! So why do you define it?

And what did youi think, when you wrote this nonsense code line:
x_speed=((MouseX()-320)-x_speed)/8+x_speedDo you have any idea, what it should do? Or did you only paste it from anywhere?


Your both viewmodes do exactly the SAME!!! So why two modes?

This cannot work in BlitzMax:
  If(KeyDown(1)>0)
BlitzMax needs a KEY_CODE instead of a 1 and TRUE instead of >0


This is the same problem: Both IF-branches react on the SPACE key
  Else If(KeyDown(32)>0)
   MoveEntity(PlayerCollider,0.1,0,0)
  EndIf
  If(KeyDown(KEY_SPACE)>0)
   PlayerVY# = 0.1
  EndIf

STOP PASTING code lines you do not understand. START thinking about step-by-step solutions. DEVELOPE a first simple system that works without any foreign code line, then expand your code to the next step by writing new lines. Always test the game before you add the next!!!

Why did you add a COLLISION already in the camera test code? Is it necessary for the camera movement? NO!

Your whole code is a ugly conglomeration of unnecessary code lines.


You have not yet managed to describe in words how the camera should move. So how would you be able to code it?
And dont tell me: The camera should move like in "blablabla"-game. That is not a scientific description!
I can see that you desperately try to connect the camera view to the actors eyes. But as long as we do not exactly know how you wish the camera to work, we cannot help you.

and you do not respond on our questions and do not give feedback on our code examples. What is so wrong with my example in post #15? You don't say any word about it. So how should I know, what you really want?


Another point:
How will you investigate a camera movement and turnament if you have no test sourrounding? you need a mini-world of cubes or lines to not loose orientation when moving the player or the camera. Have a look on my example in post #15. I gave you a mini-world, where you will not loose orientation.


Lets again start with your headline:

"Can someone walk me through creating third person camera movement with mouse?"

Do you reallly plan to create a camera movement related to the mouse?
Or do you plan to create a camera turning related to the mouse?


...back from Egypt

William

@Midimaster i would still have the issue of the above code regardless of how i am expressing it. umm.. okay may be we can work this out together. is there anything wrong with referencing other code?
im still interested in oldschool app/gamedev

Naughty Alien

@ William
..out of curiosity, which bit of 3rd person code i have shared, doesnt work?

Midimaster

It looks like your calculation of the centered Mouse fails. In the very first moment the adding is extremly high, because the mouse moves to the center and this is resulting in an extremly high x_speed. The same with y_speed. Print out both values and you will see


Here is a test code for the behavoir:
You can see that the first moment escalates the values:

Code (vb) Select
' MouseSpeed TEST with or without StartCenterMouse
Graphics 600,400
Global xArc:Float, x_speed:Float

Repeat
    Print "Mouse=" + MouseX() + "    Direction=" + xArc + " Speed=" + x_speed
    x_speed = MouseX()-300
    xArc = xArc + x_speed
    MoveMouse 300,200
    Delay 100
    Flip 1
Until KeyHit(KEY_ESCAPE) Or AppTerminate()

results:
Building untitled2
[ 98%] Processing:untitled2.bmx
[ 99%] Compiling:untitled2.bmx.gui.release.win32.x86.c
[100%] Linking:untitled2.exe
Executing:untitled2.exe
Mouse=0    Direction=0.000000000 Speed=0.000000000
Mouse=300    Direction=-300.000000 Speed=-300.000000
Mouse=300    Direction=-300.000000 Speed=0.000000000
Mouse=300    Direction=-300.000000 Speed=0.000000000

To prevent this you need a first Mouse-Call without setting x_speed outside of the Main-Loop:

' MouseSpeed TEST with or without StartCenterMouse
Graphics 600,400
Global xArc:Float, x_speed:Float

StartCenterMouse()   ' <---- THIS HEALS THE PROBLEM

Repeat
    Print "Mouse=" + MouseX() + "    Direction=" + xArc + " Speed=" + x_speed
    x_speed = MouseX()-300
    xArc = xArc + x_speed
    MoveMouse 300,200
    Delay 100
    Flip 1
Until KeyHit(KEY_ESCAPE) Or AppTerminate()


Function StartCenterMouse()
    MoveMouse 300,200
    Delay 33
    MouseXSpeed()
    HideMouse
End Function

Now it start as wished:
Building untitled2
[ 98%] Processing:untitled2.bmx
[ 99%] Compiling:untitled2.bmx.gui.release.win32.x86.c
[100%] Linking:untitled2.exe
Executing:untitled2.exe
Mouse=301    Direction=0.000000000 Speed=0.000000000
Mouse=302    Direction=1.00000000 Speed=1.00000000
Mouse=300    Direction=3.00000000 Speed=2.00000000
Mouse=301    Direction=3.00000000 Speed=0.000000000
...back from Egypt

William

Quote from: Naughty Alien on May 16, 2023, 07:57:45@ William
..out of curiosity, which bit of 3rd person code i have shared, doesnt work?
i'll try it, what is object_horizontal and object_vertical?
edit: Nevermind.
im still interested in oldschool app/gamedev

William

Okay i have it how i want it kind of.

'main program
Strict

Framework openb3d.b3dglgraphics

Graphics3D 800,600, 0, 3

Include "player.bmx"
Include "camera.bmx"
Include "createTerrain.bmx"
Include "CameraFunctions.bmx"

' Light the world, todo;maybe put the lighting in bmx zone file. for now it is in main.
Local light:TLight=CreateLight()
RotateEntity light,90,0,0


 Repeat

    If KeyDown( KEY_RIGHT )=True Then TurnEntity Pivot,0,-1,0
    If KeyDown( KEY_LEFT )=True Then TurnEntity Pivot,0,1,0
    If KeyDown( KEY_DOWN )=True Then MoveEntity Pivot,0,0,-1
    If KeyDown( KEY_UP )=True Then MoveEntity Pivot,0,0,1
    If KeyDown( key_W )=True Then MoveEntity Pivot,0,1,0
    If KeyDown( key_S )=True Then MoveEntity Pivot,0,-1,0


CameraFunction()

'PositionEntity camera,x#,terra_y#,z#

   
    UpdateWorld
    RenderWorld
    Flip 1

'Text 0,0,"Use cursor keys to move about the terrain"

Flip


Until AppTerminate() Or KeyHit(KEY_ESCAPE)
'camera-
Global camera:TCamera=CreateCamera(Pivot)
Global x_speed:Float
Global y_speed:Float
Global cameracontrol:Int = False
PositionEntity( Camera, 0.3, 2, -2.5 )
CameraRange( Camera, 0.1, 100 )
Function CameraFunction()
If (KeyHit(KEY_TAB) And cameracontrol = False) Then cameracontrol = True
If KeyHit(KEY_TAB) And cameracontrol = True Then cameracontrol = False
If (cameracontrol = True)
Text 0,0,"camera control = true"
    x_speed = ((MouseX()-GraphicsWidth()/2)-x_speed)/8+x_speed
    y_speed = ((MouseY()-GraphicsHeight()/2)-y_speed)/8+y_speed
    MoveMouse (GraphicsWidth()/2,GraphicsHeight()/2)
    TurnEntity Pivot, 0, -x_speed , 0
    TurnEntity Pivot, 0, +y_speed , 0
    Else Text 0,0,"cameracontrol = false"
EndIf
End Function

(player.bmx)
' load player mesh
Local Player:TMesh=LoadAnimMesh("Media/models/Player/player.b3d")
ScaleEntity Player,1,1,1
Global Pivot:TPivot=CreatePivot()
EntityParent Player, Pivot



I do not know why but after tab is pressed and i press it again cameracontrol remains true. Also i haven't discovered how to get the player to point the cameras direction and im also not sure how to move the pivot in the direction the camera is facing (Yet)
im still interested in oldschool app/gamedev

Midimaster

you cannot check KeyHit(KEY_TAB) twice! If KeyHit was pressed it will be detected in the first line. This removes the keypress from the keys buffer. So a second call will fail

this would work:
If (KeyHit(KEY_TAB)
    If cameracontrol = False Then cameracontrol = True
    If cameracontrol = True  Then cameracontrol = False
Endif
If (cameracontrol = True)
   Text 0,0,"camera control = true"
Else
   Text 0,0, "camera control = true"
EndIf


In your CameraFunction() code you do not turn the camera, but the pivot. This means, that also the player is already looking into the same direction the camera looks. So if you want to move in this direction you simply do it with
MoveEntity Pivot,0,0,1

If you only want to turn the camera but the player should still stand in the old direction, you should only use:

If (cameracontrol = True)
    Text 0,0,"camera control = true"
    x_speed = ((MouseX()-GraphicsWidth()/2)-x_speed)/8+x_speed
    y_speed = ((MouseY()-GraphicsHeight()/2)-y_speed)/8+y_speed
    MoveMouse (GraphicsWidth()/2,GraphicsHeight()/2)
   
    ' looking left/right:
    TurnEntity Camera, 0, x_speed , 0

    ' looking up/down
    TurnEntity Camera, yspeed, 0 , 0
Else
    Text 0,0,"cameracontrol = false"
    RotateEntity Camera,0,0,0   ' RESETs the camera !!!
EndIf

After this change the camera can do different things than the player. If you now switch off cameracontrol mode you need to reset the camera


...back from Egypt

William

Right on, got the camera system working as i want it, i published the code to my github project zarosath/BlitzKingdoms Camera.bmx

so this has been RESOLVED. Next i need to work on animations & collisions so it may have basic player stuff setup.

Thank you @Midimaster
im still interested in oldschool app/gamedev

Midimaster

Related to your P.M....

Very simple Model Of Gravity

Here is a very simple model of gravity. It is based on simply adding downwards energy to any ySpeed. You can use it in 2D and 3D with any entity. You can adjust it to simulate any kind of realistic (earth) or fantasy (planet) gravity. Also the floors ability of reversing the energy (trampolin effect) is adjustable. Also the video motion time (Slow-Motion-Effect) can be set.

Gravity.gif

SuperStrict
' simple gravity example

Graphics 800,600

Const GRAVITY:Float = 0.1   ' the worlds gravity         lower= less gravity
Const ELASTIC:Float = 0.8   ' the floor's elastic factor 0 = no trampolin effect
Const ENERGY :Float = 7     ' the initital energy (by a jump, or by a shoot)
Const MOTION :Int   = 10    ' the video speed            higher =  Slow Motion

Global YSpeed:Float  ' the ball's y-speed positiv=rises up, negativ=falling down

Global ballX:Float, ballY:Float, ballTimer:Int
Repeat
Cls
If KeyHit(KEY_SPACE)
ySpeed = ENERGY
ballX  = 50
EndIf
CalculateBall
SetColor 0,255,0
DrawLine 0,500,800,500
DrawText "Press SPACE to kick the balls into the sky", 100,100
SetColor 255,0,0
DrawOval 30, 490-ballY,10,10
SetColor 255,255,0
DrawOval ballX, 490-ballY,10,10
Flip 0
Until AppTerminate() 



Function CalculateBall()
If ballTimer<MilliSecs()
ballTimer = MilliSecs() + MOTION
ySpeed   = ySpeed - GRAVITY
ballY  = ballY + ySpeed
ballx  = ballX + 1
If ballY<0
  ballY=0
  YSpeed   = -YSpeed*ELASTIC
EndIf
EndIf
End Function
...back from Egypt

William

Quote from: Midimaster on May 18, 2023, 00:38:18Related to your P.M....

Very simple Model Of Gravity

Here is a very simple model of gravity. It is based on simply adding downwards energy to any ySpeed. You can use it in 2D and 3D with any entity. You can adjust it to simulate any kind of realistic (earth) or fantasy (planet) gravity. Also the floors ability of reversing the energy (trampolin effect) is adjustable. Also the video motion time (Slow-Motion-Effect) can be set.

Gravity.gif

SuperStrict
' simple gravity example

Graphics 800,600

Const GRAVITY:Float = 0.1   ' the worlds gravity         lower= less gravity
Const ELASTIC:Float = 0.8   ' the floor's elastic factor 0 = no trampolin effect
Const ENERGY :Float = 7     ' the initital energy (by a jump, or by a shoot)
Const MOTION :Int   = 10    ' the video speed            higher =  Slow Motion

Global YSpeed:Float  ' the ball's y-speed positiv=rises up, negativ=falling down


        ySpeed   = ySpeed - GRAVITY
        ballY  = ballY + ySpeed
        ballx  = ballX + 1
End Function

i grasp that part but for some reason
Local WhoCollided:TEntity = EntityCollided(pivot,GroupEnvironment)isnt registering collision with the terrain, i dont know if it is because it's position is at 0,0,0 same as terrain (at least i think but not sure)
im still interested in oldschool app/gamedev

Midimaster

Did you both add to GroupEnviroment? The pivot and the terrain?


How I would search for the bug:

Create a new app in a separate code with only a cube and a plane to learn. Does it collide? Then replace the plane with your terrain and test again, then replace the cube with your player...
...back from Egypt

William

alright i am working on collision and so i wanted to move the player entity more onto the terrain instead of 0,0,0 in case, for debug purposes.

but its bugged, MoveEntity(pivot,14,0.1,-15) the player is far from the camera however it works correctly when If KeyDown( KEY_UP )=True Then MoveEntity Pivot,0,0,1
i dont know if it is related to collisions
i will investigate later however i posted in case you have insight about this.

i have updated github with this so you can look at it and maybe test it. https://github.com/zarosath/blitzKingdoms
im still interested in oldschool app/gamedev