How to Make Spider Man Master Game using JS

piyush608 Spider Man

Creating a shopping cart using HTML, CSS, and JavaScript involves setting up a user interface for displaying products, adding products to the cart, viewing the cart, and removing products from the cart. Here’s a step-by-step guide to building a basic shopping cart:

HTML

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="description"
                content="A Simple Spiderman Game in HTML5, CSS3 and Javascript" />
        <meta name="author" content="Chandula Janith (RedEdge967)" />
    <title>Spider-Man Game | A spiderman game to fight with more Villains of Spider-Man</title>
    <link rel="shortcut icon" href="images/spider-head.png" />
</head>
<style type="text/css">
    html,
    body {
        height: 100%;
        width: 100%;
        margin: 0;
        font-size: 0;
        background: #000;
    }

    .canvas-wrapper {
        float: left;
        position: absolute;
        top: 50%;
        left: 50%;

        -webkit-transform: translate(-50%, -50%);
        -moz-transform: translate(-50%, -50%);
        -ms-transform: translate(-50%, -50%);
        -o-transform: translate(-50%, -50%);
        transform: translate(-50%, -50%);
    }

    .key {
        height: 30px;
        min-width: 20px;
        line-height: 30px;
        text-align: center;
        border: 1px solid #ccc;
        border-bottom: 3px solid #bbb;
        background: white;
        display: inline-block;
        padding: 0 5px;
        border-radius: 5px;
        box-shadow: inset 0 -1px 0 #ccc;
        color: #333;
        font-weight: bold;
    }

    .key.spacebar {
        padding: 0 40px;
    }

    .keyboard {
        margin: 5px 0;
        font-size: 15px;
        font-family: Helvetica;
        color: white;
    }

    .action {
        margin-right: 15px;
    }

    .link {
        width: 100%;
        text-align: center;
        font-size: 20px;
        color: #ccc;
        font-family: SpidermanGamePixelFont, Helvetica, Arial;
        margin-top: 20px;
    }
</style>
<body>
    <div class="canvas-wrapper">
        <div class="keyboard">
            <div class="key spacebar">Spacebar</div>
            <span class="action">- Shoot</span>

            <div class="key">←</div>
            <div class="key">→</div>
            <span class="action">- Left/Right</span>

            <div class="key">↑</div>
            <span class="action">- Jump</span>

            <div class="key">Esc</div>
            <span class="action">- Pause</span>
        </div>
        <canvas id="canvas"></canvas>
        <div class="link">
            View Source on 
            <a href="https://github.com/RedEdge967/mini-spidey" target="_blank">Github</a>
        </div>
    </div>
</body>
<script type="text/javascript" src="spiderman-game.js"></script>
<script type="text/javascript">

var game = new SpidermanGame({
    canvas: "#canvas"
});
game.load();

</script>
</html>

 

CSS (styles.css)

@font-face {
    font-family: SpidermanGamePixelFont;
    src: url(../fonts/pixel.otf);
}

.spiderman-game-menu-container,
.spiderman-game-menu-container * {
    -webkit-box-sizing: border-box;
    -moz-box-sizing: border-box;
    box-sizing: border-box;

    -webkit-user-select: none;
    -khtml-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    -o-user-select: none;
    user-select: none;
    cursor: default;
}

.spiderman-game-menu-container {
    position: absolute;
    display: none;
    height: auto;

    -webkit-transform: translate(-50%, -50%);
    -moz-transform: translate(-50%, -50%);
    -ms-transform: translate(-50%, -50%);
    -o-transform: translate(-50%, -50%);
    transform: translate(-50%, -50%);
}

.spiderman-game-menu-title {
    text-align: center;
    font-size: 20px;
    line-height: 60px;
    font-family: SpidermanGamePixelFont;
    color: white;
    display: block;
    padding: 5px;
}

.spiderman-game-menu-button {
    line-height: 30px;
    font-size: 15px;
    text-align: center;
    font-family: SpidermanGamePixelFont;
    color: white;
}

.spiderman-game-menu-button:hover {
    color: red;
}

.spiderman-game-menu-button:active {
    color: rgb(200, 0, 0);
}

 

JavaScript (script.js)

