我在画布上创建了许多小点,在创建过程中,它会获取它们的x,y坐标和半径,以供以后用于生成的碰撞函数。这导致页面变得无响应,即使我摆脱了它的间隔。我认为在无响应之前,要处理的函数时间太长。任何帮助将非常感激。这是与我的问题有关的代码。
var foodX=[]; // array for the x coordinate of the points
var foodY=[]; // array for the y coordinate of the points
var foodR=[]; // array for the radius of the points
var points=[]; //array to store the variable used to create the points for later deletion
function drawFood() { //draws all the points on my canvas
for (var food=0; food<10000; food++) { //creates 10000 points
var foodPosX=randInt(0,10000); //create a random x coordinate between 0 and 10000 on the canvas
var foodPosY=randInt(0,10000); //create a random y coordinate between 0 and 10000 on the canvas
var r=randInt(3,5) //create a random radius create a random radius between 3 and 5
ctx.beginPath();
var point=ctx.arc(foodPosX, foodPosY, r, 0, 2*Math.PI); //this variable draws each point onto the canvas
ctx.fillStyle= colors[randInt(0,7)]; // uses an array I have with different colors so I can draw different colored points randomly
ctx.fill();
ctx.closePath();
foodX[food]=foodPosX; //stores my x coordinate in an array for the point currently being created
foodY[food]=foodPosY; //stores my y coordinate in an array for the point currently being created
foodR[food]=r; //stores the radius of the point being created
points[food]=point; //stores the variable creating the point so it can be deleted when the players collides with it
}
}
function checkCollision() {
for (var i=foodX.length-1; i<foodX.length; i--) { //loop through the array backwards to check for collisions
var fXD=Math.abs(player.pX-foodX[i]); //calculates the distance between the players x coordinate and the points x coordinate
var fYD=Math.abs(player.pY-foodY[i]); //calculates the distance between the players y coordinate and the points y coordinate
var rSum=circR+foodR[i]; //adds the radius's together for the player's radius and the foods radius
if (fXD<=rSum && fYD<=rSum) { //checks if the player is currently touching the point being checked
foodX.splice(i,1); //deletes the points x coordinate from array
foodY.splice(i, 1); //deletes the points y coordinate from array
foodR.splice(i, 1); //deletes the points radius from array
points.splice(i, 1); //deletes the point the was just collided with
eatFood(); //function for when the player eats the point
}
}
}
function randInt(min, max) { //This function creates a random integer between the selected numbers
min=Math.ceil(min);
max=Math.floor(max);
return Math.floor(Math.random()*(max-min))+min;
}
我试图使其简短,以至于抱歉,如果太多或太少。我正在尝试创建一个类似于agar.io的游戏,除了它将只是一个脱机的单人游戏版本。
答案 0 :(得分:4)
我邀请您考虑学习有关 Functional Programming 范例的更多信息。 几年前,我是一名游戏开发人员,发现在FP中进行思考可以极大地清理代码,并帮助我更好地概念化游戏对象。
下面是用FP样式编写的部分代码解决方案;我尝试表达的主要思想是
代码如下:
// Assuming the ff:
// 1. an object 'ctx' exists that knows how to draw stuff
// 2. an array 'colors' exists and contains colors you have
const ctx = document.createElement('canvas').getContext('2d')
const colors = ['blue','red','yellow','black','silver','gray','navy','aqua']
// function "newRandomFood" returns a food object whose properties are randomized
function newRandomFood() {
return {
x: randInt(0,10000),
y: randInt(0,10000),
r: randInt(3,5),
color: colors[randInt(0,7)] // uses an array I have with different colors so I can draw different colored points randomly
}
}
// function "drawFood" draws given food object to canvas as a path
function drawFood(food) {
ctx.beginPath();
ctx.arc(food.x, food.y, food.r, 0, 2*Math.PI); //this variable draws each point onto the canvas. Method doesn't return anything
ctx.fillStyle = food.color;
ctx.fill();
ctx.closePath();
}
// function "randInt" creates a random integer between the selected numbers
function randInt(min, max) {
min=Math.ceil(min);
max=Math.floor(max);
return Math.floor(Math.random()*(max-min))+min;
}
/* generate your foodstuffs */
const foods = Array(1000) // create an array with 1000 elements
.fill('') // fill each element with anything so iteration won't skip
.map(_ => newRandomFood()) // fill each element with a random food item
console.log(foods) // display all the food objects you have
foods.map(food => // for every food item...
drawFood(food)) // ...draw that food
希望这会有所帮助。 干杯,
答案 1 :(得分:1)
绘制很多点时,您需要对如何管理它们很聪明。
绘制10000弧并将其填充10000次是消耗性的。而是尝试调用实际光栅化尽可能小的光栅的上下文方法,例如通过将同一颜色的所有弧合并到单个子路径中。 就性能而言,最好的方法甚至是按颜色对这些点进行排序,但是通常看起来很奇怪。
对于碰撞检测,当前正在每次检查每个点。取而代之的是,将点打包到每个 n 个单元格每个 n 个网格中。然后在您的checkCollision中,仅检查该单元格中的点(很好,您还将检查相邻的点)。 这样,您将避免在每次检查时都检查场景中的所有点。
从该网格中获得的好处是,您还可以检查某些点是否确实被其他点隐藏,从而可以被绘图功能丢弃。
对于您来说,这是一个非常粗糙的起点,其中图形将在一个子路径中打包共享相同颜色的连续弧,并将它们打包在碰撞函数使用的网格中。
var colors = generateColors(7);
canvas.width = canvas.height = 2000;
var ctx = canvas.getContext('2d');
var grid = generateGrid(100, 100);
var points = generatePoints(10000);
var dirty = true; // a flag to know when we need to redraw
points.forEach(putInGrid);
// ToDo: mark hidden points
canvas.addEventListener('mousemove', onmousemove);
anim();
function generateColors(nb) {
var list = [];
for(var i = 0; i<nb; i++) {
list.push(randColor());
}
return list;
}
function randColor() {
return '#'+(Math.random()*0xFFFFFF|0).toString(16);
}
function generateGrid(width, height) {
var grid = [];
for(var i = 0; i<width*height; i++) {
grid.push([]);
}
grid.width = width;
grid.height = height;
return grid;
}
function generatePoints(nb) {
var list = [];
for(var i=0; i<nb; i++) {
list.push(new Point());
}
return list;
}
function Point() {
this.x = Math.random() * canvas.width;
this.y = Math.random() * canvas.height;
this.rad = Math.random() * 10 + 2;
this.color = colors[Math.random() * colors.length | 0];
}
function putInGrid(point, i) {
var index = getCellIndex(point.x, point.y);
grid[index].push(point);
}
function getCellIndex(x, y) {
if(x > canvas.width - 1) x = canvas.width - 1;
if(y > canvas.height - 1) y = canvas.height - 1;
var ratio_x = grid.width/canvas.width;
var ratio_y = grid.height/canvas.height;
var norm_y = Math.floor(y * ratio_y);
var norm_x = Math.floor(x * ratio_x);
return (norm_y * grid.width) + norm_x;
}
function draw() {
ctx.clearRect(0,0,canvas.width, canvas.height);
var point = points[0];
ctx.fillStyle = point.color;
ctx.beginPath();
for(var i=0; i<points.length; i++) {
point = points[i];
if(point.color !== ctx.fillStyle) {
ctx.fill();
ctx.fillStyle = point.color;
ctx.beginPath();
}
ctx.moveTo(point.x + point.rad, point.y);
ctx.arc(point.x, point.y, point.rad, 0, Math.PI*2);
}
ctx.fill();
}
function checkCollision(x, y) {
// ToDo: loop through adjacent cells too
var index = getCellIndex(x, y);
var cell = grid[index];
if(cell) {
cell.forEach(checkPointCollision);
}
function checkPointCollision(point, pt_index) {
if(Math.hypot(x - point.x, y - point.y) <= point.rad) {
cell.splice(pt_index, 1);
var newPoint = new Point();
grid[getCellIndex(newPoint.x, newPoint.y)]
.push(newPoint);
points.splice(points.indexOf(point), 1, newPoint);
dirty = true;
}
}
}
function onmousemove(e) {
var rect = canvas.getBoundingClientRect();
checkCollision(e.clientX - rect.left, e.clientY - rect.top);
}
function anim() {
if(dirty)
draw();
modified = false;
requestAnimationFrame(anim);
}
<canvas id="canvas"></canvas>