
Code outside of package:sky should import this code using package:sky/rendering.dart package:sky/widgets.dart Moving this code into the "src" directory is a convention that signifies that and it cleans up the generated dartdoc because the libraries in the src directory aren't included in the generated documentation. Instead, the classes are documented in the widgets.dart and rendering.dart libraries.
309 lines
8.5 KiB
Dart
309 lines
8.5 KiB
Dart
import 'dart:sky' as sky;
|
|
import 'dart:math' as math;
|
|
|
|
import 'package:sky/mojo/asset_bundle.dart';
|
|
import 'package:sky/rendering.dart';
|
|
import 'package:sky/theme/colors.dart' as colors;
|
|
import 'package:sky/widgets.dart';
|
|
import 'package:skysprites/skysprites.dart';
|
|
|
|
AssetBundle _initBundle() {
|
|
if (rootBundle != null)
|
|
return rootBundle;
|
|
return new NetworkAssetBundle(Uri.base);
|
|
}
|
|
|
|
final AssetBundle _bundle = _initBundle();
|
|
|
|
ImageMap _images;
|
|
SpriteSheet _spriteSheet;
|
|
TestApp _app;
|
|
|
|
main() async {
|
|
_images = new ImageMap(_bundle);
|
|
|
|
await _images.load([
|
|
'assets/sprites.png'
|
|
]);
|
|
|
|
String json = await _bundle.loadString('assets/sprites.json');
|
|
_spriteSheet = new SpriteSheet(_images['assets/sprites.png'], json);
|
|
|
|
_app = new TestApp();
|
|
runApp(_app);
|
|
}
|
|
|
|
class TestApp extends App {
|
|
|
|
Widget build() {
|
|
ThemeData theme = new ThemeData(
|
|
brightness: ThemeBrightness.light,
|
|
primarySwatch: colors.Purple
|
|
);
|
|
|
|
return new Theme(
|
|
data: theme,
|
|
child: new Title(
|
|
title: 'Test Sprite Performance',
|
|
child: new SpriteWidget(new TestPerformance())
|
|
)
|
|
);
|
|
}
|
|
}
|
|
|
|
class TestPerformance extends NodeWithSize {
|
|
final int numFramesPerTest = 100;
|
|
final int numTests = 5;
|
|
|
|
TestPerformance() : super(new Size(1024.0, 1024.0)) {
|
|
}
|
|
|
|
int test = 0;
|
|
int frame = 0;
|
|
int testStartTime;
|
|
|
|
void update(double dt) {
|
|
if (frame % numFramesPerTest == 0) {
|
|
if (test > 0 && test <= numTests) {
|
|
// End last test
|
|
int currentTime = new DateTime.now().millisecondsSinceEpoch;
|
|
int totalTestTime = currentTime - testStartTime;
|
|
double millisPerFrame =
|
|
totalTestTime.toDouble() / numFramesPerTest.toDouble();
|
|
print(" - RESULT fps: ${(1.0 / (millisPerFrame / 1000)).toStringAsFixed(1)} millis/frame: ${millisPerFrame.round()}");
|
|
|
|
// Clear test
|
|
removeAllChildren();
|
|
}
|
|
|
|
if (test < numTests) {
|
|
// Start new test
|
|
PerformanceTest perfTest = createTest(test);
|
|
addChild(perfTest);
|
|
|
|
print("TEST ${test + 1}/$numTests STARTING: ${perfTest.name}");
|
|
|
|
testStartTime = new DateTime.now().millisecondsSinceEpoch;
|
|
}
|
|
test++;
|
|
}
|
|
frame++;
|
|
}
|
|
|
|
PerformanceTest createTest(int n) {
|
|
if (test == 0) {
|
|
// Test atlas performance
|
|
return new TestPerformanceAtlas();
|
|
} else if (test == 1) {
|
|
// Test atlas performance
|
|
return new TestPerformanceAtlas2();
|
|
} else if (test == 2) {
|
|
// Test sprite performance
|
|
return new TestPerformanceSprites();
|
|
} else if (test == 3) {
|
|
// Test sprite performance
|
|
return new TestPerformanceSprites2();
|
|
} else if (test == 4) {
|
|
// Test particle performance
|
|
return new TestPerformanceParticles();
|
|
}
|
|
return null;
|
|
}
|
|
}
|
|
|
|
abstract class PerformanceTest extends Node {
|
|
String get name;
|
|
}
|
|
|
|
class TestPerformanceParticles extends PerformanceTest {
|
|
String get name => "64 particle systems";
|
|
|
|
final grid = 8;
|
|
TestPerformanceParticles() {
|
|
for (int x = 0; x < grid; x++) {
|
|
for (int y = 0; y < grid; y++) {
|
|
ParticleSystem particles = new ParticleSystem(
|
|
_spriteSheet["explosion_particle.png"],
|
|
rotateToMovement: true,
|
|
startRotation:90.0,
|
|
startRotationVar: 0.0,
|
|
endRotation: 90.0,
|
|
startSize: 0.3,
|
|
startSizeVar: 0.1,
|
|
endSize: 0.3,
|
|
endSizeVar: 0.1,
|
|
emissionRate:100.0,
|
|
greenVar: 127,
|
|
redVar: 127
|
|
);
|
|
particles.position = new Point(x * 1024.0 / (grid - 1), y * 1024.0 / (grid - 1));
|
|
addChild(particles);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
class TestPerformanceSprites extends PerformanceTest {
|
|
String get name => "1001 sprites (24% offscreen)";
|
|
|
|
final int grid = 100;
|
|
|
|
TestPerformanceSprites() {
|
|
for (int x = 0; x < grid; x++) {
|
|
for (int y = 0; y < grid; y++) {
|
|
Sprite sprt = new Sprite(_spriteSheet["asteroid_big_1.png"]);
|
|
sprt.scale = 1.0;
|
|
sprt.position = new Point(x * 1024.0 / (grid - 1), y * 1024.0 / (grid - 1));
|
|
addChild(sprt);
|
|
|
|
//sprt.actions.run(new ActionRepeatForever(new ActionTween((a) => sprt.rotation = a, 0.0, 360.0, 1.0)));
|
|
}
|
|
}
|
|
|
|
Sprite sprt = new Sprite(_spriteSheet["asteroid_big_1.png"]);
|
|
sprt.position = new Point(512.0, 512.0);
|
|
addChild(sprt);
|
|
}
|
|
|
|
void update(double dt) {
|
|
for (Sprite sprt in children) {
|
|
sprt.rotation += 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
class TestPerformanceSprites2 extends PerformanceTest {
|
|
String get name => "1001 sprites (24% offscreen never added)";
|
|
|
|
final int grid = 100;
|
|
|
|
TestPerformanceSprites2() {
|
|
for (int x = 12; x < grid - 12; x++) {
|
|
for (int y = 0; y < grid; y++) {
|
|
Sprite sprt = new Sprite(_spriteSheet["asteroid_big_1.png"]);
|
|
sprt.scale = 1.0;
|
|
sprt.position = new Point(x * 1024.0 / (grid - 1), y * 1024.0 / (grid - 1));
|
|
addChild(sprt);
|
|
|
|
//sprt.actions.run(new ActionRepeatForever(new ActionTween((a) => sprt.rotation = a, 0.0, 360.0, 1.0)));
|
|
}
|
|
}
|
|
|
|
Sprite sprt = new Sprite(_spriteSheet["asteroid_big_1.png"]);
|
|
sprt.position = new Point(512.0, 512.0);
|
|
addChild(sprt);
|
|
}
|
|
|
|
void update(double dt) {
|
|
for (Sprite sprt in children) {
|
|
sprt.rotation += 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
class TestPerformanceAtlas extends PerformanceTest {
|
|
String get name => "1001 rects drawAtlas (24% offscreen)";
|
|
|
|
final int grid = 100;
|
|
|
|
double rotation = 0.0;
|
|
List<Rect> rects = [];
|
|
Paint cachedPaint = new Paint()
|
|
..setFilterQuality(sky.FilterQuality.low)
|
|
..isAntiAlias = false;
|
|
|
|
TestPerformanceAtlas() {
|
|
for (int x = 0; x < grid; x++) {
|
|
for (int y = 0; y < grid; y++) {
|
|
rects.add(_spriteSheet["asteroid_big_1.png"].frame);
|
|
}
|
|
}
|
|
rects.add(_spriteSheet["asteroid_big_1.png"].frame);
|
|
}
|
|
|
|
void paint(PaintingCanvas canvas) {
|
|
// Setup transforms
|
|
List<sky.RSTransform> transforms = [];
|
|
|
|
for (int x = 0; x < grid; x++) {
|
|
for (int y = 0; y < grid; y++) {
|
|
double xPos = x * 1024.0 / (grid - 1);
|
|
double yPos = y * 1024.0 / (grid - 1);
|
|
|
|
transforms.add(createTransform(xPos, yPos, rects[0].size.width / 2.0, rects[0].size.height / 2.0, rotation, 1.0));
|
|
}
|
|
}
|
|
|
|
transforms.add(createTransform(512.0, 512.0, rects[0].size.width / 2.0, rects[0].size.height / 2.0, rotation, 1.0));
|
|
|
|
// Draw atlas
|
|
Rect cullRect = spriteBox.visibleArea;
|
|
canvas.drawAtlas(_spriteSheet.image, transforms, rects, null, null, cullRect, cachedPaint);
|
|
}
|
|
|
|
void update(double dt) {
|
|
rotation += 1.0;
|
|
}
|
|
|
|
sky.RSTransform createTransform(double x, double y, double ax, double ay, double rot, double scale) {
|
|
double scos = math.cos(convertDegrees2Radians(rot)) * scale;
|
|
double ssin = math.sin(convertDegrees2Radians(rot)) * scale;
|
|
double tx = x + -scos * ax + ssin * ay;
|
|
double ty = y + -ssin * ax - scos * ay;
|
|
return new sky.RSTransform(scos, ssin, tx, ty);
|
|
}
|
|
}
|
|
|
|
class TestPerformanceAtlas2 extends PerformanceTest {
|
|
String get name => "1001 rects drawAtlas (24% offscreen never added)";
|
|
|
|
final int grid = 100;
|
|
|
|
double rotation = 0.0;
|
|
List<Rect> rects = [];
|
|
Paint cachedPaint = new Paint()
|
|
..setFilterQuality(sky.FilterQuality.low)
|
|
..isAntiAlias = false;
|
|
|
|
TestPerformanceAtlas2() {
|
|
for (int x = 12; x < grid - 12; x++) {
|
|
for (int y = 0; y < grid; y++) {
|
|
rects.add(_spriteSheet["asteroid_big_1.png"].frame);
|
|
}
|
|
}
|
|
rects.add(_spriteSheet["asteroid_big_1.png"].frame);
|
|
}
|
|
|
|
void paint(PaintingCanvas canvas) {
|
|
// Setup transforms
|
|
List<sky.RSTransform> transforms = [];
|
|
|
|
for (int x = 12; x < grid - 12; x++) {
|
|
for (int y = 0; y < grid; y++) {
|
|
double xPos = x * 1024.0 / (grid - 1);
|
|
double yPos = y * 1024.0 / (grid - 1);
|
|
|
|
transforms.add(createTransform(xPos, yPos, rects[0].size.width / 2.0, rects[0].size.height / 2.0, rotation, 1.0));
|
|
}
|
|
}
|
|
|
|
transforms.add(createTransform(512.0, 512.0, rects[0].size.width / 2.0, rects[0].size.height / 2.0, rotation, 1.0));
|
|
|
|
// Draw atlas
|
|
Rect cullRect = spriteBox.visibleArea;
|
|
canvas.drawAtlas(_spriteSheet.image, transforms, rects, null, null, cullRect, cachedPaint);
|
|
}
|
|
|
|
void update(double dt) {
|
|
rotation += 1.0;
|
|
}
|
|
|
|
sky.RSTransform createTransform(double x, double y, double ax, double ay, double rot, double scale) {
|
|
double scos = math.cos(convertDegrees2Radians(rot)) * scale;
|
|
double ssin = math.sin(convertDegrees2Radians(rot)) * scale;
|
|
double tx = x + -scos * ax + ssin * ay;
|
|
double ty = y + -ssin * ax - scos * ay;
|
|
return new sky.RSTransform(scos, ssin, tx, ty);
|
|
}
|
|
}
|