|
const frame = new Frame("fit", 1024, 768, darker, dark); |
|
frame.on("ready", ()=>{ // ES6 Arrow Function - similar to function(){} |
|
zog("ready from ZIM Frame"); // logs in console (F12 - choose console) |
|
|
|
// often need below - so consider it part of the template |
|
let stage = frame.stage; |
|
let stageW = frame.width; |
|
let stageH = frame.height; |
|
|
|
// REFERENCES for ZIM at http://zimjs.com |
|
// see http://zimjs.com/learn.html for video and code tutorials |
|
// see http://zimjs.com/docs.html for documentation |
|
// see https://www.youtube.com/watch?v=pUjHFptXspM for INTRO to ZIM |
|
// see https://www.youtube.com/watch?v=v7OT0YrDWiY for INTRO to CODE |
|
|
|
// CODE HERE |
|
|
|
// This feature uses Box2D for physics |
|
// and the ZIM physics.js helper file |
|
// As of ZIM 10, physics is integrated into ZIM and the docs |
|
// see examples here https://zimjs.com/physics |
|
|
|
// This app is for the CodePen Challenge on Polygons |
|
// There is a Box2D polygon shape |
|
// but this would not let objects inside |
|
// and ZIM only automatically maps Triangle, Rectangle, Circle |
|
// You can custom map the polygon with setMap() if desired |
|
|
|
// SO... the plan is to make a Polygon with a Blob |
|
// setting the controlType to none |
|
// which makes straight lines from point to point. |
|
// Then add Rectangle objects along the lines |
|
// with physics added and join them with a weld joint. |
|
// This means we can put things inside! (or outside) |
|
|
|
|
|
const width = 30; // width of polygon sides |
|
// we will put all the parts in a Container |
|
// so we can easily remove them to change polygons |
|
let holder = new Container(stageW, stageH).addTo(); |
|
// The number of sides can be set from 3-8 with the tab controls |
|
let startNum = 5; |
|
let joints; // for storing joints to remove later |
|
|
|
// Make a physics world |
|
// requires Box2D and ZIM physics.js helper |
|
const physics = new Physics(0); // no gravity |
|
|
|
// create a function to make the polygon |
|
// because we need to change the sides |
|
// with the tab controls later |
|
makePoly(startNum); |
|
function makePoly(points) { |
|
|
|
let poly = new Blob({ |
|
points:points, |
|
borderWidth:width, |
|
borderColor:blue, |
|
controlType:"none", |
|
interactive:false |
|
}).transformPoints("scale", 2).center(holder); |
|
|
|
// find the distance between points |
|
let p0 = poly.pointControls[0]; |
|
let p1 = poly.pointControls[1]; |
|
let length = dist(p0, p1); |
|
// above is ZIM dist() function - or use |
|
// let length = Math.sqrt((p0.x-p1.x)**2 + (p0.y-p1.y)**2); |
|
let angle = 360 / points; // for a regular polygon |
|
|
|
// We will loop through the control points |
|
// but we need to know the last point |
|
// so we can make and position lines as we go |
|
// Controls are inside Blob so get global points |
|
let firstPoint = p0.localToGlobal(0, 0); // where is the 0,0 globally |
|
let lastPoint = firstPoint; |
|
let lastRect = null; |
|
let firstRect = null; |
|
joints = []; |
|
|
|
// need two points each time to make a rectangle between |
|
// so skip the first point... |
|
// then need to do one more after the loop |
|
loop(poly.pointControls, (point, i)=>{ |
|
if (i==0) return; // like a continue in a for loop |
|
let thisPoint = point.localToGlobal(0, 0); |
|
makeRect(lastPoint, thisPoint, i); |
|
lastPoint = point.localToGlobal(0, 0); |
|
}); |
|
makeRect(lastPoint, firstPoint, points); // the one more |
|
|
|
function makeRect(lastPoint, thisPoint, num) { |
|
// find half way between this point and last point |
|
let midPoint = new Point( |
|
thisPoint.x+(lastPoint.x-thisPoint.x)/2, // part way between points |
|
thisPoint.y+(lastPoint.y-thisPoint.y)/2 |
|
); |
|
|
|
// Adjust for Blob start angle |
|
// let rectAngle = angle*(num-3); |
|
// works hard coded for 5 sides |
|
// but to make it work for any points use this - yum! |
|
// this will be 2,2,3,3,4,4 for num points from 3-8 |
|
// and then Blob always start with point0 at top |
|
// and we must subtract half the angle on even numbers - sigh. |
|
let rectAngle = angle*(num-Math.ceil(points/2))-(points%2==0?angle/2:0); |
|
|
|
let rect = new Rectangle(length, width, faint) // set to color to see |
|
.centerReg(holder) |
|
.loc(midPoint) // passing in an object with an x and y works for loc |
|
.rot(rectAngle) |
|
.addPhysics(); |
|
if (!lastRect) { |
|
firstRect = rect; |
|
} else { |
|
joints.push(physics.join(rect, lastRect, thisPoint)); |
|
} |
|
lastRect = rect; |
|
} |
|
joints.push(physics.join(firstRect, lastRect, firstPoint)); |
|
|
|
// need to make poly follow welded rectangles |
|
// easiest way is to weld something at registration of poly |
|
// we don't want the circles inside to interact with this |
|
// so set the maskBits to another bit setting (2,4,8,16,etc.) |
|
// default is 1 for all physics shapes - but can set categoryBits to adjust |
|
let marker = new Circle(1, clear).loc(poly, null, holder).addPhysics({maskBits:2}); |
|
joints.push(physics.join(firstRect, marker, firstPoint)); |
|
|
|
// now make poly follow and rotate based on our marker |
|
physics.Ticker.add(()=>{ |
|
// poly.loc(marker); works until we added controls to remake poly |
|
// then introduced a bug where when we remove poly, |
|
// this ticker adds it again to the stage! |
|
// so make sure the loc does not add polly with the add:false |
|
poly.loc({x:marker.x, y:marker.y, add:false}).rot(marker.rotation); |
|
}); |
|
|
|
// Add a bunch of circles inside - or whatever... |
|
let colors = series(pink,green,red,orange,brown,yellow); |
|
interval(70, obj=>{ |
|
new Circle({min:20, max:30}, colors) |
|
.center(holder) |
|
.addPhysics() |
|
.impulse( // push them in different directions |
|
rand(3,5,null,true), // negative too |
|
rand(3,5,null,true) |
|
); |
|
// normally, the end count == total |
|
// but when you start right away, the count starts at 0 |
|
// so the end count == total-1 |
|
if (obj.count == obj.total-1) { |
|
physics.drag(); |
|
holder.cur(); |
|
} |
|
}, 12, true); // run 12 times and start right away |
|
|
|
} // end make physics |
|
|
|
const controls = new Tabs({ |
|
tabs:[3,4,5,6,7,8], |
|
width:350, |
|
selectedBackgroundColor:green, |
|
selectedColor:darker |
|
}) |
|
.centerReg() |
|
.pos(null,30,null,true) |
|
// make poly hit interface! false is not dynamic (static) |
|
.addPhysics(false) |
|
.change(()=>{ |
|
// stop the drag while we add circles |
|
physics.noDrag(); |
|
holder.cur("default"); |
|
// remove old joints and physics mappings |
|
loop(joints, joint=>{ |
|
physics.break(joint); |
|
}) |
|
loop(holder, child=>{ |
|
if (child.physics) { // actual Blob does not get physics |
|
child.removePhysics(); |
|
} |
|
}); |
|
holder.removeAllChildren(); |
|
makePoly(Number(controls.text)); |
|
}); |
|
controls.selectedIndex = startNum-3; // starting tabs at 3 poly lines |
|
|
|
new Label({text:"ZIM - Physics Polygon with Drag", color:white}).alp(.7).pos(30,30).bot(); |
|
|
|
|
|
// DOCS FOR ITEMS USED |
|
// https://zimjs.com/docs.html?item=Frame |
|
// https://zimjs.com/docs.html?item=Physics |
|
// https://zimjs.com/docs.html?item=addPhysics |
|
// https://zimjs.com/docs.html?item=Container |
|
// https://zimjs.com/docs.html?item=Circle |
|
// https://zimjs.com/docs.html?item=Rectangle |
|
// https://zimjs.com/docs.html?item=Blob |
|
// https://zimjs.com/docs.html?item=Label |
|
// https://zimjs.com/docs.html?item=Tabs |
|
// https://zimjs.com/docs.html?item=change |
|
// https://zimjs.com/docs.html?item=drag |
|
// https://zimjs.com/docs.html?item=noDrag |
|
// https://zimjs.com/docs.html?item=loop |
|
// https://zimjs.com/docs.html?item=cur |
|
// https://zimjs.com/docs.html?item=pos |
|
// https://zimjs.com/docs.html?item=bot |
|
// https://zimjs.com/docs.html?item=alp |
|
// https://zimjs.com/docs.html?item=rot |
|
// https://zimjs.com/docs.html?item=addTo |
|
// https://zimjs.com/docs.html?item=centerReg |
|
// https://zimjs.com/docs.html?item=center |
|
// https://zimjs.com/docs.html?item=rand |
|
// https://zimjs.com/docs.html?item=loop |
|
// https://zimjs.com/docs.html?item=interval |
|
// https://zimjs.com/docs.html?item=dist |
|
// https://zimjs.com/docs.html?item=Point |
|
// https://zimjs.com/docs.html?item=series |
|
// https://zimjs.com/docs.html?item=zog |
|
// https://zimjs.com/docs.html?item=Ticker |
|
|
|
// FOOTER |
|
// call remote script to make ZIM Foundation for Creative Coding icon |
|
createIcon(frame); |
|
|
|
}); // end of ready |