Simulations et moteurs physiques avec box2dweb

Contenu du snippet

Ce code source est tiré d'un article de mon blog technique présentant la librairie box2dweb. Cette bibliothèque initialement crée en C++ tire partie de la puissance de la balise canvas d'HTML5 pour gérer des simulations physiques en 2D. Elle a fait ses preuves et a été portée sur de nombreux langages tels que Flash/ActionScript.

Avec l'arrivée du portage de Box2D en javascript, nous pouvons immaginer simplement des intéractions physiques de qualité dans nos jeux/animations en utilisant les canvas d'HTML 5. Ci joint le lien vers le tutoriel original

IMPORTANT: la description des codes sources de ce site semble avoir un problème, afin de voir le tutoriel vérifiez qu'il n'y a pas d'espace entre les tirets de l'url...

http://www.codeyourweb.org/introduction-pratique-aux-simulations-physiques-avec-box2dweb/

PS: Il m'est impossible de poster tout le code (taille du Zip limité a 1Mo), néanmoins vous pourrez trouver le code source complet a l'adresse: http://www.codeyourweb.org/test/gamePhysics.zip

Source / Exemple :


// init box2d objects
var b2Vec2 = Box2D.Common.Math.b2Vec2;
var b2AABB = Box2D.Collision.b2AABB;
var b2BodyDef = Box2D.Dynamics.b2BodyDef;
var b2Body = Box2D.Dynamics.b2Body;
var b2FixtureDef = Box2D.Dynamics.b2FixtureDef;
var b2Fixture = Box2D.Dynamics.b2Fixture;
var b2World = Box2D.Dynamics.b2World;
var b2PolygonShape = Box2D.Collision.Shapes.b2PolygonShape;
var b2DebugDraw = Box2D.Dynamics.b2DebugDraw;

var world;
var ctx;
var canvas_width;
var canvas_height;

// 100 for 1px per cm
var scale = 100;

$('document').ready(function(){	
	var canvas = $('#gfxWindow');
    ctx = canvas.get(0).getContext('2d');
    canvas_width = parseInt(canvas.attr('width'));
    canvas_height = parseInt(canvas.attr('height'));
     
    //first create the world
  	world = createWorld();
    createGround(world);
	setInterval(step, 1000 / 60);  
	
	// create box on the scene
	$('#createBox').click(function(){
	    var options = {
        'density' : parseFloat($('#boxDensity').val()) ,
        'friction' : parseFloat($('#boxFriction').val()) ,
        'restitution' : parseFloat($('#boxRestitution').val()) ,
        'linearDamping' : 0.0 ,
        'angularDamping' : 0.0 ,
        'type' : b2Body.b2_dynamicBody
		}
		console.dir(options);
		createBox(world, "model", Math.random() * 6 , 3 , .3, .3, options);
	});
	
	// edit ground parameters
	$('#changeGroundParams').click(function(){
		var body = world.GetBodyList();
		while(body){
			var data = body.GetUserData();
				if(data != null && data == "ground"){
						body.GetFixtureList().SetDensity(parseFloat($('#groundDensity').val()));
						body.GetFixtureList().SetFriction(parseFloat($('#groundFriction').val()));
						body.GetFixtureList().SetRestitution(parseFloat($('#groundRestitution').val()));
						console.dir(body.GetFixtureList());
				}
			
			body = body.GetNext();
		}
	});	
	
	// adding velocity to all objects
	$('#moreVx').click(function(){
		var body = world.GetBodyList();
		while(body){
			var data = body.GetUserData();
				if(data != null && data == "model"){	
					body.SetSleepingAllowed(false);				
					body.SetLinearVelocity(new b2Vec2(1,4));
				}
			
			body = body.GetNext();
		}
	});
	
	$('#lessVx').click(function(){
		var body = world.GetBodyList();
		while(body){
			var data = body.GetUserData();
				if(data != null && data == "model"){
					body.SetSleepingAllowed(false);		
					body.SetLinearVelocity(new b2Vec2(-1,4));
				}
			
			body = body.GetNext();
		}
	});
	
	// wind effect on all objects
	$('#wind').click(function(){
		var body = world.GetBodyList();
		while(body){
			var data = body.GetUserData();
				if(data != null && data == "model"){	
					body.SetSleepingAllowed(false);
					if(body.GetTransform().position['x'] > 3.5){
						body.SetLinearVelocity(new b2Vec2(Math.random() * 2,Math.random() * 3));
					}else{
						body.SetLinearVelocity(new b2Vec2(0 - Math.random() * 2, Math.random() * 3));
					}
				}
			
			body = body.GetNext();
		}
	});
});

// 
function step() 
{
    var fps = 60;
    var timeStep = 1.0/fps;
	
    world.Step(timeStep , 8 , 3);
    world.ClearForces();
     
    draw_world(world, ctx);
}

// drawing and refresh physical interactions
function draw_world(world, context) 
{
    //first clear the canvas
    ctx.clearRect( 0 , 0 , canvas_width, canvas_height );
     
    ctx.fillStyle = '#EEEEEE';
    ctx.fillRect(0,0, canvas_width, canvas_height);
         
    //convert the canvas coordinate directions to cartesian
    ctx.save();
    ctx.translate(0 , canvas_height);
    ctx.scale(1 , -1);
    world.DrawDebugData();
    ctx.restore();
     
    ctx.font = 'bold 18px arial';
    ctx.textAlign = 'center';
    ctx.fillStyle = '#000000';
    ctx.fillText("Box2d Hello World Example", 400, 20);
    ctx.font = 'bold 14px arial';
}

// creating world
function createWorld(){
    //Gravity vector x, y - 10 m/s2 - thats earth!!
    var gravity = new b2Vec2(0, -10);   
    world = new b2World( gravity , true );	
	//setup debug draw
    var debugDraw = new b2DebugDraw();
    debugDraw.SetSprite(document.getElementById("gfxWindow").getContext("2d"));
    debugDraw.SetDrawScale(scale);
    debugDraw.SetFillAlpha(0.5);
    debugDraw.SetLineThickness(1.0);
    debugDraw.SetFlags(b2DebugDraw.e_shapeBit | b2DebugDraw.e_jointBit);
     
    world.SetDebugDraw(debugDraw);     
    return world;
}

// creating ground
function createGround(world) 
{
    var bodyDef = new b2BodyDef();
     
    fixDef = new b2FixtureDef;
    fixDef.density = 2500;
    fixDef.friction = 0.8;
    fixDef.restitution = 0.4;
    fixDef.shape = new b2PolygonShape;
    fixDef.shape.SetAsBox(canvas_width / scale , .1);  
	bodyDef.userData = "ground";
    bodyDef.position.Set(0 , 0);
     
    return world.CreateBody(bodyDef).CreateFixture(fixDef);
}

//Create standard boxes of given height , width at x,y
function createBox(world, name, x, y, width, height, options) 
{      
    var body_def = new b2BodyDef();
    var fix_def = new b2FixtureDef();
     
    fix_def.density = options.density;
    fix_def.friction = options.friction;
    fix_def.restitution = options.restitution;
     
    fix_def.shape = new b2PolygonShape();
         
    fix_def.shape.SetAsBox( width , height );
	body_def.userData = name;
    body_def.position.Set(x , y);
    body_def.linearDamping = options.linearDamping;
    body_def.angularDamping = options.angularDamping;
    body_def.type = options.type;
     
    var b = world.CreateBody( body_def );
    var f = b.CreateFixture(fix_def);
     
    return b;
}

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.