Author Topic: RPG камера с движением персонажа  (Read 1194 times)

0 Members and 1 Guest are viewing this topic.

Offline Alec - WS3D Developer

  • Producer
  • Administrator
  • Marquess
  • *
  • Posts: 911
  • Reputation 36
  • Game making is my hobby for life!
RPG камера с движением персонажа
« on: November 13, 2014, 09:12:25 PM »
RPG камера с движением персонажа

Во многих играх есть упрвление персонажем с камерой от 3-го лица.
Как это реализовано в примере? Как обычно:
1.. Камера направлена на персонаж, которым управляет игрок;
2.. Игрок кликает на какое-либо место на земле (террейне), куда он хочет. чтобы персонаж переместился;
3.. Когда игрок кликает на какое-либо место на земле, появляется метка - куда перемещается персонаж.

Up/Down - увеличение/уменьшение камеры
Left/Right - вращение камеры

Code: [Select]
'' Example: RPG camera with Actor Movement
'' by Frank Dodd
'' Adapted Alex Artifex
'' Short description:
'-- 1. the camera is looking at player character
'-- 2. player clicks on the ground to move to that location
'-- 3. a mark appears at the clicked location to show where the charater is going.

    ' headers
    #include "WorldSim3D.bi"


    ' this enumeration describes what the player is currently doing
    enum PlayerActions
        Player_Stopped
        Player_Moving
    end enum


    ' VARIABLES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ' the camera position
    DIM as single CameraX, CameraZ
    ' the camera angle rotated around the player and distance from the player
    DIM as single CameraAngle = 0.0, CameraDistance = 300.0
    ' the distance the camera will rotate and zoom in the next frame
    DIM as single CameraRotate = 0.0, CameraZoom = 0.0

    ' the players position (start them in the middle of the map)
    DIM as single PlayerX = 2500.0, PlayerY = 0.0, PlayerZ = 2500.0
    ' the distance the player will move in the next frame
    DIM as single MoveX, MoveZ
    ' the action the playing is carrying out
    DIM as PlayerActions PlayerAction = Player_Stopped

    ' the node the player clicked on
    DIM as wNode ClickedNode
    ' the position the player clicked
    DIM as single ClickX, ClickY, ClickZ
    ' not used in this demo. but the angle of the surface at the click
    DIM as single NormalX, NormalY, NormalZ
    ' the start and end positions of a line used to detect collisions
    DIM as wVECTOR rayStart, rayEnd

    ' pointers to keyboard events and mouse events
    DIM KeyEvent as wKEY_EVENT PTR
    DIM MouseEvent as wMOUSE_EVENT PTR
Dim BitmapFont as wFont


    ' START THE PROGRAM ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ' start the interface
    'limit the frame rate and capture keyboard and mouse events
    wStart( wDT_OPENGL, 800, 600, wBITS_PER_PIXEL_32, _
            wWINDOWED, wSHADOWS, wCAPTURE_EVENTS, wVERTICAL_SYNC_ON )

    ' set the window title
    wSetWindowCaption( "DEMO: Third Person Camera, Click and Move" )
