View topic - Turret rotating independant from unit chassis?



All times are UTC + 1 hour


Post new topic Reply to topic  [ 10 posts ] 
Author Message
PostPosted: 03 Sep 2011, 11:52 
User avatar

Joined: 20 Aug 2009, 19:49
Does anyone have an idea how to make a units turret compensate for
the units turning in order to give the illusion of working independant of it?

What i want is basically a chassis that can move and turn in any direction while the turret stays focussed at the target.


Top
 Offline Profile  
 
PostPosted: 03 Sep 2011, 12:19 
Moderator
User avatar

Joined: 26 Oct 2007, 15:21
Im not sure I understand the question, since I believe almost all tanks do this in spring.


Top
 Offline Profile  
 
PostPosted: 03 Sep 2011, 12:46 
User avatar

Joined: 20 Aug 2009, 19:49
I have a turret, i have a chassis.

If the chassis piece turns the turret piece will turn the same in addition to its own turning.

If i now have a fast turning unit with a slow turing turret usually a turn of the vehicle will cause it to loose aim.

What i want now is that the turret works totally independant of the chassis so the chassis may turn in one direction for movement while the turret isn't affected at all, basically like floating over the chassis and not beeing attached to it.

I guess i could work it out if i were to find out how much the unit turned in worldspace and then counterbalance that movement by rotating the turret piece in the other direction.


I reduced my Problem to a simpler one: Can i turn a unit piece by a set angle, for example 90┬░ left without knowing what the result will be?
OR
Can i get a pieces current rotation? Wiki says the function for this is broken...


Top
 Offline Profile  
 
PostPosted: 03 Sep 2011, 13:52 
Moderator
User avatar

Joined: 22 Feb 2006, 01:02
Location: cheap kitchen
real world tanks keep their gun pointed at the target now matter how the chasis rotates or tilts.
[url]ie http://www.youtube.com/watch?v=JTq2DTyA ... page#t=18s[/url]

Erik wrote:
I guess i could work it out if i were to find out how much the unit turned in worldspace and then counterbalance that movement by rotating the turret piece in the other direction.
i think that should work.
could also be used for hot air ballons that do not rotate when they change direction, radar dishes on vehicles and other stuff.

Something similiar:
I tried to make units aim at units that are in LOS but not in weapon range yet. Because it looks kind of silly if a tank drives towards an enemy without pre-aiming.
Gave them a long range weapon that aims the turret but never fires (or is invisible and does no damage, both work)
Kind of worked but had some problems too...


Top
 Offline Profile  
 
PostPosted: 03 Sep 2011, 13:55 
Moderator
User avatar

Joined: 29 Apr 2005, 00:14
Location: #moddev - join it!
Quote:
Can i get a pieces current rotation? Wiki says the function for this is broken...


If you are using lua;

http://springrts.com/wiki/Animation-LuaCallouts

Spring.UnitScript.GetPieceRotation ( piece ) -> number x, y, z


Top
 Offline Profile  
 
PostPosted: 03 Sep 2011, 14:27 
Moderator
User avatar

Joined: 22 Feb 2006, 01:02
Location: cheap kitchen
gun always aimed "downwards", no matter how chasis rotates:
Image

Code:
function updateheading()
   while (true) do
      lastheading = currentheading
      currentheading = Spring.GetUnitHeading(unitID)
      deltaheading = lastheading - currentheading      
      Sleep (200)

   local _,turretDir,_ = Spring.UnitScript.GetPieceRotation (turret)--pro tip: do this for tilting axis too
   deltaheading = deltaheading * math.pi / 32768
   Turn (turret, y_axis, (deltaheading+turretDir), math.rad(180))
   end   
end

needs stuff to keep unit from doing that when it is actually aiming but thats just the principle.
was thinking to make it toggleable by on/off button.


Top
 Offline Profile  
 
PostPosted: 04 Sep 2011, 13:08 
User avatar

Joined: 20 Aug 2009, 19:49
Working solution with one small bug.
Implemented here as a hovercraft unit so the turret is basically the chassis, the unit can move around a target and stay focussed at all times.
For the tank variant replace "chassis" by a centered turret.

Feel free to use it but if you do any improvements please post them.

Code:
local chassis = piece "chassis"
local flare1 = piece "flare1"

local SIG_RESTORE=2
local SIG_TURRET=4

local attack_mode=0 --will the unit turn turret along movement or focus on the enemy?

--constant for converting unitheadings to radians
local conversion= 2*3.14159/(2^16)
local attack_heading=conversion*Spring.GetUnitHeading(unitID)


local function restore()
   Signal(SIG_RESTORE)
   SetSignalMask(SIG_RESTORE)
   local unit_dir=0

   Sleep(5000)
   --slowly restore to original settings
   while(true) do
     unit_dir=Spring.GetUnitHeading(unitID)
     if (attack_heading<0.03+conversion*unit_dir and attack_heading>-0.03+conversion*unit_dir) then
       attack_heading=conversion*unit_dir

       attack_mode=0         
     end
     --TODO: take into consideration shortest way, as it is now sometimes the
     --longer turn is taken making the poor driver pretty sick xD
     if attack_heading>=0.03+conversion*unit_dir then attack_heading=attack_heading-0.03 end
     if attack_heading<=-0.03+conversion*unit_dir then attack_heading=attack_heading+0.03 end
     Sleep(60)
   end
