Dark Papers
ORGANIZATION
// ZIM is organized in sections: // FRAME, DISPLAY, METHODS, CONTROLS, CODE, WRAP, META // Let's have a brief look at each... // see https://zimjs.com/docs.html all the details! // NOTE: ZIM works fine with ES6 - these examples are in ES5 // All CodePen examples at https://codepen.io/topic/zim for instance are ES6 // --------------------------------- // FRAME - the framework class that makes and scales the canvas and stage // scaling, width, height, color, outerColor, ready, assets, path, etc. new Frame(FIT, 1024, 768, light, dark, ready, ["pic.png", "sound.mp3"], "assets/"); function ready() { // given F (frame), S (stage), W (stageW), H (stageH) const sound = new Aud("sound.mp3"); new Pic("pic.png").center().tap(()=>{ sound.play(); }); } // end ready // --------------------------------- // DISPLAY - classes for objects viewed on the stage like shapes and components const circle = new Circle(100, red); // also Rectangle, Triangle and Blob const button = new Button(200, 100, "GO!"); // etc. and dozens more like Label, Slider, Dial, Tabs, ColorPicker... // --------------------------------- // METHODS - methods for the display objects above circle.center(); // adds to and centers button on stage circle.drag(); // allows the circle to be dragged and dropped circle.animate(obj:{alpha:0}, 5); // fades out circle over 5 seconds // etc. and dozens more - also see PRINCIPLES sections below... // --------------------------------- // CONTROLS - classes that affect Display objects new MotionController(circle); // circle moves to mouse press new Pages(S, {page:home}, {page:help}); // handle pages and swiping new Layout(S, [{object:header},{object:content},{object:footer}]); // responsive design with many more options (like css flex table) // etc. including Parallax, Scroller, Pen, Guide, Grid, Emitter, SoundWave... // --------------------------------- // CODE - non-Canvas code convienence functions const array = [red, yellow, green, blue]; let color = pluck(array); // let color = shuffle(array)[0]; // shuffles array and picks first color // let color = array[rand(array.length-1)]; // gets random element // etc. many more including browser functions and asynchronous calls // --------------------------------- // WRAP - a dozen three-letter global functions starting with z zog("hello world"); // short for console.log(); zid("tagID"); // short for document.getElementById(); // etc. including selectors similar to $() in jQuery // --------------------------------- // META - a few classes and functions operating on zim DISTILL = true; distill(); // writes to console all the commands used to reduce code zimify(createjsObj); // adds zim Methods to native createjs display objects wonder.count("wow"); // once set up records different types of stats // --------------------------------- The docs have all the details and changes are found at https://zimjs.com/updates.html Please also see the TRICKS section below!
TREATS
// Here are some handy things that ZIM provides to make coding easier // In the later examples, we list a few handy things CreateJS and JavaScript provide // --------------------------------- // CONFIGURATION OBJECTS // Introduced in ZIM DUO so referred to as the ZIM DUO technique // Classes, methods and functions accept parameters (often dozens) // These are values only and the order matches an expected order as defined in the docs // Many parameters have default values but order must be kept // So if you want to only set the seventh parameter to false then you need six placeholder null values circle.drag(null, null, null, null, null, null, false); // This is really unmanageable at times so ZIM also accepts a configuration object as a single parameter // The configuration object has properties that match the parameter names as set out in the docs // The order in which we provide the properties does not matter: circle.drag({onTop:false}); circle.drag({onTop:false, slide:true}); // Note: when there are only a few parameters, the ZIM DUO technique might not be available (see docs) // Note: this is an alternative to having a short list of parameters and then setting properties after // Advanced note: this technique is accomplished with zob() and you can use it in your own code // --------------------------------- // CHAINING // Chainable methods let you place one method after the other in the same statement // It is a technique to avoid repeating the object // Traditionally we would have multiple statements - and these still work: const circle = new Circle(); circle.center(); circle.x -= 100; // move it to the left circle.drag(); // Chainable methods return the object they are placed on // Below, the Circle object is created and then centered // the center() method returns the Circle object which then has its drag() set // the drag() method returns the Circle object which is then assigned to the const circle const circle = new Circle().center().mov(-100).drag(); // Often we stack the methods (this allows us to comment out parts too) // Note: watch you only put the semi-colon on your last line const circle = new Circle() .center() .mov(-100) .drag(); // You cannot assign an object to a variable if you chain a property on the end: const circle = new Circle().center().alpha = .5; // would put .5 into const circle // So ZIM provides a set of short chainable methods (like mov() in the example above): loc(x, y, container) pos(x, y, right, bottom, container) mov(relativeX, relativeY) alp(alpha) rot(rotation) siz(width, height, only) ske(skewX, skewY) reg(regX, regY) sca(scale, scaleY) // --------------------------------- // STYLE // STYLE can be used to set any parameter on a DisplayObject. // For instance: Circle, Blob, Button, Pane, Bitmap, Sprite, etc. // These are applied at the time the objects are made. // They are cascading with each level overriding the previous level: // // 1. GENERAL: any style can be specified in general // corner:30 will make all corners default to 30 // 2. TYPE: styles for object type can be set to override the general styles // Button:{corner:0} will make all button corners default to 0 // 3. GROUP: styles for a group can be set to override the type styles // homePage:{corner:20} will make all objects of that group default to 20 // 4. OBJECT: styles applied as parameters to the object override all other styles // new Button({corner:40}) will make this button have a corner of 40 STYLE = { corner:20, backgroundColor:pink, type:{ Button:{width:{min:100, max:500}, corner:0, centerReg:true, move:{y:series([-150, -50, 50, 150])}}, Dial:{add:true, x:800, y:600, backgroundColor:red, scale:2, outline:true}, Pane:{corner:ignore, color:white, draggable:true, width:300, label:"HI!"}, ProgressBar:{add:true, x:200, y:600, barType:"rectangle", transform:true}, Tabs:{add:true, x:100, y:100} }, group:{ homePage:{corner:30} } } new Button(); // will have a corner of 0 and be pink new Button({group:"homePage"}); // will have a corner of 30 and be pink new Button({corner:10, group:"homePage"}); // will have a corner of 10 and be pink new Button({corner:"ignore"}) // will have a corner of its default 20 and be pink new Button({style:false}).pos(700,100); // will have original default styles new Dial(); // will be red and scaled twice as big and have an outline new Tabs(); // will have a corner of 20 and selection will be pink var p = new ProgressBar({corner:15}); // will be a bar with transform tools, corner 15 p.percent = 25; new Pane().show(); // will ignore corner 30 and use its original 20 - it will say HI! in white and be draggable STYLE can now accept the DisplayObject class names directly: STYLE = {Button:{backgroundColor:red}}; // no need for type:{Button:{etc.}} // --------------------------------- // LOOPS // A traditional for loop in JavaScript looks like this: for (let i=0; i<10, i++) { zog(i); } // ZIM provides a simpler and more feature rich loop: loop(10, i => { zog(i); }); // often we loop through an array, an object or a zim Container // ZIM loop provides an additional context sensitive first parameter: const array = [red, green, yellow, blue]; loop(array, color => { // the index number is now the second parameter zog(color); }); // Note: to continue in a loop use return - to exit the loop return a value // See the docs for more features and examples (note, there are TWO listings for ZIM loop) // --------------------------------- // TIMEOUT AND INTERVAL // As of ZIM Cat, time is in seconds rather than milliseconds (see TIME constant to adjust) // A traditional time out and interval in JavaScript looks like this: setTimeout(()=>{zog("once after a second");}, 1000); setInterval(()=>{zog("repeat after a second");}, 1000); // These do not use a requestAnimationFrame so they can take resources when app is minimized // and contrary to event listener format, the function comes first which obscures the time // ZIM provides a timeout and interval to adjust these and adds more features // such as a total number for the interval, run immediately, pause(), time, count, etc. see docs timeout(1, ()=>{zog("once after a second");}); interval(1, ()=>{zog("repeat after a second");}); // --------------------------------- // ZIM VEE VALUE // Introduced in ZIM VEE (5) as a way to pass in dynamic parameters // For instance, ZIM Emitter emits particles and we may want to emit a variety of particles // We might want to pass in a range of decay times, etc. // We could pass in a random number for the decay time but then it would always use that decay time // So, a global function called zik() was created to PICK from a ZIM VEE value // The ZIM VEE value can be the following: // 1. an Array of values to pick from - eg. [red, green, blue] // 2. a series - eg. series(red, green, blue) to run in order // 3. a Function that returns a value - eg. function(){return Date.now();} // 4. a ZIM RAND object literal - eg. {min:10, max:20, integer:true, negative:true} max is required // 5. any combination of the above - eg. [red, function(){x>100?[green, blue]:yellow}] zik is recursive // 6. a single value such as a Number, String, Rectangle(), etc. this just passes through unchanged // The docs will indicate when a ZIM VEE value can be used as a parameter // For instance, here is a ZIM interval that changes the interval time as it runs: interval({min:.2, max:.8}, dropBombs); // bombs will fall at different rates between .2s and .8s interval([1, 2], dropBombs); // bombs will fall at either 1 or 2 s // --------------------------------- // EXTENDING ZIM // The DISPLAY classes extend CreateJS classes (see the CreateJS panel below) // And you can extend ZIM with ES6 using extends, super, etc. just like you would any class. class Drunk extends Rectangle { // ES6 Class and extends constructor(w=10, h=10) { // ES6 default parameters super(w, h, pink); // ES6 calling super constructor (a must) this.reg(w/2, h); } // ES6 Getter Setter methods set tipsy(angle){this._angle = this.rotation = angle;} get tipsy(){return this._angle;} } // In ES5 // you can extend the ZIM classes in a similar way with extend() // This is a helper method that wraps up the tricky JavaScript 5 process of extending classes // extend() is based on the CreateJS extend() method with a few changes: var Collection = function() { // the super constructor must be run this.super_constructor(); // custom properties and methods, etc. } extend(Collection, Container); // Collection will be a Container // see the docs for more options // In ES6 this is: class Collection extends Container { constructor() { super(); // etc. } } // --------------------------------- // JAVASCRIPT FUNCTIONS // In JavaScript we can define (declare) and call (run) a function like so: function greet() {zog("hello");} greet(); // In JavaScript, a function is also first-class object // So we can store a function object in a variable (just like storing a Number object in a variable): const greet = function(){zog("hello");}; // a function literal or an anonymous function assigned to a const greet(); // run the function - will log "hello" in the console // We also have a new Arrow function in ES6 button.on("click", ()=>{}); // same as anonymous button.on("click", function(){}); // in ES5 // or a named function button.on("click", go); function go() {} There are some tricks available for the Arrow function (look it up online) but a common one is we do not need brackets if we collect a single parameter: button.on("click", e=>{}); // We can also pass a function object as a parameter to be run later timeout(1, ()=>{circle.removeFrom(); stage.update();}); // We have passed the function object as the second parameter to the timeout() method // Alternatively, we could declare a function and pass that in as a parameter: function remove() { circle.removeFrom(); stage.update(); } timeout(1, remove); // Note: that we do not call the remove function in the timeout() but rather refer to it // This second way is longer so we often use the first way with the anonymous function // We can also store a function as a property of an object // All the ZIM functions (aside from the global short functions) are stored in an object called zim // As such, we call this zim object the zim "namespace" rand(10,20); // returns a random integer between and including 10 and 20 (more options available) mobile(); // returns if the app is mobile and if so which type Circle(); // is the Circle class (in JavaScript, a class is a function) // --------------------------------- // EVENTS // CreateJS provides an on() method to add events and an off() method to remove events // These replace the traditional addEventListener() and removeEventListener() methods in JavaScript // The immediate benefit is that they are shorter! // They work the same way but have a few conveniences: const circle = new Circle().center(); let score = 0; circle.on("click", () => { score++; }); // We can automatically remove the event once it runs once: circle.on("click", () => { score++; }, null, true); // the fourth parameter set to true makes the event run once // Note: above we use the anonymous function as the second parameter // We could declare the function and use the function reference instead: function addScore() { score++; } circle.on("click", addScore); // As mentioned, this is longer so we tend to use the arrow or anonymous function // --------------------------------- // EVENT OBJECT // The event functions receive an event object with extra information // Imagine that we have a zim Container called monsters with 100 monster objects inside monsters.on("click", e => { // e is the event object e.target.removeFrom(); // e.target is whatever monster caused the event so one monster will be removed // e.currentTarget is a reference to the object the event was put on - so in this case, monsters stage.update(); }); // Note: ZIM drag() uses the event object to drag an object in a container: monsters.drag(); // would drag which ever monster inside monsters is pressed monsters.drag({all:true}); // would drag all the monsters // Here we use the event object to find out which key is pressed: frame.on("keydown", e => { zog(e.keyCode); // will tell you the code of the key if (e.keyCode == 32) {zog("spacebar");} }); // --------------------------------- // MODULES // ZIM and CreateJS use the module pattern to give a "namespace" object // The module pattern allows you to use the same namespace across scripts // This allows you to use only the modules you need and combine these in any order // ZIM was initially provided as modules (code, display, methods, controls, frame, etc.) // but this was discontinued in favor of ZIM DISTILL (see below) // You can use the module pattern in your code // Perhaps you want to store code for each page of your app in separate files // you would then import each page at the top of your main HTML page: <script src="page1.js"></script> <script src="page2.js"></script> // Here is what the module pattern would look like: // this is inside page1.js: var app = function(app) { app.makePage1 = function() { zog("page1"); }; // etc. return app; // return the object with its properties to the outside } (app || {}); // the app namespace object if it exists OR an object literal if it does not // this is inside page2.js: var app = function(app) { app.makePage2 = function() { zog("page2"); }; // etc. return app; // return the object with its properties to the outside } (app || {}); // the app namespace object if it exists OR an object literal if it does not // then in your main HTML page you can call the remote functions: app.makePage1(); app.makePage2();
CREATEJS
// CreateJS is an open source library of JavaScript modules for the HTML Canvas // https://createjs.com // CreateJS (specifically EaselJS) gives us the stage, basic display classes and events // These generally follow the structure and names found in Adobe Flash // The Display classes are Bitmap, Shape, Container, Text, Sprite and MovieClip // CreateJS also has SoundJS, PreloadJS and TweenJS modules // that are used by ZIM Frame loadAssets() and the move() and animate() methods // EXAMPLES // To use CreateJS classes, use the createjs namespace: const container = new createjs.Container(); stage.addChild(container); // you cannot use any of the dozens of ZIM METHODS // for instance, you cannot use container.center(); // nor can you use container.drag(); etc. because these are ZIM // you can use a ZIM METHOD as a zim function: zim.center(container, stage); zim.drag(container); // or you can zimify a CreateJS object: zimify(container); // then you can use ZIM METHODS // BETTER SOLUTION // The above is annoying so in ZIM 4TH, we made a major change: // ZIM extends all the basic CreateJS display classes // The ZIM classes are pretty well the same as the CreateJS classes // except they have all the ZIM METHODS // and they have width and height parameters and properties // The Sprite class in ZIM is also modified to match ZIM animations const container = new Container().center().drag(); // DON'T FORGET // because ZIM classes extend CreateJS classes // they also have all of the original CreateJS methods and properties // the ZIM docs mention these but you will need to go to CreateJS // to read about their details https://www.createjs.com/docs/easeljs/ // CreateJS METHODS: on(), off(), getBounds(), setBounds(), cache(), uncache(), updateCache(), dispatchEvent(), addChild(), removeChild(), addChildAt(), getChildAt(), contains(), removeAllChildren(), etc. // CreateJS PROPERTIES: x, y, rotation, scaleX, scaleY, regX, regY, skewX, skewY, alpha, cursor, shadow, mouseChildren, mouseEnabled, parent, numChildren, compositeOperation, etc. // CreateJS EVENTS: added, click, dblclick, mousedown, mouseout, mouseover, pressmove, pressup, removed, rollout, rollover
PRINCIPLES
// ZIM is Object Oriented - see the ZIM Learn Tutorials for full definition videos // CLASS and OBJECT // A class is a template from which an object is made using the new keyword const rect = new Rectangle(); // Rectangle is the class, rect holds the object // METHODS // A method does something to an object or lets the object do something (verb) // We use the dot syntax . to say that a method belongs to an object rect.addTo(); // adds the rect to the stage rect.drag(); // lets the rect be dragged // (a method is a function that belongs to an object) // PROPERTIES // A property describes the object or is something the object has (adjective) // We use the dot syntax . to say that a property belongs to an object rect.color = red; // sets the color of the rect to red zog(rect.alpha); // gets the transparency of the rect rect.x = 20; // positions the rect to 20 pixels // (a property is a variable that belongs to an object) // EVENTS // An event is when something happens like a click, a load, a resize, etc. // We use the on() method to capture these and run a function rect.on("mousedown", e => { // using a function literal as second parameter rect.rotation += 90; // add 90 degrees to the rect rotation // e is an optional event parameter that collects extra information // such as e.target which gives what caused the event // this is useful for events on containers of multiple objects }); // ZIM is filled with Classes, Objects, Methods, Properties and Events // The documentation has a section detailing each of these // You can make your own as well - see the ZIM Learn Tutorials about this
PROGRAMMING
// ZIM and CreateJS are programmed in JavaScript // So you are programming in JavaScript when you code in ZIM // JavaScript has all the traditional programming basics // See the ZIM Learn Tutorials What IZ section for detailed videos // Here are some very quick definitions: // SYNTAX // When coding you have to use certain characters in certain places // If you get this wrong, there is often an error shown in the console (F12) // You can only use words that are language keywords or that have been defined correctly // OPERATORS // operators (often one character) are part of the coding languages // arithmatic: + - * / % // assignment: = // comparison: == < > <= >= ! // ; ends a statement, etc. // PRIMATIVES "string"; // a String is a collection of letters, like a word or words 7; // a Number needs no quotes and is... a number true; // a Boolean true or false // these are also wrapped in JavaScript objects but don't worry about that // EXPRESSIONS // An expression is anything that evaluates to an object // 10 + 10 // "hello " + name // + is concatenation here (append) // STATEMENTS // A statement ends in a semi-colon; // It is a combination of operators and expressions let x = speed + 10; // These are usually on one line each but they do not have to be let y = 20; let z = "30"; // two statements on the same line // Sometimes we leave off the ; which still works if the statement is on its own line // and if JavaScript is in a non-strict mode (default) // BRACKETS // Brackets always have matching pairs // {} are used to hold a block of code that will be usually be done in order (or an object literal) // [] are an Array literal // () are used for order of operation and for parameters // When we nest brackets often we indent to help us keep track // VARIABLES // A variable is used to hold or refer to an object (the object can change) // It is like a container with a label (name or identifier) // Here we use the keyword var to declare a variable with an identifier x // We then assign the variable x the number 7 using the assignment operator: var x; x = 7; var y = 9; // or we usually declare and assign in one statement // In ES6 we were given two more keywords for declaring variables - const and let. // const is for when we will always keep the same object in the variable. // let is for when we may change which object is stored. // We use const and let now more than var as they more specifically show what we intend // this can help us debug as code gets more complex. const a = 10; a = 15; // would give an error because we cannot change the 10 object to the 15 object. let b = 5; b = 20; // would be fine. // we can mutate the object - as in, change its properties const circle = new Circle(); circle.color = red; // fine as we do not change the object stored. // let is also scoped to any brackets {} it is declared in - eg. function, for, or if blocks. // the ES5 var is scoped to any function brackets {} it is declared in. // CONDITIONALS // A conditional tests to compare the value of an expression // Here we use the if else keywords round brackets and curly brackets // to make a conditional expression // We use the comparison operator == to test if x is equal to 7 // We run the first block of code if the x == 7 Boolean expression is true // We run the second block of code if the x == 7 Boolean expression is false // These blocks of code could have many statements: if (x == 7) { //do this; } else { //do this; } // FUNCTIONS // A function declares a block of code to be run any time the function is called // Here we declare a function with an identifier of test // We collect a parameter (like a variable) called n // and we define a block of code that does a conditional test on n // If the test is true we return true and otherwise we return false // return is a keyword that makes the function end and send back a value // We can make functions without parameters // We can make functions that do not return a value // It depends on what we want the function to do // Finally, we execute or run the function by using the identifier and () // Note, here we are passing the value of x into the function // This means that we will be testing whatever x is // x happens to be 7 from above so we have 7 * 5 = 35 which is less than 50 // So test(x) would have a value of Boolean false function test(n) { // we indent the block of code to make it easier to read // as we start nesting code, indenting is very important if (n * 5 > 50) {return true;} return false; } test(x); // We can call this function anywhere in the code as many times as we want // We can even call the function before we define it // JavaScript will "hoist" the declarations and definitions to the top automatically // LOOPS // A loop repeats a block of code while a condition is true // Here we loop starting with a variable i having a value of 0 // We keep looping as long as i is less than 10 // Each time we finish a loop we add one to the value of i // The i++ is a short form for i = i + 1 // Each time we loop we do what is in the block of code // So we would execute (call) the function makeMonster ten times: for (let i=0; i<10; i++) { // note that we indent the block of code makeMonster(); } // ARRAYS // An Array is a list of variables each with an index that increases from zero const a = [red, green, blue, yellow]; a[0]; // refers to the first element in the array red zog(a[1]); // displays green in the console window a[0] = "pink"; // assigns "pink" to first element of the array // You can nest arrays too const b = [["a","b","c"],["d","e","f"]]; zog(b[0][1]); // b // OBJECTS // An object literal is a collection of properties each with a value that we access via identifier const o = {name:"Dan Zen", occupation:"Inventor"} o["name"]; // has a value of "Dan Zen" o.name; // is the same thing and has a value of "Dan Zen" o["occupation"] = "Professor"; // replaces "Inventor" with "Professor" o.occupation = "Inventor"; // puts "Inventor" back into occupation