This commit is contained in:
2020-03-29 15:43:50 -07:00
parent 2d7c90cb33
commit 096685a701
5 changed files with 142 additions and 6 deletions

View File

@@ -43,6 +43,8 @@ main {
right: 10vw;
transform: perspective(50cm) rotateX(45deg);
transition: transform 2s ease;
}
.Cup {
@@ -96,8 +98,11 @@ main {
.Die {
background: #fff;
border: 1px solid #000;
height: 20px;
border-radius: 2px;
height: 10px;
position: fixed;
transform: translate(-10px, -10px);
width: 20px;
transform: translate(-5px, -5px);
width: 10px;
transition: transform 0.4s ease-out;
}

View File

@@ -1,4 +1,6 @@
import { Power } from "./power.js";
import { View } from "./model.js";
import { MessageHandler } from "./updates.js";
interface Point {
x: number;
@@ -19,6 +21,7 @@ const touchLocation = (event: TouchEvent): Point => {
export class Die {
node: HTMLDivElement;
messageHandler: MessageHandler;
power: Power;
x: number;
@@ -32,7 +35,7 @@ export class Die {
positionRAF: number | null = null;
constructor() {
constructor(messageHandler: MessageHandler) {
const node = document.getElementById("Die");
if (!node) {
throw new Error("No dice");
@@ -40,6 +43,7 @@ export class Die {
this.node = node as HTMLDivElement;
this.messageHandler = messageHandler;
this.power = new Power();
this.x = this.initialX();
@@ -96,7 +100,10 @@ export class Die {
window.removeEventListener("mouseup", this.dragEnd);
window.removeEventListener("touchend", this.dragEnd);
console.log("TOSS!", this.startX, this.startY, this.x, this.y);
this.messageHandler.update("toss", {
power: this.getTossPower(),
direction: this.getTossDirection()
});
}
private updatePosition = () => {
@@ -119,4 +126,15 @@ export class Die {
return 0;
}
}
private getTossDirection = () => {
if (this.startX && this.startY) {
const dx = this.x - this.startX;
const dy = this.y - this.startY;
return Math.atan2(dy, dx);
} else {
return 0;
}
}
}

View File

@@ -1,5 +1,7 @@
import { Die } from "./die.js";
import { MessageHandler } from "./updates.js";
export const startApp = () => {
const die = new Die();
const messageHandler = new MessageHandler();
const die = new Die(messageHandler);
};

9
src/model.ts Normal file
View File

@@ -0,0 +1,9 @@
export interface State {
view: View;
}
export enum View {
Throw,
Toss,
Wait
}

102
src/updates.ts Normal file
View File

@@ -0,0 +1,102 @@
import * as Model from "./model.js";
// Updates
const toss = ({ power, direction }: { power: number, direction: number }) => {
console.log("Power", power);
console.log("Direction", direction);
document.getElementById("Table")!.style.transform = "initial";
document.getElementById("Toss")!.style.display = "none";
document.getElementById("Die")!.style.display = "none";
const die = document.createElement("div");
const startX = window.outerWidth / 2;
const startY = window.outerHeight * 0.9;
die.id = "Die-toss";
die.className = "Die";
die.style.left = startX + "px";
die.style.top = startY + "px";
document.getElementById("game")!.appendChild(die);
// Add +/- pi/20 variance
const throwDirection = direction + Math.random()*0.15 - 0.075;
const table = document.getElementById("Table");
if (!table) {
throw new Error("no table");
}
const tableX = table.clientLeft;
const tableY = table.clientTop;
const tableWidth = table.clientWidth;
const tableHeight = table.clientHeight;
// multiplying both by tableHeight as we want at full-power throw to go off
// the far side of the table
const dx = tableHeight * (0.3 + power) * Math.cos(throwDirection);
const dy = tableHeight * (0.3 + power) * Math.sin(throwDirection);
console.log("Moving to", dx, dy);
setTimeout(() => {
die.style.transform = `translate(${dx}px, ${dy}px)`
}, 2000);
};
const setView = (view: Model.View) => {
console.log("Load view", view);
switch (view) {
case Model.View.Throw:
const toss = document.getElementById("Toss")
toss!.style.visibility = "none";
return;
case Model.View.Toss:
case Model.View.Wait:
return;
}
};
type Updates = typeof updates;
type UpdateFn = keyof Updates;
const updates = {
setView,
toss
};
type Func<F> = F extends (a: infer A) => any ? A : never;
type Message<F extends UpdateFn> = {
fn: F,
args: Func<Updates[F]>
};
export class MessageHandler {
constructor() {
window.addEventListener("message", this.recieve);
}
update = <F extends UpdateFn>(fn: F, args: Func<Updates[F]>) => {
const message = JSON.stringify({ fn, args });
window.postMessage(message, window.location.origin);
}
recieve = (event: MessageEvent) => {
if (event.origin !== window.location.origin) return;
const message: Message<UpdateFn> = extractData(event.data);
(<any>updates[message.fn])(message.args)
}
}
const extractData = <F extends UpdateFn>(data: string): Message<F> => {
const message = JSON.parse(data);
if (!message.fn) {
throw new Error("invalid message");
}
return message;
}