Свободная камера

Published
» Способ реализации: vJass
» Тип: Наработка
» Версия Warcraft: 1.26, 1.27a, 1.27b, 1.28f
Свободная камера с поворотом на мышь и перемещением на wasd. Что-то вроде фоторежима в ААА играх.

Для поворота, нужно зажать ПКМ и отвести курсор в сторону.
Для перемещения в пространстве, нужно зажать одну из кнопок WASD.

Ограничения на тангаж нет
Можно сделать сальто или не докрутить и оставить камеру в перевернутом положении.
Это можно исправить, изменением крена при определенном тангаже
Но при таком перевороте, управление тангажом инвертируется.
Тоже можно исправить, инвертируя тангаж вместе с изменением крена,
Но тогда, при превышении тангажа, крен изменится на противоположное, тангаж инвертируется.
Курсор продолжает перемещаться вверх, тем самым превышая тангаж > пункт выше
Не верится, но это тоже можно исправить, инвертирую тангаж только при отпускании ПКМ
Я эти все пункты проверил, но все вырезал, только мешает.

Столкновение с рельефом

Использование
- Скачиваем пример
- Скачиваем мемхак (Любой подойдет (Если не ошибаюсь))
- Думаем, где это пригодится
- Так как это изменение камеры, можно спокойно загнать это все в условие GetLocalPlayer()
- И вообще сделать все управление на фреймах
» Код
globals
    
    real RotateSensitivityX = .1
    real RotateSensitivityY = .1
    real DistanceOnTime = 7
    
    real CurX = 0
    real CurY = 0
    
    real CamX
    real CamY
    real CamZ
    
    camerasetup cmr
    
endglobals

function RAbs takes real r returns real 
    
    if r < 0 then
        set r =  r * -1
    endif
    
    return r 
endfunction

function GetPointZ takes real x, real y returns real 
    local location loc = Location(x, y)
    local real z = GetLocationZ(loc)
    call RemoveLocation(loc)
    set loc = null
    return z
endfunction

