Top.Mail.Ru
Ответы
Аватар пользователя

Фронтенд-разработка

Интерфейсы и пользовательский опыт: HTML/CSS, JavaScript-фреймворки, доступность, кросс-браузерность. Как ускорить загрузку страниц или почему не рендерится React компонент?
12 постов
14 участников
Аватар пользователя
12 часов назад
Оцените мою игру на HTML
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
<!DOCTYPE html>
<html lang="ru">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Игра "Стратегия"</title>
    <style>
      body {
        font-family: Arial, sans-serif;
        text-align: center;
        background: #f4f4f4;
        padding: 20px;
      }
      h1 {
        color: #222;
      }
      #scoreboard,
      #status {
        font-size: 20px;
        margin: 10px 0;
      }
      #board {
        display: grid;
        grid-template-columns: repeat(10, 40px);
        grid-gap: 2px;
        margin: auto;
        width: fit-content;
        border: 2px solid #333;
        background: #ccc;
      }
      .cell {
        width: 40px;
        height: 40px;
        background: #fff;
        border: 1px solid #999;
        cursor: pointer;
        transition: background 0.3s, border 0.3s;
        display: flex;
        align-items: center;
        justify-content: center;
        font-size: 18px;
        font-weight: bold;
      }
      .cell:hover {
        background: #f0f0f0;
      }
      .player1 {
        background-color: lightblue;
      }
      .player2 {
        background-color: lightgreen;
      }
      .winning {
        animation: pulse 1s infinite;
        border: 3px solid red !important;
      }
      @keyframes pulse {
        0% {
          transform: scale(1);
        }
        50% {
          transform: scale(1.1);
        }
        100% {
          transform: scale(1);
        }
      }
      #controls {
        margin-top: 20px;
      }
      button {
        padding: 10px 20px;
        font-size: 16px;
        cursor: pointer;
        border: none;
        background-color: #333;
        color: #fff;
        border-radius: 5px;
        transition: background 0.3s;
        margin: 0 5px;
      }
      button:hover {
        background-color: #555;
      }
      @media (max-width: 500px) {
        #board {
          grid-template-columns: repeat(10, 30px);
          grid-gap: 2px;
        }
        .cell {
          width: 30px;
          height: 30px;
          font-size: 14px;
        }
      }
    </style>
  </head>
  <body>
    <h1>Игра "Стратегия"</h1>
    <div id="scoreboard">Игрок 1: 0 | Игрок 2: 0 | Ничья: 0</div>
    <div id="status">Ход игрока 1</div>
    <div id="board"></div>
    <div id="controls">
      <button id="undoBtn">Отмена хода</button>
      <button id="resetBtn">Новая игра</button>
    </div>
    <audio id="moveSound" src="move.mp3" preload="auto"></audio>
    <audio id="winSound" src="win.mp3" preload="auto"></audio>
    <script>
      const boardSize = 10;
      const winningCount = 5;
      let currentPlayer = 1;
      let gameActive = true;
      let score = { player1: 0, player2: 0, draws: 0 };
      let boardState = new Array(boardSize * boardSize).fill(0);
      let moveHistory = [];

      const boardElement = document.getElementById("board");
      const statusElement = document.getElementById("status");
      const scoreboardElement = document.getElementById("scoreboard");
      const resetBtn = document.getElementById("resetBtn");
      const undoBtn = document.getElementById("undoBtn");
      const moveSound = document.getElementById("moveSound");
      const winSound = document.getElementById("winSound");

      function updateScoreboard() {
        scoreboardElement.textContent = `Игрок 1: ${score.player1} | Игрок 2: ${score.player2} | Ничья: ${score.draws}`;
      }

      function createBoard() {
        boardElement.innerHTML = "";
        for (let i = 0; i < boardSize * boardSize; i++) {
          const cell = document.createElement("div");
          cell.classList.add("cell");
          cell.dataset.index = i;
          cell.addEventListener("click", () => handleCellClick(cell, i));
          boardElement.appendChild(cell);
        }
      }

      function handleCellClick(cell, index) {
        if (!gameActive || boardState[index] !== 0) return;

        if (moveSound) {
          moveSound.currentTime = 0;
          moveSound.play();
        }

        boardState[index] = currentPlayer;
        cell.classList.add(currentPlayer === 1 ? "player1" : "player2");
        moveHistory.push({ index, player: currentPlayer });

        const row = Math.floor(index / boardSize);
        const col = index % boardSize;

        if (checkWin(row, col, currentPlayer)) {
          statusElement.textContent = `Победа игрока ${currentPlayer}!`;
          gameActive = false;
          if (currentPlayer === 1) score.player1++;
          else score.player2++;
          updateScoreboard();
          highlightWinningSequence(row, col, currentPlayer);
          if (winSound) {
            winSound.currentTime = 0;
            winSound.play();
          }
          return;
        }

        if (boardState.every(cell => cell !== 0)) {
          statusElement.textContent = "Ничья!";
          gameActive = false;
          score.draws++;
          updateScoreboard();
          return;
        }

        currentPlayer = currentPlayer === 1 ? 2 : 1;
        statusElement.textContent = `Ход игрока ${currentPlayer}`;
      }

      function checkWin(row, col, player) {
        function countDir(dr, dc) {
          let count = 0;
          let r = row + dr;
          let c = col + dc;
          while (
            r >= 0 &&
            r < boardSize &&
            c >= 0 &&
            c < boardSize &&
            boardState[r * boardSize + c] === player
          ) {
            count++;
            r += dr;
            c += dc;
          }
          return count;
        }

        const directions = [
          { dr: 0, dc: 1 },
          { dr: 1, dc: 0 },
          { dr: 1, dc: 1 },
          { dr: 1, dc: -1 }
        ];

        for (const { dr, dc } of directions) {
          let count = 1;
          count += countDir(dr, dc);
          count += countDir(-dr, -dc);
          if (count >= winningCount) return true;
        }
        return false;
      }

      function highlightWinningSequence(row, col, player) {
        const directions = [
          { dr: 0, dc: 1 },
          { dr: 1, dc: 0 },
          { dr: 1, dc: 1 },
          { dr: 1, dc: -1 }
        ];
        let winningSequence = [];

        for (const { dr, dc } of directions) {
          let sequence = [{ row, col }];
          let r = row + dr;
          let c = col + dc;
          while (
            r >= 0 &&
            r < boardSize &&
            c >= 0 &&
            c < boardSize &&
            boardState[r * boardSize + c] === player
          ) {
            sequence.push({ row: r, col: c });
            r += dr;
            c += dc;
          }
          r = row - dr;
          c = col - dc;
          while (
            r >= 0 &&
            r < boardSize &&
            c >= 0 &&
            c < boardSize &&
            boardState[r * boardSize + c] === player
          ) {
            sequence.push({ row: r, col: c });
            r -= dr;
            c -= dc;
          }
          if (sequence.length >= winningCount) {
            winningSequence = sequence;
            break;
          }
        }

        winningSequence.forEach(pos => {
          const index = pos.row * boardSize + pos.col;
          const cell = boardElement.querySelector(`[data-index='${index}']`);
          if (cell) {
            cell.classList.add("winning");
          }
        });
      }

      function undoMove() {
        if (!gameActive || moveHistory.length === 0) return;
        const lastMove = moveHistory.pop();
        boardState[lastMove.index] = 0;
        const cell = boardElement.querySelector(`[data-index='${lastMove.index}']`);
        if (cell) cell.classList.remove("player1", "player2", "winning");
        currentPlayer = lastMove.player;
        statusElement.textContent = `Ход игрока ${currentPlayer}`;
      }

      function resetGame() {
        boardState = new Array(boardSize * boardSize).fill(0);
        currentPlayer = 1;
        gameActive = true;
        moveHistory = [];
        statusElement.textContent = `Ход игрока ${currentPlayer}`;
        createBoard();
      }

      resetBtn.addEventListener("click", resetGame);
      undoBtn.addEventListener("click", undoMove);

      createBoard();
      updateScoreboard();
    </script>
  </body>
