ZIM BITS TUTORIAL

<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<title>ZIM BITS - Falling, Dodging and Catching Game</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 = dark; // or any HTML color such as "violet" or "#333333"
const outerColor = light;
const assets = ["bomb.png", "coin.png", "bang.png", "wow.png", "robber.png"];
const path = "assets/";


new Frame(scaling, width, height, color, outerColor, ready, assets, path);
function ready() {
	
	// given F (Frame), S (Stage), W (width), H (height)
	
	// ZIM BITS - Falling, Dodging and Catching Game  (2020)

	// To make things fall we can animate objects from the top to the bottom
	// This can be done with code in a Ticker or just using ZIM animate()

	// often we want to make multiple copies fall
	// we use ZIM interval with a random range input to make falling random

	// to animate multiple objects it is best to add the objects to a Container
	// then we can loop through the objects in the container and move each one

	// we often have something that is catching or avoiding the falling objects
	// for instance, a person - then we might want the person to follow the mouse
	// or perhaps keyboard or drag in some cases
	// we can do this manually or use a ZIM MotionController

	// we will probably want to check if the person catches or hits the objects
	// in a Ticker we do a hitTest to see if the object has hit the person
	// depending on how many objects and their shapes
	// we choose from the variety of zim hitTests
	// the fastest hitTest is hitTestBounds as it calculates rectangle intersection
	// others may bog if there are too many as they use graphical hitTests

	// EXTRA
	// we might want to keep score if we are collecting things
	// and perhaps make the person lose points or die if they get hit
	// we may want to have multiple types of things falling worth different points
	// in that case, as we make the object we assign the points as a property of the object
	// and then when we check the hit test, we can access the points
	// we would want to add sounds, perhaps levels with different speeds, etc.

	// STEPS
	// 1. create a backing that can be used as a mask (or just go full screen)
	// 2. create a container for the game (or just use the stage)
	// 3. create a person to dodge and catch items and position at the bottom
	// 4. move the player with a MotionController
	// 5. optionally start the game when the user moves their mouse or swipes
	// 6. add an interval to create and animate objects to drop
	// 7. add a Ticker to test for hits
	// 8. we can make little animations, etc. when things are hit


	// STEPS
	// 1. create a backing that can be used as a mask (or just go full screen)
	const backing = new Rectangle(W-80, H-250, grey)
		.center()
		.mov(0,-20);

	// 2. create a container for the game (or just use the stage)
	const game = new Container(backing.width, backing.height)
		.loc(backing)
		.setMask(backing);

	// 3. create a person to dodge and catch items and position at the bottom
	const robber = new Pic("robber.png")
		.centerReg()
		.pos(0,0,CENTER,BOTTOM,game);

	// 4. move the player with a MotionController
	new MotionController({
		target:robber,
		type:"mousemove", // default
		speed:20, // default
		damp:.1, // default
		axis:"horizontal",
		boundary:new Boundary(robber.width/2,backing.y + backing.height, backing.width-robber.width, 0),
		container:game
	});

	// 5. optionally start the game when the user moves their mouse or swipes
	S.on("stagemousemove", startGame, null, true); // only once
	function startGame() {

		// 6. create and animate objects to drop
		dropBombs();
		dropCoins();

		// 7. add a Ticker to run an animation function
		Ticker.add(test);
	}

	// 6. create and animate objects to drop
	// BOMBS
	const bombs = new Container().addTo(game);
	function dropBombs() {
		interval([.2, 1.2], function() {
			const bomb = new Pic("bomb.png")
				.centerReg()
				.loc(rand(0, game.width), 50, bombs)
				.animate({
					props:{y:backing.height-20},
					time:2,
					ease:"linear",
					call:function (target) {
						explode(target);
						remove(target);
					}
				});
			const explosion = new Pic("bang.png").centerReg({add:false}); // do not add
			bomb.explosion = explosion;
		});
	}

	// 6. create and animate objects to drop
	// COINS
	const coins = new Container().addTo(game);
	function dropCoins() {
		interval([.5, 1.5], function() {
			const coin = new Pic("coin.png")
				.centerReg()
				.loc(rand(0, game.width), -30, coins)
				.animate({
					props:{y:H},
					time:3,
					ease:"linear",
					call:remove
				});
			const wow = asset("wow.png").clone().centerReg({add:false}); // do not add
			coin.wow = wow;
		});
	}


	// 7. add a Ticker to run an animation function
	function test() {
		bombs.loop(function(bomb) {
			if (robber.hitTestBounds(bomb)) {
				explode(bomb);
			}
		}, true); // true loops backwards as we are removing children
		coins.loop(function(coin) {
			if (robber.hitTestBounds(coin)) {
				grab(coin);
				// get points etc.
			}
		}, true); // true loops backwards as we are removing children
	}

	// 8. we can make little animations, etc. when things are hit
	function explode(bomb) {
		const explosion = bomb.explosion;
		if (explosion) {
			explosion
				.loc(bomb)
				.animate({alpha:0}, .1, null, remove, null, .1); // last param is wait
		}
		remove(bomb);
	}

	// 8. we can make little animations, etc. when things are hit
	function grab(coin) {
		coin.wow
			.addTo(game)
			.loc(robber)
			.mov(0,-130)
			.animate({alpha:0}, .1, null, remove, null, .1); // last param is wait;
		remove(coin);
	}

	function remove(obj) {
		obj.removeFrom();
		obj = null;
	}


	const title = "Falling Items to Catch or Avoid";
	new Label(title, 30, null, "#666")
		.pos(40, 40);

	const docItems = "Frame,Container,Rectangle,Label,hitTestBounds,move,MotionController,animate,loop,pos,mov,reg,addTo,removeFrom,center,setMask,loop,interval,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>