Zwiebelchen
Hosted Project GR
- Joined
- Sep 17, 2009
- Messages
- 7,234
I once made a system that abused GetCameraTargetPosition and periodic repanning with very close CameraBounds to detect arrow-key and mouse-to-border camera movement on locked-hero cams.
However, I could never make it look smooth enough due to a lot of flaws with the camera natives (SetCameraBounds was too slow and SetCameraTargetPosition and PanCameraToTimed both interrupt player initiated camera movements).
This is how the original algorithm worked:
Just to go sure: this algorithm definitely works (as I said, I made such a system in the past)! But it doesn't look smooth on moving units, as only half of the update cycles of the camera bounds can be used to actually pan the camera back to the hero. The second cycle is always wasted for detecting camera movement without possible repanning on the hero.
The problem is the line marked with (*). I could technically already pan the camera to the unit here (along with the small radius), but this would make camera movement in the opposite quadrant of the unit walking direction un-detectable, as adjusting camera bounds will make the camera always move to the closest valid position within the camera bounds from the current position, not to the actual center of the camera bounds, which means it is already in one of the corners even without the player moving the camera, so there's no way to detect this particular moving direction.
So I came up with this algorithm, to double the panning rate of the camera:
As you can see, I basicly get rid of one waiting interval of non-panning, as, assuming moving the camera does ALWAYS change BOTH x and y coordinates (so 0°, 90°, 180° and 270° rotation must be prohibited), there's always one coordinate that can be detected freely. The periodic adjustment of camera bounds with detection margin can always be based on the actual position of the unit instead of the position of the last re-centering process without detection margin.
There's a drawback to this approach, however: moving the mouse to the upper or lower border of the screen will, again, cause X and Y coordinates to change, always resulting in a left/right rotation as if you moved the mouse to those borders instead.
This can be overcome if we keep the decision of rotating the camera on hold until both X and Y movement direction are known (and can be translated into U/V coordinates). As Up/down and Left/right will never in the same quadrant, there can't be a false positive anymore.
This is the adjusted code for this method:
This effectively halves the detection rate again (to the same rate as with the old algorithm), but the panning rate still remains doubled, so it definitely looks smoother.
What do you guys think?
Btw, this approach is lightning-fast in multiplayer, as GetCameraTargetPosition gets updated a lot more frequently than the Arrow-Key events. So this basicly also comes with an in-built highly-responsive Arrow-Key event in case you don't mind the locked camera.
It all depends on how high the panning FPS can get.
However, I could never make it look smooth enough due to a lot of flaws with the camera natives (SetCameraBounds was too slow and SetCameraTargetPosition and PanCameraToTimed both interrupt player initiated camera movements).
This is how the original algorithm worked:
Code:
- Adjust camera bounds to the unit to pan the camera with 0 radius
(unfortunately it's not possible to use any of the panning natives, as those always interrupt any player controlled camera movement)
- wait until the camera bounds got updated (takes between 0.05 and 0.1 seconds from my tests)
- Adjust the camera bounds with a small detection margin (like 2-5 coordinate units) based on the last no-radius panning coordinates*
- wait until the camera bounds got updated
- as the update most likely happened just before the next cycle hits, the camera might have already moved through the camera movement initiated by the player
- you can now detect the camera movement via GetCameraTargetPosition()
- convert the X/Y movement direction into U/V (screen) movement direction and rotate the screen based on that
- repeat from the top
Just to go sure: this algorithm definitely works (as I said, I made such a system in the past)! But it doesn't look smooth on moving units, as only half of the update cycles of the camera bounds can be used to actually pan the camera back to the hero. The second cycle is always wasted for detecting camera movement without possible repanning on the hero.
The problem is the line marked with (*). I could technically already pan the camera to the unit here (along with the small radius), but this would make camera movement in the opposite quadrant of the unit walking direction un-detectable, as adjusting camera bounds will make the camera always move to the closest valid position within the camera bounds from the current position, not to the actual center of the camera bounds, which means it is already in one of the corners even without the player moving the camera, so there's no way to detect this particular moving direction.
So I came up with this algorithm, to double the panning rate of the camera:
Code:
- Adjust the camera bounds with a small detection margin only in X direction; lock Y direction to the unit
- wait until camera bounds got updated
- detect the movement in X direction
- convert the X movement direction into U/V (screen) movement direction and rotate the camera
- Adjust the camera bounds again with a small detection margin, but this time in Y direction; lock X direction to the unit
- wait until camera bounds got updated
- detect the movement in Y direction
- convert the Y movement direction into U/V (screen) movement direction and rotate the camera
- repeat
As you can see, I basicly get rid of one waiting interval of non-panning, as, assuming moving the camera does ALWAYS change BOTH x and y coordinates (so 0°, 90°, 180° and 270° rotation must be prohibited), there's always one coordinate that can be detected freely. The periodic adjustment of camera bounds with detection margin can always be based on the actual position of the unit instead of the position of the last re-centering process without detection margin.
There's a drawback to this approach, however: moving the mouse to the upper or lower border of the screen will, again, cause X and Y coordinates to change, always resulting in a left/right rotation as if you moved the mouse to those borders instead.
This can be overcome if we keep the decision of rotating the camera on hold until both X and Y movement direction are known (and can be translated into U/V coordinates). As Up/down and Left/right will never in the same quadrant, there can't be a false positive anymore.
This is the adjusted code for this method:
Code:
- Adjust the camera bounds with a small detection margin only in X direction; lock Y direction to the unit
- wait until camera bounds got updated
- detect the movement in X direction
- store the X movement direction into a variable
- Adjust the camera bounds again with a small detection margin, but this time in Y direction; lock X direction to the unit
- wait until camera bounds got updated
- detect the movement in Y direction
- convert the Y movement direction and the stored X movement into U/V (screen) movement direction and rotate the camera
- repeat
This effectively halves the detection rate again (to the same rate as with the old algorithm), but the panning rate still remains doubled, so it definitely looks smoother.
What do you guys think?
Btw, this approach is lightning-fast in multiplayer, as GetCameraTargetPosition gets updated a lot more frequently than the Arrow-Key events. So this basicly also comes with an in-built highly-responsive Arrow-Key event in case you don't mind the locked camera.
It all depends on how high the panning FPS can get.