import 'dart:html'; import 'dart:math'; typedef void gridIterator(int x, int y); class Game { List> grid; CanvasElement canvas; Random rng = new Random(); double _oscill = 0.1; bool _oscillDir = true; // oscillate upwards (true) or downwards (false) double _OSCILLSPEED = 1.0; bool _fwd = true; Point _curPos = Point(-1, 0); bool isRandom = false; Game(CanvasElement this.canvas) { grid = _buildGrid(5, new Color(255, 255, 255)); } // In-World Logic Updates void update([int speed]) { Point next = isRandom ? nextPosRandom() : nextPosOrdered(_curPos); if (_curPos.x < 0) _curPos = Point(0, _curPos.y); Color newColor = isRandom ? randomColor() : nextColor( grid[_curPos.y][_curPos.x], step: speed ?? 1); grid[next.y][next.x] = newColor; _curPos = next; } Point nextPosOrdered(Point curPos) { Point pos = Point(curPos.x, curPos.y); pos = Point(pos.x + 1, pos.y); if (pos.x >= grid[pos.y].length) pos = Point(0, pos.y + 1); if (pos.y >= grid.length) pos = Point(0, 0); return pos; } Point nextPosRandom() { int ry = rng.nextInt(grid.length); return Point(rng.nextInt(grid[ry].length), ry); } Color randomColor([int max = 255]) { return new Color(rng.nextInt(max), rng.nextInt(max), rng.nextInt(max)); } Color nextColor(Color col, {int step = 1}) { if (col.r > 254 || col.g > 254 || col.b > 254) return randomColor(100); if (col.r > col.g && col.r > col.b) return Color(col.r + step, col.g, col.b); else if (col.b > col.r && col.b > col.g) return Color(col.r, col.g, col.b + step); else return Color(col.r, col.g + step, col.b); } // Render Pipeline void draw([num interp]) { CanvasRenderingContext2D ctx = this.canvas.context2D; int brickW = (canvas.width ~/ grid[0].length); int brickH = (canvas.height ~/ grid.length); ctx.clearRect(0, 0, canvas.width, canvas.height); _grid_foreach((x, y) { Color col = _getOscillatedCol(grid[y][x]); ctx.setFillColorRgb(col.r, col.g, col.b); ctx.fillRect(x * brickW, y * brickH, brickW, brickH); }); // This should usually be place in update() // Placed here to highlight render speed changes for some examples // See variable timestep & dirty flag Loops for details _oscillate(); } // Slightly oscillating colors to highlight rendering updates void _oscillate() { if (_oscill >= 50.0 || _oscill <= -50.0) { _oscillDir = !_oscillDir; _oscill = max(min(_oscill, 49.0), -49.0); } else _oscillDir == true ? _oscill += _OSCILLSPEED : _oscill -= _OSCILLSPEED; } Color _getOscillatedCol(Color col) { int o = _oscill.toInt(); return new Color(col.r + o, col.g + o, col.b + o); } void _grid_foreach(gridIterator fun) { for (int y = 0; y < grid.length; y++) { for (int x = 0; x < grid[y].length; x++) { fun(x, y); } } } List> _buildGrid(int size, Color col) { List> grid = new List(size); for (int y = 0; y < size; y++) { grid[y] = new List(size); for (int x = 0; x < size; x++) { grid[y][x] = col; } } return grid; } // Grid Size Button Implementation // true makes squares larger // false makes squares smaller void changeGridSize(bool larger) { if (larger) { if (grid.length <= 5) return; this.grid = _buildGrid(grid.length - 5, Color(255, 255, 255)); } else { if (grid.length >= 60) return; this.grid = _buildGrid(grid.length + 5, Color(255, 255, 255)); } } void toggleRandomOrder() { isRandom = !isRandom; } } class Color { final int r; final int g; final int b; const Color(this.r, this.g, this.b); @override String toString() { return "Color: (r:$r, g:$g, b:$b)"; } }