BitmapFont = wGetFont ( "../media/Fonts/myfont4.png" )

    ' PLAYER SETUP ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ' load the 3D model for the player
    DIM as wMesh Mesh = wGetMesh( "../Media/Models/Characters/Blade/Blade.md2" )

    if Mesh = 0 then
        Print "Missing File (are you running from the WS3D directory?"
        End
    endif

    ' load the paint job for the 3D model
    DIM as wTexture Texture = wGetTexture( "../Media/Models/Characters/Blade/Blade.jpg" )

    ' add the 3D model to the scene as an object we can see
    DIM as wNode PlayerNode = wAddMeshToScene( Mesh )

    ' paint the object and turn off lighting
    wSetNodeMaterialTexture( PlayerNode, Texture, 0 )
    wSetNodeMaterialFlag( PlayerNode, wMF_LIGHTING, wOFF )

    ' put zumlin into the stand animation loop
    wPlayNodeMD2Animation( PlayerNode, wMD2_STAND )


    ' CLICK OBJECT SETUP ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ' we are going to do this in a very simple way by using a cube, you should
    ' really create a flat rectangle in a 3D package and use that instead.
    DIM as wNode ClickNode = wAddTestSceneNode
    wSetNodeScale( ClickNode, 5.0, 0.1, 5.0 )

    ' load the paint job for the click node
    Texture = wGetTexture( "../media/Textures/beam.png" )

    ' paint the object and turn off lighting
    wSetNodeMaterialTexture( ClickNode, Texture, 0 )
    wSetNodeMaterialFlag( ClickNode, wMF_LIGHTING, wOFF )
    wSetNodeMaterialType( ClickNode, wMT_TRANSPARENT_ALPHA_CHANNEL )


    ' TERRAIN SETUP ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ' create the terrain
    DIM as wNode Terrain = wAddTerrain( "../media/Heightmaps/terrain-heightmap.bmp" )

    ' scale it up a bit but leave it quite flat
    wSetNodeScale( Terrain, 40.0, 1.0, 40.0 )

    ' load and set the terrain color
    Texture = wGetTexture( "../media/Textures/surface.jpg" )
    wSetNodeMaterialTexture( Terrain, Texture, 0 )

    ' load and set the terrain detail
    Texture = wGetTexture( "../media/Textures/detailmap3.jpg" )
    wSetNodeMaterialTexture( Terrain, Texture, 1 )

    ' repeat the detail map a lot so it looks detailed!
    wScaleTerrainDetailTexture( Terrain, 1.0, 60.0 )

    ' set up the material and lighting
    wSetNodeMaterialFlag( Terrain, wMF_LIGHTING, wOFF )
    wSetNodeMaterialType( Terrain, wMT_DETAIL_MAP )


    ' COLLISION SETUP ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ' as we want to pick a location on the ground to move too we need to set up
    ' collision for the ground so we can detect when things hit it.
    ' First we create a collision object from the ground
    DIM as wSelector terrainCollision = _
            wGetCollisionGroupFromTerrain ( Terrain, 1 )

    ' then we attach that collision object to the ground
    wSetNodeTriangleSelector( Terrain, terrainCollision )


    ' CAMERA SETUP ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ' add a camera that we can control ourselves
    DIM as wNode Camera = wAddCamera( 0.0,0.0,0.0, 0.0,0.0,0.0 )

    ' show stuff in the distance
    wSetCameraClipDistance( Camera, 12000 )


    ' MAIN LOOP ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ' while WS3D is running
    WHILE wRunning
        ' clear the screen with blue
        wBeginScene( 240, 255, 255 )

       ' if there is an WS3D key press available ~~~~~~~~~~~~~~~~~~~~~~~~~
        while wKeyEventAvailable

            ' read the key press
            KeyEvent = wReadKeyEvent

            ' handle the key press
            select case as const KeyEvent->key
            case KEY_LEFT
                if KeyEvent->direction = wKEY_DOWN then
                    ' the LEFT key was pushed down
                    CameraRotate = -0.02
                else
                    ' the LEFT key is being released
                    CameraRotate = 0.0
                endif

            case KEY_RIGHT
                if KeyEvent->direction = wKEY_DOWN then
                    ' the RIGHT key was pushed down
                    CameraRotate = 0.02
                else
                    ' the RIGHT key is being released
                    CameraRotate = 0.0
                endif

            case KEY_UP
                if KeyEvent->direction = wKEY_DOWN then
                    ' the UP key was pushed down
                    CameraZoom = 0.75
                else
                    ' the UP key is being released
                    CameraZoom = 0.0
                endif

            case KEY_DOWN
                if KeyEvent->direction = wKEY_DOWN then
                    ' the DOWN key was pushed down
                    CameraZoom = -0.75
                else
                    ' the DOWN key is being released
                    CameraZoom = 0.0
                endif
