Перейти к основному содержимому

Инструкции по выполнению шага

На данный момент игра сохраняет сведения о положениях мячика, ракетки и нажатий. Однако не имеется никакой возможности выгрузить эти данные или где-то сохранить. Для того, чтобы получилось сделать такую функцию, внесём следующие изменения в наш главный файл index.html сразу после элемента datasetSize:

<!-- Начало места, которое мы изменяем -->
<h1 class="datasetSize">0</h1>
<div class="download">
<img src="assets/download.svg" width="50px"><a download="ping_pong_dataset.csv" href='none'></a></img>
</div>
<h1 class="score">
Current: <a>0</a><br />
Best score: <a>0</a><br />
Average: <a>0</a>
</h1>
<!-- Конец редактирования -->

Тут мы создали элемент группы <div> и вложили в него элемент изображения <img>. А внутри изображения <img> мы вложили элемент ссылки <a>, который будем использовать для выгрузки файла в формате CSV. Файл CSV это текстовый файл, в котором содержится информация. Каждая строка – это отдельная строка таблицы, а столбцы отделены один от другого знаком разделителя. Чаще всего разделитель это запятая , или точка с запятой ;. Для картинки можно использовать любое изображение, отдаленно ассоциирующееся с кнопкой загрузки. В нашем примере будет использоваться следующая картинка:

Картинка download.svg для выгрузки данных

Положение только что созданного элемента необходимо зафиксировать, поэтому внесём в файл style.css следующие настройки:

к сведению

Следующая часть добавляется в конец файла style.css.

.download {
position: fixed;
cursor: pointer;
left: 250px;
top: 50px;
}

Новая настройка cursor: pointer меняет внешний вид мышки при наведении на элемент с классом download. Тем самым пользователю даётся подсказка, что это не просто картинка, а кнопка, на которую можно нажать.

Аналогично прошлым шагам, опишем логику выгрузки файла в виде скрипта на JavaScript. Создаём новый файл в папке js под именем download.js и не забываем добавить его в index.html перед подгрузкой скрипта с движком игры:

<!-- Начало места, которое мы изменяем -->
<script src="js/scores.js"></script>
<script src="js/download.js"></script>
<script src="js/engine.js"></script>
</body>

</html>
<!-- Конец редактирования -->

Вот так будет выглядеть наша папка проекта после создания файла download.js:

ping-pong
├── index.html
├── assets
│ ├── ball.png
│ ├── paddle.png
│ ├── background.jpg
│ ├── style.css
│ └── download.svg
└── js
├── render.js
├── engine.js
├── controls.js
├── pause.js
├── scores.js
├── logging.js
└── download.js

В самом файле напишем следующий код:

// https://stackoverflow.com/questions/21012580/is-it-possible-to-write-data-to-file-using-only-javascript
let textFile = null;
const makeTextFile = function (text) {
var data = new Blob([text], {
type: "text/plain"
});

// При замене ранее сгенерированного файла необходимо вручную удалить связь
// с привязанной к нему ссылкой во избежание утечек памяти
if (textFile !== null) {
window.URL.revokeObjectURL(textFile);
}

textFile = window.URL.createObjectURL(data);

return textFile;
};

const downloadBtn = document.getElementsByClassName("download")[0];

downloadBtn.addEventListener(
"click",
function () {
var link = downloadBtn.getElementsByTagName("a")[0];
link.href = makeTextFile(recordData.join("\r\n"));
link.style.display = "block";
link.click();
},
false
);

В начале файла мы объявляем переменную с пустым значением null, в которой будем хранить ссылку на текстовое представление массива recordData. Ниже объявляется функция makeTextFile. Ей в качестве входного аргумента передаётся текст, который подаётся на вход объекту Blob. Объект Blob - это объект, подобный файлу, который содержит необработанные данные только для чтения. Поскольку это файлоподобный объект, то к нему можно получить доступ в виде гиперссылки при помощи метода window.URL.createObjectURL. После получения ссылки на объект, функция makeTextFile её возвращает как результат своей работы.

После этого нам осталось только получить доступ к элементу с иконкой загрузки и привязать к нему обработчик событий клика клавиши. Внутри функции обратного вызова мы получаем доступ к элементу ссылке при помощи метода getElementsByTagName. Устанавливаем в качестве значения атрибута href (от англ. hypertext reference — гипертекстовая ссылка) полученную из текстового представления recordData гиперссылку. Включаем её отображение и вызываем эмуляцию нажатия при помощи метода click.

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

Пример выгруженного набора данных с записями игр

к сведению

Итоговый результат выполнения шага можно скачать тут.