canvas塔防小游戏代码

代码语言:html

所属分类:游戏

代码描述:canvas塔防小游戏代码,可随意点击设置攻击位置,还可以选择攻击参数,不能让敌人过右边的红线。

代码标签: canvas 塔防 小游戏 代码

下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开

<!DOCTYPE html>
<html lang="en" >

<head>
  <meta charset="UTF-8">
  


  
  
  
<style>
html,
body,
main {
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 10px;
  align-items: center;
  justify-content: center;
}

canvas {
  outline: solid 20px black;
  background: black;
  border-radius: 10px;
}
</style>


  
  
</head>

<body >
  
<script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/p5.1.6.0.js"></script>
      <script >
"use strict";
console.clear();
function setup() {
    canvas = createCanvas(800, 600);
    colorMode(HSL);
    restart();
}
let canvas;
let scene;
let mouseVector;
function restart() {
    mouseVector = null;
    scene = new Scene({ health: 100, gameOver: false, canAddTurretAtMouse: false, canvas });
    scene.add(new Turret(createVector(2 * width / 3, height / 2)));
    loop();
}
function spawnEnemy() {
    scene.add(new Enemy());
}
function tryAddTurretAtMouse() {
    if (!scene.data.gameOver && scene.data.canAddTurretAtMouse) {
        scene.add(new Turret(mouseVector));
    }
}
function checkForGameOver() {
    if (scene.data.health <= 0) {
        scene.data.gameOver = true;
    }
    return scene.data.gameOver;
}
/**
 * ==============
 *  P5 Lifecycle
 * ==============
 */
function keyPressed() {
    if (key === "r") {
        restart();
    }
}
function mousePressed() {
    tryAddTurretAtMouse();
    scene.executeListeners("mousepressed");
}
function draw() {
    background(11);
    mouseVector = createVector(mouseX, mouseY);
    if (checkForGameOver()) {
        drawGameOver();
        return;
    }
    scene.update();
    if (frameCount % 30 === 0) {
        spawnEnemy();
    }
    // Draw hover turret
    scene.data.canAddTurretAtMouse = false;
    let hoverTurret;
    const turretNearMouse = scene.closest(mouseVector, "turret", 100);
    if (inBounds(mouseVector) && !turretNearMouse) {
        hoverTurret = new Turret(mouseVector);
        scene.data.canAddTurretAtMouse = true;
    }
    /**
     * Draw start
     */
    if (hoverTurret)
        hoverTurret.predraw();
    scene.draw();
    if (hoverTurret)
        hoverTurret.draw();
    // Draw health bar
    push();
    const healthHeight = map(scene.data.health, 0, 100, 0, height);
    rectMode(CENTER);
    noStroke();
    fill("red");
    rect(width - 4, height / 2, 8, healthHeight);
    pop();
}
function drawGameOver() {
    scene.draw();
    // Draw GAME OVER text
    push();
    const NUM_LABELS = 5;
    const MAX_OFFSET = 4;
    const LABEL_OFFSET_X = map(mouseX, 0, width, MAX_OFFSET * 2, MAX_OFFSET);
    const LABEL_OFFSET_Y = map(mouseY, 0, height, MAX_OFFSET * 2, MAX_OFFSET);
    translate(-LABEL_OFFSET_X * NUM_LABELS, -LABEL_OFFSET_Y * NUM_LABELS);
    for (let i = 0; i < NUM_LABELS; i++) {
        translate(LABEL_OFFSET_X, LABEL_OFFSET_Y);
        const textColor = map(i, -1, NUM_LABELS - 1, 11, 100, true);
        noStroke();
        fill(textColor);
        textAlign(CENTER, CENTER);
        textSize(120);
        text("GAME OVER", width / 2, height / 2);
    }
    pop();
}
function drawDebugValue(value, title) {
    const valueStr = title ? `[${title}: ${value}]` : `[${value}]`;
    noStroke();
    fill("lime");
    textSize(24);
    textAlign(LEFT, TOP);
    text(valueStr, 0, 0);
    const margin = textWidth("WWW");
    translate(ceil(textWidth(valueStr) / margin) * margin + 10, 0);
}
/**
 * =========
 *  Helpers
 * =========
 */
function inBounds(pos) {
    const oob = pos.x < 0 || pos.x > width || pos.y < 0 || pos.y > height;
    return !oob;
}
// Required for getTurnTowardsDiff()
function getAngleBetween(p1, p2) {
    return atan2(p2.y - p1.y, p2.x - p1.x);
}
// Required for getTurnTowardsDiff()
function normalizeAngle(a) {
    const positiveAngle = a < 0 ? TAU + a % TAU : a % TAU;
    return positiveAngle > PI ? positiveAngle - TAU : positiveAngle;
}
function getDistSq(p1, p2) {
    return sq(p2.x - p1.x) + sq(p2.y - p1.y);
}
/**
 * =========
 *  Classes
 * =========
 */
