From 913110508cd8e5300864fbcc8046f25d3525b0f3 Mon Sep 17 00:00:00 2001 From: "anton.gurov" Date: Fri, 8 Nov 2019 13:52:15 +0300 Subject: [PATCH 01/14] story changes, ui fixes --- config.json | 4 ++-- engine/screens/game.go | 2 +- engine/screens/menu.go | 2 ++ story/choose_your_pill.md | 0 ...chans_for_game.md => go_game_dos_and_donts.md} | 2 ++ story/index.md | 13 +++++++++---- ..._blt.md => linux_go_blt_install_quickstart.md} | 8 +++++--- story/makefile_and_crosscompiling.md | 10 ++++++++++ story/static_types_vs_ecs.md | 15 ++++++++++++++- 9 files changed, 45 insertions(+), 11 deletions(-) create mode 100644 story/choose_your_pill.md rename story/{go_chans_for_game.md => go_game_dos_and_donts.md} (99%) rename story/{linux_go_blt.md => linux_go_blt_install_quickstart.md} (86%) create mode 100644 story/makefile_and_crosscompiling.md diff --git a/config.json b/config.json index b669e58..ea1bcd6 100644 --- a/config.json +++ b/config.json @@ -1,10 +1,10 @@ { - "version": "v0.0.1.4-2-g20fa78a", + "version": "v0.0.1.4-3-g5619155", "title": "Alchemyst", "sizeX": 100, "sizeY": 47, "fpsLimit": 60, - "font": ".\/resources\/fonts-ttf\/LiberationMono-Bold.ttf", + "font": "./resources/fonts-ttf/LiberationMono-Bold.ttf", "fontSize": "8x12", "verbosity": "debug" } \ No newline at end of file diff --git a/engine/screens/game.go b/engine/screens/game.go index 7405a31..0ef1da8 100644 --- a/engine/screens/game.go +++ b/engine/screens/game.go @@ -31,7 +31,7 @@ func (ts *GameScreen) Enter() { Print(1, ts.mw.H-2, "Press [color=white]?[/color] for help") } func (ts *GameScreen) Exit() { - ts.mw.GetLayer("base").ClearArea(1, ts.mw.H-2, 30, 1) + ts.mw.GetLayer("overlay").ClearArea(0, ts.mw.H-3, 30, 3) //remove what we dont need } diff --git a/engine/screens/menu.go b/engine/screens/menu.go index 41c79b5..257f1f1 100644 --- a/engine/screens/menu.go +++ b/engine/screens/menu.go @@ -67,6 +67,8 @@ func (ms *MenuScreen) HandleInput(input string) { //} switch input { + case "Escape": + fallthrough case "Space": ms.scm.SetScreen(ms.scm.PreviousScreen) break diff --git a/story/choose_your_pill.md b/story/choose_your_pill.md new file mode 100644 index 0000000..e69de29 diff --git a/story/go_chans_for_game.md b/story/go_game_dos_and_donts.md similarity index 99% rename from story/go_chans_for_game.md rename to story/go_game_dos_and_donts.md index b278c97..d6455b1 100644 --- a/story/go_chans_for_game.md +++ b/story/go_game_dos_and_donts.md @@ -1,4 +1,6 @@ + + декодирование ввода в отдельном потоке Реализация FPS и троттлинг diff --git a/story/index.md b/story/index.md index f7c3f76..01b0b2b 100644 --- a/story/index.md +++ b/story/index.md @@ -1,5 +1,10 @@ -RLG и Golang - полезные советы +RLG и Golang - некоторые полезные советы === -1. [Установка и некоторые особенности работы](./linux_go_blt.md) связки BLT + Go на Linux -2. Реализация [некоторых возможностей](./go_chans_for_game.md) Go - chans, tickers, throttling -3. [Система типов](./static_types_vs_ecs.md) - нативная или ECS? \ No newline at end of file +0. [Выбираем инструменты](./choose_your_pill.md) +1. [Установка и некоторые особенности работы](linux_go_blt_install_quickstart.md) связки BLT + Go на Linux +2. Что [стоит и НЕ стоит](go_game_dos_and_donts.md) делать с возможностями Go - +chans, +tickers, +throttling, -closures +3. [Система типов](./static_types_vs_ecs.md) - нативная или ECS? На самом деле и то, и то + +#####Дополнения + +1. Как [не делать лишнюю работу](./makefile_and_crosscompiling.md) и почему это **важно**. \ No newline at end of file diff --git a/story/linux_go_blt.md b/story/linux_go_blt_install_quickstart.md similarity index 86% rename from story/linux_go_blt.md rename to story/linux_go_blt_install_quickstart.md index e32fd3e..7da307b 100644 --- a/story/linux_go_blt.md +++ b/story/linux_go_blt_install_quickstart.md @@ -1,9 +1,9 @@ Установка и работа с BLT на Linux == -Для Windows и Mac проблем с Go + BLT, насколько мне известно нет. +Про Windows и Mac в контексте связки Go + BLT, я говорить не буду, поскольку не ел устриц. С Linux, которая моя основная рабочая ось - другая история, здесь вносят свой шарм особенности работы линкера. -Дело в том, что в составе BLT есть готовые биндинги для Go, НО! В Terminal/Include/Go по умолчанию +Дело в том, что BLT написана на C. Но! есть готовые биндинги для Go, НО! В Terminal/Include/Go по умолчанию указаны такие флаги линкера CGO (стр 25) ```go // #cgo LDFLAGS: -lBearLibTerminal @@ -44,4 +44,6 @@ RPATH ./ Ура! Теперь кладем libBearLibTerminal.so прямо в папку с main.go и запускам go run (или скомпилированный бинарник) прям оттуда. Собранные таким образом бинарники будут искать библиотеку в той же папке, где находятся они сами. -Теперь при дистрибуции приложения можно просто положить .so файл библиотеки рядом, и все будет работать! \ No newline at end of file +Теперь при дистрибуции приложения можно просто положить .so файл библиотеки рядом, и все будет работать! + +Вторая кочка, на котрой \ No newline at end of file diff --git a/story/makefile_and_crosscompiling.md b/story/makefile_and_crosscompiling.md new file mode 100644 index 0000000..88749ee --- /dev/null +++ b/story/makefile_and_crosscompiling.md @@ -0,0 +1,10 @@ +Автоматизация сборки и тестирование +=== + +- Почему это важно: мелочи сжирают кучу времени. Не позволяйте им это делать! +- настройка под Linux: все внешние либы собраны и включены в монорепо (дело вкуса) +- Go-специфичные вещи: glide, go mod +- Кросскомпиляция, CGO для Mac и Linux. CGO_ENABLED=1, mingw, локальная линковка библиотек +- Таргеты: Убираем бардак за собой - distclean, build +- Автоматическое тестирование, testify. Не ленитесь писать тесты! +- Деплой/публикация после сборки \ No newline at end of file diff --git a/story/static_types_vs_ecs.md b/story/static_types_vs_ecs.md index 39e6198..d11ca12 100644 --- a/story/static_types_vs_ecs.md +++ b/story/static_types_vs_ecs.md @@ -2,8 +2,21 @@ Плюсы использования нативной системы типов +- Примитивы типа Rect +- Интерфейсы, type casting и переиспользования Blit +- свитчи по типам + Минусы использования нативной системы типы +- Структура структуры (эм..) иммутабельна + ECS - меняем бойлерплейт на относительное снижение связности -Минутка рекламы gogue \ No newline at end of file +- Делаем динамическую систему типов там и только там где нам надо +- Возможность физически впихнуть в кеш проца все актуальные данные +- Особая актуальность для Go - обработка в main thread всего что связано с Io + +Минутка рекламы gogue + +- Толковый туториал, неплохой код +- Пользуйтесь и продвигайте \ No newline at end of file From 49768295f20d33c8f05b50edf7bce02adfff7e99 Mon Sep 17 00:00:00 2001 From: "anton.gurov" Date: Fri, 8 Nov 2019 14:23:27 +0300 Subject: [PATCH 02/14] update story --- story/linux_go_blt_install_quickstart.md | 94 +++++++++++++++++++++++- 1 file changed, 93 insertions(+), 1 deletion(-) diff --git a/story/linux_go_blt_install_quickstart.md b/story/linux_go_blt_install_quickstart.md index 7da307b..398235d 100644 --- a/story/linux_go_blt_install_quickstart.md +++ b/story/linux_go_blt_install_quickstart.md @@ -46,4 +46,96 @@ RPATH ./ Теперь при дистрибуции приложения можно просто положить .so файл библиотеки рядом, и все будет работать! -Вторая кочка, на котрой \ No newline at end of file +Вторая кочка, на которой мне пришлось столкнуться - +то то, что вызов любой своей функции не из main thread BLT воспринимает крайне нервно, +и сыпет фатальными ошибками. Справедливости ради точно так же ведет себя и большинство +других библиотек связанных с рендером и вводом-выводом, тот же SDL например. Так что +воспринимайте это как милую особенность использования CGO. + +Лекарство тут ровно одно - вызывать сишные foreign functions из main thread. +Для реализации этого требования мне показалась полезной следующая конструкция +```go +package main + +import "runtime" + +... + + +// Рецепт чтобы убежать от [fatal] 'refresh' was not called from the main thread +// https://github.com/golang/go/wiki/LockOSThread +func init() { + runtime.LockOSThread() +} + +type GameState struct { + Mainfunc chan func() +} + +// do запускает функцию f в контексте main thread. +func (g *GameState) Do(f func()) { + done := make(chan struct{}, 1) + g.Mainfunc <- func() { + f() + f = nil //zero pointer в замыкание + done <- struct{}{} + } + <-done +} + + +var State = GameState{ + Mainfunc: make(chan func()), //блокирующий канал(!) +} +// И где-то в Main Loop делаем примерно так: +func MainLoop(state GameState) { + ... + //В этом select обработка ввода, рендер, пеерколючение состояний интерфейса итп + for f := range state.Mainfunc { + f() + }} +... +``` + +State - это обычный Value Object, экземпляр типа GameState. Я его использую как +контейнер для важных для игры данных - уровня, состояния рендера, разных тикеров, +каналов для рендера и ввода-вывода итп. Так как он глобальный (или просто передается +по аргументам), то именно в него встроен метод Do. Если нам скажем в пакете где +описывается некий предмет надо нарисовать при его поднятии какой-то супер-эффект +на экране - мы поступаем вот так: + +```go +package item + +import "main" +import blt "some.repo.ru/user/bearlibterminal" + +var State main.GameState + +//функция скажем поднятия описание предмета... +func (item *Item) Pickup() { + + .... + doSuperEffect(State) +} +//and there we go like this: +func doSuperEffect(State main.GameState) { + ... + State.Do(func() { + renderSuperEffect() +// ...do stuff in main thread + }) + ... +} +... +func renderSuperEffect() { + blt.Layer(0) + blt.Print("WAAAGH") + ... +} +``` + +Здесь renderSuperEffect - непосредственная реализация эффекта, doSuperEffect - +запихивает в очередь на выполнения в main thread эту самую реализацию. Которая с успехом +выполняется в main loop. В целом картина именно такая, но больше подробностей можно +найти по ссылкам в комментариях. From c268071314d64f5f555b13a658bab752c45125ed Mon Sep 17 00:00:00 2001 From: "anton.gurov" Date: Fri, 8 Nov 2019 14:34:13 +0300 Subject: [PATCH 03/14] footnote --- story/linux_go_blt_install_quickstart.md | 40 +++++++++++++++++------- 1 file changed, 28 insertions(+), 12 deletions(-) diff --git a/story/linux_go_blt_install_quickstart.md b/story/linux_go_blt_install_quickstart.md index 398235d..c36a453 100644 --- a/story/linux_go_blt_install_quickstart.md +++ b/story/linux_go_blt_install_quickstart.md @@ -9,7 +9,11 @@ // #cgo LDFLAGS: -lBearLibTerminal ``` Что подразумевает глобальную вивдимость библиотеки. Увы, пока пакета с BLT для распространенных дистрибутивов Linux нет. -Поэтому беде нужно помочь руками. Сначала вручную показать линтеру, что такая библиотека есть, и потом перезагрузить +Поэтому беде нужно помочь руками. + +#####Первый метод + +Сначала вручную показать линтеру, что такая библиотека есть, и потом перезагрузить кеш путей к библиотекам:: ```bash $ sudo echo "/path/to/libbearterminal.so" > /etc/ld.so.conf.d/libbearterminal.conf && sudo ldconfig @@ -19,18 +23,20 @@ $ sudo echo "/path/to/libbearterminal.so" > /etc/ld.so.conf.d/libbearterminal.co распространенному стереотипу - доля красноглазых пользователей Linux с каждым годом падает, и эта консольная магия для большинства уже некомильфо. -Способ второй, которым воспользовался я, намного проще для пользователя. -Редактируем файл с биндингами примерно следующим образом: +#####Второй метод + +Способ второй, которым воспользовался я, с которым намного проще жить. +Редактируем файл с биндингами (BearLibTerminal.go) примерно следующим образом: ```go // #cgo LDFLAGS: -L. -Wl,-rpath -Wl,./ -lBearLibTerminal // #include // #include import "C" ``` -(знатоки С, простите, я этими флагами вообще +(знатоки С, простите если что не так, я этими флагами вообще пользоваться не умею) -Далее - собираем приложение с libtcod ```go build -o test```. +Далее - собираем минимальное приложение с blt ```go build -o test```. Проверяем, что относительные пути записались в бинарник: ```bash @@ -41,14 +47,20 @@ objdump -p test | grep RPATH RPATH ./ ``` -Ура! Теперь кладем libBearLibTerminal.so прямо в папку с main.go и запускам go run (или скомпилированный бинарник) прям -оттуда. Собранные таким образом бинарники будут искать библиотеку в той же папке, где находятся они сами. +Ура! Теперь кладем libBearLibTerminal.so прямо в папку с main.go и запускам go run +(или скомпилированный бинарник) прям оттуда. Собранные таким образом бинарники будут +искать библиотеку в той же папке, где находятся они сами. -Теперь при дистрибуции приложения можно просто положить .so файл библиотеки рядом, и все будет работать! +Теперь при дистрибуции приложения можно просто положить .so файл библиотеки рядом, +и все будет работать! -Вторая кочка, на которой мне пришлось столкнуться - -то то, что вызов любой своей функции не из main thread BLT воспринимает крайне нервно, -и сыпет фатальными ошибками. Справедливости ради точно так же ведет себя и большинство +Горутины и многопоточность +--- + +Вторая кочка, на которой мне пришлось столкнуться - то то, что вызов любой своей +функции не из main thread BLT воспринимает крайне нервно, +и сыпет фатальными ошибками. Это неприятно, тк часто Го выбирают именно за +многопоточность из коробки. Но справедливости ради точно так же ведет себя и большинство других библиотек связанных с рендером и вводом-выводом, тот же SDL например. Так что воспринимайте это как милую особенность использования CGO. @@ -99,7 +111,7 @@ func MainLoop(state GameState) { State - это обычный Value Object, экземпляр типа GameState. Я его использую как контейнер для важных для игры данных - уровня, состояния рендера, разных тикеров, -каналов для рендера и ввода-вывода итп. Так как он глобальный (или просто передается +каналов для рендера и ввода-вывода итп[^1]. Так как он глобальный (или просто передается по аргументам), то именно в него встроен метод Do. Если нам скажем в пакете где описывается некий предмет надо нарисовать при его поднятии какой-то супер-эффект на экране - мы поступаем вот так: @@ -139,3 +151,7 @@ func renderSuperEffect() { запихивает в очередь на выполнения в main thread эту самую реализацию. Которая с успехом выполняется в main loop. В целом картина именно такая, но больше подробностей можно найти по ссылкам в комментариях. + +[^1]: Если такой контейнер сериализовать (рекурсивно вместе со всем содержимым) и +записать на диск, то потом можно его прочитать и десереализовать. Получив тем самым почти +бесплатно Save / Load. \ No newline at end of file From 1c9eae28a1032fa08a7ef20d96acba3a8c1867ed Mon Sep 17 00:00:00 2001 From: "anton.gurov" Date: Fri, 8 Nov 2019 14:35:41 +0300 Subject: [PATCH 04/14] typos --- story/linux_go_blt_install_quickstart.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/story/linux_go_blt_install_quickstart.md b/story/linux_go_blt_install_quickstart.md index c36a453..b431bcb 100644 --- a/story/linux_go_blt_install_quickstart.md +++ b/story/linux_go_blt_install_quickstart.md @@ -111,7 +111,7 @@ func MainLoop(state GameState) { State - это обычный Value Object, экземпляр типа GameState. Я его использую как контейнер для важных для игры данных - уровня, состояния рендера, разных тикеров, -каналов для рендера и ввода-вывода итп[^1]. Так как он глобальный (или просто передается +каналов для рендера и ввода-вывода итп[1]. Так как он глобальный (или просто передается по аргументам), то именно в него встроен метод Do. Если нам скажем в пакете где описывается некий предмет надо нарисовать при его поднятии какой-то супер-эффект на экране - мы поступаем вот так: @@ -152,6 +152,6 @@ func renderSuperEffect() { выполняется в main loop. В целом картина именно такая, но больше подробностей можно найти по ссылкам в комментариях. -[^1]: Если такой контейнер сериализовать (рекурсивно вместе со всем содержимым) и -записать на диск, то потом можно его прочитать и десереализовать. Получив тем самым почти +[1]: Если такой контейнер сериализовать (рекурсивно вместе со всем содержимым) и +записать на диск, то потом можно его прочитать и десериализовать. Получив тем самым почти бесплатно Save / Load. \ No newline at end of file From 43fc7a30885a88936e2ae125a6819ec11ed16dc5 Mon Sep 17 00:00:00 2001 From: "anton.gurov" Date: Fri, 8 Nov 2019 14:36:46 +0300 Subject: [PATCH 05/14] typos --- story/linux_go_blt_install_quickstart.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/story/linux_go_blt_install_quickstart.md b/story/linux_go_blt_install_quickstart.md index b431bcb..07e8204 100644 --- a/story/linux_go_blt_install_quickstart.md +++ b/story/linux_go_blt_install_quickstart.md @@ -112,9 +112,10 @@ func MainLoop(state GameState) { State - это обычный Value Object, экземпляр типа GameState. Я его использую как контейнер для важных для игры данных - уровня, состояния рендера, разных тикеров, каналов для рендера и ввода-вывода итп[1]. Так как он глобальный (или просто передается -по аргументам), то именно в него встроен метод Do. Если нам скажем в пакете где -описывается некий предмет надо нарисовать при его поднятии какой-то супер-эффект -на экране - мы поступаем вот так: +по аргументам), то именно в него встроен метод Do. + +Если нам скажем в пакете, где описывается некий предмет, надо нарисовать при его +поднятии какой-то супер-эффект на экране - мы поступаем вот так: ```go package item From ed03230823fa85fd9654352d4166805a627bbbdb Mon Sep 17 00:00:00 2001 From: "anton.gurov" Date: Fri, 8 Nov 2019 14:38:15 +0300 Subject: [PATCH 06/14] typos 2 --- story/index.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/story/index.md b/story/index.md index 01b0b2b..f97494c 100644 --- a/story/index.md +++ b/story/index.md @@ -5,6 +5,7 @@ RLG и Golang - некоторые полезные советы 2. Что [стоит и НЕ стоит](go_game_dos_and_donts.md) делать с возможностями Go - +chans, +tickers, +throttling, -closures 3. [Система типов](./static_types_vs_ecs.md) - нативная или ECS? На самом деле и то, и то -#####Дополнения +Дополнения +--- 1. Как [не делать лишнюю работу](./makefile_and_crosscompiling.md) и почему это **важно**. \ No newline at end of file From 33f755d22d41c029896cbfebe54700147c86b1bf Mon Sep 17 00:00:00 2001 From: "anton.gurov" Date: Fri, 8 Nov 2019 14:39:30 +0300 Subject: [PATCH 07/14] updates --- story/makefile_and_crosscompiling.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/story/makefile_and_crosscompiling.md b/story/makefile_and_crosscompiling.md index 88749ee..e3cfa87 100644 --- a/story/makefile_and_crosscompiling.md +++ b/story/makefile_and_crosscompiling.md @@ -4,7 +4,8 @@ - Почему это важно: мелочи сжирают кучу времени. Не позволяйте им это делать! - настройка под Linux: все внешние либы собраны и включены в монорепо (дело вкуса) - Go-специфичные вещи: glide, go mod -- Кросскомпиляция, CGO для Mac и Linux. CGO_ENABLED=1, mingw, локальная линковка библиотек +- Кросскомпиляция, CGO для Mac и Linux. CGO_ENABLED=1, mingw, локальная видимость библиотек +- Makefile и нафига он нужен - Таргеты: Убираем бардак за собой - distclean, build - Автоматическое тестирование, testify. Не ленитесь писать тесты! - Деплой/публикация после сборки \ No newline at end of file From 485392f0a6053b59236a2786acbdcfea089d789e Mon Sep 17 00:00:00 2001 From: "anton.gurov" Date: Fri, 8 Nov 2019 14:41:41 +0300 Subject: [PATCH 08/14] typos --- story/linux_go_blt_install_quickstart.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/story/linux_go_blt_install_quickstart.md b/story/linux_go_blt_install_quickstart.md index 07e8204..ecd8826 100644 --- a/story/linux_go_blt_install_quickstart.md +++ b/story/linux_go_blt_install_quickstart.md @@ -8,13 +8,14 @@ ```go // #cgo LDFLAGS: -lBearLibTerminal ``` -Что подразумевает глобальную вивдимость библиотеки. Увы, пока пакета с BLT для распространенных дистрибутивов Linux нет. +Что подразумевает глобальную вивдимость библиотеки. Увы, пока пакета с BLT для +распространенных дистрибутивов Linux нет. Поэтому беде нужно помочь руками. #####Первый метод Сначала вручную показать линтеру, что такая библиотека есть, и потом перезагрузить -кеш путей к библиотекам:: +кеш путей к библиотекам (пример для Ubuntu): ```bash $ sudo echo "/path/to/libbearterminal.so" > /etc/ld.so.conf.d/libbearterminal.conf && sudo ldconfig ``` From 2ea4020be7a2669dbb072d6682368bd890d65089 Mon Sep 17 00:00:00 2001 From: "anton.gurov" Date: Fri, 8 Nov 2019 14:42:39 +0300 Subject: [PATCH 09/14] typos 5 --- story/linux_go_blt_install_quickstart.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/story/linux_go_blt_install_quickstart.md b/story/linux_go_blt_install_quickstart.md index ecd8826..8ea142a 100644 --- a/story/linux_go_blt_install_quickstart.md +++ b/story/linux_go_blt_install_quickstart.md @@ -58,7 +58,7 @@ RPATH ./ Горутины и многопоточность --- -Вторая кочка, на которой мне пришлось столкнуться - то то, что вызов любой своей +Вторая кочка, на которой мне пришлось споткнуться - то то, что вызов любой своей функции не из main thread BLT воспринимает крайне нервно, и сыпет фатальными ошибками. Это неприятно, тк часто Го выбирают именно за многопоточность из коробки. Но справедливости ради точно так же ведет себя и большинство From 482ab67156b74be07e239063c9cc8c4bfe0c2ebe Mon Sep 17 00:00:00 2001 From: "anton.gurov" Date: Fri, 8 Nov 2019 14:45:13 +0300 Subject: [PATCH 10/14] typos 6 --- story/linux_go_blt_install_quickstart.md | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/story/linux_go_blt_install_quickstart.md b/story/linux_go_blt_install_quickstart.md index 8ea142a..989b74e 100644 --- a/story/linux_go_blt_install_quickstart.md +++ b/story/linux_go_blt_install_quickstart.md @@ -111,9 +111,9 @@ func MainLoop(state GameState) { ``` State - это обычный Value Object, экземпляр типа GameState. Я его использую как -контейнер для важных для игры данных - уровня, состояния рендера, разных тикеров, -каналов для рендера и ввода-вывода итп[1]. Так как он глобальный (или просто передается -по аргументам), то именно в него встроен метод Do. +контейнер для важных для игры данных - географии уровня, состояния объектов и мобов, +разных тикеров, каналов для рендера и ввода-вывода итп[1]. Так как он глобальный +(или просто передается всюду по аргументам), то именно в него встроен метод Do. Если нам скажем в пакете, где описывается некий предмет, надо нарисовать при его поднятии какой-то супер-эффект на экране - мы поступаем вот так: @@ -154,6 +154,4 @@ func renderSuperEffect() { выполняется в main loop. В целом картина именно такая, но больше подробностей можно найти по ссылкам в комментариях. -[1]: Если такой контейнер сериализовать (рекурсивно вместе со всем содержимым) и -записать на диск, то потом можно его прочитать и десериализовать. Получив тем самым почти -бесплатно Save / Load. \ No newline at end of file +[1]: Если такой контейнер аккуратно сериализовать (рекурсивно вместе со всем содержимым) и записать на диск... То потом можно его прочитать и десериализовать. Получив тем самым почти бесплатно Save / Load. \ No newline at end of file From 7411f05685624d0960ed3c073d828e5c9154f35c Mon Sep 17 00:00:00 2001 From: "anton.gurov" Date: Fri, 8 Nov 2019 14:48:47 +0300 Subject: [PATCH 11/14] typos 7 --- story/linux_go_blt_install_quickstart.md | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/story/linux_go_blt_install_quickstart.md b/story/linux_go_blt_install_quickstart.md index 989b74e..0218b89 100644 --- a/story/linux_go_blt_install_quickstart.md +++ b/story/linux_go_blt_install_quickstart.md @@ -126,25 +126,21 @@ import blt "some.repo.ru/user/bearlibterminal" var State main.GameState -//функция скажем поднятия описание предмета... -func (item *Item) Pickup() { +//функция скажем поднятия особенного предмета... +func (item *SpecialItem) Pickup() { .... - doSuperEffect(State) -} -//and there we go like this: -func doSuperEffect(State main.GameState) { - ... - State.Do(func() { - renderSuperEffect() -// ...do stuff in main thread - }) - ... + //выполняем строго в main thread + State.Do(func() { + renderSuperEffect() + }) } ... +//тут собственно отрисовка эффекта func renderSuperEffect() { + ... blt.Layer(0) - blt.Print("WAAAGH") + blt.Print(x,y, "WAAAGH") ... } ``` From 657af45eb1e395fd3142cc5d27a41f4139318cef Mon Sep 17 00:00:00 2001 From: "anton.gurov" Date: Fri, 8 Nov 2019 14:52:41 +0300 Subject: [PATCH 12/14] typos 8 --- story/static_types_vs_ecs.md | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/story/static_types_vs_ecs.md b/story/static_types_vs_ecs.md index d11ca12..cd94f5a 100644 --- a/story/static_types_vs_ecs.md +++ b/story/static_types_vs_ecs.md @@ -2,19 +2,18 @@ Плюсы использования нативной системы типов -- Примитивы типа Rect -- Интерфейсы, type casting и переиспользования Blit -- свитчи по типам +- Примитивы типа Coords, Rect +- Интерфейсы, type casting и переиспользование Blit Минусы использования нативной системы типы - Структура структуры (эм..) иммутабельна -ECS - меняем бойлерплейт на относительное снижение связности +ECS - достигаем относительного снижения связности ценой чудовищного бойлерплейта - Делаем динамическую систему типов там и только там где нам надо - Возможность физически впихнуть в кеш проца все актуальные данные -- Особая актуальность для Go - обработка в main thread всего что связано с Io +- Да, это много копипасты. Но мы используем статически типизированный язык, а не питон, что вы хотели? Минутка рекламы gogue From c22c4d890f7a4576bfdf1acafe1e6a010bf3f8fd Mon Sep 17 00:00:00 2001 From: "anton.gurov" Date: Fri, 8 Nov 2019 18:05:19 +0300 Subject: [PATCH 13/14] bruteforce --- .gopath | 0 config.json | 4 +- .../precomputed_shade/precomputed_shade.go | 55 +++++++++++-------- 3 files changed, 35 insertions(+), 24 deletions(-) delete mode 100644 .gopath diff --git a/.gopath b/.gopath deleted file mode 100644 index e69de29..0000000 diff --git a/config.json b/config.json index ea1bcd6..0cadf1e 100644 --- a/config.json +++ b/config.json @@ -5,6 +5,6 @@ "sizeY": 47, "fpsLimit": 60, "font": "./resources/fonts-ttf/LiberationMono-Bold.ttf", - "fontSize": "8x12", + "fontSize": "9x14", "verbosity": "debug" -} \ No newline at end of file +} diff --git a/engine/fov/precomputed_shade/precomputed_shade.go b/engine/fov/precomputed_shade/precomputed_shade.go index e55e498..4dec910 100644 --- a/engine/fov/precomputed_shade/precomputed_shade.go +++ b/engine/fov/precomputed_shade/precomputed_shade.go @@ -78,6 +78,9 @@ Pre-Computed Visiblity Trees on RogueBasin Adam Milazzo's FOV Method Roundup where a similar method described as 'permissive' is detailed */ +const MIN_LIT_TO_BE_VISIBLE = 1 +const MIN_WALL_LIT_TO_BE_VISIBLE = 4 + var errNotFoundCell = errors.New("Cell not found") var errOutOfBounds = errors.New("Cell out of bounds") @@ -163,9 +166,9 @@ func (ps *precomputedShade) PrecomputeFovMap() { //Bresanham lines / Raycast var lineX, lineY float64 - for i := 0; i < 360; i++ { - dx := math.Sin(float64(i) / (float64(180) / math.Pi)) - dy := math.Cos(float64(i) / (float64(180) / math.Pi)) + for i := 0; i < 720; i++ { // 1/2 of angles + dx := math.Sin(float64(i) / (float64(360) / math.Pi)) //1/2 of angles + dy := math.Cos(float64(i) / (float64(360) / math.Pi)) lineX = 0 lineY = 0 @@ -204,11 +207,11 @@ func (ps *precomputedShade) recalc(level *gamemap.Level, initCoords types.Coords level.GetTile(initCoords).Visible = true - var fullShade = make([]byte, 360) + var fullShade = make([]byte, 720) // 1/2 of angles for i := range fullShade { fullShade[i] = 1 } - var emptyShade = make([]byte, 360) + var emptyShade = make([]byte, 720) // 1/2 of angles currentShade := emptyShade nextShade := emptyShade @@ -236,7 +239,11 @@ func (ps *precomputedShade) recalc(level *gamemap.Level, initCoords types.Coords //fmt.Printf("\n level coords: %v", lc) for _, angle := range cell.occludedAngles { - if level.GetTile(lc).BlocksSight { + if level.GetTile(lc).BlocksSight && ps.LightWalls { + if (nextShade[angle] == 0 && currentShade[angle] == 0) { + level.GetTile(lc).Visible = true + level.GetTile(lc).Explored = true + } nextShade[angle] = 1 } @@ -256,7 +263,7 @@ func (ps *precomputedShade) ComputeFov(level *gamemap.Level, initCoords types.Co for _, cell := range ps.CellList { //fmt.Printf("\n coords: %v, distance: %f, lit: %d", cell.Coords, cell.distance, cell.lit) cs, err := ps.toLevelCoords(level, initCoords, cell.Coords) - if cell.lit > 2 { + if cell.lit > MIN_LIT_TO_BE_VISIBLE { if err != nil { continue } @@ -265,21 +272,25 @@ func (ps *precomputedShade) ComputeFov(level *gamemap.Level, initCoords types.Co } //light walls, crutch - if level.GetTile(cs).BlocksSight && ps.LightWalls { - if cell.IsAdjacentTo(&types.Coords{0,0}) { - level.GetTile(cs).Visible = true - } else { - for _, maybeNb := range ps.CellList { - if //int(maybeNb.distance) == int(cell.distance-1) && - maybeNb.IsAdjacentTo(&cell.Coords) && - //(maybeNb.X == cell.X || maybeNb.Y == cell.Y) && - maybeNb.lit > 5 { //magic constant! - level.GetTile(cs).Visible = true - level.GetTile(cs).Explored = true - } - } - } - } + //if level.GetTile(cs).BlocksSight && ps.LightWalls { + // if cell.IsAdjacentTo(&types.Coords{0,0}) { + // level.GetTile(cs).Visible = true + // } else { + // maybeLit := false + // for _, maybeNb := range ps.CellList { + // if //int(maybeNb.distance) == int(cell.distance-1) && + // maybeNb.IsAdjacentTo(&cell.Coords) && + // (maybeNb.X == cell.X || maybeNb.Y == cell.Y) && + // maybeNb.lit > MIN_WALL_LIT_TO_BE_VISIBLE { //magic constant! + // maybeLit = true + // } + // } + // if maybeLit { + // level.GetTile(cs).Visible = true + // level.GetTile(cs).Explored = true + // } + // } + //} } } From becf7ea14372bc4b21587b3fde2a35c33abd0ee1 Mon Sep 17 00:00:00 2001 From: "anton.gurov" Date: Fri, 8 Nov 2019 18:44:37 +0300 Subject: [PATCH 14/14] fix keypad bindings --- config.json | 4 ++-- engine/screens/game.go | 16 ++++++++-------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/config.json b/config.json index 0cadf1e..ce33f4f 100644 --- a/config.json +++ b/config.json @@ -1,5 +1,5 @@ { - "version": "v0.0.1.4-3-g5619155", + "version": "v0.0.1.5", "title": "Alchemyst", "sizeX": 100, "sizeY": 47, @@ -7,4 +7,4 @@ "font": "./resources/fonts-ttf/LiberationMono-Bold.ttf", "fontSize": "9x14", "verbosity": "debug" -} +} \ No newline at end of file diff --git a/engine/screens/game.go b/engine/screens/game.go index 0ef1da8..49e9aa2 100644 --- a/engine/screens/game.go +++ b/engine/screens/game.go @@ -38,28 +38,28 @@ func (ts *GameScreen) Exit() { func (ts *GameScreen) HandleInput(input string) { //ts.state.Do(func(){ switch input { - case "Up", "k", "8": + case "Up", "k", "KP_8": ts.walk(ts.state, 0, -1) break - case "Down", "j", "2": + case "Down", "j", "KP_2": ts.walk(ts.state, 0, 1) break - case "Left", "h", "4": + case "Left", "h", "KP_4": ts.walk(ts.state, -1, 0) break - case "Right", "l", "6": + case "Right", "l", "KP_6": ts.walk(ts.state, 1, 0) break - case "y", "7": + case "y", "KP_7": ts.walk(ts.state, -1, -1) break - case "u", "9": + case "u", "KP_9": ts.walk(ts.state, 1, -1) break - case "b", "1": + case "b", "KP_1": ts.walk(ts.state, -1, 1) break - case "n", "3": + case "n", "KP_3": ts.walk(ts.state, 1, 1) break case "Shift+/":