throw
This commit is contained in:
11
site.css
11
site.css
@@ -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;
|
||||
}
|
||||
|
||||
22
src/die.ts
22
src/die.ts
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
9
src/model.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
export interface State {
|
||||
view: View;
|
||||
}
|
||||
|
||||
export enum View {
|
||||
Throw,
|
||||
Toss,
|
||||
Wait
|
||||
}
|
||||
102
src/updates.ts
Normal file
102
src/updates.ts
Normal 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;
|
||||
}
|
||||
Reference in New Issue
Block a user