class Scene {
    constructor(data) {
        this.debugShowFrameRate = false;
        this.debugShowSceneObjsCount = false;
        this.objsData = {};
        this.data = Object.assign({}, data);
    }
    get objDataTypeIds() {
        return Object.keys(this.objsData);
    }
    get allObjs() {
        const allObjs = this.objDataTypeIds.map(id => this.getObjsByType(id)).flat();
        allObjs.sort((a, b) => a.zIndex - b.zIndex);
        return allObjs;
    }
    getObjsDataByType(typeId) {
        this._validateObjDataType(typeId);
        return this.objsData[typeId];
    }
    getObjsByType(typeId) {
        return this.getObjsDataByType(typeId).objs;
    }
    setObjsByType(typeId, objs) {
        const objsDataByType = this.getObjsDataByType(typeId);
        objsDataByType.objs = objs;
    }
    add(obj) {
        if (obj.scene === this) {
            throw new Error("This object was already added to the scene.");
        }
        obj.scene = this;
        this.getObjsByType(obj.typeId).push(obj);
        obj._dependencies.filter(dep => dep.scene !== this).forEach(dep => {
            this.add(dep);
        });
        return obj;
    }
    remove(typeId, id) {
        let objs = this.getObjsByType(typeId);
        const removeIndex = objs.findIndex(obj => obj.id === id);
        if (removeIndex === -1)
            return;
        const nextObjs = [...objs];
        const [objToRemove] = nextObjs.splice(removeIndex, 1);
        objToRemove.removeDependencies();
        objToRemove.scene = null;
        this.setObjsByType(typeId, nextObjs);
    }
    draw() {
        this.allObjs.forEach((obj) => obj._predraw());
        this.allObjs.forEach((obj) => obj._draw());
        // Debug statements
        push();
        translate(10, 10);
        if (this.debugShowFrameRate) {
            this.debugShowFrameRate__Buffer = this.debugShowFrameRate__Buffer || [];
            this.debugShowFrameRate__Buffer.push(frameRate());
            this.debugShowFrameRate__Buffer = this.debugShowFrameRate__Buffer.slice(-60);
            const fr = this.debugShowFrameRate__Buffer.reduce((acc, fr) => acc + fr, 0) / this.debugShowFrameRate__Buffer.length;
            drawDebugValue(fr.toFixed(0), "FPS");
        }
        if (this.debugShowSceneObjsCount) {
            drawDebugValue(this.allObjs.length, "Objs");
        }
        pop();
    }
    update() {
        this.allObjs.forEach((obj) => obj._update());
    }
    closestInfo(pos, typeId, range = Infinity, excludeObjs = []) {
        const objs = this.getObjsByType(typeId);
        const notFound = { closest: null, closestDist: Infinity };
        if (!objs)
            return notFound;
        let closest = null;
        let closestDistSq = Infinity;
        objs.forEach(obj => {
            if (excludeObjs.includes(obj))
                return;
            const distSq = getDistSq(pos, obj.pos);
            if (distSq < closestDistSq) {
                closestDistSq = distSq;
                closest = obj;
            }
        });
        const closestDist = sqrt(closestDistSq);
        if (closestDist > range) {
            return notFound;
        }
        return { closest, closestDist };
    }
    closest(pos, typeId, range, excludeObjs) {
        const { closest } = this.closestInfo(pos, typeId, range, excludeObjs);
        return closest;
    }
    _validateObjDataType(typeId) {
        // If objs data doesn't already exist for that type, add it.
        if (!this.objsData[typeId]) {
            this.objsData[typeId] = { typeId, objs: [] };
        }
    }
    executeListeners(event) {
        this.allObjs.forEach(obj => {
            const listeners = obj._listeners[event];
            if (listeners && listeners.length > 0) {
                listeners.forEach(listener => {
                    listener();
                });
            }
        });
    }
}
class SceneObj {
    constructor(pos, angle = 0, radius = 10) {
        this.typeId = "generic";
        this._scene = null;
        this._dependencies = [];
        this._listeners = {};
        this.zIndex = 0;
        this.id = `ID-${Math.random()}`;
        this.pos = pos.copy();
        this.angle = angle;
        this.radius = radius;
        this.createdFrame = frameCount;
    }
    get diameter() {
        return this.radius * 2;
    }
    get scene() {
        return this._scene;
    }
    set scene(scene) {
        if (scene && this._scene) {
            throw new Error("Tried overriding existing `scene` property with a new one. Object cannot be a part of two scenes");
        }
        this._scene = scene;
    }
    _predraw() {
        this.predraw();
    }
    predraw() { }
    _draw() {
        this.draw();
    }
    draw() { }
    _update() {
        this.update();
    }
    update() { }
    on(event, callback) {
        const regionalizedCallback = () => {
            if (this.mouseOver()) {
                callback();
            }
        };
        switch (event) {
            case "mousedown":
            case "mousepressed":
            case "mouseover":
                this._listeners[event] = this._listeners[event] || [];
                this._listeners[event].push(regionalizedCallback);
                break;
            default:
                throw new Error("Unknown event type " + event);
        }
    }
    off(event) {
        switch (event) {
            case "mousedown":
            case "mousepressed":
            case "mouseover":
                this._listeners[event] = [];
                break;
            default:
                throw new Error("Unknown event type " + event);
        }
    }
    addDependency(dep) {
        this._dependencies.push(dep);
        if (this.scene) {
            this.scene.add(dep);
        }
    }
    detachDependency(dep) {
        this._dependencies = this._dependencies.filter((dependency) => dep !== dependency);
    }
    removeDependencies() {
        this.........完整代码请登录后点击上方下载按钮下载查看

网友评论0