(function(window, document) {

// change this to relative path (relative to script) or to absolute path
// where the audio, fonts and images folders are located
// (include a slash at the end)
var RESOURCES_FOLDER_PATH = "";

var requestAnimationFrame = (function() {
    if (window.requestAnimationFrame) return window.requestAnimationFrame;
    if (window.oRequestAnimationFrame) return window.oRequestAnimationFrame;
    if (window.msRequestAnimationFrame) return window.msRequestAnimationFrame;
    if (window.mozRequestAnimationFrame) return window.mozRequestAnimationFrame;
    return function(callback) {
        setTimeout(callback, 1000 / 60);
    }
})();

window.requestAnimFrame = requestAnimationFrame;

var link = document.createElement("link");
link.setAttribute("rel", "stylesheet");
link.setAttribute("href", RESOURCES_FOLDER_PATH + "css/spiderman-game.css");
document.head.appendChild(link);


var RESOURCES = {
    "JUMP"               : "images/jump.png",
    "RUNNING_CHANGE_STEP": "images/running-change-step.png",
    "RUNNING_LEFT_STEP"  : "images/running-left-step.png",
    "RUNNING_RIGHT_STEP" : "images/running-right-step.png",
    "SHOOT_CHANGE_STEP"  : "images/shoot-change-step.png",
    "SHOOT_JUMP"         : "images/shoot-jump.png",
    "SHOOT_LEFT-STEP"    : "images/shoot-left-step.png",
    "SHOOT_RIGHT-STEP"   : "images/shoot-right-step.png",
    "SHOOT"              : "images/shoot.png",
    "SLIDE"              : "images/slide.png",
    "STANDING"           : "images/standing.png",
    "WEB_PROJECTILE"     : "images/web.png",
    "BACKGROUND"         : "images/background.jpg",
    "ROOF"               : "images/wall.jpg",
    "BUILDING"           : "images/building.png",
    "SPIDER_HEAD"        : "images/spider-head.png",
    "HEART"              : "images/heart.png",
    "VENOM"              : "images/venom.png",
    "THUG"               : "images/thug.png",
    "KNIFE"              : "images/knife.png",
};

var AUDIO_RESOURCES = {
    "AMAZING_SPIDER_MAN_2" : new Audio(RESOURCES_FOLDER_PATH + "audio/amazing-spider-man-2.mp3"),
    "FRIENDLY_SPIDERMAN"   : new Audio(RESOURCES_FOLDER_PATH + "audio/60-theme-song.mp3"),
    "MOVIE_THEME"          : new Audio(RESOURCES_FOLDER_PATH + "audio/old-theme.mp3"),
    "ANIMATED_SERIES"      : new Audio(RESOURCES_FOLDER_PATH + "audio/animated-series-theme.mp3"),
    "SHOOT"                : new Audio(RESOURCES_FOLDER_PATH + "audio/shooting-web.mp3"),
};

var AUDIO_LOOP = [
    "AMAZING_SPIDER_MAN_2",
    "FRIENDLY_SPIDERMAN",
    "MOVIE_THEME",
    "ANIMATED_SERIES",
];

var KEY = {
    ARROW_LEFT: 37,
    ARROW_UP: 38,
    ARROW_RIGHT: 39,
    ARROW_DOWN: 40,
    SPACEBAR: 32,
    A: 65,
    S: 87,
    D: 68,
    W: 87,
    ESC: 27,
};

var DIRECTION = {
    RIGHT: 1,
    LEFT: -1,
}

function SpidermanGame(opts) {
    var options = {
        canvas: "canvas",
        score: 0,
        muted: false,
        soundEffects: true,
    };

    opts = opts || {};

    for (var option in options) {
        if (opts.hasOwnProperty(option)) {
            options[option] = opts[option];
        }

        this[option] = options[option];
    }

    // how many frames have passed
    this.frame = 0;
    this.resources = {};

    this.cameraX = 0;
    this.score = this.score || 0;

    this.scene = {
        spiderman: null,
        projectiles: [],
        roofs: [],
        enemies: [],
    }; // object that contains information about the next scene
}

SpidermanGame.prototype.paused             = false;
SpidermanGame.prototype.initialized        = false;
SpidermanGame.prototype.soundEffects       = true;
SpidermanGame.prototype.escapeKey          = false;
SpidermanGame.prototype.muted              = false;
SpidermanGame.prototype.slowmotion         = false;

SpidermanGame.prototype.load = function() {
    if (this.initialized) return false;

    var self = this;

    this.canvas = document.querySelector(this.canvas);
    if (!this.canvas) {
        this.canvas = document.createElement("canvas");
        document.body.appendChild(this.canvas);
    }
    this.ctx = this.canvas.getContext("2d");
    this.canvas.height = 400;
    this.canvas.width = 711;

    var menu = document.createElement("div");
    menu.innerHTML = 
    '<div class="spiderman-game-menu-container">' +
        '<div class="spiderman-game-menu-title">PAUSED</div>' +
        '<div class="spiderman-game-menu-button spiderman-game-menu-button-resume">RESUME</div>' +
        '<div class="spiderman-game-menu-button spiderman-game-menu-button-mute-sounds">MUTE SOUNDS</div>' +
        '<div class="spiderman-game-menu-button spiderman-game-menu-button-mute-music">MUTE MUSIC</div>' +
        '<div class="spiderman-game-menu-button spiderman-game-menu-button-mute-slowmotion">TOGGLE SLOWMOTION</div>' +
    '</div>';
    menu = menu.firstChild;
    menu.style.display = "none";
    menu.querySelector(".spiderman-game-menu-button-resume").onclick = function() {
        self.unpause();
    }

    menu.querySelector(".spiderman-game-menu-button-mute-sounds").onclick = function() {
        if (self.soundEffects) {
            self.soundEffects = false;
            this.innerHTML = "UNMUTE SOUNDS";
        } else {
            self.soundEffects = true;
            this.innerHTML = "MUTE SOUNDS";
        }
    }

    menu.querySelector(".spiderman-game-menu-button-mute-music").onclick = function() {
        if (self.muted) {
            self.unmute();
            this.innerHTML = "MUTE MUSIC";
        } else {
            self.mute();
            this.innerHTML = "UNMUTE MUSIC";
        }
    }

    menu.querySelector(".spiderman-game-menu-button-mute-slowmotion").onclick = function() {
        if (self.slowmotion) {
            self.setSlowmotion(false);
        } else {
            self.setSlowmotion(true);
        }
    }
    document.body.appendChild(menu);
    this.pauseMenu = menu;

    var gameoverMenu = document.createElement("div");
    gameoverMenu.innerHTML = 
    '<div class="spiderman-game-menu-container">' +
        '<div class="spiderman-game-menu-title">GAME OVER</div>' +
        '<div class="spiderman-game-menu-title">FINAL SCORE: <span class="spiderman-game-score">0</span></div>' +
        '<div class="spiderman-game-menu-button spiderman-game-menu-button-restart">RESTART</div>' +
    '</div>';
    gameoverMenu = gameoverMenu.firstChild;

    gameoverMenu.querySelector(".spiderman-game-menu-button-restart").onclick = function() {
        self.restart();
    }
    document.body.appendChild(gameoverMenu);
    this.gameoverMenu = gameoverMenu;

    var spiderman = new SpiderMan(this);
    this.spiderman = spiderman;

    document.addEventListener("keydown", function(e) {
        var keyCode = e.keyCode || e.which;

        // fire this on the FIRST keydown callback
        if (keyCode == KEY.ESC && !self.escapeKey) {
            self.escapeKey = true;
            if (self.paused) {
                self.unpause();
            } else {
                self.pause();
            }
        }

        self.spiderman.keydown(e.keyCode || e.which);
    });

    document.addEventListener("keyup", function(e) {
        var keyCode = e.keyCode || e.which;
        if (keyCode == KEY.ESC) {
            self.escapeKey = false;
        }

        self.spiderman.keyup(keyCode);
    });

    window.addEventListener("resize", function() {
        // resizing might change the canvas position, re position the menu if it is visible
        if (self.paused) {
            self.showPauseMenu();
        }
        if (self.gameIsOver) {
            self.showGameoverMenu();
        }
    });

    for (var i = 0; i < AUDIO_LOOP.length; i++) {
        var soundName = AUDIO_LOOP[i];
        var sound = AUDIO_RESOURCES[soundName];
        sound.setAttribute("data-name", soundName);
        sound.ontimeupdate = function() {
            if (this.currentTime >= this.duration) {
                var current = AUDIO_LOOP.indexOf(this.getAttribute("data-name"));
                var next = (current + 1) % (AUDIO_LOOP.length);
                
                self.playSound(AUDIO_LOOP[next], false, 0);
            }
        }
    }

    // to show that canvas is here, but is being loaded
    this.canvas.style.backgroundColor = "black";
    this.ctx.font = "30px Helvetica";
    this.ctx.textAlign = "center";
    this.ctx.fillStyle = "white";
    this.ctx.fillText("Loading...", this.canvas.width / 2, this.canvas.height / 2);

    return new Promise(function(resolve, reject) {
        var reourcesArray = [];

        for (var resource in RESOURCES) {
            reourcesArray.push({
                name: resource,
                source: RESOURCES_FOLDER_PATH + RESOURCES[resource],
            });
        }

        var index = 0;

        function loadNext() {
            if (!reourcesArray[index]) {
                var roof = new Roof(self, 0);

                self.scene.spiderman = spiderman;
                self.scene.roofs = [roof];
                self.update();
                self.playSound(AUDIO_LOOP[0], false, 0);

                // if game was muted in initial options
                if (self.muted) self.mute();

                return resolve();
            }

            var resource = reourcesArray[index];
            var img = new Image();

            img.onload = function() {
                index++;
                self.resources[resource.name] = img;
                loadNext();
            }
            img.src = resource.source;
        }

        loadNext();
    });
}

SpidermanGame.prototype.setSlowmotion = function(slowmo) {
    if (slowmo) {
        this.slowmotion = true;

        window.requestAnimFrame = function(callback) {
            setTimeout(callback, 1000 / 10);
        }

        for (var audio in AUDIO_RESOURCES) {
            AUDIO_RESOURCES
.playbackRate = 0.5;
        }
    } else {
        this.slowmotion = false;

        window.requestAnimFrame = requestAnimationFrame;

        for (var audio in AUDIO_RESOURCES) {
            AUDIO_RESOURCES
.playbackRate = 1;
        }
    }
}

SpidermanGame.prototype.mute = function() {
    this.muted = true;

    for (var audio in AUDIO_RESOURCES) {
        AUDIO_RESOURCES
.volume = 0;
    }
}

SpidermanGame.prototype.unmute = function() {
    this.muted = false;

    for (var audio in AUDIO_RESOURCES) {
        AUDIO_RESOURCES
.volume = 1;
    }
}

SpidermanGame.prototype.showPauseMenu = function() {
    if (this.gameoverMenu.style.display == "block") return;
    var pauseMenu = this.pauseMenu;

    var canvasRect = this.canvas.getBoundingClientRect(); // includes CSS translations
    var left = canvasRect.left;
    var top = canvasRect.top;

    this.pauseMenu.style.display = "block";
    this.pauseMenu.style.left = (left + this.canvas.width / 2) + "px";
    this.pauseMenu.style.top = (top + this.canvas.height / 2) + "px";
}

SpidermanGame.prototype.showGameoverMenu = function() {
    var gameoverMenu = this.gameoverMenu;
    this.gameoverMenu.querySelector(".spiderman-game-score").innerHTML = this.score;

    var canvasRect = this.canvas.getBoundingClientRect(); // includes CSS translations
    var left = canvasRect.left;
    var top = canvasRect.top;

    this.gameoverMenu.style.display = "block";
    this.gameoverMenu.style.left = (left + this.canvas.width / 2) + "px";
    this.gameoverMenu.style.top = (top + this.canvas.height / 2) + "px";
}

SpidermanGame.prototype.pause = function() {
    this.paused = true;
    this.showPauseMenu();
};

SpidermanGame.prototype.unpause = function() {
    this.paused = false;

    this.pauseMenu.style.display = "none";

    this.update();
}

SpidermanGame.prototype.playSound = function(audio, clone, currentTime) {
    audio = audio && audio.play ? audio : AUDIO_RESOURCES
;

    if (audio && audio.play) {
        if (clone) {
            audio = audio.cloneNode(true);
        }

        if (currentTime != undefined) {
            audio.currentTime = currentTime;
        }

        return audio.play();
    }
};

SpidermanGame.prototype.pauseSound = function(audio) {
    if (audio && audio.pause) {
        return audio.pause();
    }

    if (AUDIO_RESOURCES
) {
        AUDIO_RESOURCES
.pause();
    }
}

SpidermanGame.prototype.drawBackground = function() {
    var background = this.resources.BACKGROUND;
    var backgroundWidth = background.width;
    var backgroundHeight = background.height;

    var x = this.cameraX / 5 * -1;
    var y = 0;

    x %= Math.min(background.width, this.canvas.width);

    var ratio = backgroundWidth / backgroundHeight;
    this.ctx.drawImage(background, x, y, this.canvas.height * ratio, this.canvas.height);
    this.ctx.drawImage(background, x + this.canvas.height * ratio, y, this.canvas.height * ratio, this.canvas.height);
}

SpidermanGame.prototype.drawRoofs = function() {
    var roofs = this.scene.roofs;

    for (var i = 0; i < roofs.length; i++) {
        roofs[i].update();
    }

    // if roof left the frame and was removed, add another one
    if (roofs.length < 3) {
        var lastRoof = roofs[roofs.length - 1];
        var x = lastRoof.x + lastRoof.fullWidth + Math.round(Math.random() * 50) + 100;

        var roof = new Roof(this, x);
        this.addRoof(roof);
        roofs[0].update();
    }
}

SpidermanGame.prototype.drawEnemies = function() {
    var enemies = this.scene.enemies;

    for (var i = 0; i < enemies.length; i++) {
        enemies[i].update();
    }
}

SpidermanGame.prototype.update = function() {
    if (this.paused) return;
    if (this.gameIsOver) return;

    // draw the scene
    var scene = this.scene;
    var spiderman = scene.spiderman;
    var projectiles = scene.projectiles;

    // clear the canvas for re drawing
    this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
    this.drawBackground();
    this.drawRoofs();
    this.drawEnemies();

    for (var i = 0; i < projectiles.length; i++) {
        projectiles[i].update();
    }

    spiderman.update();

    this.ctx.fillStyle = "white";
    this.ctx.font = "20px SpidermanGamePixelFont, Monospace, Helvetica";
    this.ctx.textAlign = "center";
    this.ctx.textBaseline = "top";
    this.ctx.fillText(this.score, this.canvas.width / 2, 5);

    for (var i = 0; i < projectiles.length; i++) {
        var projectile = projectiles[i];
        var x = projectile.x;
        var y = projectile.y;

        var character = this.isCharacterAtPoint(x, y);
        if (character) {
            projectile.handleHitWithCharacter(character);
            character.handleHitWithProjectile(projectile);
        }
    }

    requestAnimFrame(this.update.bind(this));
}

SpidermanGame.prototype.addProjectile = function(projectile) {
    if (projectile instanceof Projectile) {
        this.scene.projectiles.push(projectile);
    }
}

SpidermanGame.prototype.removeProjectile = function(projectile) {
    var projectiles = this.scene.projectiles;
    if (projectiles.indexOf(projectile) > -1) {
        projectiles.splice(projectiles.indexOf(projectile), 1);
    }
}

SpidermanGame.prototype.addEnemy = function(enemy) {
    if (enemy instanceof Enemy) {
        this.scene.enemies.push(enemy);
    }
}

SpidermanGame.prototype.removeEnemy = function(enemy) {
    var enemies = this.scene.enemies;
    if (enemies.indexOf(enemy) > -1) {
        enemies.splice(enemies.indexOf(enemy), 1);
    }
}

SpidermanGame.prototype.addRoof = function(roof) {
    if (roof instanceof Roof) {
        this.scene.roofs.push(roof);
    }
}

SpidermanGame.prototype.removeRoof = function(roof) {
    var roofs = this.scene.roofs;
    if (roofs.indexOf(roof) > -1) {
        roofs.splice(roofs.indexOf(roof), 1);
    }
}

// checks if given point is roof
SpidermanGame.prototype.isRoofAtPoint = function(x, y) {
    x -= this.cameraX; // to move point relative to canvas
    for (var i = 0; i < this.scene.roofs.length; i++) {
        var roof = this.scene.roofs[i];

        // since character is relative to the camera, calculate X of roof relative to camera as well
        var roofX = roof.x - this.cameraX;

        if (roofX <= x && roofX + roof.fullWidth >= x && y >= roof.y) return roof;
    }

    return false;
}

SpidermanGame.prototype.isCharacterAtPoint = function(x, y) {
    // enemies + spiderman
    var characters = this.scene.enemies.concat(this.spiderman);
    x -= this.cameraX;

    for (var i = 0; i < characters.length; i++) {
        var character = characters[i];
        var stateImg = character.stateImg || {};

        var left = character.x - this.cameraX;
        var top = character.y;
        var right = left + stateImg.width * character.scale;
        var bottom = top + stateImg.height * character.scale;

        var isCharacter = 
               left   <= x // check left bound
            && top    <= y // top bound
            && right  >= x // right bound
            && bottom >= y; // bottom bound

        if (isCharacter) return character;
    }

    return false;
}

SpidermanGame.prototype.restart = function() {
    var roof = new Roof(this);
    roof.x = 0;

    this.spiderman = new SpiderMan(this);
    this.scene.spiderman = this.spiderman;
    this.scene.projectiles = [];
    this.scene.roofs = [roof];
    this.scene.enemies = [];
    this.cameraX = 0;
    this.score = 0;

    this.paused = false;
    this.gameIsOver = false;

    this.gameoverMenu.style.display = "none";
    this.pauseMenu.style.display = "none";

    this.update();
}

SpidermanGame.prototype.gameover = function() {
    this.gameIsOver = true;

    this.showGameoverMenu();
}

function SpiderMan(game) {
    this.game = game;
    this.canvas = game.canvas;
    this.ctx = game.ctx;
    this.name = "SPIDER_MAN";
    this.x = 0;
    this.y = 0; 
    this.states = ["STANDING"];
    this.scale = 0.5;
    this.keydowns = [];
    this.health = 5;
    this.maxHealth = 5;

    this.web = 50;

    this.velocityX = 0;
    this.velocityY = 0;

    // to regenerate every N fps (approximately N / 60 seconds)
    this.regenerationSpeed = 1200;

    // how many frames have passed
    this.frame = 0;

    this.runningFrames = ["RUNNING_RIGHT_STEP", "RUNNING_CHANGE_STEP", "RUNNING_LEFT_STEP", "RUNNING_CHANGE_STEP"];
    this.runningShootingFrames = ["SHOOT_RIGHT-STEP", "SHOOT_CHANGE_STEP", "SHOOT_LEFT-STEP", "SHOOT_CHANGE_STEP"];
    this.runningFrame = 0;

    this.gravityForce = 0.7;

    this.runningDirection = 0;
    this.runningSpeed = 5;

    this.shootingFrame = 0;
    this.wasDamagedOnPreviousFrame = false;
}

SpiderMan.prototype.keyIsDown = function(keyCode) {
    return this.keydowns.indexOf(keyCode) > -1;
}

SpiderMan.prototype.hasState = function(state) {
    return this.states.indexOf(state) > -1;
}

SpiderMan.prototype.hasStates = function(states) {
    states = states.split(" ");
    var hasStates = true;
    for (var i = 0; i < states.length; i++) {
        hasState = hasState && this.hasState(states[i]);
    }
    return hasStates;
}

SpiderMan.prototype.addState = function(state) {
    if (this.hasState(state) === false) this.states.push(state);
}

SpiderMan.prototype.removeState = function(state) {
    if (state instanceof Array) {
        for (var i = 0; i < state.length; i++) {
            this.removeState(state[i]);
        }
    }

    if (this.hasState(state)) this.states.splice(this.states.indexOf(state), 1);
}

SpiderMan.prototype.handleHitWithProjectile = function(projectile) {
    if (projectile.name != "WEB") {
        this.health -= projectile.damage;
        this.wasDamagedOnPreviousFrame = true;
    }
}

// returns the image to draw in position of spiderman
SpiderMan.prototype.stateImage = function() {
    var state = "STANDING";

    if (this.hasState("JUMP")) {
        state = "JUMP";

        if (this.velocityY == 0) {
            this.velocityY = -15;
        }
    }

    if (this.velocityY >= 0) this.removeState("JUMP");

    if (this.hasState("RUNNING")) {
        state = this.runningFrames[this.runningFrame];

        // if user is shooting while running
        if (this.hasState("SHOOT")) state = this.runningShootingFrames[this.runningFrame];

        // every 10th frame update the image
        if (this.frame % 10 === 0) {
            this.runningFrame++;
            this.runningFrame %= this.runningFrames.length - 1;
        }

        this.velocityX = this.runningDirection * this.runningSpeed;
    } else {
        this.velocityX = 0;
    }

    if (this.hasState("SHOOT")) {
        if (!this.hasState("RUNNING")) state = "SHOOT";
        if (this.shootingFrame % 20 === 0) {
            this.shoot(this.game.resources.SHOOT);
        }
        this.shootingFrame++;
    }

    var image = this.game.resources[state] || this.game.resources["STANDING"];
    this.stateImg = image; // so that stateImage is accessible

    return image;
}

SpiderMan.prototype.keydown = function(keyCode) {
    this.keydowns.push(keyCode);
}

SpiderMan.prototype.keyup = function(keyCode) {
    this.runningFrame = 0;

    if (keyCode == KEY.ARROW_RIGHT || keyCode == KEY.ARROW_LEFT) {
        this.removeState("RUNNING");
    }

    if (keyCode == KEY.SPACEBAR) {
        this.removeState("SHOOT");
        // reset the shootingFrame so if user presses space rapidly, it shoots rapidly
        // but if user holds the space, it shoots every 20 frame
        this.shootingFrame = 0;
    }

    while (this.keydowns.indexOf(keyCode) > -1) {
        this.keydowns.splice(this.keydowns.indexOf(keyCode), 1);
    }
}

SpiderMan.prototype.regenerate = function() {
    // if this is 300th fps, regenerate
    if (this.frame % this.regenerationSpeed === 0 && this.health < this.maxHealth) {
        this.health = Math.round(this.health + 1);
    }
}

SpiderMan.prototype.shoot = function(img) {
    if (this.web <= 0) return;

    var direction = this.runningDirection || 1;
    var web = new Projectile(this.game);

    web.name = "WEB";
    web.damage = 2;

    web.x = this.x + img.width * this.scale + 1;
    if (this.runningDirection == DIRECTION.LEFT) {
        web.x = this.x - 1; // left hand will be the X position of the spiderman
    }
    web.y = this.y + img.height * this.scale / 2;

    web.update = function() {            
        var x = this.x - this.game.cameraX;
        var y = this.y;

        if (direction == DIRECTION.LEFT) {
            // if spiderman is turned to left,
            // move web by 20pixels since X coordinates start from LEFT to right
            x -= 20;
        }

        this.ctx.drawImage(this.game.resources["WEB_PROJECTILE"], x, y - 10, 20, 20);

        this.x += direction * 10;
        if (this.x - this.game.cameraX >= this.canvas.width || this.x <= 0) this.remove();
    }

    web.handleHitWithCharacter = function(character) {
        // somtimes projectile is being hit by the spiderman ON launch
        // the best way is probably to launch it better but for now, i'll just make sure
        // it doesn't get destroyed on launch
        if (character.name != "SPIDER_MAN") return this.remove();
    }

    web.spiderman = this;

    this.game.addProjectile(web);
    if (this.game.soundEffects == true) {
        this.game.playSound("SHOOT", true, 0);
    }

    this.web--;
}

SpiderMan.prototype.drawHealthbar = function() {
    var heart = {
        width: 25,
        height: 25,
    };

    for (var i = 0; i < this.health; i++) {
        // (i + 1) * 5 for every 5 pixel padding per heart
        var x = i * heart.width + 5 * (i + 1);
        var y = 5;
        this.ctx.drawImage(this.game.resources.HEART, x, y, heart.width, heart.height);
    }
}

SpiderMan.prototype.drawWebbar = function() {
    var img = this.game.resources.WEB_PROJECTILE;
    var string = "X " + this.web;
    this.ctx.fillStyle = "white";
    this.ctx.font = "15px SpidermanGamePixelFont, Monospace, Arial";
    this.ctx.textAlign = "start";
    this.ctx.textBaseline = "top";

    var web = {
        width: 20,
        height: 20,
    };

    var text = {
        string: string,
        width: this.ctx.measureText(string).width,
        verticalPadding: 5,
        horizontalPadding: 10,
    };

    var x = this.canvas.width - web.width - text.width - text.horizontalPadding * 2;
    var y = text.verticalPadding;

    var textX = x + web.width + text.horizontalPadding;
    var textY = y;

    this.ctx.drawImage(img, x, y, web.width, web.height);
    this.ctx.fillText(text.string, textX, textY);
}

// function that gets called with global update function
SpiderMan.prototype.update = function() {
    if (this.keyIsDown(KEY.ARROW_UP) && !this.hasState("FALL")) {
        this.addState("JUMP");
    }
    if (this.keyIsDown(KEY.ARROW_RIGHT)) {
        this.addState("RUNNING");
        this.runningDirection = DIRECTION.RIGHT;
    }
    if (this.keyIsDown(KEY.ARROW_LEFT)) {
        this.addState("RUNNING");
        this.runningDirection = DIRECTION.LEFT;
    }
    if (this.keyIsDown(KEY.SPACEBAR)) {
        this.addState("SHOOT");
    }

    if (this.y >= this.canvas.height || !this.health || !this.web) {
        this.game.gameover();
    }

    var img = this.stateImage();

    this.velocityY += this.gravityForce;

    this.y += this.velocityY;
    this.x += this.velocityX;

    if (this.x - this.game.cameraX < 0) {
        this.x = this.game.cameraX; // dont allow going left
    }

    if (this.x - this.game.cameraX > 150) {
        this.game.cameraX += this.velocityX;
    }
    
    // check if coordinates are on the roof, before increasing it by velocityX, because it might BE inside the building
    // after velocityX
    // check if left side is on the roof
    var roofLeft = this.game.isRoofAtPoint(this.x - this.velocityX, this.y + img.height * this.scale + 1);
    // check if right X hit the roof
    var roofRight = this.game.isRoofAtPoint(this.x + img.width * this.scale - this.velocityX, this.y + img.height * this.scale + 1);

    // check if spiderman is standing on the ground (roof)
    if (roofLeft || roofRight) {
        var roof = roofLeft || roofRight;

        // since velocity might kinda make the spiderman go INSIDE the wall by adding too much Y,
        // we'll just check if spider's y is INSIDE the wall just because of the velocityY
        // just to make sure that spider is actually on the roof
        if (roof.y + this.velocityY <= this.y) {
            this.x -= this.velocityX;
            this.velocityX = 0;
        } else {
            this.y = this.canvas.height - roof.height - img.height * this.scale;
            this.velocityY = 0;
            this.removeState("FALL");
        }
    }

    var x = this.x - this.game.cameraX;
    var y = this.y;
    var width = img.width * this.scale;
    var height = img.height * this.scale;

    this.ctx.save();

    // if the spiderman is running to the left, flip him
    if (this.runningDirection == DIRECTION.LEFT) {
        this.ctx.scale(-1, 1);
        x *= -1;
        x -= width;
    }

    this.ctx.drawImage(img, x, y, width, height);
    this.ctx.restore();

    if (this.wasDamagedOnPreviousFrame) {
        this.wasDamagedOnPreviousFrame = false;

        this.ctx.fillStyle = "rgba(0, 0, 0, 0.2)";
        this.ctx.fillRect(x, y, width, height);
    }

    this.regenerate();
    this.drawHealthbar();
    this.drawWebbar();

    this.frame++;
}

function Projectile(game) {
    this.x = 0;
    this.y = 0;

    this.damage = 0;
    this.name = "UNKNOWN";

    this.canvas = game.canvas;
    this.ctx = game.ctx;
    this.game = game;
}

Projectile.prototype.update = function() {
}

Projectile.prototype.remove = function() {
    this.game.removeProjectile(this);
}

Projectile.prototype.handleHitWithCharacter = function() {
    this.remove();
}

function Roof(game, x, y) {
    this.game = game;
    this.canvas = game.canvas;
    this.ctx = game.ctx;

    this.width = Math.round(Math.random() * (this.game.resources.BUILDING.width - 200)) + 200;
    this.height = Math.round(Math.random() * 50) + 100;
    this.fullWidth = this.width + 15; // 15 pixels for right end of the roof top

    this.x = x || 0;
    this.y = this.canvas.height - this.height;

    // 70% chance?
    var shouldSpawnEnemy = Math.round(Math.random() * 100) >= 30;
    if (shouldSpawnEnemy) {
        var enemy = new Enemy(this.game, {
            x: this.x + this.width / 2,
        });
        enemy.y = this.y - 1 - enemy.stateImg.height * enemy.scale;
        this.game.addEnemy(enemy);
        this.enemy = enemy;
    }
}

Roof.prototype.update = function() {
    var renderX = this.x - this.game.cameraX;
    var roof = this.game.resources.BUILDING;

    this.ctx.drawImage(roof, 0, 0, this.width, this.height, renderX, this.y, this.width, this.height);
    this.ctx.drawImage(roof, this.width, 0, 15, 26, renderX + this.width, this.y, 15, 26);

    if (renderX + this.width <= 0) {
        this.game.removeRoof(this);
        this.game.removeEnemy(this.enemy);
    }
}


function Enemy(game, opts) {
    opts = opts || {};

    this.game = game;
    this.canvas = game.canvas;
    this.ctx = game.ctx;

    this.health = opts.health || 4;
    this.maxHealth = opts.maxHealth || this.health;
    this.name = opts.name || "THUG";
    this.x = opts.x || this.canvas.width - 50;
    this.y = opts.y || 0;
    // just to control the scaling of an image
    this.scale = 0.5;
    this.stateImg = this.game.resources[this.name];

    this.wasDamagedOnPreviousFrame = false;
    this.frame = 0;
};

Enemy.prototype.shoot = function() {
    var self = this;
    var knife = this.game.resources.KNIFE;

    var projectile = new Projectile(this.game);
    projectile.name = "KNIFE";
    projectile.damage = 1;

    projectile.x = this.x - knife.width * this.scale / 2;
    // so knifes height is divided by 4 because, 2 is for center, and another 2 is for 0.5 scale
    projectile.y = this.y + (this.stateImg.height * this.scale / 2) - (knife.height * this.scale / 4);
    projectile.update = function() {
        this.ctx.drawImage(knife, this.x - this.game.cameraX, this.y, knife.width * self.scale / 2, knife.height * self.scale / 2);

        this.x -= 10;
    }

    this.game.addProjectile(projectile);
}

Enemy.prototype.drawHealthbar = function() {
    var healthbar = {
        height: 5,
        width: 100,
        style: "red",
        borderWidth: 2,
        borderStyle: "black"
    };

    var x = this.x - this.game.cameraX;
    x -= healthbar.width / 2; // to center the healthbar with the X of the character
    x += this.stateImg.width * this.scale / 2; // to center the healthbar with the X of characters center

    var y      = this.y - (healthbar.height + healthbar.borderWidth * 2) - 5;
    var width  = healthbar.width * this.health / this.maxHealth; // get the width for current health
    var height = healthbar.height;

    var borderX      = x - healthbar.borderWidth;
    var borderY      = y - healthbar.borderWidth;
    var borderWidth  = healthbar.width + healthbar.borderWidth * 2;
    var borderHeight = healthbar.height + healthbar.borderWidth * 2;

    this.ctx.fillStyle = healthbar.borderStyle;
    this.ctx.fillRect(borderX, borderY, borderWidth, borderHeight);

    this.ctx.fillStyle = healthbar.style;
    this.ctx.fillRect(x, y, width, height);
}

Enemy.prototype.update = function() {
    var img = this.game.resources[this.name];
    this.stateImg = img;

    if (this.health <= 0) {
        this.remove();
    }

    this.drawHealthbar();

    var x = this.x - this.game.cameraX;
    var y = this.y;
    var width = img.width * this.scale;
    var height = img.height * this.scale;

    this.ctx.save();
    this.ctx.scale(-1, 1);

    this.ctx.drawImage(this.game.resources[this.name], (x + width) * -1, y, width, height);
    this.ctx.restore();

    if (this.wasDamagedOnPreviousFrame) {
        this.wasDamagedOnPreviousFrame = false;
        this.ctx.fillStyle = "rgba(255, 0, 0, 0.2)";
        this.ctx.fillRect(x, y, width, height);
    }

    var isInScreen = this.x - this.game.cameraX <= this.canvas.width;

    if (this.frame % 100 === 0 && isInScreen) {
        this.shoot();
    }

    this.frame++;
}

Enemy.prototype.remove = function() {
    this.game.score++;
    this.game.spiderman.web += this.maxHealth;
    this.game.removeEnemy(this);	
}

Enemy.prototype.handleHitWithProjectile = function(projectile) {
    if (projectile.name == "WEB") {
        this.health -= projectile.damage;
        this.wasDamagedOnPreviousFrame = true;
    }
}

window.SpidermanGame = SpidermanGame;
window.Projectile    = Projectile;
window.SpiderMan     = SpiderMan;
window.Enemy         = Enemy;
window.Roof          = Roof;

})(window, document);

 

