diff --git a/.gitattributes b/.gitattributes
index f2cb800..89d2165 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -2,4 +2,5 @@
*.css linguist-generated
*.sh linguist-generated
*.bat linguist-generated
+*.txt linguist-language=Dox
.luaurc linguist-language=Json
diff --git a/.github/workflows/CD.yml b/.github/workflows/CD.yml
index 349a2ef..0deec41 100644
--- a/.github/workflows/CD.yml
+++ b/.github/workflows/CD.yml
@@ -10,8 +10,12 @@ permissions:
id-token: write
jobs:
- npm-gly-cli:
+ npm:
runs-on: ubuntu-latest
+ strategy:
+ fail-fast: false
+ matrix:
+ package: ['gly-cli', 'gly-engine', 'core-native-html5']
steps:
-
uses: actions/checkout@master
@@ -26,7 +30,7 @@ jobs:
registry-url: 'https://registry.npmjs.org'
-
run: |
- lua tools/build_npm_cli.lua
+ lua tools/cd_npm_${{ matrix.package }}.lua
-
working-directory: ./dist
run: |
diff --git a/.github/workflows/DOCS.yml b/.github/workflows/DOCS.yml
index 807b77a..3bcb033 100644
--- a/.github/workflows/DOCS.yml
+++ b/.github/workflows/DOCS.yml
@@ -1,8 +1,8 @@
name: docs
env:
- CLOUDFLARE_PROJECT_DOXYGEN: doxygen-engine
- CLOUDFLARE_PROJECT_PONG: pong-engine
+ CLOUDFLARE_PROJECT_DOXYGEN: doxygen-gly
+ CLOUDFLARE_PROJECT_EXAMPLE: example-gly
on:
workflow_dispatch:
@@ -21,11 +21,14 @@ jobs:
steps:
-
uses: actions/checkout@master
+ -
+ run: |
+ docker run --rm -v $(pwd):/app -w /app rodrigodornelles/doxygen:lua lua tools/doxygen_plugins.lua
-
run: |
docker run --rm -v $(pwd):/app -w /app rodrigodornelles/doxygen:lua doxygen
-
- if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name == github.repository
+ if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name == github.repository || github.event_name == 'workflow_dispatch'
uses: cloudflare/pages-action@v1
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
@@ -33,20 +36,28 @@ jobs:
projectName: ${{ env.CLOUDFLARE_PROJECT_DOXYGEN }}
directory: html
- pong:
- runs-on: ubuntu-latest
+ example:
if: github.event_name == 'push' || github.event.pull_request.draft == false
+ runs-on: ubuntu-latest
+ strategy:
+ fail-fast: false
+ matrix:
+ game: ['asteroids', 'dvdplayer', 'helloworld', 'launcher', 'pong']
steps:
-
uses: actions/checkout@master
+ -
+ uses: leafo/gh-actions-lua@v10
+ with:
+ luaVersion: '5.4'
-
run: |
- docker run --rm -v $(pwd):/app -w /app rodrigodornelles/doxygen:lua ./cli.sh build --core html5 ./examples/pong/game.lua --dist ./html/
+ ./cli.sh build @${{ matrix.game }} --core html5 --dist ./html/
-
- if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name == github.repository
+ if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name == github.repository || github.event_name == 'workflow_dispatch'
uses: cloudflare/pages-action@v1
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
- projectName: ${{ env.CLOUDFLARE_PROJECT_PONG }}
+ projectName: ${{ matrix.game }}-${{ env.CLOUDFLARE_PROJECT_EXAMPLE }}
directory: html
diff --git a/.gitignore b/.gitignore
index 8831805..d24ea0a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,4 +3,5 @@ vendor/
dist/
html/
latex/
+doxygen/
.out
\ No newline at end of file
diff --git a/.luaurc b/.luaurc
index 192531f..1cfeb33 100644
--- a/.luaurc
+++ b/.luaurc
@@ -16,10 +16,12 @@
"native_draw_color",
"native_draw_flush",
"native_draw_font",
+ "native_draw_image",
"native_draw_line",
"native_draw_rect",
"native_draw_start",
"native_draw_text",
+ "native_get_system_lang",
"io"
]
}
diff --git a/Doxyfile b/Doxyfile
index 6a7d43c..88efec5 100644
--- a/Doxyfile
+++ b/Doxyfile
@@ -1,9 +1,9 @@
# Custom Configs
DOXYFILE_ENCODING = UTF-8
-PROJECT_NAME = "Engine"
-PROJECT_NUMBER = 0.0.6
+PROJECT_NAME = "Gly Game Engine"
+PROJECT_NUMBER = 0.0.7
PROJECT_BRIEF = "Game engine in lua"
-PROJECT_LOGO =
+PROJECT_LOGO = assets/icon80x80.png
OUTPUT_DIRECTORY = .
RECURSIVE = YES
CREATE_SUBDIRS = NO
@@ -17,18 +17,19 @@ SHORT_NAMES = YES
INLINE_GROUPED_CLASSES = YES
INLINE_SIMPLE_STRUCTS = YES
TYPEDEF_HIDES_STRUCT = YES
-SOURCE_BROWSER = YES
+SHOW_FILES = NO
+SOURCE_BROWSER = NO
VERBATIM_HEADERS = NO
+REPEAT_BRIEF = NO
PREDEFINED = DOXYGEN=
PLANTUML_JAR_PATH = $(PLANTUML_JAR_PATH)
PLANTUML_CFG_FILE =
PLANTUML_INCLUDE_PATH =
OUTPUT_LANGUAGE = English
-FILE_PATTERNS = *.lua
-FILTER_PATTERNS = *.lua=lua2dox
+FILE_PATTERNS = *.lua *.txt
+FILTER_PATTERNS = *="lua tools/doxygen_filter.lua"
EXTENSION_MAPPING = .lua=C++
-INPUT = README.md SUPPORT.md src examples
-USE_MDFILE_AS_MAINPAGE = README.md
+INPUT = docs src examples
MARKDOWN_ID_STYLE = GITHUB
ALIASES += startjson=@startuml{json}
ALIASES += endjson=@enduml
@@ -40,6 +41,10 @@ ALIASES += endsalt=@enduml
GENERATE_TREEVIEW = YES
DISABLE_INDEX = NO
FULL_SIDEBAR = NO
+HTML_HEADER = doxygen/header.html
HTML_EXTRA_STYLESHEET = $(DOXYGEN_AWESOME_PATH)/doxygen-awesome.css \
- $(DOXYGEN_AWESOME_PATH)/doxygen-awesome-sidebar-only.css
+ $(DOXYGEN_AWESOME_PATH)/doxygen-awesome-sidebar-only.css \
+ $(DOXYGEN_AWESOME_PATH)/doxygen-awesome-sidebar-only-darkmode-toggle.css
+HTML_EXTRA_FILES = $(DOXYGEN_AWESOME_PATH)/doxygen-awesome-darkmode-toggle.js \
+ $(DOXYGEN_AWESOME_PATH)/doxygen-awesome-paragraph-link.js
HTML_COLORSTYLE = LIGHT
diff --git a/docs/index.txt b/docs/index.txt
new file mode 100644
index 0000000..71455dd
--- /dev/null
+++ b/docs/index.txt
@@ -0,0 +1,7 @@
+@mainpage
+
+@li @ref helloworld
+@li @ref install
+@li @ref why "Plataform Support"
+@li [View the CLI/Engine source code](https://github.com/gamelly/gly-engine)
+@li @ref why "Comparison between Game Engines"
diff --git a/docs/install.txt b/docs/install.txt
new file mode 100644
index 0000000..f856cd0
--- /dev/null
+++ b/docs/install.txt
@@ -0,0 +1,60 @@
+@page install How to Install
+
+@li @ref cli_download "download a unique lua file using wget"
+@li @ref cli_download "download a unique lua file using curl"
+@li @ref npm_install "install as system command using npm"
+@li @ref npm_install "install as project dependency using npm"
+
+@anchor npm_install
+
+## using npm
+
+### global
+
+```
+npm install -g demoon @gamely/gly-cli
+```
+
+now you can execute as a global command!
+
+```
+gly-cli version
+```
+
+### local
+
+```
+npm install --dev @gamely/gly-cli
+```
+
+now you need use npx to run inside your project!
+
+```
+npx gly-cli version
+```
+
+---
+
+@anchor cli_download
+
+## unique lua file
+
+@note @b Attention! that although it is a `.lua` file, @n it is obfuscating in a way, to browse the source code use `lua cli.lua cli-dump`
+
+### curl
+
+```
+wget get.gamely.com.br/cli.lua -o cli.lua
+```
+
+### wget
+
+```
+wget get.gamely.com.br/cli.lua
+```
+
+now you need a lua to execute a cli!
+
+```
+lua cli.lua version
+```
diff --git a/docs/why.txt b/docs/why.txt
new file mode 100644
index 0000000..958b328
--- /dev/null
+++ b/docs/why.txt
@@ -0,0 +1,45 @@
+@page why Features and Support
+
+## Comparison between Game Engines
+
+### In-game Resources
+
+| Native Resource | Gly Engine | Love2D | GameMaker | Unity | Godot |
+| :--------------- | :--------- | :--------- | :--------- | :--------- | :--------- |
+| Http Requests | Yes | No | No | Yes | Yes |
+| Json Parse | Yes | No | No | No | Yes |
+| I18N API | Yes | No | No | No | No |
+| Cache API | Yes | No | No | Yes | No |
+| QRCode API | Yes | No | No | No | No |
+| Blend modes | No | No | Yes | Yes | Yes |
+| Shadders | No | Yes | Yes | Yes | Yes |
+| Image Tint | No | Yes | Yes | Yes | Yes |
+| Image Rotate | No | Yes | Yes | Yes | Yes |
+| Polygon Rotate | Yes | No | No | No | No |
+| WASM HTML5 | Yes | No | Yes | Yes | Yes |
+| Non-WASM HTML5 | Yes | No | Yes | No | No |
+
+### Development Resources
+
+| Native Resource | Gly Engine | Love2D | GameMaker | Unity | Godot |
+| :--------------- | :--------- | :--------- | :--------- | :--------- | :----------- |
+| CLI toolchain | Yes | No | No | No | Yes |
+| REPL script | Lua | No | No | No | No |
+| Code script | Lua, Haxe or JS | Lua | GMS | C# | C#, GDScript |
+| Visual script | No | No | Yes | Yes | No |
+| Package manager | Yes | No | Yes | Yes | No |
+| IDE Programming | Yes | No | Yes | Yes | Yes |
+| Unit Test tools | Yes | No | No | Yes | Yes |
+
+
+## Plataform Support
+
+@call support
+
+### Development environment
+
+| Tier 1 | Linux, MacOS or BSD | main platform |
+| :----- | :------------------ | :------------ |
+| Tier 2 | NodeJS CLI | full support WIP
+| Tier 3 | HTML5 IDE | support
+| Tier 4 | Windows | support
diff --git a/examples/asteroids/game.lua b/examples/asteroids/game.lua
index 92399f9..cb16ed8 100644
--- a/examples/asteroids/game.lua
+++ b/examples/asteroids/game.lua
@@ -26,7 +26,25 @@
--! 8 -> 4: resume
--! @enduml
---! @cond
+local function i18n(std, game)
+ return {
+ ['pt-BR'] = {
+ ['lifes:'] = 'vidas:',
+ ['Continue'] = 'Continuar',
+ ['New Game'] = 'Novo Jogo',
+ ['Dificulty'] = 'Dificuldade',
+ ['Invincibility'] = 'Imortabilidade',
+ ['Object Limit'] = 'Limitador',
+ ['Graphics'] = 'Graficos',
+ ['fast'] = 'rapido',
+ ['pretty'] = 'bonito',
+ ['Language'] = 'Idioma',
+ ['Credits'] = 'Creditos',
+ ['Exit'] = 'Sair'
+ }
+ }
+end
+
local function draw_logo(std, game, height, anim)
anim = anim or 0
std.draw.font('sans', 32)
@@ -143,7 +161,6 @@ local function asteroid_destroy(std, game, id)
return score
end
---! @endcond
local function init(std, game)
-- game
@@ -205,7 +222,7 @@ local function loop(std, game)
local keyv = std.key.press.down - std.key.press.up
local keyh = std.key.press.right - std.key.press.left + std.key.press.enter + std.key.press.red
if keyv ~= 0 and game.milis > game.menu_time + 250 then
- game.menu = std.math.clamp(game.menu + keyv, game.player_pos_x == (game.width/2) and 2 or 1, 8)
+ game.menu = std.math.clamp(game.menu + keyv, game.player_pos_x == (game.width/2) and 2 or 1, 9)
game.menu_time = game.milis
end
if keyh ~= 0 and game.milis > game.menu_time + 100 then
@@ -226,8 +243,10 @@ local function loop(std, game)
game.graphics_fastest = std.math.clamp(game.graphics_fastest + keyh, 0, 1)
game.fps_max = 100
elseif game.menu == 7 then
- game.state = 2
+ std.i18n.next_language()
elseif game.menu == 8 then
+ game.state = 2
+ elseif game.menu == 9 then
std.game.exit()
end
end
@@ -372,30 +391,35 @@ local function draw(std, game)
if game.state == 1 then
local s2 = 0
local h = game.height/16
- local graphics = game.graphics_fastest == 1 and 'rapido' or 'bonito'
+ local hmenu = (h*(4+game.menu)) + 24
+ local language = std.i18n.get_language()
+ local graphics = game.graphics_fastest == 1 and 'fast' or 'pretty'
local s = draw_logo(std, game, h*2)
std.draw.font('sans', 16)
std.draw.color(std.color.white)
if game.player_pos_x ~= (game.width/2) then
- std.draw.text(game.width/2 - s, h*6, 'Continuar')
+ std.draw.text(game.width/2 - s, h*5, 'Continue')
end
- std.draw.text(game.width/2 - s, h*7, 'Novo Jogo')
- std.draw.text(game.width/2 - s, h*8, 'Dificuldade')
- std.draw.text(game.width/2 - s, h*9, 'Imortalidade')
- std.draw.text(game.width/2 - s, h*10, 'Limitador')
- std.draw.text(game.width/2 - s, h*11, 'Graficos')
- std.draw.text(game.width/2 - s, h*12, 'Creditos')
- std.draw.text(game.width/2 - s, h*13, 'Sair')
- std.draw.line(game.width/2 - s, (h*(5+game.menu)) + 24, game.width/2 + s, (h*(5+game.menu)) + 24)
+ std.draw.text(game.width/2 - s, h*6, 'New Game')
+ std.draw.text(game.width/2 - s, h*7, 'Dificulty')
+ std.draw.text(game.width/2 - s, h*8, 'Invincibility')
+ std.draw.text(game.width/2 - s, h*9, 'Object Limit')
+ std.draw.text(game.width/2 - s, h*10, 'Graphics')
+ std.draw.text(game.width/2 - s, h*11, 'Language')
+ std.draw.text(game.width/2 - s, h*12, 'Credits')
+ std.draw.text(game.width/2 - s, h*13, 'Exit')
+ std.draw.line(game.width/2 - s, hmenu, game.width/2 + s, hmenu)
std.draw.color(std.color.red)
s2=std.draw.text(game.level)
- std.draw.text(game.width/2 + s - s2, h*8, game.level)
+ std.draw.text(game.width/2 + s - s2, h*7, game.level)
s2=std.draw.text(game.imortal)
- std.draw.text(game.width/2 + s - s2, h*9, game.imortal)
+ std.draw.text(game.width/2 + s - s2, h*8, game.imortal)
s2=std.draw.text(game.asteroids_max)
- std.draw.text(game.width/2 + s - s2, h*10, game.asteroids_max)
+ std.draw.text(game.width/2 + s - s2, h*9, game.asteroids_max)
s2=std.draw.text(graphics)
- std.draw.text(game.width/2 + s - s2, h*11, graphics)
+ std.draw.text(game.width/2 + s - s2, h*10, graphics)
+ s3=std.draw.text(language)
+ std.draw.text(game.width/2 + s - s3, h*11, language)
return
elseif game.state == 2 then
local height = game.height/4
@@ -475,11 +499,12 @@ local P = {
version='1.0.0'
},
config = {
- require = 'math random',
+ require = 'math math.random i18n',
fps_drop = 5,
fps_time = 5
},
callbacks={
+ i18n=i18n,
init=init,
loop=loop,
draw=draw,
diff --git a/examples/dvdplayer/game.lua b/examples/dvdplayer/game.lua
new file mode 100644
index 0000000..02790cd
--- /dev/null
+++ b/examples/dvdplayer/game.lua
@@ -0,0 +1,46 @@
+local function init(std, game)
+ game.x = game.width/2
+ game.y = game.height/2
+ game.size = 80
+ game.hspeed = game.width/5000
+ game.vspeed = game.height/4000
+end
+
+local function loop(std, game)
+ game.x = std.math.clamp(game.x + (game.hspeed * game.dt), 0, game.width - game.size)
+ game.y = std.math.clamp(game.y + (game.vspeed * game.dt), 0, game.height - game.size)
+ if game.x == 0 or game.x == game.width - game.size then
+ game.hspeed = -1 * game.hspeed
+ end
+ if game.y == 0 or game.y == game.height - game.size then
+ game.vspeed = -1 * game.vspeed
+ end
+end
+
+local function draw(std, game)
+ std.draw.clear(std.color.black)
+ std.draw.image('icon80x80.png', game.x, game.y)
+end
+
+local function exit(std, game)
+end
+
+local P = {
+ meta={
+ title='DVD Player',
+ author='RodrigoDornelles',
+ description='a logo bouncing between the corners',
+ version='1.0.0'
+ },
+ assets={
+ 'assets/icon80x80.png:icon80x80.png'
+ },
+ callbacks={
+ init=init,
+ loop=loop,
+ draw=draw,
+ exit=exit
+ }
+}
+
+return P;
diff --git a/examples/launcher/game.lua b/examples/launcher/game.lua
index 35dfedb..2f9f360 100644
--- a/examples/launcher/game.lua
+++ b/examples/launcher/game.lua
@@ -1,5 +1,4 @@
---! @file examples/launcher/game.lua
---!
+--! @par Game FSM
--! @startuml
--! hide empty description
--! skinparam State {
@@ -39,7 +38,6 @@
--! 9 --> [*]
--! @enduml
---! @cond
local function next_state(game, new_state)
if game._state + 1 == new_state then
game._state = new_state
@@ -64,7 +62,6 @@ local function halt_state(game)
end
end
end
---! @endcond
local function init(std, game)
if not game._state then
@@ -239,7 +236,7 @@ local P = {
version='1.0.0'
},
config={
- require='http random math csv load'
+ require='http math.random math csv load'
},
callbacks={
init=init,
diff --git a/npm/core-native-html5/README.md b/npm/core-native-html5/README.md
new file mode 100644
index 0000000..61513eb
--- /dev/null
+++ b/npm/core-native-html5/README.md
@@ -0,0 +1,108 @@
+
+
+> create your own game-engine with just javascript.
+
+## Example
+
+### The Game
+```javascript
+function awesome_game(loop, draw, keys) {
+ let color = 0x00FFFFFF
+
+ loop.callback(() => {
+
+ })
+ draw.callback(() => {
+ draw.color(0x000000FF)
+ draw.rect(0, 0, 0, draw.width, draw.heigth)
+ draw.color(color)
+ draw.rect(0, 10, 20, 30, 40)
+ })
+ keys.callback((key, press) => {
+ if (key == 'KeyZ' && press) {
+ color = 0xFF0000FF
+ }
+ })
+}
+```
+
+### The Engine
+
+```javascript
+
+const engine = {
+ loop: {
+ callback: (f) => {engine.callback_loop = f}
+ },
+ draw: {
+ color: gly.global.get('native_draw_color'),
+ rect: gly.global.get('native_draw_rect'),
+ callback: (f) => {engine.callback_draw = f}
+ },
+ keys: {
+ callback: (f) => {engine.callback_keys = f}
+ },
+}
+
+gly.global.set('native_callback_init', (width, heigth, game) => {
+ game(engine.loop, engine.draw, engine.keys)
+ engine.draw.width = width
+ engine.draw.heigth = heigth
+})
+
+gly.init('#gameCanvas')
+gly.load(awesome_game)
+
+gly.global.set('native_callback_loop', engine.callback_loop)
+gly.global.set('native_callback_draw', engine.callback_draw)
+gly.global.set('native_callback_keyboard', engine.callback_keys)
+
+function updateKey(ev) {
+ gly.input(ev.code, ev.type === 'keydown')
+}
+window.addEventListener('keydown', updateKey)
+window.addEventListener('keyup', updateKey)
+
+function tick() {
+ gly.update()
+ window.requestAnimationFrame(tick)
+}
+tick()
+```
+
+## Cheatcheet
+
+### Direct API
+
+ * **gly.init(canvas_selector)**
+ * **gly.load(game_file_text)**
+ * **gly.input(key, value)**
+ * **gly.error(behavior)**
+ * **gly.resize()**
+ * **gly.update(milis)**
+ * **gly.global.set(name, value)**
+ * **gly.global.get(name)**
+
+### Functions
+
+ * **native_draw_start()**
+ * **native_draw_flush()**
+ * **native_draw_clear(color)**
+ * **native_draw_color(color)**
+ * **native_draw_font(name, size)**
+ * **native_draw_rect(mode, x, y, width, heigth)**
+ * **native_draw_line(x1, y1, x2, y2)**
+ * **native_draw_text(x, y, text)**
+ * **native_draw_poly(mode, verts, x, y, scale, angle, ox, oy)**
+ * **native_dict_http**
+ * **native_dict_json**
+
+### Callbacks
+
+ * **native_callback_loop(milis)**
+ * **native_callback_draw()**
+ * **native_callback_resize(width, height)**
+ * **native_callback_keyboard(key, value)**
+ * **native_callback_init(width, height, game)**
diff --git a/npm/core-native-html5/package.json b/npm/core-native-html5/package.json
new file mode 100644
index 0000000..4e121cf
--- /dev/null
+++ b/npm/core-native-html5/package.json
@@ -0,0 +1,17 @@
+{
+ "name": "@gamely/core-native-html5",
+ "version": "{{version}}",
+ "author": "RodrigoDornelles",
+ "license": "Apache-2.0",
+ "homepage": "https://gamely.com.br",
+ "repository": "https://github.com/gamelly/gly-engine",
+ "funding": "https://github.com/sponsors/RodrigoDornelles",
+ "bugs": "https://github.com/gamelly/gly-engine/issues",
+ "description": "create your own game-engine with just javascript.",
+ "main": "dist/index.js",
+ "keywords": [
+ "game engine",
+ "game",
+ "engine"
+ ]
+}
diff --git a/npm-gly-cli.json b/npm/gly-cli/package.json
similarity index 95%
rename from npm-gly-cli.json
rename to npm/gly-cli/package.json
index 35af420..5366ee8 100644
--- a/npm-gly-cli.json
+++ b/npm/gly-cli/package.json
@@ -1,6 +1,6 @@
{
"name": "@gamely/gly-cli",
- "version": "0.0.6",
+ "version": "{{version}}",
"author": "RodrigoDornelles",
"license": "Apache-2.0",
"homepage": "https://gamely.com.br",
diff --git a/npm/gly-engine/README.md b/npm/gly-engine/README.md
new file mode 100644
index 0000000..c7a3718
--- /dev/null
+++ b/npm/gly-engine/README.md
@@ -0,0 +1,3 @@
+
diff --git a/npm/gly-engine/package.json b/npm/gly-engine/package.json
new file mode 100644
index 0000000..db64311
--- /dev/null
+++ b/npm/gly-engine/package.json
@@ -0,0 +1,17 @@
+{
+ "name": "@gamely/gly-engine",
+ "version": "{{version}}",
+ "author": "RodrigoDornelles",
+ "license": "Apache-2.0",
+ "homepage": "https://gamely.com.br",
+ "repository": "https://github.com/gamelly/gly-engine",
+ "funding": "https://github.com/sponsors/RodrigoDornelles",
+ "bugs": "https://github.com/gamelly/gly-engine/issues",
+ "description": "Game Engine written in 100% lua that runs in a vacuum.",
+ "main": "dist/index.lua",
+ "keywords": [
+ "game engine",
+ "game",
+ "engine"
+ ]
+}
diff --git a/src/cli/commands/build.lua b/src/cli/commands/build.lua
index 37ad9c4..b8db00f 100644
--- a/src/cli/commands/build.lua
+++ b/src/cli/commands/build.lua
@@ -38,7 +38,8 @@ local function build(args)
'src/engine/meta/html5_webos/appinfo.json',
'src/engine/core/html5/index.html',
'src/engine/core/html5/index.html',
- 'src/engine/core/html5/engine.js',
+ 'src/engine/core/html5/driver-wasmoon.js',
+ 'src/engine/core/html5/core-native-html5.js',
'assets/icon80x80.png'
}
},
@@ -53,23 +54,11 @@ local function build(args)
'src/engine/meta/html5_tizen/.tproject',
'src/engine/core/html5/index.html',
'src/engine/core/html5/index.html',
- 'src/engine/core/html5/engine.js',
+ 'src/engine/core/html5/driver-wasmoon.js',
+ 'src/engine/core/html5/core-native-html5.js',
'assets/icon80x80.png'
}
},
- html5_ginga={
- src='src/engine/core/native/main.lua',
- post_exe='ginga dist/main.ncl -s '..screen,
- pipeline={
- zeebo_meta.late(dist..'game.lua'):file(dist..'index.html'):pipe()
- },
- extras={
- 'src/engine/meta/html5_ginga/main.ncl',
- 'src/engine/core/html5/index.html',
- 'src/engine/core/html5/index.html',
- 'src/engine/core/html5/engine.js',
- }
- },
html5={
src='src/engine/core/native/main.lua',
pipeline={
@@ -77,7 +66,8 @@ local function build(args)
},
extras={
'src/engine/core/html5/index.html',
- 'src/engine/core/html5/engine.js'
+ 'src/engine/core/html5/driver-wasmoon.js',
+ 'src/engine/core/html5/core-native-html5.js'
}
},
nintendo_wii={
diff --git a/src/cli/commands/info.lua b/src/cli/commands/info.lua
index f493228..e297b8a 100644
--- a/src/cli/commands/info.lua
+++ b/src/cli/commands/info.lua
@@ -21,7 +21,6 @@ local help_message = "Available commands:\n"
.."- ginga: Runs the Ginga core.\n"
.."- html5_webos: Builds for HTML5 on WebOS.\n"
.."- html5_tizen: Builds for HTML5 on Tizen.\n"
- .."- html5_ginga: Runs the Ginga core for HTML5.\n"
.."- html5: Runs the standard HTML5 core.\n"
.."- nintendo_wii: Builds for the Nintendo Wii.\n"
.."\n"
@@ -44,7 +43,7 @@ local help_message = "Available commands:\n"
.."- To run a game: ./cli.sh run ./examples/asteroids/game.lua " .. "-" .. "-core repl\n"
.."- To display metadata: ./cli.sh meta ./examples/asteroids/game.lua\n"
-local version_message = '0.0.6'
+local version_message = '0.0.7'
local function help()
return true, help_message
diff --git a/src/cli/commands/tools.lua b/src/cli/commands/tools.lua
index 4909bd2..0c13119 100644
--- a/src/cli/commands/tools.lua
+++ b/src/cli/commands/tools.lua
@@ -1,5 +1,6 @@
local zeebo_compiler = require('src/lib/cli/compiler')
local zeebo_bundler = require('src/lib/cli/bundler')
+local zeebo_fs = require('src/lib/cli/fs')
local function bundler(args)
local path, file = args.file:match("(.-)([^/\\]+)$")
@@ -11,16 +12,56 @@ local function compiler(args)
end
local function love_zip(args)
- return false, 'not implemented!'
+ os.execute('mkdir -p '..args.dist..'_love')
+ os.execute('mv '..args.path..'/* '..args.dist..'_love 2> /dev/null')
+ local zip_pid = io.popen('cd '..args.dist..'_love && zip -9 -r Game.love .')
+ local stdout = zip_pid:read('*a')
+ local ok = zip_pid:close()
+ zeebo_fs.move(args.dist..'_love/Game.love', args.dist..'Game.love')
+ zeebo_fs.clear(args.dist..'_love')
+ os.remove(args.dist..'_love')
+ return ok, stdout
end
local function love_exe(args)
return false, 'not implemented!'
end
+local function haxe_build(args)
+ local game_name = args.game
+ local game_file, file_error = io.open(game_name, 'r')
+ local game_content = game_file and game_file:read('*a')
+
+ if file_error then
+ return false, file_error
+ end
+
+ local pattern_utf8 = '_G%.require%("lua%-utf8"%)'
+ local replace_utf8 = 'select(2, pcall(require, "lua-utf8")) or select(2, pcall(require, "utf8")) or string'
+ local pattern_object = 'std%.(%w+):(%w+)'
+ local replace_object = 'std.%1.%2'
+
+ game_content = game_content:gsub(pattern_utf8, replace_utf8)
+ game_content = game_content:gsub(pattern_object, replace_object)
+
+ game_file:close()
+ game_file, file_error = io.open(game_name, 'w')
+
+ if file_error then
+ return false, file_error
+ end
+
+ game_file:write(game_content)
+ game_file:close()
+
+ return true
+end
+
+
local P = {
bundler = bundler,
compiler = compiler,
+ ['tool-haxe-build'] = haxe_build,
['tool-love-zip'] = love_zip,
['tool-love-exe'] = love_exe
}
diff --git a/src/cli/main.lua b/src/cli/main.lua
index 003b195..94b3ee7 100644
--- a/src/cli/main.lua
+++ b/src/cli/main.lua
@@ -1,3 +1,6 @@
+--! @short gly-cli
+--! @par Command List
+--! @call commands
local os = require('os')
local zeebo_argparse = require('src/lib/cli/argparse')
@@ -39,9 +42,12 @@ local command = zeebo_argparse.from(arg)
.add_next_value('file', {required=true})
.add_option_get('dist', {default='a.out'})
--
+ .add_subcommand('tool-haxe-build', commands_tools)
+ .add_next_value('game', {required=true})
+ --
.add_subcommand('tool-love-zip', commands_tools)
.add_next_value('path', {required=true})
- .add_option_get('dist', {required=true})
+ .add_option_get('dist', {default='./dist/'})
--
.add_subcommand('tool-love-exe', commands_tools)
.add_next_value('file', {required=true})
diff --git a/src/engine/core/ginga/draw.lua b/src/engine/core/ginga/draw.lua
index 21a9974..55c6ccc 100644
--- a/src/engine/core/ginga/draw.lua
+++ b/src/engine/core/ginga/draw.lua
@@ -3,6 +3,7 @@ local math = require('math')
--! @cond
local canvas = nil
local game = nil
+local std = nil
--! @endcond
local function color(c)
@@ -41,11 +42,20 @@ local function line(x1, y1, x2, y2)
canvas:drawLine(x1, y1, x2, y2)
end
-local function install(std, lgame, application, ginga)
+local function image(src, x, y)
+ local image = std.mem.cache('image'..src, function()
+ return canvas:new('../assets/'..src)
+ end)
+ canvas:compose(x, y, image)
+end
+
+local function install(lstd, lgame, application, ginga)
canvas = ginga.canvas
game = lgame
+ std = lstd
std = std or {}
std.draw = std.draw or {}
+ std.draw.image=image
std.draw.clear=clear
std.draw.color=color
std.draw.rect=rect
diff --git a/src/engine/core/ginga/main.lua b/src/engine/core/ginga/main.lua
index 3206080..a0b2265 100644
--- a/src/engine/core/ginga/main.lua
+++ b/src/engine/core/ginga/main.lua
@@ -4,6 +4,8 @@ local engine_fps = require('src/lib/engine/fps')
local engine_math = require('src/lib/engine/math')
local engine_game = require('src/lib/engine/game')
local engine_http = require('src/lib/engine/http')
+local engine_i18n = require('src/lib/engine/i18n')
+local engine_memory = require('src/lib/engine/memory')
local engine_color = require('src/lib/object/color')
local engine_keys = require('src/engine/core/ginga/keys')
local engine_loop = require('src/engine/core/ginga/loop')
@@ -67,6 +69,10 @@ local function install(evt, gamefile)
time={1, 10, 30, 40, 60, 90}
}
+ local system_language = function()
+ return 'pt-BR'
+ end
+
application = zeebo_module.loadgame(gamefile)
if not application then
error('game not loaded!')
@@ -84,14 +90,16 @@ local function install(evt, gamefile)
:package('@keys', engine_keys)
:package('@loop', engine_loop)
:package('@draw', engine_draw, ginga)
- :package('@draw_fps', engine_draw_fps)
- :package('@draw_poly', engine_draw_poly, polygons)
+ :package('@draw.fps', engine_draw_fps)
+ :package('@draw.poly', engine_draw_poly, polygons)
+ :package('@memory', engine_memory)
:package('load', zeebo_module.load)
:package('csv', engine_encoder, library_csv)
:package('json', engine_encoder, library_json)
:package('math', engine_math.clib)
- :package('random', engine_math.clib_random)
+ :package('math.random', engine_math.clib_random)
:package('http', engine_http, protocol_http_ginga)
+ :package('i18n', engine_i18n, system_language)
:register(register_event_loop)
:register(register_fixed_loop)
:run()
diff --git a/src/engine/core/html5/core-native-html5.js b/src/engine/core/html5/core-native-html5.js
new file mode 100644
index 0000000..327a799
--- /dev/null
+++ b/src/engine/core/html5/core-native-html5.js
@@ -0,0 +1,230 @@
+const engine = {
+ stop: false,
+ file: './main.lua',
+ error: {
+ callback: null,
+ capture: false,
+ console: false,
+ canvas: false,
+ stop: false
+ },
+ images: {},
+ listen: {},
+ global: {
+ native_draw_start: () => {
+ engine.canvas_ctx.clearRect(0, 0, engine.canvas_element.width, engine.canvas_element.height)
+ },
+ native_draw_flush: () => {},
+ native_draw_clear: (color) => {
+ engine.canvas_ctx.fillStyle = '#' + color.toString(16).padStart(8, '0')
+ engine.canvas_ctx.fillRect(0, 0, engine.canvas_element.width, engine.canvas_element.height)
+ },
+ native_draw_color: (color) => {
+ const hex = '#' + color.toString(16).padStart(8, '0')
+ engine.canvas_ctx.strokeStyle = hex
+ engine.canvas_ctx.fillStyle = hex
+ },
+ native_draw_line: (x1, y1, x2, y2) => {
+ engine.canvas_ctx.beginPath()
+ engine.canvas_ctx.moveTo(x1, y1)
+ engine.canvas_ctx.lineTo(x2, y2)
+ engine.canvas_ctx.stroke()
+ },
+ native_draw_rect: (mode, x, y, w, h) => {
+ mode === 1 ? engine.canvas_ctx.strokeRect(x, y, w, h) : engine.canvas_ctx.fillRect(x, y, w, h)
+ },
+ native_draw_font: (name, size) => {
+ const font_size = size || name
+ const font_name = 'sans'
+ engine.canvas_ctx.font = `${font_size}px ${font_name}`;
+ engine.canvas_ctx.textBaseline = 'top'
+ engine.canvas_ctx.textAlign = 'left'
+ },
+ native_draw_text: (x, y, text) => {
+ if (x && y) {
+ engine.canvas_ctx.fillText(text, x, y)
+ }
+ const { width, actualBoundingBoxAscent, actualBoundingBoxDescent } = engine.canvas_ctx.measureText(text || x)
+ return [width, actualBoundingBoxAscent + actualBoundingBoxDescent]
+ },
+ native_draw_image: (src, x, y) => {
+ if (!(src in engine.images)) {
+ engine.images[src] = document.createElement('img')
+ engine.images[src].src = src
+ engine.images[src].onload = function() {
+ engine.images[src].attributes.done = 'true'
+ }
+ }
+ if (engine.images[src].attributes.done) {
+ engine.canvas_ctx.drawImage(engine.images[src], x, y)
+ }
+ },
+ native_get_system_language: () => {
+ return navigator.language
+ },
+ native_dict_poly: {
+ poly2: (mode, verts, x, y, scale = 1, angle = 0, ox = 0, oy = 0) => {
+ let index = 0
+ engine.canvas_ctx.beginPath()
+ while (index < verts.length) {
+ const px = verts[index];
+ const py = verts[index + 1];
+ const xx = x + ((ox - px) * -scale * Math.cos(angle)) - ((oy - py) * -scale * Math.sin(angle));
+ const yy = y + ((oy - px) * -scale * Math.sin(angle)) + ((ox - py) * -scale * Math.cos(angle));
+ if (index < 2) {
+ engine.canvas_ctx.moveTo(xx, yy)
+ } else {
+ engine.canvas_ctx.lineTo(xx, yy)
+ }
+ index += 2;
+ }
+ engine.canvas_close[mode]()
+ }
+ },
+ native_dict_http: {
+ handler: (self) => {
+ const method = self.method
+ const headers = new Headers(self.headers_dict)
+ const params = new URLSearchParams(self.params_dict)
+ const url = `${self.url}` + '?' + params.toString()
+ const body = ['HEAD', 'GET'].includes(method) ? null : self.body_content
+ self.promise()
+ fetch(url, {
+ body: body,
+ method: method,
+ headers: headers
+ })
+ .then((response) => {
+ self.set('ok', response.ok)
+ self.set('status', response.status)
+ return response.text()
+ })
+ .then((content) => {
+ self.set('body', content)
+ self.resolve()
+ })
+ .catch((error) => {
+ self.set('ok', false)
+ self.set('error', `${error}`)
+ self.resolve()
+ })
+ }
+ },
+ native_dict_json: {
+ encode: JSON.stringify,
+ decode: JSON.parse
+ }
+ }
+}
+
+function errorController(func) {
+ if (engine.stop) {
+ return
+ }
+ if (!engine.error.capture) {
+ return func()
+ }
+ try {
+ func()
+ }
+ catch(e) {
+ if (engine.error.console) {
+ console.log(e)
+ }
+ if (engine.error.stop) {
+ engine.stop = true
+ }
+ if (engine.error.canvas) {
+ engine.global.native_draw_start()
+ engine.global.native_draw_clear(0x0000FFFF)
+ engine.global.native_draw_color(0xFFFFFFFF)
+ engine.global.native_draw_text(8, 16, 'Fatal ERROR')
+ engine.global.native_draw_text(8, 32, e.toString())
+ }
+ if (engine.error.callback) {
+ engine.error.callback(e)
+ }
+ }
+}
+
+function resizeCanvas() {
+ if (engine.body_element.clientWidth > engine.body_element.clientHeight) {
+ engine.canvas_element.height = engine.body_element.clientHeight
+ engine.canvas_element.width = engine.body_element.clientWidth
+ }
+ else {
+ engine.canvas_element.height = Math.floor(engine.body_element.clientHeight / 2)
+ engine.canvas_element.width = engine.body_element.clientWidth
+ }
+}
+
+const gly = {
+ init: (canvas_selector) => {
+ engine.body_element = document.querySelector('body')
+ engine.canvas_element = document.querySelector(canvas_selector)
+ engine.canvas_ctx = engine.canvas_element.getContext("2d")
+ engine.canvas_close = [
+ () => engine.canvas_ctx.fill(),
+ () => {
+ engine.canvas_ctx.closePath()
+ engine.canvas_ctx.stroke()
+ },
+ () => engine.canvas_ctx.stroke()
+ ]
+ resizeCanvas()
+ },
+ load: (game_file) => {
+ const {width, height} = engine.canvas_element
+ errorController(() => {
+ engine.listen.native_callback_init(width, height, game_file)
+ })
+ },
+ input: (key, value) => {
+ errorController(() => {
+ engine.listen.native_callback_keyboard(key, value)
+ })
+ },
+ error: (behavior, error_callback) => {
+ const silent = behavior.includes('silent')
+ engine.error.capture = !behavior.includes('default')
+ engine.error.console = !silent && behavior.includes('console')
+ engine.error.canvas = !silent && behavior.includes('canvas')
+ engine.error.stop = !silent && behavior.includes('stop')
+ engine.error.callback = error_callback
+ },
+ resize: () => {
+ resizeCanvas()
+ const {width, height} = engine.canvas_element
+ errorController(() => {
+ engine.listen.native_callback_resize(width, height)
+ })
+ },
+ update: (milis) => {
+ errorController(() => {
+ engine.listen.native_callback_loop(milis)
+ engine.listen.native_callback_draw()
+ })
+ },
+ engine: {
+ set: (file_name) => engine.file = file_name,
+ get: () => engine.file
+ },
+ global: {
+ set: (var_name, value) => {
+ engine.listen[var_name] = value
+ },
+ get: (var_name) => {
+ return engine.global[var_name]
+ }
+ }
+}
+
+if (typeof exports === 'object' && typeof module !== 'undefined') {
+ module.exports = gly;
+} else if (typeof define === 'function' && define.amd) {
+ define([], function() {
+ return gly;
+ });
+} else {
+ window.gly = gly;
+}
diff --git a/src/engine/core/html5/driver-wasmoon.js b/src/engine/core/html5/driver-wasmoon.js
new file mode 100644
index 0000000..cd55350
--- /dev/null
+++ b/src/engine/core/html5/driver-wasmoon.js
@@ -0,0 +1,82 @@
+import { LuaFactory, LuaMultiReturn } from 'https://cdn.jsdelivr.net/npm/wasmoon@1.16.0/+esm'
+
+if (!gly) {
+ error('gly is not loaded!')
+}
+
+gly.wasmoon = async (game_file) => {
+ const factory = new LuaFactory()
+ const engine_file = gly.engine.get()
+ const lua = await factory.createEngine()
+ const engine_response = await fetch(engine_file)
+ const engine_lua = await engine_response.text()
+ await lua.doString(engine_lua)
+
+ gly.global.set('native_callback_init', lua.global.get('native_callback_init'))
+ gly.global.set('native_callback_loop', lua.global.get('native_callback_loop'))
+ gly.global.set('native_callback_draw', lua.global.get('native_callback_draw'))
+ gly.global.set('native_callback_resize', lua.global.get('native_callback_resize'))
+ gly.global.set('native_callback_keyboard', lua.global.get('native_callback_keyboard'))
+ lua.global.set('native_draw_start', gly.global.get('native_draw_start'))
+ lua.global.set('native_draw_flush', gly.global.get('native_draw_flush'))
+ lua.global.set('native_draw_clear', gly.global.get('native_draw_clear'))
+ lua.global.set('native_draw_color', gly.global.get('native_draw_color'))
+ lua.global.set('native_draw_font', gly.global.get('native_draw_font'))
+ lua.global.set('native_draw_rect', gly.global.get('native_draw_rect'))
+ lua.global.set('native_draw_line', gly.global.get('native_draw_line'))
+ lua.global.set('native_draw_image', gly.global.get('native_draw_image'))
+ lua.global.set('native_dict_http', gly.global.get('native_dict_http'))
+ lua.global.set('native_dict_json', gly.global.get('native_dict_json'))
+ lua.global.set('native_dict_poly', gly.global.get('native_dict_poly'))
+ lua.global.set('native_draw_text', (x, y, text) => {
+ const native_draw_text = gly.global.get('native_draw_text')
+ return LuaMultiReturn.from(native_draw_text(x, y, text))
+ })
+
+ gly.error('stop, canvas, console')
+ gly.init('#gameCanvas')
+
+ if (typeof game_file === 'string' && !game_file.includes('\n')) {
+ const game_response = await fetch(game_file)
+ gly.load(await game_response.text())
+ } else {
+ gly.load(game_file)
+ }
+
+ const keys = [
+ [403, 'red'],
+ [404, 'green'],
+ [405, 'yellow'],
+ [406, 'blue'],
+ ['KeyZ', 'red'],
+ ['KeyX', 'green'],
+ ['KeyC', 'yellow'],
+ ['KeyV', 'blue'],
+ ['Enter', 'enter'],
+ ['ArrowUp', 'up'],
+ ['ArrowDown', 'down'],
+ ['ArrowLeft', 'left'],
+ ['ArrowRight', 'right'],
+ ];
+
+ function updateSize() {
+ gly.resize()
+ }
+
+ function updateKey(ev) {
+ const key = keys.find(key => key[0] == ev.code)
+ if (key) {
+ gly.input(key[1], Number(ev.type === 'keydown'))
+ }
+ }
+
+ function updateLoop() {
+ window.requestAnimationFrame(updateLoop);
+ gly.update((new Date()).getTime())
+ }
+
+ window.addEventListener("resize", updateSize);
+ window.addEventListener('keydown', updateKey)
+ window.addEventListener('keyup', updateKey)
+ window.requestAnimationFrame(updateLoop);
+}
diff --git a/src/engine/core/html5/engine.js b/src/engine/core/html5/engine.js
deleted file mode 100644
index c6c7e09..0000000
--- a/src/engine/core/html5/engine.js
+++ /dev/null
@@ -1,159 +0,0 @@
-import { LuaFactory, LuaMultiReturn } from 'https://cdn.jsdelivr.net/npm/wasmoon@1.16.0/+esm'
-
-document.addEventListener('DOMContentLoaded', async () => {
- const factory = new LuaFactory()
- const lua = await factory.createEngine()
-
- const engine_response = await fetch('./main.lua')
- const game_response = await fetch('./game.lua')
-
- const engine_lua = await engine_response.text()
- const game_lua = await game_response.text()
-
- const body_element = document.querySelector('body')
- const canvas_element = document.querySelector('#gameCanvas')
- const canvas_ctx = canvas_element.getContext("2d")
- const canvas_close = [
- () => canvas_ctx.fill(),
- () => {
- canvas_ctx.closePath()
- canvas_ctx.stroke()
- },
- () => canvas_ctx.stroke()
- ]
-
- lua.global.set('native_draw_start', () => {
- canvas_ctx.clearRect(0, 0, canvas_element.width, canvas_element.height)
- })
- lua.global.set('native_draw_flush', () => {})
- lua.global.set('native_draw_clear', (color) => {
- canvas_ctx.fillStyle = '#' + color.toString(16).padStart(8, '0')
- canvas_ctx.fillRect(0, 0, canvas_element.width, canvas_element.height)
- })
- lua.global.set('native_draw_color', (color) => {
- const hex = '#' + color.toString(16).padStart(8, '0')
- canvas_ctx.strokeStyle = hex
- canvas_ctx.fillStyle = hex
- })
- lua.global.set('native_draw_line', (x1, y1, x2, y2) => {
- canvas_ctx.beginPath()
- canvas_ctx.moveTo(x1, y1)
- canvas_ctx.lineTo(x2, y2)
- canvas_ctx.stroke()
- })
- lua.global.set('native_draw_rect', (mode, x, y, w, h) => mode === 1?
- canvas_ctx.strokeRect(x, y, w, h):
- canvas_ctx.fillRect(x, y, w, h)
- )
- lua.global.set('native_draw_font', (name, size) => {})
- lua.global.set('native_draw_text', (x, y, text) => {
- x && y && canvas_ctx.fillText(text, x, y)
- const { width, actualBoundingBoxAscent, actualBoundingBoxDescent } = canvas_ctx.measureText(text || x)
- return LuaMultiReturn.from([width, actualBoundingBoxAscent + actualBoundingBoxDescent])
- })
- lua.global.set('native_dict_poly', {
- poly2: (mode, verts, x, y, scale = 1, angle = 0, ox = 0, oy = 0) => {
- let index = 0
- canvas_ctx.beginPath()
- while (index < verts.length) {
- const px = verts[index];
- const py = verts[index + 1];
- const xx = x + ((ox - px) * -scale * Math.cos(angle)) - ((ox - py) * -scale * Math.sin(angle));
- const yy = y + ((oy - px) * -scale * Math.sin(angle)) + ((oy - py) * -scale * Math.cos(angle));
- if (index < 2) {
- canvas_ctx.moveTo(xx, yy)
- } else {
- canvas_ctx.lineTo(xx, yy)
- }
- index = index + 2;
- }
- canvas_close[mode]()
- }
- })
- lua.global.set('native_dict_http', {
- handler: (self) => {
- const method = self.method
- const headers = new Headers(self.headers_dict)
- const params = new URLSearchParams(self.params_dict)
- const url = `${self.url}` + '?' + params.toString()
- const body = ['HEAD', 'GET'].includes(method)? null: self.body_content
- self.promise()
- fetch(url, {
- body: body,
- method: method,
- headers: headers
- })
- .then((response) => {
- self.set('ok', response.ok)
- self.set('status', response.status)
- return response.text()
- })
- .then((content) => {
- self.set('body', content)
- self.resolve()
- })
- .catch((error) => {
- self.set('ok', false)
- self.set('error', `${error}`)
- self.resolve()
- })
- }
- })
- lua.global.set('native_dict_json', {
- encode: JSON.stringify,
- decode: JSON.parse
- })
-
- if (body_element.clientWidth > body_element.clientHeight) {
- canvas_element.height = body_element.clientHeight
- canvas_element.width = body_element.clientWidth
- }
- else {
- canvas_element.height = Math.floor(body_element.clientHeight / 2)
- canvas_element.width = body_element.clientWidth
- }
-
- await lua.doString(engine_lua)
- const engine_callbacks = {
- init: lua.global.get('native_callback_init'),
- update: lua.global.get('native_callback_loop'),
- draw: lua.global.get('native_callback_draw'),
- keyboard: lua.global.get('native_callback_keyboard'),
- }
- engine_callbacks.init(canvas_element.width, canvas_element.height, game_lua)
-
- setTimeout(() => {
- const keys = [
- [403, 'red'],
- [404, 'green'],
- [405, 'yellow'],
- [406, 'blue'],
- ['KeyZ', 'red'],
- ['KeyX', 'green'],
- ['KeyC', 'yellow'],
- ['KeyV', 'blue'],
- ['Enter', 'enter'],
- ['ArrowUp', 'up'],
- ['ArrowDown', 'down'],
- ['ArrowLeft', 'left'],
- ['ArrowRight', 'right'],
- ];
-
- const keyHandler = (ev) => keys
- .filter(key => [ev.code, ev.keyCode].includes(key[0]))
- .map(key => engine_callbacks.keyboard(key[1], Number(ev.type === 'keydown')))
-
- window.addEventListener('keydown', keyHandler)
- window.addEventListener('keyup', keyHandler)
- }, 100)
-
- const tick = () => {
- const now = new Date()
- const milis = now.getTime()
- engine_callbacks.update(milis)
- engine_callbacks.draw()
- window.requestAnimationFrame(tick)
- }
-
- tick()
-})
diff --git a/src/engine/core/html5/index.html b/src/engine/core/html5/index.html
index 1017fa4..4620874 100644
--- a/src/engine/core/html5/index.html
+++ b/src/engine/core/html5/index.html
@@ -36,6 +36,10 @@
-
+
+
+