...省略... var win = 0; var clr = 600; var numoni = 2; var posme; var orime; var posoni = ["true,4,1,-15,0,-25", "true,4,1,15,0,-25"]; var orioni = ["true,4,3.14,0,1,0", "true,4,3.14,0,1,0"]; var live = [true, false, false, false] var thnk; ...省略... function moveobj(wa, wpyr) { //メインループ ...省略... //敵行動 for(thnk = 0; thnk < numoni; thnk++) { if(!live[thnk]) continue; var tgt = thinkOni(); moveOni(tgt, true, 0); oldtgt[thnk] = tgt; } //体つくり genBody(0); for(thnk = 0; thnk < numoni; thnk++) { if(!live[thnk]) continue; genBody(thnk + 1); } viewp(); //終了条件 if(clr <= num) gameclear(); else if(bound(0)) gameover(); else if(numoni){ for(thnk = 0; thnk < numoni; thnk++){ if(!live[thnk]) continue; if(bound(thnk + 1)) gamewin(thnk); } } } ...省略... //オブジェクト位置情報 //位置4*4マトリクス(継続パラメータ) var VONI = 0.3; var TONI = new N6LMatrix(4).UnitMat(); var ONI = [new N6LMatrix(4).UnitMat()]; var oldpos = []; var oldpos2 = []; var trate = 20; var trateW = 20; var oldtgt = [4]; var depth = 5; var depthW = 5; var cont = 10; var count = [0, 0, 0, 0]; var rotoni = 2.75; var rotation = rotoni * (Math.PI / 180); var notVec = [0,0,0]; var dang = 30; var skp = 8; //敵思考 function thinkOni(){ //if(!thnk)return 1; //else return 7; count[thnk]++; chknotVec(); //近くの壁検知 var ttt = [0, 0, 0, 0, 0, 0, 0, 0, 0]; var uuu = [false, false, false, false, true, false, false, false, false]; var bnd; //一定行動&危険察知 if(count[thnk] < cont) { bnd = moveOni(oldtgt[thnk], false, 0); ONI[thnk] = new N6LMatrix(TONI); if(bnd < 0) return oldtgt[thnk]; ttt[oldtgt[thnk]] = bnd; } count[thnk] = 0; var i; var j; var k; var c; var h; var rnd; var b = false; //危険察知 for(i = 0; i < 3; i++) { for(j = 0; j < 3; j++) { k = i * 3 + j; if(count[thnk] < cont && k == oldtgt[thnk]) continue; ttt[k] = moveOni(k, false, 0); ONI[thnk] = new N6LMatrix(TONI); } } //前進と前の行動優先 if(ttt[4] == -1 && Math.floor(Rand(0, 100)) < trate) return 4; if(oldtgt[thnk] != 4 && ttt[oldtgt[thnk]] == -1 && Math.floor(Rand(0, 100)) < trateW) return oldtgt[thnk]; uuu[oldtgt[thnk]] = true; h = 7; if(oldtgt[thnk] == 4) h++; c = 0; //安全な回転 while(c < h) { rnd = Math.floor(Rand(0, 9)); if(uuu[rnd]) continue; uuu[rnd] = true; c++; if(ttt[rnd] == -1) return rnd; } //危険な中でも一番安全な選択 for(i = 1, j = ttt[0], k = 0; i < 9; i++) { if(j < ttt[i]) { j = ttt[i]; k = i; } } while(true) { rnd = Math.floor(Rand(0, 9)); if(ttt[rnd] != j) continue; return rnd; } } function chknotVec() { //近くの壁察知 var i; var j; var k; var n = []; var min; var mid; var max; var nmin; var nmid; var nmax; var dcp = ONI[thnk].Pos(); var dc = dcp.Sub(oldpos2[thnk]).DirectionCosine().NormalVec(); //各軸の壁の近さ for(i = 1; i < 4; i++) { if(dc.x[i] != 0.0) { k = -1; j = (-50.0 - dcp.x[i]) / dc.x[i]; if(j < 0.0) { k = 1; j = (50.0 - dcp.x[i]) / dc.x[i]; } n[i - 1] = k * j; } else n[i - 1] = 999999; } //順番 min = n[0]; nmin = 0; max = n[0]; nmax = 0; if(Math.abs(n[1]) < Math.abs(min)) { min = n[1]; nmin = 1; } if(Math.abs(max) < Math.abs(n[1])) { max = n[1]; nmax = 1; } if(Math.abs(n[2]) < Math.abs(min)) { min = n[2]; nmin = 2; } if(Math.abs(max) < Math.abs(n[2])) { max = n[2]; nmax = 2; } for(i = 0; i< 3; i++) if(n[i] != min && n[i] != max) { mid = n[i]; nmid = i; } if(Math.abs(min) < dang) notVec[nmin] = new N6LMatrix().QSIGN(min) * 1; else { notVec = [0,0,0]; return;} if(Math.abs(mid) < dang) notVec[nmid] = new N6LMatrix().QSIGN(mid) * 2; else notVec[nmid] = 0; if(Math.abs(max) < dang) notVec[nmax] = new N6LMatrix().QSIGN(max) * 3; else notVec[nmax] = 0; } function moveOni(k, bbb, cnt){//移動&危険察知 if(!x3domRuntime) return -1; var x = k % 3 - 1; var y = Math.floor(k / 3) - 1; //var wpyr = new N6LVector([1, x * rotation, y * rotation, x * rotation], true); var wpyr = new N6LVector([1, x * rotation, y * rotation, 0], true); var outmat = []; var outv = []; var WA; if(!bbb) { //危険察知 WA = ONI[thnk].MoveMat(outmat, outv, new N6LVector(4, true).ZeroVec(), wpyr.Mul(skp), VONI * skp, 0, 0, 5); //目的の関数 if(!cnt) TONI = new N6LMatrix(ONI[thnk]); var dep = depthW; if(k == 4) dep = depth; //直進はより深く //壁検知 var max = outv[0].Max(); var dir; for(x = 1; x < 4; x++) { if(outv[0].x[x] == max) { dir = x - 1; } } if(Math.abs(notVec[dir]) == 1){ wpyr = wpyr.Mul(-1); var outmat2 = []; var outv2 = []; WA = WA.MoveMat(outmat2, outv2, new N6LVector(4, true).ZeroVec(), wpyr.Mul(skp), VONI * skp, 0, 0, 5); //目的の関数 if(notVec[dir] < 0) { if(outv[0].x[dir] < outv2[0].x[dir]) return cnt; //危険 } else if(outv2[0].x[dir] < outv[0].x[dir]) return cnt; //危険 } ONI[thnk] = new N6LMatrix(WA); if(dep < cnt) return -1; //安全 if(bound(thnk + 1)) return cnt; //危険 return moveOni(k, false, cnt + 1); //同じ方向のみさらに調べる } else WA = ONI[thnk].MoveMat(outmat, outv, new N6LVector(4, true).ZeroVec(), wpyr, VONI, 0, 0, 5); //目的の関数 //値を適用 ONI[thnk] = new N6LMatrix(WA); //x3domに適用 var Vec = ONI[thnk].Vector(); var pos = ONI[thnk].Pos(); oldpos2[thnk] = new N6LVector(oldpos[thnk]); oldpos[thnk] = new N6LVector(pos); var oni = pos.ToX3DOM(true); var rot = Vec.ToX3DOM(); var elm = document.getElementById('oniT' + String(thnk)); elm.setAttribute('translation', oni.toString()); elm = document.getElementById('oniR' + String(thnk)); elm.setAttribute('rotation', rot.toString()); } var egg = [2.0, 2.0, 2.0, 2.0, 2.0]; var eggarea = []; var oldegg = [new N6LVector([1, 0, 0, 25], true), new N6LVector([1, 0, 0, -25], true)]; var add = 0.02; var num = 0; var r = 4.0; //体つくり function genBody(id){ egg[id] += add; if(1.0 < egg[id]) { egg[id] = 0.0; var mat; var col; if(!id) { mat = new N6LMatrix(A); col = '0.3 0.3 0.6'; } else { mat = new N6LMatrix(ONI[id - 1]); switch(id) { case 1 : col = '0.6 0.15 0.3'; break; case 2 : col = '0.6 0.5 0.15'; break; case 3 : col = '0.23 0.6 0.15'; break; case 4 : col = '0.15 0.6 0.6'; break; default : col = '0 0 0'; break; } } var pos = mat.Pos(); var trns = pos.x[1] + ' ' + pos.x[2] + ' ' + pos.x[3]; var line = oldegg[id].x[1] + ' ' + oldegg[id].x[2] + ' ' + oldegg[id].x[3] + ' ' + pos.x[1] + ' ' + pos.x[2] + ' ' + pos.x[3]; oldegg[id] = new N6LVector(pos); var area = Math.floor((pos.x[1] + 50) / 25) * 16 + Math.floor((pos.x[2] + 50) / 25) * 4 + Math.floor((pos.x[3] + 50) / 25); eggarea[num] = area; //タグの動的追加 var material = document.createElement("material"); material.setAttribute("diffuseColor", col); var appearance = document.createElement("appearance"); var sphere = document.createElement("sphere"); sphere.setAttribute("radius", String(r)); var shape = document.createElement("shape"); var transform = document.createElement("transform"); transform.setAttribute("id", "sph_" + num); transform.setAttribute("translation", trns); appearance.appendChild(material); shape.appendChild(appearance); shape.appendChild(sphere); transform.appendChild(shape); var lmaterial = document.createElement("material"); lmaterial.setAttribute("emissiveColor", col); var lcoordinate = document.createElement("coordinate"); lcoordinate.setAttribute("point", line); var lindexedlineset = document.createElement("indexedlineset"); lindexedlineset.setAttribute("coordIndex", "0 1 -1"); var llineproperties = document.createElement("lineproperties"); llineproperties.setAttribute("linetype", "1"); //llineproperties.setAttribute("linewidthScaleFactor", "10"); var lappearance = document.createElement("appearance"); var lshape = document.createElement("shape"); lappearance.appendChild(lmaterial); lappearance.appendChild(llineproperties); lshape.appendChild(lappearance); lindexedlineset.appendChild(lcoordinate); lshape.appendChild(lindexedlineset); var parent_object = document.getElementById("x3dsn"); parent_object.appendChild(transform); parent_object.appendChild(lshape); num++; //debug//デバッグ用 var elm = document.getElementById('debug'); //elm.innerText = 'oldtgt = ' + String(oldtgt) + '\n' + String(num) + ' 個産まれた '; elm.innerText = 'win : ' + String(win) + '\n' + String(num) + ' 個産まれた '; } } function bound(id){ //衝突検知 var i; var j; var elm; var pos; var bpos; var dis; var str; var token; var mat; if(!id) { mat = new N6LMatrix(A); } else { mat = new N6LMatrix(ONI[id - 1]); bpos = A.Pos(); } pos = mat.Pos(); //壁 if((pos.x[1] < -50.0 + r || 50.0 - r < pos.x[1]) || (pos.x[2] < -50.0 + r || 50.0 - r < pos.x[2]) || (pos.x[3] < -50.0 + r || 50.0 - r < pos.x[3])) return true; //キャラ同士 if(id) { dis = bpos.Sub(pos).Abs(); if(dis < r * 1.5) return true; } for(i = 0; i < numoni; i++) { if(i == id - 1 || !live[i]) continue; bpos = ONI[i].Pos(); dis = bpos.Sub(pos).Abs(); if(dis < r * 1.5) { if(id) { live[i] = false; elm = document.getElementById('oniS' + String(i)); elm.setAttribute('render', 'false'); win++; } return true; } } var area = [ Math.floor((pos.x[1] + 50) / 25 + 0) * 16 + Math.floor((pos.x[2] + 50) / 25 + 0) * 4 + Math.floor((pos.x[3] + 50) / 25 + 0), Math.floor((pos.x[1] + 50) / 25 - 1) * 16 + Math.floor((pos.x[2] + 50) / 25 + 0) * 4 + Math.floor((pos.x[3] + 50) / 25 + 0), Math.floor((pos.x[1] + 50) / 25 + 1) * 16 + Math.floor((pos.x[2] + 50) / 25 + 0) * 4 + Math.floor((pos.x[3] + 50) / 25 + 0), Math.floor((pos.x[1] + 50) / 25 + 0) * 16 + Math.floor((pos.x[2] + 50) / 25 - 1) * 4 + Math.floor((pos.x[3] + 50) / 25 + 0), Math.floor((pos.x[1] + 50) / 25 + 0) * 16 + Math.floor((pos.x[2] + 50) / 25 + 1) * 4 + Math.floor((pos.x[3] + 50) / 25 + 0), Math.floor((pos.x[1] + 50) / 25 + 0) * 16 + Math.floor((pos.x[2] + 50) / 25 + 0) * 4 + Math.floor((pos.x[3] + 50) / 25 - 1), Math.floor((pos.x[1] + 50) / 25 + 0) * 16 + Math.floor((pos.x[2] + 50) / 25 + 0) * 4 + Math.floor((pos.x[3] + 50) / 25 + 1)]; for(i = 0; i < num - (numoni + 1); i++) { //当該体が含まれる隣接エリア for(j = 0; j < area.length; j++) if(eggarea[i] != area[j]) continue; //体 elm = document.getElementById("sph_" + i); str = elm.translation; token = str.split(' '); bpos = new N6LVector([1, token[0], token[1], token[2]], true); dis = bpos.Sub(pos).Abs(); if(dis < r * 1.5) return true; } return false; //安全 } //終了処理 function gameclear(){ V = 0.0; var elm = document.getElementById('debug'); var str = 'ゲームクリア!!!\nScore : ' + String(num * 10 + win * 1500 + 1 * 5000) + '\nEgg : ' + String(num) + ' × 10 = ' + String(num * 10) + '\nWinBonus : 1500 × ' + String(win) + ' = ' + String(win * 1500) + '\nClearBonus : 5000 × 1 = 5000'; elm.innerText = str; window.alert(str); game = false; } function gameover(){ V = 0.0; var elm = document.getElementById('debug'); var str = 'ゲームオーバー!!!\nScore : ' + String(num * 10 + win * 1500 + 0 * 5000) + '\nEgg : ' + String(num) + ' × 10 = ' + String(num * 10) + '\nWinBonus : 1500 × ' + String(win) + ' = ' + String(win * 1500) + '\nClearBonus : 5000 × 0 = 0'; elm.innerText = str; window.alert(str); game = false; } function gamewin(id){ live[id] = false; var elm = document.getElementById('oniS' + String(id)); elm.setAttribute('render', 'false'); win++; var i; for(i = 0; i < numoni; i++) if(live[i]) return; V = 0.0; elm = document.getElementById('debug'); var str = 'ゲームウィン!!!\nScore : ' + String(num * 10 + win * 1500 + 0 * 5000) + '\nEgg : ' + String(num) + ' × 10 = ' + String(num * 10) + '\nWinBonus : 1500 × ' + String(win) + ' = ' + String(win * 1500) + '\nClearBonus : 5000 × 0 = 0'; elm.innerText = str; window.alert(str); game = false; } //lookat//注視 function viewp() { if(!x3domRuntime || !numoni) return; var elm; var i; var j; var k; var dis = 999999; var WM = new N6LMatrix(A); var pos = WM.Pos(); var lookat; for(i = 0; i < numoni; i++){ if(!live[i]) continue; lookat = ONI[i].Pos(); //目標位置 j = lookat.Sub(pos).Abs(); if(j < dis) {dis = j; k = i;} } lookat = ONI[k].Pos(); //目標位置 /* //視垂台カリング失敗。むむむ。 var TVM = new N6LMatrix(VM); var Offset = ONI.Pos(); var Right = TVM.GetRow(1); var Up = TVM.GetRow(2); var Normal = TVM.GetRow(3); var radius = 0.001; var sH = 0.5; var near = Normal.Dot(Offset); var far = -(Normal.Dot(Offset)) + 120.0; var left = Right.Dot(Offset) - sH; var right = Right.Dot(Offset) + sH; var bottom = Up.Dot(Offset) - sH; var top = Up.Dot(Offset) + sH; if((-radius <= near) && (-radius <= far) && (-radius <= left) && (-radius <= right) && (-radius <= bottom) && (-radius <= top)) { OutArrow(); return; } */ var LAM = WM.LookAtMat2(lookat); //目的の関数 //オイラー角を求める//ロールの処理が難しいから軸はこの順番 var lamel = LAM.EulerAngle(2, 3, 1); var wmel = WM.EulerAngle(2, 3, 1); var p = lamel.x[1] - wmel.x[1]; var y = lamel.x[2] - wmel.x[2]; //if(wmel.x[2] < lamel.x[2]) y = wmel.x[2] - lamel.x[2]; var r = 0.0 - wmel.x[3]; //elm = document.getElementById('debug'); //elm.innerText = String(Math.floor(r * (180.0 / Math.PI))); //ロールの処理が難しい //var Theta = Math.atan2(p, - WM.QSIGN(y) * Math.sqrt(y * y + r * r)); //var Theta = Math.atan2(p, -y) + 2.0 * r; var Theta = Math.atan2(p, -y); //矢印セット var az = new N6LVector(4, true).UnitVec(3); var dir = new N6LVector([1.0, 0.75, 0.0, -2.0], true).RotAxis(az, Theta); var ppp = WM.GetCol(0); WM.x[1].x[0] = 0; WM.x[2].x[0] = 0; WM.x[3].x[0] = 0; dir = WM.Mul(dir).Add(ppp); WM = WM.TranslatedMat(dir); var pos = WM.Pos().ToX3DOM(true); var AM = new N6LMatrix(A); AM = AM.RotAxis(az, Theta - Math.PI / 2.0); var ori = AM.Vector().ToX3DOM(); elm = document.getElementById('arrowT'); elm.setAttribute('translation', pos.toString()); elm = document.getElementById('arrowR'); elm.setAttribute('rotation', ori.toString()); //debug//デバッグ用 //elm = document.getElementById('debug'); //elm.innerText = 'th = ' + String(Math.floor(Theta * (180.0 / Math.PI))); } function OutArrow(){ var elm = document.getElementById('arrowT'); var pos = new N6LVector([1, 1000, 0, 0], true).ToX3DOM(true); elm.setAttribute('translation', pos.toString()); }
var trate = 20; var trateW = 20; var oldtgt = [4]; var depth = 5; var depthW = 5; var cont = 10; var count = [0, 0, 0, 0]; var rotoni = 2.75; var rotation = rotoni * (Math.PI / 180); var notVec = [0,0,0]; var dang = 30; var skp = 8; //敵思考 function thinkOni(){ //if(!thnk)return 1; //else return 7; count[thnk]++; chknotVec(); //近くの壁検知 var ttt = [0, 0, 0, 0, 0, 0, 0, 0, 0]; var uuu = [false, false, false, false, true, false, false, false, false]; var bnd; //一定行動&危険察知 if(count[thnk] < cont) { bnd = moveOni(oldtgt[thnk], false, 0); ONI[thnk] = new N6LMatrix(TONI); if(bnd < 0) return oldtgt[thnk]; ttt[oldtgt[thnk]] = bnd; } count[thnk] = 0; var i; var j; var k; var c; var h; var rnd; var b = false; //危険察知 for(i = 0; i < 3; i++) { for(j = 0; j < 3; j++) { k = i * 3 + j; if(count[thnk] < cont && k == oldtgt[thnk]) continue; ttt[k] = moveOni(k, false, 0); ONI[thnk] = new N6LMatrix(TONI); } } //前進と前の行動優先 if(ttt[4] == -1 && Math.floor(Rand(0, 100)) < trate) return 4; if(oldtgt[thnk] != 4 && ttt[oldtgt[thnk]] == -1 && Math.floor(Rand(0, 100)) < trateW) return oldtgt[thnk]; uuu[oldtgt[thnk]] = true; h = 7; if(oldtgt[thnk] == 4) h++; c = 0; //安全な回転 while(c < h) { rnd = Math.floor(Rand(0, 9)); if(uuu[rnd]) continue; uuu[rnd] = true; c++; if(ttt[rnd] == -1) return rnd; } //危険な中でも一番安全な選択 for(i = 1, j = ttt[0], k = 0; i < 9; i++) { if(j < ttt[i]) { j = ttt[i]; k = i; } } while(true) { rnd = Math.floor(Rand(0, 9)); if(ttt[rnd] != j) continue; return rnd; } }