在画布上使用 DPI Fix 现在有请求动画帧错误非常慢

问题描述

帮助!前端新手。致力于简单的 Break Out 游戏。它非常像素化 - 因此实施了 DPI Fix,它改变了所有 x 和 y 位置,现在请求动画帧不起作用。非常慢。也试过 setTimeOut 来影响速度无济于事。请帮助我了解问题所在以及如何解决

```
<!DOCTYPE html>
<html lang="en" dir="ltr">
  <head>
    <Meta charset="utf-8">
    <title>HTML5 BREAK OUT GAME</title>
    <link rel="stylesheet" href="styles.css">
  </head>
  <body>

      <canvas id="myCanvas"></canvas>






      <script src="main.js"></script>


  </body>
</html>
```
//get DPI DOTS PER INCH / PPI PIXELS PER INCH
let dpi = window.devicePixelRatio;


// Grab reference of canvas & set up context to be able to draw

var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");


// frames per second var holds custom speed num for request animation frame method

let framesPerSecond = 60;

// X & Y position on canvas

var x = canvas.width*2;
var y = canvas.height+500;

// add value to x & y after every frame

var dx = 2;
var dy = -2;

// ballRadius that will hold the radius of the drawn circle and be used for calculations//

var ballRadius = 40;

// defining the height and width of the paddle and its starting point on the x axis

var paddleHeight = 30;
var paddleWidth = 245;
var paddleX = (canvas.width-paddleWidth)/2;

// vars holding info on button pressed

var rightpressed = false;
var leftpressed = false;

// information about the bricks such as their width and height,rows and columns,so bricks can be drawn

var brickRowCount = 3;
var brickColumnCount = 5;
var brickWidth = 400;
var brickHeight = 60;
var brickPadding = 15;
var brickOffsetTop = 75;
var brickOffsetLeft = 65;

// variable to record the score

var score = 0;

// variable holding num of lives

var lives = 3;


var requestAnimationFrame = window.requestAnimationFrame ||
                            window.mozRequestAnimationFrame ||
                            window.webkitRequestAnimationFrame ||
                            window.msRequestAnimationFrame;

// two dimensional array holding all bricks,brick columns (c),which in turn will contain the brick rows (r),which in turn will each contain an object containing the x and y position to paint each brick on the screen - adding key/value pair of status

var bricks = [];
for(var c=0; c<brickColumnCount; c++) {
    bricks[c] = [];
    for(var r=0; r<brickRowCount; r++) {
        bricks[c][r] = { x: 0,y: 0,status: 1 };

    }
}


// event listeners for up and down keys for controlls

document.addEventListener("keydown",keyDownHandler,false);
document.addEventListener("keyup",keyUpHandler,false);

// event listener for mouse movement

document.addEventListener("mousemove",mouseMoveHandler,false);




function fix_dpi() {
//get CSS height getComputedStyle method (canvas) chained to getPropertyValue of "height" of "canvas" chained to slice method to return string minus "px"
//the + prefix casts it to an integer whole number

  // CURRENT HEIGHT
let style_height = +getComputedStyle(canvas).getPropertyValue("height").slice(0,-2);


// CURRENT WIDTH
let style_width = +getComputedStyle(canvas).getPropertyValue("width").slice(0,-2);

//scale the canvas
  // Change height based on current (window / viewport) height X dpi
canvas.setAttribute('height',style_height * dpi);
canvas.setAttribute('width',style_width * dpi);

}





// When we press a key down,this information is stored in a variable. The relevant variable in each case is set to true. When the key is released,the variable is set back to false.

function keyDownHandler(e) {
    if(e.key == "Right" || e.key == "ArrowRight") {
        rightpressed = true;
    }
    else if(e.key == "Left" || e.key == "ArrowLeft") {
        leftpressed = true;
    }
}

function keyUpHandler(e) {
    if(e.key == "Right" || e.key == "ArrowRight") {
        rightpressed = false;
    }
    else if(e.key == "Left" || e.key == "ArrowLeft") {
        leftpressed = false;
    }
}

// update paddle position based on pointer coordinates,using clientX (mousemove API) - offSetLeft (HTML DOM API),relativX - 1/2 paddleWidth,anchors pointer to paddle center.


function mouseMoveHandler(e) {
  var relativeX = e.clientX - canvas.offsetLeft;
  if(relativeX > 0 && relativeX < canvas.width) {
    paddleX = relativeX - paddleWidth/2;
  }
}




// collision detection function that will loop through all the bricks and compare every single brick's position with the ball's coordinates as each frame is drawn. define the b variable for storing the brick object in every loop of the collision detection,if collision balls moves away - status of brick changed to 0,so draw function will not draw again in new frame,score increases,when score == # of bricks - win.

