...省略...
<script>
var TMan = new N6LTimerMan(); //タイマーマネージャー
var rate = 2;
var img = new Array();
var readed = [false, false, false];
var answer = new Array();
var answercost = 1e12;
var answerhcost = 1e12;
var wanswer = new Array();
var wanswercost = 1e12;
var wanswerhcost = 1e12;
var data;
var elm;
var ctx;
var movefrm = 4;
var anifrm0 = 4;
var anifrm1 = 32;
var anispan = 4;
var tipsize = 8;
var maxdep = 120;
var coleps = 5;
var eps = 5e-14;
var tipmapsize = [480 / 8, 320 / 8];
var overthink = 10000;
var think = 0;
var rethink = 1.5;
var rtd = 0;
var rep = 0;
var sdep = 0;
var rew = 6;
var nrep = 0;
var bto = false;
var wthink = 0;
var wrethink = 1.5;
var wrtd = 0;
var wrep = 0;
var wsdep = 0;
var wrew = 6;
var wnrep = 0;
var wbto = false;
var rearway;
var tipcost = [
[64, [0, 255, 0]],
[256, [0, 128, 0]],
[1024, [192, 192, 0]],
[8, [160, 128, 32]],
[8, [128, 128, 128]] ];
var movedir = [
[[1, 0], 1, [0,7,1,6,2,5,3,4]],
[[1, 1], 1.414214, [1,0,2,7,3,6,4,5]],
[[0, 1], 1, [2,1,3,0,4,7,5,6]],
[[-1, 1], 1.414214, [3,2,4,1,5,0,6,7]],
[[-1, 0], 1, [4,3,5,2,6,1,7,0]],
[[-1, -1], 1.414214, [5,4,6,3,7,2,0,1]],
[[0, -1], 1, [6,5,7,4,0,3,1,2]],
[[1, -1], 1.414214, [7,6,0,5,1,4,2,3]] ];
class Kuro {
constructor() {
this.frm = 0;
this.pos = [160, 265];
this.tgt = [160, 265];
this.route = new Array();
this.nowroute = 0;
this.state = 0;
this.size = 32;
}
}
class Col {
constructor(r, g, b, a) {
this.r = 0;
this.g = 0;
this.b = 0;
this.a = 0;
if(isNaN(a) == false){
this.r = r;
this.g = g;
this.b = b;
this.a = a;
}
}
}
var tipmap = new Array();
var kuro = new Kuro();
function enter() {
if(readed[0] == false){
img[0] = new Image();
img[0].src = "./img/astarmap.jpg";
img[0].onload = () => {
readed[0] = true;
analyzemap();
return;
};
}
if(readed[1] == false){
img[1] = new Image();
img[1].src = "./img/kuro000.png";
img[1].onload = () => {
readed[1] = true;
return;
};
}
if(readed[2] == false){
img[2] = new Image();
img[2].src = "./img/kuro001.png";
img[2].onload = () => {
readed[2] = true;
return;
};
}
elm = document.getElementById('cnv0');
ctx = elm.getContext("2d");
elm.addEventListener("click",e=>{
const rect = e.target.getBoundingClientRect();
const viewX = e.clientX - rect.left,
viewY = e.clientY - rect.top;
const scaleWidth = elm.clientWidth / elm.width,
scaleHeight = elm.clientHeight / elm.height;
const canvasX = Math.floor(viewX / scaleWidth),
canvasY = Math.floor(viewY / scaleHeight);
kuro.tgt = [canvasX, canvasY];
calcroute();
});
TMan.add();
Loop(0);
}
function Loop(id){
if(isreaded() == true){
ctx.fillStyle = "rgb(0, 0, 0)" ;
ctx.strokeStyle = 'rgb(0, 0, 0)';
ctx.clearRect(0, 0, 480, 320);
ctx.drawImage(img[0], 0, 0);
movekuro();
drawkuro();
dispinfo();
}
TMan.timer[id].setalerm(function() { Loop(id); }, 50);
}
function drawkuro(){
var dimg = img[1];
if((kuro.frm % anifrm0) == 0) dimg = img[2];
var dy = anispan * Math.sin((kuro.frm % anifrm1) / anifrm1 * Math.PI * 2);
ctx.drawImage(dimg, kuro.pos[0] - (kuro.size / 2), kuro.pos[1] + dy - (kuro.size / 2));
}
function analyzemap(){
ctx.fillStyle = "rgb(0, 0, 0)" ;
ctx.strokeStyle = 'rgb(0, 0, 0)';
ctx.clearRect(0, 0, 480, 320);
ctx.drawImage(img[0], 0, 0);
var w = 480;
var h = 320;
var imgdata = ctx.getImageData(0, 0, w, h);
var data = imgdata.data;
var x;
var y;
var i;
var tip;
tipmap = new Array();
for(y = 0; y < h; y = y + tipsize){
for(x = 0; x < w; x = x + tipsize){
var c = getcolor(data, x, y, w, h);
tip = 0;
for(i = 0; i < tipcost.length; i++){
if((tipcost[i][1][0] - coleps <= c.r)&&(c.r <= tipcost[i][1][0] + coleps)&&
(tipcost[i][1][1] - coleps <= c.g)&&(c.g <= tipcost[i][1][1] + coleps)&&
(tipcost[i][1][2] - coleps <= c.b)&&(c.b <= tipcost[i][1][2] + coleps)){
tip = i;
break;
}
}
if((tip < 0)||(tipcost.length <= tip)) tip = 0;
tipmap.push(tip);
}
}
}
function getcolor(data, x, y, w, h){
var pos = (y * w + x) * 4;
var ret = new Col();
if(w * h * 4 < pos) return ret;
ret.r = data[pos + 0];
ret.g = data[pos + 1];
ret.b = data[pos + 2];
ret.a = data[pos + 3];
return ret;
}
function movekuro(){
kuro.frm++;
if(kuro.state == 0) return;
if((kuro.frm % movefrm) == (movefrm - 1)) kuro.nowroute++;
if(kuro.route.length - 2 < kuro.nowroute){
kuro.pos = kuro.tgt;
kuro.state = 0;
}
else {
var now = [kuro.route[kuro.nowroute][0] * tipsize, kuro.route[kuro.nowroute][1] * tipsize];
var next = [kuro.route[kuro.nowroute + 1][0] * tipsize, kuro.route[kuro.nowroute + 1][1] * tipsize];
var delta = [(next[0] - now[0]) / movefrm * (kuro.frm % movefrm), (next[1] - now[1]) / movefrm * (kuro.frm % movefrm)];
kuro.pos = [now[0] + delta[0], now[1] + delta[1]];
}
}
function calcroute(){
kuro.route = new Array();
kuro.nowroute = 0;
var st = [Math.floor(kuro.pos[0] / tipsize), Math.floor(kuro.pos[1] / tipsize)];
var ed = [Math.floor(kuro.tgt[0] / tipsize), Math.floor(kuro.tgt[1] / tipsize)];
var wans = new Array();
wanswer = new Array();
wanswercost = 1e12;
wanswerhcost = 1e12;
wthink = 0;
wbto = false;
wrtd = -1;
wnrep = -1;
getnearway(st, ed);
var ret;
if((st[0] != nearway[0])||(st[1] != nearway[1])){
ret = serchway(wans.slice(), st, ed, 0, 0, maxdep, 0);
if(ret == true){
wanswer = answer.slice();
wanswercost = answercost;
wanswerhcost = answerhcost;
}
}
var ans = new Array();
answer = new Array();
answercost = 1e12;
answerhcost = 1e12;
think = 0;
bto = false;
rtd = -1;
nrep = -1;
r = astar(ans.slice(), st, ed, 0, 0, maxdep, 0);
ret = (ret || r);
if(ret == true){
if(wanswercost < answercost){
kuro.route = wanswer.slice();
}
else {
kuro.route = answer.slice();
}
kuro.nowroute = 0;
kuro.state = 1;
}
return ret;
}
//ans:経路配列
//now:現在位置
//end:終了位置
//cost:経路コスト
//hcost:推計経路コスト
//maxdepth:最大ネスト深度
//depth:現在のネスト数
//answer:解答経路文字列
//answercost:解答経路コスト
//ret:解決できたか?
function serchway(ans, now, end, cost, hcost, maxdepth, depth){
wthink++;
if((maxdepth < depth)||(overthink < wthink)){
wbto = true;
return false;
}
var ret = false;
var rrr;
ans.push(now);
if((now[0] == nearway[0])&&(now[1] == nearway[1])) {
if((cost < wanswercost)||((wanswercost - eps < cost)&&(cost < wanswercost + eps)&&(hcost < wanswerhcost))){
wanswercost = cost;
wanswerhcost = hcost;
wanswer = ans.slice();
if(wrtd < 0){
wrtd = depth / rethink;
if(depth - wrtd < wrew) wrtd = depth - wrew;
// wbto = true;
}
else {
rrr = depth / rethink;
if(depth - rrr < wrew) rrr = depth - wrew;
if(rrr < wrtd) wrtd = rrr;
// wbto = true;
}
answer = ans.slice();
answercost = 1e12;
answerhcost = 1e12;
think = 0;
bto = false;
rtd = -1;
nrep = -1;
var r = astar(ans.slice(), nearway, end, cost, h, maxdepth, 0);
return r;
}
}
var i;
var dir = setdir(now, nearway);
for(i = 0; i < dir.length; i++){
if(wbto == true){
if(wrtd < depth){
if(overthink < wthink) return ret;
}
else {
if((i < dir.length - 1)){
wbto = false;
wthink = 0;
}
}
}
var next = [Math.floor(now[0] + movedir[dir[i]][0][0]), Math.floor(now[1] + movedir[dir[i]][0][1])];
if(isoutmap(next) == true) continue;
if(isGone(ans, next) == false){
var h = heuristic(next, nearway);
if(cost + h < wanswercost){
if(h < hcost) h = hcost;
var crnt = tipmapsize[0] * next[1] + next[0];
var mcost = tipcost[tipmap[crnt]][0] * movedir[dir[i]][1];
var r = serchway(ans.slice(), next, end, cost + mcost, h, maxdepth, depth + 1);
ret = (ret || r);
}
}
if((depth <= wrtd)&&(i == dir.length - 1)){
rrr = depth / wrethink;
if(depth - rrr < wrew) rrr = depth - wrew;
if(rrr < wrtd) wrtd = rrr;
wbto = true;
}
}
return ret;
}
//ans:経路配列
//now:現在位置
//end:終了位置
//cost:経路コスト
//hcost:推計経路コスト
//maxdepth:最大ネスト深度
//depth:現在のネスト数
//answer:解答経路文字列
//answercost:解答経路コスト
//ret:解決できたか?
function astar(ans, now, end, cost, hcost, maxdepth, depth){
think++;
if((maxdepth < depth)||(overthink < think)){
bto = true;
return false;
}
var ret = false;
var rrr;
ans.push(now);
if((now[0] == end[0])&&(now[1] == end[1])) {
if((cost < answercost)||((answercost - eps < cost)&&(cost < answercost + eps)&&(hcost < answerhcost))){
answercost = cost;
answerhcost = hcost;
answer = ans.slice();
if(rtd < 0){
rtd = depth / rethink;
if(depth - rtd < rew) rtd = depth - rew;
// bto = true;
}
else {
rrr = depth / rethink;
if(depth - rrr < rew) rrr = depth - rew;
if(rrr < rtd) rtd = rrr;
// bto = true;
}
return true;
}
}
var i;
var dir = setdir(now, end);
for(i = 0; i < dir.length; i++){
if(bto == true){
if(rtd < depth){
if(overthink < think) return ret;
}
else {
if((i < dir.length - 1)){
bto = false;
think = 0;
}
}
}
var next = [Math.floor(now[0] + movedir[dir[i]][0][0]), Math.floor(now[1] + movedir[dir[i]][0][1])];
if(isoutmap(next) == true) continue;
if(isGone(ans, next) == false){
var h = heuristic(next, end);
if(cost + h < answercost){
if(h < hcost) h = hcost;
var crnt = tipmapsize[0] * next[1] + next[0];
var mcost = tipcost[tipmap[crnt]][0] * movedir[dir[i]][1];
var r = astar(ans.slice(), next, end, cost + mcost, h, maxdepth, depth + 1);
ret = (ret || r);
}
}
if((depth <= rtd)&&(i == dir.length - 1)){
rrr = depth / rethink;
if(depth - rrr < rew) rrr = depth - rew;
if(rrr < rtd) rtd = rrr;
bto = true;
}
}
return ret;
}
function getnearway(now, end){
var sub;
var near = [-1, -1];
var nd = 1e12;
var nh = 1e12;
var d;
var h;
var x;
var y;
var crnt;
var tip;
for(y = 0; y < tipmapsize[1]; y++){
for(x = 0; x < tipmapsize[0]; x++){
crnt = tipmapsize[0] * y + x;
tip = tipmap[crnt];
if((tip == 3)||(tip == 4)){
sub = [x - now[0], y - now[1]];
d = Math.sqrt(sub[0] * sub[0] + sub[1] * sub[1]);
h = heuristic([x, y], end);
if((d < nd)||(h < nh)&&(nd - eps < d)&&(d < nd + eps)){
nd = d;
nh = h;
near = [x, y];
}
}
}
}
nearway = near;
}
function setdir(now, end){
var sub = [Math.floor(end[0] - now[0]), Math.floor(end[1] - now[1])];
if(sub[0] == 0) sub[0] = 0;
else if(sub[0] < 0) sub[0] = -1;
else sub[0] = 1;
if(sub[1] == 0) sub[1] = 0;
else if(sub[1] < 0) sub[1] = -1;
else sub[1] = 1;
var i;
for(i = 0; i < movedir.length; i++){
if((sub[0] == movedir[i][0][0])&&(sub[1] == movedir[i][0][1])) return movedir[i][2];
}
return movedir[0][2];
}
function heuristic(now, end){
var sub = [end[0] - now[0], end[1] - now[1]];
var crnt = tipmapsize[0] * now[1] + now[0];
var ret = Math.sqrt(sub[0] * sub[0] + sub[1] * sub[1]) / rate * tipcost[tipmap[crnt]][0];
return ret;
}
function isoutmap(pos){
if((pos[0] < 0)||(tipmapsize[0] - 1 < pos[0])||(pos[1] < 0)||(tipmapsize[1] - 1 < pos[1])) return true;
return false;
}
function isGone(ans, now){
var i;
for(i = 0; i < ans.length; i++){
if((ans[i][0] == now[0])&&(ans[i][1] == now[1])){
return true;
}
}
return false;
}
function isreaded(){
for(var i = 0; i < 3; i++){
if(readed[i] == false) return false;
}
return true;
}
function dispinfo(){
var nowelm = document.getElementById('OUTTXTNOW');
var tgtelm = document.getElementById('OUTTXTTGT');
nowelm.value = Math.floor(kuro.pos[0]) + ', ' + Math.floor(kuro.pos[1]) + ' :state: ' + kuro.state;
tgtelm.value = Math.floor(kuro.tgt[0]) + ', ' + Math.floor(kuro.tgt[1]);
}
</script>
...省略...