Basic playmat stuff: deck/discard, hand, card movement
This commit is contained in:
parent
2b40f95d18
commit
d32d50226b
5978
interact.js
Normal file
5978
interact.js
Normal file
File diff suppressed because it is too large
Load Diff
12
package.json
Normal file
12
package.json
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"name": "final",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "",
|
||||||
|
"main": "server.js",
|
||||||
|
"scripts": {
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1",
|
||||||
|
"start": "node server.js"
|
||||||
|
},
|
||||||
|
"author": "",
|
||||||
|
"license": "ISC"
|
||||||
|
}
|
141
script.js
Normal file
141
script.js
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
let deckName, deckJSON, cardCount, deckWidth, deckHeight,
|
||||||
|
piles = {'deck': [], discard: []};
|
||||||
|
|
||||||
|
window.addEventListener('load', () => {
|
||||||
|
deckName = document.querySelector('#card-container').getAttribute("data-deckName");
|
||||||
|
let xhr = new XMLHttpRequest();
|
||||||
|
xhr.addEventListener("load", () => {
|
||||||
|
deckJSON = JSON.parse(xhr.responseText);
|
||||||
|
piles['deck'] = deckJSON.ObjectStates[0].DeckIDs.map(c => c - 100);
|
||||||
|
cardCount = piles['deck'].length;
|
||||||
|
shuffle(piles['deck']);
|
||||||
|
deckWidth = deckJSON.ObjectStates[0].CustomDeck["1"].NumWidth;
|
||||||
|
deckHeight = deckJSON.ObjectStates[0].CustomDeck["1"].NumHeight;
|
||||||
|
console.log(deckName);
|
||||||
|
});
|
||||||
|
xhr.open("GET", "/" + deckName + ".json");
|
||||||
|
xhr.send();
|
||||||
|
});
|
||||||
|
|
||||||
|
let cardInteract = interact('.card')
|
||||||
|
.draggable({
|
||||||
|
restrict: {
|
||||||
|
restriction: "parent",
|
||||||
|
endOnly: true,
|
||||||
|
elementRect: { top: 0, left: 0, bottom: 1, right: 1 }
|
||||||
|
},
|
||||||
|
|
||||||
|
snap: {
|
||||||
|
targets: [() => {
|
||||||
|
// TODO: maybe change to dropzone?
|
||||||
|
let pos = document.body.getBoundingClientRect(),
|
||||||
|
style = window.getComputedStyle(hand),
|
||||||
|
handHeight = parseInt(style.getPropertyValue("height"));
|
||||||
|
return {y: pos.bottom,
|
||||||
|
range: handHeight/2};
|
||||||
|
}],
|
||||||
|
relativePoints: [{x: 0.5 , y: 1}]
|
||||||
|
},
|
||||||
|
|
||||||
|
onmove: dragMoveListener
|
||||||
|
})
|
||||||
|
.on('hold', event => {
|
||||||
|
let target = event.target,
|
||||||
|
transform = target.style.transform;
|
||||||
|
// Scale up for visibility
|
||||||
|
if (transform.includes("scale(2)")) {
|
||||||
|
// translate the element
|
||||||
|
target.style.webkitTransform =
|
||||||
|
target.style.transform = transform.replace(" scale(2)", "");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
target.style.webkitTransform =
|
||||||
|
target.style.transform = transform + ' scale(2)';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
interact('.card-pile')
|
||||||
|
.dropzone({
|
||||||
|
accept: '.card',
|
||||||
|
ondrop: event => {
|
||||||
|
let pile = piles[event.target.getAttribute('data-pile')];
|
||||||
|
pile.push(event.relatedTarget.getAttribute('data-num'));
|
||||||
|
event.relatedTarget.parentElement.removeChild(event.relatedTarget);
|
||||||
|
|
||||||
|
// update deck text
|
||||||
|
event.target.innerHTML = `DECK<br>${pile.length}/${cardCount}`;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.draggable({manualStart: true})
|
||||||
|
.on('move', event => {
|
||||||
|
let interaction = event.interaction;
|
||||||
|
let pile = piles[event.target.getAttribute('data-pile')];
|
||||||
|
|
||||||
|
// if the pointer was moved while being held down
|
||||||
|
// and an interaction hasn't started yet
|
||||||
|
if (interaction.pointerIsDown &&
|
||||||
|
!interaction.interacting() &&
|
||||||
|
pile.length > 0) {
|
||||||
|
// draw a new card
|
||||||
|
let newCard = document.createElement('div');
|
||||||
|
newCard.className = "card";
|
||||||
|
let style = window.getComputedStyle(newCard);
|
||||||
|
let cardNum = pile.pop();
|
||||||
|
newCard.setAttribute('data-num', cardNum);
|
||||||
|
newCard.style.backgroundPosition = `
|
||||||
|
${(cardNum % deckWidth) * parseInt(style.getPropertyValue("width"))}px
|
||||||
|
${Math.floor(cardNum/deckHeight) * parseInt(style.getPropertyValue("height"))}px`;
|
||||||
|
newCard.style.backgroundImage = `url('${deckName}.png')`;
|
||||||
|
newCard.style.backgroundSize = `${deckWidth * 100}% ${deckHeight * 100}%`;
|
||||||
|
|
||||||
|
// insert the card to the page
|
||||||
|
document.querySelector("#card-container").appendChild(newCard);
|
||||||
|
|
||||||
|
// update deck text
|
||||||
|
event.target.innerHTML = `DECK<br>${pile.length}/${cardCount}`;
|
||||||
|
|
||||||
|
// start a drag interaction targeting the clone
|
||||||
|
interaction.start({name: 'drag'}, cardInteract, newCard);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Fisher-Yates shuffle from https://bost.ocks.org/mike/shuffle/
|
||||||
|
function shuffle(array) {
|
||||||
|
let m = array.length, t, i;
|
||||||
|
|
||||||
|
// While there remain elements to shuffle…
|
||||||
|
while (m) {
|
||||||
|
// Pick a remaining element…
|
||||||
|
i = Math.floor(Math.random() * m--);
|
||||||
|
|
||||||
|
// And swap it with the current element.
|
||||||
|
t = array[m];
|
||||||
|
array[m] = array[i];
|
||||||
|
array[i] = t;
|
||||||
|
}
|
||||||
|
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
function dragMoveListener (event) {
|
||||||
|
let interaction = event.interaction;
|
||||||
|
|
||||||
|
let target = event.target,
|
||||||
|
// keep the dragged position in the data-x/data-y attributes
|
||||||
|
x = (parseFloat(target.getAttribute('data-x')) || 0) + event.dx,
|
||||||
|
y = (parseFloat(target.getAttribute('data-y')) || 0) + event.dy;
|
||||||
|
|
||||||
|
// translate the element
|
||||||
|
target.style.webkitTransform =
|
||||||
|
target.style.transform =
|
||||||
|
'translate(' + x + 'px, ' + y + 'px)';
|
||||||
|
|
||||||
|
// raise to top
|
||||||
|
target.parentElement.removeChild(target);
|
||||||
|
document.querySelector("#card-container").appendChild(target);
|
||||||
|
|
||||||
|
// update the posiion attributes
|
||||||
|
target.setAttribute('data-x', x);
|
||||||
|
target.setAttribute('data-y', y);
|
||||||
|
}
|
||||||
|
|
91
server.js
Normal file
91
server.js
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
// jshint node:true
|
||||||
|
// jshint esversion:6
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
const http = require('http'),
|
||||||
|
qs = require('querystring'),
|
||||||
|
fs = require('fs'),
|
||||||
|
url = require('url'),
|
||||||
|
https = require('https'),
|
||||||
|
port = 8080;
|
||||||
|
|
||||||
|
const deckName = "the_Unholy_Priest_update_2";
|
||||||
|
|
||||||
|
const server = http.createServer((req, res) => {
|
||||||
|
const uri = url.parse(req.url);
|
||||||
|
|
||||||
|
if (req.method === 'POST') {
|
||||||
|
handlePost(res, req, uri);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
switch( uri.pathname ) {
|
||||||
|
case '/':
|
||||||
|
case '/index.html':
|
||||||
|
sendIndex(res, "");
|
||||||
|
break;
|
||||||
|
case '/style.css':
|
||||||
|
sendFile(res, 'style.css', 'text/css');
|
||||||
|
break;
|
||||||
|
case '/script.js':
|
||||||
|
sendFile(res, 'script.js', 'application/javascript');
|
||||||
|
break;
|
||||||
|
case '/interact.js':
|
||||||
|
sendFile(res, 'interact.js', 'application/javascript');
|
||||||
|
break;
|
||||||
|
case '/' + deckName + '.png':
|
||||||
|
sendFile(res, deckName + '.png', 'image/png');
|
||||||
|
break;
|
||||||
|
case '/' + deckName + '.json':
|
||||||
|
sendFile(res, deckName + '.json', 'application/json');
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
res.writeHead(404, {'Content-type': "text/html; charset=utf-8"});
|
||||||
|
const html = `
|
||||||
|
<head>
|
||||||
|
<title>404 Not Found</title>
|
||||||
|
<link rel="stylesheet" href="style.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>Error 404: Path ${uri.pathname} not found</h1>
|
||||||
|
You seem to have gone to the wrong place, would you like to go
|
||||||
|
back to the <a href="/">main page</a>?
|
||||||
|
</body>`;
|
||||||
|
res.end(html, 'utf-8');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
server.listen(process.env.PORT || port);
|
||||||
|
console.log('listening on 8080');
|
||||||
|
|
||||||
|
function sendIndex(res) {
|
||||||
|
let cards = [];
|
||||||
|
const html = `
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<script src="interact.js"></script>
|
||||||
|
<script src="script.js"></script>
|
||||||
|
<link rel="stylesheet" type="text/css" href="style.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="card-container" data-deckName="${deckName}">
|
||||||
|
<div class="card-pile deck" data-pile="deck">DECK</div>
|
||||||
|
<div class="card-pile discard" data-pile="discard"></div>
|
||||||
|
<div id="hand"></div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>`;
|
||||||
|
res.writeHead(200, {'contentType': 'text/html; charset=utf-8'});
|
||||||
|
res.end(html, 'utf-8');
|
||||||
|
}
|
||||||
|
|
||||||
|
function sendFile(res, filename, contentType='text/html; charset=utf-8') {
|
||||||
|
fs.readFile(filename, (error, content) => {
|
||||||
|
res.writeHead(200, {'Content-type': contentType});
|
||||||
|
res.end(content, 'utf-8');
|
||||||
|
if (error) {
|
||||||
|
console.error(error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
42
style.css
Normal file
42
style.css
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
body {
|
||||||
|
margin: 0 0 0 0;
|
||||||
|
}
|
||||||
|
.card {
|
||||||
|
position: absolute;
|
||||||
|
border-radius: 5px;
|
||||||
|
width: 142px;
|
||||||
|
height: 200px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#card-container {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#hand {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0px;
|
||||||
|
width: 100%;
|
||||||
|
height: 20%;
|
||||||
|
background-color: #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-pile {
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
color: #eee;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
-moz-user-select: none;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.deck {
|
||||||
|
background-color: blue;
|
||||||
|
}
|
||||||
|
|
||||||
|
.discard {
|
||||||
|
background-color: red;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user