├── License.md ├── README.md ├── css └── style.css ├── images ├── Gem Blue.png ├── Gem Green.png ├── Gem Orange.png ├── Heart.png ├── Key.png ├── Rock.png ├── Selector.png ├── Star.png ├── char-boy.png ├── char-cat-girl.png ├── char-horn-girl.png ├── char-pink-girl.png ├── char-princess-girl.png ├── enemy-bug.png ├── grass-block.png ├── stone-block.png └── water-block.png ├── index.html └── js ├── app.js ├── engine.js └── resources.js /License.md: -------------------------------------------------------------------------------- 1 | 2 | Copyright © 2012 - 2020, Udacity, Inc. 3 | 4 | Udacity hereby grants you a license in and to the Educational Content, including but not limited to homework assignments, programming assignments, code samples, and other educational materials and tools (as further described in the Udacity Terms of Use), subject to, as modified herein, the terms and conditions of the Creative Commons Attribution-NonCommercial- NoDerivs 3.0 License located at http://creativecommons.org/licenses/by-nc-nd/4.0 and successor locations for such license (the "CC License") provided that, in each case, the Educational Content is specifically marked as being subject to the CC License. 5 | 6 | Udacity expressly defines the following as falling outside the definition of "non-commercial": 7 | (a) the sale or rental of (i) any part of the Educational Content, (ii) any derivative works based at least in part on the Educational Content, or (iii) any collective work that includes any part of the Educational Content; 8 | (b) the sale of access or a link to any part of the Educational Content without first obtaining informed consent from the buyer (that the buyer is aware that the Educational Content, or such part thereof, is available at the Website free of charge); 9 | (c) providing training, support, or editorial services that use or reference the Educational Content in exchange for a fee; 10 | (d) the sale of advertisements, sponsorships, or promotions placed on the Educational Content, or any part thereof, or the sale of advertisements, sponsorships, or promotions on any website or blog containing any part of the Educational Material, including without limitation any "pop-up advertisements"; 11 | (e) the use of Educational Content by a college, university, school, or other educational institution for instruction where tuition is charged; and 12 | (f) the use of Educational Content by a for-profit corporation or non-profit entity for internal professional development or training. 13 | 14 | 15 | 16 | THE SERVICES AND ONLINE COURSES (INCLUDING ANY CONTENT) ARE PROVIDED "AS IS" AND "AS AVAILABLE" WITH NO REPRESENTATIONS OR WARRANTIES OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. YOU ASSUME TOTAL RESPONSIBILITY AND THE ENTIRE RISK FOR YOUR USE OF THE SERVICES, ONLINE COURSES, AND CONTENT. WITHOUT LIMITING THE FOREGOING, WE DO NOT WARRANT THAT (A) THE SERVICES, WEBSITES, CONTENT, OR THE ONLINE COURSES WILL MEET YOUR REQUIREMENTS OR EXPECTATIONS OR ACHIEVE THE INTENDED PURPOSES, (B) THE WEBSITES OR THE ONLINE COURSES WILL NOT EXPERIENCE OUTAGES OR OTHERWISE BE UNINTERRUPTED, TIMELY, SECURE OR ERROR-FREE, (C) THE INFORMATION OR CONTENT OBTAINED THROUGH THE SERVICES, SUCH AS CHAT ROOM SERVICES, WILL BE ACCURATE, COMPLETE, CURRENT, ERROR- FREE, COMPLETELY SECURE OR RELIABLE, OR (D) THAT DEFECTS IN OR ON THE SERVICES OR CONTENT WILL BE CORRECTED. YOU ASSUME ALL RISK OF PERSONAL INJURY, INCLUDING DEATH AND DAMAGE TO PERSONAL PROPERTY, SUSTAINED FROM USE OF SERVICES. 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Classic Arcade Game Clone Project 2 | 3 | ## Table of Contents 4 | 5 | - [Instructions](#instructions) 6 | - [Contributing](#contributing) 7 | 8 | ## Instructions 9 | 10 | Use this [rubric](https://review.udacity.com/#!/rubrics/15/view) for self-checking your submission. 11 | 12 | Make sure the functions you write are **object-oriented** - either class functions (like `Player` and `Enemy`) or class prototype functions such as `Enemy.prototype.checkCollisions`. Also make sure that the keyword `this` is used appropriately within your class and class prototype functions to refer to the object the function is called upon. 13 | 14 | Your **README.md** file should be updated with instructions on both how to 1. Run and 2. Play your arcade game. 15 | 16 | For detailed instructions on how to get started, check out this [guide](https://docs.google.com/document/d/1v01aScPjSWCCWQLIpFqvg3-vXLH2e8_SZQKC8jNO0Dc/pub?embedded=true). 17 | 18 | ## Contributing 19 | 20 | This repository is the starter code for _all_ Udacity students. Therefore, we most likely will not accept pull requests. 21 | 22 | # Archival Note 23 | This repository is deprecated; therefore, we are going to archive it. However, learners will be able to fork it to their personal Github account but cannot submit PRs to this repository. If you have any issues or suggestions to make, feel free to: 24 | - Utilize the https://knowledge.udacity.com/ forum to seek help on content-specific issues. 25 | - Submit a support ticket along with the link to your forked repository if (learners are) blocked for other reasons. Here are the links for the [retail consumers](https://udacity.zendesk.com/hc/en-us/requests/new) and [enterprise learners](https://udacityenterprise.zendesk.com/hc/en-us/requests/new?ticket_form_id=360000279131). -------------------------------------------------------------------------------- /css/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | text-align: center; 3 | } 4 | -------------------------------------------------------------------------------- /images/Gem Blue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/udacity/frontend-nanodegree-arcade-game/838049dff7b3313d9d8e4347b11628433cafb45b/images/Gem Blue.png -------------------------------------------------------------------------------- /images/Gem Green.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/udacity/frontend-nanodegree-arcade-game/838049dff7b3313d9d8e4347b11628433cafb45b/images/Gem Green.png -------------------------------------------------------------------------------- /images/Gem Orange.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/udacity/frontend-nanodegree-arcade-game/838049dff7b3313d9d8e4347b11628433cafb45b/images/Gem Orange.png -------------------------------------------------------------------------------- /images/Heart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/udacity/frontend-nanodegree-arcade-game/838049dff7b3313d9d8e4347b11628433cafb45b/images/Heart.png -------------------------------------------------------------------------------- /images/Key.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/udacity/frontend-nanodegree-arcade-game/838049dff7b3313d9d8e4347b11628433cafb45b/images/Key.png -------------------------------------------------------------------------------- /images/Rock.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/udacity/frontend-nanodegree-arcade-game/838049dff7b3313d9d8e4347b11628433cafb45b/images/Rock.png -------------------------------------------------------------------------------- /images/Selector.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/udacity/frontend-nanodegree-arcade-game/838049dff7b3313d9d8e4347b11628433cafb45b/images/Selector.png -------------------------------------------------------------------------------- /images/Star.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/udacity/frontend-nanodegree-arcade-game/838049dff7b3313d9d8e4347b11628433cafb45b/images/Star.png -------------------------------------------------------------------------------- /images/char-boy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/udacity/frontend-nanodegree-arcade-game/838049dff7b3313d9d8e4347b11628433cafb45b/images/char-boy.png -------------------------------------------------------------------------------- /images/char-cat-girl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/udacity/frontend-nanodegree-arcade-game/838049dff7b3313d9d8e4347b11628433cafb45b/images/char-cat-girl.png -------------------------------------------------------------------------------- /images/char-horn-girl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/udacity/frontend-nanodegree-arcade-game/838049dff7b3313d9d8e4347b11628433cafb45b/images/char-horn-girl.png -------------------------------------------------------------------------------- /images/char-pink-girl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/udacity/frontend-nanodegree-arcade-game/838049dff7b3313d9d8e4347b11628433cafb45b/images/char-pink-girl.png -------------------------------------------------------------------------------- /images/char-princess-girl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/udacity/frontend-nanodegree-arcade-game/838049dff7b3313d9d8e4347b11628433cafb45b/images/char-princess-girl.png -------------------------------------------------------------------------------- /images/enemy-bug.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/udacity/frontend-nanodegree-arcade-game/838049dff7b3313d9d8e4347b11628433cafb45b/images/enemy-bug.png -------------------------------------------------------------------------------- /images/grass-block.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/udacity/frontend-nanodegree-arcade-game/838049dff7b3313d9d8e4347b11628433cafb45b/images/grass-block.png -------------------------------------------------------------------------------- /images/stone-block.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/udacity/frontend-nanodegree-arcade-game/838049dff7b3313d9d8e4347b11628433cafb45b/images/stone-block.png -------------------------------------------------------------------------------- /images/water-block.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/udacity/frontend-nanodegree-arcade-game/838049dff7b3313d9d8e4347b11628433cafb45b/images/water-block.png -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Effective JavaScript: Frogger 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /js/app.js: -------------------------------------------------------------------------------- 1 | // Enemies our player must avoid 2 | var Enemy = function() { 3 | // Variables applied to each of our instances go here, 4 | // we've provided one for you to get started 5 | 6 | // The image/sprite for our enemies, this uses 7 | // a helper we've provided to easily load images 8 | this.sprite = 'images/enemy-bug.png'; 9 | }; 10 | 11 | // Update the enemy's position, required method for game 12 | // Parameter: dt, a time delta between ticks 13 | Enemy.prototype.update = function(dt) { 14 | // You should multiply any movement by the dt parameter 15 | // which will ensure the game runs at the same speed for 16 | // all computers. 17 | }; 18 | 19 | // Draw the enemy on the screen, required method for game 20 | Enemy.prototype.render = function() { 21 | ctx.drawImage(Resources.get(this.sprite), this.x, this.y); 22 | }; 23 | 24 | // Now write your own player class 25 | // This class requires an update(), render() and 26 | // a handleInput() method. 27 | 28 | 29 | // Now instantiate your objects. 30 | // Place all enemy objects in an array called allEnemies 31 | // Place the player object in a variable called player 32 | 33 | 34 | 35 | // This listens for key presses and sends the keys to your 36 | // Player.handleInput() method. You don't need to modify this. 37 | document.addEventListener('keyup', function(e) { 38 | var allowedKeys = { 39 | 37: 'left', 40 | 38: 'up', 41 | 39: 'right', 42 | 40: 'down' 43 | }; 44 | 45 | player.handleInput(allowedKeys[e.keyCode]); 46 | }); 47 | -------------------------------------------------------------------------------- /js/engine.js: -------------------------------------------------------------------------------- 1 | /* Engine.js 2 | * This file provides the game loop functionality (update entities and render), 3 | * draws the initial game board on the screen, and then calls the update and 4 | * render methods on your player and enemy objects (defined in your app.js). 5 | * 6 | * A game engine works by drawing the entire game screen over and over, kind of 7 | * like a flipbook you may have created as a kid. When your player moves across 8 | * the screen, it may look like just that image/character is moving or being 9 | * drawn but that is not the case. What's really happening is the entire "scene" 10 | * is being drawn over and over, presenting the illusion of animation. 11 | * 12 | * This engine makes the canvas' context (ctx) object globally available to make 13 | * writing app.js a little simpler to work with. 14 | */ 15 | 16 | var Engine = (function(global) { 17 | /* Predefine the variables we'll be using within this scope, 18 | * create the canvas element, grab the 2D context for that canvas 19 | * set the canvas element's height/width and add it to the DOM. 20 | */ 21 | var doc = global.document, 22 | win = global.window, 23 | canvas = doc.createElement('canvas'), 24 | ctx = canvas.getContext('2d'), 25 | lastTime; 26 | 27 | canvas.width = 505; 28 | canvas.height = 606; 29 | doc.body.appendChild(canvas); 30 | 31 | /* This function serves as the kickoff point for the game loop itself 32 | * and handles properly calling the update and render methods. 33 | */ 34 | function main() { 35 | /* Get our time delta information which is required if your game 36 | * requires smooth animation. Because everyone's computer processes 37 | * instructions at different speeds we need a constant value that 38 | * would be the same for everyone (regardless of how fast their 39 | * computer is) - hurray time! 40 | */ 41 | var now = Date.now(), 42 | dt = (now - lastTime) / 1000.0; 43 | 44 | /* Call our update/render functions, pass along the time delta to 45 | * our update function since it may be used for smooth animation. 46 | */ 47 | update(dt); 48 | render(); 49 | 50 | /* Set our lastTime variable which is used to determine the time delta 51 | * for the next time this function is called. 52 | */ 53 | lastTime = now; 54 | 55 | /* Use the browser's requestAnimationFrame function to call this 56 | * function again as soon as the browser is able to draw another frame. 57 | */ 58 | win.requestAnimationFrame(main); 59 | } 60 | 61 | /* This function does some initial setup that should only occur once, 62 | * particularly setting the lastTime variable that is required for the 63 | * game loop. 64 | */ 65 | function init() { 66 | reset(); 67 | lastTime = Date.now(); 68 | main(); 69 | } 70 | 71 | /* This function is called by main (our game loop) and itself calls all 72 | * of the functions which may need to update entity's data. Based on how 73 | * you implement your collision detection (when two entities occupy the 74 | * same space, for instance when your character should die), you may find 75 | * the need to add an additional function call here. For now, we've left 76 | * it commented out - you may or may not want to implement this 77 | * functionality this way (you could just implement collision detection 78 | * on the entities themselves within your app.js file). 79 | */ 80 | function update(dt) { 81 | updateEntities(dt); 82 | // checkCollisions(); 83 | } 84 | 85 | /* This is called by the update function and loops through all of the 86 | * objects within your allEnemies array as defined in app.js and calls 87 | * their update() methods. It will then call the update function for your 88 | * player object. These update methods should focus purely on updating 89 | * the data/properties related to the object. Do your drawing in your 90 | * render methods. 91 | */ 92 | function updateEntities(dt) { 93 | allEnemies.forEach(function(enemy) { 94 | enemy.update(dt); 95 | }); 96 | player.update(); 97 | } 98 | 99 | /* This function initially draws the "game level", it will then call 100 | * the renderEntities function. Remember, this function is called every 101 | * game tick (or loop of the game engine) because that's how games work - 102 | * they are flipbooks creating the illusion of animation but in reality 103 | * they are just drawing the entire screen over and over. 104 | */ 105 | function render() { 106 | /* This array holds the relative URL to the image used 107 | * for that particular row of the game level. 108 | */ 109 | var rowImages = [ 110 | 'images/water-block.png', // Top row is water 111 | 'images/stone-block.png', // Row 1 of 3 of stone 112 | 'images/stone-block.png', // Row 2 of 3 of stone 113 | 'images/stone-block.png', // Row 3 of 3 of stone 114 | 'images/grass-block.png', // Row 1 of 2 of grass 115 | 'images/grass-block.png' // Row 2 of 2 of grass 116 | ], 117 | numRows = 6, 118 | numCols = 5, 119 | row, col; 120 | 121 | // Before drawing, clear existing canvas 122 | ctx.clearRect(0,0,canvas.width,canvas.height); 123 | 124 | /* Loop through the number of rows and columns we've defined above 125 | * and, using the rowImages array, draw the correct image for that 126 | * portion of the "grid" 127 | */ 128 | for (row = 0; row < numRows; row++) { 129 | for (col = 0; col < numCols; col++) { 130 | /* The drawImage function of the canvas' context element 131 | * requires 3 parameters: the image to draw, the x coordinate 132 | * to start drawing and the y coordinate to start drawing. 133 | * We're using our Resources helpers to refer to our images 134 | * so that we get the benefits of caching these images, since 135 | * we're using them over and over. 136 | */ 137 | ctx.drawImage(Resources.get(rowImages[row]), col * 101, row * 83); 138 | } 139 | } 140 | 141 | renderEntities(); 142 | } 143 | 144 | /* This function is called by the render function and is called on each game 145 | * tick. Its purpose is to then call the render functions you have defined 146 | * on your enemy and player entities within app.js 147 | */ 148 | function renderEntities() { 149 | /* Loop through all of the objects within the allEnemies array and call 150 | * the render function you have defined. 151 | */ 152 | allEnemies.forEach(function(enemy) { 153 | enemy.render(); 154 | }); 155 | 156 | player.render(); 157 | } 158 | 159 | /* This function does nothing but it could have been a good place to 160 | * handle game reset states - maybe a new game menu or a game over screen 161 | * those sorts of things. It's only called once by the init() method. 162 | */ 163 | function reset() { 164 | // noop 165 | } 166 | 167 | /* Go ahead and load all of the images we know we're going to need to 168 | * draw our game level. Then set init as the callback method, so that when 169 | * all of these images are properly loaded our game will start. 170 | */ 171 | Resources.load([ 172 | 'images/stone-block.png', 173 | 'images/water-block.png', 174 | 'images/grass-block.png', 175 | 'images/enemy-bug.png', 176 | 'images/char-boy.png' 177 | ]); 178 | Resources.onReady(init); 179 | 180 | /* Assign the canvas' context object to the global variable (the window 181 | * object when run in a browser) so that developers can use it more easily 182 | * from within their app.js files. 183 | */ 184 | global.ctx = ctx; 185 | })(this); 186 | -------------------------------------------------------------------------------- /js/resources.js: -------------------------------------------------------------------------------- 1 | /* Resources.js 2 | * This is simply an image loading utility. It eases the process of loading 3 | * image files so that they can be used within your game. It also includes 4 | * a simple "caching" layer so it will reuse cached images if you attempt 5 | * to load the same image multiple times. 6 | */ 7 | (function() { 8 | var resourceCache = {}; 9 | var readyCallbacks = []; 10 | 11 | /* This is the publicly accessible image loading function. It accepts 12 | * an array of strings pointing to image files or a string for a single 13 | * image. It will then call our private image loading function accordingly. 14 | */ 15 | function load(urlOrArr) { 16 | if(urlOrArr instanceof Array) { 17 | /* If the developer passed in an array of images 18 | * loop through each value and call our image 19 | * loader on that image file 20 | */ 21 | urlOrArr.forEach(function(url) { 22 | _load(url); 23 | }); 24 | } else { 25 | /* The developer did not pass an array to this function, 26 | * assume the value is a string and call our image loader 27 | * directly. 28 | */ 29 | _load(urlOrArr); 30 | } 31 | } 32 | 33 | /* This is our private image loader function, it is 34 | * called by the public image loader function. 35 | */ 36 | function _load(url) { 37 | if(resourceCache[url]) { 38 | /* If this URL has been previously loaded it will exist within 39 | * our resourceCache array. Just return that image rather than 40 | * re-loading the image. 41 | */ 42 | return resourceCache[url]; 43 | } else { 44 | /* This URL has not been previously loaded and is not present 45 | * within our cache; we'll need to load this image. 46 | */ 47 | var img = new Image(); 48 | img.onload = function() { 49 | /* Once our image has properly loaded, add it to our cache 50 | * so that we can simply return this image if the developer 51 | * attempts to load this file in the future. 52 | */ 53 | resourceCache[url] = img; 54 | 55 | /* Once the image is actually loaded and properly cached, 56 | * call all of the onReady() callbacks we have defined. 57 | */ 58 | if(isReady()) { 59 | readyCallbacks.forEach(function(func) { func(); }); 60 | } 61 | }; 62 | 63 | /* Set the initial cache value to false, this will change when 64 | * the image's onload event handler is called. Finally, point 65 | * the image's src attribute to the passed in URL. 66 | */ 67 | resourceCache[url] = false; 68 | img.src = url; 69 | } 70 | } 71 | 72 | /* This is used by developers to grab references to images they know 73 | * have been previously loaded. If an image is cached, this functions 74 | * the same as calling load() on that URL. 75 | */ 76 | function get(url) { 77 | return resourceCache[url]; 78 | } 79 | 80 | /* This function determines if all of the images that have been requested 81 | * for loading have in fact been properly loaded. 82 | */ 83 | function isReady() { 84 | var ready = true; 85 | for(var k in resourceCache) { 86 | if(resourceCache.hasOwnProperty(k) && 87 | !resourceCache[k]) { 88 | ready = false; 89 | } 90 | } 91 | return ready; 92 | } 93 | 94 | /* This function will add a function to the callback stack that is called 95 | * when all requested images are properly loaded. 96 | */ 97 | function onReady(func) { 98 | readyCallbacks.push(func); 99 | } 100 | 101 | /* This object defines the publicly accessible functions available to 102 | * developers by creating a global Resources object. 103 | */ 104 | window.Resources = { 105 | load: load, 106 | get: get, 107 | onReady: onReady, 108 | isReady: isReady 109 | }; 110 | })(); 111 | --------------------------------------------------------------------------------