「タンクウォーズ」ゲームをプレイしたことがありますか?
私は JavaScript + Canvas を使ってこのゲームをプログラミングしています (個人的な挑戦のため)。必要なのは、ゲームを開始するたびにそのランダムな緑の土地を生成するアルゴリズムですが、私は数学があまり得意ではないので、自分でやるな。
誰かにコードを教えてもらいたくありません。アルゴリズムのアイデアだけが欲しいのです。
ありがとう!
「タンクウォーズ」ゲームをプレイしたことがありますか?
私は JavaScript + Canvas を使ってこのゲームをプログラミングしています (個人的な挑戦のため)。必要なのは、ゲームを開始するたびにそのランダムな緑の土地を生成するアルゴリズムですが、私は数学があまり得意ではないので、自分でやるな。
誰かにコードを教えてもらいたくありません。アルゴリズムのアイデアだけが欲しいのです。
ありがとう!
(9セグメント)
(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
}
パーリン ノイズの生成を調べてください。これを優れた平滑化アルゴリズムと組み合わせることで、かなり優れた地形を生成でき、かなり高速です。コードのリファレンス バージョンがネットのどこかにあり、かなり有利なスタートを切ることができます。
うわー...ある時点で、私は戦車戦に完全にハマっていました。
あなたは学習の冒険をしているので...
context.globalCompositeOperation についても学ぶことができます。
このキャンバス操作により、実際の草の画像を取得し、それをゲームに合成できます。
drawImage(); の x/y を変更することで、草の外観をランダム化できます。
確かに、実際の草は、完成したゲームに含めるには気が散りすぎるかもしれませんが、合成について学ぶことは貴重な知識です。
...そして質問の+1:自分自身に挑戦してよかったです!
@DesertIvyが指摘したように、フラクタルなどの斬新で書かれたアルゴリズムが確かにあり、ライブラリもあるかもしれませんが、画像にあるものを生成したい場合は、かなり簡単です。ポイント間の曲線)。一度に正しくしようとせず、段階的に行うと簡単です。
leftmost.y = 0
ますslope = Math.random()-0.5;
。right.y = left.y + slope * (right.x-left.x);
、各 y: の後に勾配を更新しますslope += Math.random()-0.5;
。すべてがゲーム画面に収まる場合は、今のところ気にしないでください。mingeny
、maxgeny
) を見つけます (ポイント 4 で生成中にこれを追跡できます)。minscry
ゲーム画面 ( 、 )の最大値と最小値の y を選択します (maxscry
上から 4 番目、下から 4 番目と言います)。minscry
次に、生成された ys を と の間にまたがるように変換します。maxscry
すべての点について、 do を行いますapoint.y = minscry + (maxscry-minscry)/(maxgeny-mingeny)*(apoint.y-mingeny)
。curvemodifier
leftx と rightx の間のセクションの特定の x の y に追加します。円弧は円である必要はありません: 簡単に生成できる放物線または余弦をお勧めします: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)
.まず、ランダムな y (55,65 の間) のポイントが必要です。got x=0 したがって、これが緑の原点です。x1,y1 のままにします (x1 は常に 0)。
次に、30 から 40 の間のランダムな整数が必要です。これは x2 です。そして、y1 + 8 から y1 + 20 の範囲にあるランダムな y。
次に、同じ原理で x3 と y3 (式タイプ 1 と呼びましょう)
ここで、最初に -1 または 1 のいずれかの乱数を取得する必要があります。これは y4 の方向になります。したがって、y4 は y3 より高くなったり低くなったりする可能性があります。これは式タイプ 2 になります。
新しい y の最大値と最小値の y を保持する必要があります。それが交差する場合は逆になります -> これは補正タイプの式 3 になります。
Xn はボードの幅 >= まで増加し続けます。
日食の行に参加してください...そして、ウェブ検索が進むべき道のようです!
これを簡単にするために使用できるコード化されたライブラリがたくさんあると確信しています。しかし、これを自分でコーディングしようとしている場合、これが私の考えです。
他のすべてのものから地形を定義する必要があります。たとえば、環境のすべての部分がクラスターです。たとえば、ノード (ポイント) によって、これらのクラスターをどのように分離するかを定義する必要があります。
一連のポイントから多角形を作成できます。この多角形は、この場合は地形のように、任意のものにすることができます。
渡された画像にピークがあり、それらがノード (ポイント) であることを確認してください。環境の境界にもノードを定義することを忘れないでください。