【问题标题】:Make identical objects move independently in Javascript Canvas使相同的对象在 Javascript Canvas 中独立移动
【发布时间】:2016-10-02 12:03:14
【问题描述】:

所以我正在尝试制作一个简单的太空游戏。您将拥有一艘左右移动的船,并且小行星将在画布顶部上方以随机 X 位置和大小生成,它们将朝船下方移动。

如何在不同的位置创建小行星物体?就像一次在画布中存在多个,而不是将它们创建为具有单独变量的完全独立的对象?

这设置了我希望创建小行星的变量。

 var asteroids = {
size: Math.floor((Math.random() * 40) + 15),
startY: 100,
startX: Math.floor((Math.random() * canvas.width-200) + 200),
speed: 1
}

这是我用来画小行星的。 (它在随机 x 坐标处形成一个随机大小的六边形)

function drawasteroid() {
this.x = asteroids.startX;
this.y = 100;
this.size = asteroids.size;
ctx.fillStyle = "#FFFFFF";

ctx.beginPath();
ctx.moveTo(this.x,this.y-this.size*0.5);
ctx.lineTo(this.x+this.size*0.9,this.y);
ctx.lineTo(this.x+this.size*0.9,this.y+this.size*1);
ctx.lineTo(this.x,this.y+this.size*1.5);
ctx.lineTo(this.x-this.size*0.9,this.y+this.size*1);
ctx.lineTo(this.x-this.size*0.9,this.y);
ctx.fill(); 

}

我在这个 sn-p 中包含了我的所有代码。运行它后,您会看到我目前有一艘正在移动的船,并且小行星以随机大小和随机 x 坐标绘制。我只需要知道如何让小行星向下移动,同时创造其他也会向下移动的新小行星。

感谢您的所有帮助!我是 javascript 新手。

// JavaScript Document

////// Variables //////
var canvas = {width:300, height:500, fps:30};
var score = 0;

var player = {
	x:canvas.width/2,
	y:canvas.height-100,
	defaultSpeed: 5,
	speed: 10
	};
	
var asteroids = {
	size: Math.floor((Math.random() * 40) + 15),
	startY: 100,
	startX: Math.floor((Math.random() * canvas.width-200) + 200),
	speed: 1
}

var left = false;
var right = false;



////// Arrow keys //////

function onkeydown(e) {
		if(e.keyCode === 37) { 
			left = true;
		} 
		
		if(e.keyCode === 39) {
			right = true;	
		} 
}

function onkeyup(e) {
		if (e.keyCode === 37) { 
			left = false;
		} 
		
		if(e.keyCode === 39) {
			right = false;	
		} 
}
	

////// other functions //////


//function to clear canvas
function clearCanvas() {
	ctx.clearRect(0,0,canvas.width,canvas.height);
}

// draw the score in the upper left corner
function drawscore(score) {
	var score = 0;
	ctx.fillStyle = "#FFFFFF";
	ctx.fillText(score,50,50);
}

// Draw Player ship.
function ship(x,y) {
	var x = player.x;
	var y = player.y;
	ctx.fillStyle = "#FFFFFF";

	ctx.beginPath();
    ctx.moveTo(x,y);
    ctx.lineTo(x+15,y+50);
    ctx.lineTo(x-15,y+50);
    ctx.fill();
}

// move player ship.
function moveShip() {
	document.onkeydown = onkeydown;
	document.onkeyup = onkeyup;
	if (left === true && player.x > 50) {
		player.x -= player.speed;
	}
	if (right === true && player.x < canvas.width - 50) {
		player.x += player.speed;
	}
}


// Draw Asteroid
function drawasteroid() {
	this.x = asteroids.startX;
	this.y = 100;
	this.size = asteroids.size;
	ctx.fillStyle = "#FFFFFF";
	
	ctx.beginPath();
    ctx.moveTo(this.x,this.y-this.size*0.5);
    ctx.lineTo(this.x+this.size*0.9,this.y);
    ctx.lineTo(this.x+this.size*0.9,this.y+this.size*1);
	ctx.lineTo(this.x,this.y+this.size*1.5);
	ctx.lineTo(this.x-this.size*0.9,this.y+this.size*1);
	ctx.lineTo(this.x-this.size*0.9,this.y);
    ctx.fill();
		
}

// move Asteroid
function moveAsteroid() {
	//don't know how I should go about this.
}



// update
setInterval (update, 1000/canvas.fps);

function update() {
	
// test collisions and key inputs
	moveShip();
	
// redraw the next frame of the animation
	clearCanvas();
	drawasteroid();
	drawscore();
	ship();
}
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>My Game</title>   

<script src="game-functions.js"></script>

<!--
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js"></script>
-->
        
</head>

<body>

<canvas id="ctx" width="300" height="500" style="border: thin solid black; background-color: black;"></canvas>
<br>


<script>
////// Canvas setup //////
var ctx = document.getElementById("ctx").getContext("2d");


</script>

</body>
</html>

【问题讨论】:

  • 为什么不让它们分开放置在数组中的对象?这样你就可以遍历你的小行星数组,并在每次调用 setainterval 时移动每一个。一旦小行星离开画布,您可以设定条件从阵列中移除小行星。您还可以通过添加一个额外的小行星来指定最大的小行星,只有当数组是一定长度时。
  • 这是一个正确的方法吗?我认为最终会产生很多相同的代码,但变量名称不同。 (asteroid1, asteroid2, asteroid3, asteroid4, asteroid5)
  • 有没有办法做这样的事情,变量名称本身会因单独的小行星而改变?如果是小行星# 并且 # 将被每个新小行星的新数字替换?我知道它不会是#,但你明白我的意思吗?
  • 对我的答案的修改是否解决了您的问题?
  • 是的。我的意思是,我是初学者,所以我不完全了解如何正确使用数组。但我现在正朝着正确的方向前进。谢谢!

标签: javascript html canvas game-physics


【解决方案1】:

您想让小行星的创建动态化...所以为什么不设置一个 setInterval 以随机间隔调用,如下所示。您不需要为您创建的每个 Asteroids 对象单独声明。您可以在 setInterval 函数中声明一个临时的。这将使用相同的声明实例化多个不同的对象。当然,您需要将每个对象存储在某个位置,这正是数组的用途。

如果小行星不在画布上,您还必须确保在调用 moveAsteroid 函数时将小行星从阵列中移除。下面的 setInterval 函数应在窗口加载时调用,并与您的主要渲染 setInterval 函数一起存在。

您还必须稍微更改一下 moveAsteroid 函数,以便能够从数组中指向特定的 Asteroids 对象。您可以通过添加 Asteroids 对象作为函数的参数或通过使函数成为 Asteroids 类的属性并使用 this 来做到这一点。我在下面的例子中做了后者。

 var astArray = [];
 var manageAsteroidFrequency = 2000;


 var Asteroids {
      X: //something
      Y://something
      speed:1
      move: function() {
             this.X -= speed;
       }

   }


 var mainRenderingFunction = setInterval( function() {

      for (var i = astArray.length-1 ; i > -1; i --){
            if(astArray[i].Y < 0){
                 astArray.splice(i, 1)
             }else{
                 astArray[i].move;
              }
        }

  }, 40);


 var manageAsteroids = setInterval( function () {

       if (astArray.length < 4){
             var tmpAst = new Asteroids();
             astArray.push(tmpAst);
           }

       manageAsteroidFrequency = Math.floor(Math.random()*10000);
       }, manageAsteroidFrequency);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-28
    • 2021-06-15
    • 2019-03-25
    • 1970-01-01
    相关资源
    最近更新 更多