From 681772b0ca59b428d24da7b1f030db7b5ca295e7 Mon Sep 17 00:00:00 2001 From: Will Billingsley <wbilling@une.edu.au> Date: Tue, 24 Jul 2018 03:50:57 +1000 Subject: [PATCH] Solution to tutorial 3 --- gameOfLife.js | 151 ++++++++++--------------- gameOfLife.ts | 77 +++++++++++++ index.html | 6 +- package-lock.json | 280 ++++++++++++++++++++++++++++++++++++++++++++++ package.json | 20 ++++ render.js | 69 +++++------- render.ts | 37 ++++++ tsconfig.json | 59 ++++++++++ 8 files changed, 565 insertions(+), 134 deletions(-) create mode 100644 gameOfLife.ts create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 render.ts create mode 100644 tsconfig.json diff --git a/gameOfLife.js b/gameOfLife.js index b98b705..ba7da91 100644 --- a/gameOfLife.js +++ b/gameOfLife.js @@ -1,101 +1,68 @@ "use strict"; - -// Our code is wrapped in an anonymous function to keep -// variables private by default -(function () { - - let h = 20 // height of the board - let w = 40 // width of the board - - /* - The board is represented in memory as a flat array, eg: - [ 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0 ] - But we'll initialise its contents in a function. - */ - let board = [] - - // Calculates an index into the board for a given (x, y) location - function boardIndex(x, y) { - return y * w + x +var Life = /** @class */ (function () { + function Life(w, h) { + if (w === void 0) { w = 40; } + if (h === void 0) { h = 20; } + this.w = w; + this.h = h; + this.board = this.emptyBoard(); } - - // Zeroes the contents of the board array - function emptyBoard() { - for (let x = 0; x < w; x++) { - for (let y = 0; y < h; y++) { - board[boardIndex(x, y)] = 0 - } + Life.prototype.boardIndex = function (x, y) { + return y * this.w + x; + }; + Life.prototype.x = function (index) { + return index % this.w; + }; + Life.prototype.y = function (index) { + return Math.floor(index / this.w); + }; + Life.prototype.emptyBoard = function () { + var arr = []; + for (var i = 0; i < this.h * this.w; i++) { + arr.push(false); } - } - - // toggles wheter a cell is "alive" or not - function toggleCell(x, y) { - let idx = boardIndex(x, y) - board[idx] = !board[idx] - } - - // determines whether a cell is alive, dealing with range checks - function isAlive(x, y) { - let idx = boardIndex(x, y) - return (x >= 0) && (y >= 0) && (x < w) && (y < h) && board[idx] - } - - function liveNeighbours(x, y) { - let count = 0 - for (let i = x - 1; i <= x + 1; i++) { - for (let j = y - 1; j <= y + 1; j++) { - if (isAlive(i,j) && ((i != x) || (j != y))) { - count++ + return arr; + }; + Life.prototype.toggleCell = function (x, y) { + var b = this.boardIndex(x, y); + this.board[b] = !this.board[b]; + }; + Life.prototype.isAlive = function (x, y) { + var b = this.boardIndex(x, y); + return (x >= 0) && (y >= 0) && (x < this.w) && (y < this.h) + && this.board[b]; + }; + Life.prototype.liveNeighbours = function (x, y) { + var live = 0; + for (var _i = 0, _a = [x - 1, x, x + 1]; _i < _a.length; _i++) { + var i = _a[_i]; + for (var _b = 0, _c = [y - 1, y, y + 1]; _b < _c.length; _b++) { + var j = _c[_b]; + if (this.isAlive(i, j) && (i != x || j != y)) { + live++; } } } - return count - } - - // Steps the game forward by a single tick, by calculating the - // next state of the board's cells - function stepGame() { - let nextBoard = [] - - for (var x = 0; x < w; x++) { - for (let y = 0; y < h; y++) { - let idx = boardIndex(x, y) - let alive = isAlive(x, y) - let neighbours = liveNeighbours(x, y) - - if ( - (alive && (neighbours == 2 || neighbours == 3)) || - (!alive && neighbours == 3) - ) { - nextBoard[idx] = 1 - } else { - nextBoard[idx] = 0 + return live; + }; + Life.prototype.stepGame = function () { + var nextBoard = this.emptyBoard(); + for (var x = 0; x < this.w; x++) { + for (var y = 0; y < this.h; y++) { + var index = this.boardIndex(x, y); + var alive = this.isAlive(x, y); + var neighbours = this.liveNeighbours(x, y); + if ((alive && (neighbours == 2 || neighbours == 3)) || + (!alive && neighbours == 3)) { + nextBoard[index] = true; + } + else { + nextBoard[index] = false; } } } - - board = nextBoard - } - - - // publish our game on the window object - window.gameOfLife = { - - getW: function() { return w }, - - getH: function() { return h }, - - isAlive: isAlive, - - emptyBoard: emptyBoard, - - toggleCell: toggleCell, - - stepGame: stepGame - - } - - -})() \ No newline at end of file + this.board = nextBoard; + }; + return Life; +}()); +//# sourceMappingURL=gameOfLife.js.map \ No newline at end of file diff --git a/gameOfLife.ts b/gameOfLife.ts new file mode 100644 index 0000000..ecf4b91 --- /dev/null +++ b/gameOfLife.ts @@ -0,0 +1,77 @@ + +class Life { + + board: Array<boolean> + + constructor(public w:number = 40, public h:number = 20) { + this.board = this.emptyBoard() + } + + boardIndex(x:number, y:number):number { + return y * this.w + x + } + + x(index:number) { + return index % this.w + } + + y(index:number) { + return Math.floor(index / this.w) + } + + emptyBoard():boolean[] { + let arr = <boolean[]>[] + for (let i = 0; i < this.h * this.w; i++) { + arr.push(false) + } + return arr + } + + toggleCell(x:number, y:number):void { + let b = this.boardIndex(x,y) + this.board[b] = !this.board[b] + } + + isAlive(x:number, y:number):boolean { + let b = this.boardIndex(x,y) + return (x >= 0) && (y >= 0) && (x < this.w) && (y < this.h) + && this.board[b] + } + + liveNeighbours(x:number, y:number) { + let live = 0 + for (let i of [x - 1, x, x + 1]) { + for (let j of [y - 1, y, y + 1]) { + if (this.isAlive(i,j) && (i != x || j != y)) { + live++ + } + } + } + return live + } + + stepGame():void { + let nextBoard = this.emptyBoard() + for (let x = 0; x < this.w; x++) { + for (let y = 0; y < this.h; y++) { + let index = this.boardIndex(x, y) + let alive = this.isAlive(x, y) + let neighbours = this.liveNeighbours(x, y) + + if ( + (alive && (neighbours == 2 || neighbours == 3)) || + (!alive && neighbours == 3) + ) { + nextBoard[index] = true + } else { + nextBoard[index] = false + } + } + } + this.board = nextBoard + } + +} + + + diff --git a/index.html b/index.html index c926c6b..0d9bfd1 100644 --- a/index.html +++ b/index.html @@ -7,14 +7,14 @@ <h1>Conway's Game of Life</h1> <svg xmlns="http://www.w3.org/2000/svg" id="game" width="640" height="400"></svg> <div> - <button class="btn btn-primary" onclick="javascript: { gameOfLife.stepGame(); render(); }">Step</button> + <button class="btn btn-primary" onclick="javascript: { life.stepGame(); render(); }">Step</button> </div> </div> + <script src="https://d3js.org/d3.v5.min.js"></script> <script src="gameOfLife.js"></script> <script src="render.js"></script> - <script> - gameOfLife.emptyBoard() + <script> render() </script> diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..85d5906 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,280 @@ +{ + "name": "tutorial-conway-life-t3", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@types/d3": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@types/d3/-/d3-5.0.0.tgz", + "integrity": "sha512-BVfPw7ha+UgsG24v6ymerMY4+pJgQ/6p+hJA4loCeaaqV9snGS/G6ReVaQEn8Himn67dWn/Je9WhRbnDO7MzLw==", + "dev": true, + "requires": { + "@types/d3-array": "*", + "@types/d3-axis": "*", + "@types/d3-brush": "*", + "@types/d3-chord": "*", + "@types/d3-collection": "*", + "@types/d3-color": "*", + "@types/d3-contour": "*", + "@types/d3-dispatch": "*", + "@types/d3-drag": "*", + "@types/d3-dsv": "*", + "@types/d3-ease": "*", + "@types/d3-fetch": "*", + "@types/d3-force": "*", + "@types/d3-format": "*", + "@types/d3-geo": "*", + "@types/d3-hierarchy": "*", + "@types/d3-interpolate": "*", + "@types/d3-path": "*", + "@types/d3-polygon": "*", + "@types/d3-quadtree": "*", + "@types/d3-random": "*", + "@types/d3-scale": "*", + "@types/d3-scale-chromatic": "*", + "@types/d3-selection": "*", + "@types/d3-shape": "*", + "@types/d3-time": "*", + "@types/d3-time-format": "*", + "@types/d3-timer": "*", + "@types/d3-transition": "*", + "@types/d3-voronoi": "*", + "@types/d3-zoom": "*" + } + }, + "@types/d3-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-1.2.1.tgz", + "integrity": "sha512-YBaAfimGdWE4nDuoGVKsH89/dkz2hWZ0i8qC+xxqmqi+XJ/aXiRF0jPtzXmN7VdkpVjy1xuDmM5/m1FNuB6VWA==", + "dev": true + }, + "@types/d3-axis": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/@types/d3-axis/-/d3-axis-1.0.10.tgz", + "integrity": "sha512-5YF0wfdQMPKw01VAAupLIlg/T4pn5M3/vL9u0KZjiemnVnnKBEWE24na4X1iW+TfZiYJ8j+BgK2KFYnAAT54Ug==", + "dev": true, + "requires": { + "@types/d3-selection": "*" + } + }, + "@types/d3-brush": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/d3-brush/-/d3-brush-1.0.8.tgz", + "integrity": "sha512-9Thv09jvolu9T1BE3fHmIeYSgbwSpdxtF6/A5HZEDjSTfgtA0mtaXRk5AiWOo0KjuLsI+/7ggD3ZGN5Ye8KXPQ==", + "dev": true, + "requires": { + "@types/d3-selection": "*" + } + }, + "@types/d3-chord": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/@types/d3-chord/-/d3-chord-1.0.7.tgz", + "integrity": "sha512-WbCN7SxhZMpQQw46oSjAovAmvl3IdjhLuQ4r7AXCzNKyxtXXBWuihSPZ4bVwFQF3+S2z37i9d4hfUBatcSJpog==", + "dev": true + }, + "@types/d3-collection": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/@types/d3-collection/-/d3-collection-1.0.7.tgz", + "integrity": "sha512-vR3BT0GwHc5y93Jv6bxn3zoxP/vGu+GdXu/r1ApjbP9dLk9I2g6NiV7iP/QMQSuFZd0It0n/qWrfXHxCWwHIkg==", + "dev": true + }, + "@types/d3-color": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-1.2.1.tgz", + "integrity": "sha512-xwb1tqvYNWllbHuhMFhiXk63Imf+QNq/dJdmbXmr2wQVnwGenCuj3/0IWJ9hdIFQIqzvhT7T37cvx93jtAsDbQ==", + "dev": true + }, + "@types/d3-contour": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@types/d3-contour/-/d3-contour-1.2.1.tgz", + "integrity": "sha512-p8iC4KeVFyT3qRTGQRj0Jf5QDdPsDUevBEnma7gEsY1yDolVSLanG2eFAiLV+xj8/5DK7oU7Ey8z0drs3pbsug==", + "dev": true, + "requires": { + "@types/d3-array": "*", + "@types/geojson": "*" + } + }, + "@types/d3-dispatch": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-dispatch/-/d3-dispatch-1.0.6.tgz", + "integrity": "sha512-xyWJQMr832vqhu6fD/YqX+MSFBWnkxasNhcStvlhqygXxj0cKqPft0wuGoH5TIq5ADXgP83qeNVa4R7bEYN3uA==", + "dev": true + }, + "@types/d3-drag": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@types/d3-drag/-/d3-drag-1.2.1.tgz", + "integrity": "sha512-J9liJ4NNeV0oN40MzPiqwWjqNi3YHCRtHNfNMZ1d3uL9yh1+vDuo346LBEr8yyBm30WHvrHssAkExVZrGCswtA==", + "dev": true, + "requires": { + "@types/d3-selection": "*" + } + }, + "@types/d3-dsv": { + "version": "1.0.33", + "resolved": "https://registry.npmjs.org/@types/d3-dsv/-/d3-dsv-1.0.33.tgz", + "integrity": "sha512-jx5YvaVC3Wfh6LobaiWTeU1NkvL2wPmmpmajk618bD+xVz98yNWzmZMvmlPHGK0HXbMeHmW/6oVX48V9AH1bRQ==", + "dev": true + }, + "@types/d3-ease": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/@types/d3-ease/-/d3-ease-1.0.7.tgz", + "integrity": "sha1-k6MBhovp4VBh89RDQ7GrP4rLbwk=", + "dev": true + }, + "@types/d3-fetch": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@types/d3-fetch/-/d3-fetch-1.1.2.tgz", + "integrity": "sha512-w6ANZv/mUh+6IV3drT22zgPWMRobzuGXhzOZC8JPD+ygce0/Vx6vTci3m3dizkocnQQCOwNbrWWWPYqpWiKzRQ==", + "dev": true, + "requires": { + "@types/d3-dsv": "*" + } + }, + "@types/d3-force": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@types/d3-force/-/d3-force-1.1.1.tgz", + "integrity": "sha512-ePkELuaFWY4yOuf+Bvx5Xd+ihFiYG4bdnW0BlvigovIm8Sob2t76e9RGO6lybQbv6AlW9Icn9HuZ9fmdzEoJyg==", + "dev": true + }, + "@types/d3-format": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@types/d3-format/-/d3-format-1.3.0.tgz", + "integrity": "sha512-ZiY4j3iJvAdOwzwW24WjlZbUNvqOsnPAMfPBmdXqxj3uKJbrzBlRrdGl5uC89pZpFs9Dc92E81KcwG2uEgkIZA==", + "dev": true + }, + "@types/d3-geo": { + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/@types/d3-geo/-/d3-geo-1.10.3.tgz", + "integrity": "sha512-hfdaxM2L0wA9mDZrrSf2o+DyhEpnJYCiAN+lHFtpfZOVCQrYBA5g33sGRpUbAvjSMyO5jkHbftMWPEhuCMChSg==", + "dev": true, + "requires": { + "@types/geojson": "*" + } + }, + "@types/d3-hierarchy": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@types/d3-hierarchy/-/d3-hierarchy-1.1.2.tgz", + "integrity": "sha512-L+Ht4doqlCIH8jYN2AC1mYIOj13OxlRhdWNWXv2pc3o5A9i3YmQ0kz6A7w8c+Ujylfusi/FO+zVlVnQoOHc2Qw==", + "dev": true + }, + "@types/d3-interpolate": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-1.2.0.tgz", + "integrity": "sha512-qM9KlUrqbwIhBRtw9OtAEbkis1AxsOJEun2uxaX/vEsBp3vyNBmhPz9boXXEqic9ZRi7fCpUNRwyZvxa0PioIw==", + "dev": true, + "requires": { + "@types/d3-color": "*" + } + }, + "@types/d3-path": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-1.0.7.tgz", + "integrity": "sha512-U8dFRG+8WhkLJr2sxZ9Cw/5WeRgBnNqMxGdA1+Z0+ZG6tK0s75OQ4OXnxeyfKuh6E4wQPY8OAKr1+iNDx01BEQ==", + "dev": true + }, + "@types/d3-polygon": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-polygon/-/d3-polygon-1.0.6.tgz", + "integrity": "sha512-E6Kyodn9JThgLq20nxSbEce9ow5/ePgm9PX2EO6W1INIL4DayM7cFaiG10DStuamjYAd0X4rntW2q+GRjiIktw==", + "dev": true + }, + "@types/d3-quadtree": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/d3-quadtree/-/d3-quadtree-1.0.5.tgz", + "integrity": "sha1-HOHmWerkUw3wyxJ/KX8XQaNnqC4=", + "dev": true + }, + "@types/d3-random": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@types/d3-random/-/d3-random-1.1.1.tgz", + "integrity": "sha512-jUPeBq1XKK9/5XasTvy5QAUwFeMsjma2yt/nP02yC2Tijovx7i/W5776U/HZugxc5SSmtpx4Z3g9KFVon0QrjQ==", + "dev": true + }, + "@types/d3-scale": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-2.0.1.tgz", + "integrity": "sha512-D5ZWv8ToLvqacE7XkdMNHMiiVDULdDxT7FMMGU0YJC3/nVzBmApjyTyxracUWOQyY3KK7YhZ05on8pOcNi0dfQ==", + "dev": true, + "requires": { + "@types/d3-time": "*" + } + }, + "@types/d3-scale-chromatic": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@types/d3-scale-chromatic/-/d3-scale-chromatic-1.2.0.tgz", + "integrity": "sha512-bhS2SVzUzRtrxp1REhGCfHmj8pyDv9oDmsonYiPvBl8KCxPJTxnfXBF39PzAJrYnRKM41TR0kQzsJvL+NmcDtg==", + "dev": true + }, + "@types/d3-selection": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@types/d3-selection/-/d3-selection-1.3.1.tgz", + "integrity": "sha512-G+eO+2G1iW3GNrROxhoU+ar+bIJbQq1QkxcfhwjQ19xA20n3T31j5pSJqAOWvPSoFTz4Ets/DQgYhmgT4jepDg==", + "dev": true + }, + "@types/d3-shape": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-1.2.3.tgz", + "integrity": "sha512-iP9TcX0EVi+LlX+jK9ceS+yhEz5abTitF+JaO2ugpRE/J+bccaYLe/0/3LETMmdaEkYarIyboZW8OF67Mpnj1w==", + "dev": true, + "requires": { + "@types/d3-path": "*" + } + }, + "@types/d3-time": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-1.0.8.tgz", + "integrity": "sha512-/UCphyyw97YAq4zKsuXH33R3UNB4jDSza0fLvMubWr/ONh9IePi1NbgFP222blhiCe724ebJs8U87+aDuAq/jA==", + "dev": true + }, + "@types/d3-time-format": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/d3-time-format/-/d3-time-format-2.1.0.tgz", + "integrity": "sha512-/myT3I7EwlukNOX2xVdMzb8FRgNzRMpsZddwst9Ld/VFe6LyJyRp0s32l/V9XoUzk+Gqu56F/oGk6507+8BxrA==", + "dev": true + }, + "@types/d3-timer": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-1.0.7.tgz", + "integrity": "sha512-830pT+aYZrgbA91AuynP3KldfB1A1s60d0gKiV+L7JcSKSJapUzUffAm8VZod7RQOxF5SzoItV6cvrTzjbmrJQ==", + "dev": true + }, + "@types/d3-transition": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@types/d3-transition/-/d3-transition-1.1.2.tgz", + "integrity": "sha512-sTENKlKkUaKUYjeYIj69VYIi3VKeBinY/pYdy5VkjNmEOIasUtZIyAY04waMU4Rq7u+czKQdcP7Aoaf5wpDGfA==", + "dev": true, + "requires": { + "@types/d3-selection": "*" + } + }, + "@types/d3-voronoi": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@types/d3-voronoi/-/d3-voronoi-1.1.7.tgz", + "integrity": "sha512-/dHFLK5jhXTb/W4XEQcFydVk8qlIAo85G3r7+N2fkBFw190l0R1GQ8C1VPeXBb2GfSU5GbT2hjlnE7i7UY5Gvg==", + "dev": true + }, + "@types/d3-zoom": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/@types/d3-zoom/-/d3-zoom-1.7.1.tgz", + "integrity": "sha512-Ofjwz6Pt53tRef9TAwwayN+JThNVYC/vFOepa/H4KtwjhsqkmEseHvc2jpJM7vye5PQ5XHtTSOpdY4Y/6xZWEg==", + "dev": true, + "requires": { + "@types/d3-interpolate": "*", + "@types/d3-selection": "*" + } + }, + "@types/geojson": { + "version": "7946.0.4", + "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.4.tgz", + "integrity": "sha512-MHmwBtCb7OCv1DSivz2UNJXPGU/1btAWRKlqJ2saEhVJkpkvqHMMaOpKg0v4sAbDWSQekHGvPVMM8nQ+Jen03Q==", + "dev": true + }, + "typescript": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.9.2.tgz", + "integrity": "sha512-Gr4p6nFNaoufRIY4NMdpQRNmgxVIGMs4Fcu/ujdYk3nAZqk7supzBE9idmvfZIlH/Cuj//dvi+019qEue9lV0w==", + "dev": true + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..9808823 --- /dev/null +++ b/package.json @@ -0,0 +1,20 @@ +{ + "name": "tutorial-conway-life-t3", + "version": "1.0.0", + "description": "For the second tutorial, we're going to work with SVG, and CSS via SASS.", + "main": "gameOfLife.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "git@gitlab.une.edu.au:cosc360in2018/tutorial-conway-life-t2.git" + }, + "author": "", + "license": "ISC", + "devDependencies": { + "@types/d3": "^5.0.0", + "typescript": "^2.9.2" + }, + "dependencies": {} +} diff --git a/render.js b/render.js index 5118aff..1874a42 100644 --- a/render.js +++ b/render.js @@ -1,41 +1,32 @@ "use strict"; - +/// <reference types="d3" /> +var life = new Life(); +var game = d3.select("#game").append("g"); +var cellSize = 20; function render() { - - let xmlns = "http://www.w3.org/2000/svg" - - let cellSize = 20 - - let gameDiv = document.getElementById("game") - gameDiv.innerHTML = "" - - for (let y = 0; y < gameOfLife.getH(); y++) { - let row = document.createElementNS(xmlns, "g") - row.setAttribute("class", "gamerow") - gameDiv.appendChild(row) - - for (let x = 0; x < gameOfLife.getW(); x++) { - - let t = document.createElementNS(xmlns, "rect") - t.setAttribute("x", x * cellSize) - t.setAttribute("y", y * cellSize) - t.setAttribute("width", cellSize) - t.setAttribute("height", cellSize) - t.classList.add("cell") - - if (gameOfLife.isAlive(x, y)) { - t.classList.add("alive") - } - - let handler = function(evt) { - gameOfLife.toggleCell(x, y) - render() - } - - t.addEventListener("mousedown", handler) - - row.appendChild(t) - } - } - -} \ No newline at end of file + console.log("rendering"); + var update = game.selectAll("rect").data(life.board); + update.attr("class", function (d) { + return d ? "cell alive" : "cell"; + }); + update.enter() + .append("rect") + .attr("class", function (d) { + return d ? "cell alive" : "cell"; + }) + .attr("x", function (val, i) { + return life.x(i) * cellSize; + }) + .attr("y", function (val, i) { + return life.y(i) * cellSize; + }) + .attr("width", cellSize) + .attr("height", cellSize) + .on("click", function (d, i) { + var x = life.x(i); + var y = life.y(i); + life.toggleCell(x, y); + render(); + }); +} +//# sourceMappingURL=render.js.map \ No newline at end of file diff --git a/render.ts b/render.ts new file mode 100644 index 0000000..4350c65 --- /dev/null +++ b/render.ts @@ -0,0 +1,37 @@ +/// <reference types="d3" /> + +const life = new Life() +const game = d3.select("#game").append("g") +const cellSize = 20 + +function render() { + console.log("rendering") + + let update = game.selectAll("rect").data(life.board) + + update.attr("class", (d) => { + return d ? "cell alive" : "cell" + }) + + update.enter() + .append("rect") + .attr("class", (d) => { + return d ? "cell alive" : "cell" + }) + .attr("x", (val,i) => { + return life.x(i) * cellSize + }) + .attr("y", (val,i) => { + return life.y(i) * cellSize + }) + .attr("width", cellSize) + .attr("height", cellSize) + .on("click", (d,i) => { + let x = life.x(i) + let y = life.y(i) + life.toggleCell(x,y) + render() + }) + + +} \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..c00ff48 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,59 @@ +{ + "compilerOptions": { + /* Basic Options */ + "target": "es5", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */ + //"module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */ + // "lib": [], /* Specify library files to be included in the compilation. */ + // "allowJs": true, /* Allow javascript files to be compiled. */ + // "checkJs": true, /* Report errors in .js files. */ + // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ + // "declaration": true, /* Generates corresponding '.d.ts' file. */ + // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ + "sourceMap": true, /* Generates corresponding '.map' file. */ + // "outFile": "./", /* Concatenate and emit output to single file. */ + // "outDir": "./", /* Redirect output structure to the directory. */ + // "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ + // "composite": true, /* Enable project compilation */ + // "removeComments": true, /* Do not emit comments to output. */ + // "noEmit": true, /* Do not emit outputs. */ + // "importHelpers": true, /* Import emit helpers from 'tslib'. */ + // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ + // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ + + /* Strict Type-Checking Options */ + "strict": true, /* Enable all strict type-checking options. */ + // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* Enable strict null checks. */ + // "strictFunctionTypes": true, /* Enable strict checking of function types. */ + // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ + // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ + // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ + + /* Additional Checks */ + // "noUnusedLocals": true, /* Report errors on unused locals. */ + // "noUnusedParameters": true, /* Report errors on unused parameters. */ + // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ + // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ + + /* Module Resolution Options */ + // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ + // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ + // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ + // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ + // "typeRoots": [], /* List of folders to include type definitions from. */ + // "types": [], /* Type declaration files to be included in compilation. */ + // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ + "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ + // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ + + /* Source Map Options */ + // "sourceRoot": "./", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ + // "mapRoot": "./", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ + // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ + + /* Experimental Options */ + // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ + // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ + } +} \ No newline at end of file -- GitLab