function collisionDetection() {
    for(var c=0; c<brickColumnCount; c++) {
        for(var r=0; r<brickRowCount; r++) {
            var b = bricks[c][r];
            if(b.status == 1) {
                if(x > b.x && x < b.x+brickWidth && y > b.y && y < b.y+brickHeight) {
                    dy = -dy;
                    b.status = 0;
                      score++;
                      if(score == brickRowCount*brickColumnCount) {
                        alert("YOU WIN,CONGRATULATIONS!");
                        document.location.reload();
                    }
                }
            }
        }
    }
}

// draws text for score keeping

function drawscore() {
    ctx.font = "bold 50px Helvetica,Arial,sans-serif";
    ctx.fillStyle = "#0095DD";
    ctx.fillText("score: "+score,65,50);
}

// draws lives left

function drawLives() {
    ctx.font = "bold 50px Helvetica,sans-serif";
    ctx.fillStyle = "#0095DD";
    ctx.fillText("Lives: "+lives,1925,50);
}

// define a drawing loop (draw function called by setInterval 10 mil sec)

// drawBall draws the ball

function drawBall() {
    ctx.beginPath();
    ctx.arc(x,y,ballRadius,Math.PI*2);
    ctx.fillStyle = "#0095DD";
    ctx.fill();
    ctx.closePath();
};

// drawPaddle draws the paddle

function drawPaddle() {
  ctx.beginPath();
  ctx.rect(paddleX,canvas.height-paddleHeight,paddleWidth,paddleHeight);
  ctx.fillStyle = "#0095DD";
  ctx.fill();
  ctx.closePath();
}

// drawBricks draws bricks from top left,brickX & brickY calc for correct position of each new brick. using two dimensional array with status key/value pair. Only draw if status = 1.

function drawBricks() {
    for(var c=0; c<brickColumnCount; c++) {
        for(var r=0; r<brickRowCount; r++) {
            if(bricks[c][r].status == 1) {
                var brickX = (c*(brickWidth+brickPadding))+brickOffsetLeft;
                var brickY = (r*(brickHeight+brickPadding))+brickOffsetTop;
                bricks[c][r].x = brickX;
                bricks[c][r].y = brickY;
                ctx.beginPath();
                ctx.rect(brickX,brickY,brickWidth,brickHeight);
                ctx.fillStyle = "#0095DD";
                ctx.fill();
                ctx.closePath();
            }
        }
    }
}

// draw function draws everything while moving (animating) using request animation frame & set time out method with anonuymous func holding "draw" statements & frames per second variable holding custom speed num to control speed of animation

function draw() {
    setTimeout(function() {
        // fix blurry canvas
     fix_dpi()

   // removes earlier drawn image so no trail visible
      ctx.clearRect(0,canvas.width,canvas.height);
    // calls drawBricks func
    drawBricks();
    // calls drawBall function
    drawBall();
    // calls drawPaddle function
    drawPaddle();
    // calls drawscore function
    drawscore();
    // calls drawLives function
    drawLives();
    // calls collisionDectection function
    collisionDetection();


// COLLISION DETECTION left & right wall- if x axis postion plus x axis increment is greater than canvas width minus ballRadius OR if x axis plus x axis increment is less than ballRadius subtract increment amount (move back)

// 2nd If statement collision with top wall move away,if touch bottom game over and reload,if touch paddle move back

    if(x + dx > canvas.width-ballRadius || x + dx < ballRadius) {
        dx = -dx;
    }

    if(y + dy < ballRadius) {
    dy = -dy;
  } else if(y + dy > canvas.height-ballRadius) {
        if(x > paddleX && x < paddleX + paddleWidth) {
            dy = -dy;
        }
        else {
          lives--;
            if(!lives) {
                alert("GAME OVER");
                document.location.reload();
            }
            else {
                            x = canvas.width/2;
                            y = canvas.height-30;
                            dx = 3;
                            dy = -3;
                            paddleX = (canvas.width-paddleWidth)/2;
            }
        }
    }

// if rightpressed true add 7 to paddle x axis position moving right vice versa for leftpressed

// KEEP PADDLE INSIDE CANVAS,if paddle position plus paddle width is greater than canvas width (boundary) change position to canvas width minus paddle width.
// If paddle position is less than 0 (left boundary) move to 0 - left boundary

if(rightpressed && paddleX < canvas.width-paddleWidth) {
paddleX += 7;
}
else if(leftpressed && paddleX > 0) {
paddleX -= 7;
}

// apply increment to axis positions

    x += dx;
    y += dy;

// giving control of the framerate back to the browser It will sync the framerate accordingly and render the shapes only when needed. This produces a more efficient,smoother animation loop than the older setInterval  method.

requestAnimationFrame(draw);

},1000 / framesPerSecond);


};

// draw();
requestAnimationFrame(draw);
```

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...