end

local function turret()
   Signal(SIG_TURRET)
   SetSignalMask(SIG_TURRET)

   local unit_dir=Spring.GetUnitHeading(unitID)

   local diff_dir=0

   Sleep(180)
   while(true) do
     if (attack_mode==1) then
      unit_dir=Spring.GetUnitHeading(unitID)

      --turn the chassis piece to exactly the needed position
      Turn(chassis, y_axis,attack_heading-conversion*unit_dir)

      Sleep(30)
    end

    --normal behaviour when not in combat situation
    if (attack_mode==0) then Sleep(30) end   
   end
end


function script.Create()
 StartThread(turret)
end

function script.Killed(recentDamage, maxHealth)
   Explode(chassis, SFX.SHATTER)    
end

function script.StartMoving ()
  Move(chassis, y_axis, 20,9)
end

function script.StopMoving ()

end

function script.AimFromWeapon1()
   return flare1
end

function script.QueryWeapon1()
   return flare1
end

function script.AimWeapon1( heading, pitch )
   Signal(SIG_RESTORE)
   Signal(1)
   SetSignalMask(1)   
   attack_mode=1
   --aiming animation


   local unit_dir=Spring.GetUnitHeading(unitID)

   while(true) do
     unit_dir=Spring.GetUnitHeading(unitID)
     if (attack_heading<0.10+conversion*unit_dir+heading and attack_heading>-0.10+conversion*unit_dir+heading) then
       --fire shot !
       StartThread(restore)
       return true
         
     end

     --TODO: take into consideration shortest way, as it is now sometimes the
     --longer turn is taken
    -- Spring.Echo("attack heading",attack_heading)
    -- Spring.Echo("wanted heading",conversion*unit_dir+heading)
     if attack_heading>=0.10+conversion*unit_dir+heading then
        attack_heading=attack_heading-0.10
     end
     if attack_heading<=-0.10+conversion*unit_dir+heading then
             attack_heading=attack_heading+0.10
     end

     Sleep(60)
   end

   --attack_heading=2*3.1415926 --this would be a full circle


   StartThread(restore)
   return true

end


Top
 Offline Profile  
 
PostPosted: 04 Sep 2011, 17:29 
Moderator
User avatar

Joined: 22 Feb 2006, 01:02
Location: cheap kitchen
cool :-)
2 small things:
Signal(1)
SetSignalMask(1)

why not use the constants here?

In function turret() does the Sleep(180) before the loop have a use?


Top
 Offline Profile  
 
PostPosted: 04 Sep 2011, 18:05 
User avatar

Joined: 20 Aug 2009, 19:49
nope the sleep has no use, mostlikely an artifact of earlier attemts on this.
As for the constant that might aswell be called SIGNAL_AIM or anything.


Top
 Offline Profile  
 
PostPosted: 06 Sep 2011, 12:23 
User avatar

Joined: 20 Aug 2009, 19:49
Code:
--Define the wheel pieces

local wheel_speed = math.rad(180)
--Define the pieces of the weapon
local chassis = piece "chassis"
local turret = piece "turret"
local guns = piece "guns"
local flare1 = piece "flare1"
local flare2 = piece "flare2"
local active_barrel = 1      --the barrel that the next shot will be fired from
local number_of_barrels = 2      --how many barrel there are in total

local SIG_AIM=1
local SIG_RESTORE=2
local SIG_TURRET=4
--constant for converting unitheadings to radians
local conversion= 2*3.14159/(2^16)
local attack_heading=conversion*Spring.GetUnitHeading(unitID)

local attack_mode=0 --will the unit turn turret along movement or focus on the enemy?


