|
class Rummikub extends Croquet.Model { |
|
init() { |
|
this.tiles = ['red', 'blue', 'green', 'orange'].map(color => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12].map(number => ({ |
|
color, |
|
number, |
|
tileState: 'UNPICKED', |
|
x: Math.random() * .2, |
|
y: Math.random() * .2 |
|
}))).reduce((a, b) => a.concat(b), [{ |
|
color: 'green', |
|
number: ':)', |
|
tileState: 'UNPICKED', |
|
x: Math.random() * .2, |
|
y: Math.random() * .2 |
|
}, { |
|
color: 'red', |
|
number: ':)', |
|
tileState: 'UNPICKED', |
|
x: Math.random() * .2, |
|
y: Math.random() * .2 |
|
}]) |
|
this.users = [] |
|
this.stillOpen = true |
|
|
|
this.subscribe("default", "drawTile", this.drawTile) |
|
this.subscribe("default", "newUser", this.newUser) |
|
this.subscribe("default", "updateTile", this.updateTile) |
|
} |
|
|
|
unpickedTiles() { |
|
return this.tiles.filter(tile => tile.tileState === 'UNPICKED') |
|
} |
|
|
|
newUser(user) { |
|
this.users.push(user) |
|
} |
|
|
|
drawTile(name) { |
|
if (this.unpickedTiles().length) { |
|
let tile = this.unpickedTiles()[Math.floor(Math.random() * this.unpickedTiles().length)] |
|
tile.tileState = name |
|
return tile |
|
} |
|
} |
|
|
|
updateTile({number, color, tileState, x, y}) { |
|
let tile = this.tiles.find(tile => tile.number === number && tile.color === color) |
|
if (tileState) tile.tileState = tileState |
|
if (x) tile.x = x |
|
if (y) tile.y = y |
|
} |
|
|
|
} |
|
Rummikub.register(); |
|
|
|
function inHand(y) { |
|
return y > hand.getBoundingClientRect().top |
|
} |
|
|
|
class MyView extends Croquet.View { |
|
constructor(model) { |
|
super(model); |
|
this.model = model; |
|
|
|
let savedName = localStorage.getItem('name'); |
|
if (savedName !== null && savedName !== "null") { |
|
this.name = savedName |
|
} else { |
|
this.name = prompt("What's your name?") |
|
localStorage.setItem('name', this.name) |
|
} |
|
this.publish("default", "newUser", {name: this.name, viewId: this.viewId}) |
|
} |
|
|
|
getTile({color, number}) { |
|
return this.model.tiles.find(tile => tile.number === number && tile.color === color) |
|
} |
|
|
|
update() { |
|
let score = {} |
|
this.model.tiles.forEach(({tileState}) => { |
|
if (!(tileState === "UNPICKED" || tileState === "PLAYED")) { |
|
score[tileState] = (score[tileState] || 0) + 1 |
|
} |
|
}) |
|
scoreboard.innerHTML = JSON.stringify(score).replace("{", "").replace("}", "").replace(/"/g, "").replace(",", '<br>') |
|
|
|
this.model.tiles.forEach(({color, number, x, y, tileState}) => { |
|
let id = color + number |
|
if (!(tileState === "UNPICKED" || tileState === "PLAYED" || tileState === this.name)) { |
|
let elem = document.getElementById(id) |
|
if (elem) elem.remove() |
|
return |
|
} |
|
let elem = document.getElementById(id) |
|
if (!elem) { |
|
elem = document.createElement('div') |
|
elem.innerHTML = `<div style="color:${color}; font-size: 1.5em">${number}</div>` |
|
elem.id = id |
|
elem.classList.add('tile') |
|
elem.ontouchend = e => setTimeout(() => { |
|
elem.moving = false |
|
elem.style["z-index"] = 1 |
|
}, 1000) |
|
elem.ontouchmove = e => { |
|
elem.moving = true |
|
|
|
let b = elem.getBoundingClientRect() |
|
let clientX = e.touches[0].clientX - (b.width /2) |
|
let clientY = e.touches[0].clientY - (b.height/2) |
|
|
|
elem.style.left = clientX + "px" |
|
elem.style.top = clientY + "px" |
|
elem.style["z-index"] = 999 |
|
|
|
let currentTileState = this.getTile({color, number}).tileState |
|
let newTileState |
|
if (inHand(e.touches[0].clientY + (b.height/2))) { |
|
newTileState = this.name |
|
} else if (currentTileState === this.name) { |
|
newTileState = "PLAYED" |
|
} |
|
|
|
this.publish("default", "updateTile", { |
|
color, number, |
|
x: clientX / window.innerWidth, |
|
y: clientY / window.innerHeight, |
|
tileState: newTileState |
|
}) |
|
} |
|
container.append(elem) |
|
} else if (!elem.moving) { |
|
elem.style.left = x * window.innerWidth + "px" |
|
elem.style.top = y * window.innerHeight + "px" |
|
} |
|
elem.firstChild.style.display = tileState === "UNPICKED" ? 'none' : 'block' |
|
}) |
|
} |
|
|
|
} |
|
|
|
Croquet.Session.join("Rummikub", Rummikub, MyView).then(r => window.r = r); |