PanCamera without interupting mouse scrolling

Zwiebelchen

You can change this now in User CP.
Reaction score
60
I am currently writing my own 3rd person camera system, which is unique in the way that it does not automaticly change the angle of attack and rotation, but allows the controlling of both values by using the arrow keys or moving the mouse curser to the borders of the screen.

I detect the mouse border events by comparing the last cameraX and Y of the player to the current ones. It works pretty well so far.

The only problem is: I can not use SetCameraTargetController, as it completely disables mouse scrolling, which is important for this system to work. I tried periodically setting the Camera targets coordinates by using PanCamera, but it always "cancels" the mouse scrolling so that i need to hit the screen border again instead of just leaving the curser there.

To make short:
Is there a way to pan a camera without interupting the current mouse scrolling?
 

Zwiebelchen

You can change this now in User CP.
Reaction score
60
AFAIR, no.
But there are several pan functions (at least 2), try them all.
I tried PanCameraTo, PanCameraTimedTo and SetCameraPosition ... neither of them did work.

However, it seems that adjusting the camera bounds does help. It works like a panning too, but only if the camera bounds remain set. That means using camera bounds to pan the camera in this system would disable the minimap. I think I could live with that ... dunno.
 

Troll-Brain

You can change this now in User CP.
Reaction score
85
If you can't live without the minimap and want to be crazy you could still use trackables.
 

Zwiebelchen

You can change this now in User CP.
Reaction score
60
If you can't live without the minimap and want to be crazy you could still use trackables.
Not an option, as trackables would totally disrupt the advantage mouse scrolling provides: That it is not sync-dependant and thus works instant.


EDIT: Almost got it to work. I can't believe this is actually possible!! I just need to fix unit movement triggering a false positive on the scrolling 'events'.
 

Troll-Brain

You can change this now in User CP.
Reaction score
85
Not an option, as trackables would totally disrupt the advantage mouse scrolling provides: That it is not sync-dependant and thus works instant.


