96 lines
6.5 KiB
Markdown
96 lines
6.5 KiB
Markdown
|
# wasm
|
|||
|
|
|||
|
В этой задаче вам нужно научиться запускать go в браузере и работать с API браузера.
|
|||
|
|
|||
|
Автоматических тестов в задаче нет, нужно решить задачу, поменять константу в файле `done.go`
|
|||
|
и послать код в систему. Мы проверим код глазами. Если задача не решена на самом деле,
|
|||
|
мы умножим оценку на -1.
|
|||
|
|
|||
|
## Сборка и запуск
|
|||
|
|
|||
|
Код нужно писать в файле `flappygopher/main.go`. Чтобы собрать код, нужно выставить переменные окружения
|
|||
|
`GOOS` и `GOARCH`. Обычно `GOOS` (читается как гус) задаёт операционную систему, под которую нужно собрать
|
|||
|
код. А `GOARCH` задаёт архитектуру процессора, под которую нужно собрать код.
|
|||
|
|
|||
|
В данном случае, код собирается для браузера и сохраняется в формате WASM.
|
|||
|
|
|||
|
```
|
|||
|
# Внутри директории wasm/flappygopher
|
|||
|
env GOOS=js GOARCH=wasm go build -o flappygopher.wasm
|
|||
|
```
|
|||
|
|
|||
|
В директории `flappygopher` находится отдельный go модуль, чтобы его можно было открыть как отдельный проект.
|
|||
|
Отдельный проект позволяет настроить `GOOS` и `GOARCH`, так чтобы в IDE работал автокомплит.
|
|||
|
Чтобы настроить эти переменные в vscode, нужно выставить настройку `go.toolsEnvVars`.
|
|||
|
В других IDE, ищите инструкцию сами.
|
|||
|
|
|||
|
```
|
|||
|
prime@fedora ~/C/s/w/flappygopher (master)> cat .vscode/settings.json
|
|||
|
{
|
|||
|
"go.toolsEnvVars": {
|
|||
|
"GOOS": "js",
|
|||
|
"GOARCH": "wasm",
|
|||
|
}
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
После того как вы собрали код, нужно запустить web сервер для раздачи файлов. Проще всего
|
|||
|
воспользоваться питоном.
|
|||
|
|
|||
|
```
|
|||
|
prime@fedora ~/C/s/w/flappygopher (master)> python3 -m http.server
|
|||
|
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
|
|||
|
```
|
|||
|
|
|||
|
Перейдите по ссылке и откройте инструменты разработчика. В `javascript` консоли вы должны увидеть
|
|||
|
сообщение об ошибке. На линуксе консоль открывается комбинацией `Ctrl+Shift+i`.
|
|||
|
|
|||
|
![error](./error.png)
|
|||
|
|
|||
|
Если ошибка такая как на скриншоте (паника из го) - то все хорошо. Если какая-то другая, то
|
|||
|
значит у вас проблемы с окружением.
|
|||
|
|
|||
|
Поправьте код, уберите панику и вставьте `fmt.Println("Hello, JS")`. Пересоберите код.
|
|||
|
Обновите страницу в браузере. (питон сервер должен работать в отдельной вкладке, перезапускать его не нужно).
|
|||
|
Ошибка должна уйти и вместо неё появиться ваше сообщение.
|
|||
|
|
|||
|
## Файлы с исходным кодом
|
|||
|
|
|||
|
В проекте есть несколько файлов. Вам нужно понимать их смысл.
|
|||
|
|
|||
|
- `index.html` - эта та страница, которую открывает браузер. Этот файл менять не нужно.
|
|||
|
В начале файла записан код, который загружает, инициализирует и запускает WASM файл.
|
|||
|
- `wasm_exec.js` - код на js, который распространяется вместе с go тулчейном. Этот код настраивает
|
|||
|
взаимодействие с go со стороны js. Внутрь wasm модуля нельзя положить js код,
|
|||
|
а какой-то js код для bootstrap всего Go рантайма нужен. Поэтому этот код
|
|||
|
распространяется как отдельный файл.
|
|||
|
- `main.go` - ваш код на go, который будет загружен и запущен. Внутри будет вызвана
|
|||
|
функция `main`. Код внутри `main.go` может использовать пакет [`syscall/js`](https://pkg.go.dev/syscall/js) для взаимодействия
|
|||
|
с браузером. Также можно использовать пакеты [`honnef.co/go/js/dom/v2`](https://pkg.go.dev/honnef.co/go/js/dom/v2)
|
|||
|
и [`console`](./console/console.go).
|
|||
|
|
|||
|
## Задача
|
|||
|
|
|||
|
![screen](./screenshot.png)
|
|||
|
|
|||
|
Попробуйте написать игру flappybird, используя [Canvas API](https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API).
|
|||
|
|
|||
|
Для этого нужно:
|
|||
|
|
|||
|
1. Создать `<canvas>` элемент на странице и получить на него ссылку.
|
|||
|
2. Получить из элемента `2d` контекст для рисования.
|
|||
|
3. Запустить цикл игры, используя `requestAnimationFrame`. Эта функция
|
|||
|
просит браузер вызвать колбек перед отрисовкой следующего кадра.
|
|||
|
4. В этом колбеке вы должны:
|
|||
|
* Обновить состояние игры
|
|||
|
* Очистить канвас и нарисовать на нём новый фрейм.
|
|||
|
* Зашедулить следующий фрейм, используя `requestAnimationFrame`
|
|||
|
|
|||
|
## Советы
|
|||
|
|
|||
|
* В `js/dom` есть баг в функции [`drawImage`](https://github.com/dominikh/go-js-dom/pull/84/files#diff-93cd0c9358c072a082261eee3d3d83d5305dadabac1a2b25ba084d94ed8b3495R2394). Если вам потребуется
|
|||
|
эта функция, делайте вызов через нетипизированное API.
|
|||
|
* Чтобы разобраться с Canvas API, посмотрите [туториалы](https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Basic_usage#a_simple_example). Транслировать их на го придётся самим.
|
|||
|
* Вы можете создавать `<canvas>` элемент из go, используя `document.createElement`,
|
|||
|
или вписать элемент в html и получить на него ссылку по id.
|