ZIM BITS TUTORIAL
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<title>ZIM BITS - Side Scroller Backing Animation Loop</title>
<!-- Welcome to ZIM at https://zimjs.com - Code Creativity! -->
<!-- ZIM runs on the HTML Canvas powered by JavaScript and CreateJS https://createjs.com -->
<!-- Founded by Inventor Dan Zen - http://danzen.com - Canadian New Media Award Winner -->
<!-- ZIM is free to use. You can donate to help improve ZIM at http://zimjs.com/donate -->
<script src="https://zimjs.org/cdn/1.3.4/createjs.js"></script>
<script src="https://zimjs.org/cdn/01/zim_min.js"></script>
<!-- use zimjs.com/distill for minified individual functions! -->
<script src="https://zimjs.com/bits/footer10.js"></script><!-- you will not need this -->
<script>
// SCALING OPTIONS
// scaling can have values as follows with full being the default
// FIT sets canvas and stage to dimensions and scales to fit inside window size
// FILL sets canvas and stage to dimensions and scales to fit outside window size
// FULL sets stage to window size with no scaling
// "tagID" add canvas to HTML tag of ID - set to dimensions if provided - no scaling
const scaling = FIT; // this will resize to fit inside the screen dimensions
const width = 1000;
const height = 800;
const color = darker;
const outerColor = dark;
// 1. prepare a list of assets and a path
const assets = [
"sceneForeground.png",
"sceneRoad.png",
"sceneBacking.png",
"car.png"
];
const path = "assets/";
// 2. create a Waiter for the the asset loading
const waiter = new Waiter();
new Frame(scaling, width, height, color, outerColor, ready, assets, path, waiter);
function ready() {
// given F (Frame), S (Stage), W (width), H (height)
// ZIM BITS - Side Scroller Backing Animation Loop (2016 - updated 2022)
// sidescrollers are fun! Flinstones @Hanna-Barbera in this case, I am sure!
// Scroller is a background animator for horizontal or vertical scrolling
// you can dynamically set the speed and direction but
// the background is a long display object often a Bitmap
// it needs to be seamless at the ends so wrapping is not noticed
// the background gets automatically cloned and placed for looping
// and needs to be longer than the direction you are going
// STEPS
// 1. prepare a list of assets and a path
// 2. create a Waiter for the the asset loading
// 3. optionally we can set up a shape for a mask of the Scroller
// 4. create a container for all the objects being scrolled (optional)
// 5. add the background pic to the stage and position or scale
// 6. create a Scroller and set the background pic as the background
// 7. optionally, make more than one scroller for a parallax effect
// 8. make an object that is "moving" in the scene
// 9. we are going to make a CheckBox to handle masking or not
// 10. we are going to make a slider to controll the speed of the Scrollers
// 11. add sliders to Accelerator to control all at once with slider
// 3. optionally we can set up a shape for a mask of the Scroller
const rect = new Rectangle(500, 350, null, null, null, 50);
// 4. create a container for all the objects being scrolled (optional)
const animation = new Container(W, H).addTo()
// 5. add the background pic to the stage and position or scale
const backgroundPic = new Pic("sceneBacking.png")
.sca(.5)
.loc(0, 200, animation);
// 6. create a Scroller and set the background pic as the background
// gapFix just joins the seam together a little more when dynamically changing speed
const background = new Scroller({backing:backgroundPic, speed:1, gapFix:1});
// 7. optionally, make more than one scroller for a parallax effect
const roadPic = new Pic("sceneRoad.png")
.sca(.5)
.loc(0, 200, animation);
const road = new Scroller({backing:roadPic, speed:3.8, gapFix:1});
// 8. make an object that is "moving" in the scene
const car = new Pic("car.png")
.sca(.5)
.reg(100, 320)
.center(animation)
.mov(-80)
.animate({props:{y:"2"}, time:.2, rewind:true, loop:true}) // note, relative y animation with quotes
.tap(function() {
car.animate({obj:{rotation:-30}, time:.4, rewind:true, rewindWait:.3, override: false});
});
const foregroundPic = new Pic("sceneForeground.png");
foregroundPic // restart chain because need height of foregroundPic
.sca(.5)
.loc(0, roadPic.y + (roadPic.height-foregroundPic.height)+1, animation); // note heights now include scale
const foreground = new Scroller({backing:foregroundPic, speed:4.3, gapFix:1});
// 9. we are going to make a CheckBox to handle masking or not
const checkBox = new CheckBox({
size:26,
label:new Label("MASK", 24, null, "#999")
})
.center()
.mov(-120, 200);
let mask;
checkBox.on("change", function() {
if (checkBox.checked) {
rect
.center(S, 0)
.mov(0, -20);
const m = animation.setMask(rect);
} else {
animation.setMask(null);
S.removeChild(rect);
}
});
// 10. we are going to make a slider to controll the speed of the Scrollers
const slider = new Slider({
min:-20,
max:300,
barLength:200,
button:new Button({
width:25,
height:25,
backing:new Circle(13, green),
rollBacking:new Circle(13, blue),
label:""
})
});
slider // restart chain because need the slider height
.loc(checkBox.x + 170, checkBox.y + slider.height/2);
slider.currentValue = slider.max / 3;
// 11. add sliders to Accelerator to control all at once with slider
// the old way is down below, before there was an Accelerator
const accelerator = new Accelerator([background, road, foreground]);
slider.change(function () {
accelerator.percentSpeed = slider.currentValue
})
// // 11. set ProportionDamp objects to convert the slider to the desired speed
// // each Scroller is going at a different speed
// // this is a pretty easy calculation but ProportionDamp removes the thinking ;-)
//
// // baseMin, baseMax, targetMin, targetMax, damp, factor, targetRound
// // could have set to 0 or small positive amount but thought it might be fun to reverse
// const backgroundPD = new ProportionDamp(slider.min, slider.max, -background.speed*.2, background.speed*3, .05);
// const roadPD = new ProportionDamp(slider.min, slider.max, -road.speed*.2, road.speed*3, .05);
// const foregroundPD = new ProportionDamp(slider.min, slider.max, -foreground.speed*.2, foreground.speed*3, .05);
//
// Ticker.add(function(){
// background.speed = backgroundPD.convert(slider.currentValue);
// road.speed = roadPD.convert(slider.currentValue);
// foreground.speed = foregroundPD.convert(slider.currentValue);
// });
const title = "Scroller";
new Label(title, 30, null, "#666")
.pos(40, 40);
const docItems = "Frame,Container,Circle,Rectangle,Label,Button,CheckBox,Waiter,Slider,tap,change,animate,cur,pos,mov,reg,sca,addTo,center,setMask,Scroller,Accelerator,ProportionDamp,zog,Ticker";
makeFooter(S, W, H, null, docItems); // ZIM BITS footer - you will not need this
} // end of ready
</script>
<meta name="viewport" content="width=device-width, user-scalable=no" />
</head>
<body>
<!-- canvas with id="myCanvas" is made by zim Frame -->
</body>
</html>