Compare commits
10 Commits
a4842de29e
...
a4a8db2b8d
Author | SHA1 | Date | |
---|---|---|---|
|
a4a8db2b8d | ||
|
746df1cfc9 | ||
|
12c3980f92 | ||
|
cad9df9ead | ||
|
7d0b953fbe | ||
|
72f0eede9d | ||
|
0b1474f41f | ||
|
d618506653 | ||
|
39b87ac1a5 | ||
|
161a6bd06c |
104
scorekeeper/scorekeep.html
Normal file
104
scorekeeper/scorekeep.html
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Scrabble Score</title>
|
||||||
|
<style>
|
||||||
|
* { box-sizing: border-box; }
|
||||||
|
|
||||||
|
html {
|
||||||
|
background-color: #eee;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.score {
|
||||||
|
color: white;
|
||||||
|
display: inline-block;
|
||||||
|
font-family: monospace, sans-serif;
|
||||||
|
font-weight: bold;
|
||||||
|
margin: 0;
|
||||||
|
position: relative;
|
||||||
|
text-align: center;
|
||||||
|
vertical-align: center;
|
||||||
|
width: 50%;
|
||||||
|
height: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.score span { font-size: 20vw; }
|
||||||
|
|
||||||
|
.score.p1 {
|
||||||
|
background-color: darkblue;
|
||||||
|
border: solid 1vw darkblue;
|
||||||
|
border-right: dashed 1vw darkred;
|
||||||
|
}
|
||||||
|
.score.p2 {
|
||||||
|
background-color: darkred;
|
||||||
|
border: solid 1vw darkred;
|
||||||
|
border-bottom: dashed black 1vw;
|
||||||
|
}
|
||||||
|
.score.p3 {
|
||||||
|
background-color: darkgreen;
|
||||||
|
border: solid 1vw darkgreen;
|
||||||
|
border-top: dashed darkblue 1vw;
|
||||||
|
}
|
||||||
|
.score.p4 {
|
||||||
|
background-color: black;
|
||||||
|
border: solid 1vw black;
|
||||||
|
border-left: dashed darkgreen 1vw;
|
||||||
|
}
|
||||||
|
|
||||||
|
input {
|
||||||
|
background: transparent;
|
||||||
|
border: none;
|
||||||
|
border-bottom: solid thin black;
|
||||||
|
color: white;
|
||||||
|
font-family: monospace;
|
||||||
|
font-size: 3vw;
|
||||||
|
opacity: 0.5;
|
||||||
|
position: absolute;
|
||||||
|
right: 2vw;
|
||||||
|
bottom: 1vw;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
console.log("Loaded");
|
||||||
|
function updateScore(event, player) {
|
||||||
|
if (event.key != 'Enter') return;
|
||||||
|
var sbEl = document.querySelector('.score.' + player + ' span');
|
||||||
|
sbEl.innerHTML = +(sbEl.innerHTML) + +(event.target.value);
|
||||||
|
event.target.value = "";
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="p1 score">
|
||||||
|
<span class>0</span>
|
||||||
|
<input name=p1 type=number placeholder="add points"
|
||||||
|
onkeypress="updateScore(event, 'p1')" />
|
||||||
|
</div><!--
|
||||||
|
--><div class="p2 score">
|
||||||
|
<span class>0</span>
|
||||||
|
<input name=p2 type=number placeholder="add points"
|
||||||
|
onkeypress="updateScore(event, 'p2')" />
|
||||||
|
</div><!--
|
||||||
|
--><div class="p3 score">
|
||||||
|
<span class>0</span>
|
||||||
|
<input name=p3 type=number placeholder="add points"
|
||||||
|
onkeypress="updateScore(event, 'p3')" />
|
||||||
|
</div><!--
|
||||||
|
--><div class="p4 score">
|
||||||
|
<span class>0</span>
|
||||||
|
<input name=p4 type=number placeholder="add points"
|
||||||
|
onkeypress="updateScore(event, 'p4')" />
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
4
spike-wars/.babelrc
Normal file
4
spike-wars/.babelrc
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"presets": ["es2015", "stage-0"],
|
||||||
|
"plugins": ["transform-flow-strip-types"]
|
||||||
|
}
|
@ -65,8 +65,8 @@ task browserify(
|
|||||||
dependsOn: [npmInstall, flowCheck],
|
dependsOn: [npmInstall, flowCheck],
|
||||||
type: NodeTask) {
|
type: NodeTask) {
|
||||||
|
|
||||||
inputs.dir('src/main/js/${project.name}.js')
|
//inputs.dir('src/main/js/${project.name}.js')
|
||||||
outputs.file('build/webroot/js/${project.name}-${project.version}.js')
|
//outputs.file('build/webroot/js/${project.name}-${project.version}.js')
|
||||||
|
|
||||||
doFirst { file('build/webroot/js').mkdirs() }
|
doFirst { file('build/webroot/js').mkdirs() }
|
||||||
script = file('node_modules/browserify/bin/cmd.js')
|
script = file('node_modules/browserify/bin/cmd.js')
|
||||||
@ -88,6 +88,7 @@ task minifyJavaScript(
|
|||||||
def argsArr = []
|
def argsArr = []
|
||||||
argsArr << '--compilation_level=SIMPLE_OPTIMIZATIONS'
|
argsArr << '--compilation_level=SIMPLE_OPTIMIZATIONS'
|
||||||
argsArr << "--js_output_file=build/webroot/js/${project.name}-${project.version}.min.js"
|
argsArr << "--js_output_file=build/webroot/js/${project.name}-${project.version}.min.js"
|
||||||
|
argsArr << '--language-in=ECMASCRIPT5'
|
||||||
argsArr << "build/webroot/js/${project.name}-${project.version}.js"
|
argsArr << "build/webroot/js/${project.name}-${project.version}.js"
|
||||||
|
|
||||||
args argsArr
|
args argsArr
|
||||||
|
@ -13,9 +13,14 @@
|
|||||||
"author": "Jonathan Bernard <jdbernard@gmail.com>",
|
"author": "Jonathan Bernard <jdbernard@gmail.com>",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"babel-plugin-transform-flow-strip-types": "^6.8.0",
|
||||||
"babel-preset-es2015": "^6.9.0",
|
"babel-preset-es2015": "^6.9.0",
|
||||||
|
"babel-preset-stage-0": "^6.5.0",
|
||||||
"babelify": "^7.3.0",
|
"babelify": "^7.3.0",
|
||||||
"browserify": "^13.0.1",
|
"browserify": "^13.0.1",
|
||||||
"flow-bin": "^0.29.0"
|
"flow-bin": "^0.29.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"stats.js": "^0.16.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,10 +8,15 @@
|
|||||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||||
|
|
||||||
<link href="css/spike-wars-${version}.css" type="text/css" rel="stylesheet"/>
|
<link href="css/spike-wars-${version}.css" type="text/css" rel="stylesheet"/>
|
||||||
|
<link href='http://fonts.googleapis.com/css?family=Press+Start+2P|PT+Mono' rel='stylesheet' type='text/css'>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
<div id=spike-wars>
|
||||||
<h1>Spike Wars!</h1>
|
<h1>Spike Wars!</h1>
|
||||||
|
<canvas width=960 height=384></canvas>
|
||||||
|
</div>
|
||||||
|
<div><input id=pause type=checkbox checked=false>Pause</input>
|
||||||
<script type='application/javascript' src="js/spike-wars-${version}.js"></script>
|
<script type='application/javascript' src="js/spike-wars-${version}.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
16
spike-wars/src/main/js/game-logic.js
Normal file
16
spike-wars/src/main/js/game-logic.js
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
// @flow
|
||||||
|
import type Board from './game-types';
|
||||||
|
import type GameState from './game-types';
|
||||||
|
import SpikeWarsArtist from './spike-wars-artist';
|
||||||
|
|
||||||
|
function render(state: GameState, artist: SpikeWarsArtist): void {
|
||||||
|
}
|
||||||
|
|
||||||
|
function update(state: GameState): GameState {
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleKeyboardEvent(ke: KeyboardEvent) {
|
||||||
|
}
|
||||||
|
|
||||||
|
export {render, update};
|
5
spike-wars/src/main/js/game-types.js
Normal file
5
spike-wars/src/main/js/game-types.js
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
export type Piece = "WALL" | "PLAYER" | "DEBUG";
|
||||||
|
export type Board = Array<number>;
|
||||||
|
export type GameState = {
|
||||||
|
board: Board,
|
||||||
|
};
|
56
spike-wars/src/main/js/spike-wars-artist.js
Normal file
56
spike-wars/src/main/js/spike-wars-artist.js
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
// @flow
|
||||||
|
type ConstructorOptions = {
|
||||||
|
canvasSelector?: string,
|
||||||
|
rows: number,
|
||||||
|
columns: number };
|
||||||
|
|
||||||
|
export default class SpikeWarsArtist {
|
||||||
|
canvas: HTMLCanvasElement;
|
||||||
|
|
||||||
|
// This is a reference to the drawing API: how we tell the computer to draw
|
||||||
|
// on the canvas. It is a 2D context, meaning we draw in two-dimensions, like
|
||||||
|
// on paper.
|
||||||
|
canvas2d: CanvasRenderingContext2D;
|
||||||
|
|
||||||
|
rows: number; // How many rows are on our game board?
|
||||||
|
cols: number; // How many columns are on our game board?
|
||||||
|
tileWidth: number; // How wide is one of our game board spots?
|
||||||
|
tileHeight: number; // How tall is one of our game bouard spots?
|
||||||
|
|
||||||
|
constructor({canvasSelector = 'canvas', rows, columns}: ConstructorOptions) {
|
||||||
|
this.canvas = ((document.querySelector(canvasSelector): any): HTMLCanvasElement);
|
||||||
|
|
||||||
|
var c2d: ?CanvasRenderingContext2D = this.canvas.getContext('2d');
|
||||||
|
if (c2d) this.canvas2d = c2d;
|
||||||
|
else throw "Cannot get 2D rendering context!"; // TODO: better handling
|
||||||
|
|
||||||
|
this.rows = rows;
|
||||||
|
this.cols = columns;
|
||||||
|
|
||||||
|
this.tileHeight = Math.ceil(this.canvas.height / this.rows);
|
||||||
|
this.tileWidth = Math.ceil(this.canvas.width / this.cols);
|
||||||
|
|
||||||
|
console.log("SpikeWarsArtist: \n\trows: ", this.rows, "\tcols: ", this.cols,
|
||||||
|
"\n\ttileWidth: ", this.tileWidth, "\ttileHeight: ", this.tileHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
coord2idx(row: number, col: number): number { return (this.cols * row) + col; }
|
||||||
|
idx2row(idx: number): number { return Math.floor(idx/this.cols); }
|
||||||
|
idx2col(idx: number): number { return idx % this.cols; }
|
||||||
|
|
||||||
|
drawSolidColor(row: number, col: number, color: string): void {
|
||||||
|
this.drawSolidColorIdx(this.coord2idx(row, col), color); }
|
||||||
|
|
||||||
|
drawSolidColorIdx(idx: number, color: string): void {
|
||||||
|
this.canvas2d.fillStyle = color;
|
||||||
|
|
||||||
|
this.canvas2d.fillRect(
|
||||||
|
(idx % this.cols) * this.tileWidth,
|
||||||
|
Math.floor(idx / this.cols) * this.tileHeight,
|
||||||
|
this.tileWidth, this.tileHeight); }
|
||||||
|
|
||||||
|
drawImage(image: CanvasImageSource, row: number, col: number): void {
|
||||||
|
this.canvas2d.drawImage(image,
|
||||||
|
row * this.tileWidth, col * this.tileWidth,
|
||||||
|
this.tileWidth, this.tileHeight); }
|
||||||
|
}
|
135
spike-wars/src/main/js/spike-wars.js
Normal file
135
spike-wars/src/main/js/spike-wars.js
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
// @flow
|
||||||
|
import Stats from 'stats.js';
|
||||||
|
import SpikeWarsArtist from './spike-wars-artist';
|
||||||
|
import {update, render} from './game-logic';
|
||||||
|
|
||||||
|
import type Board from './game-types';
|
||||||
|
import type GameState from './game-types';
|
||||||
|
import type Piece from './game-types';
|
||||||
|
|
||||||
|
const WALL = "WALL";
|
||||||
|
const DEBUG = "DEBUG";
|
||||||
|
|
||||||
|
type SpikeWarsOptions = {fps?: number, stats?: Object};
|
||||||
|
|
||||||
|
export default class SpikeWars {
|
||||||
|
rows: number;
|
||||||
|
cols: number;
|
||||||
|
|
||||||
|
// This is where we keep track of all the things that are happening in the
|
||||||
|
// game.
|
||||||
|
state: GameState;
|
||||||
|
|
||||||
|
nextGameTick: number; // At what time does the next game update happen?
|
||||||
|
skipTicks: number; // How long does the game wait between updates?
|
||||||
|
|
||||||
|
// This is the thing that knows how to draw stuff.
|
||||||
|
artist: SpikeWarsArtist;
|
||||||
|
|
||||||
|
stats: ?Object;
|
||||||
|
pauseCheckbox: HTMLInputElement;
|
||||||
|
paused: boolean;
|
||||||
|
|
||||||
|
// The constructor is the function that is run when somebody first creates a
|
||||||
|
// new SpikeWars instance. This is where we set stuff up for the first time.
|
||||||
|
constructor({fps = 30, stats}: SpikeWarsOptions) {
|
||||||
|
|
||||||
|
// Get our artist
|
||||||
|
this.rows = 16;
|
||||||
|
this.cols = 40;
|
||||||
|
this.artist = new SpikeWarsArtist({rows: this.rows, columns: this.cols});
|
||||||
|
|
||||||
|
this.state = {board: this.newBoard(), count: 0}; // create a new board
|
||||||
|
|
||||||
|
this.stats = stats;
|
||||||
|
|
||||||
|
this.pauseCheckbox = window.document.getElementsByTagName('input')[0];
|
||||||
|
this.pauseCheckbox.checked = false;
|
||||||
|
this.pauseCheckbox.addEventListener('change', () => { this.toggleGamePaused() });
|
||||||
|
this.paused = false;
|
||||||
|
|
||||||
|
this.skipTicks = Math.ceil(1000 / fps);
|
||||||
|
// TODO: register event handlers on the canvas element.
|
||||||
|
}
|
||||||
|
|
||||||
|
// This function creates a new board.
|
||||||
|
newBoard(): Board {
|
||||||
|
var board = new Array(this.rows * this.cols);
|
||||||
|
for (var i = 0; i < board.length; i++) {
|
||||||
|
var col = i % this.cols;
|
||||||
|
var row = Math.floor(i / this.cols);
|
||||||
|
if (col === 0 || col === (this.cols - 1) ||
|
||||||
|
row === 0 || row === (this.rows - 1)) board[i] = WALL; }
|
||||||
|
return board; }
|
||||||
|
|
||||||
|
toggleGamePaused(): void {
|
||||||
|
this.paused = this.pauseCheckbox.checked;
|
||||||
|
|
||||||
|
if (!this.paused) {
|
||||||
|
this.nextGameTick = new Date().getTime();
|
||||||
|
this.gameLoop(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
// The game loop is where the game actually runs. It is called a loop because
|
||||||
|
// it runs over and over and over, in a loop until it is time to stop the
|
||||||
|
// game.
|
||||||
|
gameLoop(): void {
|
||||||
|
if (this.paused) return;
|
||||||
|
|
||||||
|
// We are going to ask the browser to call us again next time we have a
|
||||||
|
// chance to draw. We're doing this first because we want to make sure we
|
||||||
|
// reserve our place in line before we get busy doing stuff.
|
||||||
|
window.requestAnimationFrame(() => { this.gameLoop(); });
|
||||||
|
//window.setTimeout(() => { this.gameLoop(); });
|
||||||
|
|
||||||
|
// Now we need to check if it is time to do stuff. If our computer is
|
||||||
|
// really fast the game loop might run really fast, or if our computer is
|
||||||
|
// busy the speed might change. That messes up the game (we want it to just
|
||||||
|
// go one speed). So to fix this we use a kind of clock. We figure out how
|
||||||
|
// fast we want the game to run. Then we figure out how much time we should
|
||||||
|
// wait in between each game "tick" (like a clock).
|
||||||
|
//
|
||||||
|
// Is it time for the next game tick?
|
||||||
|
if ((new Date()).getTime() > this.nextGameTick) {
|
||||||
|
if (this.stats) this.stats.begin();
|
||||||
|
|
||||||
|
// Yes! So the first thing we need to do is figure out when the next tick
|
||||||
|
// should be.
|
||||||
|
this.nextGameTick += this.skipTicks;
|
||||||
|
|
||||||
|
// Then we update our game state.
|
||||||
|
this.state = update(this.state);
|
||||||
|
|
||||||
|
// And we re-draw the world.
|
||||||
|
render(this.state, this.artist);
|
||||||
|
if (this.stats) this.stats.end(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
startGame(): void {
|
||||||
|
this.nextGameTick = new Date().getTime();
|
||||||
|
this.drawBoard(this.artist, this.state.board);
|
||||||
|
this.gameLoop(); }
|
||||||
|
|
||||||
|
drawBoard(artist: SpikeWarsArtist, board: Board): void {
|
||||||
|
for (var i = 0; i < board.length; i++) {
|
||||||
|
var color: string;
|
||||||
|
switch (board[i]) {
|
||||||
|
case WALL: color = 'black'; break;
|
||||||
|
case DEBUG: color = 'red'; break;
|
||||||
|
default: color = 'white';
|
||||||
|
}
|
||||||
|
this.artist.drawSolidColorIdx(i, color); } }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// instantiate the instance of SpikeWars
|
||||||
|
if (false) {
|
||||||
|
var stats = new Stats();
|
||||||
|
stats.showPanel(0);
|
||||||
|
document.body.appendChild(stats.dom);
|
||||||
|
window.spikeWars = new SpikeWars({fps: 30, stats: stats}); }
|
||||||
|
|
||||||
|
else { window.spikeWars = new SpikeWars({fps: 30}); }
|
||||||
|
|
||||||
|
//window.spikeWars.startGame();
|
||||||
|
|
22
spike-wars/src/main/scss/spike-wars.scss
Normal file
22
spike-wars/src/main/scss/spike-wars.scss
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
html {
|
||||||
|
background-color: gray;
|
||||||
|
}
|
||||||
|
|
||||||
|
#spike-wars {
|
||||||
|
background-color: white;
|
||||||
|
border: solid 8px black;
|
||||||
|
margin: 24px auto;
|
||||||
|
padding: 48px;
|
||||||
|
width: 960px;
|
||||||
|
|
||||||
|
canvas {
|
||||||
|
width: 960px;
|
||||||
|
height: 384px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-family: 'Press Start 2P', sans-serif;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user