export function startShootingGame(backgroundImage) {
return new Promise((resolve) => {
const gameContainer = document.createElement('div');
gameContainer.style.position = 'fixed';
gameContainer.style.top = 0;
gameContainer.style.left = 0;
gameContainer.style.width = '100vw';
gameContainer.style.height = '100vh';
gameContainer.style.zIndex = 9999;
document.body.appendChild(gameContainer);
const scene = new THREE.Scene();
const camera = new THREE.OrthographicCamera(
window.innerWidth / -2, window.innerWidth / 2,
window.innerHeight / 2, window.innerHeight / -2,
1, 1000
);
camera.position.z = 10;
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
gameContainer.appendChild(renderer.domElement);
const loader = new THREE.TextureLoader();
loader.load(backgroundImage, (texture) => {
scene.background = texture;
});
const playerGeometry = new THREE.BoxGeometry(30, 30, 1);
const playerMaterial = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
const player = new THREE.Mesh(playerGeometry, playerMaterial);
player.position.x = -200;
scene.add(player);
const bullets = [];
const enemies = [];
let score = 0;
let gameActive = true;
const keys = { up: false, down: false, left: false, right: false, space: false };
// キーボード入力イベント
document.addEventListener('keydown', (event) => {
if (event.key) {
switch (event.key.toLowerCase()) {
case 'w': keys.up = true; break;
case 's': keys.down = true; break;
case 'a': keys.left = true; break;
case 'd': keys.right = true; break;
case ' ': keys.space = true; break;
}
}
});
document.addEventListener('keyup', (event) => {
if (event.key) {
switch (event.key.toLowerCase()) {
case 'w': keys.up = false; break;
case 's': keys.down = false; break;
case 'a': keys.left = false; break;
case 'd': keys.right = false; break;
case ' ': keys.space = false; break;
}
}
});
let count = 20;
const infoBox = document.createElement('div');
infoBox.style.position = 'absolute';
infoBox.style.top = '10px';
infoBox.style.left = '10px';
infoBox.style.color = 'blue';
infoBox.style.fontSize = '20px';
infoBox.textContent = `残り時間: ${count}秒`;
gameContainer.appendChild(infoBox);
const countDown = setInterval(() => {
if (!gameActive) return;
count--;
infoBox.textContent = `残り時間: ${count}秒`;
if (count === 0) gameStop();
}, 1000);
function gameStop() {
clearInterval(countDown);
gameActive = false;
cancelAnimationFrame(animationId);
document.body.removeChild(gameContainer);
resolve(score);
}
let lastShot = 0;
let animationId;
// タッチ操作用のボタンを作成
const touchControls = document.createElement('div');
touchControls.style.position = 'absolute';
touchControls.style.bottom = '20px';
touchControls.style.left = '20px';
touchControls.style.width = '150px';
touchControls.style.height = '150px';
touchControls.style.zIndex = 10000;
touchControls.style.display = 'grid';
touchControls.style.gridTemplateColumns = 'repeat(3, 50px)';
touchControls.style.gridGap = '5px';
gameContainer.appendChild(touchControls);
const fireButton = document.createElement('button');
fireButton.textContent = 'FIRE';
fireButton.style.position = 'absolute';
fireButton.style.bottom = '20px';
fireButton.style.right = '20px';
fireButton.style.width = '80px';
fireButton.style.height = '80px';
fireButton.style.fontSize = '16px';
fireButton.style.zIndex = 10000;
gameContainer.appendChild(fireButton);
const directions = ['↑', '←', '↓', '→'];
const directionKeys = ['up', 'left', 'down', 'right'];
directions.forEach((label, index) => {
const button = document.createElement('button');
button.textContent = label;
button.style.fontSize = '20px';
button.style.width = '50px';
button.style.height = '50px';
touchControls.appendChild(button);
button.addEventListener('touchstart', () => {
keys[directionKeys[index]] = true;
});
button.addEventListener('touchend', () => {
keys[directionKeys[index]] = false;
});
});
fireButton.addEventListener('touchstart', () => {
keys.space = true;
});
fireButton.addEventListener('touchend', () => {
keys.space = false;
});
function animate() {
if (!gameActive) return;
animationId = requestAnimationFrame(animate);
const time = performance.now();
if (keys.up) player.position.y += 6;
if (keys.down) player.position.y -= 6;
if (keys.left) player.position.x -= 6;
if (keys.right) player.position.x += 6;
if (keys.space && time - lastShot > 250) {
const bullet = new THREE.Mesh(
new THREE.BoxGeometry(20, 10, 1),
new THREE.MeshBasicMaterial({ color: 0x00ff00 })
);
bullet.position.set(player.position.x + 20, player.position.y, 0);
bullets.push(bullet);
scene.add(bullet);
lastShot = time;
}
bullets.forEach((bullet, index) => {
bullet.position.x += 15;
if (bullet.position.x > window.innerWidth / 2) {
scene.remove(bullet);
bullets.splice(index, 1);
}
});
if (Math.random() < 0.02) {
const enemy = new THREE.Mesh(
new THREE.BoxGeometry(30, 30, 1),
new THREE.MeshBasicMaterial({ color: 0xff0000 })
);
enemy.position.set(window.innerWidth / 2, (Math.random() - 0.5) * window.innerHeight, 0);
enemies.push(enemy);
scene.add(enemy);
}
enemies.forEach((enemy, eIndex) => {
enemy.position.x -= 3;
bullets.forEach((bullet, bIndex) => {
if (bullet.position.distanceTo(enemy.position) < 20) {
scene.remove(enemy);
enemies.splice(eIndex, 1);
scene.remove(bullet);
bullets.splice(bIndex, 1);
score++;
}
});
});
renderer.render(scene, camera);
}
animate();
});
}