wCloseKEY_ESC()
            end Select
        wend


        ' if there are any mouse clicks available ~~~~~~~~~~~~~~~
        while wMouseEventAvailable

            ' read the mouse event out
            MouseEvent = wReadMouseEvent

            ' if this is a mouse left button click event
            if MouseEvent->action = wME_LMOUSE_PRESSED_DOWN then
               
                ' get the 3D start and end coordinates of a ray that travels through
                ' where the mouse was clicked on the screen
                wGetRayFromScreenCoordinates ( MouseEvent->X, MouseEvent->Y, _
                        Camera, rayStart, rayEnd )
                       
                ' find out if the ray hits anything in the scene with a collision
                ' object attached to it.
                wGetNodeAndCollisionPointFromRay ( _
                        rayStart, rayEnd, _
                        ClickedNode, _
                        ClickX, ClickY, ClickZ, _
                        NormalX, NormalY, NormalZ )

                ' if the click hit something
                if NOT ClickedNode = wNO_OBJECT then

                    ' Put the click node at the clicked location
                    wSetNodeVisibility( ClickNode, wVISIBLE )
                    wSetNodePosition( ClickNode, ClickX, ClickY+5.0, ClickZ )

                    ' calculate the X and Z distances from the player to the click
                    DIM as single DistanceX = ClickX - PlayerX
                    DIM as single DistanceZ = ClickZ - PlayerZ
                   
                    ' use a little math to calculate the straight line distance
                    DIM as single Distance = sqr( DistanceX*DistanceX + DistanceZ*DistanceZ )
                   
                    ' calculate the number of steps zumlin has to take to cover the
                    ' distance. (Zumlin run animation moves about 5.0 units a step)
                    DIM as single Steps = Distance / 5.0
                   
                    ' we can use this to calculate how far in both the X and the Z
                    ' Zumlin should move with each step
                    MoveX = DistanceX / Steps
                    MoveZ = DistanceZ / Steps


                    ' we need to rotate zumlin to face the direction he is going to
                    ' move. again a little maths can calculate the angle for us.
                    ' the function atan2 takes the opposite and adjacent lengths of
                    ' a right angled triangle and gives us the rotation angle in
                    ' radians. we multiply this by 57.3 to convert it into degrees
                    Dim as Single angle = atan2( DistanceX, DistanceZ ) * 57.2957795

                    ' we can now use this to rotate zumlin to point in the
                    ' direction he is travelling
                    wSetNodeRotation( PlayerNode, 0.0, angle - 90.0, 0.0 )

                    ' now for zumlins animation
                    ' If zumlin was stopped
                    if PlayerAction = Player_Stopped Then
                        ' Start his moving animation
                        wPlayNodeMD2Animation( PlayerNode, wMD2_RUN )
                        PlayerAction = Player_Moving
                    End If

                end if
            endif
        wend

        ' Add the Players movement speed to its position
        PlayerX += MoveX
        PlayerZ += MoveZ

        ' if zumlin is close to his destination stop moving
        if abs(ClickX - PlayerX) < 10.0 AND abs(ClickZ - PlayerZ) < 10.0 Then
            ' stop zumlin moving
            MoveX = 0
            MoveZ = 0

            ' hide the click node
            wSetNodeVisibility( ClickNode, wINVISIBLE )

            ' If zumlin was moving
            if PlayerAction = Player_Moving Then
                ' Stop his moving animation
                wPlayNodeMD2Animation( PlayerNode, wMD2_STAND )
                PlayerAction = Player_Stopped
            End If
        End If

        ' get the height of the terrain at the players current position
        PlayerY = wGetTerrainHeight( Terrain, PlayerX, PlayerZ )
       
        ' set the position of the player
        wSetNodePosition( PlayerNode, PlayerX, PlayerY+23.0, PlayerZ )


        ' SET THE CAMERA POSITION ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        ' Our camera is going to circle around the player. So think of a circle with
        ' the player in the middle. the camera will be somwhere on the ring at the
        ' edge. two numbers will define its position: -
        ' 1) the angle it is rotated around the player (from 0 to 360 degrees)
        ' 2) size of the circle
        '
        ' change the camera angle by the amount we are rotating each frame
        CameraAngle += CameraRotate

        ' change the camera distance by the amount we are zooming each frame
        CameraDistance += CameraZoom

        ' some simple maths will give us the position of the camera: -
        CameraX = Cos( CameraAngle ) * CameraDistance + PlayerX
        CameraZ = Sin( CameraAngle ) * CameraDistance + PlayerZ

        ' finally we can set the position of the camera
        wSetNodePosition( Camera, CameraX, PlayerY+CameraDistance, CameraZ )

        ' make the camera look at the player character
        wSetCameraTarget( Camera, PlayerX, PlayerY+32.0, PlayerZ )


        ' finally draw all of our 3d objects
        wDrawScene
  w2DFontDraw ( BitmapFont, "Up/Down - zoom camera, ", 50, 560, 370, 575 )
  w2DFontDraw ( BitmapFont, "Left/Right - rotate camera", 390, 560, 690, 575 )

        ' show what we have drawn
        wEndScene
        wSetFPS
    WEND

    ' Stop WS3D and free up memory
    wStop

WorldSim3D = 3D + FreeBasic. Программируй в удовольствие, а не "в тягость"! Make your project with pleasure, not with strain!

Offline Marsha

  • Friends
  • Knight
  • *
  • Posts: 128
  • Reputation 11
Re: RPG камера с движением персонажа
« Reply #1 on: July 08, 2015, 11:10:55 AM »
У меня просьба сделать урок "вид от третьего лица", но с камерой за спиной персонажа, которая поворачивалась бы вместе с ним при повороте мыши в нужную сторону, позволяя осмотреться по сторонам, как в играх серии "Готика". Перемещение при этом обычно курсорными клавишами, либо ЛКМ - бежать. Ходовая, так сказать, камера. Думаю, не только мне пригодится  :-[ :-\

Offline it_is_good

  • Friends
  • Baron (-ess)
  • *
  • Posts: 308
  • Reputation 13
  • I'm a newbie.
Re: RPG камера с движением персонажа
« Reply #2 on: July 09, 2015, 03:16:21 PM »
Я лучше в свободное время напишу статью по камере и всем необходимым формулам, что бы разработчику самому решать, что нужно, а что нет для камеры
« Last Edit: July 10, 2015, 05:33:18 PM by it_is_good »

Offline Alec - WS3D Developer

  • Producer
  • Administrator
  • Marquess
  • *
  • Posts: 911
  • Reputation 36
  • Game making is my hobby for life!
Re: RPG камера с движением персонажа
« Reply #3 on: July 10, 2015, 08:07:25 PM »
Это хорошее дело, я бы тоже был благодарен.
WorldSim3D = 3D + FreeBasic. Программируй в удовольствие, а не "в тягость"! Make your project with pleasure, not with strain!