ALL LESSONS |
Lesson 07 - Templates and Building
Differences are that time is now in seconds not milliseconds and ES6 is now used not ES5.
Theory
We have practiced the basic parts of programming - the commands, the syntax, abstraction and logic. Now it is time to put all these together to make an app.
We will use the term app loosely to mean a game, puzzle, tool, art piece, etc. We can also make a site but sites are more along the lines of what we make with traditional HTML with pages of text and pictures. An app is often one screen perhaps with panels and the user does something - like makes, communicates or plays.
Slides from WHY ZIM video presentation.
In this lesson, we introduce ZIM Frame and the ZIM Templates. We look at the steps to build apps including many common techniques such as using hitTests. Apps can be run in browsers or packaged up as mobile apps.
Let's take a look at REFERENCE and PRACTICE sections for templates and building!
Reference
ZIM Frame ► ZIM Templates
ZIM has a Frame class that makes a canvas tag, a stage, handles scaling and loading of assets.
We also store a bunch of ZIM colors - but anytime we use a ZIM color, you are welcome to use any HTML color like "red" or "#C00";
// ZIM Frame FIT mode // scaling, width, height, color, outerColor and callback function new Frame(FIT, 1024, 768, light, dark, ready); function ready() { // put code here } // the OLD template used in many older videos and examples - still works... const frame = new Frame(FIT, 1024, 768, light, dark); frame.on("ready", ()=>{ // put code here });
The ready event is called when the canvas and stage are made. We usually want to get easy access to the frame, stage and its width and height so ZIM gives global variables F, S, W, H.
new Frame(FIT, 1024, 768, light, dark, ready); function ready() { // given F (frame), S (stage), W (width), H (height) // put code here // S.update() will automatically be called } // the OLD template is used in many older videos and examples const frame = new Frame(FIT, 1024, 768, light, dark); frame.on("ready", ()=>{ const stage = frame.stage; let stageW = frame.stageW; let stageH = frame.stageH; // put code here stage.update(); // was needed to see the changes });
Scaling Modes ► ZIM Templates
In our lessons, we have been typing code into a textarea and pressing the TEST button.
This shows our code in a ZIM Frame in an HTML tag. We call this the TAG mode.
Here are the scaling modes for ZIM Frame:
Scaling Modes
- FIT - provide app dimensions and fit these inside the window - EXAMPLE
- This is the easiest as you know the dimensions
- For mobile - it can waste space at the edges
- FULL - make an app that is the size of the window - EXAMPLE
- This is harder to make as you have to manually scale things
- It is good for mobile to fill all space
- We use scaleTo() and Layout() to help us
- FILL - provide dimensions and fit these outside the window - EXAMPLE
- Like fit - but content can go outside the window
- Easy full screen when it does not matter
- TAG - fit the app to an HTML tag with this ID - EXAMPLE
- Can specify dimensions or take tag dimensions
- Can style the canvas just like an image
Loading Assets ► ASSET Template
We have full control of when to load assets such as images, sound and fonts and events for when they are loaded.
In many past ZIM examples, assets were loaded with frame.loadAssets().
Now, we can load assets right in the Frame() call. In the ready event function, we can add the image to the stage, play the sound or use the font.
// Loading an image const assets = "image.jpg"; new Frame(FIT, 1024, 768, lighter, dark, ready, assets); function ready() { const image = new Pic("image.jpg").center(); // in older versions of ZIM we used asset() which still works const image = asset("image.jpg").center(); }
// Loading two images - from a folder const assets = ["image.png", "image2.jpg"]; const path = "assets/"; new Frame(FIT, 1024, 768, lighter, dark, ready, assets, path); function ready() { new Pic("image.jpg").center(); new Pic("image2.jpg").loc(100, 100); }
// Loading a sound - using loadAssets with complete event // could just add the sound to the assets array in the earlier examples // but sometimes we want to load assets later on - like for the second part of an app const loadSound = frame.loadAssets("sound.mp3", "assets/"); loadSound.on("complete", ()=>{ new Aud("sound.mp3").play(); // new Aud("sound.mp3").play({loop:-1, volume:2}); });
Chrome and Safari give a security ERROR when interacting with local files containing images and sound. The solution is one of the following. Note that this is an error only when testing locally. When your app is on a server or as an app on mobile, there will be no problem.
Remove Security Error
- Use Firefox
- Put the file on a server
- On PC, adjust Chrome as follows:
- find your Chrome icon or shortcut
- right click and choose properties
- under Target, adjust your target to include:
- --allow-file-access-from-files
- after the quotes - for example:
- "C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" --allow-file-access-from-files
- On Mac, adjust Chrome as follows:
- open your terminal anywhere
- make sure Google Chrome is currently not running
- copy paste this line and hit enter
- open /Applications/Google\ Chrome.app --args --allow-file-access-from-files
// Loading a custom font const assets = {font: "wildwood", src:"wildwood.ttf"}; const path = "assets/"; new Frame(FIT, 1024, 768, lighter, dark, ready, assets, path); function ready() { new Label({text:"hello", font:"wildwood"}).center(); }
// Loading all together const assets = [ "image.png", "image2.jpg", "sound.mp3", {font: "wildwood", src:"wildwood.ttf"} ]; // or put on one line... const path = "assets/"; new Frame(FIT, 1024, 768, lighter, dark, ready, assets, path); function ready() { const img = new Pic("image.png").center(); const sound = new Aud("sound.mp3"); // can't play until user interacts with app img.on("click", ()=>{ sound.play(); new Label({text:"song title", font:"wildwood"}).center(); S.update(); }); // rest of your code here... } // end ready
Template ► Code Zero - Template
ZIM works within a script tag inside our HTML page.
There is an easy-to-copy template on the CODE page.
Here is the TOP and BOTTOM of the template:
<!-- TEMPLATE TOP --> <!doctype html> <html> <head> <meta charset="utf-8" /> <title>ZIM Frame - Fit Template</title> <script type="module"> import zim from "https://zimjs.org/cdn/01/zim"; // many examples and the videos use several script tags // but the import from the module is the new ES6 way // our Frame code STARTS here
// our Frame code ENDS here </script> <!-- TEMPLATE BOTTOM --> <meta name="viewport" content="width=device-width, user-scalable=no" /> </head> <body> <!-- canvas with id="myCanvas" is made by zim Frame --> </body> </html>
So, you can see, that there is not much in the template. Here is the smallest we can get the template to show a draggable circle!
// Smallest Template <html> <script type=module> import zim from "https://zimjs.org/cdn/01/zim"; new Frame({ready:()=>{ new Circle().center().drag(); }}); </script> </html>
Let's practice using templates.
Practice
This practice will be different than our earlier practices in that your are testing things in your own HTML page. Go to the ZIM Code page and from the second grey box section, COPY the ZIM template. Make an HTML page (text page with .html extension) in an editor like ATOM. REMOVE the Circle code from the template then follow the instructions below.
Reference
Building ► ZIM Badges - APP
We have the parts of coding and the template to build in - now, how do we build?
First of all... it helps to know what we are building ;-)
See the Dan Zen Creativity Tour for a guide.
Steps to Build
- Come up with an idea - see Creativity Framework
- Sketch the idea or draw wireframes
- User test the wireframes - do they make sense
- Choose a template and start coding
What First?
Build the main part of your app first.
You want to know that this will work before you put effort in to the rest of the app.
Do not build your intro screen first and have to wait for animation and click through every time you want to get to the main part of your app.
That will slow you down.
Things like your intro, help and about screens, conclusions - add these last.
Efficiencies
You want to make things easy to test.
So leave distracting sounds and animations until the end.
At least turn off your animations (see ZIM ANIMATE constant).
Often, you can build with Rectangle and Circle shapes as placeholders
and substitute final graphics when you know your app will work.
Hard Code
Do one step at a time. Get things on the stage with hard-coded values.
If you see that you are repeating code, then you can apply the Abstraction lesson.
But generally, get something to work, then make it efficient.
Then get something else on the stage, then make it efficient, etc.
Try not to wait until the end to make things efficient, but do not try to start efficient.
Build Order
We build in steps and often these go in cycles:
Common Build Order
- Add an asset
- Shape, Image, Component, Sprite, etc.
- Apply an event
- click, mousedown, pressmove, pressup, etc.
- Call a function
- animate, remove, add, move, score, etc.
- Repeat
Examples ► ZIM Examples
Most of the ZIM Examples are commented for learning and show a variety of complexities.
Note that they have been made through time so see the ZIM Tips for current code techniques.
A great place to practice is the ZIM Badges tutorial called APP that takes you through the many steps of making an app. We do not need the ZIM namespace as we use in the tutorial.
GitHub is an application for keeping track of changes. It can be used to show the actual build steps taken. Here is an advanced application called PsychicPixels in GitHub. Note the first bunch of steps at the bottom of the list. You can read a description of the changes and see the code for each step.
The code for a finished app always looks like a lot and complex. Yet the code is created a step at a time. It does take some practice to keep track of where you are going and what you have done. It almost seems like one problem after another! Yet, that is building. Make sure that you revel when things go right!
Patterns ► What IZ a Pattern?
► Module Pattern?
► MVC?
Patterns can be found when things repeat.
We can be efficient if we notice a pattern and store it in a variable, function, loop, class, etc.
There are also build patterns - where the types of apps or parts of apps have similarities across projects. These tend to be advanced so have a look at them when you are ready. There is the Module pattern and the MVC or Model View Controller pattern - and there are certainly more.
Techniques ► ZIM Bits
There are many build techniques that we use over and over in Interactive Media.
In other words - these are patterns for the parts of what we build.
These are demonstrated in the ZIM Bits site.
As we build, we insert code based on these techniques.
Build Techniques
- Collections
- Containers of monsters
- We loop and get children
- We apply events and use e.target
- We can apply hitTests
- Snapping
- Drag and drop can slightly miss
- So animate the item to final place
- Or if too far away, go back
- Proportions
- Change this to change that
- Sliders, Dials, Mouse positions
- control size, rotation, etc.
- Damping
- Head towards values
- Looks natural
- The same thing as easing
- Tilings
- A page of thumbnails
- Done with a loop or double loop
- Controls
- Scrollers, Parallax, MotionControllers, Emitters
- See Controls Lesson
- Components
- Buttons, Panes, Sliders, etc.
- See Display Objects Lesson
- Progress Bars
- Loading animations
- Based on percent loaded
- See Frame events
Hit Tests ► TIPS HitTests ► Early HitTest examples ► hitTestPath
A very important technique in Interactive Media is the hitTest.
We often want to find out if two DisplayObjects are hitting each other and we must constantly test - not just once.
So we test in a Ticker function or in a pressdrag event, etc.
See the different types of hitTests down below.
// simple hitTestBounds const rectangle = new Rectangle().center(); const dragRect = new Rectangle().loc(100,100).drag(); // can't just check once if hitting... it would only check at the start // so put hitTest in pressmove event dragRect.on("pressmove", function() { if (dragRect.hitTestBounds(rectangle)) { zog("hitting"); if (rectangle.color != red) { rectangle.color = red; stage.update(); } } else { if (rectangle.color == red) { rectangle.color = black; stage.update(); } } }); // Note - this is a simple example testing two objects // Often we have to test if an object is hitting many other objects // To do this we put the many objects in a container // and loop through the container testing each one! // See the practice examples
DisplayObjects have a Bounding Box that is a rectangle around the object. It is very quick to find out if two rectangles are hitting - it is a simple equation for the computer. But it is harder to find out if the actual shape (the object's colored part) is hitting. It is TOO SLOW to test if two complex shapes are hitting so we test to see if a Point or points are hitting a shape.
In the diagram below, the hitTestBounds (fast) would be hitting where the hitTestCircleRect (fast) would not which is a better answer.
A hitTestCircle (slower) could be used but it would test if the shape of the rect is hitting points around the circle so this is slower and not completely accurate.
The hitTestCircle is the best to use if detecting a round pod hitting the complex shape of the asteroid. This would hit if any part of the shape hits a pink dot around the asteroid.
Types of HitTests
- obj.hitTestPoint(x, y) - object shape hitting a point
- obj.hitTestReg(target) - object shape hitting the target's registration point
- obj.hitTestRect(target) - object shape hitting points in rectangle around target
- obj.hitTestCircle(target) - object shape hitting points in circle around target
- obj.hitTestCircles(target) - FAST - uses equation to see if two circles are hitting
- obj.hitTestBounds(target) - FAST - uses equation to see if bounds are hitting
- obj.hitTestPath(target) - object shape hitting points on path of Blob or Squiggle
- obj.hitTestGrid(grid specs) - FAST an index or row/col for a point on a grid
Practice
Here are examples of some build techniques. More can be found in at ZIM Bits. We are back to practicing with the TEST button on this page but you are welcome to start building apps in your own template files.
Summary
Learning to build takes time. After a while, you start to know how to solve certain problems. Keep coming back to this lesson as you progress and you will find you understand the tips here more as you go.
Programming is the world's best puzzle. Enjoy your time programming and feeling the satisfaction of building! Rest assured, ZIM helps you do things easily. Do not go off to some other framework because you find this hard. It will be just as hard and most likely harder in other frameworks. Help is always available at ZIM SLACK.
LESSON 06 - Conditionals and Debugging LESSON 08 - Controls
VIDEOS
ALL LESSONS |