Initial Source Commit
This commit is contained in:
parent
f27b385066
commit
2eacf58314
10 changed files with 400 additions and 0 deletions
64
lib/game/Game.dart
Normal file
64
lib/game/Game.dart
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
import 'dart:html';
|
||||||
|
|
||||||
|
class Game {
|
||||||
|
List<List<Color>> grid;
|
||||||
|
CanvasElement canvas;
|
||||||
|
CanvasRenderingContext2D ctx;
|
||||||
|
|
||||||
|
double _oscill = 0.0;
|
||||||
|
bool _fwd = true;
|
||||||
|
|
||||||
|
Game(CanvasElement this.canvas) {
|
||||||
|
grid = buildGrid(5,5, new Color(255, 100, 255));
|
||||||
|
ctx = this.canvas.getContext('2d');
|
||||||
|
}
|
||||||
|
|
||||||
|
void update([num dt]) {}
|
||||||
|
|
||||||
|
void draw([num interp]) {
|
||||||
|
// CanvasRenderingContext2D ctx = this.canvas.getContext('2d');
|
||||||
|
// print(grid.toString());
|
||||||
|
int brickW = (canvas.width ~/ grid[0].length);
|
||||||
|
int brickH = (canvas.height ~/ grid.length);
|
||||||
|
|
||||||
|
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||||
|
for(int y=0;y<grid.length;y++) {
|
||||||
|
for(int x=0;x<grid[y].length;x++) {
|
||||||
|
Color col = grid[y][x];
|
||||||
|
ctx.setFillColorRgb(col.r, col.g, col.b);
|
||||||
|
ctx.fillRect(x*brickW, y*brickH, brickW, brickH);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Color _oscillate(Color) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
List<List<Color>> buildGrid(int w, int h, Color col) {
|
||||||
|
List<List<Color>> grid = new List(h);
|
||||||
|
|
||||||
|
|
||||||
|
for(int y = 0; y< h; y++) {
|
||||||
|
grid[y] = new List(w);
|
||||||
|
for(int x = 0; x< w; x++) {
|
||||||
|
grid[y][x] = col;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return grid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Color {
|
||||||
|
final int r;
|
||||||
|
final int g;
|
||||||
|
final int b;
|
||||||
|
|
||||||
|
const Color(this.r, this.g, this.b);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create 2d array
|
||||||
|
// fill with random colors
|
||||||
|
// cycle colors
|
||||||
|
// set one color to random new one
|
8
lib/game/LoopExample.dart
Normal file
8
lib/game/LoopExample.dart
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
import 'package:browserloop/game/Game.dart';
|
||||||
|
|
||||||
|
abstract class LoopExample{
|
||||||
|
Game game;
|
||||||
|
|
||||||
|
void stop() {}
|
||||||
|
void start() {}
|
||||||
|
}
|
64
lib/src/00-oldcode.dart
Normal file
64
lib/src/00-oldcode.dart
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
import 'dart:html' as html;
|
||||||
|
import 'dart:math' as math;
|
||||||
|
|
||||||
|
html.CanvasRenderingContext2D ctx;
|
||||||
|
html.CanvasElement el;
|
||||||
|
|
||||||
|
math.Random rng = new math.Random();
|
||||||
|
int GRIDNUM = 10;
|
||||||
|
int animID = 0;
|
||||||
|
|
||||||
|
// These are the functions to start the animation and stop the animation.
|
||||||
|
// (They are connected to the start/stop buttons in the demo setup.)
|
||||||
|
var _stop = () => html.window.cancelAnimationFrame(animID);
|
||||||
|
var _start = () => html.window.requestAnimationFrame(eventloop);
|
||||||
|
|
||||||
|
// This is what ticks every frame of the animation.
|
||||||
|
void eventloop(currentTime) {
|
||||||
|
print(currentTime.toString());
|
||||||
|
ctx.setFillColorRgb(rng.nextInt(255), rng.nextInt(255), rng.nextInt(255));
|
||||||
|
int BRICKSIZE = (el.width ~/ GRIDNUM);
|
||||||
|
int x = rng.nextInt(GRIDNUM) * BRICKSIZE;
|
||||||
|
int y = rng.nextInt(GRIDNUM) * BRICKSIZE;
|
||||||
|
ctx.fillRect(x, y, (BRICKSIZE), (BRICKSIZE));
|
||||||
|
|
||||||
|
animID = html.window.requestAnimationFrame(
|
||||||
|
eventloop); // recursive call to our eventloop - calls it forever as soon as browser is willing to give us his time
|
||||||
|
}
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
_demoSetup();
|
||||||
|
}
|
||||||
|
|
||||||
|
//buttons and canvas setup
|
||||||
|
void _demoSetup() {
|
||||||
|
el = new html.CanvasElement(width: 480, height: 480);
|
||||||
|
html.querySelector('#basic_output').append(el);
|
||||||
|
ctx = el.getContext('2d');
|
||||||
|
var _clear = () {
|
||||||
|
_stop();
|
||||||
|
ctx.setFillColorRgb(rng.nextInt(255), rng.nextInt(255), rng.nextInt(255));
|
||||||
|
ctx.fillRect(0, 0, el.width, el.height);
|
||||||
|
ctx.setFillColorRgb(rng.nextInt(255), rng.nextInt(255), rng.nextInt(255));
|
||||||
|
};
|
||||||
|
var _changeGrid = (int delta) {
|
||||||
|
_clear();
|
||||||
|
int newgrid = GRIDNUM + delta;
|
||||||
|
GRIDNUM = (newgrid == 0) ? GRIDNUM : newgrid;
|
||||||
|
_start();
|
||||||
|
};
|
||||||
|
_clear();
|
||||||
|
|
||||||
|
html.querySelector('#basic_start').onClick.listen((e) {
|
||||||
|
print('started');
|
||||||
|
_stop();
|
||||||
|
_start();
|
||||||
|
});
|
||||||
|
html.querySelector('#basic_stop').onClick.listen((e) => _stop());
|
||||||
|
html
|
||||||
|
.querySelector('#basic_reset')
|
||||||
|
.onClick
|
||||||
|
.listen((e) => _clear());
|
||||||
|
html.querySelector('#basic_plus').onClick.listen((e) => _changeGrid(-5));
|
||||||
|
html.querySelector('#basic_minus').onClick.listen((e) => _changeGrid(5));
|
||||||
|
}
|
31
lib/src/01-WhileLoop.dart
Normal file
31
lib/src/01-WhileLoop.dart
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
import 'package:browserloop/game/Game.dart';
|
||||||
|
import 'package:browserloop/game/LoopExample.dart';
|
||||||
|
|
||||||
|
/// The most basic update loop possible.
|
||||||
|
///
|
||||||
|
/// Best not to use this loop since it has a tendency to
|
||||||
|
/// crash your browser and not load correctly at all.
|
||||||
|
/// The way to get this to run would be the setInterval method
|
||||||
|
/// simple is either through setInterval in Javascript:
|
||||||
|
/// https://www.w3schools.com/howto/howto_js_animate.asp
|
||||||
|
/// or through the Timer API in Dart, especially
|
||||||
|
/// with Timer.periodic(16, callbackFunction);
|
||||||
|
/// To see how I got it running for the example,
|
||||||
|
/// see file 02-AnimationFrameWhile.dart
|
||||||
|
class WhileLoop implements LoopExample {
|
||||||
|
Game game;
|
||||||
|
|
||||||
|
WhileLoop(Game this.game) {
|
||||||
|
eventloop();
|
||||||
|
}
|
||||||
|
|
||||||
|
void eventloop() {
|
||||||
|
while(true) {
|
||||||
|
game.update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void update() {
|
||||||
|
print("i am updating");
|
||||||
|
}
|
||||||
|
}
|
32
lib/src/02-AnimationFrameWhile.dart
Normal file
32
lib/src/02-AnimationFrameWhile.dart
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
import 'dart:html';
|
||||||
|
import 'package:browserloop/game/Game.dart';
|
||||||
|
import 'package:browserloop/game/LoopExample.dart';
|
||||||
|
|
||||||
|
/// The most basic update loop possible.
|
||||||
|
///
|
||||||
|
/// Note that this is technically cheating since it is using
|
||||||
|
/// animationFrames to improve browser performance for the examples in the
|
||||||
|
/// blog post. The real, actual simplest code is in file 01-WhileLoop.dart
|
||||||
|
class WhileLoop implements LoopExample {
|
||||||
|
Game game;
|
||||||
|
num id;
|
||||||
|
|
||||||
|
WhileLoop(Game this.game) {
|
||||||
|
window.requestAnimationFrame(eventloop);
|
||||||
|
}
|
||||||
|
|
||||||
|
void eventloop(num time) {
|
||||||
|
game.update();
|
||||||
|
game.draw();
|
||||||
|
|
||||||
|
id = window.requestAnimationFrame(eventloop);
|
||||||
|
}
|
||||||
|
|
||||||
|
void stop() {
|
||||||
|
window.cancelAnimationFrame(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void start() {
|
||||||
|
window.requestAnimationFrame(eventloop);
|
||||||
|
}
|
||||||
|
}
|
52
lib/src/03-FixedLoopVariableRender.dart
Normal file
52
lib/src/03-FixedLoopVariableRender.dart
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
import 'dart:html';
|
||||||
|
|
||||||
|
import 'package:browserloop/game/Game.dart';
|
||||||
|
import 'package:browserloop/game/LoopExample.dart';
|
||||||
|
|
||||||
|
class FixedLoopVariableRender implements LoopExample {
|
||||||
|
static final double MS_PER_UPDATE = 1000.0;
|
||||||
|
static final double SAFE_GUARD = 500.0;
|
||||||
|
Stopwatch elapsed = new Stopwatch();
|
||||||
|
double lag = 0.0;
|
||||||
|
Game game;
|
||||||
|
num id;
|
||||||
|
|
||||||
|
FixedLoopVariableRender(this.game) {
|
||||||
|
|
||||||
|
elapsed.start();
|
||||||
|
window.requestAnimationFrame(eventloop);
|
||||||
|
}
|
||||||
|
|
||||||
|
void eventloop(num time) {
|
||||||
|
lag += elapsed.elapsedMilliseconds;
|
||||||
|
elapsed.reset();
|
||||||
|
|
||||||
|
while (lag >= MS_PER_UPDATE && elapsed.elapsedMilliseconds < SAFE_GUARD) {
|
||||||
|
update();
|
||||||
|
lag -= MS_PER_UPDATE;
|
||||||
|
}
|
||||||
|
render(lag / MS_PER_UPDATE);
|
||||||
|
id = window.requestAnimationFrame(eventloop);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void update() {
|
||||||
|
print('updating');
|
||||||
|
game.update();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void render(double interp) {
|
||||||
|
print('rendering, interp:$interp');
|
||||||
|
game.draw(interp);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void stop() {
|
||||||
|
window.cancelAnimationFrame(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void start() {
|
||||||
|
window.requestAnimationFrame(eventloop);
|
||||||
|
}
|
||||||
|
}
|
15
pubspec.yaml
Normal file
15
pubspec.yaml
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
name: browserloop
|
||||||
|
description: An absolute bare-bones web app.
|
||||||
|
version: 0.0.1
|
||||||
|
#homepage: https://www.example.com
|
||||||
|
#author: marty <email@example.com>
|
||||||
|
|
||||||
|
environment:
|
||||||
|
sdk: '>=2.0.0-dev.67.0 <3.0.0'
|
||||||
|
|
||||||
|
#dependencies:
|
||||||
|
# path: ^1.4.1
|
||||||
|
|
||||||
|
dev_dependencies:
|
||||||
|
build_runner: ^0.9.0
|
||||||
|
build_web_compilers: ^0.4.0
|
1
web/favicon.ico
Normal file
1
web/favicon.ico
Normal file
|
@ -0,0 +1 @@
|
||||||
|
|
23
web/index.html
Normal file
23
web/index.html
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Browserloop</title>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<!--<link rel="stylesheet" href="styles.css">-->
|
||||||
|
<!--<link rel="icon" type="image/png" href="favicon.png">-->
|
||||||
|
|
||||||
|
<script defer src="main.dart.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<!--Basic Game-loop-->
|
||||||
|
<div id="while_output"></div>
|
||||||
|
<div id="variable_output"></div>
|
||||||
|
<!--<button id="basic_start">start</button>-->
|
||||||
|
<!--<button id="basic_stop">stop</button>-->
|
||||||
|
<!--<button id="basic_reset">reset</button>-->
|
||||||
|
<!--<button id="basic_plus">+</button>-->
|
||||||
|
<!--<button id="basic_minus">-</button>-->
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
110
web/main.dart
Normal file
110
web/main.dart
Normal file
|
@ -0,0 +1,110 @@
|
||||||
|
import 'dart:html';
|
||||||
|
import 'package:browserloop/game/Game.dart';
|
||||||
|
import 'package:browserloop/game/LoopExample.dart';
|
||||||
|
import 'package:browserloop/src/03-FixedLoopVariableRender.dart';
|
||||||
|
import 'package:browserloop/src/02-AnimationFrameWhile.dart';
|
||||||
|
|
||||||
|
List<Example> examples = [
|
||||||
|
Example("While Loop Example","#while_output"),
|
||||||
|
Example("Fixed Update, Variable Render","#variable_output")
|
||||||
|
];
|
||||||
|
LoopExample active;
|
||||||
|
|
||||||
|
class Example {
|
||||||
|
final String query;
|
||||||
|
final String name;
|
||||||
|
CanvasElement canvas = CanvasElement(width: 480, height: 480);
|
||||||
|
LoopExample loop;
|
||||||
|
|
||||||
|
Example(this.name, this.query);
|
||||||
|
}
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
examples.forEach((ex) {
|
||||||
|
appendToDOM(ex);
|
||||||
|
});
|
||||||
|
resetPlaceHolders();
|
||||||
|
}
|
||||||
|
|
||||||
|
void appendToDOM(Example example) {
|
||||||
|
querySelector(example.query).append(example.canvas);
|
||||||
|
example.canvas.onClick.forEach(activate);
|
||||||
|
print("${example.query} appended");
|
||||||
|
}
|
||||||
|
|
||||||
|
void readdToDOM(Example example) {
|
||||||
|
querySelector(example.query).children.clear();
|
||||||
|
print("${example.query} removed");
|
||||||
|
appendToDOM(example);
|
||||||
|
}
|
||||||
|
|
||||||
|
void resetPlaceHolders([Example current]) {
|
||||||
|
examples.forEach((Example ex) {
|
||||||
|
if(current == null || ex != current) {
|
||||||
|
if(ex.loop != null) {
|
||||||
|
ex.loop.stop();
|
||||||
|
ex.loop = null;
|
||||||
|
}
|
||||||
|
ex.canvas = new CanvasElement(width: ex.canvas.width,height: ex.canvas.height);
|
||||||
|
readdToDOM(ex);
|
||||||
|
|
||||||
|
CanvasRenderingContext2D ctx = ex.canvas.context2D;
|
||||||
|
Point c = Point(ex.canvas.width/2, ex.canvas.height/2);
|
||||||
|
ctx.setFillColorRgb(255, 150, 10);
|
||||||
|
ctx.fillRect(0, 0, ex.canvas.width, ex.canvas.height);
|
||||||
|
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.moveTo(c.x-25, c.y-25);
|
||||||
|
ctx.lineTo(c.x+25, c.y+25);
|
||||||
|
ctx.lineTo(c.x-25, c.y+75);
|
||||||
|
ctx.closePath();
|
||||||
|
ctx.lineWidth = 10;
|
||||||
|
ctx.setStrokeColorRgb(155, 155, 155);
|
||||||
|
ctx.setFillColorRgb(255, 255, 255);
|
||||||
|
ctx.stroke();
|
||||||
|
ctx.fill();
|
||||||
|
ctx.fillText(ex.name, c.x - ctx.measureText(ex.name).width/2, c.y - 50);
|
||||||
|
|
||||||
|
print("reset ${ex.query}");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void activate(MouseEvent e) {
|
||||||
|
if(e.target is! CanvasElement) return;
|
||||||
|
CanvasElement c = (e.target as CanvasElement);
|
||||||
|
|
||||||
|
examples.forEach((Example ex) {
|
||||||
|
if (ex.canvas == c) {
|
||||||
|
resetPlaceHolders(ex);
|
||||||
|
switch (ex.query) {
|
||||||
|
case "#while_output":
|
||||||
|
ex.loop = new WhileLoop(new Game(c));
|
||||||
|
break;
|
||||||
|
case "#variable_output":
|
||||||
|
ex.loop = new FixedLoopVariableRender(new Game(c));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
querySelector(ex.query).append(new ButtonElement()
|
||||||
|
..text = "start"
|
||||||
|
..onClick.listen((e) {
|
||||||
|
ex.loop.stop();
|
||||||
|
ex.loop.start();
|
||||||
|
}));
|
||||||
|
querySelector(ex.query).append(new ButtonElement()
|
||||||
|
..text = "stop"
|
||||||
|
..onClick.listen((e) {
|
||||||
|
ex.loop.stop();
|
||||||
|
}));
|
||||||
|
// querySelector('#reset').onClick.listen((e) => ex.loop.game.reset());
|
||||||
|
// querySelector('#plus').onClick.listen((e) => _changeGrid(-5));
|
||||||
|
// querySelector('#minus').onClick.listen((e) => _changeGrid(5));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//when a button is clicked delete all the other Loops containing games and replace them with a canvas (fn above)
|
Loading…
Reference in a new issue