</html>
Аватар пользователя
3 дня назад
Аватар пользователя
3 дня назад
Можете объяснить код каждой строчки?

Вбейте тут в поисковике html gta

Дополнен

function checkCollision() {
cars.forEach(car => {
const dx = Math.abs(player.x - (car.x + car.width / 2));
const dy = Math.abs(player.y - (car.y + car.height / 2));
if (dx < player.radius + car.width / 2 &&
dy < player.radius + car.height / 2) {
player.alive = false;
}
});
}

function updateScore() {
scoreEl.textContent = "Очки: " + score;
}

function showGameOver() {
ctx.fillStyle = "black";
ctx.font = "bold 48px sans-serif";
ctx.fillText("Игра окончена", 250, 300);
}

function gameLoop() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
drawBackground();
updatePlayer();
drawPlayer();
updateBullets();
drawBullets();
updateCars();
drawCars();
checkBulletCollision();
checkCollision();
spawnCars();

if (!player.alive) {
showGameOver();
} else {
requestAnimationFrame(gameLoop);
}
}

gameLoop();
</script>
</body>
</html>

Дополнен

function shootBullet() {
if (!player.alive) return;
bullets.push({
x: player.x,
y: player.y,
radius: 5,
speed: 7
});
}

function drawBullets() {
ctx.fillStyle = "yellow";
bullets.forEach(b => {
ctx.beginPath();
ctx.arc(b.x, b.y, b.radius, 0, Math.PI * 2);
ctx.fill();
});
}

