Hiya. Downloaded this game back in 2009 (when you could play 5 minutes for free), thought it was OK but didn't like the way character movement worked, especially the ACrabs. Didn't buy it.
Came back a little bit ago, read that there was a campaign finally, paid my $18. Little disappointed in the overall polish, and the fact the campaign doesn't actually work with an AI even in a rudimentary way, but whatever, skirmish stuff with mods is reasonably fun.
However, character movement still is, well, sub-optimal. Mod characters that aren't flying around with jets or ignoring forces don't generally work well. I found this very annoying; I paid for a game where you can buy tanks and various flavors of vehicular death machines, and most of them are, well, not fun.
Here's some code to fix that. It still has some issues (see notes below) but it's close to being a good standard solution and after testing it with a lot of different ACrab variants, I think it's solid enough to use. License is CC-NC(iow, you can't use it in a product you charge for, but otherwise fair game, I don't care about credit).
Anyhow, hope it helps people out; I got the Werhmacht mod's tanks working nicely with this, and you should see how well it works with the Coalition Dreadnought- definitely makes things a lot less frustrating
This variation is for the Coalition Dreadnought. See comments in the code to adjust for your own creations. Should note that making a hovercraft or hovertank with this is pretty easy; just adjust the sections regarding height to apply anti-grav forces and sensor distances.
Code:
function Create(self) --Initialize some variables that will get used later.self.FrontVec = Vector(self.Pos.X + 50,self.Pos.Y); self.BackVec = Vector(self.Pos.X + 50,self.Pos.Y); self.timer = Timer(); end
function Update(self) --Start our loop, every 10ms. if self.timer:IsPastSimMS(10) then
--Sensor distances. It's crucial that they're positioned about as long as the body. --Longer than the body results in some oversteer later, which may be good or bad. --Shorter results in understeer and depending on depth test... --...may give you really bad results ;-) self.FrontVec.X = self.Pos.X + 8; self.FrontVec.Y = self.Pos.Y; self.BackVec.X = self.Pos.X - 8; self.BackVec.Y = self.Pos.Y;
--Must kick Actor out of the terrain pixels slightly to avoid binding forces self:MoveOutOfTerrain(3) --Set up the data collection from our altitude sensors --Uses 100 pixel check here, but you can use shorter values if small character... --...which will greatly decrease the costs, as this is fairly expensive. local frontAlt = SceneMan:FindAltitude(self.FrontVec, 100, 0) local backAlt = SceneMan:FindAltitude(self.BackVec, 100, 0) --If we don't get a hit from FindAltitude, give it a value that tells the code... --...to adjust accordingly and not fail. if frontAlt == nil then frontAlt = -100 end if backAlt == nil then backAlt = -100 end --Get the relative altitudes for the front and back sensors. local groundFrontAlt = math.abs(self.Pos.Y - frontAlt) local groundBackAlt = math.abs(self.Pos.Y - backAlt)
--Moves altitude slightly upwards where it's necessary. --Important bit here- adjust the altitude value until it's stable and not too floaty. --This specific altitude is slightly lower than the midpoint of the sprite. local centerAlt = self:GetAltitude(0,0) if (centerAlt < 16 or frontAlt < 16 or backAlt < 16) and centerAlt > -5 then self.Pos.Y = self.Pos.Y - 1; self.Vel.Y = self.Vel.Y - 0.1 end
--Brute-force change in velocity over time. --If accel is set really high, bad things will happen ;-) local speed_max = 8.0 local accel = 1.0 if self:GetController():IsState(Controller.MOVE_LEFT) then self.Vel.X = math.max(self.Vel.X - accel,-speed_max) end if self:GetController():IsState(Controller.MOVE_RIGHT) then self.Vel.X = math.min(self.Vel.X + accel,speed_max) end
--Rotational control; provides some rotational force over time to raise/lower the body. --Note that the back control is stronger than the front, because of some lame body-lean... --...that is apparently hard-coded into ACrab skeletal sim :-/ if self.HFlipped then --print("flipped") if math.abs(groundFrontAlt - groundBackAlt) < 1 then if groundFrontAlt > groundBackAlt then --print("front is higher than back") self.AngularVel = math.min(self.AngularVel + 0.05,0.25) end
if groundFrontAlt < groundBackAlt then --print("back is higher than front") self.AngularVel = math.max(self.AngularVel - 0.1,-0.375) end else if groundFrontAlt > groundBackAlt then --print("front is higher than back") self.AngularVel = math.min(self.AngularVel + 0.1,0.5) end
if groundFrontAlt < groundBackAlt then --print("back is higher than front") self.AngularVel = math.max(self.AngularVel - 0.2,-0.75) end end else --print("not flipped") if math.abs(groundFrontAlt - groundBackAlt) < 1 then if groundFrontAlt > groundBackAlt then --print("front is higher than back") self.AngularVel = math.min(self.AngularVel + 0.1,0.375) end
if groundFrontAlt < groundBackAlt then --print("back is higher than front") self.AngularVel = math.max(self.AngularVel - 0.05,-0.25) end else if groundFrontAlt > groundBackAlt then --print("front is higher than back") self.AngularVel = math.min(self.AngularVel + 0.2,0.75)
end
if groundFrontAlt < groundBackAlt then --print("back is higher than front") self.AngularVel = math.max(self.AngularVel - 0.1,-0.5) end end end
--Brute-force adjustments of RotAngles, to prevent funky behaviors. if self.RotAngle > 0.4 then self.RotAngle = 0.4 end if self.RotAngle < - 0.4 then self.RotAngle = - 0.4 end --It's flatter, use less RotAngle. if math.abs(groundFrontAlt - groundBackAlt) < 10 then if self.RotAngle > 0.2 then self.RotAngle = 0.2 end if self.RotAngle < - 0.2 then self.RotAngle = - 0.2 end end --It's really flat, do not allow rotational forces to screw it up. if math.abs(groundFrontAlt - groundBackAlt) < 5 then if self.RotAngle > 0.1 then self.RotAngle = 0.1 end if self.RotAngle < - 0.1 then self.RotAngle = - 0.1 end end --Reset our 10ms timer self.timer:Reset(); --End our loop end --End the Update() cycle end
Notes:
1. Unresolved bug: characters are going to be able to do some strange behaviors in terms of wall-climbing. Best solution is to bring the sensors inside a bit, but it doesn't totally get rid of it because the force vector allows for upwards movement, then the collision creates a friction force and the character is stuck to the side of a wall. Probably can't be solved without using some beams to check then shoving characters out of the wall.
2. Unresolved bug: characters can, in very specific (and thankfully, rare) situations get themselves buried in pixels but able to climb upwards, as in bug 1. This really should result in the character's destruction, imho, but I guess the game doesn't see it my way. Shouldn't happen often unless you screw up your parameters.
3. Unresolved bug: angles aren't always going to provide appropriate data for the rotational force, and longer characters will have more issues with this, leading to some unrealistic behaviors. I don't think there's anything that can be done about this, but I got the T-90 in the Russian mod working pretty well with this, so I'm not quite sure how limited it is. Just don't expect miracles.
4. There's no specific AI support for patrolling or mining or whatever; should be possible to borrow that from DR's base code without too much trouble, as this does not use new keys for movement or otherwise create a nonstandard scenario.
5. Really should use forces along the character's vector instead of absolutes for a lot of this for better simulation, but tbh I felt like that was probably spending too much CPU for too little improvement.
6. Wheeled things just need straightforward spring sim to adjust final positions or just fake it by offsetting wheels based on height_then vs. height_now and do some body roll. I noticed the Dummy APC does it really brute-force; having done that before I will advise faking it, it's much cheaper if you lerp between test frames.
Oh, and one last thing: please don't send me PMs or expect me to answer questions, IDK whether I'll be around here much or not, given the slow pace of development... and most of this is self-explanatory and the code's commented very heavily to help the people who know ACrab stuff already.
Fri Dec 30, 2011 4:20 am
TheLastBanana
DRL Developer
Joined: Wed Dec 13, 2006 5:27 am Posts: 3138 Location: A little south and a lot west of Moscow
Re: Open-Source: ACrab Movement Improved
Looks like some cool stuff, although I haven't had a chance to try it out yet. Your spoiler tag was broken, so I fixed it for you - hope you don't mind.
Fri Dec 30, 2011 7:49 pm
xenoargh
Joined: Fri Dec 30, 2011 3:33 am Posts: 276
Re: Open-Source: ACrab Movement Improved
Sorry for that goof, I thought it looked OK in Preview but after I hit submit it told me I had to wait until somebody approved it, otherwise would have fixed it then
Did tests with the AI last night; this seems to work surprisingly well for them, although they continue to have major issues pathfinding through tunnels as usual.
I'd like to do the same with AHumans, but I'm fairly certain that it can't be done without major mucking around with how they operate graphically.
Fri Dec 30, 2011 8:50 pm
Asklar
Data Realms Elite
Joined: Fri Jan 07, 2011 8:01 am Posts: 6211 Location: In your office, earning your salary.
I tried this on a dummy dreadnought, and it worked very good.
Fri Dec 30, 2011 10:07 pm
Kettenkrad
Joined: Mon Oct 25, 2010 5:51 am Posts: 1198 Location: Sydney
Re: Open-Source: ACrab Movement Improved
I suppose this means I have to re-sprite my tanks. Thanks very much for this opportunity to get them to work. But dammit now I have to resprite my tanks
Sat Dec 31, 2011 12:26 am
xenoargh
Joined: Fri Dec 30, 2011 3:33 am Posts: 276
Re: Open-Source: ACrab Movement Improved
@Kettenrad: No resprite should be necessary; I got it working on your medium tank without modification. I mean, unless there are artistic reasons? I really thought the tanks were cute, although I'd honestly like to see them at scale and quite a lot less flimsy
One lil' thing to note is that for pure vehicle stuff, offsetting the feet so that the engine can't screw up and try to make it walk is a good idea.
@Asklar: I've tried Mehman's stuff over here. It's a start, but it's very slow, does weird stuff to pixels on the ground and has some other things going on that I think could be better. Moreover, it is causing some Lua errors over here, involving weapons becoming un-attached which appears to be causing the script to halt with an error state. Probably an easy fix to stop that from interfering with the script's operations, but I haven't looked into it.
TBH, I think that the problem with AHumans is engine-side and the only way to fix it mod-side is not going to be efficient, because of the number of joints involved and the math steps that would probably be required. The problem with AHumans is that their constraints don't operate correctly and they behave like floppy ragdolls all the time, when really they should only do that when they're being affected by impulse forces from impacts strong enough to change the character's velocity in a meaningful way. Fixing that on the Lua-side would involve a great deal of math fairly frequently.
There doesn't seem to be any way to change joint constraint strength Lua-side, or I'd try that out. I know that Lua can reposition the joints manually, but that's not really what I'd want the behavior to be; I'd rather see constraints that were a lot stronger unless the AHuman has been hit by something and a general lack of floppiness otherwise.
The only mod-side solution I've thought about that might provide an interim solution is to do like the "vehicles" and basically get rid of the legs entirely, representing them in a different way. IDK what that takes in terms of sprites or whether it's even possible to continue to support crouching at that point, although I'd honestly give up crouching if it meant characters could run smoothly and not generally behave very badly on the ground. This game would be so much cooler if most soldiers were ground-bound, especially if friendly Actors could pass through one another freely.
Oh, and lastly, since I mentioned the engine-side stuff. If I were a developer for this, I'd look very seriously at giving modders a generic Actor class that did not have any joints or joint behaviors defined and allow joint rotations to be defined as animations, with the joints set up to obey instructions to rotate relative degrees with constraints and constraint strengths.
Probably the vast majority of that is already in the code, other than allowing for arbitrary joints; doing it engine-side with the existing joint handler has got to be a lot cheaper than having people code it up in Lua. If Lua could call sequences to named joints, all sorts of arbitrary animations would then become possible, in a non-hackish way.
Last edited by xenoargh on Sat Dec 31, 2011 2:28 am, edited 1 time in total.
Sat Dec 31, 2011 2:20 am
Kettenkrad
Joined: Mon Oct 25, 2010 5:51 am Posts: 1198 Location: Sydney
Re: Open-Source: ACrab Movement Improved
Yup, artistic reasons.
xenoargh wrote:
One lil' thing to note is that for pure vehicle stuff, offsetting the feet so that the engine can't screw up and try to make it walk is a good idea.
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