БлогNot. Щёлкай гроссов верно и без промаха

Щёлкай гроссов верно и без промаха

На самом деле, мне снова нужен был небольшой шаблончик для яваскрипт-игрушки, связанной с установкой соответствий между словами и картинками, но не перетаскиванием, как в задаче о расстановке фамилий по позициям или в более старой "корзине истории", а простой последовательностью кликов по картинкам.

Правда, пример, как и по первой ссылке, получился опять шахматный, нужно правильно щёлкнуть по портретам участников скоро начинающегося Ставангера-2019.

Фамилия-вопрос будет появляться под лентой с портретами. Если Вы сделали правильно все 10 шагов, в конце увидите общее время игры в формате ЧЧ:ММ:СС.МС, где МС - сотые доли секунды.

Ниже можно попробовать свои и силы и посмотреть исходники.

Что примечательного в коде и может ещё пригодиться:

  • Более-менее современный вариант предзагрузки изображений с проверкой. Сначала на загрузку страницы вызывается функция preloadImages, которая получает аргументами массив с URL-адресами картинок и имя callback-функции. После загрузки всех изображений callback-функция checkImgLoaded проверяет, всё ли в порядке (складывая ширину всех картинок, которая для простоты предполагается одинаковой). Если всё хорошо, устанавливается флажок playGameFlag.
  • "Верные ответы" ставятся как скрытые атрибуты тегов img рисунков (с именем answer).
  • Функция difftime ищет разницу времени между двумя объектами Date и возвращает строку с найденным временем, проведённым в игре (время считается от первого клика, а не от загрузки страницы). Строка времени оформляется по указанному выше формату.
  • Для совместимости с Internet Explorer (по крайней мере, 11-м) пришлось переписать функцию случайного перемешивания элементов массива с красивого
     function shuffle (array) {
      array.sort(() => Math.random() - 0.5);
     }

    на то, что сейчас в коде.

  • Если использовать для рисунков формат .gif с прозрачным фоном, можно уже отмеченные картинки просто выделять фоновым цветом, что и сделано. Поэтому шаблон обходится без каких-либо стилевых указаний и дополнительных элементов разметки.

Вот исходник на момент написания и без HTML-обрамления, предполагается, что он будет работать из файла .html в кодировке Юникода UTF-8, а исходные картинки находятся в одной папке с документом и имеют имена 1.gif, ..., 10.gif (в коде онлайн-скрипта эти пути изменены).

<a name="gameStartLabel"></a>
<div align="center" id="picturebox"></div>
<div align="center" id="questionbox"></div>

<script>
 var imagesDiv = document.getElementById("picturebox");
 var questionDiv = document.getElementById("questionbox");
 var playGameFlag = false;
 var cnt, step, startTime, endTime;

 var imgSources = [ //адреса картинок
  "1.gif",  "2.gif",  "3.gif",  "4.gif",  "5.gif",
  "6.gif",  "7.gif",  "8.gif",  "9.gif",  "10.gif"
 ];
 for (var i = 0; i < imgSources.length; i++) imgSources[i] += '?' + Math.random();
 var imgArray = []; //массив рисунков
 var width_1 = 111; //ширина одной картинки
 var names = [ //подписи
  "Аронян",  "Карлсен",  "Ананд",  "Вашье-Лаграв",  "Дин Лижэнь",
  "Со",  "Мамедьяров",  "Юй Янъи",  "Грищук",  "Каруана"
 ];

 function difftime (t1,t2) {
  var msec = t2 - t1;
  var hh = Math.floor(msec / 1000 / 60 / 60);
  if (hh < 9) hh = '0' + hh;
  msec -= hh * 1000 * 60 * 60;
  var mm = Math.floor(msec / 1000 / 60);
  if (mm < 9) mm = '0' + mm;
  msec -= mm * 1000 * 60;
  var ss = Math.floor(msec / 1000);
  if (ss < 9) ss = '0' + ss;
  msec -= ss * 1000;
  msec = Math.floor (msec/10); //сотые доли сек.
  if (msec < 9) msec = '0' + msec;
  return '' + hh + ':' + mm + ':' + ss + '.' + msec;
 }

 function playInGame () { //клик на картинке
  if (playGameFlag) {
   if (startTime == 0) startTime = new Date();
   if (this.getAttribute('answer') === names[step]) {
    cnt++;
    this.style.backgroundColor = 'lightgreen';
    questionDiv.innerHTML = names[++step] + '?';
    if (cnt == 10) {
     endTime = new Date();
     var t = difftime (startTime, endTime);
     questionDiv.innerHTML = "Вы победили! Время игры = " + t;
     playGameFlag = false;
    }
   }
   else {
    this.style.backgroundColor = 'pink';
    questionDiv.innerHTML = "К сожалению, Вы ошиблись, попробуйте ещё раз!";
    playGameFlag = false;
   }
  }
  else {
   questionDiv.innerHTML = "Вы не в игре, пожалуйста, " +
    "<a href=\"#gameStartLabel\" onclick=\"reloadGame();\">начните новую игру</a>";
  }
 }

 function preloadImages (imgSources, callback) { //предзагрузка картинок
  var counter = 0;

  function onLoadGame () {
   counter++;
   if (counter == imgSources.length) callback();
  }

  for (var i = 0; i < imgSources.length; i++) {
   imgArray[i] = document.createElement('img');
   imgArray[i].onload = imgArray.onerror = onLoadGame; //выполнять 1-м
   imgArray[i].onclick = playInGame;
   imgArray[i].setAttribute('answer', names[i]);
   imgArray[i].src = imgSources[i]; //выполнять 2-м
  }
  shuffle (imgArray);
  for (var i = 0; i < imgSources.length; i++) imagesDiv.appendChild (imgArray[i]);
 }

 function shuffle (array) {
  for (var i = array.length - 1; i > 0; i--) {
   var j = Math.floor(Math.random() * (i + 1));
   var temp = array[i]; array[i] = array[j]; array[j] = temp;
  }
 }

 function startGame () {
  shuffle (names);
  cnt = step = startTime = 0;
  questionDiv.innerHTML = names[step] + '?';
  playGameFlag = true;
 }

 function reloadGame () {
  while (imagesDiv.firstChild) {
   imagesDiv.removeChild (imagesDiv.firstChild);
  }
  shuffle (imgArray);
  for (var i = 0; i < imgSources.length; i++) {
   if (imgArray[i].style.backgroundColor === 'lightgreen') imgArray[i].style.backgroundColor = '';
   imagesDiv.appendChild (imgArray[i]);
  }
  startGame();
 }

 function checkImgLoaded () { //Проверка - находим общую ширину всех картинок
  var widthSum = 0;
  for (var i = 0; i < imgSources.length; i++) {
   var img = document.createElement('img');
   img.src = imgSources[i];
   widthSum += img.width;
  }
  if (widthSum == imgSources.length * width_1) {
   startGame();
  }
 }

 window.addEventListener('load', function (e) {
  preloadImages (imgSources, checkImgLoaded);
 }, false); 
</script>
<noscript><p align="center">Включите Javascript для работы приложения!</p></noscript>

Вот все гроссы на одном полотне (где Сирожа? А Сирожи не видать):

Участники Ставангера-2019, шаржик
Участники Ставангера-2019, шаржик

теги: javascript шахматы картинка время игра

02.06.2019, 19:05; рейтинг: 97