mirror of
https://github.com/flutter/flutter
synced 2024-10-14 04:02:56 +00:00
Adds hit tests and transformations between coordinate systems in sprites
Sprite nodes use Point instead of Vector2 Updates sprite test app Refactors accounting for pivot points in sprites Adds abstract NodeWithSize class in Sprites. Refactors SpriteNode to Sprite Refactors TransformNode to Node (may need to find another name as it conflicts with Sky's Node). Sprite system now uses and caches transformation matrices. R=abarth@chromium.org Review URL: https://codereview.chromium.org/1180703002.
This commit is contained in:
parent
42877fd114
commit
dcb0fa4312
|
@ -5,6 +5,7 @@ import 'dart:math' as Math;
|
|||
import 'package:vector_math/vector_math_64.dart';
|
||||
import 'sprites.dart';
|
||||
import 'package:box2d/box2d.dart';
|
||||
import 'package:sky/framework/rendering/box.dart';
|
||||
|
||||
part 'game_world.dart';
|
||||
part 'game_box.dart';
|
||||
|
|
|
@ -2,7 +2,59 @@ part of game;
|
|||
|
||||
Math.Random _rand;
|
||||
|
||||
class GameTests extends TransformNode{
|
||||
class GameTestsBox extends SpriteBox {
|
||||
GameTestsBox(Node tests, SpriteBoxTransformMode mode) : super(tests, mode);
|
||||
|
||||
void handleEvent(Event event, BoxHitTestEntry entry) {
|
||||
|
||||
if (event is PointerEvent) {
|
||||
Point pointerPos = new Point(event.x, event.y);
|
||||
int pointer = event.pointer;
|
||||
|
||||
switch (event.type) {
|
||||
case 'pointerdown':
|
||||
List sprites = findNodesAtPosition(pointerPos);
|
||||
for (Node node in sprites) {
|
||||
if (node is Sprite) {
|
||||
Sprite sprt = node;
|
||||
sprt.colorOverlay = new Color(0x66ff0000);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class GameTestsSimple extends Node {
|
||||
Image _imgAsteroid;
|
||||
Image _imgBg;
|
||||
Image _imgShip;
|
||||
|
||||
GameTestsSimple(ImageMap images) {
|
||||
// Setup random number generator
|
||||
_rand = new Math.Random();
|
||||
|
||||
// Fetch images
|
||||
_imgBg = images["https://raw.githubusercontent.com/slembcke/GalacticGuardian.spritebuilder/GDC/Packages/SpriteBuilder%20Resources.sbpack/resources-auto/BurnTexture.png"];
|
||||
_imgAsteroid = images["https://raw.githubusercontent.com/slembcke/GalacticGuardian.spritebuilder/GDC/Packages/SpriteBuilder%20Resources.sbpack/Sprites/resources-auto/asteroid_big_002.png"];
|
||||
_imgShip = images["https://raw.githubusercontent.com/slembcke/GalacticGuardian.spritebuilder/GDC/Packages/SpriteBuilder%20Resources.sbpack/Sprites/resources-auto/GG_blueship_Lv3.png"];
|
||||
|
||||
Sprite sprt0 = new Sprite.withImage(_imgBg);
|
||||
sprt0.size = new Size(100.0, 100.0);
|
||||
sprt0.pivot = new Point(0.0, 0.0);
|
||||
sprt0.position = new Point(100.0, 100.0);
|
||||
this.addChild(sprt0);
|
||||
|
||||
Sprite sprt1 = new Sprite.withImage(_imgBg);
|
||||
sprt1.size = new Size(100.0, 100.0);
|
||||
sprt1.pivot = new Point(0.0, 0.0);
|
||||
sprt1.position = new Point(100.0, 100.0);
|
||||
sprt0.addChild(sprt1);
|
||||
}
|
||||
}
|
||||
|
||||
class GameTests extends Node{
|
||||
|
||||
Image _imgAsteroid;
|
||||
Image _imgBg;
|
||||
|
@ -24,8 +76,7 @@ class GameTests extends TransformNode{
|
|||
|
||||
void addSprite([double scale = null]) {
|
||||
TestAsteroidSprite sprt = new TestAsteroidSprite.withImage(_imgAsteroid);
|
||||
sprt.width = 64.0;
|
||||
sprt.height = 64.0;
|
||||
sprt.size = new Size(64.0, 64.0);
|
||||
|
||||
if (scale == null) {
|
||||
scale = _rand.nextDouble();
|
||||
|
@ -33,19 +84,29 @@ class GameTests extends TransformNode{
|
|||
|
||||
sprt.zPosition = scale;
|
||||
sprt.scale = scale;
|
||||
sprt.position = new Vector2(_rand.nextDouble()*1024.0, _rand.nextDouble()*1024.0);
|
||||
sprt.position = new Point(_rand.nextDouble()*1024.0, _rand.nextDouble()*1024.0);
|
||||
|
||||
this.addChild(sprt);
|
||||
|
||||
Sprite sprtMoon0 = new Sprite.withImage(_imgAsteroid);
|
||||
sprtMoon0.size = new Size(32.0, 32.0);
|
||||
sprtMoon0.position = new Point(32.0, 0.0);
|
||||
sprt.addChild(sprtMoon0);
|
||||
|
||||
Sprite sprtMoon1 = new Sprite.withImage(_imgAsteroid);
|
||||
sprtMoon1.size = new Size(32.0, 32.0);
|
||||
sprtMoon1.position = new Point(-32.0, 0.0);
|
||||
sprt.addChild(sprtMoon1);
|
||||
}
|
||||
|
||||
void update(double dt) {
|
||||
for (TransformNode child in children) {
|
||||
for (Node child in children) {
|
||||
child.update(dt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class TestAsteroidSprite extends SpriteNode {
|
||||
class TestAsteroidSprite extends Sprite {
|
||||
|
||||
Vector2 _movementVector;
|
||||
double _rotationalSpeed;
|
||||
|
@ -56,11 +117,14 @@ class TestAsteroidSprite extends SpriteNode {
|
|||
}
|
||||
|
||||
void update(double dt) {
|
||||
position = position + _movementVector * scale;
|
||||
Vector2 vPos = new Vector2(position.x, position.y);
|
||||
Vector2 vNewPos = vPos + _movementVector * scale;
|
||||
|
||||
position = new Point(vNewPos[0], vNewPos[1]);
|
||||
|
||||
// Bounce at edges
|
||||
if (position[0] < 0 || position[0] > 1024.0) _movementVector[0] = -_movementVector[0];
|
||||
if (position[1] < 0 || position[1] > 1024.0) _movementVector[1] = -_movementVector[1];
|
||||
if (position.x < 0 || position.x > 1024.0) _movementVector[0] = -_movementVector[0];
|
||||
if (position.y < 0 || position.y > 1024.0) _movementVector[1] = -_movementVector[1];
|
||||
|
||||
rotation += _rotationalSpeed;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
part of game;
|
||||
|
||||
class GameWorld extends TransformNode {
|
||||
class GameWorld extends Node {
|
||||
|
||||
World world;
|
||||
List<Body> bodies = [];
|
||||
|
@ -42,7 +42,7 @@ class GameWorld extends TransformNode {
|
|||
}
|
||||
|
||||
void addBackground() {
|
||||
SpriteNode sprtBg = new SpriteNode.withImage(_imgBg);
|
||||
Sprite sprtBg = new Sprite.withImage(_imgBg);
|
||||
sprtBg.width = width;
|
||||
sprtBg.height = height;
|
||||
sprtBg.pivot = new Vector2(0.0, 0.0);
|
||||
|
@ -81,7 +81,7 @@ class GameWorld extends TransformNode {
|
|||
bodies.add(body);
|
||||
|
||||
// Create sprite
|
||||
SpriteNode sprt = new SpriteNode.withImage(_imgAsteroid);
|
||||
Sprite sprt = new Sprite.withImage(_imgAsteroid);
|
||||
sprt.width = radius*2;
|
||||
sprt.height = radius*2;
|
||||
// sprt.colorOverlay = new Color(0x33ff0000);
|
||||
|
@ -122,7 +122,7 @@ class GameWorld extends TransformNode {
|
|||
_bodyShip = body;
|
||||
|
||||
// Create sprite
|
||||
SpriteNode sprt = new SpriteNode.withImage(_imgShip);
|
||||
Sprite sprt = new Sprite.withImage(_imgShip);
|
||||
sprt.width = radius*2;
|
||||
sprt.height = radius*2;
|
||||
sprt.position = new Vector2(width/2.0, height/2.0);
|
||||
|
@ -155,7 +155,7 @@ class GameWorld extends TransformNode {
|
|||
}
|
||||
|
||||
void updateBody(Body body) {
|
||||
SpriteNode sprt = body.userData;
|
||||
Sprite sprt = body.userData;
|
||||
double rot = 0.0; //body.getRotation();
|
||||
|
||||
// Check bounds and warp objects
|
||||
|
|
|
@ -4,27 +4,22 @@ double degrees2radians(double degrees) => degrees * Math.PI/180.8;
|
|||
|
||||
double radians2degrees(double radians) => radians * 180.0/Math.PI;
|
||||
|
||||
class TransformNode {
|
||||
class Node {
|
||||
|
||||
// Member variables
|
||||
|
||||
SpriteBox _spriteBox;
|
||||
TransformNode _parent;
|
||||
Node _parent;
|
||||
|
||||
Vector2 _position;
|
||||
Point _position;
|
||||
double _rotation;
|
||||
|
||||
bool _isMatrixDirty;
|
||||
Matrix3 _transform;
|
||||
Matrix3 _pivotTransform;
|
||||
|
||||
double _width;
|
||||
double _height;
|
||||
Matrix4 _transformMatrix;
|
||||
Matrix4 _transformMatrixFromWorld;
|
||||
|
||||
double _scaleX;
|
||||
double _scaleY;
|
||||
|
||||
Vector2 _pivot;
|
||||
|
||||
bool visible;
|
||||
|
||||
|
@ -33,20 +28,16 @@ class TransformNode {
|
|||
int _childrenLastAddedOrder;
|
||||
bool _childrenNeedSorting;
|
||||
|
||||
List<TransformNode>_children;
|
||||
List<Node>_children;
|
||||
|
||||
// Constructors
|
||||
|
||||
TransformNode() {
|
||||
_width = 0.0;
|
||||
_height = 0.0;
|
||||
Node() {
|
||||
_rotation = 0.0;
|
||||
_pivot = new Vector2(0.0, 0.0);
|
||||
_position = new Vector2(0.0, 0.0);
|
||||
_position = new Point(0.0, 0.0);
|
||||
_scaleX = _scaleY = 1.0;
|
||||
_isMatrixDirty = false;
|
||||
_transform = new Matrix3.identity();
|
||||
_pivotTransform = new Matrix3.identity();
|
||||
_transformMatrix = new Matrix4.identity();
|
||||
_children = [];
|
||||
_childrenNeedSorting = false;
|
||||
_childrenLastAddedOrder = 0;
|
||||
|
@ -57,7 +48,7 @@ class TransformNode {
|
|||
|
||||
SpriteBox get spriteBox => _spriteBox;
|
||||
|
||||
TransformNode get parent => _parent;
|
||||
Node get parent => _parent;
|
||||
|
||||
double get rotation => _rotation;
|
||||
|
||||
|
@ -66,33 +57,12 @@ class TransformNode {
|
|||
_isMatrixDirty = true;
|
||||
}
|
||||
|
||||
Vector2 get position => _position;
|
||||
Point get position => _position;
|
||||
|
||||
void set position(Vector2 position) {
|
||||
void set position(Point position) {
|
||||
_position = position;
|
||||
_isMatrixDirty = true;
|
||||
}
|
||||
|
||||
double get width => _width;
|
||||
|
||||
void set width(double width) {
|
||||
_width = width;
|
||||
_isMatrixDirty = true;
|
||||
}
|
||||
|
||||
double get height => _height;
|
||||
|
||||
void set height(double height) {
|
||||
_height = height;
|
||||
_isMatrixDirty = true;
|
||||
}
|
||||
|
||||
Vector2 get pivot => _pivot;
|
||||
|
||||
void set pivot(Vector2 pivot) {
|
||||
_pivot = pivot;
|
||||
_isMatrixDirty = true;
|
||||
}
|
||||
|
||||
double get zPosition => _zPosition;
|
||||
|
||||
|
@ -113,11 +83,11 @@ class TransformNode {
|
|||
_isMatrixDirty = true;
|
||||
}
|
||||
|
||||
List<TransformNode> get children => _children;
|
||||
List<Node> get children => _children;
|
||||
|
||||
// Adding and removing children
|
||||
|
||||
void addChild(TransformNode child) {
|
||||
void addChild(Node child) {
|
||||
assert(child._parent == null);
|
||||
|
||||
_childrenNeedSorting = true;
|
||||
|
@ -128,7 +98,7 @@ class TransformNode {
|
|||
child._addedOrder = _childrenLastAddedOrder;
|
||||
}
|
||||
|
||||
void removeChild(TransformNode child) {
|
||||
void removeChild(Node child) {
|
||||
if (_children.remove(child)) {
|
||||
child._parent = null;
|
||||
child._spriteBox = null;
|
||||
|
@ -141,7 +111,7 @@ class TransformNode {
|
|||
}
|
||||
|
||||
void removeAllChildren() {
|
||||
for (TransformNode child in _children) {
|
||||
for (Node child in _children) {
|
||||
child._parent = null;
|
||||
child._spriteBox = null;
|
||||
}
|
||||
|
@ -151,16 +121,14 @@ class TransformNode {
|
|||
|
||||
// Calculating the transformation matrix
|
||||
|
||||
Matrix3 get transformMatrix {
|
||||
Matrix4 get transformMatrix {
|
||||
if (!_isMatrixDirty) {
|
||||
return _transform;
|
||||
return _transformMatrix;
|
||||
}
|
||||
|
||||
Vector2 pivotInPoints = new Vector2(_width * _pivot[0], _height * _pivot[1]);
|
||||
|
||||
double cx, sx, cy, sy;
|
||||
|
||||
if (_rotation == 0) {
|
||||
if (_rotation == 0.0) {
|
||||
cx = 1.0;
|
||||
sx = 0.0;
|
||||
cy = 1.0;
|
||||
|
@ -175,22 +143,70 @@ class TransformNode {
|
|||
cy = Math.cos(radiansY);
|
||||
sy = Math.sin(radiansY);
|
||||
}
|
||||
|
||||
// TODO: Add support for scale
|
||||
double scaleX = 1.0;
|
||||
double scaleY = 1.0;
|
||||
|
||||
|
||||
// Create transformation matrix for scale, position and rotation
|
||||
_transform.setValues(cy * scaleX, sy * scaleX, 0.0,
|
||||
-sx * scaleY, cx * scaleY, 0.0,
|
||||
_position[0], _position[1], 1.0);
|
||||
_transformMatrix.setValues(cy * _scaleX, sy * _scaleX, 0.0, 0.0,
|
||||
-sx * _scaleY, cx * _scaleY, 0.0, 0.0,
|
||||
0.0, 0.0, 1.0, 0.0,
|
||||
_position.x, _position.y, 0.0, 1.0
|
||||
);
|
||||
|
||||
if (_pivot.x != 0 || _pivot.y != 0) {
|
||||
_pivotTransform.setValues(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, pivotInPoints[0], pivotInPoints[1], 1.0);
|
||||
_transform.multiply(_pivotTransform);
|
||||
return _transformMatrix;
|
||||
}
|
||||
|
||||
// Transforms to other nodes
|
||||
|
||||
Matrix4 _nodeToBoxMatrix() {
|
||||
Matrix4 t = transformMatrix;
|
||||
|
||||
Node p = this.parent;
|
||||
while (p != null) {
|
||||
t = new Matrix4.copy(p.transformMatrix).multiply(t);
|
||||
p = p.parent;
|
||||
}
|
||||
|
||||
return _transform;
|
||||
return t;
|
||||
}
|
||||
|
||||
Matrix4 _boxToNodeMatrix() {
|
||||
Matrix4 t = _nodeToBoxMatrix();
|
||||
t.invert();
|
||||
return t;
|
||||
}
|
||||
|
||||
Point convertPointToNodeSpace(Point boxPoint) {
|
||||
assert(boxPoint != null);
|
||||
assert(_spriteBox != null);
|
||||
|
||||
Vector4 v =_boxToNodeMatrix().transform(new Vector4(boxPoint.x, boxPoint.y, 0.0, 1.0));
|
||||
return new Point(v[0], v[1]);
|
||||
}
|
||||
|
||||
Point convertPointToBoxSpace(Point nodePoint) {
|
||||
assert(nodePoint != null);
|
||||
assert(_spriteBox != null);
|
||||
|
||||
Vector4 v =_nodeToBoxMatrix().transform(new Vector4(nodePoint.x, nodePoint.y, 0.0, 1.0));
|
||||
return new Point(v[0], v[1]);
|
||||
}
|
||||
|
||||
Point convertPointFromNode(Point point, Node node) {
|
||||
assert(node != null);
|
||||
assert(point != null);
|
||||
assert(_spriteBox != null);
|
||||
assert(_spriteBox == node._spriteBox);
|
||||
|
||||
Point boxPoint = node.convertPointToBoxSpace(point);
|
||||
Point localPoint = convertPointToNodeSpace(boxPoint);
|
||||
|
||||
return localPoint;
|
||||
}
|
||||
|
||||
// Hit test
|
||||
|
||||
bool hitTest(Point nodePoint) {
|
||||
assert(nodePoint != null);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Rendering
|
||||
|
@ -206,16 +222,13 @@ class TransformNode {
|
|||
|
||||
void prePaint(PictureRecorder canvas) {
|
||||
canvas.save();
|
||||
|
||||
canvas.translate(_position[0], _position[1]);
|
||||
canvas.rotate(degrees2radians(_rotation));
|
||||
canvas.scale(_scaleX, _scaleY);
|
||||
canvas.translate(-_width*_pivot[0], -_height*_pivot[1]);
|
||||
|
||||
// TODO: Use transformation matrix instead of individual calls
|
||||
// List<double> matrix = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0];
|
||||
// this.transformMatrix.copyIntoArray(matrix);
|
||||
// canvas.concat(matrix);
|
||||
|
||||
// TODO: Can this be done more efficiently?
|
||||
// Get the transformation matrix and apply transform
|
||||
List<double> matrix = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0];
|
||||
this.transformMatrix.copyIntoArray(matrix);
|
||||
Float32List list32 = new Float32List.fromList(matrix);
|
||||
canvas.concat(list32);
|
||||
}
|
||||
|
||||
void paint(PictureRecorder canvas) {
|
||||
|
@ -225,7 +238,7 @@ class TransformNode {
|
|||
void visitChildren(PictureRecorder canvas) {
|
||||
// Sort children primarily by zPosition, secondarily by added order
|
||||
if (_childrenNeedSorting) {
|
||||
_children.sort((TransformNode a, TransformNode b) {
|
||||
_children.sort((Node a, Node b) {
|
||||
if (a._zPosition == b._zPosition) {
|
||||
return b._addedOrder - a._addedOrder;
|
||||
}
|
31
examples/game/lib/node_with_size.dart
Normal file
31
examples/game/lib/node_with_size.dart
Normal file
|
@ -0,0 +1,31 @@
|
|||
part of sprites;
|
||||
|
||||
abstract class NodeWithSize extends Node {
|
||||
Size size;
|
||||
Point pivot;
|
||||
|
||||
NodeWithSize() {
|
||||
size = new Size(0.0, 0.0);
|
||||
pivot = new Point(0.0, 0.0);
|
||||
}
|
||||
|
||||
NodeWithSize.withSize(Size size, [Point pivot]);
|
||||
|
||||
void applyTransformForPivot(PictureRecorder canvas) {
|
||||
if (pivot.x != 0 || pivot.y != 0) {
|
||||
double pivotInPointsX = size.width * pivot.x;
|
||||
double pivotInPointsY = size.height * pivot.y;
|
||||
canvas.translate(-pivotInPointsX, -pivotInPointsY);
|
||||
}
|
||||
}
|
||||
|
||||
bool hitTest (Point nodePoint) {
|
||||
|
||||
double minX = -size.width * pivot.x;
|
||||
double minY = -size.height * pivot.y;
|
||||
double maxX = minX + size.width;
|
||||
double maxY = minY + size.height;
|
||||
return (nodePoint.x >= minX && nodePoint.x < maxX &&
|
||||
nodePoint.y >= minY && nodePoint.y < maxY);
|
||||
}
|
||||
}
|
|
@ -2,7 +2,7 @@ part of sprites;
|
|||
|
||||
// TODO: Actually draw images
|
||||
|
||||
class SpriteNode extends TransformNode {
|
||||
class Sprite extends NodeWithSize {
|
||||
|
||||
Image _image;
|
||||
bool constrainProportions = false;
|
||||
|
@ -10,12 +10,12 @@ class SpriteNode extends TransformNode {
|
|||
Color colorOverlay;
|
||||
TransferMode transferMode;
|
||||
|
||||
SpriteNode() {
|
||||
this.pivot = new Vector2(0.5, 0.5);
|
||||
Sprite() {
|
||||
}
|
||||
|
||||
SpriteNode.withImage(Image image) : super() {
|
||||
this.pivot = new Vector2(0.5, 0.5);
|
||||
Sprite.withImage(Image image) {
|
||||
this.pivot = new Point(0.5, 0.5);
|
||||
this.size = new Size(image.width.toDouble(), image.height.toDouble());
|
||||
_image = image;
|
||||
}
|
||||
|
||||
|
@ -27,21 +27,24 @@ class SpriteNode extends TransformNode {
|
|||
}
|
||||
|
||||
void paint(PictureRecorder canvas) {
|
||||
canvas.save();
|
||||
|
||||
// Account for pivot point
|
||||
applyTransformForPivot(canvas);
|
||||
|
||||
if (_image != null && _image.width > 0 && _image.height > 0) {
|
||||
canvas.save();
|
||||
|
||||
double scaleX = _width/_image.width;
|
||||
double scaleY = _height/_image.height;
|
||||
double scaleX = size.width/_image.width;
|
||||
double scaleY = size.height/_image.height;
|
||||
|
||||
if (constrainProportions) {
|
||||
// Constrain proportions, using the smallest scale and by centering the image
|
||||
if (scaleX < scaleY) {
|
||||
canvas.translate(0.0, (_height - scaleX * _image.height)/2.0);
|
||||
canvas.translate(0.0, (size.height - scaleX * _image.height)/2.0);
|
||||
scaleY = scaleX;
|
||||
}
|
||||
else {
|
||||
canvas.translate((_width - scaleY * _image.width)/2.0, 0.0);
|
||||
canvas.translate((size.width - scaleY * _image.width)/2.0, 0.0);
|
||||
scaleX = scaleY;
|
||||
}
|
||||
}
|
||||
|
@ -59,13 +62,12 @@ class SpriteNode extends TransformNode {
|
|||
}
|
||||
|
||||
canvas.drawImage(_image, 0.0, 0.0, paint);
|
||||
canvas.restore();
|
||||
}
|
||||
else {
|
||||
// Paint a red square for missing texture
|
||||
canvas.drawRect(new Rect.fromLTRB(0.0, 0.0, this.width, this.height),
|
||||
canvas.drawRect(new Rect.fromLTRB(0.0, 0.0, size.width, size.height),
|
||||
new Paint()..setARGB(255, 255, 0, 0));
|
||||
}
|
||||
canvas.restore();
|
||||
}
|
||||
|
||||
}
|
|
@ -11,8 +11,10 @@ enum SpriteBoxTransformMode {
|
|||
|
||||
class SpriteBox extends RenderBox {
|
||||
|
||||
// Member variables
|
||||
|
||||
// Root node for drawing
|
||||
TransformNode _rootNode;
|
||||
Node _rootNode;
|
||||
|
||||
// Tracking of frame rate and updates
|
||||
double _lastTimeStamp;
|
||||
|
@ -22,7 +24,9 @@ class SpriteBox extends RenderBox {
|
|||
double _systemWidth;
|
||||
double _systemHeight;
|
||||
|
||||
SpriteBox(TransformNode rootNode, [SpriteBoxTransformMode mode = SpriteBoxTransformMode.nativePoints, double width=1024.0, double height=1024.0]) {
|
||||
// Setup
|
||||
|
||||
SpriteBox(Node rootNode, [SpriteBoxTransformMode mode = SpriteBoxTransformMode.nativePoints, double width=1024.0, double height=1024.0]) {
|
||||
assert(rootNode != null);
|
||||
assert(rootNode._spriteBox == null);
|
||||
|
||||
|
@ -40,30 +44,31 @@ class SpriteBox extends RenderBox {
|
|||
_scheduleTick();
|
||||
}
|
||||
|
||||
void _addSpriteBoxReference(TransformNode node) {
|
||||
void _addSpriteBoxReference(Node node) {
|
||||
node._spriteBox = this;
|
||||
for (TransformNode child in node._children) {
|
||||
for (Node child in node._children) {
|
||||
_addSpriteBoxReference(child);
|
||||
}
|
||||
}
|
||||
|
||||
// Properties
|
||||
|
||||
double get systemWidth => _systemWidth;
|
||||
double get systemHeight => _systemHeight;
|
||||
|
||||
TransformNode get rootNode => _rootNode;
|
||||
Node get rootNode => _rootNode;
|
||||
|
||||
void performLayout() {
|
||||
size = constraints.constrain(Size.infinite);
|
||||
}
|
||||
|
||||
// Event handling
|
||||
|
||||
void handleEvent(Event event, BoxHitTestEntry entry) {
|
||||
switch (event.type) {
|
||||
case 'pointerdown':
|
||||
print("pointerdown");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Rendering
|
||||
|
||||
void paint(RenderObjectDisplayList canvas) {
|
||||
// Move to correct coordinate space before drawing
|
||||
double scaleX = 1.0;
|
||||
|
@ -104,7 +109,6 @@ class SpriteBox extends RenderBox {
|
|||
scaleX = size.width/_systemWidth;
|
||||
scaleY = scaleX;
|
||||
_systemHeight = size.height/scaleX;
|
||||
print("systemHeight: $_systemHeight");
|
||||
break;
|
||||
case SpriteBoxTransformMode.fixedHeight:
|
||||
scaleY = size.height/_systemHeight;
|
||||
|
@ -129,6 +133,8 @@ class SpriteBox extends RenderBox {
|
|||
canvas.restore();
|
||||
}
|
||||
|
||||
// Updates
|
||||
|
||||
int _animationId = 0;
|
||||
|
||||
void _scheduleTick() {
|
||||
|
@ -151,4 +157,29 @@ class SpriteBox extends RenderBox {
|
|||
_rootNode.update(delta);
|
||||
_scheduleTick();
|
||||
}
|
||||
|
||||
// Hit tests
|
||||
|
||||
List<Node> findNodesAtPosition(Point position) {
|
||||
assert(position != null);
|
||||
|
||||
List<Node> nodes = [];
|
||||
|
||||
// Traverse the render tree and find objects at the position
|
||||
_addNodesAtPosition(_rootNode, position, nodes);
|
||||
|
||||
return nodes;
|
||||
}
|
||||
|
||||
_addNodesAtPosition(Node node, Point position, List<Node> list) {
|
||||
// Visit children first
|
||||
for (Node child in node.children) {
|
||||
_addNodesAtPosition(child, position, list);
|
||||
}
|
||||
// Do the hit test
|
||||
Point posInNodeSpace = node.convertPointToNodeSpace(position);
|
||||
if (node.hitTest(posInNodeSpace)) {
|
||||
list.add(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,14 +3,14 @@ library sprites;
|
|||
import 'dart:sky';
|
||||
import 'dart:math' as Math;
|
||||
import 'package:vector_math/vector_math_64.dart';
|
||||
import 'package:sky/framework/app.dart';
|
||||
import 'dart:typed_data';
|
||||
import 'package:sky/framework/rendering/box.dart';
|
||||
//import 'package:sky/framework/rendering/node.dart';
|
||||
import 'package:sky/framework/rendering/object.dart';
|
||||
import 'package:sky/framework/scheduler.dart' as scheduler;
|
||||
import 'package:sky/framework/net/image_cache.dart' as image_cache;
|
||||
|
||||
part 'sprite_box.dart';
|
||||
part 'transform_node.dart';
|
||||
part 'sprite_node.dart';
|
||||
part 'node.dart';
|
||||
part 'node_with_size.dart';
|
||||
part 'sprite.dart';
|
||||
part 'image_map.dart';
|
|
@ -19,5 +19,5 @@ void allLoaded(ImageMap loader) {
|
|||
// Create a new app with the sprite box that contains our game world
|
||||
//app = new AppView(new GameBox(new GameWorld(loader)));
|
||||
//print("hello");
|
||||
app = new AppView((new SpriteBox(new GameTests(loader), SpriteBoxTransformMode.letterbox)));
|
||||
app = new AppView((new GameTestsBox(new GameTests(loader), SpriteBoxTransformMode.nativePoints)));
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue