JANUARY 25, 2015 LEARN TO CODE STNMAST2008 IN MAKE YOUR OWN APP: PART TWO 1 EXTEND YOUR APP! You’ll need a mixture of concentration and creativity — but learning to code is the new literacy and puts you among the 1% of the global population tuned in to the language of the future, says Eleanor Mills W e all know about the three Rs – reading, writing and arithmetic. Well, in the 21st century there is a new kind of literacy we all need to get to grips with: computer coding. PART TWO 13 THE POWER OF LIBRARIES Using jQuery and CSS to change image ! THE BRIEF 14 LOOPING Repeating the image change 15 ADDING TOUCH Detecting a touch input 16 OBJECT AND LOGIC Creating player logic 17 SCORING Is there a snap? Last week nearly 10,000 of you took up The Sunday Times’s challenge to create an app; this week we give you the final steps. Coding is a surprising mixture of extreme attention to detail and creativity. Today we hope you will discover that with your Snap That! game. Yes, you need to follow the instructions carefully to get the program to work, but the Playto Editor, powered by Decoded, makes the coding experience easier. What pictures you use for the game is entirely up to you. We’ve created versions with cats, dogs, cakes and cars, but why not use your favourite photographs? It’s your app, so you choose. That’s the point of this — to create a nation driving technology, rather than being passive users of it. When we code we stand on the shoulders of giants: we don’t have to reinvent a geolocator, or one of those clever drop-down calendars; we can just import the best way of doing it by copying and pasting. By introducing coding into the national curriculum, we are leading the western world in equipping our children with the skills they will need. The Sunday Times wants to empower you in technology. By completing this two-part series, you will join the 1% of the world that understands the language of the future. That has to be worth a bit of effort. 18 SINGLE WINNER Preventing multiple snaps 19 WINNER LOGIC Is there a winner? PRELOADING IMAGES AND DEBUGGING 20 Speeding up the gameplay and testing for errors CREATE AN APP IN A DAY 13 THE POWER OF LIBRARIES Welcome back. If you missed last week’s supplement, which covered steps 1-12, you can find them online at tinyurl.com/STsnap if you’re a subscriber, or at learn.playto.io/snap-that/ lesson/0 outside the paywall. // Use jQuery to change css background image of canvas 1 & 2 $("canvas#1").css("background-image", url1); $("canvas#2").css("background-image", url2); Now we’re going to finish making our Snap That! web app. Go to thesundaytimes.co.uk/learntocode and open your project. 14 Last week we set up the format for the game, found some pictures online, which we put in an image array, and tested our random number generator. This week we’re going to write the code that makes the game work and tell it to select from our images at random every two seconds. We’ve printed a complete list of the code for the Snap That! app on the back cover of this section, for reference. So, our first task is to add a CSS image background instruction to our canvas elements from JavaScript — in other words, to tell the game to put our pictures in the boxes. It is called a background image because we can put text and other items on top. This is complex stuff, but luckily for us we can use an open source JavaScript library — or jQuery — to help. Here’s what you do next. 1 CONNECT JQUERY LIBRARY The phrase “standing on the shoulders of giants” is often used of services such as jQuery. It is a library of JavaScript code that is freely available for coders of all capabilities to include in their programs. See panel, right, and take a look at its website, jquery.com, if you’d like to find out more. The code for the functions we are about to include runs to hundreds of lines. Rather than insert it all into our script.js file, we create a short link in our index.html file that directs the browser to where it can find the code. It then remembers it (until you clear the browser’s cache). To include jQuery code we are going to use a CDN, or content delivery network (see panel, far right). Insert the code below in your index.html file (above where you link to script.js). This will give us the power to use all the functions within the jQuery library. LOOPING JQUERY jQuery is a JavaScript library for web developers that makes using JavaScript quicker and easier. jQuery provides many easy-to-use functions that help you to manipulate and add interactivity quickly to your HTML page. When connected to our project it can be used to make dynamic changes in our code. jQuery UI is a library that contains many reusable components such as date pickers, progress bars, tooltips and lots more. <canvas id="2">Canvas not supported </canvas> 3 CHANGE CANVAS BACKGROUND IMAGE FROM SCRIPT.JS Now we have added unique IDs to our canvas elements we can go to our script.js file and use the code below to change their backgrounds (pretty cool, huh?). We are using a jQuery function here called “.css” which adds CSS to an element. The “$” is shorthand for jQuery — to save developers from typing “jQuery”. Have a look at the preview and you should see your images displaying. When you press the Refresh icon, the images should change randomly. All the rest of the code will be in the script.js file until we reach step 20. Let’s also add a comment (“// play function ends here”) to the final closing { bracket. It’s easy to forget which function these closing brackets connect to, so it is a good habit to comment closing brackets. // Create play function function play() { // Randomly change number // Test random numbers We’re adding these unique identifier attributes, or IDs, to each canvas element in our index.html file so we can apply different image backgrounds. <p>PLAYER 2</p> Inside our “play” function should be the variables for num 1 & 2, img 1 & 2, url 1 & 2 and our jQuery functions to change the canvas background image. imgArray.length ); 2 ID CANVAS ELEMENTS // console.log("First random number is" +num1); IDS The “ID” attribute can be added to any element to identify that element uniquely. This allows JavaScript or CSS to be used to manipulate the style, behaviour and content of the element. The HTML specification states that the ID of an element should be unique. This means that one element should not have the same ID as another. In practice, in most cases you’ll probably get away with using duplicate IDs. A content delivery network (CDN) is a network of servers all over the world that host files for developers to use. In this instance we’re using a CDN to hold our jQuery file. Many developers probably want to use jQuery, so it makes sense for us to all link to the same file. Also, now we’re happy our random number generator is working properly we can “comment out” the console.log tests — that is, we put two slashes before them to tell the browser not to treat it as code. See “Comments” panel on page 5. num2 = Math.floor( Math.random() * <script src="script.js"></script> <p>PLAYER 1</p> Create a new function called “play”. Watch where this code is added. It needs to wrap around the code you’ve already written that changes the image randomly. imgArray.length ); 1.11.0.min.js"></script> </canvas><h1>PLAY SNAP THAT!</h1> 1 CREATE ‘PLAY’ FUNCTION num1 = Math.floor( Math.random() * <script src="//code.jquery.com/jquery- <canvas id="1">Canvas not supported Now we’ve got our images displaying we need to set them to change on a timer. To do this we will use something called a loop. CONTENT DELIVERY NETWORK // console.log("Second random number is" +num2); // Create image variables var img1 = imgArray[ num1 ]; var img2 = imgArray[ num2 ]; // Create css value for background image var url1 = "url("+ path + img1 +")"; var url2 = "url("+ path + img2 +")"; // Use jQuery to change css background image of canvas 1 & 2 $("canvas#1").css("background-image", url1); ATTRIBUTE Each element of an HTML page can have a number of “attributes”. A paragraph, for example, might have a style attribute, or a link might have a source attribute. These are additional pieces of information added by the developer about a specific element on the page. $("canvas#2").css("background- Watch where we add this code. It should go directly above where we begin the “play” function. image",url2); // Create variables for canvasSTNMAST2008 1 & 2 var canvas1 = document.getElementById("1"); } // play function ends here 2 LOOP PLAY FUNCTION ON TIMER To get the play function to loop we can add a “setTimeout” function. This is another native function in JavaScript. In the brackets that follow the function we need to add two “arguments”. The first defines which function to run, and the second defines how long to wait. In this case we are running the “play” function, and setting the “delay” argument to 2000 milliseconds — that’s two seconds, of course, but we measure it in milliseconds. See “Arguments” panel, right, for more information about how this works. Add this on the line just before your “play” function closes. // Repeat loop every 2000 milliseconds setTimeout(play, 2000); } // play function ends here 3 USE H1 TO PLAY Now that the image loop is within a function it won’t play automatically. We need a button to trigger play, and we can use the h1 to start the game. We can add a load of jQuery functions to begin play and to hide and show the h1 and paragraph elements. Watch where this code is added. It goes above where the “play” function begins. var canvas2 = document.getElementById("2"); ARGUMENTS Arguments are bits of information that you give a function that modify the behaviour of the function. If we were to think of functions as verbs, we could consider arguments as adverbs. Imagine we had a robot that understood the function “walk()”. We could pass an argument to the function to tell the function to walk quickly like this: walk(“quickly”); A more realistic JavaScript function would be the native function alert(). The alert() function displays a popup in your browser with a message. We pass the function the message to display like this: alert(“Hello, world!”). In this example, “Hello, world!” would be the argument. $("h1").click(function() { // Run play function }); // Create play function When you press your h1 in the “View Your App” preview, the images should randomly cycle! 15 ADDING TOUCH Amazing! We’ve got our snap game looping and displaying random images. Now we need to detect when a player touches the screen. 1 CREATE VARIABLES FOR CANVAS 1 & 2 Our canvas elements have been labelled in our HTML as either 1 or 2. We use “document.getElementById” to find an element in our HTML document and store the result in a new variable. var canvas1 = document.getElementById("1"); var canvas2 = document.getElementById("2"); // Create event listeners for canvas 1 & 2 canvas1.addEventListener("touchstart", playTouch1); canvas2.addEventListener("touchstart", playTouch2); VIEW MY APP On a desktop computer, if you hover over “view your app” a QR (quick response) code should appear. This is a visual link to view your app, and if you have a QR code reader, you can scan this image and your app should open. If you don’t have a QR code reader, you should also see a short link appear when you hover over the “view your app” link. You can type this link into the browser on your phone or tablet and your app will open. playTouch1); h1 when it has been pressed $("p").show(); JavaScript can be used to identify the name, or ID, of an element on a page. It is what’s called a “native” function of JavaScript (one that will work without any external libraries or plugins). // Create variables for canvas 1 & 2 canvas1.addEventListener("touchstart", // Use jQuery 'hide' function to hide DOCUMENT. GETELEMENTBYID After “touchstart” we tell it what to do when a touch is received. “playTouch1” and “playTouch2” are new functions that we’ll create next. We could call these anything, but these names are short and clear. // Create event listeners for canvas 1 & 2 play(); 'p's when play is started The “addEventListener” function (see panel, below left) allows us to detect if there is a user touch or click. In the brackets we define when the device should react. In our case we want it to trigger when the user first touches the screen, so on “touchstart”, rather than “touchend” or “touchmove”. When a touch is detected in a canvas — in other words, on one of the pictures — it will trigger one of these functions. Now we’re using touch we can’t test this on a PC any more, so we can use an alert popup instead. Get “View Your App” running on your smart phone or tablet and test the touch events are registering. starts play // Use jQuery 'show' function to show 2 CREATE EVENT LISTENERS FOR CANVAS 1 & 2 3 CREATE PLAYTOUCH 1 & PLAYTOUCH 2 // Use jQuery 'click' function so h1 $("h1").hide(); // Create play function ! canvas2.addEventListener("touchstart", EVENT LISTENER An event listener is a function that responds to some event in your browser. For instance, you can add an event listener to the “submit” event of a form on your page. When the form is submitted by the user, any functions listening for this event will be run before the normal behaviour of submitting the form content to the server is allowed. This is exactly how form validation works. In this case, the event listener will check the submitted details and if any of the data is invalid (for example, an email address isn’t valid), the event listener will stop the browser from submitting the form. playTouch2); // User clicks canvas1 EVENT. PREVENTDEFAULT function playTouch1() { // Test touch is registered alert("Player 1 Touch!"); Sometimes on a web app we don’t want the default behaviour of, say, a mouse click to trigger anything. The “prevent default” function will prevent something from happening (usually a new page loading), which means that we can give the user a smoother experience. } // User clicks canvas2 function playTouch2() { // Test touch is registered alert("Player 2 Touch!"); } 4 PREVENT TOUCH MOVE When you were testing your apps, you may have found that the browser screen moved up and down. For our game we want to fix the browser in place. So we insert another “addEventListener” at the top of script.js. This is targeting the Turn to page 4 Â CREATE AN APP IN A DAY } // play function ends here whole document body element and prevents the default behaviour. // Find out if there was a snap // Stop browser scrolling function snapCheck() { document.body. addEventListener("touchmove", function(event) { event.preventDefault(); }); // Test if script.js is working // alert("Hello World!"); Your game is now able to detect touch inputs! You’ll have to test this next bit on your smartphone or tablet, as your PC (probably) can’t detect touch. If you hover over “View Your App”, a short URL and a QR tag will show to help you launch your app on your device. If your game is working properly, when you press the top canvas (player 1) or bottom canvas (player 2) an alert should pop up! 16 OBJECTS AND LOGIC if (num1 == num2) { OBJECT An object is a good way of storing a number of variables. Rather than saving the score and the ID of one player separately, we can save them together. This means they will be easier to compare when we need to pick a winner. Under the lines where we created our “num1” and “num2” variables, create two “objects”. These look like the variables created just above, but they contain multiple pieces of information, a score and an ID. We set their initial scores to zero and give them each a unique ID. // Create variables for which card to pick randomly var num1; alert("SNAP!"); } else { // Images do not match! alert("NO SNAP!"); } } // User clicks canvas1 function playTouch1() { // Test touch is registered // alert("Player 1 Touch!"); // Run snapCheck to see if there is a snap! LOGIC Logic is what we call the decisions we make in code. In this case we are comparing “num1” and “num2” and asking if they are the same (==). If they are, this means the images must be the same, an alert pops up that says “SNAP!” snapCheck(); } // User clicks canvas2 function playTouch2() { // Test touch is registered // alert("Player 2 Touch!"); // Run snapCheck to see if there is a } Now when a player taps an image, our new snapCheck function will run to see if there is a snap. Test this is working on your smartphone or tablet. Tap “Play Snap That” and if the images are the same you should see a popup: “SNAP!” id: 1, }; }; 2 CREATE SNAPCHECK FUNCTION Next, we’re going to check if a snap has been made. Create a new function at the bottom of script.js. We can call this anything, but snapCheck seems a good name. Inside the function we are going to compare the two “num” variables to see if they are the same. In JavaScript we use “==” to compare two things. If they are the same, an alert is triggered that will say, “SNAP!” If they are not the same, an alert will display saying, “NO SNAP!” Our new snapCheck function won’t change anything quite yet, though, as we aren’t running this new function. Return true means that the function will stop and record a value of “true”; return false means the same but that a value of “false” will be recorded. snapCheck(); score: 0, id: 2, ‘RETURN TRUE’ AND ‘RETURN FALSE’ snap! var player1 = { score: 0, A double plus (++) adds one to a variable, and a double minus (--) takes away one from a variable. Comment out the lines in playTouch1 and playTouch2 that run the two alerts and add in snapCheck(); // Create object for Player 1 var player2 = { ++ AND Finally, we’re going to add in a line that will run our new snapCheck function. var num2; // Create object for Player 2 +/- 3 RUN SNAPCHECK IN PLAYTOUCH FUNCTIONS Our app is taking shape. Let’s weave in some behaviour to turn our app into a game. First we need to store information about our players. We’re going to create an object and use this in our game logic (see panels, right). 1 CREATE OBJECTS FOR PLAYER 1 AND PLAYER 2 // Images match! Snap! <SPAN> 17 SPAN SCORING A span is an HTML element that we can use to hold a word or piece of text. Spans can be updated dynamically – in the case of a score, for example. We can now detect if there is a snap or not. We should award players points when they get a snap, and let’s give them some feedback while they play so it’s easy to see who’s winning. with the ID score1 and score2. 1 ADDING A SCORE SPAN We need an area to display the score in our HTML content. Find the two p elements for PLAYER 1 & 2 and add spans <p>PLAYER 1: <span id="score1">0</span></p> <p>PLAYER 2: <span id="score2">0</span> </p> 2 TELL SNAPCHECK WHICH PLAYER TOUCHED SCREEN // User clicks canvas1 CACHED What is "cached"? It means that something — usually images or videos — is saved to a user’s browser so that it can be loaded more quickly. ERROR? DON'T PANIC Inevitably it won't always work. If you get an error message, go back through and check every line of code. We’ve printed the complete code for the app on the back cover. Help is also at hand at our forum — post your problem at forum.playto.io function playTouch1() { // Images match! Snap! // Test touch is registered // alert("SNAP!"); // alert("Player 1 Touch!"); // Player gains 1 point // Run snapCheck to see if there is a player.score++; snap! 3 // Update player score snapCheck(player1); } $("span#score"+player.id).html(player. score); // Highlight player won! // User clicks canvas2 function playTouch2() { // Test touch is registered // alert("Player 2 Touch!"); // Run snapCheck to see if there is a $("p#player"+player.id). # snap! snapCheck(player2); } When we call “snapCheck” from within “playTouch1” and “playTouch2” we can be clear which player has touched the screen. Add “player1” and “player2” as an argument between the brackets that follow “snapCheck”. 3 ADD A PLAYER ARGUMENT TO SNAPCHECK Now in our “snapCheck” function we can use our player object as an argument to give that player a point. First, add an argument into the brackets after “snapCheck” — snapCheck(player). Then inside snapCheck it will replace “player” with the information sent from “playTouch1” or “playTouch2”. It will then change player1.score or player2. score. We use ++ to increase by 1, and -- to decrease by 1. // Find out if there was a snap function snapCheck(player) { if (num1 == num2) { // Images match! Snap! alert("SNAP!"); // Player gains 1 point player.score++; } else { // Images do not match! alert("NO SNAP!"); // Player loses 1 point player.score--; } } STNMAST2008 css("background", "LightGreen"); } else { // alert("NO SNAP!"); // Player loses 1 point # In CSS and jQuery, a hash symbol means that you are targeting the “ID” of an element. THE CONSOLE // Images do not match! player.score--; // Update player score $("span#score"+player.id).html(player. score); // Highlight player lost a point $("p#player"+player.id). CSS css("background", "DeepPink"); } } 5 RESET PLAYER P BACKGROUND CSS CSS, THE LANGUAGE OF DESIGN CSS stands for cascading style sheets. It was developed by Hakon Wium Lie and Bert Bos in the early 1990s. Fundamentally, CSS gives developers the ability to breathe life into HTML – colours, borders, backgrounds and more. We’ll be showing you a variety of CSS commands, but to see an entire list of them have a look at the W3 Schools CSS page at w3schools.com/css. So when a snap is attempted, the background colour of our player p elements will change. When a new pair of images is shown, we need to reset our player p backgrounds to yellow. Now the score has changed, we can display it in our page using a jQuery “.html” function. This replaces any existing HTML in an element with updated content. It is great when you want to dynamically give a user new text or information. Comment out the alerts in “snapCheck” and add in two new jQuery functions. Remember, $ means the program is using a jQuery function. Finally, we use another jQuery CSS function to change the background of our “player p” to show who won, or lost, a point. // Find out if there was a snap function snapCheck(player) { if (num1 == num2) { 1) It is a place to output diagnostic information like JavaScript and CSS errors and any information passed to the console. 2) It is an interface in your browser where you can execute JavaScript commands directly. This lets you test out JavaScript commands before adding them to a script. Add a new jQuery CSS function in the play function. // Repeat loop every 2000 milliseconds setTimeout(play, 2000); // Reset player p backgrounds $("p").css("background", "yellow"); } // play function ends here 6 ADD P PLAYER IDs IN HTML Finally, we need to add the p paragraph IDs into our HTML so they will change colour. <p id="player1">PLAYER 1: <span id="score1">0</span></p> <p id="player2">PLAYER 2: <span id="score2">0</span></p> 4 DISPLAY UPDATED SCORE AND HIGHLIGHT WINNER The console displays diagnostic information about the web page being displayed. It has two purposes: You should find that if the images are matching, the player’s score will increase and the p background will change to green. If not, the player will lose a point and the colour will change to pink. The colours should reset when an image changes. 18 SINGLE WINNER You may have noticed in your testing that it is possible to have more than one winner, or loser. This is not ideal ... 1 CREATE A ‘SNAPMADE’ FUNCTION Below your player objects, create a new variable. Again, we could call this new variable Turn to page 6 Â COMMENTS These are essential for any web project. One reason you should always try to put comments in your work is in case another developer picks up the project and wants to continue with it. In the open-source community, where hundreds or thousands of people will be working on a project, comments allow people to explain how they decided to structure the code. Even if you’re the only one who will ever be coding your project, if you write some code and then come back to it a year later you may have forgotten why you wrote it. Comments are really useful for jogging the memory. CREATE AN APP IN A DAY // Test touch is registered anything, but “snapMade” is short and clear. This will allow us to control what happens when a snap has been made, and stop any further points being dished out. // alert("Player 1 Touch!"); // Run snapCheck to see if there is a // Create object for Player 2 var player2 = { score: 0, id: 2, }; // Create snapMade variable var snapMade = "NO"; 2 SET SNAPMADE TO ‘YES’ IN SNAPCHECK “snapMade” will now be set to “YES” if a player correctly gets a snap. BE AS CREATIVE AS YOU LIKE Once you understand the principles of CSS, you can add as many rules for each bit of the page as you like. What's great too is that they're all interchangeable, so if you know how to change the size of a heading, you can change the size of a paragraph (or anything else you like). // Find out if there was a snap function snapCheck(player) { if (num1 == num2) { // Images match! Snap! // alert("SNAP!"); // Player gains 1 point player.score++; // Update player score $("span#score"+player.id).html(player. score); // Highlight player won! $("p#player"+player.id). css("background", "LightGreen"); // Snap Made! snapMade = "YES"; } 3 RESET SNAPMADE IN PLAY FUNCTION At the top of our play function, now that images are reset, we should reset snapMade to “NO” so the game can continue. // Create play function function play() { // Reset snapMade snapMade = "NO"; // Randomly change number num1 = Math.floor( Math.random() * imgArray.length ); num2 = Math.floor( Math.random() * imgArray.length ); snap! if (snapMade == "NO") { snapCheck(player1); } } // User clicks canvas2 function playTouch2() { // Test touch is registered // alert("Player 2 Touch!"); // Run snapCheck to see if there is a snap! if (snapMade == "NO") { RGB snapCheck(player2); } IN THE PINK There is a set number of "word colours" that have already been defined by developers, but if you truly want to customise your design, you'll need to pick your own. To do this, you can go to colorpicker.com, and you'll see that each colour has an R, G and B value (standing for red, green, blue). Just select a colour you like, and then copy the RGB colours to your CSS. For example, you might change your heading to a lovely shade of pink: h1 { color: rgb(222, 38, 210); } If you'd like to have a bit of transparency in your colour, you can also give it an "alpha" value between 0 and 1, with 0 being completely transparent and 1 being opaque. h1 { color: rgba(222, 38, 210, 0.8); } } Now only one player should be able to win a point for each image snap. Have a quick play to check it is working properly! 19 WINNER LOGIC It’s possible that you’ve already had some fun playing your snap game. We think every game benefits from a goal — so next we’re going to set a winning score, and when that target is reached we’ll display a winner. Finally, in our playTouch functions, before we run snapCheck we use some logic to see if a snap has already been made. If snapMade is equal to “NO”, the program will go on to check if the images match. If snapMade is equal to “YES”, snapCheck will not be run and the player cannot gain any points. // User clicks canvas1 function playTouch1() { In the Playto editor, hover over the “View Your App” link in the top right of the screen. This will give you a short link that’s perfect for sharing on your favourite social media sites! Why not challenge your friends and family to a game the next time you see them. You could ask your friends to share their scores via social media and create a leaderboard of the speediest snappers. 1 ADD ISTHEWINNER LOGIC TO PLAY FUNCTION Inside your play function, add some logic which checks if “player1” or “player2” is the winner. If not, the play function will carry on looping the images as before. Watch where this code is added. The check code starts just after the “play” function starts, and ends just before the “play” function finishes. // Create play function function play() { // Check is there is a winner?? if (isTheWinner(player1) || isTheWinner(player2)) { return } else { // Reset snapMade 4 ADD SNAPMADE LOGIC TO PLAYTOUCH 1 & PLAYTOUCH 2 LET THE WORLD PLAY YOUR GAME snapMade = "NO"; ....... // Repeat loop every 2000 milliseconds setTimeout(play, 2000); We would like to thank the team at Decoded for all their help with this project, and for creating the Snap That! game. Decoded, which has offices in London, New York and Sydney, aims to spread “digital enlightenment”. It runs regular one-day courses for those wanting to improve their digital skills as well as providing online resources such as the tutorial on which this supplement is based. Go to decoded.com to find out more. } // isTheWinner logic ends here } // play function ends here You’ve now finished all the JavaScript in your Snap That! game. When you play it, there should be a set number of wins, and when that is reached, the looping images will stop and the h1 will change to display the winner! 20 2 CREATE ISTHEWINNER FUNCTION Now we need to create our “isTheWinner” function. You can put this right at the bottom of script.js. This will receive either “player1” or “player2” when it is run from our “play” function. It then compares the score value with a number. We’ve set the number of wins to 2 — you can set it to whatever you like. PRELOADING IMAGES AND DEBUGGING You may find that your images are a little sluggish to load, and they don’t always display in sync. This is because we are reloading the background image each time. What we can do is preload the images first — then the browser will be able to call the cached versions and run much more smoothly. If the player score is equal to 2, it will send a message back to the play function that there is a winner. If the player score is not equal to 2 it will send a message that there is currently no winner. Our play function checks both player1 and player2. If there are no winners it will continue looping our images. 1 ADD PRELOADING SPANS TO HTML // Has a player won? <canvas class="card" id="2">Canvas not function isTheWinner() { supported</canvas> // If player reaches a score of 2 points they win!! if(player.score == 2) { // Tell play function there is a winner! STNMAST2008 In your HTML, just below the second canvas element, add in some spans with unique IDs. Each span needs a unique ID; we’ve used “preload-01” etc. You will need the same number of spans as you have images in your game. <span id="preload-01"></span> <span id="preload-02"></span> <span id="preload-03"></span> <span id="preload-04"></span> <span id="preload-05"></span> return true } // Tell play function there is no winner return false } In your Style.css file add an instruction for each of your new spans (we’ve done two below). Each span should be given one of your images as its background. As we haven’t given our spans any size they will not display in our page. However, our CSS will now preload our images. span#preload-01 { 3 HIDE P AND SHOW NEW H1 CONTENT If there is a winner, we can add jQuery functions to hide our player scores, show our h1 and change the content of our h1 to display the winner. Check this is working properly. You can also play around with the target score to make it harder or easier to win! // Has a player won? function isTheWinner(player) { // If player reaches a score of 5 points they win!! if(player.score == 2) { $("p").hide(); $("h1").html("PLAYER " + player.id + " WINS!"); $("h1").show(); // Tell play function there is a winner! return true } // Tell play function there is no winner return false } 2 ADD BACKGROUND IMAGES TO YOUR SPANS IN CSS background: url("http://image-url/ image1.jpg"); } span#preload-02 { background: url("http://image-url/ image2.jpg"); } 3 CHECK OUR IMAGES ARE PRELOADING IN NETWORK Test out your game. The images should load much more smoothly now. You can also check the images are loading by using a browser tool similar to the console from step 11. Open the console as before, but then click on the “Network” tab to the left of the console at the top of the console space. When you refresh the page you should see all your images loading in the background. CONGRATULATIONS! Feel free to customise your game. You can change the colours, fonts, the number of wins required, how fast the images cycle and add as many images as you like! I’m sure you’ve figured this out, but if you want to play again, simply refresh the browser. When you’re finished, make sure you share your creation. See the “Let the world play your game” panel on the opposite page for ideas. We’ve built versions of Snap That! with cats, cars, dogs and cakes. Let your imagination run riot and tell us what you’ve come up with Quick check: if you have followed the instructions in last week’s section and these pages correctly, the code you have written should look as it does in the boxes below — if you have any problems there is a forum waiting to help you at forum.playto.io. Key in your question and it will be answered INDEX .HTML <!--This app was made by Harriet--> <!DOCTYPE html> <html> <head> <title>Snap That!</title> <meta name="viewport" content="width=device-width, initial-scale=1.0, userscalable=no"> <link href="style.css" rel="stylesheet"> </head> <body> <section> <canvas id="1" >Canvas not supported</canvas> <h1>PLAY SNAP THAT!</h1> <p id="player1"> PLAYER 1: <span id="score1">0</span> </p> <p id="player2">PLAYER 2: <span id="score1">0</span></p> <canvas id="2">Canvas not supported</canvas> <span id="preload-01"></span> <span id="preload-02"></span> <span id="preload-03"></span> <span id="preload-04"></span> <span id="preload-05"></span> </section> <script src="//code.jquery.com/ jquery-1.11.0.min.js"></script> <script src="script.js"></script> </body> </html> SCRIPT.JS STYLE.CSS body { font-family:Helvetica; text-align:center; background:LightGrey; } canvas { width:100%; height:42%; background-color:yellow; border-radius:15px; background-image:url("http:// image-url/image1.jpg"); background-size:cover; background-position:center; } html, body, section { height:100%; } h1 { background:yellow; padding:2%; margin:2%; border:2px solid black; border-radius:40px; } p { width:40%; float:left; padding:2%; margin:2%; border:2px solid black; border-radius:40px; background:yellow; display:none; } span#preload-01 { background: url(“http://image-url/ image1.jpg”); } span#preload-02 { background: url(“http://image-url/ image2.jpg”); } span#preload-03 { background: url(“http://image-url/ image3.jpg”); } span#preload-04 { background: url(“http://image-url/ image4.jpg”); } span#preload-05 { background: url(“http://image-url/ image5.jpg”); } // Stop browser scrolling document.body. addEventListener("touchmove", function(event) { event.preventDefault(); }); // Test if script.js is working // alert("Hello World!"); // Define images to use var imgArray = ["http://image-url/ image1.jpg","http://image-url/image2. jpg","http://image-url/image3. jpg","http://image-url/image4. jpg","http://image-url/image5.jpg"]; // Create variables for which card to pick randomly var num1; var num2; // Create object for Player 1 var player1 = { score: 0, id: 1, }; // Create object for Player 2 var player2 = { score: 0, id: 2, }; // Create snapMade variable var snapMade = "NO"; // Use h1 to play $("h1").click(function() { // Run play function play(); // Use jQuery 'hide' function to hide h1 when it has been pressed $("h1").hide(); // Use jQuery 'show' function to show 'p's when play is started $("p").show(); }); // Create variables for canvas 1 & 2 var canvas1 = document. getElementById("1"); var canvas2 = document. getElementById("2"); // Create event listeners for canvas 1 & 2 canvas1.addEventListener("touchstart", playTouch1); canvas2.addEventListener("touchstart", playTouch2); // User clicks canvas1 function playTouch1() { // Test touch is registered // alert("Player 1 Touch!"); // Run snapCheck to see if there is a snap! if (snapMade == "NO") { snapCheck(player1); } } // User clicks canvas2 function playTouch2() { // Test touch is registered // alert("Player 2 Touch!"); // Run snapCheck to see if there is a snap! if (snapMade == "NO") { snapCheck(player2); } } // Create play function function play() { // Check is there is a winner?? if (isTheWinner(player1) || isTheWinner(player2)) { return } else { // Reset snapMade snapMade = "NO"; // Randomly change number num1 = Math.floor( Math.random() * imgArray.length ); num2 = Math.floor( Math.random() * imgArray.length ); // Test random numbers // console.log("First random number is " +num1); // console.log("Second random number is "+num2); // Create image variables var img1 = imgArray[ num1 ]; var img2 = imgArray[ num2 ]; // Create css value for background image var url1 = "url("+ img1 +")"; var url2 = "url("+ img2 +")"; // Use jQuery to change css background image of canvas 1 & 2 $("canvas#1").css("backgroundimage", url1); $("canvas#2").css("backgroundimage", url2); // Repeat loop every 2000 milliseconds setTimeout(play, 2000); // Reset player p backgrounds $("p").css("background", "yellow"); } // isTheWinner logic ends here } // play function ends here // Find out if there was a snap function snapCheck(player) { if (num1 == num2) { // Images match! Snap! // alert("SNAP!"); // Player gains 1 point player.score++; // Update player score $("span#score"+player.id). html(player.score); // Highlight player won! $("p#player"+player.id). css("background", "LightGreen"); // Snap Made! snapMade = "YES"; } else { // Images do not match! // alert("NO SNAP!"); // Player loses 1 point player.score--; // Update player score $("span#score"+player.id).html(player. score); // Highlight player lost a point $("p#player"+player.id). css("background", "DeepPink"); } } // Has a player won? function isTheWinner(player) { // If player reaches a score of 5 points they win!! if(player.score == 2) { $("p").hide(); $("h1").html("PLAYER " + player. id + " WINS!"); $("h1").show(); // Tell play function there is a winner! return true } // Tell play function there is no winner return false } TO GET STARTED GO TO THESUNDAYTIMES.CO.UK/LEARNTOCODE
© Copyright 2024