private void Form1_Load(object sender, EventArgs e) { sogc = new SimpleOpenGlControl(); sogc.Dock = DockStyle.Fill; sogc.Paint += new PaintEventHandler(sogc_Paint); sogc.Resize += new EventHandler(sogc_Resize); Controls.Add(sogc); sogc.InitializeContexts(); InitOpenGL(sogc.Size, 1, PointF.Empty); // Define the gravity vector. b2Vec2 gravity = new b2Vec2(0.0f, -10.0f); // Do we want to let bodies sleep? bool doSleep = true; // Construct a world object, which will hold and simulate the rigid bodies. world = new b2World(gravity, doSleep); // world.SetWarmStarting(true); { b2BodyDef bd = new b2BodyDef(); b2Body ground = world.CreateBody(bd); b2PolygonShape shape = new b2PolygonShape(); shape.SetAsEdge(new b2Vec2(-40.0f, 0.0f), new b2Vec2(40.0f, 0.0f)); ground.CreateFixture(shape, 0.0f); } { float a = 0.5f; b2CircleShape shape = new b2CircleShape(); shape.m_radius = a; b2Vec2 x = new b2Vec2(-7.0f, 0.95f); b2Vec2 y; b2Vec2 deltaX = new b2Vec2(0, 1.25f); b2Vec2 deltaY = new b2Vec2(0, 1.25f); y= deltaY; for (int j = 0; j < 8; ++j) { b2BodyDef bd = new b2BodyDef(); bd.type = b2BodyType.b2_dynamicBody; bd.position = y; b2Body body = world.CreateBody(bd); body.CreateFixture(shape, 5.0f); y += deltaY; } } GDIDebugThing.instance.SetFlags(EDebugFlags.e_shapeBit); world.SetDebugDraw(GDIDebugThing.instance); System.Timers.Timer timer = new System.Timers.Timer(); timer.Interval = 85; timer.SynchronizingObject = this; timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed); timer.Start(); }
public Car( b2World b2world, double width, double length, double[] position, double angle, double power, double max_steer_angle, double max_speed, Wheel[] wheels ) { this.wheels = wheels; // /* // pars is an object with possible attributes: // width - width of the car in meters // length - length of the car in meters // position - starting position of the car, array [x, y] in meters // angle - starting angle of the car, degrees // max_steer_angle - maximum angle the wheels turn when steering, degrees // max_speed - maximum speed of the car, km/h // power - engine force, in newtons, that is applied to EACH powered wheel // wheels - wheel definitions: [{x, y, rotatable, powered}}, ...] where // x is wheel position in meters relative to car body center // y is wheel position in meters relative to car body center // revolving - boolean, does this turn rotate when steering? // powered - is force applied to this wheel when accelerating/braking? // */ // this.max_steer_angle=pars.max_steer_angle; // this.max_speed=pars.max_speed; // this.power=pars.power; var wheel_angle = 0.0;//keep track of current wheel angle relative to car. // //when steering left/right, angle will be decreased/increased gradually over 200ms to prevent jerkyness. //initialize body var def = new b2BodyDef(); def.type = b2Body.b2_dynamicBody; def.position = new b2Vec2(position[0], position[1]); def.angle = angle.DegreesToRadians(); def.linearDamping = 0.55; //gradually reduces velocity, makes the car reduce speed slowly if neither accelerator nor brake is pressed def.bullet = true; //dedicates more time to collision detection - car travelling at high speeds at low framerates otherwise might teleport through obstacles. def.angularDamping = 0.3; this.body = b2world.CreateBody(def); //initialize shape var fixdef = new b2FixtureDef(); fixdef.density = 1.0; fixdef.friction = 0.3; //friction when rubbing agaisnt other shapes fixdef.restitution = 0.4; //amount of force feedback when hitting something. >0 makes the car bounce off, it's fun! var fixdef_shape = new b2PolygonShape(); fixdef.shape = fixdef_shape; fixdef_shape.SetAsBox(width / 2, length / 2); body.CreateFixture(fixdef); //initialize wheels foreach (var item in wheels) { item.Initialize(this); } //return array of wheels that turn when steering IEnumerable <Wheel> getRevolvingWheels = from w in wheels where w.revolving select w; // //return array of powered wheels IEnumerable <Wheel> getPoweredWheels = from w in wheels where w.powered select w; #region setSpeed Action <double> setSpeed = (speed) => { /* * speed - speed in kilometers per hour */ var velocity0 = this.body.GetLinearVelocity(); //Console.WriteLine("car setSpeed velocity0 " + new { velocity0.x, velocity0.y }); var velocity2 = vectors.unit(new[] { velocity0.x, velocity0.y }); //Console.WriteLine("car setSpeed velocity2 " + new { x = velocity2[0], y = velocity2[1] }); var velocity = new b2Vec2( velocity2[0] * ((speed * 1000.0) / 3600.0), velocity2[1] * ((speed * 1000.0) / 3600.0) ); //Console.WriteLine("car setSpeed SetLinearVelocity " + new { velocity.x, velocity.y }); this.body.SetLinearVelocity(velocity); }; #endregion #region getSpeedKMH this.getSpeedKMH = delegate { var velocity = this.body.GetLinearVelocity(); var len = vectors.len(new double[] { velocity.x, velocity.y }); return((len / 1000.0) * 3600.0); }; #endregion #region getLocalVelocity Func <double[]> getLocalVelocity = delegate { /* * returns car's velocity vector relative to the car */ var retv = this.body.GetLocalVector(this.body.GetLinearVelocityFromLocalPoint(new b2Vec2(0, 0))); return(new double[] { retv.x, retv.y }); }; #endregion #region update this.update = (msDuration) => { #region 1. KILL SIDEWAYS VELOCITY //kill sideways velocity for all wheels for (var i = 0; i < wheels.Length; i++) { wheels[i].killSidewaysVelocity(); } #endregion #region 2. SET WHEEL ANGLE //calculate the change in wheel's angle for this update, assuming the wheel will reach is maximum angle from zero in 200 ms var incr = (max_steer_angle / 200.0) * msDuration; if (steer_right == STEER_RIGHT) { wheel_angle = Math.Min(Math.Max(wheel_angle, 0) + incr, max_steer_angle); //increment angle without going over max steer } else if (steer_left == STEER_LEFT) { wheel_angle = Math.Max(Math.Min(wheel_angle, 0) - incr, -max_steer_angle); //decrement angle without going over max steer } else { wheel_angle = 0; } //update revolving wheels getRevolvingWheels.WithEach( w => w.setAngle(wheel_angle) ); #endregion #region 3. APPLY FORCE TO WHEELS var base_vect = new double[2]; //vector pointing in the direction force will be applied to a wheel ; relative to the wheel. //if accelerator is pressed down and speed limit has not been reached, go forwards var lessthanlimit = (getSpeedKMH() < max_speed); var flag1 = (accelerate == ACC_ACCELERATE) && lessthanlimit; if (flag1) { base_vect = new double[] { 0, -1 }; } else if (accelerate == ACC_BRAKE) { //braking, but still moving forwards - increased force if (getLocalVelocity()[1] < 0) { base_vect = new double[] { 0, 1.3 }; } //going in reverse - less force else { base_vect = new double[] { 0, 0.7 }; } } else { base_vect[0] = 0; base_vect[1] = 0; } //multiply by engine power, which gives us a force vector relative to the wheel var fvect = new double[] { power *base_vect[0], power *base_vect[1] }; //apply force to each wheel getPoweredWheels.WithEachIndex( (w, i) => { var wp = w.body.GetWorldCenter(); var wf = w.body.GetWorldVector(new b2Vec2(fvect[0], fvect[1])); //Console.WriteLine("getPoweredWheels ApplyForce #" + i); w.body.ApplyForce(wf, wp); } ); //if going very slow, stop - to prevent endless sliding var veryslow = (getSpeedKMH() < 4); var flag2 = veryslow && (accelerate == ACC_NONE); if (flag2) { //Console.WriteLine("setSpeed 0"); setSpeed(0); } #endregion }; #endregion }
public Wheel() { 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) => { this.rotation = angle.DegreesToRadians(); /* * 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 }; }
private void initPhysics() { CCSize s = CCDirector.SharedDirector.WinSize; var gravity = new b2Vec2(0.0f, -10.0f); _world = new b2World(gravity); float debugWidth = s.Width / PTM_RATIO * 2f; float debugHeight = s.Height / PTM_RATIO * 2f; CCDraw debugDraw = new CCDraw(new b2Vec2(debugWidth / 2f + 10, s.Height - debugHeight - 10), 2); debugDraw.AppendFlags(b2DrawFlags.e_shapeBit); _world.SetDebugDraw(debugDraw); _world.SetAllowSleeping(true); _world.SetContinuousPhysics(true); //m_debugDraw = new GLESDebugDraw( PTM_RATIO ); //world->SetDebugDraw(m_debugDraw); //uint32 flags = 0; //flags += b2Draw::e_shapeBit; // flags += b2Draw::e_jointBit; // flags += b2Draw::e_aabbBit; // flags += b2Draw::e_pairBit; // flags += b2Draw::e_centerOfMassBit; //m_debugDraw->SetFlags(flags); // Call the body factory which allocates memory for the ground body // from a pool and creates the ground box shape (also from a pool). // The body is also added to the world. b2BodyDef def = b2BodyDef.Create(); def.allowSleep = true; def.position = b2Vec2.Zero; def.type = b2BodyType.b2_staticBody; b2Body groundBody = _world.CreateBody(def); groundBody.SetActive(true); // Define the ground box shape. // bottom b2EdgeShape groundBox = new b2EdgeShape(); groundBox.Set(b2Vec2.Zero, new b2Vec2(s.Width / PTM_RATIO, 0)); b2FixtureDef fd = b2FixtureDef.Create(); fd.shape = groundBox; groundBody.CreateFixture(fd); // top groundBox = new b2EdgeShape(); groundBox.Set(new b2Vec2(0, s.Height / PTM_RATIO), new b2Vec2(s.Width / PTM_RATIO, s.Height / PTM_RATIO)); fd.shape = groundBox; groundBody.CreateFixture(fd); // left groundBox = new b2EdgeShape(); groundBox.Set(new b2Vec2(0, s.Height / PTM_RATIO), b2Vec2.Zero); fd.shape = groundBox; groundBody.CreateFixture(fd); // right groundBox = new b2EdgeShape(); groundBox.Set(new b2Vec2(s.Width / PTM_RATIO, s.Height / PTM_RATIO), new b2Vec2(s.Width / PTM_RATIO, 0)); fd.shape = groundBox; groundBody.CreateFixture(fd); // _world.Dump(); }