【问题标题】:JavaScript + Canvas Moving ObjectJavaScript + Canvas 移动对象
【发布时间】:2016-05-20 03:25:12
【问题描述】:

我正在尝试在 Canvas 中制作乒乓球游戏。我想我会先让球穿过街道。问题是当我循环绘制函数时,它变成一条线,而不是每个新位置的球。 (见下面的截图。)

我认为清除画布然后重新绘制所有内容可以解决问题,但显然不是。

这是我的代码:

HTML:

<!doctype html>
<html lang="sv">
    <head>
        <meta charset="utf-8" />
        <link rel="stylesheet" href="style.css">
        <title>Super Pong!</title>
        <script type="text/javascript" src="superPong.js"></script>
    </head>

    <body>
        <nav>
            <ul id="navlist">
                <li><a href="#">Button 1</a></li>
                <li><a href="#">Button 2</a></li>
                <li><a href="#">Button 3</a></li>
                <li><a href="#">Button 4</a></li>
            </ul>
        </nav>
        <div id="content">
            <canvas width="1000" height="600">Your browser does not support HTML5 Canvas</canvas>
        </div>
    </body>
</html>

CSS:

body {
    background-color: #E93D19;
    color: #341711;
    font-family: "Lucida Sans Unicode", "Lucida Grande", sans-serif;
    font-size: 2vw;
}

#content {
    text-align: center;
    padding-top: 3%;
}

canvas {
    background-color: white;
}

nav {
    height: 100px;
    width: 100%;
    text-align: center;
    font-size: 3vw;
}

#navlist {
    background-color: #FD851D;
    list-style-type: none;
    margin: 0;
    overflow: hidden;
    padding: 0;
    transform: translateY(10%);
}

#navlist li {
    display: inline;
}

#navlist a {
    color: #C91D09;
    text-decoration: none;
}

#navlist a:hover {
    background-color: #C91D09;
    color: #FD851D;
}

JavaScript:

window.addEventListener("load", eventWindowLoaded, false);

function eventWindowLoaded(){
    var canvas=document.querySelector("canvas");
    var ctx=canvas.getContext("2d");
    var canWidth=canvas.width;
    var canHeight=canvas.height;
    var pi=Math.PI;
    var timer=null;
    var ms=16;

    var gameBall={
        size:30,
        positionX:0,
        positionY:0,
        color:"#FFF",

        set setSize(newSize){
            this.size=newSize;
        },
        set setPosX(posX){
            this.positionX=posX;
        },
        set setPosY(posY){
            this.positionY=posY;
        },
        set setColor(newColor){
            this.color=newColor;
        },
        get getSize(){
            return this.size;
        },
        get getPosX(){
            return this.positionX;
        },
        get getPosY(){
            return this.positionY;
        },
        get getColor(){
            return this.color;
        }
    }

    function clearCanvas(){
        ctx.clearRect(0,0,canWidth,canHeight);
    }

    function drawBackground(){
        ctx.fillStyle="#000";
        ctx.fillRect(0,0,canWidth,canHeight);
    }

    function drawBall(){
        ctx.save();
        var posX=gameBall.getPosX;
        var posY=gameBall.getPosY;
        var size=gameBall.getSize;
        ctx.fillStyle=gameBall.getColor;
        ctx.arc(posX,posY,size,0,2*pi,true);
        ctx.fill();
        ctx.restore();
    }

    function updateBall(){
        //clearCanvas();
        //drawBackground();
        gameBall.setPosX=gameBall.getPosX+3;
        gameBall.setPosY=gameBall.getPosY+3;
        drawBall();
    }

    gameBall.setPosX=100;
    gameBall.setPosY=100;
    drawBackground();

    timer=setInterval(updateBall, ms);
}

【问题讨论】:

  • 我会建议在每次更新时清除画布,然后再绘制新位置等。我看到你的 updateBall 函数中有这个,但它似乎被注释掉了。我说它没用对吗?
  • 目前被注释掉的原因是我尝试了几种不同的解决方案(例如“ctx.save() 和 ctx.restore()”)。遗憾的是两者都不起作用。
  • 我创建了一个小提琴(代码略有更新,但问题仍然存在)jsfiddle.net/Q5HDu/288
  • @Phrosen。在处理了 2 个问题后,我添加了一个答案,显示了您的 Fiddle 的工作版本。祝你的项目好运!

