TheLegend
New Member
- Reaction score
- 10
Advanced Third Person Camera
by TheLegend
After i saw the system that AceHart created I decided to write my own camera system.by TheLegend
The system is easy to use, it doesn't leak or lag, and its fast
FEATURES AND INFO
JASS:
// Advanced Third Person Camera by TheLegend
// Features:
// Features:
// - The camera can be rotated
// - The distance of the camera can be reduced or increased
// - The camera avoids objects that can block your view
// - It can be switched from one unit to another
// - It can be switched on or off
// - It can adjust the height and the angle according to the terrain
// Controls:
// - Escape - Turn off or on
// - Arrow keys - Rotation and distance change
// What you need:
// - vJASS
// - No variables needed
// It doesnt leak or lag
// Just copy everything from the map header to your map
SYSTEM
Before we start with the system you need a Terrain Pathability Checker. Use this one since its the best. PS: this library isn't mine but the Camera library is
JASS:
library TerrainPathability initializer Initialization
globals
private constant real MAX_RANGE = 10.
private constant integer DUMMY_ITEM_ID = 039;wolg039;
endglobals
globals
private item Item = null
private rect Find = null
private item array Hid
private integer HidMax = 0
public real X = 0.
public real Y = 0.
endglobals
function IsTerrainDeepWater takes real x, real y returns boolean
return not IsTerrainPathable(x, y, PATHING_TYPE_FLOATABILITY) and IsTerrainPathable(x, y, PATHING_TYPE_WALKABILITY)
endfunction
function IsTerrainShallowWater takes real x, real y returns boolean
return not IsTerrainPathable(x, y, PATHING_TYPE_FLOATABILITY) and not IsTerrainPathable(x, y, PATHING_TYPE_WALKABILITY) and IsTerrainPathable(x, y, PATHING_TYPE_BUILDABILITY)
endfunction
function IsTerrainLand takes real x, real y returns boolean
return IsTerrainPathable(x, y, PATHING_TYPE_FLOATABILITY)
endfunction
function IsTerrainPlatform takes real x, real y returns boolean
return not IsTerrainPathable(x, y, PATHING_TYPE_FLOATABILITY) and not IsTerrainPathable(x, y, PATHING_TYPE_WALKABILITY) and not IsTerrainPathable(x, y, PATHING_TYPE_BUILDABILITY)
endfunction
private function HideItem takes nothing returns nothing
if IsItemVisible(GetEnumItem()) then
set Hid[HidMax] = GetEnumItem()
call SetItemVisible(Hid[HidMax], false)
set HidMax = HidMax + 1
endif
endfunction
function IsTerrainWalkable takes real x, real y returns boolean
call MoveRectTo(Find, x, y)
call EnumItemsInRect(Find ,null, function HideItem)
call SetItemPosition(Item, x, y)
set X = GetItemX(Item)
set Y = GetItemY(Item)
call SetItemVisible(Item, false)
loop
exitwhen HidMax <= 0
set HidMax = HidMax - 1
call SetItemVisible(Hid[HidMax], true)
set Hid[HidMax] = null
endloop
return (X-x)*(X-x)+(Y-y)*(Y-y) <= MAX_RANGE*MAX_RANGE and not IsTerrainPathable(x, y, PATHING_TYPE_WALKABILITY)
endfunction
private function Initialization takes nothing returns nothing
set Find = Rect(0., 0., 128., 128.)
set Item = CreateItem(DUMMY_ITEM_ID, 0, 0)
call SetItemVisible(Item, false)
endfunction
endlibrary
Now we cone to the TPC System. It doesn't leak or lag. It took me hours to complete it. Just copy it to the map header like the Pathing library
JASS:
library ThirdPersonCamera initializer Init uses TerrainPathability
globals
//How often the camera should be adjusted, 0.15 is ok
private constant real Period = 0.15
//The angle of the camera
private constant real CameraAngle = 345
//The Height of the camera
private constant real CameraHeight = 150
//The maximum and minimum distance
private constant real CameraMaxDistance = 800
private real array CameraMaxNow
private constant real CameraMinDistance = 50
//Booleans to control the options of the camera
private constant boolean CameraAllowArrows = true
private constant boolean CameraAllowEscape = true
private constant boolean CameraNotDead = true
//Dont tuch anything here
private group CameraMainUnits = CreateGroup()
private group CameraTargetUnits = CreateGroup()
private real array CameraRotate
private real array CameraDistance
private boolean array CameraLeft
private boolean array CameraRight
private boolean array CameraFront
private boolean array CameraBack
private boolean array CameraDisable
endglobals
function ATPCRemove takes unit u returns nothing
call GroupRemoveUnit(CameraTargetUnits, u)
if GetLocalPlayer() == GetOwningPlayer(u) then
call ResetToGameCamera(1.5)
endif
endfunction
private function CameraRemovePlayerMain_function takes nothing returns nothing
if GetOwningPlayer(GetEnumUnit()) == bj_forceRandomCurrentPick then
call GroupRemoveUnit(CameraMainUnits, GetEnumUnit())
call GroupRemoveUnit(CameraTargetUnits, GetEnumUnit())
endif
endfunction
private function CameraRemovePlayer_function takes nothing returns nothing
if GetOwningPlayer(GetEnumUnit()) == bj_forceRandomCurrentPick then
call GroupRemoveUnit(CameraTargetUnits, GetEnumUnit())
endif
endfunction
function ATPCRemovePlayerMain takes player p returns nothing
set bj_forceRandomCurrentPick = p
call ForGroup(CameraMainUnits, function CameraRemovePlayerMain_function)
call ForGroup(CameraTargetUnits, function CameraRemovePlayer_function)
if GetLocalPlayer() == p then
call ResetToGameCamera(1.5)
endif
endfunction
function ATPCRemovePlayer takes player p returns nothing
set bj_forceRandomCurrentPick = p
call ForGroup(CameraTargetUnits, function CameraRemovePlayer_function)
if GetLocalPlayer() == p then
call ResetToGameCamera(1.5)
endif
endfunction
function ATPCAddMainUnit takes unit u returns nothing
local player p = GetOwningPlayer(u)
call ATPCRemovePlayerMain(p)
call GroupAddUnit(CameraMainUnits, u)
set p = null
endfunction
function ATPCAddUnit takes unit u returns nothing
local player p = GetOwningPlayer(u)
local integer i = GetPlayerId(p)
call ATPCRemovePlayer(p)
set CameraRotate<i> = 0
set CameraDistance<i> = CameraMaxDistance
call GroupAddUnit(CameraTargetUnits, u)
set p = null
endfunction
private function usesCamera takes nothing returns nothing
if GetOwningPlayer(GetEnumUnit()) == GetTriggerPlayer() then
set bj_isUnitGroupDeadResult = false
endif
endfunction
private function CameraOn takes nothing returns nothing
local integer i = GetPlayerId(GetTriggerPlayer())
if GetOwningPlayer(GetEnumUnit()) == GetTriggerPlayer() then
set CameraRotate<i> = 0
set CameraDistance<i> = CameraMaxDistance
call GroupAddUnit(CameraTargetUnits, GetEnumUnit())
endif
endfunction
private function CameraOff takes nothing returns nothing
if GetOwningPlayer(GetEnumUnit()) == GetTriggerPlayer() then
call GroupRemoveUnit(CameraTargetUnits, GetEnumUnit())
endif
endfunction
private function StopActions takes nothing returns nothing
set bj_isUnitGroupDeadResult = true
call ForGroup(CameraTargetUnits, function usesCamera)
if bj_isUnitGroupDeadResult then
call ForGroup(CameraMainUnits, function CameraOn)
set CameraDisable[GetPlayerId(GetTriggerPlayer())] = false
else
call ForGroup(CameraTargetUnits, function CameraOff)
if GetLocalPlayer() == GetTriggerPlayer() then
set CameraDisable[GetPlayerId(GetTriggerPlayer())] = true
call ResetToGameCamera(1.5)
endif
endif
endfunction
private function CameraAdjust takes nothing returns nothing
local unit u = GetEnumUnit()
local location l = Location(0,0)
local real x
local real y
local real z
local real x1
local real y1
local real z1
if GetLocalPlayer() == GetOwningPlayer(u) then
set CameraDistance[GetPlayerId(GetOwningPlayer(u))] = 25
set x = GetUnitX(u)
set y = GetUnitY(u)
call MoveLocation(l,x,y)
set z = GetLocationZ(l)
set x1 = x + 64 * Cos((GetUnitFacing(u) + CameraRotate[GetPlayerId(GetOwningPlayer(u))]) * bj_DEGTORAD)
set y1 = y + 64 * Sin((GetUnitFacing(u) + CameraRotate[GetPlayerId(GetOwningPlayer(u))]) * bj_DEGTORAD)
call MoveLocation(l,x1,y1)
set z1 = GetLocationZ(l)
loop
set x1 = x - CameraDistance[GetPlayerId(GetOwningPlayer(u))] * Cos((GetUnitFacing(u) + CameraRotate[GetPlayerId(GetOwningPlayer(u))]) * bj_DEGTORAD)
set y1 = y - CameraDistance[GetPlayerId(GetOwningPlayer(u))] * Sin((GetUnitFacing(u) + CameraRotate[GetPlayerId(GetOwningPlayer(u))]) * bj_DEGTORAD)
if ( (IsTerrainWalkable(x1, y1) or IsTerrainDeepWater(x1, y1) or GetUnitFlyHeight(u) > 0) and (CameraDistance[GetPlayerId(GetOwningPlayer(u))] < CameraMaxNow[GetPlayerId(GetOwningPlayer(u))]) ) then
set CameraDistance[GetPlayerId(GetOwningPlayer(u))] = CameraDistance[GetPlayerId(GetOwningPlayer(u))] + 25
else
exitwhen true
endif
endloop
call PanCameraToTimed(GetUnitX(u), GetUnitY(u), Period)
call SetCameraField(CAMERA_FIELD_ROTATION, GetUnitFacing(u) + CameraRotate[GetPlayerId(GetOwningPlayer(u))], Period)
call SetCameraField(CAMERA_FIELD_ZOFFSET, GetUnitFlyHeight(u) + z + CameraHeight + GetCameraField(CAMERA_FIELD_ZOFFSET) - GetCameraTargetPositionZ(), -Period)
call SetCameraField(CAMERA_FIELD_ZOFFSET, GetUnitFlyHeight(u) + z + CameraHeight + GetCameraField(CAMERA_FIELD_ZOFFSET) - GetCameraTargetPositionZ(), Period)
call SetCameraField(CAMERA_FIELD_ANGLE_OF_ATTACK, CameraAngle + ((z1 - z) * 0.5), 0.32)
call SetCameraField(CAMERA_FIELD_TARGET_DISTANCE, CameraDistance[GetPlayerId(GetOwningPlayer(u))], Period)
endif
call RemoveLocation(l)
set u = null
set l = null
endfunction
private function Actions takes nothing returns nothing
call ForGroup(CameraTargetUnits, function CameraAdjust)
endfunction
private function Death takes nothing returns nothing
if IsUnitInGroup(GetTriggerUnit(), CameraTargetUnits) then
call ATPCRemove(GetTriggerUnit())
endif
endfunction
private function KeyLeft takes nothing returns nothing
set CameraLeft[GetPlayerId(GetTriggerPlayer())] = not CameraLeft[GetPlayerId(GetTriggerPlayer())]
endfunction
private function KeyRight takes nothing returns nothing
set CameraRight[GetPlayerId(GetTriggerPlayer())] = not CameraRight[GetPlayerId(GetTriggerPlayer())]
endfunction
private function KeyUp takes nothing returns nothing
set CameraFront[GetPlayerId(GetTriggerPlayer())] = not CameraFront[GetPlayerId(GetTriggerPlayer())]
endfunction
private function KeyDown takes nothing returns nothing
set CameraBack[GetPlayerId(GetTriggerPlayer())] = not CameraBack[GetPlayerId(GetTriggerPlayer())]
endfunction
private function DoKeys takes nothing returns nothing
local integer i = 0
loop
if CameraLeft<i> then
set CameraRotate<i> = CameraRotate<i> + 8
if CameraRotate<i> > 360 then
set CameraRotate<i> = CameraRotate<i> - 360
endif
endif
if CameraRight<i> then
set CameraRotate<i> = CameraRotate<i> - 8
if CameraRotate<i> < -360 then
set CameraRotate<i> = CameraRotate<i> + 360
endif
endif
if CameraFront<i> then
if CameraMaxNow<i> > CameraMinDistance + 25 then
set CameraMaxNow<i> = CameraMaxNow<i> - 25
endif
endif
if CameraBack<i> then
if (CameraMaxNow<i> < CameraMaxDistance - 25) then
set CameraMaxNow<i> = CameraMaxNow<i> + 25
endif
endif
set i = i + 1
exitwhen i >= 12
endloop
endfunction
private function UnitCheck takes nothing returns nothing
local unit c = GetEnumUnit()
local boolean d = false
if IsUnitInGroup(c, CameraMainUnits) and (d == false) then
set d = true
call ATPCAddUnit (c)
endif
endfunction
private function Selector takes nothing returns nothing
local group Selected
if CameraDisable[GetPlayerId(GetTriggerPlayer())] == false then
set Selected = GetUnitsSelectedAll(GetTriggerPlayer())
if (IsUnitType(GetTriggerUnit(), UNIT_TYPE_HERO) == true) and CountUnitsInGroup(Selected) == 1 then
call ATPCAddMainUnit (GetTriggerUnit())
endif
call ForGroup(Selected, function UnitCheck)
if IsUnitInGroup(GetTriggerUnit(), CameraTargetUnits) == false then
call ATPCAddUnit (GetTriggerUnit())
endif
call DestroyGroup (Selected)
endif
endfunction
private function Init takes nothing returns nothing
local integer i //Player index
local trigger t = CreateTrigger()
local trigger t1 = CreateTrigger()
local trigger t2 = CreateTrigger()
local trigger t3 = CreateTrigger()
local trigger t4 = CreateTrigger()
local timer ct //For the rotation
local player p
call TriggerRegisterTimerEventPeriodic(t, Period)
call TriggerAddAction(t, function Actions)
if CameraAllowEscape then
set t = CreateTrigger()
call TriggerAddAction(t, function StopActions)
set i = 0
loop
call TriggerRegisterPlayerEventEndCinematic( t, Player(i) )
set i = i + 1
exitwhen i >= 12
endloop
endif
if CameraNotDead then
set t = CreateTrigger()
call TriggerAddAction(t, function Death)
set i = 0
loop
call TriggerRegisterPlayerUnitEvent(t, Player(i), EVENT_PLAYER_UNIT_DEATH, null)
set i = i + 1
exitwhen i >= 12
endloop
endif
set t = CreateTrigger()
call TriggerAddAction(t, function Selector)
set i = 0
loop
call TriggerRegisterPlayerSelectionEventBJ( t, Player(i), true )
set i = i + 1
exitwhen i >= 12
endloop
call TriggerAddAction(t1, function KeyLeft)
call TriggerAddAction(t2, function KeyRight)
call TriggerAddAction(t3, function KeyUp)
call TriggerAddAction(t4, function KeyDown)
set i = 0
loop
set CameraRotate<i> = 0
set CameraDistance<i> = CameraMaxDistance
set CameraLeft<i> = false
set CameraRight<i> = false
set CameraFront<i> = false
set CameraBack<i> = false
set CameraDisable<i> = false
set CameraMaxNow <i> = CameraMaxDistance
set p = Player(i)
if CameraAllowArrows then
call TriggerRegisterPlayerEvent(t1, p, EVENT_PLAYER_ARROW_LEFT_DOWN)
call TriggerRegisterPlayerEvent(t1, p, EVENT_PLAYER_ARROW_LEFT_UP)
call TriggerRegisterPlayerEvent(t2, p, EVENT_PLAYER_ARROW_RIGHT_DOWN)
call TriggerRegisterPlayerEvent(t2, p, EVENT_PLAYER_ARROW_RIGHT_UP)
call TriggerRegisterPlayerEvent(t3, p, EVENT_PLAYER_ARROW_UP_DOWN)
call TriggerRegisterPlayerEvent(t3, p, EVENT_PLAYER_ARROW_UP_UP)
call TriggerRegisterPlayerEvent(t4, p, EVENT_PLAYER_ARROW_DOWN_DOWN)
call TriggerRegisterPlayerEvent(t4, p, EVENT_PLAYER_ARROW_DOWN_UP)
endif
set i = i + 1
exitwhen i >= 12
endloop
set ct = CreateTimer()
call TimerStart(ct, 0.05, true, function DoKeys)
set ct = null
set t = null
set t1 = null
set t2 = null
set t3 = null
set t4 = null
set p = null
endfunction
endlibrary
</i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i>
I once again repeat that you need vJASS to use it
FAQ
Q - Does it work in multiplayer?
A - Yes it does
Q - Does it leak?
A - Nope
Q - Did you test it?
A - Yes i did test it more than once
Q - How does it avoid other objects?
A - If you are standing in front of a tree the camera will try to avoid the tree so that you are able to see normaly
Q - What do you mean by "changes the angle"?
A - If you are climbing a hill you will be able to see its top no matter the angle of the side
Here is the test map:
View attachment TheLegend's TPC.w3x