0
0

plunkerで liquidfun その4

Posted at

概要

plunkerで liquidfunやってみた。
エンジン、やってみた。

写真

image.png

サンプルコード


var world = null;
var FPS = 1000 / 45;
var STAGE_WIDTH = 456;
var STAGE_HEIGHT = 456;
var SCALE = 10;
var ITEM_TYPE_PARTICLE = "particle";
var ITEM_TYPE_POLYGON = "polygon";
var ITEM_TYPE_CIRCLE = "circle";
var physicsEngine = PhysicsEngine();
var viewer = Viewer({
	id: "canvas"
});
function PhysicsEngine() {
	var GRAVITY = 10;
	var PARTICLE_DENSITY = 1;
	var PARTICLE_SIZE = 20;
	var PARTICLE_FLAGS = b2_waterParticle;
	var items_ = [];
	world = new b2World(new b2Vec2(0, GRAVITY));
	items_.push(createParticle_({
		shapeRadius: PARTICLE_SIZE,
		particleRadius: PARTICLE_DENSITY,
		x: 200,
		y: 50
	}));
	items_.push(createStaticWall_({
		x: 170,
		y: 20,
		width: 60,
		height: 5
	}));
	items_.push(createStaticWall_({
		x: 170,
		y: 20,
		width: 5,
		height: 215
	}));
	items_.push(createStaticWall_({
		x: 230,
		y: 30,
		width: 5,
		height: 205
	}));
	var p0 = createBox({
		x: 175,
		y: 100,
		width: 60,
		height: 50
	});
	items_.push(p0);
	var c0 = createCircle({
		x: 200,
		y: 250,
		r: 14
	});
	items_.push(c0);
	var b0 = createcircle({
		x: 200,
		y: 300,
		r: 35
	});
	items_.push(b0);
	var joint2 = new b2DistanceJointDef();
	joint2.collideConnected = false;
	joint2.frequencyHz = 0;
	joint2.dampingRatio = 0;
	joint2.length = 9.0 / SCALE;
	var j2 = joint2.InitializeAndCreate(p0.body, c0.body, p0.body.GetWorldCenter(), c0.body.GetWorldCenter());
	var joint1 = new b2RevoluteJointDef();
	joint1.enableMotor = true;
	joint1.motorSpeed = 2 * Math.PI;
	joint1.maxMotorTorque = 1e7;
	var j1 = joint1.InitializeAndCreate(b0.body, c0.body, b0.body.GetWorldCenter());
	return {
		update: update,
		getItems: getItems
	};
	function update() {
		world.Step(FPS / 1000, 10, 10);
	}
	function getItems() {
		return items_;
	}
	function createParticle_(params) {
		var shapeRadius = params.shapeRadius / SCALE;
		var particleRadius = params.particleRadius / SCALE;
		var x = params.x / SCALE;
		var y = params.y / SCALE;
		var particleSystemDef = new b2ParticleSystemDef();
		particleSystemDef.radius = particleRadius;
		particleSystemDef.dampingStrength = 0.1;
		var particleSystem = world.CreateParticleSystem(particleSystemDef);
		var shape = new b2CircleShape();
		shape.radius = shapeRadius;
		var particleGroupDef = new b2ParticleGroupDef();
		particleGroupDef.shape = shape;
		particleGroupDef.position.Set(x, y);
		particleGroupDef.flags = PARTICLE_FLAGS;
		particleSystem.CreateParticleGroup(particleGroupDef);
		return {
			type: ITEM_TYPE_PARTICLE,
			particleSystem: particleSystem,
			particleRadius: particleRadius
		}
	}
	function createStaticWall_(params) {
		var width = params.width / SCALE;
		var height = params.height / SCALE;
		var x = params.x / SCALE;
		var y = params.y / SCALE;
		var bodyDef = new b2BodyDef();
		bodyDef.type = b2_staticBody;
		bodyDef.position.Set(x, y);
		var body = world.CreateBody(bodyDef);
		var shape = new b2PolygonShape;
		shape.vertices[0] = new b2Vec2(0, 0);
		shape.vertices[1] = new b2Vec2(width, 0);
		shape.vertices[2] = new b2Vec2(width, height);
		shape.vertices[3] = new b2Vec2(0, height);
		body.CreateFixtureFromShape(shape, 0.5);
		return {
			type: ITEM_TYPE_POLYGON,
			body: body,
			shape: shape
		};
	}
	function createcircle(params) {
		var x = params.x / SCALE;
		var y = params.y / SCALE;
		var r = params.r / SCALE;
		var bodyDef = new b2BodyDef;
		bodyDef.type = b2_staticBody;
		bodyDef.position.Set(x, y);
		var body = world.CreateBody(bodyDef);
		var circle = new b2CircleShape;
		circle.radius = r;
		var fixtureDef = new b2FixtureDef();
		fixtureDef.density = 0;
		fixtureDef.shape = circle;
		fixtureDef.restitution = 0.6;
		body.CreateFixtureFromDef(fixtureDef);
		return {
			type: ITEM_TYPE_CIRCLE,
			body: body,
			shape: circle
		};
	}
	function createCircle(params) {
		var x = params.x / SCALE;
		var y = params.y / SCALE;
		var r = params.r / SCALE;
		var bodyDef = new b2BodyDef;
		bodyDef.type = b2_dynamicBody;
		bodyDef.position.Set(x, y);
		var body = world.CreateBody(bodyDef);
		var circle = new b2CircleShape;
		circle.radius = r;
		var fixtureDef = new b2FixtureDef();
		fixtureDef.density = 0.1;
		fixtureDef.friction = 1.0;
		fixtureDef.restitution = 0.1;
		fixtureDef.shape = circle;
		body.CreateFixtureFromDef(fixtureDef);
		return {
			type: ITEM_TYPE_CIRCLE,
			body: body,
			shape: circle
		};
	}
	function createBox(params) {
		var width = params.width / SCALE;
		var height = params.height / SCALE;
		var x = params.x / SCALE;
		var y = params.y / SCALE;
		var bodyDef = new b2BodyDef();
		bodyDef.type = b2_dynamicBody;
		bodyDef.position.Set(x, y);
		var body = world.CreateBody(bodyDef);
		var shape = new b2PolygonShape;
		shape.vertices[0] = new b2Vec2(0, 0);
		shape.vertices[1] = new b2Vec2(width, 0);
		shape.vertices[2] = new b2Vec2(width, height);
		shape.vertices[3] = new b2Vec2(0, height);
		body.CreateFixtureFromShape(shape, 1.6);
		return {
			type: ITEM_TYPE_POLYGON,
			body: body,
			shape: shape
		};
	}
}
function Viewer(params) {
	var canvas_ = document.getElementById(params.id);
	var ctx = canvas_.getContext("2d");
	return {
		update: update
	};
	function update(params) {
		var items = params.items;
		ctx.clearRect(0, 0, STAGE_WIDTH, STAGE_HEIGHT);
		var i;
		var j;
		for (i = 0; i < items.length; i++)
		{
			var item = items[i];
			var position = null;
			if (item.type === ITEM_TYPE_PARTICLE)
			{
				var buffer = item.particleSystem.GetPositionBuffer();
				for (j = 0; j < buffer.length; j = j + 2)
				{
					ctx.beginPath();
					ctx.arc(buffer[j] * SCALE, buffer[j + 1] * SCALE, item.particleRadius * SCALE, 0, Math.PI * 2, true);
					ctx.closePath();
					ctx.fillStyle = "rgba(229, 178, 178, 1)";
					ctx.fill();
				}
			}
			else if (item.type === ITEM_TYPE_POLYGON)
			{
				position = item.body.GetPosition();
				ctx.beginPath();
				for (j = 0; j < item.shape.vertices.length; j++)
				{
					var vector = item.shape.vertices[j];
					if (j <= 0)
					{
						ctx.moveTo((vector.x + position.x) * SCALE, (vector.y + position.y) * SCALE);
					}
					else
					{
						ctx.lineTo((vector.x + position.x) * SCALE, (vector.y + position.y) * SCALE);
					}
				}
				ctx.closePath();
				ctx.strokeStyle = "rgb(127, 229, 127)";
				ctx.lineWidth = 1;
				ctx.stroke();
				ctx.fillStyle = "rgba(127, 229, 127, 0.5)";
				ctx.fill();
			}
			else if (item.type === ITEM_TYPE_CIRCLE)
			{
				position = item.body.GetPosition();
				ctx.beginPath();
				ctx.arc(position.x * SCALE, position.y * SCALE, item.shape.radius * SCALE, 0, Math.PI * 2, false);
				ctx.closePath();
				ctx.strokeStyle = "rgb(127, 229, 127)";
				ctx.lineWidth = 1;
				ctx.stroke();
				ctx.fillStyle = "rgba(127, 229, 127, 0.5)";
				ctx.fill();
			}
		}
	}
}
setInterval(function() {
	physicsEngine.update();
	viewer.update({
		items: physicsEngine.getItems()
	});
}, FPS);



成果物

以上。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0