EDIT: Almost got it to work. I can't believe this is actually possible!! I just need to fix unit movement triggering a false positive on the scrolling 'events'.
I'm not talking how good the trackables solution would be good (in fact it would be even lame), just wanted to say that :
You can use trackables without any sync, but you have to create X trackables fo X players :( (and using smartly a "" path for trackables).
But yes, trackables events have delay.

Anyway i'm glad that you have found what you wanted without any help :thup:
 

Zwiebelchen

You can change this now in User CP.
Reaction score
60
I'm not talking how good the trackables solution would be good (in fact it would be even lame), just wanted to say that :
You can use trackables without any sync, but you have to create X trackables fo X players :( (and using smartly a "" path for trackables).
But yes, trackables events have delay.

Anyway i'm glad that you have found what you wanted without any help :thup:
I could still need help, as I simply do not get why unit movement triggers the scrolling.

Maybe you can help me with that:


It works fine as long as the unit is not moving, but for some reason moving units fire the Up/Down event every 4 update cycles.

PS: Didn't implement the left/right event yet ... but it's the same as up/down, really, so it won't make any problems.

EDIT: Nevermind ... found the problem.
 

Zwiebelchen

You can change this now in User CP.
Reaction score
60
I still have this problem that moving units trigger the up/down event.

Any idea why? If I increase the update interval, it works for some reason. It has to be something to do with the updating of the CamX and CamY values. However, I do not understand why, as I check only for them when they actually changed.

Please help!

EDIT: Seems that it was a problem of when I retrieved the cam data ... works fine now. Awesome!
 

Zwiebelchen

You can change this now in User CP.
Reaction score
60
Omfg, why the heck doesn't it work, goddamnit? ... Always when I think that it works fine now, the bug appears again.

Please, someone check this code and tell me what is causing that sometimes when the target moves the up/down event fires.

JASS:
library ZCS initializer Init

globals
    private constant integer numberofplayers = 8
    private constant real updateinterval = 0.02 //50 fps
    private constant real minmovedistance = 0.20
    private constant real maxboundoffset = 0.25
    private constant real maxmoverange = 0.3
    private constant real angleofattackchange = 3
    
    private real CamX = 0
    private real CamY = 0
    private real CamZ = 0
    private real CamEyeX = 0
    private real CamEyeY = 0
    private real CamEyeZ = 0
    private real CamXTemp = 0
    private real CamYTemp = 0
    private boolean switch = true
endglobals

private struct cam
    player p
    unit target
    real x
    real y
    real z
    real eyex
    real eyey
    real eyez
    
    method update takes nothing returns nothing
        local real dx = 0
        local real dy = 0
        local real du = 0
        local real dv = 0
        local real angle = 0
        if GetUnitTypeId(this.target) != 0 then
            if GetLocalPlayer() == this.p then
                if switch then //allow camera movement again
                    set CamXTemp = CamX
                    set CamYTemp = CamY
                    call SetCameraBounds(this.x-maxboundoffset, this.y-maxboundoffset, this.x-maxboundoffset, this.y+maxboundoffset, this.x+maxboundoffset, this.y+maxboundoffset, this.x+maxboundoffset, this.y-maxboundoffset)
                else
                    if CamX != CamXTemp or CamY != CamYTemp then //only perform cam changes when the cam has really changed since focus release
                        set angle = Atan2(this.y-this.eyey, this.x-this.eyex)-1.57085
                        call BJDebugMsg(R2S(angle))
                        set dx = CamX-this.x //offset from old position
                        set dy = CamY-this.y
                        if dx >= -maxmoverange and dx <= maxmoverange and dy >= -maxmoverange and dy <= maxmoverange then //movement is valid
                            set du = dy*Sin(angle) + dx*Cos(angle) //coordinate transformation
                            set dv = dy*Cos(angle) - dx*Sin(angle)
                        endif
                        call BJDebugMsg(R2S(dy)+" and "+R2S(dv))
                        if RAbsBJ(dv) > RAbsBJ(du) then //up/down turning
                            if dv <= -minmovedistance or dv >= minmovedistance then
                                if dv < 0 then
                                    call SetCameraField(CAMERA_FIELD_ANGLE_OF_ATTACK, bj_RADTODEG*GetCameraField(CAMERA_FIELD_ANGLE_OF_ATTACK)-angleofattackchange, 0)
                                else
                                    call SetCameraField(CAMERA_FIELD_ANGLE_OF_ATTACK, bj_RADTODEG*GetCameraField(CAMERA_FIELD_ANGLE_OF_ATTACK)+angleofattackchange, 0)
                                endif
                            endif
                        else //left/right
                            if du < -minmovedistance or du > minmovedistance then
                                if du < 0 then
                                    call BJDebugMsg("Turn Left")
                                else
                                    call BJDebugMsg("Turn Right")
                                endif
                            endif
                        endif
                    endif
                    set this.x = GetUnitX(this.target)
                    set this.y = GetUnitY(this.target)
                    set this.eyex = CamEyeX
                    set this.eyey = CamEyeY
                    call SetCameraBounds(this.x, this.y, this.x, this.y, this.x, this.y, this.x, this.y) //disallow camera movement
                    set dx = 0
                    set dy = 0
                    set du = 0
                    set dv = 0
                endif
            endif
        endif
    endmethod
endstruct

globals   
    private cam array Cams[numberofplayers]
endglobals

private function Update takes nothing returns nothing
        local integer i = 0
        set CamX = GetCameraTargetPositionX() //not synced ... do not use these values for synced operations
        set CamY = GetCameraTargetPositionY()
        set CamZ = GetCameraTargetPositionZ()
        set CamEyeX = GetCameraEyePositionX()
        set CamEyeY = GetCameraEyePositionY()
        set CamEyeZ = GetCameraEyePositionZ()
        loop
            exitwhen i >= numberofplayers
            if Cams<i> != 0 then
                call Cams<i>.update()
            endif
            set i = i + 1
        endloop
        set switch = not switch
        if switch then
            call TimerStart(GetExpiredTimer(), 0.02, false, function Update)
        else
            call TimerStart(GetExpiredTimer(), 0.01, false, function Update)
        endif
endfunction

public function EnableCam takes player p, unit u returns nothing
    local location l
    local integer id = GetPlayerId(p)
    if GetPlayerSlotState(p) == PLAYER_SLOT_STATE_PLAYING and GetPlayerController(p) == MAP_CONTROL_USER then
        set l = GetUnitLoc(u)
        set Cams[id].target = u
        set Cams[id].x = GetLocationX(l)
        set Cams[id].y = GetLocationY(l)
        set Cams[id].z = GetLocationZ(l)
        set Cams[id].eyex = GetLocationX(l)
        set Cams[id].eyey = GetLocationY(l)-500
        set Cams[id].eyez = GetLocationZ(l)+500
        call RemoveLocation(l)
    endif
    set l = null
endfunction

public function DisableCam takes player p returns nothing
    if GetPlayerId(p) &lt; numberofplayers then
        if Cams[GetPlayerId(p)] != 0 then
            set Cams[GetPlayerId(p)].target = null
            if GetLocalPlayer() == p then
                call ResetToGameCamera(0)
            endif
        endif
    endif
endfunction

private function InitCallback takes nothing returns nothing
    local integer i = 0
    local timer t = GetExpiredTimer()
    loop
        exitwhen i &gt;= numberofplayers
        if GetPlayerSlotState(Player(i)) == PLAYER_SLOT_STATE_PLAYING and GetPlayerController(Player(i)) == MAP_CONTROL_USER then
            set Cams<i> = cam.create()
            set Cams<i>.p = Player(i)
        endif
        set i = i + 1
    endloop
    call TimerStart(t, 0, false, function Update)
    set t = null
endfunction

private function Init takes nothing returns nothing
    call TimerStart(CreateTimer(), 0.5, false, function InitCallback)
endfunction

endlibrary</i></i></i></i>
 

Troll-Brain

You can change this now in User CP.
Reaction score
85
Camera pan is not something truly instant (takes less than 0.03 s or so, don't remember).
That should be kinda the same with SetCameraBounds, test it.
 

Zwiebelchen

You can change this now in User CP.
Reaction score
60
Camera pan is not something truly instant (takes less than 0.03 s or so, don't remember).
That should be kinda the same with SetCameraBounds, test it.
SetCameraBounds doesn't interupt mouse scrolling, although it is not instant. I wish it would.

And its not really about pans not being instant. I would be totally fine with that ... I just do not want that it interupts mouse look, but it does.


Okay ... it seems that camera quick position does not cancel mouse look. Is there a way to fire the "Go to quick position" by trigger?
Can I use ForceUIkey? Which key is the space bar?
 

Troll-Brain

You can change this now in User CP.
Reaction score
85
Okay ... it seems that camera quick position does not cancel mouse look. Is there a way to fire the "Go to quick position" by trigger?
Can I use ForceUIkey? Which key is the space bar?
It doesn't cancel mouse basically because it doesn't pan the camera, you can simulate an escape, a letter ("a to z"), but definitely not the space bar.

Anyway, even if you could simulate, it would be delayed like force ui key (don't remember but again i'm pretty sure that the delay is at very least 0.3 s, could be much more and host connection dependant).
And more evil, between two force ui action you must respect a delay, else it will be ignored, and i suppose a real press by the player in game count as well (hard to test and i don't care coz of the reasons above, i mean it's already lame)

Finally this point is edited internally by wc3 (when a building is attacked, and so one).
And also for initialization melee in blizzard.j, but ofc this last point doesn't really matter if you know it.
 

Zwiebelchen

You can change this now in User CP.
Reaction score
60
I gave up on trying to use Setting the map bounds to pan the camera.

basicly, setting the camera bounds updates the cam position at the same moment the new [ljass]GetCameraTargetPositionX()[/ljass] becomes available.

That means that you can only pan the camera on every second [ljass]GetCameraTargetPositionX()[/ljass], as you need to Set the Cam bounds to X and Y of the unit on the first get, and set the Cam bounds to X-0.01, Y+0.01 on the second, to allow scrolling again.
Setting it instantly to X-0.01, Y+0.01 wouldn't pan the camera to the center, but just the closest position to its earlier position.

[ljass]GetCameraTargetPositionX()[/ljass] gets updated every 25 miliseconds, which equals up to 40 fps. 20 fps if you consider that you can only use every second change, as you have to wait for the cam bounds to be updated. 20 FPS, however, is not fast enough for smooth camera movement.

I could add a little delay in reaction time, by just "releasing" the cambounds on every third of forth update, but that would still generate a small "low fps moment", just less frequently, so it's not optimal either.


Sad thing. The [ljass]GetCameraTargetPositionX()[/ljass] was fast as lightning, even in bnet games.


I try again with trackables.
 

Troll-Brain

You can change this now in User CP.
Reaction score
85
GetCameraTargetPositionX() gets updated every 25 miliseconds
Hmm, i didn't thought in this way, so maybe PanCamera is truly instant, but it's the GetCameraTarget... functions which are updated each 0.025 s.
That doesn't really change something though.

For the trackable thing it was mostly a joke, it will require lot of work, for a lame result i think, trackable events have delay.
 

Zwiebelchen

You can change this now in User CP.
Reaction score
60
For the trackable thing it was mostly a joke, it will require lot of work, for a lame result i think, trackable events have delay.
I gave it a quick try and gave up on it. Trackables suck alone for the fact that you can not "attach" them to the camera properly.
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      The Helper Discord

      Members online

      No members online now.

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top