function Trig_Rotation_Actions takes nothing returns nothing
    
    local real x = GetCursorX()
    local real y = GetCursorY()
    
    local real pitch = CameraSetupGetField(cmr, CAMERA_FIELD_ANGLE_OF_ATTACK) * bj_DEGTORAD
    local real yaw   = CameraSetupGetField(cmr, CAMERA_FIELD_ROTATION) * bj_DEGTORAD
    local real roll  = CameraSetupGetField(cmr, CAMERA_FIELD_ROLL) * bj_DEGTORAD
    
    local real sensaX = RAbs(RotateSensitivityX * (x - CurX))
    local real sensaY = RAbs(RotateSensitivityY * (y - CurY))

    call CameraSetupApply(cmr, true, false)
    //
    // ChangeRotation
    //

    if IsKeyPressed (0x02) then
        if CurX > x then
            call CameraSetupSetField(cmr, CAMERA_FIELD_ROTATION, CameraSetupGetField(cmr, CAMERA_FIELD_ROTATION) + sensaX, 0)
            // Ограничения на + вроде нет, но я перестраховался
            if CameraSetupGetField(cmr, CAMERA_FIELD_ROTATION) >= 350 then
                call CameraSetupSetField(cmr, CAMERA_FIELD_ROTATION, 360 - CameraSetupGetField(cmr, CAMERA_FIELD_ROTATION), 0)
            endif
        endif
        if CurX < x then
            call CameraSetupSetField(cmr, CAMERA_FIELD_ROTATION, CameraSetupGetField(cmr, CAMERA_FIELD_ROTATION) - sensaX, 0)
            // Ограничение - >0  
            if CameraSetupGetField(cmr, CAMERA_FIELD_ROTATION) <= 10 then
                call CameraSetupSetField(cmr, CAMERA_FIELD_ROTATION, 360 + CameraSetupGetField(cmr, CAMERA_FIELD_ROTATION), 0)
            endif
        endif
        
        
        if CurY > y then
            call CameraSetupSetField(cmr, CAMERA_FIELD_ANGLE_OF_ATTACK, CameraSetupGetField(cmr, CAMERA_FIELD_ANGLE_OF_ATTACK) - sensaY, 0)
        endif
        if CurY < y then
            call CameraSetupSetField(cmr, CAMERA_FIELD_ANGLE_OF_ATTACK, CameraSetupGetField(cmr, CAMERA_FIELD_ANGLE_OF_ATTACK) + sensaY, 0)
        endif
        
    endif
    
    set CurX = x
    set CurY = y
    
    //
    //  Change Position
    //
    
    if IsKeyPressed(0x57) then // W_KEY
        set CamX = CameraSetupGetDestPositionX(cmr) + DistanceOnTime * Cos(pitch) * Cos(yaw)
        set CamY = CameraSetupGetDestPositionY(cmr) + DistanceOnTime * Sin(yaw) * Cos(pitch)
        set CamZ = (CameraSetupGetField(cmr, CAMERA_FIELD_ZOFFSET) - DistanceOnTime * Sin(pitch - 3.14))
    endif
    if IsKeyPressed(0x53) then // S_KEY
        set CamX = CameraSetupGetDestPositionX(cmr) + DistanceOnTime * Cos(pitch - 3.14) * Cos(yaw)
        set CamY = CameraSetupGetDestPositionY(cmr) + DistanceOnTime * Sin(yaw) * Cos(pitch - 3.14)
        set CamZ = (CameraSetupGetField(cmr, CAMERA_FIELD_ZOFFSET) - DistanceOnTime * Sin(pitch))
    endif
    if IsKeyPressed(0x41) then // A_KEY
        set CamX = CameraSetupGetDestPositionX(cmr) + DistanceOnTime * 0.5 * Cos(roll) * Cos(yaw + 1.57)
        set CamY = CameraSetupGetDestPositionY(cmr) + DistanceOnTime * 0.5 * Sin(yaw + 1.57) * Cos(roll)
        set CamZ = (CameraSetupGetField(cmr, CAMERA_FIELD_ZOFFSET) - DistanceOnTime * 0.7 * Sin(roll)) 
    endif
    if IsKeyPressed(0x44) then // D_KEY
        set CamX = CameraSetupGetDestPositionX(cmr) + DistanceOnTime * 0.5 * Cos(roll) * Cos(yaw - 1.57)
        set CamY = CameraSetupGetDestPositionY(cmr) + DistanceOnTime * 0.5 * Sin(yaw - 1.57) * Cos(roll)
        set CamZ = (CameraSetupGetField(cmr, CAMERA_FIELD_ZOFFSET) - DistanceOnTime * 0.5 * Sin(roll)) 
    endif
    
    // Ограничение высоты
    if CamZ > GetPointZ(CamX, CamY) + 1000 then
        set CamZ = 1000
    elseif CamZ < GetPointZ(CamX, CamY) + 30 then
        set CamZ = GetPointZ(CamX, CamY) + 30
    endif
    
    // call BJDebugMsg(R2S(GetPointZ(CamX, CamY) + 30) + " - " + R2S(CameraSetupGetField(cmr, CAMERA_FIELD_ZOFFSET)))
    
    call CameraSetupSetDestPosition(cmr, CamX, CamY, 0)
    call CameraSetupSetField(cmr, CAMERA_FIELD_ZOFFSET, CamZ, 0) 
endfunction

//===========================================================================
function InitTrig_FreeCamera takes nothing returns nothing
    set gg_trg_FreeCamera = CreateTrigger(  )
    
    set cmr = gg_cam_cmr
    call CameraSetupSetField(cmr, CAMERA_FIELD_TARGET_DISTANCE, 0, 0)
    call SetSkyModel( "Environment\\Sky\\DalaranSky\\DalaranSky.mdl" )
    
    call TriggerRegisterTimerEventPeriodic( gg_trg_FreeCamera, 0.01 )
    call TriggerAddAction( gg_trg_FreeCamera, function Trig_Rotation_Actions )
endfunction


Views: 162

Bergi_Bear #1 - 1 month ago 0
Голосов: +0 / -0
А можно ли колесо задействовать отдаление/приближение?
ofeerist #2 - 1 month ago (изм. ) 0
Голосов: +0 / -0
Bergi_Bear:
А можно ли колесо задействовать отдаление/приближение?
Нет, не могу отловить прокручивание колесика мыши.
Вот, все кнопки, которые возможно использовать.
Bergi_Bear #3 - 1 month ago 0
Голосов: +0 / -0
Если судить по рефорджу, есть событие колеса на фрейме ползунке, мы правда не знаем направление Mouse_wheel_event направление, но всё же может это можно как -то использовать. Только придётся сделать фрейм на весь экран, чтобы ловить колёсико в любом месте