Just thought I would try out Dart with canvas for a bit. So far loving the class structure (much alike java etc).
Heres a small snippet with rather basic bouncing animation of a bunch of circles in the browser window. I really need to get better at collision detection but just cant seem to easilly grasp circle to circle even though its arguably the most simplest. Heads to simple.wikipedia.org.
But yeah load this snippet into the dart editor or visit:
http://plornt.com/FallDown.html
To view and get HTML source...
#import('dart:html');
#import('dart:math');
void main() {
//Begin Game
new Game.create (query("#falldown"), _fullscreen: true);
}
class Drawable {
double _x, _y;
Game _g;
bool needsUpdate = false, markDead = false;
Drawable () {
}
void update (double time) {
//Do nothing...
print("Warning - drawable has no update method");
}
void draw (CanvasRenderingContext2D ctx) {
//Do nothing...
print("Warning - drawable has no draw method but has requested a draw");
}
}
class Ball extends Drawable {
double vel_X, vel_Y, massAndSize;
static List<Ball> balls = new List<Ball>();
String _colour;
Ball (Game g, double x, double y, [double this.vel_X = 0.0, double this.vel_Y = 0.0]) {
this._g = g;
this.massAndSize = (_g.rng.nextInt(30) + 10).toDouble();
this._x = (x > (_g.getAppWidth() - massAndSize) ? _g.getAppWidth() - massAndSize - 1 : (x < massAndSize ? massAndSize + 1 : x));
this._y = y;
_colour = get_random_color();
balls.addLast(this);
needsUpdate = true;
}
String get_random_color() {
//http://stackoverflow.com/questions/1484506/random-color-generator-in-javascript
List<String> letters = '0123456789ABCDEF'.split('');
String colour = '#';
for (var i = 0; i < 6; i++ ) {
colour = "${colour}${letters[_g.rng.nextInt(letters.length - 1)]}";
}
return colour;
}
void update (double secondsSinceLastFrame) {
vel_Y = vel_Y + (9.1 * secondsSinceLastFrame);
if (vel_X > 0) vel_X = vel_X - (3.0 * secondsSinceLastFrame);
else if (vel_X < 0) vel_X = vel_X + (3.0 * secondsSinceLastFrame);
if (vel_Y < -30.0) vel_Y = -30.0;
if (_y > (_g.getAppHeight() - this.massAndSize) || _y < this.massAndSize) vel_Y = -(vel_Y);
if (_x < this.massAndSize || _x > (_g.getAppWidth()- this.massAndSize)) vel_X = -(vel_X);
this._x = this._x + (vel_X * secondsSinceLastFrame * 30.0);
this._y = this._y + (vel_Y * secondsSinceLastFrame * 30.0);
}
void draw (CanvasRenderingContext2D ctx) {
ctx.beginPath();
ctx.arc(_x, _y, this.massAndSize, 0, 6.28318530718, true);
ctx.closePath();
ctx.fillStyle = _colour;
ctx.fill();
}
}
class Game {
CanvasElement _canvas;
CanvasRenderingContext2D _context;
List<Drawable> _objects = new List<Drawable>();
int _timeoflastfpscount = 0, _frameCount = 0, _prevInfo = 0, _sizeX, _sizeY, previousTime = new Date.now().millisecondsSinceEpoch;
bool _fullscreen = false, _schResize = false;
Random rng = new Random();
Game.create (CanvasElement this._canvas, [int this._sizeX, int this._sizeY, bool this._fullscreen]) {
if (_fullscreen) {
_sizeX = window.innerWidth;
_sizeY = window.innerHeight;
window.on.resize.add((event) {
_sizeX = window.innerWidth;
_sizeY = window.innerHeight;
_schResize = true;
});
}
//Initialise the Canvas
_canvas.height = _sizeY;
_canvas.width = _sizeX;
_context = _canvas.context2d;
for (int x = 0; x < 150; x++) {
this.spawn(new Ball(this, rng.nextDouble() * getAppWidth().toDouble(), rng.nextDouble() * getAppHeight().toDouble(), (rng.nextDouble() * 120) - 60) as Drawable);
}
//Start our animation loop
window.requestAnimationFrame(this.tick);
}
int getAppWidth () {
return _sizeX;
}
int getAppHeight () {
return _sizeY;
}
void updateFPS (int time, CanvasRenderingContext2D ctx) {
_frameCount++;
int sinceLast = (time - _timeoflastfpscount);
if (sinceLast >= 1000) {
_prevInfo = ((_frameCount / sinceLast) * 1000).round().toInt();
_frameCount = 0;
_timeoflastfpscount = time;
}
ctx.font = "12px 'Open Sans'";
ctx.fillStyle = "red";
ctx.fillText("${_prevInfo.toString()} FPS - Frames drawn since last: ${_frameCount}", 0, 16, this._sizeX);
}
void clear(CanvasRenderingContext2D ctx) {
ctx.fillStyle = "white";
ctx.rect(0, 0, _sizeX, _sizeY);
ctx.fill();
}
void spawn (Drawable d) {
_objects.addLast(d);
}
void update (List<Drawable> obj, double secondsSinceLastFrame) {
if (!obj.isEmpty()) {
int i = 0;
obj.forEach((Drawable d) {
if (d.needsUpdate) { d.update(secondsSinceLastFrame); }
if (d.markDead) {
obj.removeAt(i);
i--;
}
i++;
});
}
}
void draw (List<Drawable> obj, CanvasRenderingContext2D ctx) {
if (!obj.isEmpty()) {
obj.forEach((Drawable d) {
d.draw(ctx);
});
}
}
bool tick (int time) {
if (time == null) {
time = new Date.now().millisecondsSinceEpoch;
}
//Draw the frame
if (!_schResize) clear(_context);
else {
_canvas.height = _sizeY;
_canvas.width = _sizeX;
}
update(_objects, ((time - previousTime).toDouble() / 1000));
draw(_objects, _context);
//Show our FPS on the canvas passing along the time at the begining
updateFPS(time, _context);
//Request the next frame!
previousTime = time;
window.requestAnimationFrame(this.tick);
}
}