*UPDATED* Terrain Hugging
Note: A better method for terrain hugging is posted below this older one.Pardon the big .gif. The large size is needed to see the whole effect. You may need to let run though once to see it at true speed.
Another proof-of-concept I decided to do. The little swoosh thing (a cheap-o, 2 second sprite I made) hugs the terrain as it moves through the air. For added coolness, I made it drop emitters every 50ms slightly below its current location. These emitters would them gib themselves after (swoosh lifetime + 100)ms. The idea was to make the ground that the swoosh traveled over erupt behind it seconds after it disappeared.
I wasn't able to get the swoosh to move very well with velocities. Instead, its position is just rapidly being reset every 10ms. If I can ever get a velocity method to work, I'll post that. Also, the rotation is coded based on the slope of the terrain (it'll smoothly transition between rotations).
Would look cooler if the guy were swinging a sword
Here's the Lua for it:
Code:
function Create(self)
self.timer = Timer();
self.checkTimer = Timer();
self.checkTimerInterval = 10;
self.rotationSmoother = 5;
self.posInc = 10;
self.blastTimer = Timer();
self.Pos = SceneMan:MovePointToGround(self.Pos,15,5);
if self.Vel.X > 0 then
self.dirMod = 1;
else
self.dirMod = -1;
end
self.Vel = Vector(0,0);
end
function Update(self)
if not self.timer:IsPastSimMS(2000) then
if self.checkTimer:IsPastSimMS(self.checkTimerInterval) then
if SceneMan:FindAltitude(self.Pos,0,0) < 2 then
self:GibThis();
end
local oldPos = self.Pos;
local newPos = SceneMan:MovePointToGround(self.Pos + Vector(self.posInc*self.dirMod,-30),15,0);
local tRot = self.dirMod*math.atan2(-1*(newPos.Y-oldPos.Y),self.posInc);
if self.dirMod < 0 then
tRot = tRot + 3.14;
end
self.RotAngle = self.RotAngle + ((tRot - self.RotAngle)/self.rotationSmoother);
self.Pos = newPos;
self.checkTimer:Reset();
end
if self.blastTimer:IsPastSimMS(50) then
local rkt = CreateAEmitter("GroundBlast"); --CreateAEmitter("Particle Coalition Rocket Launcher"); --This was fun >-:)
rkt.Pos = self.Pos + Vector(0,7);
MovableMan:AddMO(rkt);
self.blastTimer:Reset();
end
end
end
--particle emitters
function Create(self)
self.timer = Timer();
end
function Update(self)
if self.timer:IsPastSimMS(1100) then
self:GibThis();
end
end
====================================
Updated Version
I decided to try and improve the terrain hugging projectile. This one now uses velocity instead of position resetting, making the effect more natural looking and less jumpy. It can also use 'OrientToVel' now too. So I don't need to use trig to figure out the rotation.
In the testing gifs below, I used blue spheres to mark the movement path of the projectile. The blue spheres also show whenever the projectile's velocity is updated. Notice how the path is a lot smoother than the one above as it travels up the cliff.
Because of an 'if statement' that I left in the script, the projectile will destroy itself if its altitude above ground drops below 2. That's what happened in the one of gifs below (left). It prevents the projectile from digging through the ground. However, this rarely happens on drops. If you want to completely prevent this from happening, remove the 3 lines that make up the "if SceneMan:FindAltitude(self.Pos,0,0) < 2 then" section.
Below are two precision tests. In the first one, look at how closely the sphere trail of the swoosh matches up with one that was previously launched from the same position and angle. There's very little variance between the two.
It isn't always exact, however. Watch what happens when two are launched at the same time, and get caught up on the sharp cliff edge. They both get a little off after that, but still stay in a line.
Feel free to use my code for whatever you can think of. Please give credit, though
This is the actual weapon you see in the .gifs above (except for the outdated one) if you want to play around with it.
Here's the new Lua:
Code:
function Create(self)
self.timer = Timer();
self.checkTimer = Timer();
self.checkTimerInterval = 10;
self.posInc = 10;
self.Pos = SceneMan:MovePointToGround(self.Pos,15,5) - Vector(0,5);
--Are we going left, or are we going right?
if self.Vel.X > 0 then
self.dirMod = 1;
else
self.dirMod = -1;
end
--So the script determines the velocity.
self.Vel = Vector(0,0);
end
function Update(self)
--Make this equal the the projectile's lifetime. Really, I don't even think this is really needed,
--since the projectile is only going to destory itself after that time has passed.
if not self.timer:IsPastSimMS(self.Lifetime) then
if self.checkTimer:IsPastSimMS(self.checkTimerInterval) then
--If it burries itself in the ground, remove it.
if SceneMan:FindAltitude(self.Pos,0,0) < 2 then
self:GibThis();
end
self.AngularVel = 0; --This keeps it from bouncing around all wierd like.
local oldPos = self.Pos;
--New pos will be 10 pixels forward, and 15 pixels above the ground.
local newPos = SceneMan:MovePointToGround(self.Pos + Vector(self.posInc*self.dirMod,-30),15,0) - Vector(0,15);
local nVel = (newPos - oldPos);
self.Vel = nVel:SetMagnitude(20*20/self.checkTimerInterval);
local rkt = CreateAEmitter("Ground Marker"); --CreateAEmitter("Particle Coalition Rocket Launcher"); --This was fun >-:)
rkt.Pos = self.Pos + Vector(0,7);
MovableMan:AddMO(rkt);
self.checkTimer:Reset();
end
end
end