<repo_name>pdarkness/Doodle-Jump-clone<file_sep>/app/scripts/coin.js
/**
 * Created with JetBrains WebStorm.
 * User: knuturm
 * Date: 10.9.2013
 * Time: 14:29
 * To change this template use File | Settings | File Templates.
 */
define(function(rect) {

    var Coin = function(rect) {
        this.rect = rect;
        this.rect.right = rect.x + rect.width;

        this.el = $('<div class="coin">');
        this.el.css({
            left: rect.x,
            top: rect.y,
            width: rect.width,
            height: rect.height
        });
    };

    Coin.prototype.onFrame = function() {}

    return Coin;
});
<file_sep>/app/scripts/game.js
/*global define, $ */

define(['player', 'platform', 'coin', 'enemy', 'controls'], function(Player, Platform, Coin, Enemy, controls) {

    var VIEWPORT_PADDING = 220;

    /**
     * Main game class.
     * @param {Element} el DOM element containig the game.
     * @constructor
     */
    var Game = function(el) {
        this.el = el;
        this.player = new Player(this.el.find('.player'), this);
        this.entities = [];
        this.platformsEl = el.find('.platforms');
        this.entitiesEl = el.find('.entities');
        this.coinsEl = el.find('.coins');
        this.worldEl = el.find('.world');
        this.gameOvEl = el.find('.gameOver');
        this.isPlaying = false;
        this.gameScore = 0;
        this.level = 1;
        this.bonus = 0;

        this.worldChunkSize = 1000;
        this.worldFromY = 0;
        this.worldToY = 1000;
        this.nextCreatePlatformsY = 800;

        this.sound = new Howl({
            urls: ['/sounds/jump.mp3', '/sounds/jump.ogg']
        })

        // Cache a bound onFrame since we need it each frame.
        this.onFrame = this.onFrame.bind(this);
    };

    Game.prototype.freezeGame = function() {
        this.isPlaying = false;
    };

    Game.prototype.unFreezeGame = function() {
        if (!this.isPlaying) {
            this.isPlaying = true;

            // Restart the onFrame loop
            this.lastFrame = +new Date() / 1000;
            requestAnimFrame(this.onFrame);
        }
    };


    Game.prototype.createWorld = function() {
        // Ground
        for(i=0;i<10-this.level;i++){
            //console.log(this.level(this.level));
            this.addPlatform(new Platform({
                x: 0,
                y: -i*100,
                width: 400,
                height: 10
            }));
        }

    };

    Game.prototype.addPlatform = function(platform) {
        this.entities.push(platform);
        this.platformsEl.append(platform.el);
    };

    Game.prototype.addCoin = function(coin) {
        this.entities.push(coin);
        this.coinsEl.append(coin.el);
    };

    Game.prototype.addEnemy = function(enemy) {
        this.entities.push(enemy);
        this.entitiesEl.append(enemy.el);
    };

    Game.prototype.gameOver = function() {
        this.freezeGame();

        if (this.gameScore === 0){
            alert('Game Over! Score: ' + Math.floor(this.player.maxScore));
        }
        else{
            alert('Game Over! Score: ' + (this.gameScore+ Math.floor(this.player.maxScore)));
        }
        this.worldChunkSize = 1000;
        this.worldFromY = 0;
        this.worldToY = 1000;
        this.nextCreatePlatformsY = 800;

        var game = this;
        setTimeout(function() {
            game.start();
        }, 0);
    };

    /**
     * Runs every frame. Calculates a delta and allows each game entity to update itself.
     */
    Game.prototype.onFrame = function() {
        if (!this.isPlaying) {
            return;
        }
        //if(this.nextCreatePlatformsY < this.player.pos.y)
        if(Math.abs(this.player.pos.y)>this.nextCreatePlatformsY){
            this.nextCreatePlatformsY += this.worldChunkSize;
            this.worldFromY += this.worldChunkSize;
            this.worldToY += this.worldChunkSize;

            for(i=0;i<20;i++){
            this.addPlatform(new Platform({
                x: Math.floor(Math.random() * (380+ (i+1)))%380,
                y: -Math.floor(Math.random() * (this.worldToY - this.worldFromY + 1) + this.worldFromY),
                width: 80,
                height: 10
            }));

            }
            var mod = (Math.random()*1000)%400;
            var modY = (-Math.floor(Math.random() * (this.worldToY - this.worldFromY + 1) + this.worldFromY));
            this.addEnemy(new Enemy({
                start: {x: mod, y: modY},
                end: {x: mod-150, y: modY}
            }));
            this.addCoin(new Coin({
                x: Math.floor(Math.random() * (380+ (i+1)))%380,
                y: modY
            }));
        }

        var now = +new Date() / 1000,
            delta = now - this.lastFrame;
        this.lastFrame = now;

        controls.onFrame(delta);
        this.player.onFrame(delta);

        for (var i = 0, e; e = this.entities[i]; i++) {
            e.onFrame(delta);

            if (e.dead) {
                this.entities.splice(i--, 1);
            }
        }



        this.updateViewport();

        // Request next frame.
        requestAnimFrame(this.onFrame);
    };

    Game.prototype.updateViewport = function() {
        var minY = this.viewport.y + VIEWPORT_PADDING;
        var maxY = this.viewport.y + this.viewport.height + VIEWPORT_PADDING;

        var playerY = this.player.pos.y;
        var playerX = this.player.pos.x;

        if (playerY < minY) {
            this.viewport.y = playerY - VIEWPORT_PADDING;
        } else if (playerY > maxY) {
            this.viewport.y = playerY - this.viewport.height + VIEWPORT_PADDING;
        }

        this.worldEl.css({
            left: -this.viewport.x,
            top: -this.viewport.y
        });
    };

    /**
     * Starts the game.
     */
    Game.prototype.start = function() {
        // Cleanup last game.
        this.entities.forEach(function(e) { e.el.remove(); });
        this.entities = [];

        // Set the stage.
        this.createWorld();
        this.player.reset();
        this.viewport = {x: 0, y: 0, width: 400, height: 550};

        // Then start.
        this.unFreezeGame();
    };


    Game.prototype.forEachCoin = function(handler) {
        for (var i = 0, e; e = this.entities[i]; i++) {
            if (e instanceof Coin) {
                handler(e);
            }
        }
    };

    Game.prototype.forEachPlatform = function(handler) {
        for (var i = 0, e; e = this.entities[i]; i++) {
            if (e instanceof Platform) {
                handler(e);
            }
        }
    };

    Game.prototype.forEachEnemy = function(handler) {
        for (var i = 0, e; e = this.entities[i]; i++) {
            if (e instanceof Enemy) {
                handler(e);
            }
        }
    };

    /**
     * Cross browser RequestAnimationFrame
     */
    var requestAnimFrame = (function() {
        return window.requestAnimationFrame ||
            window.webkitRequestAnimationFrame ||
            window.mozRequestAnimationFrame ||
            window.oRequestAnimationFrame ||
            window.msRequestAnimationFrame ||
            function(/* function */ callback) {
                window.setTimeout(callback, 1000 / 60);
            };
    })();

    return Game;
});<file_sep>/README.md
Doodle-Jump-clone
=================
My first html5 game =)<br>
clone repo<br>
npm install<br>
grunt server<br>
<br>
and play =)
<file_sep>/app/scripts/player.js
/*global define */

