Make game display, still nothing happens when clicking on the cards in the hand
This commit is contained in:
parent
07cf48e857
commit
d3d8ca8816
13 changed files with 348 additions and 263 deletions
|
@ -7,7 +7,7 @@
|
||||||
<link rel="stylesheet" href="../skin.css" type="text/css"/>
|
<link rel="stylesheet" href="../skin.css" type="text/css"/>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="game">
|
<div id="game" class="on">
|
||||||
<div id="them">
|
<div id="them">
|
||||||
<ul class="hand"></ul>
|
<ul class="hand"></ul>
|
||||||
<ul class="kasu"></ul>
|
<ul class="kasu"></ul>
|
||||||
|
|
|
@ -1,21 +1,16 @@
|
||||||
import Hanafuda;
|
import Hanafuda;
|
||||||
import * as Dom from UnitJS.Dom;
|
import * as Dom from UnitJS.Dom;
|
||||||
|
|
||||||
function Card(name) {
|
|
||||||
var value = Hanafuda.Card[name];
|
|
||||||
var dom = Dom.make('li', {
|
|
||||||
class: [
|
|
||||||
"card",
|
|
||||||
"value" + Hanafuda.getValue(this.value),
|
|
||||||
"month" + this.value.flower
|
|
||||||
]
|
|
||||||
});
|
|
||||||
return {
|
|
||||||
value: value,
|
|
||||||
dom: dom
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
make: Card
|
make: Card
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function Card(name) {
|
||||||
|
var value = Hanafuda.Card[name];
|
||||||
|
return {
|
||||||
|
value: value,
|
||||||
|
dom: Dom.make('li', {
|
||||||
|
class: ["card", "value" + value.monthOffset, "month" + value.flower]
|
||||||
|
})
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
|
@ -1,28 +1,34 @@
|
||||||
|
import * as Card from GUI.Card;
|
||||||
|
import * as State from GUI.Screen.Game.State;
|
||||||
|
|
||||||
function HandCard() {
|
return {
|
||||||
Card.apply(this, arguments);
|
make: HandCard
|
||||||
}
|
|
||||||
|
|
||||||
HandCard.prototype.onClick = function() {
|
|
||||||
var card = this;
|
|
||||||
return function() {
|
|
||||||
if(status.playing && status.step == "ToPlay") {
|
|
||||||
if(selected != undefined) {
|
|
||||||
selected.setSelected(false);
|
|
||||||
} else {
|
|
||||||
card.play();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
HandCard.prototype.setSelected = setSelected;
|
function HandCard(name) {
|
||||||
|
var card = Card.make(name);
|
||||||
|
card.onClick = onClick;
|
||||||
|
return card;
|
||||||
|
|
||||||
HandCard.prototype.play = function() {
|
function onClick() {
|
||||||
var matching = matchingInRiver(this.value);
|
return function() {
|
||||||
if(matching.length > 1) {
|
if(State.state.playing && State.state.step == "ToPlay") {
|
||||||
this.setSelected(true);
|
if(State.getSelected() != undefined) {
|
||||||
} else {
|
State.select(false);
|
||||||
play({play: this.name});
|
} else {
|
||||||
}
|
play();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function play() {
|
||||||
|
var matching = State.matchingInRiver(card.value);
|
||||||
|
if(matching.length > 1) {
|
||||||
|
State.select(card);
|
||||||
|
} else {
|
||||||
|
State.play({play: card.name});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,9 @@
|
||||||
import * as Card from GUI.Card;
|
import * as Card from GUI.Card;
|
||||||
|
import * as State from GUI.Screen.Game.State;
|
||||||
|
|
||||||
|
return {
|
||||||
|
make: RiverCard
|
||||||
|
};
|
||||||
|
|
||||||
function RiverCard(name) {
|
function RiverCard(name) {
|
||||||
var card = Card.make(name);
|
var card = Card.make(name);
|
||||||
|
@ -10,25 +15,18 @@ function RiverCard(name) {
|
||||||
function onClick() {
|
function onClick() {
|
||||||
return function() {
|
return function() {
|
||||||
if(candidate) {
|
if(candidate) {
|
||||||
var withCard = selected.name;
|
var withCard = State.getSelected().name;
|
||||||
selected.setSelected(false);
|
State.select(false);
|
||||||
play(
|
State.play(
|
||||||
status.step == 'ToPlay' ? {capture: [withCard, card.name]} : {choose: card.name}
|
State.state.step == 'ToPlay' ?
|
||||||
|
{capture: [withCard, card.name]} : {choose: card.name}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function setCandidate() {
|
function setCandidate(yes) {
|
||||||
candidate = yes;
|
candidate = yes;
|
||||||
card.dom.classList.toggle("candidate", yes);
|
card.dom.classList.toggle("candidate", yes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RiverCard.prototype.onClick = function() {
|
|
||||||
var card = this;
|
|
||||||
};
|
|
||||||
|
|
||||||
return {
|
|
||||||
make: RiverCard
|
|
||||||
};
|
|
||||||
|
|
|
@ -1,14 +1,13 @@
|
||||||
import * as Card from GUI.Card;
|
import * as Card from GUI.Card;
|
||||||
|
import dom from GUI.Screen.Game.State;
|
||||||
function TurnedCard(name) {
|
|
||||||
var card = Card.make(name);
|
|
||||||
card.dom.id = "turned";
|
|
||||||
deck.appendChild(this.dom);
|
|
||||||
}
|
|
||||||
|
|
||||||
TurnedCard.prototype.onClick = Card.prototype.onClick;
|
|
||||||
TurnedCard.prototype.setSelected = setSelected;
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
make: TurnedCard
|
make: TurnedCard
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function TurnedCard(name) {
|
||||||
|
var card = Card.make(name);
|
||||||
|
card.dom.id = "turned";
|
||||||
|
dom.deck.appendChild(card.dom);
|
||||||
|
return card;
|
||||||
|
}
|
||||||
|
|
|
@ -1,74 +1,77 @@
|
||||||
|
import * as Card from GUI.Card;
|
||||||
|
import * as HandCard from GUI.Card.HandCard;
|
||||||
|
import * as RiverCard from GUI.Card.RiverCard;
|
||||||
|
import * as TurnedCard from GUI.Card.TurnedCard;
|
||||||
|
import * as Screen from GUI.Screen;
|
||||||
|
import {animate, catchUp, delay, getQueue} from GUI.Screen.Game.Animation;
|
||||||
|
import {dom, init as initState, select, sets, state} from GUI.Screen.Game.State;
|
||||||
import Hanafuda;
|
import Hanafuda;
|
||||||
import I18n;
|
import I18n;
|
||||||
import Messaging;
|
import Messaging;
|
||||||
import players from Room;
|
import players from Room;
|
||||||
import * as Screen from GUI.Screen;
|
import Save;
|
||||||
import Session;
|
import Session;
|
||||||
import StatusHandler;
|
import StatusHandler;
|
||||||
import * as Async from UnitJS.Async;
|
import * as Async from UnitJS.Async;
|
||||||
import * as Dom from UnitJS.Dom;
|
import * as Dom from UnitJS.Dom;
|
||||||
import * as Fun from UnitJS.Fun;
|
import * as Fun from UnitJS.Fun;
|
||||||
|
|
||||||
var deck = document.getElementById("deck");
|
|
||||||
var rest = document.getElementById("rest");
|
|
||||||
var status = {
|
|
||||||
dom: document.getElementById("status"),
|
|
||||||
game: null,
|
|
||||||
playing: false,
|
|
||||||
step: null,
|
|
||||||
month: null
|
|
||||||
};
|
|
||||||
var sets;
|
|
||||||
var selected = null;
|
|
||||||
var turnedCard = null;
|
|
||||||
var queue = [];
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
init: init
|
init: init
|
||||||
}
|
}
|
||||||
|
|
||||||
function init(state) {
|
function init(gameID) {
|
||||||
sets = buildSets();
|
initState();
|
||||||
window.addEventListener('focus', runQueue);
|
initMessageHandlers();
|
||||||
|
Async.run(
|
||||||
|
Async.bind(
|
||||||
|
getSavedState(gameID),
|
||||||
|
function(state) {
|
||||||
|
return Async.sequence(
|
||||||
|
startSession(),
|
||||||
|
setGame({tag: "Game", state: state, logs: []})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function fail(errorCode) {
|
||||||
|
return function(f) {
|
||||||
|
Screen.dialog({
|
||||||
|
text: I18n.get(errorCode),
|
||||||
|
answers: [
|
||||||
|
{label: 'backToMain', action: function() {window.location = '..';}}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getSavedState(gameID) {
|
||||||
|
var gameState = Save.get('games.state.Game#' + gameID);
|
||||||
|
return gameState != undefined ? Async.wrap(gameState) : fail('gameNotFound');
|
||||||
|
}
|
||||||
|
|
||||||
|
function startSession() {
|
||||||
|
var name = Save.get('player.name');
|
||||||
|
if(name != undefined) {
|
||||||
|
Session.start(name);
|
||||||
|
return Async.wrap();
|
||||||
|
} else {
|
||||||
|
return fail('noNameToPlay');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function initMessageHandlers() {
|
||||||
|
window.addEventListener('focus', catchUp);
|
||||||
Messaging.addEventListener(["Game"], function(o) {
|
Messaging.addEventListener(["Game"], function(o) {
|
||||||
queue.push(handleGameMessage(o));
|
delay(handleGameMessage(o));
|
||||||
if(document.hasFocus() && queue.length == 1) {
|
if(document.hasFocus() && getQueue().length == 1) {
|
||||||
runQueue();
|
catchUp();
|
||||||
} else {
|
} else {
|
||||||
StatusHandler.set("♪");
|
StatusHandler.set("♪");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
Async.run(setGame({tag: "Game", state: state, logs: []}));
|
|
||||||
}
|
|
||||||
|
|
||||||
function buildSets() {
|
|
||||||
var sets = {};
|
|
||||||
['river', 'you', 'them'].forEach(function(id) {
|
|
||||||
var dom = document.getElementById(id);
|
|
||||||
if(dom.tagName.toLowerCase() == 'ul') {
|
|
||||||
sets[id] = {card: null, dom: dom};
|
|
||||||
} else {
|
|
||||||
sets[id] = {};
|
|
||||||
for(var i = 0; i < dom.children.length; i++) {
|
|
||||||
if(dom.children[i].tagName.toLowerCase() == 'ul') {
|
|
||||||
sets[id][dom.children[i].className] = {card: {}, dom: dom.children[i]};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return sets;
|
|
||||||
}
|
|
||||||
|
|
||||||
function runQueue() {
|
|
||||||
if(queue.length > 0) {
|
|
||||||
var length = queue.length;
|
|
||||||
Async.run.apply(null, queue.concat(
|
|
||||||
Async.apply(function() {
|
|
||||||
queue = queue.slice(length);
|
|
||||||
runQueue();
|
|
||||||
})
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleGameMessage(o) {
|
function handleGameMessage(o) {
|
||||||
|
@ -88,8 +91,8 @@ function setGame(o) {
|
||||||
setStatus(o.state);
|
setStatus(o.state);
|
||||||
setCaptures(o.state);
|
setCaptures(o.state);
|
||||||
[
|
[
|
||||||
[sets.river, o.state.public.river, RiverCard],
|
[sets.river, o.state.public.river, RiverCard.make],
|
||||||
[sets.you.hand, o.state.playerHand, HandCard]
|
[sets.you.hand, o.state.playerHand, HandCard.make]
|
||||||
].forEach(function(args) {setCardSet.apply(null, args)});
|
].forEach(function(args) {setCardSet.apply(null, args)});
|
||||||
setTheirCards(o.state);
|
setTheirCards(o.state);
|
||||||
handleStep(o)(f);
|
handleStep(o)(f);
|
||||||
|
@ -99,13 +102,13 @@ function setGame(o) {
|
||||||
function handleStep(o) {
|
function handleStep(o) {
|
||||||
return function(f) {
|
return function(f) {
|
||||||
handleTurnedCard(o, f);
|
handleTurnedCard(o, f);
|
||||||
if(status.step == "Scored") {
|
if(state.step == "Scored") {
|
||||||
if(status.playing) {
|
if(state.playing) {
|
||||||
askKoikoi(o, f);
|
askKoikoi(o, f);
|
||||||
} else {
|
} else {
|
||||||
theyScored(o, f);
|
theyScored(o, f);
|
||||||
}
|
}
|
||||||
} else if (status.step == "Over") {
|
} else if (state.step == "Over") {
|
||||||
gameEnd(o, f);
|
gameEnd(o, f);
|
||||||
} else {
|
} else {
|
||||||
f();
|
f();
|
||||||
|
@ -114,10 +117,10 @@ function handleStep(o) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleTurnedCard(o, f) {
|
function handleTurnedCard(o, f) {
|
||||||
if(status.step == "Turned") {
|
if(state.step == "Turned") {
|
||||||
setTurned(o.state.public.step.contents);
|
setTurned(o.state.public.step.contents);
|
||||||
} else {
|
} else {
|
||||||
if(status.step == "ToPlay" && o.state.public.playing == o.state.public.oyake) {
|
if(state.step == "ToPlay" && o.state.public.playing == o.state.public.oyake) {
|
||||||
rest.className = ["card", "turn" + o.state.public.turns].join(' ');
|
rest.className = ["card", "turn" + o.state.public.turns].join(' ');
|
||||||
}
|
}
|
||||||
if(deck.lastChild.id != "rest") {
|
if(deck.lastChild.id != "rest") {
|
||||||
|
@ -134,7 +137,6 @@ function askKoikoi(o, f) {
|
||||||
{label: 'koikoi', action: function() {play({koiKoi: true}); f();}}
|
{label: 'koikoi', action: function() {play({koiKoi: true}); f();}}
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function theyScored(o, f) {
|
function theyScored(o, f) {
|
||||||
|
@ -176,114 +178,26 @@ function applyDiff(o) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function animate(movement) {
|
|
||||||
return Async.bind(
|
|
||||||
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 || new TurnedCard(card.name);
|
|
||||||
turnedCard = null;
|
|
||||||
movingCards.push([{card: cardSet, dom: deck}, dest, card]);
|
|
||||||
}
|
|
||||||
return movingCards;
|
|
||||||
}),
|
|
||||||
function(movingCards) {
|
|
||||||
return Async.parallel.apply(null,
|
|
||||||
movingCards.map(function(args) { return moveCard.apply(null, args); })
|
|
||||||
);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function moveCard(fromSet, toSet, card) {
|
|
||||||
var from, originalCard;
|
|
||||||
var slot = 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 Async.sequence(
|
|
||||||
Async.wait(10),
|
|
||||||
Async.apply(function() {
|
|
||||||
card.dom.style.left = 0;
|
|
||||||
card.dom.style.top = 0;
|
|
||||||
}),
|
|
||||||
Async.wait(1000),
|
|
||||||
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) {
|
|
||||||
Messaging.send({
|
|
||||||
tag: "Play",
|
|
||||||
move: move,
|
|
||||||
onGame: status.game
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function matchingInRiver(card) {
|
|
||||||
return Fun.mapFilter(
|
|
||||||
Fun.of(sets.river.card),
|
|
||||||
Fun.defined
|
|
||||||
)(Hanafuda.sameMonth(card).map(Fun.proj('name')));
|
|
||||||
}
|
|
||||||
|
|
||||||
function setStatus(game) {
|
function setStatus(game) {
|
||||||
Dom.clear(status.dom);
|
Dom.clear(dom.status);
|
||||||
status.game = game;
|
state.game = game;
|
||||||
status.step = game.public.step.tag;
|
state.step = game.public.step.tag;
|
||||||
if(game.public.month != status.month) {
|
if(game.public.month != state.month) {
|
||||||
status.month = game.public.month;
|
state.month = game.public.month;
|
||||||
}
|
}
|
||||||
status.dom.appendChild(
|
dom.status.appendChild(
|
||||||
Dom.make('li', {textContent: I18n.get('monthFlower')(I18n.get(status.month))})
|
Dom.make('li', {textContent: I18n.get('monthFlower')(I18n.get(state.month))})
|
||||||
);
|
);
|
||||||
var turn = null;
|
var turn = null;
|
||||||
status.playing = Session.is(game.public.playing);
|
state.playing = Session.is(game.public.playing);
|
||||||
if(status.playing) {
|
if(state.playing) {
|
||||||
sets.you.hand.dom.classList.toggle("yourTurn", status.step == "ToPlay");
|
sets.you.hand.dom.classList.toggle("yourTurn", state.step == "ToPlay");
|
||||||
turn = I18n.get("yourTurn");
|
turn = I18n.get("yourTurn");
|
||||||
} else {
|
} else {
|
||||||
sets.you.hand.dom.classList.remove("yourTurn");
|
sets.you.hand.dom.classList.remove("yourTurn");
|
||||||
turn = I18n.get('playing')(players.get(game.public.playing));
|
turn = I18n.get('playing')(players.get(game.public.playing));
|
||||||
}
|
}
|
||||||
status.dom.appendChild(Dom.make('li', {textContent: turn}));
|
dom.status.appendChild(Dom.make('li', {textContent: turn}));
|
||||||
}
|
}
|
||||||
|
|
||||||
function setCaptures(game) {
|
function setCaptures(game) {
|
||||||
|
@ -296,7 +210,7 @@ function setCaptures(game) {
|
||||||
Dom.clear(byClass[family.class]);
|
Dom.clear(byClass[family.class]);
|
||||||
});
|
});
|
||||||
game.public.players[key].meld.forEach(function(cardName) {
|
game.public.players[key].meld.forEach(function(cardName) {
|
||||||
var card = new Card(cardName);
|
var card = Card.make(cardName);
|
||||||
byClass[card.value.family.class].appendChild(card.dom);
|
byClass[card.value.family.class].appendChild(card.dom);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -307,7 +221,7 @@ function setCardSet(set, cardNames, constructor) {
|
||||||
set.card = {};
|
set.card = {};
|
||||||
Dom.clear(set.dom);
|
Dom.clear(set.dom);
|
||||||
cardNames.forEach(function(cardName) {
|
cardNames.forEach(function(cardName) {
|
||||||
var card = new constructor(cardName);
|
var card = constructor(cardName);
|
||||||
set.card[cardName] = card;
|
set.card[cardName] = card;
|
||||||
set.dom.appendChild(card.dom);
|
set.dom.appendChild(card.dom);
|
||||||
});
|
});
|
||||||
|
@ -315,7 +229,7 @@ function setCardSet(set, cardNames, constructor) {
|
||||||
|
|
||||||
function setTheirCards(game) {
|
function setTheirCards(game) {
|
||||||
var turnsTheyPlayed = Math.floor(
|
var turnsTheyPlayed = Math.floor(
|
||||||
(game.public.turns + (Session.is(game.public.oyake) ? 0 : 1)) / 2
|
(game.public.gameState.turns + (Session.is(game.public.oyake) ? 0 : 1)) / 2
|
||||||
);
|
);
|
||||||
Dom.clear(sets.them.hand.dom);
|
Dom.clear(sets.them.hand.dom);
|
||||||
for(var i = 0; i < 8 - turnsTheyPlayed; i++) {
|
for(var i = 0; i < 8 - turnsTheyPlayed; i++) {
|
||||||
|
@ -324,20 +238,8 @@ function setTheirCards(game) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function setTurned(cardName) {
|
function setTurned(cardName) {
|
||||||
turnedCard = new TurnedCard(cardName);
|
state.turnedCard = TurnedCard.make(cardName);
|
||||||
if(status.playing) {
|
if(state.playing) {
|
||||||
selected = turnedCard;
|
select(turnedCard);
|
||||||
showCandidates(Hanafuda.Card[cardName], true);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function showCandidates(card, yes) {
|
|
||||||
matchingInRiver(card).forEach(function(riverCard) {riverCard.setCandidate(yes);});
|
|
||||||
}
|
|
||||||
|
|
||||||
function setSelected(yes) {
|
|
||||||
selected = yes ? this : null;
|
|
||||||
this.dom.classList.toggle('selected', yes);
|
|
||||||
showCandidates(this.value, yes);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
106
js/GUI/Screen/Game/Animation.js
Normal file
106
js/GUI/Screen/Game/Animation.js
Normal file
|
@ -0,0 +1,106 @@
|
||||||
|
import * as Card from GUI.Card;
|
||||||
|
import * as State from GUI.Screen.Game.State;
|
||||||
|
import * as Async from UnitJS.Async;
|
||||||
|
import * as Dom from UnitJS.Dom;
|
||||||
|
|
||||||
|
var queue = [];
|
||||||
|
|
||||||
|
return {
|
||||||
|
animate: animate,
|
||||||
|
catchUp: catchUp,
|
||||||
|
delay: delay,
|
||||||
|
getQueue: getQueue
|
||||||
|
};
|
||||||
|
|
||||||
|
function animate(movement) {
|
||||||
|
return Async.bind(
|
||||||
|
Async.apply(function() {
|
||||||
|
var card;
|
||||||
|
var movingCards = [];
|
||||||
|
var side = (State.state.playing) ? 'you' : 'them';
|
||||||
|
var dest = State.sets.river;
|
||||||
|
if(movement.captures != undefined) {
|
||||||
|
card = Card.make(movement.played);
|
||||||
|
dest = State.sets[side];
|
||||||
|
movingCards.push([State.sets.river, dest, Card.make(movement.captures)]);
|
||||||
|
} else {
|
||||||
|
card = RiverCard.make(movement.played);
|
||||||
|
}
|
||||||
|
if(movement.source == 'Hand') {
|
||||||
|
movingCards.push([State.sets[side].hand, dest, card]);
|
||||||
|
} else {
|
||||||
|
var cardSet = {};
|
||||||
|
cardSet[card.name] = State.state.turnedCard || TurnedCard.make(card.name);
|
||||||
|
State.state.turnedCard = null;
|
||||||
|
movingCards.push([{card: cardSet, dom: State.dom.deck}, dest, card]);
|
||||||
|
}
|
||||||
|
return movingCards;
|
||||||
|
}),
|
||||||
|
function(movingCards) {
|
||||||
|
return Async.parallel.apply(null,
|
||||||
|
movingCards.map(function(args) { return moveCard.apply(null, args); })
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function catchUp() {
|
||||||
|
if(queue.length > 0) {
|
||||||
|
var length = queue.length;
|
||||||
|
Async.run.apply(null, queue.concat(
|
||||||
|
Async.apply(function() {
|
||||||
|
queue = queue.slice(length);
|
||||||
|
catchUp();
|
||||||
|
})
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function delay(animation) {
|
||||||
|
queue.push(animation);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getQueue() {
|
||||||
|
return queue;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 moveCard(fromSet, toSet, card) {
|
||||||
|
var from, originalCard;
|
||||||
|
var slot = Dom.make('li', {class: ['card', 'slot']});
|
||||||
|
if (fromSet.card[card.name] != undefined) {
|
||||||
|
originalCard = fromSet.card[card.name].dom;
|
||||||
|
delete fromSet.card[card.name];
|
||||||
|
} else {
|
||||||
|
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 Async.sequence(
|
||||||
|
Async.wait(10),
|
||||||
|
Async.apply(function() {
|
||||||
|
card.dom.style.left = 0;
|
||||||
|
card.dom.style.top = 0;
|
||||||
|
}),
|
||||||
|
Async.wait(1000),
|
||||||
|
Async.apply(function() {
|
||||||
|
fromSet.dom.removeChild(slot);
|
||||||
|
card.dom.classList.remove('moving');
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
84
js/GUI/Screen/Game/State.js
Normal file
84
js/GUI/Screen/Game/State.js
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
import Messaging;
|
||||||
|
|
||||||
|
var dom = {
|
||||||
|
deck: document.getElementById('deck'),
|
||||||
|
rest: document.getElementById('rest'),
|
||||||
|
status: document.getElementById('status')
|
||||||
|
};
|
||||||
|
var selected;
|
||||||
|
var sets = {};
|
||||||
|
var state = {
|
||||||
|
game: null,
|
||||||
|
playing: false,
|
||||||
|
step: null,
|
||||||
|
month: null,
|
||||||
|
turnedCard: null,
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
dom: dom,
|
||||||
|
getSelected: getSelected,
|
||||||
|
init: init,
|
||||||
|
matchingInRiver: matchingInRiver,
|
||||||
|
play: play,
|
||||||
|
select: select,
|
||||||
|
sets: sets,
|
||||||
|
state: state
|
||||||
|
};
|
||||||
|
|
||||||
|
function init() {
|
||||||
|
buildSets();
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildSets() {
|
||||||
|
['river', 'you', 'them'].forEach(function(id) {
|
||||||
|
var setDom = document.getElementById(id);
|
||||||
|
if(setDom.tagName.toLowerCase() == 'ul') {
|
||||||
|
sets[id] = {card: null, dom: setDom};
|
||||||
|
} else {
|
||||||
|
sets[id] = {};
|
||||||
|
for(var i = 0; i < setDom.children.length; i++) {
|
||||||
|
if(setDom.children[i].tagName.toLowerCase() == 'ul') {
|
||||||
|
var child = setDom.children[i].className;
|
||||||
|
sets[id][child] = {card: {}, dom: setDom.children[i]};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function getSelected() {
|
||||||
|
return selected;
|
||||||
|
}
|
||||||
|
|
||||||
|
function matchingInRiver(card) {
|
||||||
|
return Fun.mapFilter(
|
||||||
|
Fun.of(sets.river.card),
|
||||||
|
Fun.defined
|
||||||
|
)(Hanafuda.sameMonth(card).map(Fun.proj('name')));
|
||||||
|
}
|
||||||
|
|
||||||
|
function play(move) {
|
||||||
|
Messaging.send({
|
||||||
|
tag: "Play",
|
||||||
|
move: move,
|
||||||
|
onGame: state.game
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function showCandidates(card, yes) {
|
||||||
|
matchingInRiver(card).forEach(
|
||||||
|
function(riverCard) {riverCard.setCandidate(yes);}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function select(cardOrFalse) {
|
||||||
|
if(typeof cardOrFalse == 'object') {
|
||||||
|
selected = cardOrFalse;
|
||||||
|
}
|
||||||
|
selected.dom.classList.toggle('selected', !!cardOrFalse);
|
||||||
|
showCandidates(selected.value, !!cardOrFalse);
|
||||||
|
if(cardOrFalse === false) {
|
||||||
|
selected = null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -41,6 +41,7 @@ var Card = Object.freeze(
|
||||||
id: i,
|
id: i,
|
||||||
family: findFamily(name, i),
|
family: findFamily(name, i),
|
||||||
flower: Math.floor(i / 4),
|
flower: Math.floor(i / 4),
|
||||||
|
monthOffset: i % 4,
|
||||||
name: name
|
name: name
|
||||||
};
|
};
|
||||||
return o;
|
return o;
|
||||||
|
@ -51,7 +52,6 @@ return {
|
||||||
Flower: Flower,
|
Flower: Flower,
|
||||||
Family: Family,
|
Family: Family,
|
||||||
Card: Card,
|
Card: Card,
|
||||||
getValue: getValue,
|
|
||||||
sameMonth: sameMonth
|
sameMonth: sameMonth
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -67,11 +67,6 @@ function findFamily(name, i) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function getValue(card) {
|
|
||||||
var first = 4 * card.flower;
|
|
||||||
return card.id - first;
|
|
||||||
}
|
|
||||||
|
|
||||||
function sameMonth(card) {
|
function sameMonth(card) {
|
||||||
var first = 4 * card.flower;
|
var first = 4 * card.flower;
|
||||||
return [0,1,2,3].map(function(i) {return Card[CardNames[first + i]];});
|
return [0,1,2,3].map(function(i) {return Card[CardNames[first + i]];});
|
||||||
|
|
15
js/Main.js
15
js/Main.js
|
@ -1,24 +1,11 @@
|
||||||
import I18n;
|
|
||||||
import * as Screen from GUI.Screen;
|
|
||||||
import * as Login from GUI.Screen.Login;
|
import * as Login from GUI.Screen.Login;
|
||||||
import * as Hall from GUI.Screen.Hall;
|
import * as Hall from GUI.Screen.Hall;
|
||||||
import * as Game from GUI.Screen.Game;
|
import * as Game from GUI.Screen.Game;
|
||||||
import Save;
|
|
||||||
|
|
||||||
var gamePath = window.location.pathname.match(/\/game\/([0-9A-Fa-f]+)/);
|
var gamePath = window.location.pathname.match(/\/game\/([0-9A-Fa-f]+)/);
|
||||||
|
|
||||||
if(gamePath) {
|
if(gamePath) {
|
||||||
var gameState = Save.get('games.state.Game#' + gamePath[1]);
|
Game.init(gamePath[1])
|
||||||
if(gameState != undefined) {
|
|
||||||
Game.init(gameState);
|
|
||||||
} else {
|
|
||||||
Screen.dialog({
|
|
||||||
text: I18n.get('gameNotFound'),
|
|
||||||
answers: [
|
|
||||||
{label: 'backToMain', action: function() {window.location = '..';}}
|
|
||||||
]
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
Login.init();
|
Login.init();
|
||||||
Hall.init();
|
Hall.init();
|
||||||
|
|
|
@ -9,8 +9,9 @@ var s = 1000; /* ms */
|
||||||
var keepAlivePeriod = 20;
|
var keepAlivePeriod = 20;
|
||||||
var reconnectDelay = 1;
|
var reconnectDelay = 1;
|
||||||
var routes = {callbacks: [], children: {}};
|
var routes = {callbacks: [], children: {}};
|
||||||
|
var messagesQueue = [];
|
||||||
var wsHandlers = {
|
var wsHandlers = {
|
||||||
open: [function() {on = true; reconnectDelay = 1}, ping],
|
open: [function() {on = true; reconnectDelay = 1}, catchUp, ping],
|
||||||
close: [function() {on = false;}, reconnect]
|
close: [function() {on = false;}, reconnect]
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -79,9 +80,19 @@ function messageListener(event) {
|
||||||
};
|
};
|
||||||
|
|
||||||
function send(o) {
|
function send(o) {
|
||||||
ws.send(JSON.stringify(o));
|
if(isOn()) {
|
||||||
o.direction = 'client > server';
|
ws.send(JSON.stringify(o));
|
||||||
log(o);
|
o.direction = 'client > server';
|
||||||
|
log(o);
|
||||||
|
} else {
|
||||||
|
messagesQueue.push(o);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function catchUp() {
|
||||||
|
var messages = messagesQueue;
|
||||||
|
messagesQueue = [];
|
||||||
|
messagesQueue.forEach(send);
|
||||||
}
|
}
|
||||||
|
|
||||||
function log(message) {
|
function log(message) {
|
||||||
|
|
|
@ -28,6 +28,7 @@ return {
|
||||||
return "This month's flower is the " + flower;
|
return "This month's flower is the " + flower;
|
||||||
},
|
},
|
||||||
noGames: "No games being played",
|
noGames: "No games being played",
|
||||||
|
noNameToPlay: "Your name isn't set, how about choosing one first ?",
|
||||||
notFound: "No one goes by that name",
|
notFound: "No one goes by that name",
|
||||||
notYet: "Not yet",
|
notYet: "Not yet",
|
||||||
ok: "Ok",
|
ok: "Ok",
|
||||||
|
@ -88,6 +89,7 @@ return {
|
||||||
return "C'est le mois des " + flower;
|
return "C'est le mois des " + flower;
|
||||||
},
|
},
|
||||||
noGames: "Aucune partie en cours",
|
noGames: "Aucune partie en cours",
|
||||||
|
noNameToPlay: "Et si on commençait par aller choisir un nom pour jouer",
|
||||||
notFound: "Personne ne s'appelle comme ça",
|
notFound: "Personne ne s'appelle comme ça",
|
||||||
notYet: "Pas pour l'instant",
|
notYet: "Pas pour l'instant",
|
||||||
ok: "Ok",
|
ok: "Ok",
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
#game .card {
|
#game .card {
|
||||||
background: url("/cards.jpg") no-repeat;
|
background: url("../skin/cards.jpg") no-repeat;
|
||||||
background-size: 400% 1300%;
|
background-size: 400% 1300%;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
border-radius: 0.5em;
|
border-radius: 0.5em;
|
||||||
|
|
Loading…
Reference in a new issue