标签: javascript css html canvas


【解决方案1】:

以下是您的 Fiddle 的工作版本。针对以下 2 个问题对其进行了重构:

  • 您之前的球仍然存在,因为 Canvas 不允许重新定位现有的球图纸。 .save & .restore 命令只是保存和恢复上下文属性——它们不保存和恢复画布上的绘图。相反,您必须擦除画布并将球重新绘制到新位置。所以 (1) drawBackground, (2) update & (3) drawBall in updateBall 是在画布上“移动”的正确方式。

  • 每次绘制context.arc(球)时都必须调用context.beginPath。如果没有,所有以前版本的 .arc 命令都将被重绘。

function eventWindowLoaded(){
	var canvas=document.querySelector("canvas");
	var ctx=canvas.getContext("2d");
	var canWidth=canvas.width;
	var canHeight=canvas.height;
	var pi=Math.PI;
	var timer=null;
	var ms=1000/60*1;

	var gameBall={
		size:30,
		positionX:0,
		positionY:0,
		color:"#FFF",

		set setSize(newSize){
			this.size=newSize;
		},
		set setPosX(posX){
			this.positionX=posX;
		},
		set setPosY(posY){
			this.positionY=posY;
		},
		set setColor(newColor){
			this.color=newColor;
		},
		get getSize(){
			return this.size;
		},
		get getPosX(){
			return this.positionX;
		},
		get getPosY(){
			return this.positionY;
		},
		get getColor(){
			return this.color;
		}
	}

	function clearCanvas(){
		ctx.clearRect(0,0,canWidth,canHeight);
	}

	function drawBall(){
		ctx.save();
		var posX=gameBall.getPosX;
		var posY=gameBall.getPosY;
		var size=gameBall.getSize;
		ctx.fillStyle=gameBall.getColor;
    ctx.beginPath();
		ctx.arc(posX,posY,size,0,2*pi,true);
		ctx.fill();
		ctx.restore();
	}

	function updateBall(){
		//clearCanvas();
		gameBall.setPosX=gameBall.getPosX+3;
		gameBall.setPosY=gameBall.getPosY+3;
    ctx.fillStyle='black';
    ctx.fillRect(0,0,canvas.width,canvas.height);
		drawBall();
	}

	gameBall.setPosX=35;
	gameBall.setPosY=35;

	timer=setInterval(updateBall, ms);
}

eventWindowLoaded();
body {
	background-color: #E93D19;
	color: #341711;
	font-family: "Lucida Sans Unicode", "Lucida Grande", sans-serif;
	font-size: 2vw;
}

#content {
	text-align: center;
	padding-top: 3%;
}

canvas {
	background-color: black;
}

nav {
	height: 100px;
	width: 100%;
	text-align: center;
	font-size: 3vw;
}

#navlist {
	background-color: #FD851D;
	list-style-type: none;
	margin: 0;
	overflow: hidden;
	padding: 0;
	transform: translateY(10%);
}

#navlist li {
	display: inline;
}

#navlist a {
	color: #C91D09;
	text-decoration: none;
}

#navlist a:hover {
	background-color: #C91D09;
	color: #FD851D;
}
<body>
        <nav>
            <ul id="navlist">
                <li><a href="#">Button 1</a></li>
                <li><a href="#">Button 2</a></li>
                <li><a href="#">Button 3</a></li>
                <li><a href="#">Button 4</a></li>
            </ul>
        </nav>
        <div id="content">
            <canvas width="600" height="400">Your browser does not support HTML5 Canvas</canvas>
        </div>
    </body>

【讨论】:

  • 但是每次更新都需要做很多工作,就像我们为了清除早期版本的球而做的很多工作一样。我尝试创建一个与背景颜色相同的球,但颜色与背景不匹配。有没有办法在不重新构建整个画布的情况下处理?
【解决方案2】:

每次重绘帧时都需要清除画布。

在绘制路径时,您需要确保每帧都创建一个新路径,而不是添加到当前路径。这通常通过调用ctx.beginPath() 来清除上下文的当前路径来完成。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2021-06-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-10
  • 1970-01-01
  • 2021-09-11
相关资源
最近更新 更多