我在下面有一些代码用于开始使用HTML5画布制作的蛇游戏。出于某种原因,我暂时用来表示我的蛇的红色圆圈正在不断地沿着鼠标移动的路径绘制。它以食物为起点。在浏览器中查看它,因为它很难描述。我想要的只是圆圈跟随鼠标并留下一条小路,它终止并且不会停留在画布上。我该怎么做呢提前谢谢!
<!doctype html>
<html>
<head>
<meta charset="UTF-8" />
<title>Snake 2.0</title>
</head>
<style>
</style>
<body>
<div>
<canvas id="canvas" width=500 height=500></canvas>
</div>
<script type="text/javascript">
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
makeFood();
function makeFood() {
foods = [];
for (var i = 0; i < 1; i++){
foods.push(new Food());
}
}
function Food() {
this.x = Math.random() * canvas.width;
this.y = Math.random() * canvas.height;
this.radius = 10;
}
function drawFood() {
for (var i = 0; i < 1; i++){
foods.push(new Food());
}
for (var i = 0; i < foods.length; i++){
var f = foods[i];
context.beginPath();
var grd = context.createRadialGradient(f.x, f.y, (f.radius - (f.radius - 1)), f.x + 1, f.y + 1, (f.radius));
grd.addColorStop(0, 'red');
grd.addColorStop(1, 'blue');
context.arc(f.x, f.y, f.radius, 0, 2 * Math.PI, true);
context.fillStyle = grd;
context.fill();
}
}
function makePower() {
powers = [];
for (var i = 0; i < 1; i++){
powers.push(new Power());
}
}
function Power() {
this.x = Math.random() * canvas.width;
this.y = Math.random() * canvas.height;
this.radius = 8;
}
function drawPower() {
for (var i = 0; i < powers.length; i++){
var p = powers[i];
context.beginPath();
var grd = context.createRadialGradient(p.x, p.y, (p.radius - (p.radius - 1)), p.x + 1, p.y + 1, (p.radius));
grd.addColorStop(0, 'green');
grd.addColorStop(1, 'yellow');
context.arc(p.x, p.y, p.radius, 0, 2 * Math.PI, true);
context.fillStyle = grd;
context.fill();
}
}
canvas.addEventListener("mousemove", function(event) {
move(event);
});
function move(e) {
context.fillStyle = "black";
context.fillRect(0, 0, canvas.width, canvas.height);
var a = e.clientX;
var b = e.clientY;
context.arc(a, b, 20, 0, 2 * Math.PI, true);
context.fillStyle = "red";
context.fill();
}
context.fillStyle = "black";
context.fillRect(0, 0, canvas.width, canvas.height);
var functions = [drawFood];
var timer = setInterval(function(){
drawFood();
}, 5000);
function stop() {
clearInterval(timer);
}
canvas.addEventListener("click", stop);
//timer = setInterval(start, 1000);
//timer = setInterval(start, 5000);
</script>
</body>
</html>
答案 0 :(得分:0)
您可以先添加“context.beginPath();”在你的“移动”功能中,在“context.arc(a,b,20,0,2 * Math.PI,true);”之前,在我的编辑器中的第102-103行。
function move(e) {
context.fillStyle = "black";
context.fillRect(0, 0, canvas.width, canvas.height);
var a = e.clientX;
var b = e.clientY;
context.beginPath();
context.arc(a, b, 20, 0, 2 * Math.PI, true);
context.fillStyle = "red";
context.fill();
}
答案 1 :(得分:0)
您应该将您移动的位置存储在一个数组中。然后一个新的计时器应该重新访问这些光盘,并在每次刻度时以更褪色的颜色重绘它们,直到光盘变黑。然后它应该从该数组中删除。
这是fiddle这样做。
代码中的更改从canvas.addEventListener("mousemove",...
开始,如下所示:
canvas.addEventListener("mousemove", function(event) {
// Replaced move function by drawDisc function,
// which needs coordinates and color intensity
drawDisc(event.clientX, event.clientY, 0xF);
});
// Array to keep track of previous positions, i.e. the trail
var trail = [];
function drawDisc(x, y, red) {
context.beginPath();
context.arc(x, y, 20, 0, 2 * Math.PI, true);
context.fillStyle = '#' + red.toString(16) + '00000';
context.fill();
// If disc is not completely faded out, push it in the trail list
if (red) {
trail.push({x: x, y: y, red: red});
}
}
// New function to regularly redraw the trail
function fadeTrail() {
var discs = trail.length;
// If there is only one disc in the trail, leave it as-is,
// it represents the current position.
if (discs > 1) {
for (var i = discs; i; i--) {
// take "oldest" disc out of the array:
disc = trail.shift();
// and draw it with a more faded color, unless it is
// the current disc, which keeps its color
drawDisc(disc.x, disc.y, disc.red - (i === 1 ? 0 : 1));
}
}
}
// New timer to fade the trail
var timerFade = setInterval(function(){
fadeTrail();
}, 10);
我认为评论会明确这是做什么的。请注意,光盘的颜色从0xF00000到0xE00000,0xD00000,...,0x000000。除当前光盘外,该光盘始终保持其0xF00000颜色。
答案 2 :(得分:0)
其他答案是正确的:
arc()
使用beginPath()
创建新路径,并避免context.fill()
将整体视为单个路径。但是,应该避免使用setTimeout
和setInterval
(甚至可以避免使用多个)。
现代浏览器支持requestAnimationFrame
计时方法,对于olders(基本上是IE9),您可以非常轻松地找到polyfills。它有很多优点,我不会在这里列举,阅读文档。
以下是代码的修改版本,它使用requestAnimationFrame
循环。
我还创建了两个屏幕外画布来更新您的foods
和powers
,这样他们就不会在每次抽奖时消失。两者都将在绘图功能中绘制。
我更改了mousemove处理程序,因此它只更新了跟踪数组,使绘图部分保留在绘制循环中。在每次调用时,它将设置一个moving
标志,让我们的绘图函数知道我们正在移动鼠标。否则,它将开始从数组中删除旧的跟踪弧。
var canvas = document.getElementById("canvas");
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
var context = canvas.getContext("2d");
// create other contexts (layer like) for your food and powers
var foodContext = canvas.cloneNode(true).getContext('2d');
var pwrContext = canvas.cloneNode(true).getContext('2d');
// a global to tell weither we are moving or not
var moving;
// a global to store our animation requests and to allow us to pause it
var raf;
// an array to store our trail position
var trail = [];
// here we can determine how much of the last position we'll keep at max (can then be updated if we ate some food)
var trailLength = 10;
// your array for the foods
var foods = [];
// a global to store the last time we drawn the food, no more setInterval
var lastDrawnFood = 0;
// start the game
draw();
function makeFood() {
foods.push(new Food());
}
function Food() {
this.x = Math.random() * canvas.width;
this.y = Math.random() * canvas.height;
this.radius = 10;
}
function drawFood() {
// clear the food Canvas (this could be done only if we ate some, avoiding the loop through all our foods at each call of this method)
foodContext.clearRect(0, 0, canvas.width, canvas.height);
foods.push(new Food());
for (var i = 0; i < foods.length; i++) {
var f = foods[i];
// draw on the food context
foodContext.beginPath();
foodContext.arc(f.x, f.y, f.radius, 0, 2 * Math.PI, true);
var foodGrd = foodContext.createRadialGradient(f.x, f.y, (f.radius - (f.radius - 1)), f.x + 1, f.y + 1, (f.radius));
foodGrd.addColorStop(0, 'red');
foodGrd.addColorStop(1, 'blue');
foodContext.fillStyle = foodGrd;
foodContext.fill();
}
}
// I'll let you update this one
function makePower() {
powers = [];
for (var i = 0; i < 1; i++) {
powers.push(new Power());
}
}
function Power() {
this.x = Math.random() * canvas.width;
this.y = Math.random() * canvas.height;
this.radius = 8;
}
function drawPower() {
pwrContext.clearRect(0, 0, canvas.width, canvas.height);
for (var i = 0; i < powers.length; i++) {
var p = powers[i];
var pwrGrd = pwrContext.createRadialGradient(p.x, p.y, (p.radius - (p.radius - 1)), p.x + 1, p.y + 1, (p.radius));
pwrGrd.addColorStop(0, 'green');
pwrGrd.addColorStop(1, 'yellow');
pwrContext.beginPath();
pwrContext.arc(p.x, p.y, p.radius, 0, 2 * Math.PI, true);
pwrContext.fillStyle = pwrGrd;
pwrContext.fill();
}
}
// the event object is already passed, no need for an anonymous function here
canvas.addEventListener("mousemove", move);
function move(e) {
// we paused the game, don't update our position
if (!raf) return;
// update the snake
var a = e.clientX - canvas.offsetLeft;
var b = e.clientY - canvas.offsetTop;
trail.splice(0, 0, {
x: a,
y: b
});
// tell our draw function that we moved
moving = true;
}
function draw(time) {
// our food timer
if (time - lastDrawnFood > 5000) {
lastDrawnFood = time;
drawFood();
}
// clear the canvas
context.fillStyle = "black";
context.fillRect(0, 0, canvas.width, canvas.height);
// draw the food
context.drawImage(foodContext.canvas, 0, 0);
// draw the power
context.drawImage(pwrContext.canvas, 0, 0);
//draw the snake
for (var i = 0; i < trail.length; i++) {
// decrease the opacity
opacity = 1 - (i / trail.length);
context.fillStyle = "rgba(255, 0,0," + opacity + ")";
// don't forget to create a new Path for each circle
context.beginPath();
context.arc(trail[i].x, trail[i].y, 20, 0, 2 * Math.PI, true);
context.fill();
}
// if we're not moving or if our trail is too long
if ((!moving || trail.length > trailLength) && trail.length > 1)
// remove the oldest trail circle
trail.pop();
// we're not moving anymore
moving = false;
// update the animation request
raf = requestAnimationFrame(draw);
}
context.fillStyle = "black";
context.fillRect(0, 0, canvas.width, canvas.height);
function toggleStop() {
if (!raf) {
// restart the animation
raf = window.requestAnimationFrame(draw);
} else {
// cancel the next call
cancelAnimationFrame(raf);
raf = 0;
}
}
canvas.addEventListener("click", toggleStop);
html, body{margin:0;}
<canvas id="canvas" width=500 height=500></canvas>