概要
plunkerで liquidfunやってみた。
重力を反転してみた。
写真
サンプルコード
var world = null;
var FPS = 1000 / 60;
var GRAVITY = 20;
var STAGE_WIDTH = 450;
var STAGE_HEIGHT = 450;
var SCALE = 10;
var ITEM_TYPE_PARTICLE = "item_type_particle";
var ITEM_TYPE_POLYGON = "item_type_polygon";
var PARTICLE_DENSITY = Number("3") || 3;
var PARTICLE_SIZE = Number("99") || 100;
var PARTICLE_FLAGS = b2_waterParticle;
switch ("powder")
{
case "elastic":
PARTICLE_FLAGS = b2_elasticParticle;
break;
case "powder":
PARTICLE_FLAGS = b2_powderParticle;
break;
case "viscous":
PARTICLE_FLAGS = b2_viscousParticle;
break;
case "tensile":
PARTICLE_FLAGS = b2_tensileParticle;
break;
case "colorMixing":
PARTICLE_FLAGS = b2_colorMixingParticle;
break;
}
var physicsEngine = PhysicsEngine();
var viewer = Viewer({
id: "canvas"
});
setInterval(function() {
physicsEngine.update();
viewer.update({
items: physicsEngine.getItems()
});
}, FPS);
setInterval(function() {
physicsEngine.changeGravity();
}, 20000);
function PhysicsEngine() {
var gravity_ = GRAVITY;
var items_ = [];
world = new b2World(new b2Vec2(0, gravity_));
items_.push(createStaticWall_({
width: STAGE_WIDTH,
height: 20,
x: 0,
y: 0
}));
items_.push(createStaticWall_({
width: STAGE_WIDTH,
height: 20,
x: 0,
y: STAGE_HEIGHT - 20
}));
items_.push(createStaticWall_({
width: 20,
height: STAGE_HEIGHT,
x: 0,
y: 0
}));
items_.push(createStaticWall_({
width: 20,
height: STAGE_HEIGHT,
x: STAGE_WIDTH - 20,
y: 0
}));
items_.push(createParticle_({
shapeRadius: PARTICLE_SIZE,
particleRadius: PARTICLE_DENSITY,
x: STAGE_WIDTH / 2,
y: STAGE_HEIGHT / 2
}));
return {
update: update,
changeGravity: changeGravity,
getItems: getItems
};
function update() {
world.Step(FPS / 1000, 10, 10);
}
function changeGravity() {
gravity_ = -gravity_;
world.SetGravity(new b2Vec2(0, gravity_));
}
function getItems() {
return items_;
}
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 createParticle_(params) {
var shapeRadius = params.shapeRadius / SCALE;
var particleRadius = params.particleRadius / SCALE;
var x = params.x / SCALE;
var y = params.y / SCALE;
particleSystemDef = new b2ParticleSystemDef();
particleSystemDef.radius = particleRadius;
particleSystemDef.dampingStrength = 0.1;
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 Viewer(params) {
var canvas_ = document.getElementById(params.id);
var context_ = canvas_.getContext("2d");
return {
update: update
};
function update(params) {
var items = params.items;
context_.clearRect(0, 0, STAGE_WIDTH, STAGE_HEIGHT);
var i = 0,
max;
for (i = 0, max = items.length; i < max; i = i + 1)
{
var item = items[i];
var position = null;
if (item.type === ITEM_TYPE_PARTICLE)
{
var buffer = item.particleSystem.GetPositionBuffer();
var j = 0,
max2;
for (j = 0, max2 = buffer.length; j < max2; j = j + 2)
{
context_.beginPath();
context_.arc(buffer[j] * SCALE, buffer[j + 1] * SCALE, item.particleRadius * SCALE, 0, Math.PI * 2, true);
context_.closePath();
context_.fillStyle = "rgba(229, 178, 178, 1)";
context_.fill();
}
}
else if (item.type === ITEM_TYPE_POLYGON)
{
position = item.body.GetPosition();
context_.beginPath();
var j = 0,
max2;
for (j = 0, max2 = item.shape.vertices.length; j < max2; j = j + 1)
{
var vector = item.shape.vertices[j];
if (j <= 0)
{
context_.moveTo((vector.x * SCALE) + (position.x * SCALE), (vector.y * SCALE) + (position.y * SCALE));
}
else
{
context_.lineTo((vector.x * SCALE) + (position.x * SCALE), (vector.y * SCALE) + (position.y * SCALE));
}
}
context_.closePath();
context_.strokeStyle = "rgb(127, 229, 127)";
context_.lineWidth = 1;
context_.stroke();
context_.fillStyle = "rgba(127, 229, 127, 0.5)";
context_.fill();
}
}
}
}
成果物
以上。