我正在使用2D breakout tutorial from MDN学习画布,并且有一个练习:尝试每次击球时将球的颜色更改为随机颜色。
在拉出球之前,我先检查球是否在墙内。如果它碰到球,首先我会生成一个随机的十六进制颜色,然后用该颜色绘制球。
但它有时仅适用。我已经记录了fillStyle
对象的ctx
属性,但是有时它不会将值更改为新颜色。
/* Reference to Canvas */
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
/* Start Ball Position */
let x = canvas.width / 2;
let y = canvas.height - 30;
/* Move Ball */
let dx = 2;
let dy = -2;
/* Ball Dimensions */
let ballRadius = 10;
/* Ball Color */
let ballColor = "#0095DD";
/* Draw Ball */
function drawBall() {
ctx.beginPath();
ctx.arc(x, y, ballRadius, 0, Math.PI * 2);
ctx.fillStyle = ballColor;
ctx.fill();
ctx.closePath();
x += dx;
y += dy;
}
/* Update Canvas */
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
bouncing();
drawBall();
}
/**
* If the ball goes outside the boundaries,
* change the direction to the opposite
*/
function bouncing() {
if(x + dx < ballRadius || x + dx > canvas.width - ballRadius) {
dx = -dx;
randomColor();
}
if(y + dy < ballRadius || y + dy > canvas.height - ballRadius) {
dy = -dy;
randomColor();
}
}
/* Change the ball color to a random hex value */
function randomColor() {
const hexColor = ['#'];
const letters = ['A', 'B', 'C', 'D', 'E', 'F'];
for(let digit = 0; digit < 6; digit++) {
let value = Math.floor(Math.random() * 16);
if(value > 9) {
value = letters[value - 9];
}
hexColor.push(value);
}
ballColor = hexColor.join('');
}
setInterval(draw, 10);
html {
box-sizing: border-box;
}
*, *::before, *::after {
box-sizing: inherit;
padding: 0;
margin: 0;
}
canvas {
background: #eee;
display: block;
margin: 0 auto;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>2D breakout game</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<canvas id="myCanvas" width="480" height="170"></canvas>
<script src="script.js"></script>
</body>
</html>
答案 0 :(得分:0)
问题出在value = letters[value - 9];
行中。这应该是value = letters[value - 10];
这是因为您想要的映射是:
10 -> A (letters[0])
11 -> B (letters[1])
12 -> C (letters[2])
13 -> D (letters[3])
14 -> E (letters[4])
15 -> F (letters[5])
所以您需要减去10而不是9。
答案 1 :(得分:-2)
您的代码运行正常,每次球反弹时都会调用函数randomColor
,但是在颜色生成逻辑中,您可以获得无效的值,例如#
,#A
或#AB
可以轻松解决,将* 16
更改为* 15
即可解决。
但还要注意,有时您的随机颜色非常接近前一种颜色,因此看起来好像没有变化,但实际上却发生了变化,这是我相信大多数时候都可以看到的颜色。 / p>
您可以想出一个“智能随机”功能,该功能可以记住最近的2或3种颜色,并防止下一种与这些颜色相似,有关更多详细信息,如何比较颜色看起来是此问题的答案:
How to compare two colors for similarity/difference
在这里,我将您的randomColor的逻辑更改为包括色差逻辑,现在,下一个颜色将真正显示与前一个颜色的对比度
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
ctx.font = "Bold 30px courier new";
let x = y = 40
let dx = dy = 2;
let ballRadius = 40;
let ballColor = "#0095DD";
/* Change the ball color to a random hex value */
function randomColor() {
const hexColor = ['#'];
const letters = ['A', 'B', 'C', 'D', 'E', 'F'];
for(let digit = 0; digit < 6; digit++) {
let value = Math.floor(Math.random() * 15);
if(value > 9) {
value = letters[value - 9];
}
hexColor.push(value);
}
if (colorDif(ballColor, hexColor.join('')) > 50)
ballColor = hexColor.join('');
else
randomColor();
}
function colorDif(color1, color2) {
if (color1 == color2) return 0;
function squaredDelta(v1, v2) {
return Math.pow(v1 - v2, 2);
}
function hexToRgb(hex) {
var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
return result ? {
r: parseInt(result[1], 16),
g: parseInt(result[2], 16),
b: parseInt(result[3], 16)
} : null;
}
var sum = 0;
var c1 = hexToRgb(color1);
var c2 = hexToRgb(color2);
sum += squaredDelta(c1.r, c2.r);
sum += squaredDelta(c1.g, c2.g);
sum += squaredDelta(c1.b, c2.b);
var conversionIndex = 19.5075;
return Math.sqrt(sum / conversionIndex);
};
function drawBall() {
ctx.beginPath();
ctx.fillText(ballColor,10,50);
ctx.fillStyle = ballColor;
ctx.arc(x, y, ballRadius, 0, Math.PI * 2);
ctx.fill();
x += dx; y += dy;
}
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
bouncing();
drawBall();
}
function bouncing() {
if(x + dx < ballRadius || x + dx > canvas.width - ballRadius) {
dx = -dx; randomColor();
}
if(y + dy < ballRadius || y + dy > canvas.height - ballRadius) {
dy = -dy; randomColor();
}
}
setInterval(draw, 10);
*, *::before, *::after {margin: 0; }
<canvas id="myCanvas" width="480" height="170"></canvas>