Показать сообщение отдельно
Старый 06.10.2011, 15:47   #8
H@NON
Дэвелопер
 
Регистрация: 17.01.2007
Сообщений: 1,552
Написано 351 полезных сообщений
(для 774 пользователей)
Ответ: Как я делал перемещение физического игрока и все работает

многие почему-то не могут сделать нормального перемещения для игрока. Специально для них привожу код.

Function AddHero(x#,y#,z#,yaw#=0)
    H.HeroT = New HeroT
    H\model = xCreateCube()
    xScaleMesh H\model, 1, 2, 0.5
    H\mass = 50
    H\radius = 1.0
    H\height = 2
    ;создаем физическую оболочку в виде капсулы
    xEntityAddCapsuleShape(H\model, H\mass, H\radius, H\height)
    ;делаем слегка трение модельке
    xEntitySetFriction(H\model,0.5)
    ;запрещаем поворачиваться модельке кроме оси Y
    xEntitySetAngularFactor(H\model, 0, 1.0, 0)
    ;убираем инерцию поворота, чтобы моделька подчинялась только нашему контролю
    xEntitySetDamping(H\model, 0, 1)
    
    xPositionEntity H\model, x, y, z
    xRotateEntity H\model, 0, yaw, 0
    ;Вспомогательный пивот для расчетов. Мне так удобнее
    helpPivot = xCreateCube(H\model)
    xScaleMesh helpPivot, 2, 0.1, 2
End Function

Function ControlHero()
    Local smoothYaw# = 0.5            ;смягчающий коэффициент поворота
    Local moveForce# = 1000            ;усилие для движения
    Local maxJump# = 50                ;максимальная скорость прыжка
    Local maxSpeed# = 20                ;макс скорость перемещения
    Local moveX#, moveZ#, jump#
    Local collCnt, collNum
    Local InGround = False                        ;указывает на земле ли моделька
    Local nx#,ny#,nz#, collEnt, nCount
    Local dYaw#
    
    collCnt = xEntityCountContacts(H\model)
    
    ;Если коллизия произошла
    If collCnt > 0 Then
        For collNum = 0 To collCnt-1
            ;Если коллизия произошла с ногами
            If xEntityGetContactY(H\model, collNum) < xEntityY(H\model,1) - H\height*0.5 Then
                ;моделька на земле
                InGround = True
                ;расчет вектора наклона земли под моделькой
                collEnt = xEntityGetContact(H\model, collNum)
                nx = nx + xEntityGetContactNX#(collEnt, collNum)
                ny = ny + xEntityGetContactNY#(collEnt, collNum)
                nz = nz + xEntityGetContactNZ#(collEnt, collNum)
                nCount = nCount + 1
            EndIf
        Next
        nx = nx / nCount
        ny = ny / nCount
        nz = nz / nCount
    EndIf
    
    ;поворот модельки мышкой
    H\Yaw = H\Yaw-mxs*smoothYaw
    xRotateEntity H\model, 0, H\Yaw, 0
    
    If InGround Then
        ;вырубаем гравитацию. Так меньше глюков
        xEntitySetGravity(H\model, 0, 0, 0)
        
        ;Если двигаемся по диагонали то уменьшить равномерно силы
        If (kdRight - kdLeft)<>0 And (kdUp - kdDown)<>0 Then maxSpeed = maxSpeed * 0.75
        
        ;сила перемещения модельки
        moveX = (kdRight - kdLeft) * (maxSpeed - Abs(xEntityGetLinearVelocityX(H\model, False))) * moveForce
        moveZ = (kdUp - kdDown) * (maxSpeed - Abs(xEntityGetLinearVelocityZ(H\model, False))) * moveForce
        
        ;поворачиваем пивот параллельно земли под моделькой
        xAlignToVector helpPivot, nx, ny, nz, 2
        dYaw = AngleDiff(xEntityYaw(helpPivot,1), xEntityYaw(H\model,1))
        xTurnEntity helpPivot, 0, dYaw, 0
        If Abs(xEntityPitch(helpPivot,1)) > 45 Then
            xRotateEntity helpPivot, 45*Sgn(xEntityPitch(helpPivot,1)), xEntityYaw(helpPivot,1), xEntityRoll(helpPivot,1), True
            xEntitySetGravity(H\model, 0, -20, 0)
        EndIf
        If Abs(xEntityRoll(helpPivot,1)) > 45 Then
            xRotateEntity helpPivot, xEntityPitch(helpPivot,1), xEntityYaw(helpPivot,1), 45*Sgn(xEntityRoll(helpPivot,1))
            xEntitySetGravity(H\model, 0, -20, 0)
        EndIf
        
        xTformVector moveX, 0, moveZ, helpPivot, 0
        
        ;применяем силы перемещения на модельку
        xEntityApplyCentralForce(H\model, xTFormedX(), 0, xTFormedZ(), True)
        ;если хотим прыгать - прыгаем
        If khSpace Then xEntitySetLinearVelocity(H\model, xEntityGetLinearVelocityX(H\model), maxJump, xEntityGetLinearVelocityZ(H\model))
        
        ;торможение модельки если не хотим идти
        If moveX = 0  Then xEntityApplyCentralForce(H\model, -xEntityGetLinearVelocityX(H\model, False)*moveForce, 0, 0, False)
        If moveZ = 0 Then xEntityApplyCentralForce(H\model, 0, 0, -xEntityGetLinearVelocityZ(H\model, False)*moveForce, False)
    Else
        ;снова включаем гравитацию модельке
        xEntitySetGravity(H\model, 0, -100, 0)
        
        ;это чтобы слегка контролировать движение в воздухе для казуальности
        moveX = (kdRight - kdLeft) * (maxSpeed - Abs(xEntityGetLinearVelocityX(H\model, False))) * moveForce * 0.1
        moveZ = (kdUp - kdDown) * (maxSpeed - Abs(xEntityGetLinearVelocityZ(H\model, False))) * moveForce * 0.1
        xEntityApplyCentralForce(H\model, moveX, 0, moveZ, False)
    EndIf
End Function
(Offline)
 
Ответить с цитированием
Эти 3 пользователя(ей) сказали Спасибо H@NON за это полезное сообщение:
CRASHER (10.10.2011), LLI.T.A.L.K.E.R. (09.10.2011), St_AnGer (10.10.2011)