<div id="eventBox">
<canvas id="gameCanvas" width="800" height="800"></canvas>
<div id="controls">
<div id="leftButton" class="controlButton">←</div>
<div id="shootButton" class="controlButton">SHOOT</div>
<div id="rightButton" class="controlButton">→</div>
</div>
<button id="startButton">GAME START</button>
<div id="couponLink"><a>こちらをクリック</a></div>
</div>
* {
margin: 0;
padding: 0;
}
body {
background-color: #333;
}
#eventBox {
position: relative;
width: 100%;
max-width: 800px;
height: auto;
margin: 0 auto;
}
canvas {
background: black;
display: block;
width: 100%;
height: auto;
aspect-ratio: 1;
margin: 0 auto;
}
#startButton, #couponLink {
display: block;
margin: 20px auto;
padding: 10px 20px;
font-size: 20px;
text-align: center;
}
#couponLink {
position: absolute;
top: 30%;
left: 0;
right: 0;
bottom: 0;
margin: auto;
display: none;
font-family: sans-serif;
height: 1.2em;
text-decoration: none;
color: white;
cursor: pointer;
}
.controlButton {
display: block;
margin: 0;
padding: 10px;
font-size: 16px;
text-align: center;
width: 40px;
height: 30px;
line-height: 30px;
background-color: lightgray;
border-radius: 4px;
}
#shootButton {
width: 120px;
}
#controls {
display: flex;
justify-content: center;
align-items: center;
margin-top: 20px;
column-gap: 10px;
}
const canvas = document.getElementById('gameCanvas');
const context = canvas.getContext('2d');
const startButton = document.getElementById('startButton');
const couponLink = document.getElementById('couponLink');
const leftButton = document.getElementById('leftButton');
const rightButton = document.getElementById('rightButton');
const shootButton = document.getElementById('shootButton');
const player = {
x: ( canvas.width / 2 ) - 25,
y: canvas.height - 50,
width: 50,
height: 50,
speed: 5,
dx: 0,
dy: 0
};
const bullets = [];
const enemies = [];
const bosses = [];
const playerImage = new Image();
playerImage.src = 'https://nag-design.com/embed/shooting/player.svg';
const enemyImage = new Image();
enemyImage.src = 'https://nag-design.com/embed/shooting/enemy.svg';
const bossImage = new Image();
bossImage.src = 'https://nag-design.com/embed/shooting/boss.svg';
let enemySpawnInterval = 1000;
let bossSpawnInterval = 10000;
let lastEnemySpawnTime = Date.now();
let lastBossSpawnTime = Date.now();
let couponMessage = '';
let couponMessageTimeout = 0;
let gameState = 'start'; // 'start', 'playing', 'gameover', 'coupon'
document.addEventListener('keydown', movePlayer);
document.addEventListener('keyup', stopPlayer);
document.addEventListener('keydown', shootBullet);
startButton.addEventListener('click', startGame);
leftButton.addEventListener('mousedown', () => movePlayer({ key: 'ArrowLeft' }));
rightButton.addEventListener('mousedown', () => movePlayer({ key: 'ArrowRight' }));
shootButton.addEventListener('mousedown', () => shootBullet({ key: ' ' }));
leftButton.addEventListener('mouseup', stopPlayer);
rightButton.addEventListener('mouseup', stopPlayer);
leftButton.addEventListener('touchstart', (e) => {
e.preventDefault();
movePlayer({ key: 'ArrowLeft' });
});
rightButton.addEventListener('touchstart', (e) => {
e.preventDefault();
movePlayer({ key: 'ArrowRight' });
});
shootButton.addEventListener('touchstart', (e) => {
e.preventDefault();
shootBullet({ key: ' ' });
});
leftButton.addEventListener('touchend', (e) => {
e.preventDefault();
stopPlayer({ key: 'ArrowLeft' });
});
rightButton.addEventListener('touchend', (e) => {
e.preventDefault();
stopPlayer({ key: 'ArrowRight' });
});
function startGame() {
gameState = 'playing';
resetGame();
startButton.style.display = 'none';
couponLink.style.display = 'none';
}
function resetGame() {
player.x = ( canvas.width / 2 ) - 25;
player.y = canvas.height - 70;
bullets.length = 0;
enemies.length = 0;
bosses.length = 0;
lastEnemySpawnTime = Date.now();
lastBossSpawnTime = Date.now();
}
function movePlayer(e) {
if (gameState !== 'playing') return;
if (e.key === 'ArrowRight') {
player.dx = player.speed;
} else if (e.key === 'ArrowLeft') {
player.dx = -player.speed;
}
}
function stopPlayer(e) {
if (e.key === 'ArrowRight' || e.key === 'ArrowLeft' || e.type === 'mouseup' || e.type === 'touchend') {
player.dx = 0;
}
}
function shootBullet(e) {
if (gameState !== 'playing') return;
if (e.key === ' ') {
bullets.push({
x: player.x + player.width / 2 - 2.5,
y: player.y,
width: 5,
height: 10,
speed: 7
});
}
}
function update() {
if (gameState !== 'playing') return;
player.x += player.dx;
player.y += player.dy;
bullets.forEach((bullet, index) => {
bullet.y -= bullet.speed;
if (bullet.y < 0) {
bullets.splice(index, 1);
}
});
if (Date.now() - lastEnemySpawnTime > enemySpawnInterval) {
enemies.push({
x: Math.random() * (canvas.width - 50),
y: 0,
width: 50,
height: 50,
speed: 3
});
lastEnemySpawnTime = Date.now();
}
if (Date.now() - lastBossSpawnTime > bossSpawnInterval) {
bosses.push({
x: Math.random() * (canvas.width - 100),
y: 0,
width: 100,
height: 100,
speed: 2,
hp: 2
});
lastBossSpawnTime = Date.now();
}
enemies.forEach((enemy, index) => {
enemy.y += enemy.speed;
if (enemy.y > canvas.height) {
enemies.splice(index, 1);
}
});
bosses.forEach((boss, index) => {
boss.y += boss.speed;
if (boss.y > canvas.height) {
bosses.splice(index, 1);
}
});
detectCollisions();
checkGameOver();
}
function detectCollisions() {
bullets.forEach((bullet, bulletIndex) => {
enemies.forEach((enemy, enemyIndex) => {
if (bullet.x < enemy.x + enemy.width &&
bullet.x + bullet.width > enemy.x &&
bullet.y < enemy.y + enemy.height &&
bullet.y + bullet.height > enemy.y) {
bullets.splice(bulletIndex, 1);
enemies.splice(enemyIndex, 1);
}
});
bosses.forEach((boss, bossIndex) => {
if (bullet.x < boss.x + boss.width &&
bullet.x + bullet.width > boss.x &&
bullet.y < boss.y + boss.height &&
bullet.y + bullet.height > boss.y) {
bullets.splice(bulletIndex, 1);
boss.hp -= 1;
if (boss.hp <= 0) {
bosses.splice(bossIndex, 1);
displayCouponMessage();
}
}
});
});
}
function checkGameOver() {
enemies.forEach((enemy) => {
if (player.x < enemy.x + enemy.width &&
player.x + player.width > enemy.x &&
player.y < enemy.y + enemy.height &&
player.y + player.height > enemy.y) {
gameOver();
}
});
bosses.forEach((boss) => {
if (player.x < boss.x + boss.width &&
player.x + player.width > boss.x &&
player.y < boss.y + boss.height &&
player.y + player.height > boss.y) {
gameOver();
}
});
}
function gameOver() {
gameState = 'gameover';
startButton.style.display = 'block';
startButton.textContent = 'RESTART';
}
function displayCouponMessage() {
couponMessage = 'クーポンGET!';
couponMessageTimeout = Date.now();
gameState = 'coupon';
couponLink.style.display = 'block';
}
function drawPlayer() {
context.drawImage(playerImage, player.x, player.y, player.width, player.height);
}
function drawBullets() {
context.fillStyle = 'red';
bullets.forEach(bullet => {
context.fillRect(bullet.x, bullet.y, bullet.width, bullet.height);
});
}
function drawEnemies() {
enemies.forEach(enemy => {
context.drawImage(enemyImage, enemy.x, enemy.y, enemy.width, enemy.height);
});
}
function drawBosses() {
bosses.forEach(boss => {
context.drawImage(bossImage, boss.x, boss.y, boss.width, boss.height);
});
}
function drawCouponMessage() {
if (couponMessage) {
context.fillStyle = 'white';
context.font = '30px Arial';
context.textAlign = 'center';
context.fillText(couponMessage, canvas.width / 2, canvas.height / 2);
if (Date.now() - couponMessageTimeout > 2000) {
couponMessage = '';
}
}
}
function drawStartScreen() {
context.clearRect(0, 0, canvas.width, canvas.height);
drawPlayer();
}
function drawGameOverScreen() {
context.fillStyle = 'white';
context.font = '50px Arial';
context.textAlign = 'center';
context.fillText('GAME OVER', canvas.width / 2, canvas.height / 2);
}
function draw() {
context.clearRect(0, 0, canvas.width, canvas.height);
if (gameState === 'start') {
drawStartScreen();
} else if (gameState === 'playing') {
drawPlayer();
drawBullets();
drawEnemies();
drawBosses();
drawCouponMessage();
} else if (gameState === 'gameover') {
drawGameOverScreen();
} else if (gameState === 'coupon') {
drawCouponMessage();
}
}
function gameLoop() {
update();
draw();
requestAnimationFrame(gameLoop);
}
gameLoop();
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.