<!DOCTYPE html>
<html>
<head>
<title>迷路アプリ</title>
<style>
#maze {
width: 600px;
height: 600px;
margin: 30px auto;
background-color: #eee;
position: relative;
}
#start, #goal {
width: 50px;
height: 50px;
background-color: #f00;
border-radius: 100%;
position: absolute;
}
.wall {
width: 100px;
height: 20px;
background-color: #333;
position: absolute;
transform-origin: 50% 50%;
transform: rotate(30deg);
}
.wall.n {
top: -10px;
left: 0;
}
.wall.ne {
top: -10px;
right: 0;
}
.wall.se {
bottom: -10px;
right: 0;
}
.wall.s {
bottom: -10px;
left: 0;
}
.wall.sw {
bottom: -10px;
left: 100px;
}
.wall.nw {
top: -10px;
left: 100px;
}
.char {
width: 50px;
height: 50px;
background-color: #00f;
border-radius: 100%;
position: absolute;
top: 0;
left: 0;
transition: transform .3s ease-in-out;
}
</style>
</head>
<body>
<div id="maze">
<div id="start"></div>
<div id="goal"></div>
<div class="wall n"></div>
<div class="wall ne"></div>
<div class="wall se"></div>
<div class="wall s"></div>
<div class="wall sw"></div>
<div class="wall nw"></div>
<div class="char"></div>
</div>
<script>
let char = document.querySelector('.char');
let walls = document.querySelectorAll('.wall');
let start = document.querySelector('#start');
let goal = document.querySelector('#goal');
let x = 0;
let y = 0;
let vx = 0;
let vy = 0;
let speed = 5;
let damping = 0.4;
let isStarted = false;
let isGameOver = false;
window.addEventListener('keydown', (event) => {
if(!isStarted || isGameOver) return;
let key = event.key;
if(key === 'ArrowRight') {
vx = speed;
vy = 0;
char.style.transform = 'rotate(0deg)';
} else if(key === 'ArrowDown') {
vx = 0;
vy = speed;
char.style.transform = 'rotate(90deg)';
} else if(key === 'ArrowLeft') {
vx = -speed;
vy = 0;
char.style.transform = 'rotate(180deg)';
} else if(key === 'ArrowUp') {
vx = 0;
vy = -speed;
char.style.transform = 'rotate(270deg)';
}
});
function checkCollision() {
if(x < 0) {
vx = -vx * damping;
x = 0;
} else if(x + char.offsetWidth > maze.offsetWidth) {
vx = -vx * damping;
x = maze.offsetWidth - char.offsetWidth;
}
if(y < 0) {
vy = -vy * damping;
y = 0;
} else if(y + char.offsetHeight > maze.offsetHeight) {
vy = -vy * damping;
y = maze.offsetHeight - char.offsetHeight;
}
walls.forEach(wall => {
if(checkOverlap(char, wall)) {
vx = -vx * damping;
vy = -vy * damping;
}
});
if(checkOverlap(char, goal)) {
isGameOver = true;
alert('ゴール!!!');
}
}
function checkOverlap(a, b) {
let rectA = a.getBoundingClientRect();
let rectB = b.getBoundingClientRect();
return !(
rectA.bottom < rectB.top ||
rectA.top > rectB.bottom ||
rectA.right < rectB.left ||
rectA.left > rectB.right
);
}
function move() {
if(!isStarted || isGameOver) return;
x += vx;
y += vy;
char.style.top = y + 'px';
char.style.left = x + 'px';
checkCollision();
requestAnimationFrame(move);
}
function init() {
isStarted = true;
requestAnimationFrame(move);
}
start.addEventListener('click', init);
</script>
</body>
</html>