define(['controls'], function(controls) {

    var PLAYER_SPEED = 350;
    var JUMP_VELOCITY = 1450;
    var GRAVITY = 4000;
    var PLAYER_HALF_WIDTH = 14;
    var PLAYER_RADIUS = 30;



    var Player = function(el, game) {
        this.game = game;
        this.el = el;

        controls.on('super', this.onSuper.bind(this));
    };

    Player.prototype.reset = function() {
        this.pos = { x: 100, y: 0 };
        this.vel = { x: 0, y: 0 };
        this.playerScore = 0;
        this.maxScore = 0;
    }

    Player.prototype.onFrame = function(delta) {
        // Player input
        this.vel.x = controls.inputVec.x * PLAYER_SPEED;

        // Jumping
        if ( this.vel.y === 0) {
            this.vel.y = -JUMP_VELOCITY;
            if(controls.keys.space)
                this.vel.y -= 300;
            if(controls.keys.down)
                this.vel.y += 500;
            this.game.sound.play();
        }
        //console.log(this.pos.y);
        if (this.pos.x < 0)
            this.pos.x = 400;

        if (this.pos.x > 400)
            this.pos.x = 0;

        //console.log(this.pos.y);
        //console.log(HELL_Y - this.maxScore);

        // Gravity
        this.vel.y += GRAVITY * delta;

        var oldY = this.pos.y;
        this.pos.x += delta * this.vel.x;
        this.pos.y += delta * this.vel.y;



        this.playerScore = Math.abs(oldY);
        this.checkCoins(oldY);
        if (this.playerScore > this.maxScore)
            this.maxScore = this.playerScore;

        // Collision detection
        this.checkPlatforms(oldY);

        this.checkEnemies();
        this.checkGameOver();

        // Update UI
        this.el.css('transform', 'translate3d(' + this.pos.x + 'px,' + this.pos.y + 'px,0)');
        this.el.toggleClass('left', this.vel.x < 0);
        this.el.toggleClass('right', this.vel.x > 0);
        this.el.toggleClass('jumping', this.vel.y < 0);
    };

    Player.prototype.onSuper = function () {
        this.vel.y -= 300;
    }

    Player.prototype.checkGameOver = function() {
        /*if (this.pos.y > HELL_Y - Math.floor(this.maxScore)) {
            this.game.gameOver();
        }*/

        if (this.game.viewport.y != 0 && (this.pos.y- this.game.viewport.y)>this.game.viewport.height){
            this.game.gameOver();
        }
        /*if (this.pos.y < 0) {
            this.game.levelOver();
        }*/
    };

    Player.prototype.checkPlatforms = function(oldY) {
        var that = this;

        this.game.forEachPlatform(function(p) {
            // Are we crossing Y.
            if (p.rect.y >= oldY && p.rect.y < that.pos.y) {

                // Are inside X bounds.
                if (that.pos.x + PLAYER_HALF_WIDTH >= p.rect.x && that.pos.x - PLAYER_HALF_WIDTH <= p.rect.right) {
                    // COLLISION. Let's stop gravity.
                    that.pos.y = p.rect.y;
                    that.vel.y = 0;
                }
            }
        });
    };

    Player.prototype.checkCoins = function(oldY) {
        var that = this;
        this.game.forEachCoin(function(p) {
            // Are we crossing Y.
            if (p.rect.y >= oldY && p.rect.y < that.pos.y) {

                // Are inside X bounds.
                if (that.pos.x + PLAYER_HALF_WIDTH >= p.rect.x && that.pos.x - PLAYER_HALF_WIDTH <= p.rect.right) {
                    that.playerScore += 5000;
                }
            }
        });
    };

    Player.prototype.checkEnemies = function() {
        var centerX = this.pos.x;
        var centerY = this.pos.y - 40;
        var that = this;
        this.game.forEachEnemy(function(enemy) {
            // Distance squared
            var distanceX = enemy.pos.x - centerX;
            var distanceY = enemy.pos.y - centerY;

            // Minimum distance squared
            var distanceSq = distanceX * distanceX + distanceY * distanceY;
            var minDistanceSq = (enemy.radius + PLAYER_RADIUS) * (enemy.radius + PLAYER_RADIUS);

            // What up?
            if (distanceSq < minDistanceSq) {
                that.game.gameOver();
            }
        });
    };

    return Player;
});
