<div id="canvas"></div>
html, body
{
width: 100%;
height: 100%;
overflow: hidden;
margin: 0;
padding: 0;
user-select: none;
}
body
{
background-color: lightgray;
}
#canvas
{
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
View Compiled
console.clear();
const colors = [0xF9B52C, 0x333333];
class Stage
{
element:HTMLElement;
app:any;
stage:any;
particleContainer:any;
containers:any[] = []
particles:any[] = [];
textures:any[] = [];
glass:any;
shine:any;
constructor(canvas:HTMLElement)
{
this.element = canvas;
this.app = new PIXI.Application(this.element.offsetWidth, this.element.offsetHeight, { antialias: false, backgroundColor : 0xD3CFE5 });
this.element.appendChild(this.app.view);
this.stage = new PIXI.Container();
this.app.stage.addChild(this.stage);
this.particleContainer = new PIXI.Container();
this.stage.addChild(this.particleContainer);
this.onResize();
}
onResize = function()
{
this.app.renderer.resize(this.element.offsetWidth, this.element.offsetHeight);
this.stage.position.x = window.innerWidth / 2;
this.stage.position.y = window.innerHeight / 2;
}
newParticle = function(color)
{
let graphic = new PIXI.Graphics();
graphic.lineStyle(0);
graphic.beginFill(color, 0.8);
graphic.drawCircle(0, 0, 2);
graphic.endFill();
let texture = this.app.renderer.generateTexture(graphic);
let sprite = new PIXI.Sprite(texture);
this.particles.push(sprite);
this.particleContainer.addChild(sprite);
return sprite;
}
}
class Sim
{
private world:any;
private width:number = 0;
private height:number = 0;
private particleSystem:any;
private particle:any;
private timeStep:number = 1.0 / 60.0;
private velocityIterations:number = 8;
private positionIterations:number = 3;
private cooldown:number = 200;
private cooling:boolean = false;
const METER:number = 100;
const OFFSET_X:number = 0;
const OFFSET_Y:number = 0;
const PADDING:number = 50;
constructor(world)
{
this.world = world;
let liquidContainerDef = new b2BodyDef();
let liquidContainer = this.world.CreateBody(liquidContainerDef);
this.onResize();
let floor = this.createWallShape(
this.width / this.METER / 2,
0.05,
new b2Vec2(this.width / this.METER / 2, this.height / this.METER + 0.05)
)
let leftWall = this.createWallShape(
0.05,
(this.height + 1000) / this.METER,
new b2Vec2(-0.05, 0)
)
let rightWall = this.createWallShape(
0.05,
(this.height + 1000) / this.METER,
new b2Vec2(this.width / this.METER + 0.05, 0)
)
liquidContainer.CreateFixtureFromDef(floor);
liquidContainer.CreateFixtureFromDef(leftWall);
liquidContainer.CreateFixtureFromDef(rightWall);
let particleSystemDef = new b2ParticleSystemDef();
particleSystemDef.radius = 0.03;
particleSystemDef.dampingStrength = 0.2;
this.particleSystem = this.world.CreateParticleSystem(particleSystemDef);
this.particle = new b2CircleShape();
}
onResize = function()
{
let h = window.innerHeight;
this.width = 254;
this.height = 180;
this.height -= this.PADDING;
}
private createWallShape(width, height, angle)
{
let wallShape = new b2PolygonShape();
wallShape.SetAsBoxXYCenterAngle(width, height, angle, 0);
let fixtureDef = new b2FixtureDef();
fixtureDef.shape = wallShape;
fixtureDef.density = 5;
return fixtureDef;
}
getParticles():number[]
{
return this.world.particleSystems[0].GetPositionBuffer();
}
step = function()
{
this.world.Step(this.timeStep, this.velocityIterations, this.positionIterations);
this.time += 1 / 60;
}
addParticles = function()
{
if(!this.cooling)
{
this.cooling = true;
this.particle.position.Set((this.width / 2) / this.METER, -this.height * 2 / this.METER);
this.particle.radius = 1;
let particleGroupDef = new b2ParticleGroupDef();
particleGroupDef.shape = this.particle;
this.particleSystem.CreateParticleGroup(particleGroupDef);
setTimeout(() => { this.cooling = false }, this.cooldown)
}
}
}
let stage = new Stage(document.getElementById('canvas'));
let gravity = new b2Vec2(0, 10);
let world = new b2World(gravity);
let sim = new Sim(world);
// window.addEventListener('resize', e =>
// {
// sim.onResize();
// stage.onResize();
// });
let simOutput: any[] = [];
let runFor:number = 10;
function runSim()
{
for(let i = 0; i < runFor * 60; i++)
{
sim.step();
var particles = sim.getParticles();
let simTick = [];
for (var j = 0; j < particles.length / 2; j++)
{
var x = (sim.width/2) - particles[j * 2] * sim.METER + sim.OFFSET_X;
var y = (sim.height/2) - (sim.height - particles[(j * 2) + 1] * sim.METER + sim.OFFSET_Y);
simTick.push({x: x, y: y});
}
simOutput.push(simTick);
}
}
let init = function()
{
sim.addParticles();
runSim();
let frame = 0;
var particles = simOutput[simOutput.length - 1];
let xMin;
let xMax;
let yMin;
let yMax;
// get bounds
for (var i = 0; i < particles.length; i++)
{
if(!xMin || particles[i].x < xMin) xMin = particles[i].x;
if(!xMax || particles[i].x > xMax) xMax = particles[i].x;
if(!yMin || particles[i].y < yMin) yMin = particles[i].y;
if(!yMax || particles[i].y > yMax) yMax = particles[i].y;
}
let areaWidth = xMax - xMin;
let areaHeight = yMax - yMin;
for (var i = 0; i < particles.length; i++)
{
let x = ((particles[i].x - xMin) / areaWidth) * 100;
let y = ((particles[i].y - yMin) / areaHeight) * 100;
//console.log(((particles[i].x + (sim.width/2)) / sim.width) * 100, Math.floor(particles[i].y))
stage.newParticle(getPixel(imageData, x, y));
}
function playSim()
{
//sim.step();
var particles = simOutput[frame];
for (var i = 0; i < particles.length; i++)
{
let p = !stage.particles[i] ? stage.newParticle(0x666666) : stage.particles[i];
p.position.set(particles[i].x, particles[i].y);
}
frame++;
if(frame < simOutput.length) requestAnimationFrame(playSim);
else requestAnimationFrame(realtimeTick);
}
playSim();
}
function realtimeTick()
{
sim.step();
var particles = sim.getParticles();
for (var i = 0; i < particles.length / 2; i++)
{
let p = !stage.particles[i] ? stage.newParticle() : stage.particles[i];
if(p.position.y > window.innerHeight/2 && !p.removed)
{
stage.remove(p, p.index);
p.removed = true;
}
else
{
var x = (sim.width/2) - particles[i * 2] * sim.METER + sim.OFFSET_X;
var y = (sim.height/2) - (sim.height - particles[(i * 2) + 1] * sim.METER + sim.OFFSET_Y);
p.position.set(x, y);
}
}
requestAnimationFrame(realtimeTick);
}
// requestAnimationFrame(tick);
// }
// window.addEventListener('click', () => { sim.addParticles(); })
// window.addEventListener('touchstart', () => { sim.addParticles(); })
// if(location.pathname.match(/fullcpgrid/i))
// {
// document.getElementById('info').style.visibility = "hidden";
// setInterval(() => {sim.addParticles()}, 500);
// }
// tick();
// var img = new Image();
let imageData;
// img.onload = function()
// {
// imageData = getImageData(img);
// init();
// };
// img.src = ;
const loader = new PIXI.loaders.Loader();
loader.add('hello', 'https://s3-us-west-2.amazonaws.com/s.cdpn.io/557388/HELLO.png')
loader.load((loader, resources) => {
// resources.bunny
// resources.spaceship
console.log(resources.hello);
imageData = getImageData(resources.hello.data);
//console.log(getPixel(imageData, 0, 0));
init();
});
function getImageData( image ) {
var canvas = document.createElement( 'canvas' );
canvas.width = image.width;
canvas.height = image.height;
var context = canvas.getContext( '2d' );
context.drawImage( image, 0, 0 );
return context.getImageData( 0, 0, image.width, image.height );
}
function getPixel(imgData, percentX, percentY)
{
let x = Math.round((percentX / 100) * imageData.width);
let y = Math.round((percentY / 100) * imageData.height);
if(x < 0) x = 0;
if(x > imageData.width) x = imageData.width;
if(y < 0) y = 0;
if(y > imageData.height) y = imageData.height;
//console.log('x', x, 'y', y, 'width', imageData.width, 'height', imageData.height)
var r, g, b, a, offset = x * 4 + y * 4 * imgData.width;
if(offset + 3 > imgData.data.length) offset = imgData.data.length - 4;
//if(percentX > 99) console.log(x)
//if(percentY > 98 && percentX > 98) console.log(x, y)
r = imgData.data[offset];
g = imgData.data[offset + 1];
b = imgData.data[offset + 2];
let str = "0x" + componentToHex(r) + componentToHex(g) + componentToHex(b);
//console.log(str);
return parseInt(str);
}
function componentToHex(c) {
var hex = c.toString(16);
return hex.length == 1 ? "0" + hex : hex;
}
View Compiled
This Pen doesn't use any external CSS resources.