Skip to content

Instantly share code, notes, and snippets.

@adam-singer
Created October 4, 2013 16:39
Show Gist options
  • Save adam-singer/6828870 to your computer and use it in GitHub Desktop.
Save adam-singer/6828870 to your computer and use it in GitHub Desktop.
library floodfill;
import 'dart:html';
//import 'dart:async';
import 'dart:collection';
CanvasElement canvas;
CanvasRenderingContext2D context;
List<List<int>> world;
//Timer running;
Vector mouse, currentTilePosition, previousTilePosition;
int width = 480, height = 480, FPS = 60;
void main() {
mouse = new Vector.zero();
previousTilePosition = new Vector.zero();
canvas = new CanvasElement(width: width, height: height);
query('body').children.add(canvas);
context = canvas.getContext("2d");
canvas
..onMouseMove.listen((event) => onMouseMove(event))
..onMouseDown.listen((event) => onMouseDown(event))
..onMouseUp.listen((event) => onMouseUp(event))
..onContextMenu.listen((event) => event.preventDefault());
world = new List<List<int>>(30);
for (var y = 0; y < 30; y++) {
world[y] = new List<int>(30);
for (var x = 0; x < 30; x++) {
world[y][x] = 0;
}
}
//running = new Timer.periodic(new Duration(milliseconds: 1000 ~/ FPS), (Timer timer) => update());
window.requestAnimationFrame(draw);
}
void update() {
}
void draw(num _) {
for (var y = 0; y < 30; y++) {
for (var x = 0; x < 30; x++) {
if (world[x][y] == 0)
context.fillStyle = '#999';
else if (world[x][y] == 1)
context.fillStyle = '#ccc';
else if (world[x][y] == 2)
context.fillStyle = '#00f';
else if (world[x][y] == 3)
context.fillStyle = '#09f';
context
..beginPath()
..rect(x * 16, y * 16, 16, 16)
..fill()
..lineWidth = 1
..strokeStyle = '#333'
..stroke();
}
}
window.requestAnimationFrame(draw);
}
void updateMouse(MouseEvent evt) {
mouse.x = evt.client.x - canvas.getBoundingClientRect().left;
mouse.y = evt.client.y - canvas.getBoundingClientRect().top;
currentTilePosition = getHoveredTilePosition();
}
void onMouseMove(MouseEvent evt) {
updateMouse(evt);
setTile(evt);
// only flood fill when a mouse button is pressed and the tile has changed
if (evt.which != 0)
if (currentTilePosition.x != previousTilePosition.x || currentTilePosition.y != previousTilePosition.y) {
previousTilePosition = currentTilePosition;
floodFill();
}
}
void onMouseDown(MouseEvent evt) {
// prevent the mouse cursor from changing
evt.preventDefault();
}
void onMouseUp(MouseEvent evt) {
setTile(evt);
floodFill();
}
void setTile(MouseEvent evt) {
if (evt.which == 1) {
world[currentTilePosition.x][currentTilePosition.y] = 1;
}
else if (evt.which == 2) {
world[currentTilePosition.x][currentTilePosition.y] = 2;
}
else if (evt.which == 3) {
world[currentTilePosition.x][currentTilePosition.y] = 0;
}
}
void floodFill() {
Queue<Vector> queue = new Queue();
for (var y = 0; y < 30; y++) {
for (var x = 0; x < 30; x++) {
// reset status
if (world[x][y] == 3)
world[x][y] = 1;
// add sources to queue
if (world[x][y] == 2)
queue.add(new Vector(x, y));
}
}
while(queue.length > 0) {
Vector currentTile = queue.removeFirst();
if (world[currentTile.x][currentTile.y] == 1 || world[currentTile.x][currentTile.y] == 2) {
if (world[currentTile.x][currentTile.y] == 1)
world[currentTile.x][currentTile.y] = 3;
if (currentTile.x - 1 > -1)
queue.add(new Vector(currentTile.x - 1, currentTile.y));
if (currentTile.y - 1 > -1)
queue.add(new Vector(currentTile.x, currentTile.y - 1));
if (currentTile.x + 1 < 30)
queue.add(new Vector(currentTile.x + 1, currentTile.y));
if (currentTile.y + 1 < 30)
queue.add(new Vector(currentTile.x, currentTile.y + 1));
}
}
}
Vector getHoveredTilePosition() {
return new Vector(
mouse.x ~/ 16,
mouse.y ~/ 16);
}
class Vector {
num x, y;
Vector(this.x, this.y);
Vector.zero() : x = 0, y = 0;
Vector operator +(Vector other) => new Vector(x + other.x, y + other.y);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment