JavaScriptで関数型ゲームエンジンを作るよ!part1
JavaScriptで関数型ゲームエンジンを作るよ!part1:
この記事は、UUUM Advent Calendar 2018 7日目です。
人生紆余曲折あって
自鯖の
懇切丁寧にブログ記事書くのはめんどくさいので適当な解説しか書いてないし、今後も書かないんじゃないかなぁと思っています。
GitHub: https://github.com/takeokunn/takengine
友達「え、エンジニアなのにエンジン作ったことないの????エンジニアなのに????」
僕「とても辛い」
ねねっち「 エ ン ジ ン に 頼 ら ず 一 か ら プ ロ グ ラ ミ ン グ し る ん だ ぁ 〜 」
僕「ねねっちでもできるならいけるやろ!!!!!」
僕「一応これでも金もらって(※要出典)働いているエンジニアだし、関数型チックに書いてクオリティ高いエンジン作るぞ!!!」
今回、参考にしたゲームエンジンは以下のyoutubeの動画です。
https://www.youtube.com/watch?v=TW1ie0pIO_E&t=2s
alexkehayias/chocolatier
ただ作るだけでは面白みがないので、縛りを入れました。
ClojureScriptで書かれたalexkehayias/chocolatierを一度もビルドせずに作る
これにより難易度が上がるので楽しさが倍増します。
・設計思想を固める
・プロジェクトをつくる ← 今回の記事はここまで
・ゲームループをつくる
・初期stateを生成し、ゲームループに合わせて更新する処理を書く
・グラフィックライブラリを導入する
・入力などのイベントを取得する ← イマココ
・当たり判定などのイベントを発火させる
・シーン管理をする
・チャリ走レベルのクソゲーを雑につくる
・シューティングゲームレベルのそれなりのものをつくる
・ゲームを自動でプレイするプログラムを書く
・ゲームを自動でクリアするプログラムを書く
描画して入力に合わせて画像を動かすところまでは動いたヤッター
Entity Component Systemをベースに作っています。
オブジェクト指向というよりはデータ指向にコードを書くことができ、美しく書くことが出来て楽しいです。
ECSの説明書こうと筆を進めていたのですが先駆者の記事が素晴らしかったのでめんどくさくなりました。
以下を参考にしたりググってください。
【Unity】Unity 2018のEntity Component System(通称ECS)について(1)
エンティティ・コンポーネント・システム wiki
このプロジェクトではこんな感じでEntity/Component/Systemを定義しています。
こんな風にEntity/Component/Sysytemを定義し、State化して
こんな感じでDirectory/Fileを作りました。
読んだことも書いたこともない
ClojureDocs 死ぬほど読みやすいので他の言語も参考にしてほしいです。
UUUMでエンジニアをするとヒルズから見える絶景を堪能できます!
仕事でゲームエンジンは開発しないけどね
詳しくはこちら →→→→→→ UUUM攻殻機動隊の紹介
はじめに
この記事は、UUUM Advent Calendar 2018 7日目です。人生紆余曲折あって
UUUM
に12月に入社した新入社員です優しくしてください。自鯖の
Docker Swarm
化を書こうかなーって思ったけど、まとまらなかったのでとりあえずゲームエンジンについて書いていこうと思ってます。懇切丁寧にブログ記事書くのはめんどくさいので適当な解説しか書いてないし、今後も書かないんじゃないかなぁと思っています。
repoと使用ライブラリ
GitHub: https://github.com/takeokunn/takengine- pixi.js
- stats.js
- keycode
- webpack
- babel
- eslint
動機
友達「え、エンジニアなのにエンジン作ったことないの????エンジニアなのに????」僕「とても辛い」
ねねっち「 エ ン ジ ン に 頼 ら ず 一 か ら プ ロ グ ラ ミ ン グ し る ん だ ぁ 〜 」
僕「ねねっちでもできるならいけるやろ!!!!!」
僕「一応これでも金もらって(※要出典)働いているエンジニアだし、関数型チックに書いてクオリティ高いエンジン作るぞ!!!」
参考にしたもの
今回、参考にしたゲームエンジンは以下のyoutubeの動画です。Functional Game Engine Design for the Web - Alex Kehayias
https://www.youtube.com/watch?v=TW1ie0pIO_E&t=2s
ClojureScript
で書かれているレポジトリalexkehayias/chocolatier
レギュレーション
ただ作るだけでは面白みがないので、縛りを入れました。ClojureScriptで書かれたalexkehayias/chocolatierを一度もビルドせずに作る
これにより難易度が上がるので楽しさが倍増します。
進捗
・設計思想を固める・プロジェクトをつくる ← 今回の記事はここまで
・ゲームループをつくる
・初期stateを生成し、ゲームループに合わせて更新する処理を書く
・グラフィックライブラリを導入する
・入力などのイベントを取得する ← イマココ
・当たり判定などのイベントを発火させる
・シーン管理をする
・チャリ走レベルのクソゲーを雑につくる
・シューティングゲームレベルのそれなりのものをつくる
・ゲームを自動でプレイするプログラムを書く
・ゲームを自動でクリアするプログラムを書く
描画して入力に合わせて画像を動かすところまでは動いたヤッター
設計思想
Entity Component Systemをベースに作っています。オブジェクト指向というよりはデータ指向にコードを書くことができ、美しく書くことが出来て楽しいです。
ECSの説明書こうと筆を進めていたのですが先駆者の記事が素晴らしかったのでめんどくさくなりました。
以下を参考にしたりググってください。
【Unity】Unity 2018のEntity Component System(通称ECS)について(1)
エンティティ・コンポーネント・システム wiki
このプロジェクトではこんな感じでEntity/Component/Systemを定義しています。
Entity周りのコード
// src/game/entity.js import { player } from 'entities'; export const entity_state = (loader, resources, stage) => ([ { type: 'entity', opts: player.create('player1', loader, resources['player'], stage) } ]); // src/entities/player.js import { pixi } from 'engine_utils'; import { position, renderable, moveable } from 'engine_components'; export const create = (uid, loader, resource, stage) => { return { uid: uid, components: [ { uid: 'sprite', state: renderable.mk_sprite_state(loader, stage, resource.name) }, { uid: 'position', state: position.mk_position_state(20, 20, 0, 0, 0) }, { uid: 'controller', state: {} } ] } };
Component周りのコード
import { animate, attack, controller, damage, ephemeral, moveable, position, renderable, text } from 'engine_components'; export const component_state = [ { type: 'component', opts: { uid: 'position', component: { fn: position.fn, select_systems: [], select_components: ['controller'], subscriptions: [], cleanup_fn: () => {} } } }, { type: 'component', opts: { uid: 'controller', component: { fn: controller.react_to_input, select_systems: ['key_input'], select_components: [], subscriptions: [], cleanup_fn: () => {} } } }, { type: 'component', opts: { uid: 'sprite', component: { fn: renderable.sprite_fn, select_systems: [], select_components: ['position'], subscriptions: [], cleanup_fn: () => {} } } }, { type: 'component', opts: { uid: 'animate', component: { fn: animate.fn, select_systems: [], select_components: ['action'], subscriptions: [], cleanup_fn: () => {} } } }, { type: 'component', opts: { uid: 'text_sprite', component: { fn: state => state, select_systems: [], select_components: ['position', 'text'], subscriptions: [], cleanup_fn: () => {} } } }, { type: 'component', opts: { uid: 'movement', component: { fn: state => state, select_systems: [], select_components: [], subscriptions: ['move_change', 'collision'], cleanup_fn: () => {} } } }, ];
system周りのコード
import { audio, collision, event, input, meta, renderer, replay, tiles } from 'engine_systems'; export const system_state = [ { type: 'system', opts: { uid: 'events', fn: event.system } }, { type: 'system', opts: { uid: 'key_input', fn: input.system } }, { type: 'system', opts: { uid: 'meta', fn: meta.system } }, { type: 'system', opts: { uid: 'tiles', fn: tiles.system } }, { type: 'system', opts: { uid: 'render', fn: renderer.system } }, { type: 'system', opts: { uid: 'audio', fn: audio.system } } ];
game loop
で回してごにょごにょするとそれっぽい動きをしてくれます。
プロジェクトをつくる
2018年12月6日現在
. ├── LICENSE ├── README.md ├── package.json ├── public │ ├── bundle.js │ ├── img │ │ └── icon.png │ └── index.html ├── src │ ├── engine │ │ ├── components │ │ │ ├── animate.js │ │ │ ├── attack.js │ │ │ ├── controller.js │ │ │ ├── damage.js │ │ │ ├── ephemeral.js │ │ │ ├── index.js │ │ │ ├── moveable.js │ │ │ ├── position.js │ │ │ ├── renderable.js │ │ │ └── text.js │ │ ├── core │ │ │ ├── core.js │ │ │ ├── ecs │ │ │ │ ├── get.js │ │ │ │ ├── index.js │ │ │ │ └── make.js │ │ │ ├── events.js │ │ │ └── index.js │ │ ├── systems │ │ │ ├── audio.js │ │ │ ├── collision.js │ │ │ ├── event.js │ │ │ ├── index.js │ │ │ ├── input.js │ │ │ ├── meta.js │ │ │ ├── renderer.js │ │ │ ├── replay.js │ │ │ └── tiles.js │ │ └── utils │ │ ├── index.js │ │ ├── pixi.js │ │ └── stats.js │ ├── entities │ │ ├── index.js │ │ └── player.js │ ├── game │ │ ├── component.js │ │ ├── entity.js │ │ ├── index.js │ │ ├── renderer.js │ │ ├── scene.js │ │ ├── system.js │ │ └── tilemap.js │ ├── main.js │ └── manifest.json └── webpack.config.js
Webpack
でjavascriptをbundleしてpublicに吐きだし、 webpack-serve
でサーバーを立ち上げています。
今回はここまで
読んだことも書いたこともないClojureScript
を解読するの、技術的体力がつきますね。ClojureDocs 死ぬほど読みやすいので他の言語も参考にしてほしいです。
UUUMでエンジニアをするとヒルズから見える絶景を堪能できます!
仕事でゲームエンジンは開発しないけどね
詳しくはこちら →→→→→→ UUUM攻殻機動隊の紹介
コメント
コメントを投稿