Эффект удара в игре Ti c ta c toe - PullRequest
2 голосов
/ 02 мая 2020

Я работал над игрой Ti c Ta c Toe и пытался создать эффект удара для квадратов Победителя.

Моя идея состояла в том, чтобы я мог взять первую и последнюю сква sh, найдите их среднее положение и используйте холст для создания линии, но она не работает должным образом.

Ниже приведен пример кода с Ссылка Fiddle :

function TicTacToe(container) {
  let count = 0;
  const getLabel = () => count++ % 2 === 0 ? 'X' : 'Y';

  function createGrid() {
    const handlerFn = function() {
      this.innerText = getLabel();
      this.removeEventListener('click', handlerFn);
    }
    Array.from({
      length: 9
    }, (_, i) => {
      const div = document.createElement('div');
      div.classList.add('tile')
      div.addEventListener('click', handlerFn)
      container.append(div);
    });
  }
  
  function createStrikeLine() {
    const tiles = document.querySelectorAll('.tile');
    const [ startX, startY ] = getPosition(tiles[0]);
    const [ endX, endY ] = getPosition(tiles[8]);
    
    console.log(startX, startY, endX, endY)
    
    const canvas = document.getElementById('ctx-strike');
    const context = canvas.getContext('2d');
    
    context.beginPath();
		context.moveTo(startX, startY);
    context.lineTo(endX, endY);
    context.stroke();
    context.closePath();
  }
  
  function getPosition(element) {
  	const left = element.offsetLeft;
    const top = element.offsetTop;
    const height = Math.floor(element.offsetWidth / 2);
    return [ left + height, top + height ];
  }

  createGrid();
  createStrikeLine();
}

const containerDiv = document.querySelector('.content');
TicTacToe(containerDiv)
div {
  display: flex;
}

.container {
  align-items: center;
  justify-content: center;
  height: 95vh;
  width: 95vw;
}

.content {
  flex-direction: row;
  flex-wrap: wrap;
  width: 30vmax;
}

#ctx-strike {
  /* position: absolute; */
  height: 30vmax;
  border: 1px solid black;
}

.tile {
  margin: 2px;
  background: white;
  border: 2px solid gray;
  border-radius: 4px;
  width: 8vw;
  height: 8vw;
  align-items: center;
  justify-content: center;
  font-size: 2em;
}

.strike-through {
  position: absolute;
  z-index: 1;
  border-bottom: 4px solid red;
  height: 6vh;
  width: 21vmax;
  
}
.translate-45 {
  -webkit-transform: rotate(45deg);
}
<div class="container">
  <div class="content"></div>
  <canvas id='ctx-strike'></canvas>
</div>

Теперь я понимаю, проблема связана с координатами, но я попытался заполнить холст, но он все равно не работает. Итак, вопрос,

  • Как определить правильные координаты для любой плитки?
  • Есть ли лучший способ сделать эффект удара, кроме холста?

Еще одна проблема, которую я видел, заключалась в том, что весь пользовательский интерфейс отзывчив, но не холст. Если вы изменяете размер контейнера, плитки расширяются / уменьшаются, но линия остается такой же

1 Ответ

0 голосов
/ 02 мая 2020

Опубликовать последнее обновление:

Другая проблема, которую я видел, заключалась в том, что весь пользовательский интерфейс отзывчив, но не холст. Если вы изменяете размер контейнера, плитки расширяются / уменьшаются, но линия остается такой же

Я думал об использовании div и css вместо canvas. Да, холст был бы менее трудоемким, css может немного справиться с отзывчивостью.

Идея:

Я создал 8 классов с возможными шаблонами для удара через:

  • По строкам: игроки могут выиграть по 3 комбинациям, если они выберут одно и то же значение в любом из рядов.
  • По столбцу: Игроки могут выиграть по 3 комбинациям, если они выберут одинаковое значение в любом из столбцов.
  • Диагонали: они могут выбирать по диагонали.

Теперь в моей логике проверки c все, что мне нужно сделать, это решить, есть ли выигрыш, выбрать шаблон выигрыша и передайте его моей функции.

Пример кода

Примечание. Я добавил раскрывающийся список, чтобы пользователи могли воспроизводить и проверять эти шаблоны по отдельности.

function TicTacToe(container) {
  const strikePatterns = [
    'row-1', 'row-2', 'row-3',
    'col-1', 'col-2', 'col-3',
    'dig-1', 'dig-2'
  ];
  let count = 0;
  const getLabel = () => count++ % 2 === 0 ? 'X' : 'Y';

  function createGrid() {
    const handlerFn = function() {
      this.innerText = getLabel();
      this.removeEventListener('click', handlerFn);
    }
    Array.from({
      length: 9
    }, (_, i) => {
      const div = document.createElement('div');
      div.classList.add('tile')
      div.addEventListener('click', handlerFn)
      container.append(div);
    });
  }

  function createStrikeLine(patternName) {
    const div = document.createElement('div');
    div.classList.add('strike-through');

    div.classList.add(patternName)
    container.append(div);
  }
  
  createGrid();

  function createPatternSelect(value) {
    const select = document.createElement('select');
    strikePatterns.forEach(function(pattern) {
      const option = document.createElement('option');
      option.innerText = pattern;
      option.value = pattern;
      select.append(option);
    })
    if (value) {
      select.value = value;
    }
    select.addEventListener('change', function(event) {
      container.innerHTML = '';
      createGrid();
      createPatternSelect(this.value);
      createStrikeLine(this.value);
    })
    container.append(select)
  }
  createPatternSelect();
}

const containerDiv = document.querySelector('.content');
TicTacToe(containerDiv)
div {
  display: flex;
}

.container {
  align-items: center;
  justify-content: center;
  height: 95vh;
  width: 95vw;
}

.content {
  flex-direction: row;
  flex-wrap: wrap;
  width: 30vmax;
  align-items: center;
  justify-content: center;
}

#ctx-strike {
  position: absolute;
  border: 1px solid black;
}

.tile {
  margin: 2px;
  background: white;
  border: 2px solid gray;
  border-radius: 4px;
  width: 8vw;
  height: 8vw;
  align-items: center;
  justify-content: center;
  font-size: 2em;
}

.strike-through {
  border-bottom: 2px solid red;
  position: absolute;
  width: 18vw;
  height: 1px;
}

.row-1 {
  margin-top: -10vw;
}

.row-2 {
  margin-top: 0;
}

.row-3 {
  margin-top: 8vw;
}

.col-1 {
  margin-left: -9vw;
  transform: rotate(90deg);
}

.col-2 {
  margin-left: 0;
  transform: rotate(90deg);
}

.col-3 {
  margin-left: 9vw;
  transform: rotate(90deg);
}

.dig-1 {
  margin-top: -1vw;
  width: 27vw;
  transform: rotate(-45deg);
}

.dig-2 {
  margin-top: -1vw;
  width: 27vw;
  
  transform: rotate(45deg);
}
<div class="container">
  <div class="content"></div>
</div>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...