public Wheel( b2World b2world, double x, double y, double width, double length, bool revolving, bool powered ) { this.revolving = revolving; this.powered = powered; this.Initialize = car => { /* wheel object pars: car - car this wheel belongs to x - horizontal position in meters relative to car's center y - vertical position in meters relative to car's center width - width in meters length - length in meters revolving - does this wheel revolve when steering? powered - is this wheel powered? */ var position = new double[] { x, y }; //this.car=pars.car; //this.revolving=pars.revolving; //this.powered=pars.powered; //initialize body var def = new b2BodyDef(); def.type = b2Body.b2_dynamicBody; def.position = car.body.GetWorldPoint(new b2Vec2(position[0], position[1])); def.angle = car.body.GetAngle(); this.body = b2world.CreateBody(def); //initialize shape var fixdef = new b2FixtureDef(); fixdef.density = 1; fixdef.isSensor = true; //wheel does not participate in collision calculations: resulting complications are unnecessary var fixdef_shape = new b2PolygonShape(); fixdef.shape = fixdef_shape; fixdef_shape.SetAsBox(width / 2, length / 2); body.CreateFixture(fixdef); var jointdef = new b2RevoluteJointDef(); //create joint to connect wheel to body if (revolving) { jointdef.Initialize(car.body, body, body.GetWorldCenter()); jointdef.enableMotor = false; //we'll be controlling the wheel's angle manually } else { jointdef.Initialize(car.body, body, body.GetWorldCenter() //, new b2Vec2(1, 0) ); jointdef.enableLimit = true; //jointdef.lowerTranslation = 0; //jointdef.upperTranslation = 0; } b2world.CreateJoint(jointdef); #region setAngle this.setAngle = (angle) => { /* angle - wheel angle relative to car, in degrees */ body.SetAngle(car.body.GetAngle() + angle.DegreesToRadians()); }; #endregion #region getLocalVelocity Func<double[]> getLocalVelocity = delegate { /*returns get velocity vector relative to car */ var res = car.body.GetLocalVector(car.body.GetLinearVelocityFromLocalPoint(new b2Vec2(position[0], position[1]))); return new double[] { res.x, res.y }; }; #endregion #region getDirectionVector Func<double[]> getDirectionVector = delegate { /* returns a world unit vector pointing in the direction this wheel is moving */ if (getLocalVelocity()[1] > 0) return vectors.rotate(new double[] { 0, 1 }, body.GetAngle()); else return vectors.rotate(new double[] { 0, -1 }, body.GetAngle()); }; #endregion #region getKillVelocityVector Func<double[]> getKillVelocityVector = delegate { /* substracts sideways velocity from this wheel's velocity vector and returns the remaining front-facing velocity vector */ var velocity = body.GetLinearVelocity(); var sideways_axis = getDirectionVector(); var dotprod = vectors.dot(new[] { velocity.x, velocity.y }, sideways_axis); return new double[] { sideways_axis[0] * dotprod, sideways_axis[1] * dotprod }; }; #endregion #region killSidewaysVelocity this.killSidewaysVelocity = delegate { /* removes all sideways velocity from this wheels velocity */ var kv = getKillVelocityVector(); body.SetLinearVelocity(new b2Vec2(kv[0], kv[1])); }; #endregion }; }