Throw looking OK-ish

This commit is contained in:
2020-03-29 10:37:10 -07:00
parent 4a1d126f9f
commit 2d7c90cb33
9 changed files with 263 additions and 20 deletions

BIN
img/beer.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

BIN
img/grass.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

View File

@@ -5,14 +5,27 @@
<link rel="stylesheet" href="site.css">
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<script type="module" src="index.js"></script>
<script type="module">
import { startApp } from "./modules/index.js";
window.addEventListener("load", startApp);
</script>
</head>
<body>
<header>
<h1>Snappa</h1>
</header>
<main>
<div id="main"></div>
<main id="game">
<div class="Table" id="Table">
<div class="Cup" id="Cup-0"></div>
<div class="Cup" id="Cup-1"></div>
<div class="Cup" id="Cup-2"></div>
<div class="Cup" id="Cup-3"></div>
</div>
<div class="Toss" id="Toss">
Touch and drag the die to throw
<div class="Power" id="Power"></div>
</div>
<div class="Die" id="Die"></div>
<noscript>It's a Gentleman's Game</noscript>
</main>
</body>

View File

@@ -1,3 +0,0 @@
import { startApp } from "./modules/index.js";
startApp();

103
site.css
View File

@@ -0,0 +1,103 @@
html,
body {
margin: 0;
padding: 0;
background: #49713e;
background: url('img/grass.png');
}
body {
display: flex;
flex-direction: column;
height: 100vh;
}
header {
background: #4c76b8;
color: #fff;
display: flex;
flex: 0;
justify-content: center;
}
h1 {
font-size: 32px;
line-height: 40px;
}
main {
display: flex;
flex: 1;
position: relative;
}
.Table {
background: #fff;
border: 10px groove #ddd;
box-shadow: 0px 12px rgba(0, 0, 0, 0.3);
position: fixed;
top: 20vh;
bottom: 20vh;
left: 10vw;
right: 10vw;
transform: perspective(50cm) rotateX(45deg);
}
.Cup {
position: absolute;
background: url('img/beer.png');
height: 64px;
width: 64px;
}
#Cup-0 {
bottom: 0;
left: 0;
}
#Cup-1 {
bottom: 0;
right: 0;
}
#Cup-2 {
top: 0;
left: 0;
}
#Cup-3 {
top: 0;
right: 0;
}
.Toss {
align-self: flex-end;
background: rgba(30,30,30,0.4);
box-sizing: border-box;
color: #ccc;
font-size: 20px;
height: 20vh;
padding-top: 8px;
position: relative;
text-align: center;
width: 100%;
}
.Power {
background: #c00;
bottom: 0;
position: absolute;
height: 40px;
width: 20%;
}
.Die {
background: #fff;
border: 1px solid #000;
height: 20px;
position: fixed;
transform: translate(-10px, -10px);
width: 20px;
}

122
src/die.ts Normal file
View File

@@ -0,0 +1,122 @@
import { Power } from "./power.js";
interface Point {
x: number;
y: number;
}
const touchLocation = (event: TouchEvent): Point => {
if (event.touches.length === 0) {
throw new Error("no touchy");
}
return {
x: event.touches[0].pageX,
y: event.touches[0].pageY,
};
}
export class Die {
node: HTMLDivElement;
power: Power;
x: number;
y: number;
offsetX: number = 0;
offsetY: number = 0;
startX: number | null = null;
startY: number | null = null;
positionRAF: number | null = null;
constructor() {
const node = document.getElementById("Die");
if (!node) {
throw new Error("No dice");
}
this.node = node as HTMLDivElement;
this.power = new Power();
this.x = this.initialX();
this.y = this.initilaY();
this.updatePosition();
node.onmousedown = this.dragStart;
node.ontouchstart = this.touchStart;
}
private initialX = () => window.innerWidth / 2;
private initilaY = () => window.innerHeight * 0.9;
private dragStart = ({ x, y }: Point) => {
window.addEventListener("mousemove", this.mouseMove);
window.addEventListener("touchmove", this.touchMove);
window.addEventListener("mouseup", this.dragEnd);
window.addEventListener("touchend", this.dragEnd);
this.offsetX = x - this.initialX();
this.offsetY = y - this.initilaY();
this.startX = x;
this.startY = y;
window.requestAnimationFrame(this.updatePosition);
}
private mouseDown = (event: MouseEvent) =>
this.dragStart({x: event.pageX, y: event.pageY});
private touchStart = (event: TouchEvent) =>
this.dragStart(touchLocation(event));
private dragMove = ({ x, y}: Point) => {
this.x = x - this.offsetX;
this.y = y - this.offsetY;
window.requestAnimationFrame(this.updatePosition);
}
private mouseMove = (event: MouseEvent) =>
this.dragMove({x: event.pageX, y: event.pageY});
private touchMove = (event: TouchEvent) =>
this.dragMove(touchLocation(event));
private dragEnd = () => {
window.removeEventListener("mousemove", this.mouseMove);
window.removeEventListener("touchmove", this.touchMove);
window.removeEventListener("mouseup", this.dragEnd);
window.removeEventListener("touchend", this.dragEnd);
console.log("TOSS!", this.startX, this.startY, this.x, this.y);
}
private updatePosition = () => {
this.node.style.left = this.x + "px";
this.node.style.top = this.y + "px";
this.power.setPower(this.getTossPower());
}
private getTossPower = () => {
if (this.startX && this.startY) {
const dx = this.x - this.startX;
const dy = this.y - this.startY;
const distance = Math.sqrt(dx*dx + dy*dy);
const scale = window.innerHeight * 0.2;
return Math.min(distance / scale, 1);
} else {
return 0;
}
}
}

View File

@@ -1,8 +1,5 @@
import { Die } from "./die.js";
export const startApp = () => {
const root = <HTMLDivElement>document.getElementById("main");
const div = document.createElement("div");
div.innerHTML = "Sup bro";
root.appendChild(div);
const die = new Die();
};

16
src/power.ts Normal file
View File

@@ -0,0 +1,16 @@
export class Power {
node: HTMLDivElement;
constructor() {
const node = document.getElementById("Power");
if (!node) {
throw new Error("no power");
}
this.node = node as HTMLDivElement;
}
setPower = (power: number) => {
this.node.style.width = power * 100 + "%";
}
}

View File

@@ -2,13 +2,8 @@
"compilerOptions": {
"module": "es2015",
"outDir": "modules",
"strictNullChecks": true,
"rootDir": "src",
"strict": true,
"target": "es2018"
},
"include": [
"src/**/*/"
],
"exclude": [
"node_modules"
]
}
}