你有没有玩过“坦克大战”游戏?
我正在用JavaScript + Canvas编程这个游戏(用于个人挑战),我需要的是每次开始游戏时生成随机绿地的算法,但我不太擅长数学,所以我不能自己做。
我不希望有人给我代码,我只想要算法的想法。
谢谢!
答案 0 :(得分:5)
(9段)
<强> Fiddle demo 强>
(7段)
主要生成函数如下所示:
var numOfSegments = 9; // split horizontal space
var segment = canvas.width / numOfSegments; // calc width of each segment
var points = [], calcedPoints;
var variations = 0.22; // adjust this: lower = less variations
var i;
//produce some random heights across the canvas
for(i=0; i < numOfSegments + 1; i++) {
points.push(segment * i);
points.push(canvas.height / 2.8 + canvas.height * variations * Math.random());
}
//render the landscape
ctx.beginPath();
ctx.moveTo(canvas.width, canvas.height);
ctx.lineTo(0, canvas.height);
calcedPoints = ctx.curve(points); // see below
ctx.closePath();
ctx.fillStyle = 'green';
ctx.fill();
curve()
函数是一个单独的函数,它生成一个基数样条曲线。在这里,您可以修改它以存储张力值以产生更多峰值。您还可以使用生成的点作为坦克移动的位置和角度的基础。
基数样条函数:
CanvasRenderingContext2D.prototype.curve = function(pts, tension, numOfSegments) {
tension = (tension != 'undefined') ? tension : 0.5;
numOfSegments = numOfSegments ? numOfSegments : 16;
var _pts = [], res = [], t, i, l, r = 0,
x, y, t1x, t2x, t1y, t2y,
c1, c2, c3, c4, st, st2, st3, st23, st32;
_pts = pts.concat();
_pts.unshift(pts[1]);
_pts.unshift(pts[0]);
_pts.push(pts[pts.length - 2]);
_pts.push(pts[pts.length - 1]);
l = (_pts.length - 4);
for (i = 2; i < l; i+=2) {
//overrides and modifies tension for each segment.
tension = 1 * Math.random() - 0.3;
for (t = 0; t <= numOfSegments; t++) {
t1x = (_pts[i+2] - _pts[i-2]) * tension;
t2x = (_pts[i+4] - _pts[i]) * tension;
t1y = (_pts[i+3] - _pts[i-1]) * tension;
t2y = (_pts[i+5] - _pts[i+1]) * tension;
st = t / numOfSegments;
st2 = st * st;
st3 = st2 * st;
st23 = st3 * 2;
st32 = st2 * 3;
c1 = st23 - st32 + 1;
c2 = -(st23) + st32;
c3 = st3 - 2 * st2 + st;
c4 = st3 - st2;
x = c1 * _pts[i] + c2 * _pts[i+2] + c3 * t1x + c4 * t2x;
y = c1 * _pts[i+1] + c2 * _pts[i+3] + c3 * t1y + c4 * t2y;
res[r++] = x;
res[r++] = y;
} //for t
} //for i
l = res.length;
for(i=0;i<l;i+=2) this.lineTo(res[i], res[i+1]);
return res; //return calculated points
}
答案 1 :(得分:3)
研究perlin噪声的产生,结合良好的平滑算法可以产生一些非常好的地形,并且相当快。有一个参考版本的代码在网络上踢,这应该为你提供一个相当沉重的headstart
答案 2 :(得分:1)
首先你需要一个随机y点(在555之间);得到x = 0 所以这是绿色的原点,让它保持为x1,y1(x1始终为0)。
然后你需要一个介于30到40之间的随机整数。这是x2。并且随机y在y1 + 8到y1 + 20的范围内。
然后x3和y3的原理相同(我们称之为公式类型1)
现在你需要首先得到一个随机的-1或1,这将是y4的方向。所以y4可以高于y3或更低......这将是公式类型2。
你需要为一个新的y保持最大和最小y,如果它越过那个,那么走另一条路 - &gt;这将是一个修正类型公式3。
Xn一直在增加,直到它的&gt; =板的宽度。
加入日食中的线条......看起来像网络搜索是要走的路!
答案 3 :(得分:1)
我确信您可以使用许多编码库来简化这一过程。但如果你想自己编写代码,这就是我的想法。
您需要从其他所有内容定义地形。因此,您的环境的每个部分都是一个集群。您需要定义如何按节点(点)分隔这些集群。
你可以从一系列点创建一个多边形,这个多边形可以成为你想要的任何东西,在这种情况下是地形。
在您传递的图像上看到,有峰值,那些是节点(点)。请记住在环境的边界上定义节点。
答案 4 :(得分:1)
肯定有一种新颖的书面算法,无论是@DesertIvy指出的分形还是其他,也许还有库,但是如果你想生成图像中的内容,它可以非常简单,因为它是点之间只有(稍微弯曲)的线条。如果你分阶段进行,不要一次尝试正确,这很容易:
leftmost.y = 0
,slope = Math.random()-0.5;
开始。right.y = left.y + slope * (right.x-left.x);
开始生成每个下一个未定义的y,并在每个y后更新斜率:slope += Math.random()-0.5;
。如果一切都适合游戏画面,请不要打扰。mingeny
,maxgeny
)(您可以在第4点生成时跟踪它)。选择游戏界面中最大和最小y的位置(minscry
,maxscry
)(比如在前四分之一和最下四分之一)。然后转换生成的ys,使其跨越minscry
和maxscry
:对于每个点,执行apoint.y = minscry + (maxscry-minscry)/(maxgeny-mingeny)*(apoint.y-mingeny)
。curvemodifier
添加到y中,用于leftx和rightx之间的任何特定x。弧不必是一个圆圈:我建议使用易于生成的抛物线或余弦:var middle = (left.x+right.x)/2; var excess = (x-left)/(middle-left);
然后var curvemodifier = curviness * (1-excess*excess);
或var curvemodifier = curviness * Math.cos(Math.PI/2*excess)
。答案 5 :(得分:1)
因为你正在学习冒险......
您可能还会了解context.globalCompositeOperation。
此画布操作可让您抓取实际草的图像并将其合成到游戏中。
您可以通过更改drawImage();
的x / y来随机化草的外观是的,实际的草可能太过分散注意力,无法包含在你完成的游戏中,但学习合成将是宝贵的知识。
...和问题+1:对你挑战自己有好处!