Sledge Game

Discuss any questions about BEPUphysics or problems encountered.
Marvin
Posts: 32
Joined: Wed Aug 04, 2010 9:16 pm

Sledge Game

Post by Marvin »

Hey,

I wanted to make a game for Windows Phone, I'm experienced with c# but kind of new to xna. I already got some 2 games with math done for practice, now I want to start on something bigger.

I want to make a sledge game, I already modelled some mountains, and used a box to test it, it works oke, but I would like to replace the box for my model. And I also would like to now how I can get the carving effect (when the sledge is sideways and under an angle it should brake and thus have an temporarily increased friction coefficient. This would be very difficult to achieve I guess, so my best bet is probably to fake it adding 2 wheels and do it like a motor cycle.

So I would like to know how I can replace this box for my own model (should be easy to do, but could not find a proper code, I'm new to making games, but have plenty of modelling knowledge so I wanted to start off).

Thanks!
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Sledge Game

Post by Norbo »

I want to make a sledge game, I already modelled some mountains, and used a box to test it, it works oke, but I would like to replace the box for my model.
It's usually best to use a simple physics object to represent complicated graphical models. While it would be possible to create a 'physical' mesh to match the model, it would be much more computationally expensive and most likely less robust due to the complexity.

If you want a more refined physical representation than just a box, you could look into a ConvexHull or a CompoundBody composed of multiple primitives (simpler the better).

When you want to render your fancy graphical mesh, you can position it using the entity's worldTransform property. It's just a convenient composition of the entity's centerPosition and orientationMatrix properties.

You may notice that the model is offset from the physical representation to start with. This is usually because the graphics mesh wasn't centered in the same way as the physical object. You can apply a local transformation to center the graphics in the way that you want before multiplying by the entity's worldTransform. There's also other options, like re-exporting the model from the modelling program with a different center, or modifying it in the content pipeline.
And I also would like to now how I can get the carving effect
The vehicle might be a good starting point. Some very short, stiffly suspended wheels and well-tuned frictions could provide a sleddy experience. The main problem would be keeping the entire thing from flipping uncontrollably. Keeping the 'vehicle' body very low and offsetting its center of mass even further down (using the Entity.centerOfMassOffset) could help. You may find that having the center of mass almost underground feels more natural, although if you go too far it will look pretty strange when flipping through the air.

You might want to use four wheels instead of two, also. Two might work with center of mass tuning, though.

Once it seems like the vehicle is as well-tuned as it's going to get, you can look into using some more external helpers if there are still behavior problems. For example, using the UprightSpring when the vehicle tips unrecoverably would keep players from getting stuck.

It would also be possible to create a non-vehicle based implementation. The SimpleCharacterController in the demos source would be a good starting point for that kind of approach.
Marvin
Posts: 32
Joined: Wed Aug 04, 2010 9:16 pm

Re: Sledge Game

Post by Marvin »

Thanks for the advice!

I was just thinking about building some sort of skateboard as a basis. with 4 wheels indeed, and if the mass swings from the left to the right, the 4 wheels will still hit the mountain but the 2 wheels on the side where the body leans to will be closer together so the wheels would shape an arc to make the turn.
Well I think I'll work on that, it is possible to make a joint between center of the wheels and a dead mass (the body) right? Than later on I will just stick the board inbetween the wheels as a dead object just for the visuals and give the wheels full transparancy. So that the mass will swing left and right, while the board will stay in line with the slope.

Also is it possible to make scale up the map? or make a larger map with the same amount of vertices?

Thanks
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Sledge Game

Post by Norbo »

While you could indeed create joints connecting wheel entities to the body, it may be a little unstable when moving very quickly over tiny bumps.

The vehicle I was referring to in my previous post is actually the Vehicle class in BEPUphysics, which supports wheeled vehicles. You can see an example in the demos under Alternate Movement/VehicleInput.cs. It handles bumps a lot better than rigid wheels since it has built in suspension and robust raycast based ground detection.

You could do such fancy wheel-morphing tuning on the vehicle as well if you found the need for it, since the wheels can be moved arbitrarily relative to the vehicle body.
Also is it possible to make scale up the map? or make a larger map with the same amount of vertices?
You can, yes. StaticTriangleGroups have a world transformation that can include scaling. Be careful, though; there are limits to single point precision floating point numbers. If the sizes get too excessive (small or large), you can end up with poor behavior and jitter (and sometimes even crashes, which I try to track down when I can). This primarily manifests itself in the general case collision detection system.

As a rule of thumb, I recommend keeping sizes between 0.5 and 10 units per dimension per entity. For example, each individual triangle in a triangle mesh collides like an entity, so they should have dimensions from 0.5 to 10 units. It's not a rigid range, though; the engine can handle values outside of that range pretty well. Just be careful if you decide to start scaling things.

The collision system rewrite will improve robustness in such situations, but they will still exist to some degree.
Marvin
Posts: 32
Joined: Wed Aug 04, 2010 9:16 pm

Re: Sledge Game

Post by Marvin »

thanks for all the help, it's comming along better and better.

is it possible to change the shape of the wheels to cones for example? or have the sit on a 45 degrees angle outwards to add stability. I've figured something out with spheres, which works quite oke, but it needs wheels for the springs and if I point them out sideways I could still spin and slide without the wheels gripping, however when the person carves the wheels would grip and would make it steer, I think this would work pretty nice, if possible, or change the shape to cones and then steer the wheels when sideways.

I have 2 more problems, my model is out there and just sticks at the place where the collision thing is being dropped and does not follow the sledge but stays there up in the sky permanent without movement.

public static model sledge
...

StaticTriangleGroup.StaticTriangleGroupVertex[] vertices;
int[] indices;
StaticTriangleGroup.getVerticesAndIndicesFromModel(sledge, out vertices, out indices);
TriangleMesh mesh = new TriangleMesh(vertices, indices);
mesh.worldMatrix = body.worldTransform;

game.modelDrawer.add(mesh);

this is the code, obviously i'm doing something wrong here.

and last but not least, I would like to add momentum to make the thing steer, however whenever the sledge is pointing at a diffrent angle the momentum will not turn with the sledge, so when it's turned 90 degrees instead of leaning to the side, it will make the nose come up. How can I turn the momentum with the direction of where the sledge is pointing to, so a side momentum for leaning will always be leaning? thanks!
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Sledge Game

Post by Norbo »

is it possible to change the shape of the wheels to cones for example? or have the sit on a 45 degrees angle outwards to add stability. I've figured something out with spheres, which works quite oke, but it needs wheels for the springs and if I point them out sideways I could still spin and slide without the wheels gripping, however when the person carves the wheels would grip and would make it steer, I think this would work pretty nice, if possible, or change the shape to cones and then steer the wheels when sideways.
If you're just working with constraints and entities, you can pretty much do whatever you want. The question is how robust the end result will be. It's hard to say for sure for any given configuration (other than that more complex usually means harder to tune). High velocities and bumps tend to behave poorly when real rigid entities are used, which is why I mentioned the Vehicle class as a good option.
I have 2 more problems, my model is out there and just sticks at the place where the collision thing is being dropped and does not follow the sledge but stays there up in the sky permanent without movement.
That code just creates an arbitrary TriangleMesh data structure and adds it to the drawer. It doesn't follow any entity automatically.

The TriangleMesh is also somewhat heavyweight if you're just looking for rendering a model at an entity's position. I'd recommend just drawing it normally and using the entity's worldTransform to position it.
I would like to add momentum to make the thing steer, however whenever the sledge is pointing at a diffrent angle the momentum will not turn with the sledge, so when it's turned 90 degrees instead of leaning to the side, it will make the nose come up. How can I turn the momentum with the direction of where the sledge is pointing to, so a side momentum for leaning will always be leaning? thanks!
You could try modifying it based on the entity's axes. The entity.orientationMatrix.Up always points up relative to the entity (same for .Right and .Forward etc.).
Marvin
Posts: 32
Joined: Wed Aug 04, 2010 9:16 pm

Re: Sledge Game

Post by Marvin »

Thanks, I managed to get the vehicle behave quite like a sledge, the forces are in the right directions now as well.

Thanks, what is the rightway to draw a model? because now I'm drawing it in the mesh.Draw in the Draw void in the PhoneGame, however the model is slightly delayed compared to the collision object, whenever it moves faster, the offset is bigger, if it's hardly changed speed its perfectly centered.

also, this is my code for the vehicle. The wheels look really odd, but is this the right way to make them under a 45 degree angle outwards?
Matrix wheelGraphicRotation = Matrix.CreateFromAxisAngle((Vector3.Down), MathHelper.PiOver2);
vehicle.addWheel(new Wheel(
new RaycastWheelShape(.375f, wheelGraphicRotation),
new WheelSuspension(Stiffness, Damping, Vector3.Down + Vector3.Right, .5f, new Vector3(1f, -1f, 3f)),
new WheelDrivingMotor(2.5f, 30000, 10000),
new WheelBrake(1.5f, 2, .02f),
new WheelSlidingFriction(DybnamicFriction, StaticFriction)));
vehicle.addWheel(new Wheel(
new RaycastWheelShape(.375f, wheelGraphicRotation),
new WheelSuspension(Stiffness, Damping, Vector3.Down + Vector3.Left, .5f, new Vector3(1f, -1f, -3f)),
new WheelDrivingMotor(2.5f, 30000, 10000),
new WheelBrake(1.5f, 2, .02f),
new WheelSlidingFriction(DybnamicFriction, StaticFriction)));
vehicle.addWheel(new Wheel(
new RaycastWheelShape(.375f, wheelGraphicRotation),
new WheelSuspension(Stiffness, Damping, Vector3.Down + Vector3.Right, .5f, new Vector3(-1f, -1f, 3f)),
new WheelDrivingMotor(2.5f, 30000, 10000),
new WheelBrake(1.5f, 2, .02f),
new WheelSlidingFriction(DybnamicFriction, StaticFriction)));
vehicle.addWheel(new Wheel(
new RaycastWheelShape(.375f, wheelGraphicRotation),
new WheelSuspension(Stiffness, Damping, Vector3.Down + Vector3.Left, .5f, new Vector3(-1f, -1f, -3f)),
new WheelDrivingMotor(2.5f, 30000, 10000),
new WheelBrake(1.5f, 2, .02f),
new WheelSlidingFriction(DybnamicFriction, StaticFriction)));
I dont need the visuals of the wheels anyway, and it seems to work ok.

Is there a quick way to test if the body is not on the ground but in mid air?
Other than this, I'm pretty much good to go. Just wondering how to draw the model without the delay/offset and if the wheels are good this way, or how to make coneshaped wheels.

thanks for all the help so far, its a great engine!
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Sledge Game

Post by Norbo »

Thanks, what is the rightway to draw a model? because now I'm drawing it in the mesh.Draw in the Draw void in the PhoneGame, however the model is slightly delayed compared to the collision object, whenever it moves faster, the offset is bigger, if it's hardly changed speed its perfectly centered.
It sounds like you might be updating the graphical world transform before the space update runs. After the space runs, the collision object has a new position that is chronologically ahead of the graphics. It becomes noticeable if the object is moving quickly because there's more movement between frames.

The other possibility is that you are currently using an interpolated property and another non-interpolated property without realizing it. The main difference between properties like worldTransform and internalWorldTransform (assuming that you're not updating BEPUphysics asynchronously on a separate thread from your main update loop) is interpolation.

When space.simulationSettings.timeStep.useInternalTimeStepping is set to true (it is false by default), the worldTransform property interpolates between the previous frame's value and the current frame's value by an amount defined by how much time has accumulated since the last update. If the collision object is being rendered at the "internal" time while the model is being drawn at the interpolated time, the model will appear to be behind. The way to fix this is to use the properties consistently, either both internal or both interpolated. Using the interpolated properties helps with keeping movement looking smooth when the game's timestep is variable.
also, this is my code for the vehicle. The wheels look really odd, but is this the right way to make them under a 45 degree angle outwards?
Conceptually, yes, that looks about right. The wheels look strange since the graphical transforms aren't oriented the right way to start with, and it doesn't affect simulation at all so you don't need to worry about it too much.

However, it looks like both 'front' wheels are offset in the same direction, and the 'back' wheels are both offset the other way. Switching up the suspension directions will fix that real quick.

While I don't know the structure of your car body, it's a good idea to keep the ray's origins well within the body to avoid them climbing walls or trees.

I created a quick version of that code that seems to work okay with the default vehicle body entity:

Code: Select all

            float Stiffness = 2000, Damping = 100, DynamicFriction = 3, StaticFriction = 4;
            Matrix wheelGraphicRotationLeft = Matrix.CreateRotationY(MathHelper.PiOver2) * Matrix.CreateRotationZ(MathHelper.PiOver4);
            Matrix wheelGraphicRotationRight = Matrix.CreateRotationY(MathHelper.PiOver2) * Matrix.CreateRotationZ(-MathHelper.PiOver4);
            vehicle.addWheel(new Wheel(
            new RaycastWheelShape(.375f, wheelGraphicRotationRight),
            new WheelSuspension(Stiffness, Damping, Vector3.Down + Vector3.Right, .8f, new Vector3(1.1f, -.3f, 1.8f)),
            new WheelDrivingMotor(2.5f, 30000, 10000),
            new WheelBrake(1.5f, 2, .02f),
            new WheelSlidingFriction(DynamicFriction, StaticFriction)));
            vehicle.addWheel(new Wheel(
            new RaycastWheelShape(.375f, wheelGraphicRotationRight),
            new WheelSuspension(Stiffness, Damping, Vector3.Down + Vector3.Right, .8f, new Vector3(1.1f, -.3f, -1.8f)),
            new WheelDrivingMotor(2.5f, 30000, 10000),
            new WheelBrake(1.5f, 2, .02f),
            new WheelSlidingFriction(DynamicFriction, StaticFriction)));
            vehicle.addWheel(new Wheel(
            new RaycastWheelShape(.375f, wheelGraphicRotationLeft),
            new WheelSuspension(Stiffness, Damping, Vector3.Down + Vector3.Left, .8f, new Vector3(-1.1f, -.3f, 1.8f)),
            new WheelDrivingMotor(2.5f, 30000, 10000),
            new WheelBrake(1.5f, 2, .02f),
            new WheelSlidingFriction(DynamicFriction, StaticFriction)));
            vehicle.addWheel(new Wheel(
            new RaycastWheelShape(.375f, wheelGraphicRotationLeft),
            new WheelSuspension(Stiffness, Damping, Vector3.Down + Vector3.Left, .8f, new Vector3(-1.1f, -.3f, -1.8f)),
            new WheelDrivingMotor(2.5f, 30000, 10000),
            new WheelBrake(1.5f, 2, .02f),
            new WheelSlidingFriction(DynamicFriction, StaticFriction)));
Edit: Note that most behaviors achievable with diagonal suspensions should be achievable with just vertical suspensions (and a bit of tuning) if you encounter complications.
Is there a quick way to test if the body is not on the ground but in mid air?
You can check a wheel's hasSupport property to tell if it's sitting on anything. To see if an Entity is actually touching anything, you can look at it's collisionPairs property. CollisionPairs will be created if it's "near" another object (i.e. bounding boxes overlap), so to see if it's really touching, you'll need to see if any collision pair has more than zero contact points. Contact points provide more information like position, normal, and collision force as well.
Marvin
Posts: 32
Joined: Wed Aug 04, 2010 9:16 pm

Re: Sledge Game

Post by Marvin »

thanks! got it working pretty neat now.

this is the code i use to draw the model (its kind of ugly):

Code: Select all

Underneath Update in VehicleInput:

void DrawModel(Model model, Matrix transform, Matrix View, Matrix Projection)
        {
            // Copy any parent transforms.
            // Matrix[] transforms = new Matrix[model.Bones.Count];
            // snowBoard.CopyAbsoluteBoneTransformsTo(transforms);

            // Draw the model. A model can have multiple meshes, so loop.
            foreach (ModelMesh mesh in model.Meshes)
            {
                // This is where the mesh orientation is set, as well 
                // as our camera and projection.
                foreach (BasicEffect effect in mesh.Effects)
                {
                    effect.EnableDefaultLighting();
                    effect.World = transform; // transforms[mesh.ParentBone.Index] * transform;
                    effect.View = View;
                    effect.Projection = Projection;
                }

            }

        }
in PhoneGame in the Draw method I call this

modelDrawer.draw(camera.viewMatrix, camera.projectionMatrix);

foreach (ModelMesh mesh in VehicleInput.snowBoard.Meshes)
{
mesh.Draw();
}
lineDrawer.draw(camera.viewMatrix, camera.projectionMatrix);

last but not least in VehicleInput again under Update method I call:
DrawModel(snowBoard, Matrix.CreateFromYawPitchRoll((float)Math.PI / 2, (float)Math.PI / 2, 0) * Matrix.CreateTranslation(0, -1.1f, 0) * vehicle.body.worldTransform, game.camera.viewMatrix, game.camera.projectionMatrix, true);

is there a better nicer way of doing?

thanks for the code, the wheels are fine now, I adjusted the friction values damping etc. works pretty good now, unfortunately the ground is just rock hard and not very snow like, but I think I will just have to go with less deep bumps for the terrain.

Also a "trail" of snow or smoke behind the board is something I'm aiming for, what would you suggest? looking into fluid behind it or add a particle system?, I personally think a v shaped fluid behind the board would be nice since it would behave with physics. But I';m not sure.
Thanks!
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Sledge Game

Post by Norbo »

It looks like you are updating the effect transforms in the VehicleInput update. If the space is updated after the VehicleInput, then the effect transforms will be out of date and will cause graphical drift between the wheels and body.

It's possible to do the transform update and draw at the same time/place; I'd recommend this approach since it is a little easier to follow.
what would you suggest? looking into fluid behind it or add a particle system?, I personally think a v shaped fluid behind the board would be nice since it would behave with physics. But I';m not sure.
You could create a bunch of sphere entities or something with custom collision rules if you wanted to go the physical route. Spheres would collide rigidly by default, resulting in not-very-particle-like behavior. By adjusting the collision rules, you could have it so they generate contacts, but do not do normal collision response. Custom inexpensive 'soft' penalty forces could be applied within each particle's collision pair colliding event.

For more information about collision rules and events:
http://www.bepu-games.com/BEPUphysics/d ... tation.pdf
http://www.bepu-games.com/BEPUphysics/d ... tation.pdf

However, the Xbox360 under the CF is not incredibly fast, nor is the phone. It would be a good idea to test it to ensure that you have the spare CPU to do a heavy particle system like this. You can create a more fake or non-physical particle system run substantially faster, particularly with some help from the GPU.
Marvin
Posts: 32
Joined: Wed Aug 04, 2010 9:16 pm

Re: Sledge Game

Post by Marvin »

Thanks, instead of using the displaymodel classes i build my own, which did not work in sync with the updates of the system, not a smart desicion, I've found the build in model draw now and works neat.

I started on making a snowtrail which looks quite oke, however I still have some issues, I'm using boxes now, however 2d textures would be much nicer and more efficient I guess. And it follows the path of the sledge nicely, but it does not follow the curve of the terrain but the curve of the sledge. This is the second problem, Is there a way to check the angle or normal of the terrain at a certain position vector? otherwise i need to make the boxes dynamic and let them collide with high mass and highfriction so they wont slide away (which is of course pretty useless waste of processing power) if I could just lay them down following the curves of the terrain that would be nice.

thanks!
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Sledge Game

Post by Norbo »

You could get the position/normal of a mesh beneath a location by raycasting from the location downwards onto the StaticTriangleGroup.
Marvin
Posts: 32
Joined: Wed Aug 04, 2010 9:16 pm

Re: Sledge Game

Post by Marvin »

Thanks, the tracks look fine now!

Haha I came up with another few questions.

A skydome, Is there a way to implement this? for example just attach a textured sphere to the character? or do I have to model it and then load it in, the problem is how the light will get trough.

and is there a way to make the models semitransparant, for example the models I draw for the tracks look like block now even with texxtures, If I just model a plane with a texture and can make them alpha transparant would be much nicer.

Thanks
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Sledge Game

Post by Norbo »

For general development/graphics help, I'd recommend the XNA website's resources, forums, Shawn Hargreaves' blog, and other educational samples. Together they provide broader and deeper help than I can.

To answer your questions concisely, you could indeed attach a textured sphere to the camera to simulate a skydome. Lighting is faked and shadows have to be programmed specifically in order to exist, so you don't need to worry about that.

It's possible to do transparency, but the BEPUphysicsDrawer isn't designed for it. It's best to use a rendering system designed to match your game instead.
Marvin
Posts: 32
Joined: Wed Aug 04, 2010 9:16 pm

Re: Sledge Game

Post by Marvin »

Thanks, figured it out.

I try to get the total rotation of an object (so instead of it's orientation, 45 degrees plus a full circle is not 45 degrees but 45+360)

I wrote this but I can not get it to work, tried multiple variations of this:

I set AirTime = 0;
then call AirMovement(dt);
when the sledge is in the air, now the airtime works fine, however the angular rotation is incorrect.

Code: Select all

void AirMovement(float dt)
        {
            // XYZ components
            float x = Math.Abs(vehicle.body.orientationMatrix.Up.X);
            float y = Math.Abs(vehicle.body.orientationMatrix.Up.Y);
            float z = Math.Abs(vehicle.body.orientationMatrix.Up.Z);

            // Create Angle Vector
            Vector3 NewAngle = new Vector3(x, y, z);
            // Vector3 NewAngle = new Vector3((float)Math.Acos(x), (float)Math.Acos(y), (float)Math.Acos(z));

            // Set Vector to Zero
            if (AirTime == 0)
            { 
                DeltaAir = NewAngle;
                AirTransformStart = AirTransform;
                AirTransform = new Vector3(0,0,0);
            }
                // Still In The Air
            else
            {
                // Directions
                float xr = 1;
                float yr = 1;
                float zr = 1;
                if (vehicle.body.angularVelocity.X < 0)
                    xr = -1;
                if (vehicle.body.angularVelocity.Y < 0)
                    yr = -1;
                if (vehicle.body.angularVelocity.Z < 0)
                    zr = -1;

                // DeltaAir is Diffrence between OldAngle and NewAngle
                DeltaAir -= NewAngle;
                AirTransform += new Vector3(xr*Math.Abs(DeltaAir.X), yr*Math.Abs(DeltaAir.Y), zr*Math.Abs(DeltaAir.Z));
                DeltaAir = NewAngle;
            }
            AirTime += dt;
        }
Thanks!
Post Reply