简体   繁体   English

输入时实时更改乒乓球的速度(JS)

[英]Change speed of pong ball in realtime on input (JS)

I have a number input which i want to it to function as a real-time update of the speed of the pong ball, however every method I've tried hasn't worked it all comes back as "NaN".我有一个数字输入,我想将它输入到 function 作为乒乓球速度的实时更新,但是我尝试过的每种方法都没有奏效,它都返回为“NaN”。 The speed is originally set to 7 but once the ball resets and a player scores id like the ball to change to the number of the input.速度最初设置为 7,但是一旦球重置并且玩家得分 id 像球一样更改为输入的数字。 Thank you谢谢

    // select canvas element
const canvas = document.getElementById("pong");

// getContext of canvas = methods and properties to draw and do a lot of thing to the canvas
const ctx = canvas.getContext("2d");

// get the value of the user input
var userSpeedInput = parseInt(document.getElementById("user-speed").value);
// speed btn
const speedBtn = document.getElementById("speed-btn");

// load sounds
let hit = new Audio();
let wall = new Audio();
let userScore = new Audio();
let comScore = new Audio();

hit.src = "sounds/hit.mp3";
wall.src = "sounds/wall.mp3";
comScore.src = "sounds/comScore.mp3";
userScore.src = "sounds/userScore.mp3";

// Ball object
const ball = {
  x: canvas.width / 2,
  y: canvas.height / 2,
  radius: 10,
  velocityX: 5,
  velocityY: 5,
  speed: userSpeedInput, // speed: userSpeedInput;
  color: "WHITE",
};

// User Paddle
const user = {
  x: 0, // left side of canvas
  y: (canvas.height - 100) / 2, // -100 the height of paddle
  width: 10,
  height: 100,
  score: 0,
  color: "WHITE",
};

// COM Paddle
const com = {
  x: canvas.width - 10, // - width of paddle
  y: (canvas.height - 100) / 2, // -100 the height of paddle
  width: 10,
  height: 100,
  score: 0,
  color: "WHITE",
};

// NET
const net = {
  x: (canvas.width - 2) / 2,
  y: 0,
  height: 10,
  width: 2,
  color: "WHITE",
};

// draw a rectangle, will be used to draw paddles
function drawRect(x, y, w, h, color) {
  ctx.fillStyle = color;
  ctx.fillRect(x, y, w, h);
}

// draw circle, will be used to draw the ball
function drawArc(x, y, r, color) {
  ctx.fillStyle = color;
  ctx.beginPath();
  ctx.arc(x, y, r, 0, Math.PI * 2, true);
  ctx.closePath();
  ctx.fill();
}

// listening to the mouse
canvas.addEventListener("mousemove", getMousePos);

function getMousePos(evt) {
  let rect = canvas.getBoundingClientRect();

  user.y = evt.clientY - rect.top - user.height / 2;
}

// when COM or USER scores, we reset the ball
function resetBall() {
  if (!ball) return;
  ball.x = canvas.width / 2;
  ball.y = canvas.height / 2;
  ball.velocityX = -ball.velocityX;
  ball.speed = userSpeedInput;
  alert(ball.speed);
}

// draw the net
function drawNet() {
  for (let i = 0; i <= canvas.height; i += 15) {
    drawRect(net.x, net.y + i, net.width, net.height, net.color);
  }
}

// draw text
function drawText(text, x, y) {
  ctx.fillStyle = "#FFF";
  ctx.font = "75px fantasy";
  ctx.fillText(text, x, y);
}

// collision detection
function collision(b, p) {
  p.top = p.y;
  p.bottom = p.y + p.height;
  p.left = p.x;
  p.right = p.x + p.width;

  b.top = b.y - b.radius;
  b.bottom = b.y + b.radius;
  b.left = b.x - b.radius;
  b.right = b.x + b.radius;

  return (
    p.left < b.right && p.top < b.bottom && p.right > b.left && p.bottom > b.top
  );
}

// update function, the function that does all calculations
function update() {
  // change the score of players, if the ball goes to the left "ball.x<0" computer win, else if "ball.x > canvas.width" the user win
  if (ball.x - ball.radius < 0) {
    com.score++;
    comScore.play();
    resetBall();
  } else if (ball.x + ball.radius > canvas.width) {
    user.score++;
    userScore.play();
    resetBall();
  }

  // the ball has a velocity
  ball.x += ball.velocityX;
  ball.y += ball.velocityY;

  // computer plays for itself, and we must be able to beat it
  // simple AI
  com.y += (ball.y - (com.y + com.height / 2)) * 0.1;

  // when the ball collides with bottom and top walls we inverse the y velocity.
  if (ball.y - ball.radius < 0 || ball.y + ball.radius > canvas.height) {
    ball.velocityY = -ball.velocityY;
    wall.play();
  }

  // we check if the paddle hit the user or the com paddle
  let player = ball.x + ball.radius < canvas.width / 2 ? user : com;

  // if the ball hits a paddle
  if (collision(ball, player)) {
    // play sound
    hit.play();
    // we check where the ball hits the paddle
    let collidePoint = ball.y - (player.y + player.height / 2);
    // normalize the value of collidePoint, we need to get numbers between -1 and 1.
    // -player.height/2 < collide Point < player.height/2
    collidePoint = collidePoint / (player.height / 2);

    // when the ball hits the top of a paddle we want the ball, to take a -45degees angle
    // when the ball hits the center of the paddle we want the ball to take a 0degrees angle
    // when the ball hits the bottom of the paddle we want the ball to take a 45degrees
    // Math.PI/4 = 45degrees
    let angleRad = (Math.PI / 4) * collidePoint;

    // change the X and Y velocity direction
    let direction = ball.x + ball.radius < canvas.width / 2 ? 1 : -1;
    ball.velocityX = direction * ball.speed * Math.cos(angleRad);
    ball.velocityY = ball.speed * Math.sin(angleRad);

    // speed up the ball everytime a paddle hits it.
    ball.speed += 0.1;
  }
}

// render function, the function that does al the drawing
function render() {
  // clear the canvas
  drawRect(0, 0, canvas.width, canvas.height, "#000");

  // draw the user score to the left
  drawText(user.score, canvas.width / 4, canvas.height / 5);

  // draw the COM score to the right
  drawText(com.score, (3 * canvas.width) / 4, canvas.height / 5);

  // draw the net
  drawNet();

  // draw the user's paddle
  drawRect(user.x, user.y, user.width, user.height, user.color);

  // draw the COM's paddle
  drawRect(com.x, com.y, com.width, com.height, com.color);

  // draw the ball
  drawArc(ball.x, ball.y, ball.radius, ball.color);
}
function game() {
  update();
  render();
}
// number of frames per second
let framePerSecond = 50;

//call the game function 50 times every 1 Sec
let loop = setInterval(game, 1000 / framePerSecond);

You'll need an event listener on the user-speed textbox that changes the value of the global variable userSpeedInput when the user types something.您需要用户速度文本框上的事件侦听器,当用户键入内容时该事件侦听器会更改全局变量userSpeedInput的值。 Right now that variable is only set once, when the page first loads.现在,该变量仅在页面首次加载时设置一次。

document.getElementById("user-speed").addEventListener("change", (e) => {
  userSpeedInput = parseInt(e.target.value);
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM