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],
 | 
			
		||||
    type: NodeTask) {
 | 
			
		||||
 | 
			
		||||
    inputs.dir('src/main/js/${project.name}.js')
 | 
			
		||||
    outputs.file('build/webroot/js/${project.name}-${project.version}.js')
 | 
			
		||||
    //inputs.dir('src/main/js/${project.name}.js')
 | 
			
		||||
    //outputs.file('build/webroot/js/${project.name}-${project.version}.js')
 | 
			
		||||
 | 
			
		||||
    doFirst { file('build/webroot/js').mkdirs() }
 | 
			
		||||
    script = file('node_modules/browserify/bin/cmd.js')
 | 
			
		||||
@@ -88,6 +88,7 @@ task minifyJavaScript(
 | 
			
		||||
    def argsArr = []
 | 
			
		||||
    argsArr << '--compilation_level=SIMPLE_OPTIMIZATIONS'
 | 
			
		||||
    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"
 | 
			
		||||
 | 
			
		||||
    args argsArr
 | 
			
		||||
 
 | 
			
		||||
@@ -13,9 +13,14 @@
 | 
			
		||||
  "author": "Jonathan Bernard <jdbernard@gmail.com>",
 | 
			
		||||
  "license": "ISC",
 | 
			
		||||
  "devDependencies": {
 | 
			
		||||
    "babel-plugin-transform-flow-strip-types": "^6.8.0",
 | 
			
		||||
    "babel-preset-es2015": "^6.9.0",
 | 
			
		||||
    "babel-preset-stage-0": "^6.5.0",
 | 
			
		||||
    "babelify": "^7.3.0",
 | 
			
		||||
    "browserify": "^13.0.1",
 | 
			
		||||
    "flow-bin": "^0.29.0"
 | 
			
		||||
  },
 | 
			
		||||
  "dependencies": {
 | 
			
		||||
    "stats.js": "^0.16.0"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -8,10 +8,15 @@
 | 
			
		||||
    <meta name="apple-mobile-web-app-capable" content="yes">
 | 
			
		||||
 | 
			
		||||
    <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>
 | 
			
		||||
 | 
			
		||||
  <body>
 | 
			
		||||
    <h1>Spike Wars!</h1>
 | 
			
		||||
    <div id=spike-wars>
 | 
			
		||||
      <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>
 | 
			
		||||
  </body>
 | 
			
		||||
</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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user