Turret rotating independant from unit chassis?

Turret rotating independant from unit chassis?

Discuss game development here, from a distinct game project to an accessible third-party mutator, down to the interaction and design of individual units if you like.

Moderator: Moderators

Post Reply
User avatar
Erik
Posts: 283
Joined: 20 Aug 2009, 20:49

Turret rotating independant from unit chassis?

Post by Erik »

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.
User avatar
Beherith
Posts: 5145
Joined: 26 Oct 2007, 16:21

Re: Turret rotating independant from unit chassis?

Post by Beherith »

Im not sure I understand the question, since I believe almost all tanks do this in spring.
User avatar
Erik
Posts: 283
Joined: 20 Aug 2009, 20:49

Re: Turret rotating independant from unit chassis?

Post by Erik »

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...
User avatar
knorke
Posts: 7971
Joined: 22 Feb 2006, 01:02

Re: Turret rotating independant from unit chassis?

Post by knorke »

real world tanks keep their gun pointed at the target now matter how the chasis rotates or tilts.
ie http://www.youtube.com/watch?v=JTq2D ... page#t=18s
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...
User avatar
FLOZi
MC: Legacy & Spring 1944 Developer
Posts: 6241
Joined: 29 Apr 2005, 01:14

Re: Turret rotating independant from unit chassis?

Post by FLOZi »

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
User avatar
knorke
Posts: 7971
Joined: 22 Feb 2006, 01:02

Re: Turret rotating independant from unit chassis?

Post by knorke »

gun always aimed "downwards", no matter how chasis rotates:
Image

Code: Select all

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.
User avatar
Erik
Posts: 283
Joined: 20 Aug 2009, 20:49

Re: Turret rotating independant from unit chassis?

Post by Erik »

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: Select all

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
User avatar
knorke
Posts: 7971
Joined: 22 Feb 2006, 01:02

Re: Turret rotating independant from unit chassis?

Post by knorke »

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?
User avatar
Erik
Posts: 283
Joined: 20 Aug 2009, 20:49

Re: Turret rotating independant from unit chassis?

Post by Erik »

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.
User avatar
Erik
Posts: 283
Joined: 20 Aug 2009, 20:49

Re: Turret rotating independant from unit chassis?

Post by Erik »

Code: Select all

--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.
Post Reply

Return to “Game Development”