在画布中随机生成对象,不重复或重叠
Posted
技术标签:
【中文标题】在画布中随机生成对象,不重复或重叠【英文标题】:Randomly generate objects in canvas without duplicate or overlap 【发布时间】:2012-12-31 02:40:29 【问题描述】:如何在地图上生成对象,而不让它们占用相同的空间或在 html5 画布上重叠?
X 坐标在一定程度上是随机生成的。我想检查数组内部是否已经存在,以及之后的 20 个值(以考虑宽度),但没有运气。
var nrOfPlatforms = 14,
platforms = [],
platformWidth = 20,
platformHeight = 20;
var generatePlatforms = function()
var positiony = 0, type;
for (var i = 0; i < nrOfPlatforms; i++)
type = ~~(Math.random()*5);
if (type == 0) type = 1;
else type = 0;
var positionx = (Math.random() * 4000) + 500 - (points/100);
var duplicatetest = 21;
for (var d = 0; d < duplicatetest; d++)
var duplicate = $(jQuery.inArray((positionx + d), platforms));
if (duplicate > 0)
var duplicateconfirmed = true;
if (duplicateconfirmed)
var positionx = positionx + 20;
var duplicateconfirmed = false;
platforms[i] = new Platform(positionx,positiony,type);
();
我最初通过让它们生成在大约 4000 大的区域中来进行作弊修复,降低了几率,但我想随着游戏的进行增加难度,通过让它们看起来更在一起,使其更难。但随后它们重叠。
粗略的图片形式,我想要这个
....[]....[].....[]..[]..[][]...
不是这个
......[]...[[]]...[[]]....[]....
我希望这是有道理的。
作为参考,这里是数组检查和难度之前的代码,只是便宜的距离破解。
var nrOfPlatforms = 14,
platforms = [],
platformWidth = 20,
platformHeight = 20;
var generatePlatforms = function()
var position = 0, type;
for (var i = 0; i < nrOfPlatforms; i++)
type = ~~(Math.random()*5);
if (type == 0) type = 1;
else type = 0;
platforms[i] = new Platform((Math.random() * 4000) + 500,position,type);
();
编辑 1
经过一些调试,重复返回 [object Object] 而不是索引号,但不知道为什么
编辑 2
问题是对象在数组平台中,而x在数组对象中,那么我该如何再次搜索呢? ,这就是它之前失败的原因。 感谢 firebug 和 console.log(platforms);
platforms = [Object image=img, x=1128, y=260, more..., Object image=img, x=1640, y=260, more... etc
【问题讨论】:
对象的宽度是否可变? @JasonSperske 没有 20px 的固定宽度 您可以将它们映射到一个网格(将对象捕捉到 20 个像素增量),然后跟踪填充在 2d 散列对象中的内容。 @Shmiddty 我该怎么做? 【参考方案1】:您可以实现一个 while 循环,该循环尝试插入一个对象,如果它发生冲突,它会静默失败。然后添加一个计数器并在放置所需数量的成功对象后退出 while 循环。如果对象靠得很近,则此循环可能会运行更长的时间,因此您可能还想给它一个最长的寿命。或者你可以实现一个'是否甚至可以将 z 对象放在 x 和 y 的地图上'以防止它永远运行。
这是一个例子(demo):
//Fill an array with 20x20 points at random locations without overlap
var platforms = [],
platformSize = 20,
platformWidth = 200,
platformHeight = 200;
function generatePlatforms(k)
var placed = 0,
maxAttempts = k*10;
while(placed < k && maxAttempts > 0)
var x = Math.floor(Math.random()*platformWidth),
y = Math.floor(Math.random()*platformHeight),
available = true;
for(var point in platforms)
if(Math.abs(point.x-x) < platformSize && Math.abs(point.y-y) < platformSize)
available = false;
break;
if(available)
platforms.push(
x: x,
y: y
);
placed += 1;
maxAttempts -= 1;
generatePlatforms(14);
console.log(platforms);
【讨论】:
仍然存在检查它们是否碰撞或重叠的功能失败的问题,并且仍然放置它 @RudigerKidd 我添加了一些应该执行此操作的 javascript【参考方案2】:以下是实现网格捕捉哈希的方法:http://jsfiddle.net/tqFuy/1/
var can = document.getElementById("can"),
ctx = can.getContext('2d'),
wid = can.width,
hei = can.height,
numPlatforms = 14,
platWid = 20,
platHei = 20,
platforms = [],
hash = ;
for(var i = 0; i < numPlatforms; i++)
// get x/y values snapped to platform width/height increments
var posX = Math.floor(Math.random()*(wid-platWid)/platWid)*platWid,
posY = Math.floor(Math.random()*(hei-platHei)/platHei)*platHei;
while (hash[posX + 'x' + posY])
posX = Math.floor(Math.random()*wid/platWid)*platWid;
posY = Math.floor(Math.random()*hei/platHei)*platHei;
hash[posX + 'x' + posY] = 1;
platforms.push(new Platform(/* your arguments */));
请注意,我正在连接 x 和 y 值并将其用作哈希键。这是为了简化检查,并且只是一个可行的解决方案,因为我们将 x/y 坐标捕捉到特定的增量。如果我们不捕捉,碰撞检查会更加复杂。
对于大型集合(根据您的标准似乎不太可能),使用排除方法可能会更好:生成所有可能位置的数组,然后对于每个“平台”,从数组中随机选择一个项目,然后将其从数组中删除。这类似于你如何洗牌。
编辑 — 需要注意的一点是numPlatforms <= (wid*hei)/(platWid*platHei)
的计算结果必须为真,否则 while 循环将永远不会结束。
【讨论】:
我现在必须尝试一下,我最终想通了,但解决方案让它真的很慢。所以,让我们试一试。谢谢 @RudigerKidd 哈希几乎总是比在数组中搜索值更快。某些浏览器上的小数据集除外。【参考方案3】:我使用这段代码搜索数组中的对象,找到了另一个问题 (Searching for objects in JavaScript arrays) 的答案
function search(array, value)
var j, k;
for (j = 0; j < array.length; j++)
for (k in array[j])
if (array[j][k] === value) return j;
我最终还重写了一堆代码,以在其他地方加速并更好地回收平台。
它有效,但缺点是我的平台较少,因为它真的开始变慢了。最后这就是我想要的,但这样做已经不可行了。
var platforms = new Array();
var nrOfPlatforms = 7;
platformWidth = 20,
platformHeight = 20;
var positionx = 0;
var positiony = 0;
var arrayneedle = 0;
var duplicatetest = 21;
function search(array, value)
var j, k;
for (j = 0; j < array.length; j++)
for (k in array[j])
if (array[j][k] === value) return j;
function generatePlatforms(ind)
roughx = Math.round((Math.random() * 2000) + 500);
type = ~~(Math.random()*5);
if (type == 0) type = 1;
else type = 0;
var duplicate = false;
for (var d = 0; d < duplicatetest; d++)
arrayneedle = roughx + d;
var result = search(platforms, arrayneedle);
if (result >= 0)
duplicate = true;
if (duplicate = true)
positionx = roughx + 20;
if (duplicate = false)
positionx = roughx;
platforms[ind] = new Platform(positionx,positiony,type);
var generatedplatforms = function()
for (var i = 0; i < nrOfPlatforms; i++)
generatePlatforms(i);
;
();
【讨论】:
【参考方案4】:您使用大数据,生成所有可能性,将每个可能性存储在一个数组中,对数组进行洗牌, 修剪前 X 项,这是您的非启发式算法。
【讨论】:
以上是关于在画布中随机生成对象,不重复或重叠的主要内容,如果未能解决你的问题,请参考以下文章