function updateBullets() {
for (let i = bullets.length - 1; i >= 0; i--) {
bullets[i].y -= bullets[i].speed;
if (bullets[i].y < 0) bullets.splice(i, 1);
}
}

function drawCars() {
ctx.fillStyle = "red";
cars.forEach(car => {
ctx.fillRect(car.x, car.y, car.width, car.height);
});
}

function updateCars() {
cars.forEach(car => {
car.y += car.speed;
if (car.y > canvas.height) {
car.y = -100;
car.x = Math.random() < 0.5 ? 270 : 490;
car.speed = 2 + Math.random() * 3;
}
});
}

Аватар пользователя
3 дня назад
Оцените мою игру на HTML GTA

<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<title>GTA Mini 2D+</title>
<style>
body {
margin: 0;
overflow: hidden;
background: #222;
color: white;
font-family: sans-serif;
}
#score {
position: absolute;
top: 10px;
left: 10px;
font-size: 20px;
}
</style>
</head>
<body>
<div id="score">Очки: 0</div>
<canvas id="gameCanvas" width="800" height="600"></canvas>
<script>
const canvas = document.getElementById("gameCanvas");
const ctx = canvas.getContext("2d");
const scoreEl = document.getElementById("score");

let score = 0;

const player = {
x: 400,
y: 500,
radius: 15,
color: "blue",
speed: 5,
alive: true
};

const bullets = [];
const cars = [];

const keys = {};

window.addEventListener("keydown", (e) => {
keys[e.key] = true;
if (e.key === " ") shootBullet();
});
window.addEventListener("keyup", (e) => keys[e.key] = false);

function drawBackground() {
ctx.fillStyle = "#a5d6a7"; // зелёный фон
ctx.fillRect(0, 0, canvas.width, canvas.height);

ctx.fillStyle = "#424242";
ctx.fillRect(250, 0, 300, canvas.height); // дорога

ctx.strokeStyle = "#fff";
ctx.setLineDash([20, 20]);
ctx.beginPath();
ctx.moveTo(400, 0);
ctx.lineTo(400, canvas.height);
ctx.stroke();
ctx.setLineDash([]);
}

function drawPlayer() {
if (!player.alive) return;
ctx.fillStyle = player.color;
ctx.beginPath();
ctx.arc(player.x, player.y, player.radius, 0, Math.PI * 2);
ctx.fill();
}

function updatePlayer() {
if (!player.alive) return;
if (keys["ArrowUp"] || keys["w"]) player.y -= player.speed;
if (keys["ArrowDown"] || keys["s"]) player.y += player.speed;
if (keys["ArrowLeft"] || keys["a"]) player.x -= player.speed;
if (keys["ArrowRight"] || keys["d"]) player.x += player.speed;

player.x = Math.max(player.radius, Math.min(canvas.width - player.radius, player.x));
player.y = Math.max(player.radius, Math.min(canvas.height - player.radius, player.y));
}

function shootBullet() {
if (!player.alive) return;
bullets.push({
x: player.x,
y: player.y,
radius: 5,
speed: 7
});
}

function drawBullets() {
ctx.fillStyle = "yellow";
bullets.forEach(b => {
ctx.beginPath();
ctx.arc(b.x, b.y, b.radius, 0, Math.PI * 2);
ctx.fill();
});
}

