Když jsem poprvé slyšel o Polymeru, myslel jsem na své staré Silverlight časy. Silverlight použil XHTML pro označení a C# pro kód. Polymer je podobný, ale Polymer používá HTML a Javascript. Podívejte se na tento skvělý článek pro úvod do Polymeru. V tomto tutoriálu vytvoříme klasickou hru Sokoban, využijeme webové komponenty a vynikající generátor Yeoman, generátor-polymer a publikujeme ji pomocí Bower.
Nastavení polymeru
Nastavení projektu Polymer je stejně jednoduché jako následující dva příkazy:
$ npm install generator-polymer -g
$ yo polymer
Požádá vás o zahrnutí některých standardních součástí. Protože žádné nepotřebujeme, můžete říci všem ne.
Toto je vygenerovaná struktura složek. Všechny vlastní prvky jsou v app/elements
složka.
.
|-- Gruntfile.js
|-- app
| |-- elements
| | |-- elements.html
| | |-- soko-ban
| | | |-- soko-ban.html
| | | `-- soko-ban.scss
| |-- index.html
| |-- scripts
| | |-- app.js
|-- bower.json
`-- package.json
Chcete-li zahájit vývoj, spusťte grunt serve
. Bude sloužit index.html
a sledujte, jak se soubory v reálném čase znovu načítají, jak se mění. Toto je index.html
, zahrnul jsem pouze základní části pro použití polymeru.
<html>
<head>
<script src="bower_components/platform/platform.js"></script>
<!-- build:vulcanized elements/elements.vulcanized.html -->
<link rel="import" href="elements/elements.html">
<!-- endbuild -->
</head>
<body unresolved>
<div class="game-container">
<!-- insert your elements here -->
<soko-ban></soko-ban>
</div>
<script src="scripts/app.js"></script>
</body>
</html>
Zahrnujeme platform.js
aktivovat Polymer a importovat elements.html
který dále importuje všechny naše prvky. Všimněte si, že je zabaleno do build:vulcanized
build block, který spojí všechny naše importované prvky do jednoho souboru. Nakonec v body
přidáváme naše vlastní polymerové prvky. Zahrnul jsem poslední prvek, který budeme stavět, sokoban-ban
, můžete jej nahradit jinými dílčími prvky a otestovat je při vytváření.
Vlastní prvek:sprite-el
První vlastní prvek, který postavíme, je prvek sprite, který poslouží jako základ pro všechny sprity, jako jsou boxy a náš přehrávač. Chcete-li přidat vlastní prvek, spusťte jediný příkaz.
$ yo polymer:el sprite-el
Tím se vytvoří elements/sprite-el
podsložku a přidejte dva soubory, sprite-el.html
a sprite-el.scss
. Vloží také sprite-el.html
v elements.html
, v podstatě to dělá za vás.
Viz sprite-el.html
vloženo do elements.html
od Yeoman.
File: elements/elements.html
<link rel="import" href="sprite-el/sprite-el.html">
Prohlášení prvku
Pojďme definovat náš vlastní prvek sprite-el
.
<link rel="import" href="../../bower_components/polymer/polymer.html">
<polymer-element name="sprite-el">
<template>
<link rel="stylesheet" href="sprite-el.css">
<div class="sprite" style="top: {{posY}}px; left: {{posX}}px; height: {{frame.height}}px; width: {{frame.width}}px; background: url({{spriteUrl}}) {{frame.x}}px {{frame.y}}px">
</div>
</template>
<script>
(function () {
'use strict';
Polymer({
publish: {
spriteUrl: 'images/sprites.png',
frame: {
x: 0,
y: 0
},
position: {
x: 0,
y: 0
},
computed: {
posX: 'position.x * 64',
posY: 'position.y * 64'
}
}
});
})();
</script>
</polymer-element>
Nejprve zahrneme polymer.html
a otevřete polymer-element
tag s sprite-el
atribut name, který je povinný a musí obsahovat -
. Dále máme dvě dílčí značky, template
a script
. template
obsahuje označení pro náš vlastní prvek. V rámci script
nazýváme Polymer
funkce pro spuštění vlastního prvku. Další informace naleznete v dokumentaci.
Šablona prvku
V šabloně zahrneme styl sprite-el.css
který je zkompilován Gruntem z sprite-el.scss
.
Dále máme div
s sprite
třída a style
atribut. style
atribut definuje top
, left
, height
, width
a background
, styl, který určuje polohu a hranice skřítka a jeho obrazu. Tyto styly zařazujeme do textu, protože pro tyto atributy stylu musíme použít datovou vazbu.
Vazba dat, publikované a vypočítané vlastnosti
Vlastnosti prvku lze svázat přímo s pohledem pomocí výrazů Polymer, jako je {{posY}}
, {{frame.height}}
, {{spriteUrl}}
.
posX
a posY
jsou definovány pod computed
vlastnost, což znamená, že se jedná o vypočítané vlastnosti. Jsou to dynamické vlastnosti, které se počítají na základě jiných hodnot vlastností. V našem případě závisí na position.x
a position.y
takže kdykoli position
změny vlastností jsou přepočítány a aktualizovány také v pohledu.
spriteUrl
a frame
jsou zveřejněné vlastnosti. To znamená, že tuto vlastnost činíte součástí „veřejného rozhraní API“ prvku. Uživatelé prvku je tedy mohou měnit. Publikované vlastnosti jsou také vázány na data a jsou přístupné pomocí {{}}
.
Vlastní prvek:box-el
Dalším vlastním prvkem je prvek box, který se bude skládat z našeho sprite-el
a bude představovat krabice, stěny a zem. Pojďme obtěžovat Yeomana ještě jednou.
$ yo polymer:el box-el
Game Art a Sprite Frames
Veškeré herní umění je převzato z 1001.com a je licencováno CC-BY-SA 4.0. Všechny sprity a úplný zdrojový kód najdete na GitHubu.
Máme pět snímků sprite – B
pro krabice BD
pro tmavé rámečky T
pro cíl W
pro stěny a G
pro zem. Ve skutečnosti je lepší definovat pohyblivé rámečky a sprity na pozadí v samostatných vrstvách, ale pro jednoduchost je všechny zahrneme do jednoho prvku. Každý snímek definuje polohu snímku v listu sprite a také jeho výšku a šířku.
Pojďme definovat náš vlastní prvek box-el
:
<polymer-element name="box-el">
<template>
<link rel="stylesheet" href="box-el.css">
<sprite-el frame="{{frame}}" position="{{model.position}}" style="height: {{frame.height}}px; width: {{frame.width}}px;"></sprite-el>
</template>
<script>
(function () {
'use strict';
Polymer({
publish: {
model: {
position: {
x: 0,
y: 0
},
type: 'W'
}
},
computed: {
frame: 'boxCoords[model.type]'
},
ready: function() {
this.boxCoords = {
"B": { x:"-192", y:"0", width:"64", height:"64" },
"BD": { x:"-128", y:"-256", width:"64", height:"64" },
"T": { x:"-64", y:"-384", width:"32", height:"32" },
"W": { x:"0", y:"-320", width:"64", height:"64" },
"G": { x:"-64", y:"-256", width:"64", height:"64" }
};
}
});
})();
</script>
</polymer-element>
Dědičnost a složení
Krabice a prvky hráče budou používat základní prvek sprite. Existují dva způsoby, jak toho dosáhnout, pomocí dědičnosti nebo složení. Nebudeme prodlužovat sprite-el
, ale raději použijte kompozici. Další informace o dědictví naleznete v tomto příspěvku na blogu a v této referenci.
Zahrnujeme sprite-el
v naší šabloně a přiřaďte jí atributy. Pamatujte na publikované vlastnosti frame
a position
? Zde je přiřadíme pomocí atributů.
Metody životního cyklu
Jedna vlastnost navíc box-el
má jiné než publikované a vypočítané vlastnosti je ready
metoda životního cyklu. ready
metoda životního cyklu se volá, když je prvek plně připraven, v tomto zpětném volání můžeme přiřadit další vlastnosti, v našem případě je to boxCoords
který používá frame
vypočítaná vlastnost.
Vlastní prvek:sokoban-el
Naším posledním vlastním prvkem je samotná hra Sokoban. To se bude skládat z našeho player-el
a krabicové, stěnové a pozemní prvky.
Herní model, herní ovladač a správce vstupu
Veškerá logika hry je uvnitř GameController
typ. Generuje herní mapu a přímo manipuluje s herním modelem. Herním modelem jsou data vázaná na náš pohled, tedy polymerní prvek. Takže všechny změny v modelu provedené GameController
se v zobrazení automaticky aktualizuje. V tomto článku se nebudu rozepisovat o logice hry, další podrobnosti si můžete prohlédnout v úplném zdrojovém kódu.
Zpracování uživatelského vstupu lze provést pomocí deklarativního mapování událostí. Ale přesto existují určitá upozornění. Viz tato otázka na Stack Overflow. Použil jsem tedy vlastní typ pro zpracování vstupu, KeyboardInputManager
.
Pojďme definovat náš vlastní prvek soko-ban
:
<polymer-element name="soko-ban">
<template>
<link rel="stylesheet" href="soko-ban.css">
<template repeat="{{box in boxes}}">
<box-el model="{{box}}"></box-el>
</template>
<player-el model="{{player}}" id="character"></player-el>
</template>
<script>
(function () {
'use strict';
Polymer({
ready: function() {
var controller = new GameController();
var model = controller.getModel();
/** Sample Model **/
/**
this.player = {
position: {
x: 0,
y: 0
}
};
this.boxes = [
{
type: 'W',
position: {
x: 10,
y: 10
}
},
{
type: 'WD',
position: {
x: 10,
y: 100
}
}
];
*/
this.player = model.player;
this.boxes = model.boxes;
var inputManager = new KeyboardInputManager();
var char = this.$.character;
inputManager.on('move', function(val) {
switch (val) {
case KeyboardInputManager.Direction.UP:
controller.move(GameController.Direction.UP);
break;
case KeyboardInputManager.Direction.RIGHT:
controller.move(GameController.Direction.RIGHT);
break;
case KeyboardInputManager.Direction.DOWN:
controller.move(GameController.Direction.DOWN);
break;
case KeyboardInputManager.Direction.LEFT:
controller.move(GameController.Direction.LEFT);
break;
}
if (controller.isGameOver()) {
this.fire('finished', { target: model.target });
}
}.bind(this));
}
});
})();
</script>
</polymer-element>
Všimněte si dvou vlastností našeho polymerního prvku player
a boxes
, nastavili jsme je do našeho modelu. Pro účely testování je můžete ručně nastavit na pevně zakódované hodnoty, jak můžete vidět v komentovaném kódu.
Opakované šablony
boxes
vlastnost je pole hodnot. Pro každou položku v poli můžeme vygenerovat jednu instanci šablony. Všimněte si použití template
tag a repeat
atribut pro iteraci přes pole polí. Další informace naleznete v dokumentaci.
Spouštění vlastních událostí
Můžete také spouštět vlastní události v rámci prvku Polymer pomocí fire
metoda. V našem případě spustíme finished
událost, kdy hra skončí. Události můžete poslouchat, jak je uvedeno níže.
document.querySelector('soko-ban')
.addEventListener('finished', function(e) {
alert('Congratz you have pushed all ' +
e.detail.target + ' boxes!');
});
Publikovat
Použili jsme generator-polymer
pro vytvoření naší aplikace. K dispozici je také další generátor, prvek generátoru a šablona Polymer pro vytváření a publikování vlastních prvků. Jakmile vytvoříte svůj vlastní prvek pomocí generátoru, můžete jej publikovat pomocí Bower. Další informace o publikování naleznete v těchto vynikajících článcích zde a zde.
Nezapomeňte přidat web-component
tag na váš bower.json
. Jakmile jej publikujete Bowerovi, měl by být váš prvek dostupný v registru Bower. Nezapomeňte jej také odeslat na adresu customelements.io.
Zjistěte více a živá ukázka
V tomto tutoriálu jsme viděli Polymer v akci při stavbě Sokobanu. Obecně platí, že nemusíte vytvářet své vlastní prvky, můžete použít stávající a skládat je a vytvářet tak poutavější prvky. Navštivte galerii webových komponent na adrese customelements.io.
S Polymerem můžete udělat více, o čem jsme se nezabývali, jako jsou prvky stylů, pozorování vlastností atd. Další informace naleznete v příručce pro vývojáře API. Úplný zdrojový kód tohoto projektu najdete na GitHubu a na mém webu si můžete prohlédnout živou ukázku.