This is the slide shown at Ember.js Tokyo event.
http://emberjs.doorkeeper.jp/events/14856
(Japanese Version: http://www.slideshare.net/yukishimada1/emberjs-event-tokyo-ja-20140922 )
1. An example of game developing
with Ember.js and WebGL
Yuki Shimada
2014/09/22
2. About me
• I majored in Computer Graphics at Toho
University, Chiba prefecture.
• I have developed a Game Engine for PS3 at a
venture company established in the University of
Tokyo.
• Then, I have transfered to Sopia Inc. (now
Accenture Inc.), as a system engineer.
• I have also worked to develop a renderer and
WebGL Web sites at a VFX studio.
• Currently, I’m a freelancer (Web & CG).
3. Demonstration
• Game Player
http://youtu.be/0iRTk_2Wjp8
• Map Editor
http://youtu.be/u6F3wGJpnUo
4. My Game Web Service
• The web service that makes easily able to develop RPG and share it on the
web.
• The RPG developers is divided into basic developers and advanced
developers.
• The advanced developers can develop RPG from the stage of game
system.
– You can write game code using TypeScript.
– (I hope to support visual programming via node connecting in the future).
– You can customize UI design using SCSS.
• The basic developers can cherry-pick one from game systems developed
by advanced developers, then within the framework of the game system,
they can easily create RPG with mouse operation only.
5. The structure of this web service
• This web service consists of two parts; game player
and production tools.
• These are constructed on Ruby on Rails.
– View and controller of Rails are rarely used.
– Ember.js controls all of the system, and Rails provide only model data.
– To describe the view, I used Emblem.
http://emblemjs.com
– To transfer model data from Rails to Ember, I used Ember Data and
ActiveModel::Serializers.
– This sample made by @ursm was very helpful in usage of Ember Data
and ActiveModel::Serializers.
http://ursm.jp/blog/2013/12/03/ember-js-and-rails/
6. Languages
• This system was wrote in CoffeeScript for production
tools, and TypeScript for game player.
• Ember.js is manipulated from Both
CoffeeScript(production tools) and TypeScript(game
player) .
• The definition of Router is wrote in CoffeeScript.
7. Using of Ember.js
• UI handling
• Data transfer of Rails Model -> Ember Data
• Data transfer of Ember Data -> WebGL
• Ember.js Observer and WebGL
• Computation of Game character’s parameters
9. UI Handling
• UI consists of HTML(Emblem) and CSS(SCSS).
– Creators can customize the look & feel of UI using SCSS.
• The UI is controlled by Two-stage structure model;
‘uiScreen’ and ‘uiTable’.
• The Screens(‘uiScreen’s) correspond to the Template
of Ember.
• Screen switching is performed by switching
templates via Ember,js.
• Switching between display and non-display of the
tables(‘uiTable’s) under the screen is performed by
jQuery.
12. Between Rails and Ember Data
The data that are complex and frequently modified are hold in the column in the Rails model as JSON text.
Using the Transform feature of Ember Data, transforming it to real JSON by eval in JavaScript, finally we obtain
Ember objects.
Definition of Ember Data Model A fixture of Rails Model (Factory Girl)
trait :as_2 do
id 2
ui_screen_id 1
screenIdentifier 'battle'
tableIdentifier 'character_0'
tableName '0:'
tableName_binding
'Tool.EScenarioCharacter.0.name'
selectable false
trs "[" +
"{"+
"'columns':[" +
"{" +
"'item':'HP:'," +
"'binding': 'Tool.EScenarioCharacter.0.hp'" +
"}" +
"]" +
"}," +
"{"+
"'columns':[" +
"{" +
"'item':'MP:'," +
"'binding': 'Tool.EScenarioCharacter.0.mp'" +
"}" +
"]" +
"}" +
"]"
end
var uiTableDefinition = {
screenIdentifier: DS.attr('string'),
tableIdentifier: DS.attr('string'),
tableName: DS.attr('string’),
tableName_binding: DS.attr('string'),
selectable: DS.attr('boolean'),
trs: DS.attr('uiTableTrs'),
…
};
Transform of Ember Data Model
window.Tool.UiTableTrsTransform =
DS.Transform.extend(
{
deserialize: function(value:any) {
var json:any = null;
eval("json = " + value);
return Ember.create(json);
}
});
13. Question : How can we get one–to-many relationships of
Ember Data Models from Rails Models?
• There exists a partially different part in data expression of ‘one to many’ in Rails and Ember
Data.
• In Rails, if the child model has reference to the parent model, you can get the list of child
models from the parent model.
• In Ember Data, the parent model must expressly have the id array of the child models.
• From the above difference, conversion process is needed.
App.Post = DS.Model.extend({
comments: DS.hasMany('comment', {async: true})
});
{
"post": {
"comments": [1, 2, 3]
}
}
App.Comment = DS.Model.extend({
post: DS.belongsTo('post')
});
{
"comment": {
"post": 1
}
}
class Post < ActiveRecord::Base
has_many :comments
end
create_table ”posts", force: true do |t|
end
class Comment < ActiveRecord::Base
belongs_to :post
end
create_table ”comments", force: true do |t|
t.integer "ui_screen_id”
end
14. Question : How can we get one–to-many relationships of
Ember Data Models from Rails Models?
Ember Data Rails Model
var uiScreenDefinition = {
var uiTableDefinition = {
screenIdentifier: DS.attr('string'),
tableIdentifier: DS.attr('string'),
tableName: DS.attr('string’),
tableName_binding: DS.attr('string'),
selectable: DS.attr('boolean'),
trs: DS.attr('uiTableTrs'),
…
};
identifier: DS.attr('string'),
config: DS.attr('uiScreenConfig'),
uiTables: DS.hasMany('ui-table')
};
Definition of
‘uiScreen’
which has
many uiTables
Definition of
‘uiTable’
which belongs
to ‘uiScreen’
create_table "ui_screens", force: true do |t|
t.string "identifier"
t.text "config"
t.text "uiTables”
end
class UiScreen < ActiveRecord::Base
has_many :ui_tables
end
create_table "ui_tables", force: true do |t|
t.integer "ui_screen_id"
t.string "screenIdentifier"
t.string "tableIdentifier"
t.string "tableName"
t.string "tableName_binding"
t.boolean "selectable"
t.text "trs”
end
class UiTable < ActiveRecord::Base
belongs_to :ui_screen
end
15. Answer: To generate has-many id array toward Ember
Data using Rails’ controller.
class Api::UiScreensController < ApplicationController
skip_before_action :verify_authenticity_token
def index
uiScreens = []
UiScreen.all.each do |uiScreen|
uiTablesStr = "["
uiScreen.ui_tables.each do |uiTable|
uiTablesStr += uiTable.id.to_s + ",“
end
uiTablesStr.chop!
uiTablesStr += "]"
uiScreen.update_attribute(:uiTables, uiTablesStr)
uiScreens.push(uiScreen)
end
jsonHash = JSON.parse(uiScreens.to_json) for item in jsonHash
item["uiTables"] = eval(item["uiTables"])
end
jsonWrapper = {}
jsonWrapper["ui_screens"] = jsonStr = jsonWrapper.to_json
jsonHash = JSON.parse(jsonStr)
render :json => jsonHash
end
Add the all ids of uiTables that belong to the
uiScreen to array character string.
Ex:”[1, 2, 5, 6, 7]”
Then, after transforming it to JSON,
output it.
{
"ui_screens": [
{
"config": "{'firstUI':'command','hiddenUIs':
['physics', 'magic', 'target', 'magic-fake'],'
calculatePosition': true}",
"created_at": "2014-09-08T02:07:53.215Z",
"id": 1,
"identifier": "battle",
"uiTables": [1, 2, 5, 6, 7]
}
]
}
17. Data transfer to WebGL
• Not using WebGL directly, I use it via Three.js.
http://threejs.org
• I also use tmlib (a cool JS game library by
@phi-jp).
http://phi-jp.github.io/tmlib.js/
• The tmlib library is integrated with three.js.
• Today, I will illustrate my method by taking
the rendering of a game map as an example.
19. Data transmission of Map Data for Map Rendering
Tool.PlayIndexRoute = Ember.Route.extend
model: ->
@modelFor('play')
afterModel: (model, transition)->
window.WrtGS.main(model)
function systemMain(err:any, args:any){
window.WrtGS = new
system.System(args);
}
module system {
export class System {
public main(model:any) {
this.map = new map.Map(model.map.get(‘type_array’),
model.map.get(‘height_array’),
model.texture.get(‘gametex_url’));
trait :as_2 do
id 2
name 'デバッグテスト'
width 5
height 5
type_array "1 N,1 W,1 N,1 W,1 Wn" +
"1 N,1 W,1 N,1 W,1 Wn" +
"1 N,1 N,1 N,1 N,1 Nn" +
"1 W,1 W,1 N,1 W,1 Wn" +
"1 W,1 W,1 N,1 W,1 Wn"
height_array "0 1,0 1,0 1,0 1,0 1n" +
"0 1,0 1,0 1,0 1,0 1n" +
"0 1,0 1,0 1,0 1,0 1n" +
"0 1,0 1,0 1,0 1,0 1n" +
"0 1,0 1,0 1,0 1,0 1n"
end
trait :as_1 do
id 1
name 'メタル'
gametex_url ‘metal.jpg’
20. Since the data is mere text data, the subsequent processes is
just to analyze the original text format of map,
create the geometry of Three.js, and assign texture images to Meshes.
// 1頂点目
geom.vertices.push( new THREE.Vector3(x-1, this.maxCeilingHeight, y) );
// 2頂点目
geom.vertices.push( new THREE.Vector3(x-1, ceilingHeight, y) );
// 3頂点目
geom.vertices.push( new THREE.Vector3(x-1, ceilingHeight, y-1) );
// 4頂点目
geom.vertices.push( new THREE.Vector3(x-1, this.maxCeilingHeight, y-1) );
// 表三角形の1個目
var face1 = new THREE.Face3( verticesStride+0, verticesStride+1, verticesStride+2 );
face1.normal = new THREE.Vector3(1, 0, 0);
geom.faces.push( face1 );
geom.faceVertexUvs[ 0 ].push( [
new THREE.Vector2( 0.75, 0 ),
new THREE.Vector2( 0.75, this.texcoordOne * (this.maxCeilingHeight - ceilingHeight) ),
new THREE.Vector2( 1, this.texcoordOne * (this.maxCeilingHeight - ceilingHeight) ) ] );
21. Transmission of Map Data for Map Rendering
In the data transmission from Ember.js to WebGL (Three.js),
I don’t do anything special.
I just extract strings from the data fulfilled in Ember model,
analyze them, and transfer them to the function for geometry
construction of Three.js.
22. Ember.js Observer and WebGL
• When an enemy is damaged, the enemy figure
is vibrated. For this process, I used the
Observer of Ember.js.
• Since the status value of a friend and foe is
supervised as an Ember object, when their
HPs decrease, the coordinate values of foe
polygon of three.js are vibrated by activating
the Observer.
23. Computation of
parameters of Game
character’s
In RPG, there exists many cases
where a parameter is calculated
from the other parameters.
→By applying computed Properties,
I solved the problem.
In the present production tools, we
can freely create all kind of
parameters of characters, and also
can describe a mathematical
relationship between the character’s
parameters freely.
24. Affinity between Ember.js and web games
• Optimal for display and update of UI
– Since the first version was processed using jQuery only, the development was
a hellish battle. Now, due to Ember.js the process becomes quite simple.
– The Ember.js is suitable for RPG with large number of UI. Why not use that
power?
• Two-way binding is useful
– In a large scale game, data synchronization between multiple points in app is
required. Ember.js take care whole synchronous processing.
• Observer is also useful
– In a game UI, the usage of not only text but also picture often happens. In that
case, we should use the data binding for the recalculation of inner data only,
so that we can focus on using another rendering library for animation in
observer of Ember.
• The Computed Properties play an active role In a game, such as RPG, that requires
a lot of computation between parameters.
25. Ember.js is Terrific!
• Finally, what I want to claim is,
• Ember.js supports the basis of both the portions of
game and production tools in the present Web
service.
• If Ember.js was not available, I could not obtain
effective software development and excellent
prospect of code.
Thanks! Ember.js!
26. Finally
• For the person who want to learn Ember.js
– I have posted the Japanese translation of the Ember.js
official guide on my github
page.https://github.com/emadurandal/emberjs-guides-japanese-
translation
– “Series introduction to Ember.js” at Developers.IO is also
must-see.
(Thank you Watanabe-san for your very fine article!)
http://dev.classmethod.jp/series/getting-started
%E2%80%8E-emberjs/