你躲避投射物的画布游戏

Canvas game where you dodge projectiles

本文关键字:游戏 布游戏 躲避 投射物      更新时间:2023-09-26

问题

我正在创建一个游戏,你必须躲避投射物,每错过一个投射物,你就会获得1分。现在我有了它,所以每一枚炮弹击中你,分数都会上升。

问题

我该如何改变这一点,使每一枚未击中你的炮弹得分都会上升?

代码

        function init() {
            level = 1;
            total_projectiles = 0;
            projectiles = [];
            c = document.getElementById("c");
            ctx = c.getContext("2d");
            ctx.fillStyle = "#ff6600";
            ctx.fillRect(0, 0, 500, 600);
            c.addEventListener("mousemove", function (e) {
                //moving over the canvas.
                var bounding_box = c.getBoundingClientRect();
                player.x = (e.clientX - bounding_box.left) * (c.width / bounding_box.width) - player_img.width / 2;
            }, false);
            setupProjectiles(); 
            requestAnimationFrame(tick);
        }
        function setupProjectiles() {
            var max_projectiles = level * projectiles_per_level;
            while (projectiles.length < max_projectiles) {
                initProjectile(projectiles.length);
            }
        }
        function initProjectile(index) {
            var max_speed = max_speed_per_level * level;
            var min_speed = min_speed_per_level * level;
            projectiles[index] = {
                x: Math.round(Math.random() * (width - 2 * projectile_w)) + projectile_w,
                y: -projectile_h,
                v: Math.round(Math.random() * (max_speed - min_speed)) + min_speed,
                delay: Date.now() + Math.random() * delay
            }
            total_projectiles++;
        }
        function collision(projectile) {
            if (projectile.y + projectile_img.height < player.y + 74) {
                return false;
            }
            if (projectile.y > player.y + 74) {
                return false;
            }
            if (projectile.x + projectile_img.width < player.x + 177) {
                return false;
            }
            if (projectile.x > player.x + 177) {
                return false;
            }
            return true;
        }
        function maybeIncreaseDifficulty() {
            level = Math.max(1, Math.ceil(player.score / 10));
            setupProjectiles();
        }
        function tick() {
            var i;
            var projectile;
            var dateNow = Date.now();
            c.width = c.width;
            for (i = 0; i < projectiles.length; i++) {
                projectile = projectiles[i];
                if (dateNow > projectile.delay) {
                    projectile.y += projectile.v;
                    if (collision(projectile)) {
                        initProjectile(i);
                        player.score++;
                    } else if (projectile.y > height) {
                        initProjectile(i);
                    } else {
                        ctx.drawImage(projectile_img, projectile.x, projectile.y);
                    }
                }
            }

您可以像这样测试"未遂事件":

  • nearRadius属性添加到射弹对象。nearRadius大于炮弹的实际半径,用于在炮弹经过玩家附近时进行打击测试。

  • isNear属性添加到射弹对象。CCD_ 4是指示CCD_ 5是否与玩家碰撞的真/假属性。

  • 当抛射物的isNear属性从true变为false时,抛射物几乎没有击中玩家。当这种情况发生时,你可以增加玩家的分数。

示例代码和演示:

var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;
function reOffset(){
    var BB=canvas.getBoundingClientRect();
    offsetX=BB.left;
    offsetY=BB.top;        
}
var offsetX,offsetY;
reOffset();
window.onscroll=function(e){ reOffset(); }
window.onresize=function(e){ reOffset(); }
var player={x:cw/2,y:50,radius:15,score:0};
var projectile={x:-30,y:30,radius:5,nearRadius:35,isNear:false}
var gameOver=false;
ctx.textAlign='center';
ctx.textBaseline='middle';
ctx.font='14px verdana';
draw();
$("#canvas").mousemove(function(e){handleMouseMove(e);});
function draw(){
    ctx.clearRect(0,0,cw,ch);
    // player
    ctx.beginPath();
    ctx.arc(player.x,player.y,player.radius,0,Math.PI*2);
    ctx.fillStyle='green';
    ctx.fill();
    // players score
    ctx.fillStyle='white';
    ctx.fillText(player.score,player.x,player.y);
    // projectile
    ctx.beginPath();
    ctx.arc(projectile.x,projectile.y,projectile.radius,0,Math.PI*2);
    ctx.fillStyle='red';
    ctx.fill();
    // projectile near 
    ctx.beginPath();
    ctx.arc(projectile.x,projectile.y,projectile.nearRadius,0,Math.PI*2);
    ctx.strokeStyle=projectile.isNear?'green':'red';
    ctx.stroke();
    // if game over
    if(gameOver){
        ctx.font='30px verdana';
        ctx.fillStyle='blue';
        ctx.fillText('Game Over',cw/2,35);
    }
}
function handleMouseMove(e){
    if(gameOver){return;}
    
    // tell the browser we're handling this event
    e.preventDefault();
    e.stopPropagation();
    projectile.x=parseInt(e.clientX-offsetX);
    projectile.y=parseInt(e.clientY-offsetY);
    var dx=projectile.x-player.x;
    var dy=projectile.y-player.y;
    // test projectile hits player
    var rr=projectile.radius+player.radius;
    gameOver=(dx*dx+dy*dy)<(rr*rr);
    
    // test projectile nearly misses player
    var rr=projectile.nearRadius+player.radius;
    var isNearNow=(dx*dx+dy*dy)<(rr*rr);
    if(projectile.isNear && !isNearNow){
        player.score++;
    }
    projectile.isNear=isNearNow;
    draw();
}
body{ background-color: ivory; }
#canvas{border:1px solid red; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<h4>Move red projectile with mouse<br>Score when outer ring passes by player.</h4>
<canvas id="canvas" width=300 height=300></canvas>