Animate turns by showing the cards movements
This commit is contained in:
parent
2a9b162324
commit
6b26ce72a1
5 changed files with 202 additions and 94 deletions
31
www/dom.js
31
www/dom.js
|
@ -1,31 +0,0 @@
|
||||||
function Dom() {
|
|
||||||
return {
|
|
||||||
clear: clear,
|
|
||||||
make: make
|
|
||||||
}
|
|
||||||
|
|
||||||
function clear(elem) {
|
|
||||||
while(elem.firstChild) {
|
|
||||||
elem.removeChild(elem.firstChild);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function make(tag, properties) {
|
|
||||||
var e = document.createElement(tag);
|
|
||||||
for(key in properties) {
|
|
||||||
var value = properties[key];
|
|
||||||
switch(key) {
|
|
||||||
case "class":
|
|
||||||
e.className = Array.isArray(value) ? value.join(' ') : value;
|
|
||||||
break;;
|
|
||||||
case "onClick":
|
|
||||||
e.addEventListener("click", value);
|
|
||||||
break;;
|
|
||||||
default:
|
|
||||||
e[key] = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return e;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
11
www/game.css
11
www/game.css
|
@ -96,6 +96,17 @@
|
||||||
background-position-y: 91.7%;
|
background-position-y: 91.7%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#game .card.slot {
|
||||||
|
background: none;
|
||||||
|
border: 1px solid transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
#game .card.moving {
|
||||||
|
position: relative;
|
||||||
|
transition-property: left, top;
|
||||||
|
transition-duration: 1s;
|
||||||
|
}
|
||||||
|
|
||||||
#game #rest {
|
#game #rest {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
248
www/game.js
248
www/game.js
|
@ -7,58 +7,181 @@ function Game(modules) {
|
||||||
step: null,
|
step: null,
|
||||||
month: null
|
month: null
|
||||||
};
|
};
|
||||||
var sets = {
|
var sets = buildSets();
|
||||||
river: {
|
|
||||||
card: null,
|
|
||||||
dom: document.getElementById("river")
|
|
||||||
},
|
|
||||||
yourHand: {
|
|
||||||
card: null,
|
|
||||||
dom: document.getElementById("you").getElementsByClassName("hand")[0]
|
|
||||||
},
|
|
||||||
theirHand: {
|
|
||||||
dom: document.getElementById("them").getElementsByClassName("hand")[0]
|
|
||||||
}
|
|
||||||
};
|
|
||||||
var selected = null;
|
var selected = null;
|
||||||
|
var queue = [];
|
||||||
|
|
||||||
|
window.addEventListener('focus', runQueue);
|
||||||
modules.messaging.addEventListener(["Game"], function(o) {
|
modules.messaging.addEventListener(["Game"], function(o) {
|
||||||
setStatus(o.game);
|
if(document.hasFocus()) {
|
||||||
setCaptures(o.game);
|
modules.async.run(handleGameMessage(o));
|
||||||
[
|
} else {
|
||||||
['river', o.game.river, RiverCard],
|
queue.push(handleGameMessage(o));
|
||||||
['yourHand', o.game.players[modules.session.getKey()].hand, HandCard]
|
}
|
||||||
].forEach(function(args) {setCardSet.apply(null, args)});
|
});
|
||||||
setTheirCards(o.game);
|
|
||||||
if(status.step == "Turned") {
|
function buildSets() {
|
||||||
setTurned(o.game.step.contents);
|
var sets = {};
|
||||||
} else {
|
['river', 'you', 'them'].forEach(function(id) {
|
||||||
if(status.step == "ToPlay" && o.game.playing == o.game.oyake) {
|
var dom = document.getElementById(id);
|
||||||
rest.className = ["card", "count" + o.game.deck].join(' ');
|
if(dom.tagName.toLowerCase() == 'ul') {
|
||||||
}
|
sets[id] = {card: null, dom: dom};
|
||||||
if(deck.lastChild.id != "rest") {
|
|
||||||
deck.removeChild(deck.lastChild);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(status.step == "Scored") {
|
|
||||||
if(status.playing) {
|
|
||||||
modules.screen.dialog({
|
|
||||||
text: modules.i18n.get('youScored'),
|
|
||||||
answers: [
|
|
||||||
{label: 'endRound', action: function() {play({koiKoi: false})}},
|
|
||||||
{label: 'koikoi', action: function() {play({koiKoi: true});}}
|
|
||||||
]
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
modules.screen.dialog({
|
sets[id] = {};
|
||||||
text: modules.i18n.get('theyScored')(modules.room.name(o.game.playing)),
|
for(var i = 0; i < dom.children.length; i++) {
|
||||||
answers: [
|
if(dom.children[i].tagName.toLowerCase() == 'ul') {
|
||||||
{label: 'ok', action: function() {}}
|
sets[id][dom.children[i].className] = {card: {}, dom: dom.children[i]};
|
||||||
]
|
}
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
return sets;
|
||||||
|
}
|
||||||
|
|
||||||
|
function runQueue() {
|
||||||
|
if(queue.length > 0) {
|
||||||
|
modules.async.run.apply(null, queue.concat(
|
||||||
|
modules.async.apply(function() {queue = [];})
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleGameMessage(o) {
|
||||||
|
if(o.game.deck == 24) {
|
||||||
|
return o.logs.length > 0 ? modules.async.sequence(applyDiff(o), setGame(o)) : setGame(o);
|
||||||
|
} else {
|
||||||
|
return applyDiff(o);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function setGame(o) {
|
||||||
|
return function(f) {
|
||||||
|
setStatus(o.game);
|
||||||
|
setCaptures(o.game);
|
||||||
|
[
|
||||||
|
[sets.river, o.game.river, RiverCard],
|
||||||
|
[sets.you.hand, o.game.players[modules.session.getKey()].hand, HandCard]
|
||||||
|
].forEach(function(args) {setCardSet.apply(null, args)});
|
||||||
|
setTheirCards(o.game);
|
||||||
|
handleStep(o)(f);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleStep(o) {
|
||||||
|
return function(f) {
|
||||||
|
if(status.step == "Turned") {
|
||||||
|
setTurned(o.game.step.contents);
|
||||||
|
} else {
|
||||||
|
if(status.step == "ToPlay" && o.game.playing == o.game.oyake) {
|
||||||
|
rest.className = ["card", "count" + o.game.deck].join(' ');
|
||||||
|
}
|
||||||
|
if(deck.lastChild.id != "rest") {
|
||||||
|
deck.removeChild(deck.lastChild);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(status.step == "Scored") {
|
||||||
|
if(status.playing) {
|
||||||
|
modules.screen.dialog({
|
||||||
|
text: modules.i18n.get('youScored'),
|
||||||
|
answers: [
|
||||||
|
{label: 'endRound', action: function() {play({koiKoi: false}); f();}},
|
||||||
|
{label: 'koikoi', action: function() {play({koiKoi: true}); f();}}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
modules.screen.dialog({
|
||||||
|
text: modules.i18n.get('theyScored')(modules.room.name(o.game.playing)),
|
||||||
|
answers: [
|
||||||
|
{label: 'ok', action: f}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
f();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function applyDiff(o) {
|
||||||
|
return modules.async.sequence.apply(null,
|
||||||
|
o.logs.map(animate).concat(
|
||||||
|
modules.async.apply(setStatus, o.game),
|
||||||
|
handleStep(o)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function animate(movement) {
|
||||||
|
return modules.async.bind(
|
||||||
|
modules.async.apply(function() {
|
||||||
|
var card;
|
||||||
|
var movingCards = [];
|
||||||
|
var side = (status.playing) ? 'you' : 'them';
|
||||||
|
var dest = sets.river;
|
||||||
|
if(movement.captures != undefined) {
|
||||||
|
card = new Card(movement.played);
|
||||||
|
dest = sets[side];
|
||||||
|
movingCards.push([sets.river, dest, new Card(movement.captures)]);
|
||||||
|
} else {
|
||||||
|
card = new RiverCard(movement.played);
|
||||||
|
}
|
||||||
|
if(movement.source == 'Hand') {
|
||||||
|
movingCards.push([sets[side].hand, dest, card]);
|
||||||
|
} else {
|
||||||
|
var cardSet = {};
|
||||||
|
cardSet[card.name] = turnedCard(card.name);
|
||||||
|
movingCards.push([{card: cardSet, dom: deck}, dest, card]);
|
||||||
|
}
|
||||||
|
return movingCards;
|
||||||
|
}),
|
||||||
|
function(movingCards) {
|
||||||
|
return modules.async.parallel.apply(null,
|
||||||
|
movingCards.map(function(args) { return moveCard.apply(null, args); })
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function moveCard(fromSet, toSet, card) {
|
||||||
|
var from, originalCard;
|
||||||
|
var slot = modules.dom.make('li', {class: ['card', 'slot']});
|
||||||
|
if (fromSet.card[card.name] != undefined) {
|
||||||
|
originalCard = fromSet.card[card.name].dom;
|
||||||
|
delete fromSet.card[card.name];
|
||||||
|
} else {
|
||||||
|
var originalCard = fromSet.dom.children[fromSet.dom.children.length - 1];
|
||||||
}
|
}
|
||||||
});
|
from = originalCard.getBoundingClientRect();
|
||||||
|
fromSet.dom.replaceChild(slot, originalCard);
|
||||||
|
card.dom.style.visibility = 'hidden';
|
||||||
|
insertCard(toSet, card);
|
||||||
|
var to = card.dom.getBoundingClientRect();
|
||||||
|
card.dom.style.left = (from.left - to.left) + 'px';
|
||||||
|
card.dom.style.top = (from.top - to.top) + 'px';
|
||||||
|
card.dom.classList.add('moving');
|
||||||
|
card.dom.style.visibility = null;
|
||||||
|
return modules.async.sequence(
|
||||||
|
modules.async.wait(10),
|
||||||
|
modules.async.apply(function() {
|
||||||
|
card.dom.style.left = 0;
|
||||||
|
card.dom.style.top = 0;
|
||||||
|
}),
|
||||||
|
modules.async.wait(1000),
|
||||||
|
modules.async.apply(function() {
|
||||||
|
fromSet.dom.removeChild(slot);
|
||||||
|
card.dom.classList.remove('moving');
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function insertCard(toSet, card) {
|
||||||
|
if(toSet.dom != undefined) {
|
||||||
|
toSet.card[card.name] = card;
|
||||||
|
toSet.dom.appendChild(card.dom);
|
||||||
|
} else {
|
||||||
|
insertCard(toSet[card.value.family.class], card);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function play(move) {
|
function play(move) {
|
||||||
modules.messaging.send({
|
modules.messaging.send({
|
||||||
|
@ -86,10 +209,10 @@ function Game(modules) {
|
||||||
var turn = null;
|
var turn = null;
|
||||||
status.playing = modules.session.is(game.playing);
|
status.playing = modules.session.is(game.playing);
|
||||||
if(status.playing) {
|
if(status.playing) {
|
||||||
sets.yourHand.dom.classList.toggle("yourTurn", status.step == "ToPlay");
|
sets.you.hand.dom.classList.toggle("yourTurn", status.step == "ToPlay");
|
||||||
turn = modules.i18n.get("yourTurn");
|
turn = modules.i18n.get("yourTurn");
|
||||||
} else {
|
} else {
|
||||||
sets.yourHand.dom.classList.remove("yourTurn");
|
sets.you.hand.dom.classList.remove("yourTurn");
|
||||||
turn = modules.i18n.get('playing')(modules.room.name(game.playing));
|
turn = modules.i18n.get('playing')(modules.room.name(game.playing));
|
||||||
}
|
}
|
||||||
status.dom.appendChild(modules.dom.make('li', {textContent: turn}));
|
status.dom.appendChild(modules.dom.make('li', {textContent: turn}));
|
||||||
|
@ -111,9 +234,8 @@ function Game(modules) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function setCardSet(setName, cardNames, constructor) {
|
function setCardSet(set, cardNames, constructor) {
|
||||||
constructor = constructor || Card;
|
constructor = constructor || Card;
|
||||||
var set = sets[setName];
|
|
||||||
set.card = {};
|
set.card = {};
|
||||||
modules.dom.clear(set.dom);
|
modules.dom.clear(set.dom);
|
||||||
cardNames.forEach(function(cardName) {
|
cardNames.forEach(function(cardName) {
|
||||||
|
@ -127,16 +249,21 @@ function Game(modules) {
|
||||||
var turnsTheyPlayed = Math.floor(
|
var turnsTheyPlayed = Math.floor(
|
||||||
(24 - game.deck + (modules.session.is(game.oyake) ? 0 : 1)) / 2
|
(24 - game.deck + (modules.session.is(game.oyake) ? 0 : 1)) / 2
|
||||||
);
|
);
|
||||||
modules.dom.clear(sets.theirHand.dom);
|
modules.dom.clear(sets.them.hand.dom);
|
||||||
for(var i = 0; i < 8 - turnsTheyPlayed; i++) {
|
for(var i = 0; i < 8 - turnsTheyPlayed; i++) {
|
||||||
sets.theirHand.dom.appendChild(modules.dom.make('li', {class: "card"}));
|
sets.them.hand.dom.appendChild(modules.dom.make('li', {class: "card"}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function setTurned(cardName) {
|
function turnedCard(cardName) {
|
||||||
var card = new Card(cardName);
|
var card = new Card(cardName);
|
||||||
card.dom.id = "turned";
|
card.dom.id = "turned";
|
||||||
deck.appendChild(card.dom);
|
deck.appendChild(card.dom);
|
||||||
|
return card;
|
||||||
|
}
|
||||||
|
|
||||||
|
function setTurned(cardName) {
|
||||||
|
turnedCard(cardName);
|
||||||
if(status.playing) {
|
if(status.playing) {
|
||||||
selected = cardName;
|
selected = cardName;
|
||||||
showCandidates(modules.hanafuda.Card[selected], true);
|
showCandidates(modules.hanafuda.Card[selected], true);
|
||||||
|
@ -173,6 +300,7 @@ function Game(modules) {
|
||||||
if(card.candidate) {
|
if(card.candidate) {
|
||||||
var withCard = selected;
|
var withCard = selected;
|
||||||
selected = null;
|
selected = null;
|
||||||
|
showCandidates(card.value, false);
|
||||||
play(
|
play(
|
||||||
status.step == 'ToPlay' ? {capture: [withCard, card.name]} : {choose: card.name}
|
status.step == 'ToPlay' ? {capture: [withCard, card.name]} : {choose: card.name}
|
||||||
);
|
);
|
||||||
|
@ -190,18 +318,16 @@ function Game(modules) {
|
||||||
}
|
}
|
||||||
|
|
||||||
HandCard.prototype.onClick = function() {
|
HandCard.prototype.onClick = function() {
|
||||||
if(status.playing && status.step == "ToPlay") {
|
var card = this;
|
||||||
var card = this;
|
return function() {
|
||||||
return function() {
|
if(status.playing && status.step == "ToPlay") {
|
||||||
if(selected != undefined) {
|
if(selected != undefined) {
|
||||||
sets.yourHand.card[selected].setSelected(false);
|
sets.you.hand.card[selected].setSelected(false);
|
||||||
} else {
|
} else {
|
||||||
card.play();
|
card.play();
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
} else {
|
};
|
||||||
return function() {};
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
HandCard.prototype.setSelected = function(yes) {
|
HandCard.prototype.setSelected = function(yes) {
|
||||||
|
|
|
@ -3,7 +3,8 @@
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<title>KoiKoi</title>
|
<title>KoiKoi</title>
|
||||||
<script src="dom.js"></script>
|
<script src="UnitJS/async.js"></script>
|
||||||
|
<script src="UnitJS/dom.js"></script>
|
||||||
<script src="translations.js"></script>
|
<script src="translations.js"></script>
|
||||||
<script src="i18n.js"></script>
|
<script src="i18n.js"></script>
|
||||||
<script src="fun.js"></script>
|
<script src="fun.js"></script>
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
window.addEventListener('load', function() {
|
window.addEventListener('load', function() {
|
||||||
var dom = Dom();
|
var dom = Dom();
|
||||||
|
var async = Async();
|
||||||
var translations = Translations();
|
var translations = Translations();
|
||||||
var i18n = I18n({translations: translations});
|
var i18n = I18n({translations: translations});
|
||||||
var fun = Fun();
|
var fun = Fun();
|
||||||
|
@ -9,7 +10,7 @@ window.addEventListener('load', function() {
|
||||||
var room = Room({dom: dom, messaging: messaging, session: session, fun: fun});
|
var room = Room({dom: dom, messaging: messaging, session: session, fun: fun});
|
||||||
var login = Login({dom: dom, i18n: i18n, messaging: messaging, room: room, screen: screen, session: session});
|
var login = Login({dom: dom, i18n: i18n, messaging: messaging, room: room, screen: screen, session: session});
|
||||||
var hanafuda = Hanafuda({fun: fun});
|
var hanafuda = Hanafuda({fun: fun});
|
||||||
var game = Game({dom: dom, i18n: i18n, fun: fun, hanafuda: hanafuda, messaging: messaging, room: room, screen: screen, session: session});
|
var game = Game({async: async, dom: dom, i18n: i18n, fun: fun, hanafuda: hanafuda, messaging: messaging, room: room, screen: screen, session: session});
|
||||||
|
|
||||||
var domElems = {
|
var domElems = {
|
||||||
join: document.getElementById('login').join,
|
join: document.getElementById('login').join,
|
||||||
|
|
Loading…
Reference in a new issue