download

 

Explanation

  1. HTML Structure:
    • The HTML includes containers for products and the shopping cart, along with a heading and a total price display.
  2. CSS Styling:
    • The CSS styles the container, products, and cart items for a clean, modern look.
    • Products and cart items are styled with a border and some padding.
    • Buttons are styled for a consistent look with hover effects.
  3. JavaScript Functionality:
    • The JavaScript initializes an array of products and an empty cart array.
    • Functions to display products, add to cart, remove from cart, and update the total price are defined.
    • Event listeners are set up for adding and removing items from the cart.
    • The displayProducts function creates HTML elements for each product and adds them to the products container.
    • The displayCart function creates HTML elements for each cart item and adds them to the cart container, and also updates the total price.
    • The addToCart function adds a product to the cart array and updates the display.
    • The removeFromCart function removes a product from the cart array and updates the display.
    • The updateTotal function calculates the total price of items in the cart and updates the total display.

This setup provides a simple and functional shopping cart. You can expand it by adding more features like quantity selection, saving the cart to local storage, or integrating with a backend server for persistent data storage.

CEO Piyush Gupta


Reviews

There are no reviews yet. Be the first one to write one.


0.0
Rated 0 out of 5
0 out of 5 stars (based on 0 reviews)
Excellent0%
Very good0%
Average0%
Poor0%
Terrible0%