Щит для игры
创建于:2025年1月10日
创建于:2025年1月10日
Можно я скину тебе свой код js игры космос там где падаю метеориты и тд а ты добавишь чтобы падала пнг щита и когда корабль попадет пулей в нее то активируется щит на 10 секунд од метеоритов и на корабле появляется анимация как будто щит возможно неоновая и нужно чтобы щит падал 2 раза за игру в рандом момент игра идет 1 минуту В КОДЕ МОЕМ УЖЕ ЕСТЬ КАКАЯ ТО СИСТЕМА ДЛЯ ЩИТА НО ОНА ПЛОХАЯ И НЕ РАБОТАЕТ
const gameContainer = document.getElementById('game-container');
const ship = document.getElementById('ship');
const scoreElement = document.getElementById('score');
const countdownElement = document.getElementById('countdown');
const soundOnButton = document.getElementById('sound-on');
const soundOffButton = document.getElementById('sound-off');
const shield = document.getElementById('shield'); // Элемент щита
const shieldEffect = document.getElementById('shield-effect'); // Элемент эффекта щита
let score = 0;
let shipX = gameContainer.clientWidth / 2 - 25;
let shipSpeed = 10;
let meteorSpeed = 5;
let bulletSpeed = 10;
let soundEnabled = true;
let shieldActive = false; // Статус щита
let shieldTimeout; // Таймер для щита
let shieldDuration = 10000; // Длительность щита 10 секунд
const shipWidth = ship.clientWidth;
const shipHeight = ship.clientHeight;
let touchStartX = 0;
let bullets = [];
let gameStarted = false;
// Звуки
const shotSound = new Audio('shot.mp3');
const reloadSound = new Audio('reload.mp3');
// Управление движением корабля
gameContainer.addEventListener('touchstart', handleTouchStart);
gameContainer.addEventListener('touchmove', handleTouchMove);
document.addEventListener('keydown', moveShip);
// Обработчик для начала касания
function handleTouchStart(event) {
if (!gameStarted) return; // Игнорировать до старта игры
touchStartX = event.touches[0].clientX;
createBullet();
}
// Обработчик для перемещения пальца
function handleTouchMove(event) {
const touchCurrentX = event.touches[0].clientX;
const deltaX = touchCurrentX - touchStartX;
textshipX = Math.max(0, Math.min(gameContainer.clientWidth - shipWidth, shipX + deltaX)); touchStartX = touchCurrentX; ship.style.left = `${shipX}px`;
}
// Управление с клавиатуры
function moveShip(event) {
if (!gameStarted) return; // Игнорировать до старта игры
if (event.key === 'ArrowLeft' && shipX > 0) {
shipX -= shipSpeed;
}
if (event.key === 'ArrowRight' && shipX < gameContainer.clientWidth - shipWidth) {
shipX += shipSpeed;
}
ship.style.left = ${shipX}px
;
}
// Функция для создания пули
function createBullet() {
const bullet = document.createElement('div');
bullet.classList.add('bullet');
bullet.style.left = ${shipX + ship.offsetWidth / 2 - bullet.offsetWidth / 2}px
;
bullet.style.top = ${gameContainer.clientHeight - 60}px
;
gameContainer.appendChild(bullet);
textif (soundEnabled) shotSound.play(); moveBullet(bullet);
}
// Движение пули
function moveBullet(bullet) {
let bulletY = parseInt(bullet.style.top);
textconst bulletInterval = setInterval(() => { bulletY -= bulletSpeed; bullet.style.top = `${bulletY}px`; if (bulletY <= 0) { clearInterval(bulletInterval); gameContainer.removeChild(bullet); } document.querySelectorAll('.meteor').forEach((meteor) => { const meteorX = parseInt(meteor.style.left); const meteorY = parseInt(meteor.style.top); if ( bulletY <= meteorY + 40 && bulletY >= meteorY && parseInt(bullet.style.left) >= meteorX && parseInt(bullet.style.left) <= meteorX + 40 ) { clearInterval(bulletInterval); gameContainer.removeChild(bullet); gameContainer.removeChild(meteor); score++; scoreElement.textContent = `Score: ${score}`; reloadSound.play(); } }); }, 20);
}
// Функция для создания метеоритов
function createMeteor() {
const meteor = document.createElement('div');
meteor.classList.add('meteor');
const meteorX = Math.random() * (gameContainer.clientWidth - 40);
meteor.style.left = ${meteorX}px
;
meteor.style.top = -40px
;
gameContainer.appendChild(meteor);
moveMeteor(meteor);
}
// Движение метеорита
function moveMeteor(meteor) {
let meteorY = -40;
const meteorInterval = setInterval(() => {
meteorY += meteorSpeed;
meteor.style.top = ${meteorY}px
;
textif (meteorY >= gameContainer.clientHeight) { clearInterval(meteorInterval); gameContainer.removeChild(meteor); } // Проверка на столкновение с кораблем if (checkCollision(ship, meteor)) { handleCollision(meteor); clearInterval(meteorInterval); gameContainer.removeChild(meteor); } }, 20);
}
// Функция проверки столкновения
function checkCollision(ship, meteor) {
const meteorRect = meteor.getBoundingClientRect();
const shipRect = ship.getBoundingClientRect();
textreturn !( meteorRect.top > shipRect.bottom || meteorRect.bottom < shipRect.top || meteorRect.right < shipRect.left || meteorRect.left > shipRect.right );
}
// Функция для обработки столкновения
function handleCollision(meteor) {
if (shieldActive) {
// Если щит активен, игнорируем столкновение
return;
}
text// Уменьшаем счёт на 10% const scoreChange = Math.round(score * 0.1); score -= scoreChange; // Обновляем отображение счёта score = Math.max(score, 0); // Чтобы счёт не стал отрицательным scoreElement.textContent = `Score: ${score}`; // Добавляем анимацию на корабль ship.classList.add('shake'); setTimeout(() => { ship.classList.remove('shake'); }, 500); // Отображаем анимацию числа, которое исчезает showScoreChange(scoreChange, meteor);
}
// Анимация изменения счёта
function showScoreChange(amount, meteor) {
const scoreChange = document.createElement('div');
scoreChange.classList.add('score-change');
scoreChange.textContent = ${amount > 0 ? '-' : '+'}${amount}
;
text// Позиционируем анимацию рядом с метеоритом const meteorRect = meteor.getBoundingClientRect(); scoreChange.style.left = `${meteorRect.left + meteorRect.width / 2 - 20}px`; scoreChange.style.top = `${meteorRect.top}px`; gameContainer.appendChild(scoreChange); setTimeout(() => { scoreChange.remove(); }, 1000);
}
// Функция для отсчета перед началом игры
function startCountdown() {
const colors = ["red", "orange", "green"];
let counter = 3;
countdownElement.textContent = counter;
countdownElement.classList.add(colors[counter - 1]);
textconst countdownInterval = setInterval(() => { counter--; countdownElement.textContent = counter; countdownElement.className = colors[counter - 1]; if (counter === 0) { clearInterval(countdownInterval); countdownElement.style.display = 'none'; startGame(); startTimer(); // Запуск таймера после отсчета } }, 1000);
}
// Запуск игры
function startGame() {
gameStarted = true;
setInterval(createBullet, 500);
setInterval(createMeteor, 1000);
setInterval(createShield, 30000); // Создаем щит каждые 30 секунд
}
// Функция для создания щита
function createShield() {
const shieldX = Math.random() * (gameContainer.clientWidth - 40);
shield.style.left = ${shieldX}px
;
shield.style.top = -40px
;
shield.style.display = 'block';
moveShield(shield);
}
// Движение щита
function moveShield(shield) {
let shieldY = -40;
const shieldInterval = setInterval(() => {
shieldY += meteorSpeed;
shield.style.top = ${shieldY}px
;
textif (shieldY >= gameContainer.clientHeight) { clearInterval(shieldInterval); shield.style.display = 'none'; } // Проверка на столкновение с пулей document.querySelectorAll('.bullet').forEach((bullet) => { const bulletX = parseInt(bullet.style.left); const bulletY = parseInt(bullet.style.top); if ( bulletY <= shieldY + 40 && bulletY >= shieldY && bulletX >= parseInt(shield.style.left) && bulletX <= parseInt(shield.style.left) + 40 ) { clearInterval(shieldInterval); shield.style.display = 'none'; activateShield(); } }); }, 20);
}
// Активация щита
function activateShield() {
shieldActive = true;
shieldEffect.style.display = 'block';
shieldEffect.style.left = ${shipX - 30}px
;
shieldEffect.style.top = ${gameContainer.clientHeight - 100}px
;
text// Деактивация щита через 10 секунд shieldTimeout = setTimeout(() => { shieldActive = false; shieldEffect.style.display = 'none'; }, shieldDuration);
}
// Переключение звука
function toggleSound(isEnabled) {
soundEnabled = isEnabled;
soundOnButton.style.display = isEnabled ? 'none' : 'block';
soundOffButton.style.display = isEnabled ? 'block' : 'none';
textif (isEnabled) { // Включаем звук shotSound.play(); } else { // Останавливаем звук, если звук выключен shotSound.pause(); shotSound.currentTime = 0; // Сбросить воспроизведение звука }
}
// Таймер на 1 минуту 3 секунды
let countdownTime = 60; // Таймер на 1 минуту
let countdownInterval;
const timerElement = document.getElementById('timer');
// Функция для запуска таймера
function startTimer() {
countdownInterval = setInterval(function () {
countdownTime--;
let minutes = Math.floor(countdownTime / 60);
let seconds = countdownTime % 60;
timerElement.textContent = ${minutes}:${seconds < 10 ? '0' : ''}${seconds}
;
textif (countdownTime <= 0) { clearInterval(countdownInterval); // Останавливаем таймер endGame(); // Заканчиваем игру } }, 1000); // обновляем каждую секунду
}
let totalScore = localStorage.getItem('totalScore') || 0; // Получаем общую сумму очков из localStorage
// Добавляем текущий результат к общим очкам
totalScore += score;
// Сохраняем общую сумму очков в localStorage
localStorage.setItem('totalScore', totalScore);
// Функция для завершения игры
function endGame() {
alert('Время вышло!'); // Оповещаем игрока
stopGameSound(); // Останавливаем звуки игры
window.location.href = "index.html"; // Возвращаем в главное меню
}
// Загрузка общих очков при загрузке страницы
document.addEventListener("DOMContentLoaded", function() {
const totalScoreElement = document.getElementById('total-score');
totalScoreElement.textContent = totalScore; // Показываем общие очки на странице
});
// Функция для остановки звуков игры (включая shotSound и reloadSound)
function stopGameSound() {
if (soundEnabled) {
shotSound.pause();
shotSound.currentTime = 0; // Сбрасываем время
reloadSound.pause();
reloadSound.currentTime = 0; // Сбрасываем время
}
}
// Запуск отсчета перед игрой
startCountdown();
// Сохраняем score в localStorage
let highScore = localStorage.getItem('highScore') || 0;
if (score > highScore) {
localStorage.setItem('highScore', score);
}
Чтобы обеспечить появление щита на поле два раза за игру в случайные моменты и активировать его при попадании пули, внесём следующие изменения в ваш код:
Вместо текущего циклического создания щитов каждые 30 секунд изменим логику так, чтобы щит появлялся ровно два раза в случайные моменты в течение игры. Для этого в функции startGame()
будем генерировать два случайных момента в пределах продолжительности игры (60 секунд) и использовать setTimeout
для вызова createShield()
в эти моменты.
Найдём секцию кода в startGame()
и заменим планирование щита:
jsfunction startGame() { gameStarted = true; setInterval(createBullet, 500); setInterval(createMeteor, 1000); // Запланировать два падения щита в случайные моменты в течение 60 секунд const firstShieldTime = Math.random() * 60000; // время в мс до первого появления const secondShieldTime = Math.random() * 60000; // время в мс до второго появления setTimeout(createShield, firstShieldTime); setTimeout(createShield, secondShieldTime); }
В вашем коде уже реализована функция createShield()
и moveShield(shield)
. Они создают щит, заставляют его падать, и проверяют столкновение с пулей. Данный функционал оставляем без изменений, поскольку он соответствует требованиям.
В коде функция activateShield()
уже включает отображение эффекта щита на корабле:
jsfunction activateShield() { shieldActive = true; shieldEffect.style.display = 'block'; shieldEffect.style.left = `${shipX - 30}px`; shieldEffect.style.top = `${gameContainer.clientHeight - 100}px`; // Деактивация щита через 10 секунд shieldTimeout = setTimeout(() => { shieldActive = false; shieldEffect.style.display = 'none'; }, shieldDuration); }
Чтобы придать эффекту неоновый вид (неоновая анимация), добавьте соответствующие CSS-стили для элемента #shield-effect
(или любого другого выбранного селектора). Например:
css#shield-effect { width: 100px; height: 100px; border-radius: 50%; border: 2px solid cyan; box-shadow: 0 0 10px cyan, 0 0 20px cyan, 0 0 30px cyan; pointer-events: none; /* чтобы щит не мешал кликам */ display: none; position: absolute; }
Анимация может быть добавлена с помощью CSS @keyframes или других эффектов по вашему усмотрению.
jsfunction startGame() { gameStarted = true; setInterval(createBullet, 500); setInterval(createMeteor, 1000); // Запланировать два падения щита в случайные моменты в течение 60 секунд const firstShieldTime = Math.random() * 60000; // время в мс до первого появления const secondShieldTime = Math.random() * 60000; // время в мс до второго появления setTimeout(createShield, firstShieldTime); setTimeout(createShield, secondShieldTime); }
При этом остальная логика падения, активации и деактивации щита, а также отображение эффекта остаются без изменений. Не забудьте добавить стили для неонового щита в вашем CSS, чтобы эффект стал более заметным.
Таким образом, щит будет появляться два раза за игру в случайные моменты, активироваться при попадании пули и отображать неоновую анимацию на корабле на 10 секунд.
Добавь изменения в мой .js и скинь полный мой код с изменениями для системы щита
Ниже приведён полный код вашего JavaScript с внесёнными изменениями для системы щита, включая планирование двух появлений щита в случайные моменты игры:
jsconst gameContainer = document.getElementById('game-container'); const ship = document.getElementById('ship'); const scoreElement = document.getElementById('score'); const countdownElement = document.getElementById('countdown'); const soundOnButton = document.getElementById('sound-on'); const soundOffButton = document.getElementById('sound-off'); const shield = document.getElementById('shield'); // Элемент щита const shieldEffect = document.getElementById('shield-effect'); // Элемент эффекта щита let score = 0; let shipX = gameContainer.clientWidth / 2 - 25; let shipSpeed = 10; let meteorSpeed = 5; let bulletSpeed = 10; let soundEnabled = true; let shieldActive = false; // Статус щита let shieldTimeout; // Таймер для щита let shieldDuration = 10000; // Длительность щита 10 секунд const shipWidth = ship.clientWidth; const shipHeight = ship.clientHeight; let touchStartX = 0; let bullets = []; let gameStarted = false; // Звуки const shotSound = new Audio('shot.mp3'); const reloadSound = new Audio('reload.mp3'); // Управление движением корабля gameContainer.addEventListener('touchstart', handleTouchStart); gameContainer.addEventListener('touchmove', handleTouchMove); document.addEventListener('keydown', moveShip); // Обработчик для начала касания function handleTouchStart(event) { if (!gameStarted) return; // Игнорировать до старта игры touchStartX = event.touches[0].clientX; createBullet(); } // Обработчик для перемещения пальца function handleTouchMove(event) { const touchCurrentX = event.touches[0].clientX; const deltaX = touchCurrentX - touchStartX; shipX = Math.max(0, Math.min(gameContainer.clientWidth - shipWidth, shipX + deltaX)); touchStartX = touchCurrentX; ship.style.left = `${shipX}px`; } // Управление с клавиатуры function moveShip(event) { if (!gameStarted) return; // Игнорировать до старта игры if (event.key === 'ArrowLeft' && shipX > 0) { shipX -= shipSpeed; } if (event.key === 'ArrowRight' && shipX < gameContainer.clientWidth - shipWidth) { shipX += shipSpeed; } ship.style.left = `${shipX}px`; } // Функция для создания пули function createBullet() { const bullet = document.createElement('div'); bullet.classList.add('bullet'); bullet.style.left = `${shipX + ship.offsetWidth / 2 - bullet.offsetWidth / 2}px`; bullet.style.top = `${gameContainer.clientHeight - 60}px`; gameContainer.appendChild(bullet); if (soundEnabled) shotSound.play(); moveBullet(bullet); } // Движение пули function moveBullet(bullet) { let bulletY = parseInt(bullet.style.top); const bulletInterval = setInterval(() => { bulletY -= bulletSpeed; bullet.style.top = `${bulletY}px`; if (bulletY <= 0) { clearInterval(bulletInterval); gameContainer.removeChild(bullet); } document.querySelectorAll('.meteor').forEach((meteor) => { const meteorX = parseInt(meteor.style.left); const meteorY = parseInt(meteor.style.top); if ( bulletY <= meteorY + 40 && bulletY >= meteorY && parseInt(bullet.style.left) >= meteorX && parseInt(bullet.style.left) <= meteorX + 40 ) { clearInterval(bulletInterval); gameContainer.removeChild(bullet); gameContainer.removeChild(meteor); score++; scoreElement.textContent = `Score: ${score}`; reloadSound.play(); } }); }, 20); } // Функция для создания метеоритов function createMeteor() { const meteor = document.createElement('div'); meteor.classList.add('meteor'); const meteorX = Math.random() * (gameContainer.clientWidth - 40); meteor.style.left = `${meteorX}px`; meteor.style.top = `-40px`; gameContainer.appendChild(meteor); moveMeteor(meteor); } // Движение метеорита function moveMeteor(meteor) { let meteorY = -40; const meteorInterval = setInterval(() => { meteorY += meteorSpeed; meteor.style.top = `${meteorY}px`; if (meteorY >= gameContainer.clientHeight) { clearInterval(meteorInterval); gameContainer.removeChild(meteor); } // Проверка на столкновение с кораблем if (checkCollision(ship, meteor)) { handleCollision(meteor); clearInterval(meteorInterval); gameContainer.removeChild(meteor); } }, 20); } // Функция проверки столкновения function checkCollision(ship, meteor) { const meteorRect = meteor.getBoundingClientRect(); const shipRect = ship.getBoundingClientRect(); return !( meteorRect.top > shipRect.bottom || meteorRect.bottom < shipRect.top || meteorRect.right < shipRect.left || meteorRect.left > shipRect.right ); } // Функция для обработки столкновения function handleCollision(meteor) { if (shieldActive) { // Если щит активен, игнорируем столкновение return; } // Уменьшаем счёт на 10% const scoreChange = Math.round(score * 0.1); score -= scoreChange; // Обновляем отображение счёта score = Math.max(score, 0); // Чтобы счёт не стал отрицательным scoreElement.textContent = `Score: ${score}`; // Добавляем анимацию на корабль ship.classList.add('shake'); setTimeout(() => { ship.classList.remove('shake'); }, 500); // Отображаем анимацию числа, которое исчезает showScoreChange(scoreChange, meteor); } // Анимация изменения счёта function showScoreChange(amount, meteor) { const scoreChange = document.createElement('div'); scoreChange.classList.add('score-change'); scoreChange.textContent = `${amount > 0 ? '-' : '+'}${amount}`; // Позиционируем анимацию рядом с метеоритом const meteorRect = meteor.getBoundingClientRect(); scoreChange.style.left = `${meteorRect.left + meteorRect.width / 2 - 20}px`; scoreChange.style.top = `${meteorRect.top}px`; gameContainer.appendChild(scoreChange); setTimeout(() => { scoreChange.remove(); }, 1000); } // Функция для отсчета перед началом игры function startCountdown() { const colors = ["red", "orange", "green"]; let counter = 3; countdownElement.textContent = counter; countdownElement.classList.add(colors[counter - 1]); const countdownInterval = setInterval(() => { counter--; countdownElement.textContent = counter; countdownElement.className = colors[counter - 1]; if (counter === 0) { clearInterval(countdownInterval); countdownElement.style.display = 'none'; startGame(); startTimer(); // Запуск таймера после отсчета } }, 1000); } // Запуск игры function startGame() { gameStarted = true; setInterval(createBullet, 500); setInterval(createMeteor, 1000); // Запланировать два падения щита в случайные моменты в течение 60 секунд const firstShieldTime = Math.random() * 60000; // время в мс до первого появления const secondShieldTime = Math.random() * 60000; // время в мс до второго появления setTimeout(createShield, firstShieldTime); setTimeout(createShield, secondShieldTime); } // Функция для создания щита function createShield() { const shieldX = Math.random() * (gameContainer.clientWidth - 40); shield.style.left = `${shieldX}px`; shield.style.top = `-40px`; shield.style.display = 'block'; moveShield(shield); } // Движение щита function moveShield(shield) { let shieldY = -40; const shieldInterval = setInterval(() => { shieldY += meteorSpeed; shield.style.top = `${shieldY}px`; if (shieldY >= gameContainer.clientHeight) { clearInterval(shieldInterval); shield.style.display = 'none'; } // Проверка на столкновение с пулей document.querySelectorAll('.bullet').forEach((bullet) => { const bulletX = parseInt(bullet.style.left); const bulletY = parseInt(bullet.style.top); if ( bulletY <= shieldY + 40 && bulletY >= shieldY && bulletX >= parseInt(shield.style.left) && bulletX <= parseInt(shield.style.left) + 40 ) { clearInterval(shieldInterval); shield.style.display = 'none'; activateShield(); } }); }, 20); } // Активация щита function activateShield() { shieldActive = true; shieldEffect.style.display = 'block'; shieldEffect.style.left = `${shipX - 30}px`; shieldEffect.style.top = `${gameContainer.clientHeight - 100}px`; // Деактивация щита через 10 секунд shieldTimeout = setTimeout(() => { shieldActive = false; shieldEffect.style.display = 'none'; }, shieldDuration); } // Переключение звука function toggleSound(isEnabled) { soundEnabled = isEnabled; soundOnButton.style.display = isEnabled ? 'none' : 'block'; soundOffButton.style.display = isEnabled ? 'block' : 'none'; if (isEnabled) { // Включаем звук shotSound.play(); } else { // Останавливаем звук, если звук выключен shotSound.pause(); shotSound.currentTime = 0; // Сбросить воспроизведение звука } } // Таймер на 1 минуту let countdownTime = 60; // Таймер на 1 минуту let countdownInterval; const timerElement = document.getElementById('timer'); // Функция для запуска таймера function startTimer() { countdownInterval = setInterval(function () { countdownTime--; let minutes = Math.floor(countdownTime / 60); let seconds = countdownTime % 60; timerElement.textContent = `${minutes}:${seconds < 10 ? '0' : ''}${seconds}`; if (countdownTime <= 0) { clearInterval(countdownInterval); // Останавливаем таймер endGame(); // Заканчиваем игру } }, 1000); // обновляем каждую секунду } let totalScore = localStorage.getItem('totalScore') || 0; // Получаем общую сумму очков из localStorage // Добавляем текущий результат к общим очкам totalScore += score; // Сохраняем общую сумму очков в localStorage localStorage.setItem('totalScore', totalScore); // Функция для завершения игры function endGame() { alert('Время вышло!'); // Оповещаем игрока stopGameSound(); // Останавливаем звуки игры window.location.href = "index.html"; // Возвращаем в главное меню } // Загрузка общих очков при загрузке страницы document.addEventListener("DOMContentLoaded", function() { const totalScoreElement = document.getElementById('total-score'); totalScoreElement.textContent = totalScore; // Показываем общие очки на странице }); // Функция для остановки звуков игры (включая shotSound и reloadSound) function stopGameSound() { if (soundEnabled) { shotSound.pause(); shotSound.currentTime = 0; // Сбрасываем время reloadSound.pause(); reloadSound.currentTime = 0; // Сбрасываем время } } // Запуск отсчета перед игрой startCountdown(); // Сохраняем score в localStorage let highScore = localStorage.getItem('highScore') || 0; if (score > highScore) { localStorage.setItem('highScore', score); }
Примечания:
#shield
и #shield-effect
для отображения щита и его эффекта.css#shield-effect { width: 100px; height: 100px; border-radius: 50%; border: 2px solid cyan; box-shadow: 0 0 10px cyan, 0 0 20px cyan, 0 0 30px cyan; pointer-events: none; display: none; position: absolute; }
Таким образом, щит будет появляться дважды за игру в случайные моменты, активироваться при попадании пули и отображать неоновый эффект на корабле в течение 10 секунд.