local function restore()
   Signal(SIG_RESTORE)
   SetSignalMask(SIG_RESTORE)
   local unit_dir=0
   local turnspeed=0.06 --the speed at which the turett will turn


   Sleep(5000)
   --slowly restore to original settings
   while(true) do
     unit_dir=Spring.GetUnitHeading(unitID)
     --reduce attack_heading & wanted_heading to a number between 0 and 2*PI
     if (attack_heading<0) then
        attack_heading=attack_heading+2*3.14159
     end    
     if (attack_heading>2*3.14159) then
        attack_heading=attack_heading-2*3.14159
     end    

     local wanted_heading=conversion*unit_dir
     if (wanted_heading<0) then
        wanted_heading=wanted_heading+2*3.14159
     end    
     if (wanted_heading>2*3.14159) then
        wanted_heading=wanted_heading-2*3.14159
     end

     local dist1=0
     local dist2=0

     --check if at original position
     --calculate distance from desired rotation
     dist1=attack_heading-wanted_heading
     if (dist1<0) then dist1=-dist1 end
     dist2=(2*3.14159-attack_heading)+wanted_heading
     if (dist2<0) then dist2=-dist2 end

     if (dist1<1.5*turnspeed or dist2<1.5*turnspeed) then
       attack_heading=wanted_heading
       attack_mode=0 --return to normal mode where turret turns along chassis
     end


     if attack_heading>wanted_heading then
        dist1=attack_heading-wanted_heading
        dist2=(2*3.14159-attack_heading)+wanted_heading
        if (dist1 >= dist2) then
         attack_heading=attack_heading+turnspeed
         wanted_heading=-100 --in order not to trigger the 2nd one aswell
        end
        if (dist1 < dist2) then
         attack_heading=attack_heading-turnspeed
         wanted_heading=-100 --in order not to trigger the 2nd one aswell
        end
     end

     if attack_heading<wanted_heading then
        dist1=wanted_heading-attack_heading
        dist2=(2*3.14159-wanted_heading)+attack_heading
        if (dist1 >= dist2) then
         attack_heading=attack_heading-turnspeed
        end
        if (dist1 < dist2) then
         attack_heading=attack_heading+turnspeed
        end
     end


     Sleep(60)
   end
end

local function manageturret()
   Signal(SIG_TURRET)
   SetSignalMask(SIG_TURRET)

   local unit_dir=Spring.GetUnitHeading(unitID)

   local diff_dir=0


   while(true) do
     if (attack_mode==1) then
      unit_dir=Spring.GetUnitHeading(unitID)

      --turn the turret piece to exactly the needed position
      Turn(turret, y_axis,attack_heading-conversion*unit_dir)

      Sleep(30)
    end

    --normal behaviour when not in combat situation
    if (attack_mode==0) then Sleep(30) end   
   end
end


function script.Create()
 StartThread(manageturret)   
end

----driving animation
function script.StartMoving()
   --Turn(guns, x_axis, 0,0.1)
end

function script.StopMoving()

end

----aimining & fire weapon
function script.AimFromWeapon1()
   return turret
end

function script.QueryWeapon1()
   if (active_barrel == 1) then return flare1 end
   if (active_barrel == 2) then return flare2 end
end

function script.AimWeapon1( heading, pitch )
   Signal(SIG_RESTORE)
   Signal(SIG_AIM)
   SetSignalMask(SIG_AIM)   
   attack_mode=1
   Turn(guns, x_axis, -pitch,0.5)
   --aiming animation
   local turnspeed=0.06 --the speed at which the turett will turn

   local unit_dir=Spring.GetUnitHeading(unitID)

   while(true) do
     unit_dir=Spring.GetUnitHeading(unitID)


     --reduce attack_heading & wanted_heading to a number between 0 and 2*PI
     if (attack_heading<0) then
        attack_heading=attack_heading+2*3.14159
     end    
     if (attack_heading>2*3.14159) then
        attack_heading=attack_heading-2*3.14159
     end    
     --Spring.Echo("attack heading",attack_heading)

     local wanted_heading=conversion*unit_dir+heading
     if (wanted_heading<0) then
        wanted_heading=wanted_heading+2*3.14159
     end    
     if (wanted_heading>2*3.14159) then
        wanted_heading=wanted_heading-2*3.14159
     end
     --Spring.Echo("wanted heading",wanted_heading)


     local dist1=0
     local dist2=0

     --check if shot can be fired
     --calculate distance from desired rotation
     dist1=attack_heading-wanted_heading
     if (dist1<0) then dist1=-dist1 end
     dist2=(2*3.14159-attack_heading)+wanted_heading
     if (dist2<0) then dist2=-dist2 end

     if (dist1<1.5*turnspeed or dist2<1.5*turnspeed) then
       attack_heading=wanted_heading
       --fire shot !
       StartThread(restore)
       return true
     end


     if attack_heading>wanted_heading then
        dist1=attack_heading-wanted_heading
        dist2=(2*3.14159-attack_heading)+wanted_heading
        if (dist1 >= dist2) then
         attack_heading=attack_heading+turnspeed
         wanted_heading=-100 --in order not to trigger the 2nd one aswell
        end
        if (dist1 < dist2) then
         attack_heading=attack_heading-turnspeed
         wanted_heading=-100 --in order not to trigger the 2nd one aswell
        end
     end

     if attack_heading<wanted_heading then
        dist1=wanted_heading-attack_heading
        dist2=(2*3.14159-wanted_heading)+attack_heading
        if (dist1 >= dist2) then
         attack_heading=attack_heading-turnspeed
        end
        if (dist1 < dist2) then
         attack_heading=attack_heading+turnspeed
        end
     end


     Sleep(60)
   end

   --attack_heading=2*3.1415926 --this would be a full circle


   StartThread(restore)
   --return true

end



Should be bug free now and taking the shortest of both turns.


Top
 Offline Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 10 posts ] 

All times are UTC + 1 hour


Who is online

Users browsing this forum: No registered users and 0 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group

Site layout created by Roflcopter et al.