let maze = []; let mazeWidth = 19; let Kind = { player: 1, enemy: 2, trap: 3, hostage: 4, }; let Buff = { snare: 1, rescue: 2, }; class Actor { constructor() { this.kind = 0; this.image = ""; this.x = 0; this.y = 0; this.buff = 0; this.buffTimer = 0; } } let goal = new Actor(); goal.kind = 9; goal.image = "▲"; goal.x = 1; goal.y = 1; let player = new Actor(); player.kind = 1; player.image = "〇"; player.x = 1; player.y = 1; let enemy = new Actor(); enemy.kind = 2; enemy.image = "E"; enemy.x = 5; enemy.y = 5; enemy.buffTimer = 0; let enemy2 = new Actor(); enemy2.kind = 2; enemy2.image = "E"; enemy2.x = 7; enemy2.y = 7; let enemy3 = new Actor(); enemy3.kind = 2; enemy3.image = "E"; enemy3.x = 9; enemy3.y = 9; let enemy4 = new Actor(); enemy4.kind = 2; enemy4.image = "E"; enemy4.x = 11; enemy4.y = 11; let enemy5 = new Actor(); enemy4.kind = 2; enemy4.image = "K"; enemy4.x = 13; enemy4.y = 11; let hostage = new Actor(); hostage.x = mazeWidth - 2; hostage.y = mazeWidth - 2; hostage.x = 5; hostage.y = 5; hostage.kind = Kind.hostage; hostage.image = "友"; let actors = [goal,player, hostage]; function setup() { createCanvas(480, 480); maze.push(new Array(mazeWidth).fill(1)); for (let y = 0; y < mazeWidth - 2; y++) { maze.push(new Array(mazeWidth).fill(0)); maze[y + 1][0] = 1; maze[y + 1][mazeWidth - 1] = 1; } maze.push(new Array(mazeWidth).fill(1)); for (let y = 2; y < mazeWidth - 2; y += 2) { for (let x = 2; x < mazeWidth - 2; x += 2) { maze[y][x] = 1; while (true) { // let r = floor(random(0, y===2 ? 4 : 3)); let r = floor(random(0, 4)); let a = [1, 0, -1, 0][r]; let b = [0, 1, 0, -1][r]; if (maze[y + b][x + a] === 1) continue; maze[y + b][x + a] = 1; break; } } } debugger; } let countWalls = (x,y) => { let blocks = 0; for(let j=x-1; j<=x+1; j++) { for(let k=y-1; k<=y+1; k++) { blocks += maze[k][j]; } } let enemies = actors .filter(a => a.kind === Kind.enemy && abs(a.x-x)<=1 && abs(a.y-y)<=1) .length; return blocks + enemies; } // ベクトルの演算の関数 // 引数のsはスカラー、vとwは3次元ベクトル let mul = (s, v) => v.map((e) => s * e); let add = (v, w) => v.map((e, i) => e + w[i]); let sub = (v, w) => add(v, mul(-1, w)); let dot = (v, w) => v[0] * w[0] + v[1] * w[1]; let norm = (v) => sqrt(v[0] ** 2 + v[1] ** 2); let normalize = (v) => mul(1 / norm(v), v); let chase = (a, b, p, q) => { let v = [0, 1, 2, 3] .map((n) => [[1, 0, -1, 0][n], [0, 1, 0, -1][n]]) .sort((v, w) => { let PE = sub([p, q], [a, b]); let r = norm(add(PE, v)); let s = norm(add(PE, w)); return r - s; }) .slice(0,3) .filter((v) => maze[q + v[1]][p + v[0]] === 0) .filter((v) => { return actors.filter(act => act.kind === Kind.enemy || act.kind === Kind.hostage || act.kind === Kind.player).every(act => { return act.x !== p+v[0] || act.y !== q+v[1]; }); }); if (v.length === 0) return [0,0]; return [v[0][0], v[0][1]]; }; let keyDownFrames = 0; function draw() { background(220); for (let y = 0; y < mazeWidth; y++) { for (let x = 0; x < mazeWidth; x++) { let w = width / mazeWidth; let m = maze[y][x]; if (m === 1) { rect(w * x, w * y, w, w); } } } if (keyIsPressed) { keyDownFrames++; } else { keyDownFrames = 0; } //ここからキー入力処理 if (keyDownFrames === 1) { let k = keyCode - 37; if (k >= 0 && k < 4) { let a = [-1, 0, 1, 0][k]; let b = [0, -1, 0, 1][k]; let p = player; if (maze[p.y + b][p.x + a] === 0) { let move = chase(p.x+a, p.y+b, p.x, p.y); p.x += move[0]; p.y += move[1]; } } //罠を置く let trapCount = actors.filter((a) => a.kind === Kind.trap).length; if (keyCode === 84 && trapCount < 3) { let trap = new Actor(); trap.x = player.x; trap.y = player.y; trap.image = "罠"; trap.kind = Kind.trap; actors.push(trap); //let trap2 = new Actor(); //trap2.x = player.x; //trap2.y = player.y; //trap2.image = '穴'; //actors.push(trap2); } for (let enemy of actors.filter((a) => a.kind === Kind.enemy)) { if (enemy.buffTimer === 0) { let rival = hostage.buff === Buff.rescue ? hostage : player; let chaseVec = chase(rival.x, rival.y, enemy.x, enemy.y); enemy.x += chaseVec[0]; enemy.y += chaseVec[1]; for (let trap of actors.filter((a) => a.kind === Kind.trap)) { if (trap.x === enemy.x && trap.y === enemy.y) { enemy.buff = Buff.snare; enemy.buffTimer = 5; } } } else { enemy.buffTimer -= 1; } } // 救出 let hitHostage = [[1,0], [0,1], [-1,0], [0,-1]].some(w => player.x + w[0] === hostage.x && player.y + w[1] === hostage.y); if (hitHostage) { hostage.buff = Buff.rescue; } if (hostage.buff === Buff.rescue) { let chaseVec = chase(player.x, player.y, hostage.x, hostage.y); hostage.x += chaseVec[0]; hostage.y += chaseVec[1]; } } //ゴール条件 if (hostage.x === 1 && hostage.y === 1){ background(0,0,255); textAlign(LEFT, TOP); fill(255); text('救出成功',150,200); noLoop(); } //ゲームオーバー条件 if (countWalls(hostage.x, hostage.y) >= 8) { background(255,0,0); textAlign(LEFT, TOP); fill(15); text('ゲームオーバー',120,200); noLoop(); } textSize(34); for (let actor of actors) { let w = width / mazeWidth; textAlign(LEFT, TOP); text(actor.image, w * actor.x, w * actor.y); } }