| 02-20-2009, 05:18 PM | #1 | |
I've been working on a 3rd person camera system and instead of using global arrays for the different values I tried only setting and calling these values locally. This might sound dangerous but I just need that adrenaline! So I'd like to know if this method of using global variables will cause any desyncs later. In short testing there hasn't been any desyncs but maybe there are some long-term effects. Here's the code: JASS:library OppiCam initializer Init requires AnyPlayerEvents globals //Anything here is set and called locally. //DON'T USE THESE VARIABLES IN GLOBAL CODE! private location Loc = Location(0,0) private boolean Up = false private boolean Down = false private boolean Right = false private boolean Left = false private real ControlableAoA private real ControlableRot private boolean Cam = false private unit Unit //Up to here everything is set and called locally. //Use the x values as the angle of attack values. Y values are the according distance/offset values. //Example: //DISTANCEX1 = 345 //DISTANCEY1 = 300 //DISTANCEX2 = 295 //DISTANCEY2 = 600 //This means you want the camera distance to be 300 at an angle of 345 and 600 at an angle of 295. //The values inbetween will be calculated linearly. private constant real DISTANCEX1 = 345 private constant real DISTANCEY1 = 300 private constant real DISTANCEX2 = 295 private constant real DISTANCEY2 = 600 private constant real OFFSETX1 = 345 private constant real OFFSETY1 = 0 private constant real OFFSETX2 = 295 private constant real OFFSETY2 = 200 private constant real OFFSETLIMIT = 345 //if the angle is greater than this value the camera will pan to the unit instead of to an offset point private constant real ZOFFSET = 100 //basic camera offset private constant real CAMTIMEOUT = 0.1 //timeout for the camera timer private constant real KEYBOARDTIMEOUT = 0.1 //timerout for the keyboard timer private constant real PANDURATION = 0.4 //duration over which the camera fields are set //higher values make the camera movement smoother but also slower private constant real MAXAOA = 355 //max controlable angle of attack; angles calculated to avoid clipping may be higher than his private constant real MINAOA = 295 private constant real MAXROT = 105 private constant real AOAINTERVAL = 3 private constant real ROTINTERVAL = 7.5 private constant real DEFAULTAOA = 345 //These are the parameters for the linear functions used to calculate the desired camera distance and offset private real DistanceM = (DISTANCEY2-DISTANCEY1)/(DISTANCEX2-DISTANCEX1) private real DistanceT = DISTANCEY1-DISTANCEX1*DistanceM private real OffsetM = (OFFSETY2-OFFSETY1)/(OFFSETX2-OFFSETX1) private real OffsetT = OFFSETY1-OFFSETX1*OffsetM endglobals //Functions for distance and offset. These are linear mathematical functions y = mx+t private function GetDynamicDistance takes real angleOfAttack returns real return DistanceM * angleOfAttack + DistanceT endfunction private function GetDynamicOffset takes real angleOfAttack returns real return OffsetM * angleOfAttack + OffsetT endfunction private struct loc real x real y real z endstruct private function DistanceBetweenCoords takes real x1, real y1, real x2, real y2 returns real local real dx = x2-x1 local real dy = y2-y1 return SquareRoot(dx*dx+dy*dy) endfunction private function GetHighestPointInLine takes real x, real y, real angle, real distance returns loc local loc maxloc = loc.create() local real r = 10 local real dx = Cos(bj_DEGTORAD*angle) local real dy = Sin(bj_DEGTORAD*angle) call MoveLocation(Loc, x, y) set maxloc.x = x set maxloc.y = y set maxloc.z = GetLocationZ(Loc) loop exitwhen r > distance call MoveLocation(Loc, x+r*dx, y+r*dy) if GetLocationZ(Loc) > maxloc.z then set maxloc.x = GetLocationX(Loc) set maxloc.y = GetLocationY(Loc) set maxloc.z = GetLocationZ(Loc) endif set r = r+10 endloop return maxloc endfunction //Camera actions, lots of stuff. All working :) private function ApplyOppiCam takes nothing returns nothing local real unitx = GetUnitX(Unit) local real unity = GetUnitY(Unit) local real unitz local real angleofattack = GetCameraField(CAMERA_FIELD_ANGLE_OF_ATTACK)* bj_RADTODEG local loc offset = GetHighestPointInLine(unitx, unity, GetCameraField(CAMERA_FIELD_ROTATION)*bj_RADTODEG+180, 500) local real panx local real pany local real anticlipangle if angleofattack > OFFSETLIMIT then set panx = unitx set pany = unity else set panx = unitx + GetDynamicOffset(angleofattack) * Cos(bj_DEGTORAD*GetUnitFacing(Unit)) set pany = unity + GetDynamicOffset(angleofattack) * Sin(bj_DEGTORAD*GetUnitFacing(Unit)) endif call PanCameraToTimed(panx, pany, PANDURATION) call MoveLocation(Loc, unitx, unity) set unitz = GetLocationZ(Loc) + GetUnitFlyHeight(Unit) set anticlipangle = 350 - bj_RADTODEG * Atan2((offset.z-unitz-ZOFFSET), DistanceBetweenCoords(unitx, unity, offset.x, offset.y)) if ControlableAoA > anticlipangle then call SetCameraField(CAMERA_FIELD_ANGLE_OF_ATTACK, anticlipangle, PANDURATION) else call SetCameraField(CAMERA_FIELD_ANGLE_OF_ATTACK, ControlableAoA, PANDURATION) endif call SetCameraField(CAMERA_FIELD_TARGET_DISTANCE, GetDynamicDistance(angleofattack), PANDURATION) call SetCameraField(CAMERA_FIELD_ZOFFSET, GetCameraField(CAMERA_FIELD_ZOFFSET) - GetCameraTargetPositionZ() + unitz + ZOFFSET, PANDURATION) call SetCameraField(CAMERA_FIELD_ROTATION, GetUnitFacing(Unit) + ControlableRot, PANDURATION) call offset.destroy() endfunction function UseOppiCam takes unit whichUnit, boolean use returns nothing if use == true then set Cam = true set Unit = whichUnit else set Cam = false endif endfunction function UseOppiCamForPlayer takes player whichPlayer, unit whichUnit, boolean use returns nothing if GetLocalPlayer() == whichPlayer then call UseOppiCam(whichUnit, use) endif endfunction private function CamPeriodic takes nothing returns nothing if Cam == true then call ApplyOppiCam() endif endfunction private function UpDown takes nothing returns nothing if GetLocalPlayer() == GetTriggerPlayer() then set Up = true if ControlableAoA > MINAOA then set ControlableAoA = ControlableAoA - AOAINTERVAL endif endif endfunction private function UpUp takes nothing returns nothing set Up = false endfunction private function DownDown takes nothing returns nothing if GetLocalPlayer() == GetTriggerPlayer() then set Down = true if ControlableAoA < MAXAOA then set ControlableAoA = ControlableAoA + AOAINTERVAL endif endif endfunction private function DownUp takes nothing returns nothing set Down = false endfunction private function LeftDown takes nothing returns nothing if GetLocalPlayer() == GetTriggerPlayer() then set Left = true if ControlableRot > -MAXROT then set ControlableRot = ControlableRot - ROTINTERVAL endif endif endfunction private function LeftUp takes nothing returns nothing set Left = false endfunction private function RightDown takes nothing returns nothing if GetLocalPlayer() == GetTriggerPlayer() then set Right = true if ControlableRot < MAXROT then set ControlableRot = ControlableRot + ROTINTERVAL endif endif endfunction private function RightUp takes nothing returns nothing set Right = false endfunction private function KeyboardPeriodic takes nothing returns nothing if Cam == true then if Up == true then if ControlableAoA > MINAOA then set ControlableAoA = ControlableAoA - AOAINTERVAL endif endif if Down == true then if ControlableAoA < MAXAOA then set ControlableAoA = ControlableAoA + AOAINTERVAL endif endif if Left == true then if ControlableRot > -MAXROT then set ControlableRot = ControlableRot - ROTINTERVAL endif endif if Right == true then if ControlableRot < MAXROT then set ControlableRot = ControlableRot + ROTINTERVAL endif endif endif endfunction private function Reset takes nothing returns nothing if GetLocalPlayer() == GetTriggerPlayer() then set ControlableAoA = DEFAULTAOA set ControlableRot = 0 endif endfunction private function CheckCam takes nothing returns boolean return Cam endfunction private function Init takes nothing returns nothing local timer t local trigger trig set ControlableAoA = DEFAULTAOA set ControlableRot = 0 set t = CreateTimer() call TimerStart(t, CAMTIMEOUT, true, function CamPeriodic) set t = CreateTimer() call TimerStart(t, KEYBOARDTIMEOUT, true, function KeyboardPeriodic) set trig = CreateTrigger() call TriggerRegisterAnyPlayerEvent(trig, EVENT_PLAYER_ARROW_UP_DOWN) call TriggerAddAction(trig, function UpDown) call TriggerAddCondition(trig, Condition(function CheckCam)) set trig = CreateTrigger() call TriggerRegisterAnyPlayerEvent(trig, EVENT_PLAYER_ARROW_UP_UP) call TriggerAddAction(trig, function UpUp) set trig = CreateTrigger() call TriggerRegisterAnyPlayerEvent(trig, EVENT_PLAYER_ARROW_DOWN_DOWN) call TriggerAddAction(trig, function DownDown) call TriggerAddCondition(trig, Condition(function CheckCam)) set trig = CreateTrigger() call TriggerRegisterAnyPlayerEvent(trig, EVENT_PLAYER_ARROW_DOWN_UP) call TriggerAddAction(trig, function DownUp) set trig = CreateTrigger() call TriggerRegisterAnyPlayerEvent(trig, EVENT_PLAYER_ARROW_LEFT_DOWN) call TriggerAddAction(trig, function LeftDown) call TriggerAddCondition(trig, Condition(function CheckCam)) set trig = CreateTrigger() call TriggerRegisterAnyPlayerEvent(trig, EVENT_PLAYER_ARROW_LEFT_UP) call TriggerAddAction(trig, function LeftUp) set trig = CreateTrigger() call TriggerRegisterAnyPlayerEvent(trig, EVENT_PLAYER_ARROW_RIGHT_DOWN) call TriggerAddAction(trig, function RightDown) call TriggerAddCondition(trig, Condition(function CheckCam)) set trig = CreateTrigger() call TriggerRegisterAnyPlayerEvent(trig, EVENT_PLAYER_ARROW_RIGHT_UP) call TriggerAddAction(trig, function RightUp) set trig = CreateTrigger() call TriggerRegisterAnyPlayerChatEvent(trig, "-reset", true) call TriggerAddAction(trig, function Reset) call TriggerAddCondition(trig, Condition(function CheckCam)) set t = null set trig = null endfunction endlibrary What the cam does (not that important):
I already had a problem when using JASS:call TriggerRegisterPlayerEvent(trig, GetLocalPlayer(), PLAYER_EVENT) //instead of call TriggerRegisterAnyPlayerEvent(trig, PLAYER_EVENT) //and then checking for GetLocalPlayer() == GetTriggerPlayer() in the actions function Turns out that what Rising_Dusk said is true. I haven't had any problems with the rest of the code, though <<yet>>. |
| 02-20-2009, 07:27 PM | #2 |
It is generally wise to do as little as possible in local blocks. Right now you are changing the value of a variable locally, which can cause desynchronizations in the checks if other players ever check those values. You should be careful with that, it seems 'risky.' |
| 02-20-2009, 08:02 PM | #3 |
Yeah right, but do other players ever check these values if I don't use them in global code? I think there's nothing wrong about using huge blocks of local code as long as you can be sure that it's safe. I mean I'm saving 11*8 variables/array members by using this method. There's no reason for keeping these values globally AS LONG as it's safe. The question is if it is :D. |