function updateBullets() {
for (let i = bullets.length - 1; i >= 0; i--) {
bullets[i].y -= bullets[i].speed;
if (bullets[i].y < 0) bullets.splice(i, 1);
}
}

function drawCars() {
ctx.fillStyle = "red";
cars.forEach(car => {
ctx.fillRect(car.x, car.y, car.width, car.height);
});
}

function updateCars() {
cars.forEach(car => {
car.y += car.speed;
if (car.y > canvas.height) {
car.y = -100;
car.x = Math.random() < 0.5 ? 270 : 490;
car.speed = 2 + Math.random() * 3;
}
});
}

Дополнен

function spawnCars() {
while (cars.length < 4) {
cars.push({
x: Math.random() < 0.5 ? 270 : 490,
y: -Math.random() * 300,
width: 40,
height: 70,
speed: 2 + Math.random() * 3
});
}
}

function checkBulletCollision() {
for (let i = cars.length - 1; i >= 0; i--) {
for (let j = bullets.length - 1; j >= 0; j--) {
const car = cars[i];
const b = bullets[j];
if (
b.x > car.x &&
b.x < car.x + car.width &&
b.y > car.y &&
b.y < car.y + car.height
) {
cars.splice(i, 1);
bullets.splice(j, 1);
score += 10;
updateScore();
break;
}
}
}
}

function checkCollision() {
cars.forEach(car => {
const dx = Math.abs(player.x - (car.x + car.width / 2));
const dy = Math.abs(player.y - (car.y + car.height / 2));
if (dx < player.radius + car.width / 2 &&
dy < player.radius + car.height / 2) {
player.alive = false;
}
});
}

function updateScore() {
scoreEl.textContent = "Очки: " + score;
}

function showGameOver() {
ctx.fillStyle = "black";
ctx.font = "bold 48px sans-serif";
ctx.fillText("Игра окончена", 250, 300);
}

function gameLoop() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
drawBackground();
updatePlayer();
drawPlayer();
updateBullets();
drawBullets();
updateCars();
drawCars();
checkBulletCollision();
checkCollision();
spawnCars();

if (!player.alive) {
showGameOver();
} else {
requestAnimationFrame(gameLoop);
}
}

gameLoop();
</script>
</body>
</html>

Дополнен
Аватар пользователя
4 дня назад
Оцените мою игру на HTML

Как файл незнаю сюда выложить но у меня есть описание # Описание игры: GTA-like 3D Игра

## Общая информация
Это браузерная 3D-игра в стиле Grand Theft Auto, созданная с использованием библиотеки Three.js. Игра предлагает открытый мир с элементами гонок, стрельбы и выполнения миссий.

## Основные особенности
- **Открытый мир**: Город с зданиями, дорогами и транспортными средствами
- **Физика**: Реализована гравитация, столкновения и движение транспортных средств
- **Миссии**: Система последовательных заданий для игрока
- **Транспорт**: Возможность входить/выходить из машин и управлять ими
- **Оружие**: Система стрельбы с разными видами оружия
- **UI**: Информационная панель с показателями здоровья, денег и текущего оружия

## Геймплей
Игрок управляет персонажем от первого лица, выполняя различные криминальные задания:
1. Поиск и угон конкретного автомобиля (красного цвета)
2. Доставка украденного автомобиля в гараж
3. Избегание полиции (розыск)

## Управление
- **WASD**: Движение персонажа
- **Shift**: Бег
- **Пробел**: Прыжок
- **ЛКМ**: Стрельба
- **E**: Вход/выход из транспортного средства
- **F**: Смена оружия

## Технические особенности
- Используется Three.js для 3D-рендеринга
- Реализована система теней и освещения
- Динамическая генерация зданий и транспортных средств
- Физика движения и столкновений
- Система миссий с отслеживанием прогресса

## Интерфейс
Игра содержит несколько элементов UI:
- Индикатор здоровья
- Счетчик денег
- Текущее оружие
- Описание текущей миссии
- Прицел в центре экрана
- Меню с кнопками начала игры и справки

Игра предлагает увлекательный опыт в стиле GTA с упором на угон автомобилей и выполнение криминальных заданий в трехмерном открытом мире.

Аватар пользователя
4 дня назад
Не работает тестер HTML кода.