I asked in the newbie questions forum, but since this apparently is not simple I'll ask here. Right now I'm using [b][url=wiki.garrysmod.com/?title=PhysObj.ComputeShadowControl]PhysObj.ComputeShadowControl [img]http://wiki.garrysmod.com/favicon.ico[/img][/url][/b] inside of the [b][url=wiki.garrysmod.com/?title=ENT.PhysicsSimulate]ENT.PhysicsSimulate [img]http://wiki.garrysmod.com/favicon.ico[/img][/url][/b] hook.
Here's what I'm trying to do: My SENT is like a vehicle of sorts, but it cruises at a set distance above the ground, except when it goes off of ledges, in which case you can glide (fly). Right now I'm working on the cruising aspect. The SENT has several variables that alter how the movement works.
[list]
[*][b]Speed[/b]
This is the constant speed that the entity tries to achieve unless told otherwise.
[*][b]Acceleration[/b]
This is in units per second. It does not effect the enitity's speed after it has reached its desired speed.
[*][b]Turn[/b]
This is how fast the entity turns when the player presses their strafe keys. It is in degrees per second.
[*][b]Handling[/b]
This is where things get tricky. I'll try and explain this as best I can.
Handling determines how quickly the current move vector changes to the one that the player is trying to move in based on current speed. The turn variable and the handling variable do not effect one another, but they do combine to represent the control the player has over the vehicle. In other words, Turn + Handling = Control.
[b]Here are some examples of how this would work:[/b]
[list][*]High turn + low handling = Spinning around when turning while sliding in your current move vector.
[*]Low turn + high handling = Very gradual turning.
[*]High turn + high handling = Moving and turning exactly where you intend to.
[*]Low turn + low handling = No control at all.[/list]
Most of the time, the mix will be somewhere in between. I'm just using extremes so you get the picture.
[*][b]Glide[/b]
This one is dependant on the input of the forward/back keys. Forward means aim down, back means aim up. The number here determines how high and far we can glide, the degrees of pitch change per second, the maximum upward pitch before no longer travelling forward and up, our speed and acceleration in air, and the amount of time it takes before descent. All of this is also in direct relation to the previous values presented.
[/list]
Now that you understand the issue (I hope), it's time for the math, which is what I suck at.
Here's what I have so far:
[lua]
function ENT:PhysicsSimulate( phys, delta )
phys:Wake()
local ply = self.Rider -- Our player controlling the SENT
local turn, speed
if self.Rider then
turn, speed = --This is what I need to find...
else
return SIM_NOTHING
end
local accel = 5 --Our acceleration
local maxspeed = 25 --Our speed
local curvec = speed or self:GetVelocity() --Our current speed
if curvec:Length() >= maxspeed then
accel = 1
end
local newpos = (curvec*delta) + speed * (0.5 * accel * (delta^2)) --Our next position to move to
local dist = (self:GetPos() - newpos):Length()
local sta = self:GetVelocity():Length()/dist --seconds to arrive
self.ShadowParams.secondstoarrive = sta // How long it takes to move to pos and rotate accordingly - only if it _could_ move as fast as it want - damping and max speed/angular will make this invalid (Cannot be 0! Will give errors if you do)
self.ShadowParams.pos = newpos // Where you want to move to
self.ShadowParams.angle = turn // Angle you want to move to
self.ShadowParams.maxangular = 1 // What should be the maximal angular force applied
self.ShadowParams.maxangulardamp = 3 // At which force/speed should it start damping the rotation
self.ShadowParams.maxspeed = 4 // Maximal linear force applied
self.ShadowParams.maxspeeddamp = 5 // Maximal linear force/speed before damping
self.ShadowParams.dampfactor = 0.8 // The percentage it should damp the linear/angular force if it reaches it's max amount
self.ShadowParams.teleportdistance = 0 // If it's further away than this it'll teleport (Set to 0 to not teleport)
self.ShadowParams.deltatime = deltatime // The deltatime it should use - just use the PhysicsSimulate one
phys:ComputeShadowControl(self.ShadowParams)
end
[/lua]
In short, none of this works yet. I haven't a clue as to how to make all of the ShadowParams work cohesively.
Anyone know how I can achieve this kind of movement I've described?
This sounds like a Jet Moto type of device. I wanted to make this work within e2.
[QUOTE=evan_madore;20035454]This sounds like a Jet Moto type of device. I wanted to make this work within e2.[/QUOTE]
It's for a gamemode I'm making. I can't really release any more information until I have this done though.
So you want to figure out what angle the 'ship' is to move to? How will the player be controlling the direction? Pointing the mouse? Keyboard? (using the mouse would be the most simple way imo)
More details :D
[QUOTE=MGinshe;20036315]So you want to figure out what angle the 'ship' is to move to? How will the player be controlling the direction? Pointing the mouse? Keyboard? (using the mouse would be the most simple way imo)
More details :D[/QUOTE]
Read it. I said it's controlled by the WASD keys (i.e. Strafe and forward/back).
[QUOTE=grea$emonkey;20036335]Read it. I said it's controlled by the WASD keys (i.e. Strafe and forward/back).[/QUOTE]
Damnit, should have read that a little better.
And let me get this a little clearer about the turning control. One of the values is how fast you turn, one of them is how accurately that turn is (so holding left strafe with a low Handling would end up in you turning too far)
[QUOTE=MGinshe;20036397]Damnit, should have read that a little better.
And let me get this a little clearer about the turning control. One of the values is how fast you turn, one of them is how accurately that turn is (so holding left strafe with a low Handling would end up in you turning too far)[/QUOTE]
Think of it like this. A car is speeding down a highway and does a sharp turn. If handling is low on this car, it spins out of control until its speed is low enough to get back into control. If the handling is high, the car will basically turn and move exactly where it was meant to.
So maybe something like:
[lua]
function Turning()
if( TurnValueBlah ) then // something unique, so as not to conflict. make sure turnvalueblah is actually existant
if( ply:KeyDown( side ) ) then
TurnValueBlah = TurnValueBlah + ((TurnValueBlah+TurningSpeed)/Handeling) // So the longer we hold the key down, the faster we turn
if( TurnValueBlah > MaxTurnSpeed ) then
TurnValueBlah = MaxTurnSpeed
end
elseif( ply:KeyDown( otherside ) ) then
TurnValueBlah = TurnValueBlah - ((TurnValueBlah+TurningSpeed)/Handeling) // So the longer we hold the key down, the faster we turn
if( TurnValueBlah < MinTurnSpeed ) then
TurnValueBlah = MinTurnSpeed
end
elseif( !ply:KeyDown( side ) and !ply:KeyDown( otherside ) ) then
if(
TurnValueBlah > 1 ) then // we have turned in one direction
TurnValueBlah = TurnValueBlah - ((TurnValueBlah+TurningSpeed)/Handeling)
elseif( TurningSpeed < -1 ) then
TurnValueBlah = TurnValueBlah + ((TurnValueBlah+TurningSpeed)/Handeling)
end
end
end
TurnAngleBlah = Angle( TurnAngleBlah.p, TurnAngleBlah.y, TurnAngleBlah.r ) // you would add TurnValBlah to the pitch, yaw, or roll (i forget which order they go in, and which one controll rotation on the axis you want)
return TurnAngleBlah
end
[/lua]
And yes, im tired too. You kinda get the point from the pseudo code. It might work, but as i said, im tired.. So thats my excuse.
I'm about to fall asleep. If I don't reply soon after you post code, it means I'll be back in 8 or 10 hours. :smile:
[editline]02:58AM[/editline]
[QUOTE=MGinshe;20036437]-snip-[/QUOTE]
What?
Gah, stupid laptop fucked all the tabbing up :/
[editline]07:16PM[/editline]
I suppose that means you went off. At least now i have time to make something decent :D
[editline]09:05PM[/editline]
~130 views and im the only post?
It sounds very much like you should just look into how wings work (and a glider is essentially just a wing), check the wing-stool or some of the wings made in e2 (although I'm not sure if people ever released those). Most of this can be faked pretty easily, but getting the right feel requires that you do look into how wings work, shouldn't be terribly complicated.
Here's a basic code that half worked. The effect I was going for was the ability to hover above any surface (caused me a lot of pain).
[lua]function ENT:PhysicsSimulate( phys, deltatime )
if self.OnTrack and self.Pilot and self.InFlight and self.OnTrack then
local track = nil
for _,v in ipairs(ents.FindInSphere(self.Entity:GetPos(),200)) do
if v:GetClass() == "env_track" then track = v end
end
local tracktr = util.TraceLine({start = self.Entity:GetPos(),endpos = self.Entity:GetPos() - self.Entity:GetUp() * 300,filter=self.Entity})
if !track or track.Entity != track then return end
phys:Wake()
if self.Pilot:KeyDown(IN_FORWARD) then self.Accel = math.Approach(self.Accel,1000,2.5)
elseif self.Pilot:KeyDown(IN_BACK) then self.Accel = math.Approach(self.Accel,-1000,-2.5)
else
if self.Accel > 0 then self.Accel = math.Approach(self.Accel,0,-4.5)
else self.Accel = math.Approach(self.Accel,0,4.5)
end
end
local pr={}
pr.secondstoarrive = 0.5;
pr.pos = tracktr.HitPos + tracktr.HitNormal * 100 + self.Entity:GetForward()*self.Accel
pr.maxangular = 20000;
pr.maxangulardamp = 50;
pr.maxspeed = 1000000;
pr.maxspeeddamp = 500000;
pr.dampfactor = 1;
pr.teleportdistance = 5000;
local fwd = self.Entity:GetForward()
local hit = tracktr.HitNormal
/* if self.LastNormal != hit:Angle() and CurTime() - self.NormalWait > 1 then
self.LastNormal = hit:Angle()
self.Angle = hit:Angle()
self.NormalWait = CurTime()
elseif CurTime() - self.NormalWait < 1 then
self.Angle = hit:Angle()
end */
if self.Pilot:KeyDown(IN_MOVERIGHT) then
self.AngInc = self.AngInc + 1
pr.pos = pr.pos + self.Entity:GetRight() * 150
elseif self.Pilot:KeyDown(IN_MOVELEFT) then
self.AngInc = self.AngInc - 1
pr.pos = pr.pos - self.Entity:GetRight() * 150
end
self.Angle = hit:Angle()
self.Angle.y = self.Entity:GetAngles().y
self.Angle.pitch = self.Angle.pitch - 270
// self.Angle = self.Angle + self.Entity:GetRight() * self.AngInc
pr.angle = self.Angle
pr.deltatime = deltatime
phys:ComputeShadowControl(pr)
end
end [/lua]
[QUOTE=MGinshe;20036437]So maybe something like:
And yes, im tired too. You kinda get the point from the pseudo code. It might work, but as i said, im tired.. So thats my excuse.[/QUOTE]
I'll have to try that.
[QUOTE=Syranide;20039317]It sounds very much like you should just look into how wings work (and a glider is essentially just a wing), check the wing-stool or some of the wings made in e2 (although I'm not sure if people ever released those). Most of this can be faked pretty easily, but getting the right feel requires that you do look into how wings work, shouldn't be terribly complicated.[/QUOTE]
Well, gliding for this is really more like a limited form of flying.
[QUOTE=Entoros;20039949]Here's a basic code that half worked. The effect I was going for was the ability to hover above any surface (caused me a lot of pain).[/QUOTE]
The main issue I'm having is making it move forward, and combining turning/handling.
I can see a lot of stuff you're not utilizing in there. You could be smoothly changing the angles with shadowcontrol, and you shouldn't need a trace for this.
Here's my new code:
[lua]
function ENT:CalcSpeed()
local dSpeed = self.DesiredSpeed --This is our top speed
local cSpeed = self:GetVelocity():Length() --This is our current speed
local Accel = self.Acceleration --This is the time it takes to get there
local newSpeed = cSpeed
if (cSpeed < dSpeed) then
newSpeed = cSpeed + ( cSpeed * (Accel/dSpeed) )
else
newSpeed = dSpeed
end
if !self.Damaged and self.Cruising then
end
return newSpeed
end
function ENT:CalcMove()
if !self.Rider then return false end
local ply = self.Rider
local doDismount = ( ply:KeyDown( IN_BACK ) and ply:KeyDown( IN_JUMP ) and true )
if doDismount then
self:Dismount()
end
local turnDir = ( ply:KeyDown( IN_MOVELEFT ) and -1 ) or ( ply:KeyDown( IN_MOVERIGHT ) and 1 ) or 0 -- Left, right, or straight?
local glideDir = ( ply:KeyDown( IN_BACK ) and 1 ) or ( ply:KeyDown( IN_FORWARD ) and -1 ) or 0 -- Up, down, or level?
local traceGroundNorm = util.QuickTrace( self.Entity:GetPos(), self.Entity:GetPos() + vector_up * -self.Hover, { self, ply } ) -- Trace the ground
if traceGroundNorm.Hit then
self.Cruising = true
else
self.Gliding = true
end
local normAng = traceGroundNorm.HitNormal:Angle() or Angle(0,0,0) -- The angle of the normalized vector of the ground
// Values to clamp our rotations by
local pitchLimit = 15 + ( (self.Gliding and 60) or 0 ) -- If we are _, our _ limit will be _
local yawLimit = 45 + ( (self.Cruising and 45) or 0 ) -- If we are _, our _ limit will be _
local rollLimit = 35 + ( (self.Gliding and 55) or 0 ) -- If we are _, our _ limit will be _
local glideDeg = math.Clamp( ( self.TurnPower * glideDir ), -pitchLimit, pitchLimit ) -- Our pitch (up/down)
local turnDeg = math.Clamp( ( self.TurnPower * turnDir ), -yawLimit, yawLimit ) -- Our yaw (left/right)
local tiltDeg = math.Clamp( ( self.TurnPower * turnDir ), -rollLimit, rollLimit ) -- Our roll (left/right)
//local curAngles = self.Entity:GetAngles()
local turnAng = self.Entity:GetAngles()
if turnDir == 0 then
turnAng = self.Entity:GetAng
// Modify our angles
turnAng:RotateAroundAxis( self.Entity:GetAngles():Forward(), glideDeg ) -- This should modify our pitch to what we want.
turnAng:RotateAroundAxis( self.Entity:GetAngles():Up(), turnDeg ) -- This should modify our yaw to what we want.
turnAng:RotateAroundAxis( self.Entity:GetAngles():Right(), tiltDeg ) -- This should modify our roll to what we want.
turnAng = turnAng + normAng
local desiredVec = turnAng:Forward() * self:CalcSpeed()
local currentVec = self.Entity:GetVelocity()
// Our newVec is what will come out as the final move vector; handlingVec is a vector added/subtracted by our current and desired vectors
local newVec, handlingVec = Vector(), Vector(1, 1, 1) * self.Handling
local currentVec, desiredVec = self.Entity:GetVelocity(), self.Entity:GetAngles():Forward()
// Here is the part that's supposed to make the machine slide when trying to turn
currentVec = currentVec - (handlingVec * turnDir)
desiredVec = desiredVec + (handlingVec * turnDir)
newVec = desiredVec
newVec.z = ( ( !self.Gliding and !self.Charging ) and traceGroundNorm.HitNormal * 5 ) or newVec.z
return newVec, turnAng
end
function ENT:PhysicsSimulate(phys, delta)
phys:Wake()
local moveVec, moveAng -- Define our values
if self.Rider then
moveVec, moveAng = self:CalcMove() -- Set our values if we have a rider
else
return SIM_NOTHING -- Otherwise we don't do anything
end
local speed = self:CalcSpeed()
moveVec = moveVec * speed
local newPos = (moveVec * delta) //+ self:GetVelocity():Length() * (0.5 * self.Acceleration * (delta^2)) --Our next position to move to
--print(tostring(newPos))
--self.ShadowParams.secondstoarrive = 1 // How long it takes to move to pos and rotate accordingly - only if it _could_ move as fast as it want - damping and max speed/angular will make this invalid (Cannot be 0! Will give errors if you do)
self.ShadowParams.pos = newPos // Where you want to move to
self.ShadowParams.angle = moveAng // Angle you want to move to
self.ShadowParams.maxangular = 1000 // What should be the maximal angular force applied
self.ShadowParams.maxangulardamp = 1000 // At which force/speed should it start damping the rotation
self.ShadowParams.maxspeed = 1000 // Maximal linear force applied
self.ShadowParams.maxspeeddamp = 1000*2 // Maximal linear force/speed before damping
self.ShadowParams.dampfactor = 0.8 // The percentage it should damp the linear/angular force if it reaches it's max amount
self.ShadowParams.teleportdistance = 0 // If it's further away than this it'll teleport (Set to 0 to not teleport)
self.ShadowParams.deltatime = deltatime // The deltatime it should use - just use the PhysicsSimulate one
phys:ComputeShadowControl(self.ShadowParams)
end
[/lua]
I tried doing a total rewrite. It doesn't work, but it's getting closer.
Problems:
-It always moves to Vector(0,0,0).
-When turning, it sets the angles in comparison to one another. In other words, it changes pitch, then changes yaw in comparison to that, and then changes roll in comparison to that.
-Since it isn't going anywhere, I can't tell whether handling works, but I'm pretty sure it doesn't.
Don't mean to be nit picky, but the var on line 29 could be thrown into the if on 31, instead of making a var (even if it is local)
[QUOTE=MGinshe;20054605]Don't mean to be nit picky, but the var on line 29 could be thrown into the if on 31, instead of making a var (even if it is local)[/QUOTE]
Right. Forgot. Did a lot of copy-pasta.
That still does not solve my problem.
I understand that I am not contributing anything to help your problem, grea$emonkey, but your OP has a typo in it.
What it is now:
[QUOTE]
[LIST]
[*]High turn + low handling = Spinning around when turning while sliding in your current move vector.
[*]Low turn + high handling = Very gradual turning.
[*]High turn + high handling = Moving and turning exactly where you intend to.
[*]Low turn + high handling = No control at all.
[/LIST][/QUOTE]
What it [I]Should[/I] be:
[QUOTE]
[LIST]
[*]High turn + low handling = Spinning around when turning while sliding in your current move vector.
[*]Low turn + [B][I]LOW[/I][/B] handling = Very gradual turning.
[*]High turn + high handling = Moving and turning exactly where you intend to.
[*]Low turn + high handling = No control at all.
[/LIST][/QUOTE]
I am sorry for being so anal about this. I just got confused and thought I should try to fix the problem.
[QUOTE=XavierStudios;20081474]I understand that I am not contributing anything to help your problem, grea$emonkey, but your OP has a typo in it.
What it is now:
What it [I]Should[/I] be:
I am sorry for being so anal about this. I just got confused and thought I should try to fix the problem.[/QUOTE]
Actually, Low turn + low handling would be almost the same as low turn + high handling, except the first one would slide around more. There [i]is[/i] a difference. Turning and handling are two separate things, but they act on one another to create a general concept of [i]control[/i].
But you're right, the last one was a typo, not the second one.
[QUOTE=grea$emonkey;20082398]Actually, Low turn + low handling would be almost the same as low turn + high handling, except the first one would slide around more. There [I]is[/I] a difference. Turning and handling are two separate things, but they act on one another to create a general concept of [I]control[/I].[/QUOTE]
My bad, it's just you had low turn + high handling twice which confused me.
You win this round. Well played.
Anyways, it has started to work. I recoded it, but it is a little funky. Very hard to describe what it's doing wrong.
[editline]02:22PM[/editline]
[QUOTE=XavierStudios;20082475]My bad, it's just you had low turn + high handling twice which confused me.
You win this round. Well played.[/QUOTE]
Thanks.
Upload the vid :)
Easier to see the problem if we can well.. see it..
[QUOTE=MGinshe;20097602]Upload the vid :)
Easier to see the problem if we can well.. see it..[/QUOTE]
Well that's just it, sometimes it works and sometimes it won't. I think most of the problems have to do with angles. If you don't fully understand angles, I found these flight dynamics pictures very useful:
Pitch: Aiming up/down
[img_thumb]http://upload.wikimedia.org/wikipedia/commons/4/48/Aptch.gif[/img_thumb]
Yaw: Turning left/right
[img_thumb]http://upload.wikimedia.org/wikipedia/commons/c/c5/Ayaw.gif[/img_thumb]
Roll: Tilting from side-to-side (i.e. Do a barrel [i]roll[/i])
[img_thumb]http://upload.wikimedia.org/wikipedia/commons/c/cc/Aileron_roll.gif[/img_thumb]
Here is what needs to be fixed:
[list]
This SENT uses the normal of the ground below it to determine a lot of things. This does not appear to be working.
[list][*]It is supposed to hover at a vector only a little bit above the ground using the normal. It seems to hover at the Z height of Vector(0,0,0) when I'm trying to use a vector that's 5 units about current ground height.
[*]I need this thing to stay roughly upright based on the angle of the ground below it. That means I need to use the ground normal as a reference point for pitch and roll.[/list]
[/list]
[list]
Movement is acting funky.
[list][*]For some reason it moves in the forward direction my pitch is pointing in. Pitch shouldn't be doing anything until I get gliding done. Could be that as soon as it spawns, it's pitch (or maybe it's the roll) turns about 90 degrees. I think that is due to my angle:RotateAroundAxis() is set up wrong.
[*]Turning yaw doesn't seem to point me where I want to go. I can't really explain this with words or a video.
[*]Turning roll is not working how I want it to. Since roll effects yaw and not pitch, it makes the angles really weird. Basically, the roll can turn this thing upside down if I let it.[/list]
[/list]
[list]
Some stuff that still needs to be scripted:
[list][*]Acceleration.
[*]Handling.
[*]Gliding.
[*]I'm probably forgetting something...[/list]
[/list]
I also want to change some collision stuff. The best way I can describe this is that I want it to kinda work like a player's collisions, but with more of a bounce. When this thing hits a wall, it kinda sticks to it. I want collisions to be sort of like that of a bounding box, except it doesn't get stuck in corners. It should be able to easily turn around when its against a wall.
[url=http://luabin.foszor.com/code/gamemodes/base/entities/entities/base_anim/init.lua#55]Evilness[/url]
You should look into the [url=http://www.facepunch.com/showthread.php?t=484237]hoverboard[/url], it uses PhysicsSimulate
Sorry, you need to Log In to post a reply to this thread.