Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p><strong>Update:</strong> I'm currently adjusting the <a href="http://jsfiddle.net/qXpZR/8/" rel="nofollow">code</a> to produce the requested result and commenting it. </p> <pre><code>(function() { // The code is encapsulated in a self invoking function to isolate the scope "use strict"; // The following lines creates shortcuts to the constructors of the Box2D types used var B2Vec2 = Box2D.Common.Math.b2Vec2, B2BodyDef = Box2D.Dynamics.b2BodyDef, B2Body = Box2D.Dynamics.b2Body, B2FixtureDef = Box2D.Dynamics.b2FixtureDef, B2Fixture = Box2D.Dynamics.b2Fixture, B2World = Box2D.Dynamics.b2World, B2PolygonShape = Box2D.Collision.Shapes.b2PolygonShape, B2RevoluteJoint = Box2D.Dynamics.Joints.b2RevoluteJoint, B2RevoluteJointDef = Box2D.Dynamics.Joints.b2RevoluteJointDef; // This makes sure that there is a method to request a callback to update the graphics for next frame window.requestAnimationFrame = window.requestAnimationFrame || // According to the standard window.mozRequestAnimationFrame || // For mozilla window.webkitRequestAnimationFrame || // For webkit window.msRequestAnimationFrame || // For ie function (f) { window.setTimeout(function () { f(Date.now()); }, 1000/60); }; // If everthing else fails var world = new B2World(new B2Vec2(0, -10), true), // Create a world with gravity physicalObjects = [], // Maintain a list of the simulated objects windInput = 0, // The input for the wind in the current frame wind = 0, // The current wind (smoothing the input values + randomness) STRAW_COUNT = 10, // Number of straws GRASS_RESET_SPEED = 2, // How quick should the straw reset to its target angle POWER_MOUSE_WIND = 120, // How much does the mouse affect the wind POWER_RANDOM_WIND = 180; // How much does the randomness affect the wind // GrassPart is a prototype for a piece of a straw. It has the following properties // position: the position of the piece // density: the density of the piece // target: the target angle of the piece // statik: a boolean stating if the piece is static (i.e. does not move) function GrassPart(position, density, target, statik) { this.width = 0.05; this.height = 0.5; this.target = target; // To create a physical body in Box2D you have to setup a body definition // and create at least one fixture. var bdef = new B2BodyDef(), fdef = new B2FixtureDef(); // In this example we specify if the body is static or not (the grass roots // has to be static to keep the straw in its position), and its original // position. bdef.type = statik? B2Body.b2_staticBody : B2Body.b2_dynamicBody; bdef.position.SetV(position); // The fixture of the piece is a box with a given density. The negative group index // makes sure that the straws does not collide. fdef.shape = new B2PolygonShape(); fdef.shape.SetAsBox(this.width/2, this.height/2); fdef.density = density; fdef.filter.groupIndex = -1; // The body and fixture is created and added to the world this.body = world.CreateBody(bdef); this.body.CreateFixture(fdef); } // This method is called for every frame of animation. It strives to reset the original // angle of the straw (the joint). The time parameter is unused here but contains the // current time. GrassPart.prototype.update = function (time) { if (this.joint) { this.joint.SetMotorSpeed(GRASS_RESET_SPEED*(this.target - this.joint.GetJointAngle())); } }; // The link method is used to link the pieces of the straw together using a joint // other: the piece to link to // torque: the strength of the joint (stiffness) GrassPart.prototype.link = function(other, torque) { // This is all Box2D specific. Look it up in the manual. var jdef = new B2RevoluteJointDef(); var p = this.body.GetWorldPoint(new B2Vec2(0, 0.5)); // Get the world coordinates of where the joint jdef.Initialize(this.body, other.body, p); jdef.maxMotorTorque = torque; jdef.motorSpeed = 0; jdef.enableMotor = true; // Add the joint to the world this.joint = world.CreateJoint(jdef); }; // A prototype for a straw of grass // position: the position of the bottom of the root of the straw function Grass(position) { var pos = new B2Vec2(position.x, position.y); var angle = 1.2*Math.random() - 0.6; // Randomize the target angle // Create three pieces, the static root and to more, and place them in line. // The second parameter is the stiffness of the joints. It controls how the straw bends. // The third is the target angle and different angles are specified for the pieces. this.g1 = new GrassPart(pos, 1, angle/4, true); // This is the static root pos.Add(new B2Vec2(0, 1)); this.g2 = new GrassPart(pos, 0.75, angle); pos.Add(new B2Vec2(0, 1)); this.g3 = new GrassPart(pos, 0.5); // Link the pieces into a straw this.g1.link(this.g2, 20); this.g2.link(this.g3, 3); // Add the pieces to the list of simulate objects physicalObjects.push(this.g1); physicalObjects.push(this.g2); physicalObjects.push(this.g3); } Grass.prototype.draw = function (context) { var p = new B2Vec2(0, 0.5); var p1 = this.g1.body.GetWorldPoint(p); var p2 = this.g2.body.GetWorldPoint(p); var p3 = this.g3.body.GetWorldPoint(p); context.strokeStyle = 'grey'; context.lineWidth = 0.4; context.lineCap = 'round'; context.beginPath(); context.moveTo(p1.x, p1.y); context.quadraticCurveTo(p2.x, p2.y, p3.x, p3.y); context.stroke(); }; var lastX, grass = [], context = document.getElementById('canvas').getContext('2d'); function updateGraphics(time) { window.requestAnimationFrame(updateGraphics); wind = 0.95*wind + 0.05*(POWER_MOUSE_WIND*windInput + POWER_RANDOM_WIND*Math.random() - POWER_RANDOM_WIND/2); windInput = 0; world.SetGravity(new B2Vec2(wind, -10)); physicalObjects.forEach(function(obj) { if (obj.update) obj.update(time); }); world.Step(1/60, 8, 3); world.ClearForces(); context.clearRect(0, 0, context.canvas.width, context.canvas.height); context.save(); context.translate(context.canvas.width/2, context.canvas.height/2); context.scale(context.canvas.width/20, -context.canvas.width/20); grass.forEach(function (o) { o.draw(context); }); context.restore(); } document.getElementsByTagName('body')[0].addEventListener("mousemove", function (e) { windInput = Math.abs(lastX - e.x) &lt; 200? 0.2*(e.x - lastX) : 0; lastX = e.x; }); var W = 8; for (var i = 0; i &lt; STRAW_COUNT; i++) { grass.push(new Grass(new B2Vec2(W*(i/(STRAW_COUNT-1))-W/2, -1))); } window.requestAnimationFrame(updateGraphics); })(); </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload