...省略...
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;
}
}