I am trying to draw a square when I click on the screen. I have the drawing logic working and I can do it onclick but for some reason it's drawing the squares somewhat randomly. Ideally I want it to be drawn from the point of click. Wherever I click should be the center of the new square. Here is what currently happens when I click the iOS simulator.
I was trying to use event.pointerEvent.localPosition.dx
and ...dy
where event
is of type SpriteBoxEvent
. I am using them to create an Offset
instance which will be used in Rect.fromCenter
as I figured that would be best to use with my pointer coordinates since I wanted them to be the center of the square.
Below is my code for my SpriteSquare
widget and the handleAdd
function that is in the parent widget, MySpriteGame
(minus the imports as those aren't causing any issues).
Here is the full GitHub repo.
sprite_square.dart
class SpriteSquare extends NodeWithSize {
Color color;
Function handler;
double left;
double top;
SpriteSquare(size, this.color, this.handler, this.top, this.left) : super(size){
userInteractionEnabled = true;
}
@override handleEvent(SpriteBoxEvent event) {
handler(event);
return true;
}
@override
Future<void> paint(Canvas canvas) async {
canvas.drawRect(
Rect.fromLTWH(left, top, size.height, size.width),
Paint()..color = color
);
}
}
handleAdd
handleAdd(SpriteBoxEvent event) {
final _whitesquare = SpriteSquare(
const Size(50.0, 50.0),
const Color(0xFFFFFFFF),
handleRemoveSelf,
Offset(event.pointerEvent.localPosition.dx, event.pointerEvent.localPosition.dy)
);
_background.addChild(_whitesquare);
return true;
}
You're creating your background SpriteSquare
with wrong sizes and then you are adding other SpriteSquare
with positions computed from touch event positions transformed to SpriteWidget
's local position which can be smaller or bigger then your background SpriteSquare
. Here is how I solved it:
SingleChildScrollView
from your MyHomePage
widget.LayoutBuilder
position in widget tree. So the final MyHomePage
's build function body is like this:return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(child: LayoutBuilder(builder: (ctx, constrain
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text(
'Select Game Engine',
),
DropdownButton<String>(
value: _whichEngine,
icon: const Icon(Icons.arrow_downward),
iconSize: 24,
elevation: 16,
style: const TextStyle(color: Colors.deepPurple)
underline: Container(
height: 2,
color: Colors.deepPurpleAccent,
),
onChanged: (String? newValue) {
setState(() {
_whichEngine = newValue!;
});
},
items: <String>[
'Flame',
'Quill',
'SpriteWidget',
'Feathers',
'Unity'
].map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
),
Expanded(
child: LayoutBuilder(
builder: (context, constraints) {
final size =
Size(constraints.maxWidth, constraints.m
if (_whichEngine == 'Flame') {
return GameWidget(
game: MyFlameGame(),
);
} else if (_whichEngine == 'SpriteWidget') {
return MySpriteGame(size: size);
} else {
return MySpriteGame(size: size);
}
},
),
),
]);
})));
SpriteSquare
. So this is the body of paint function in SpriteSquare
now:canvas.drawRect(
Rect.fromLTWH(left, top, size.height, size.width),
Paint()..color = color
);
MySpriteGame
to take a size from it's parent and construct background with that size and tweaked values in handleAdd
:class MySpriteGame extends StatelessWidget {
final _background;
MySpriteGame({Key? key, required Size size})
: _background = SpriteSquare(size, const Color(0xFF000000), () {}, 0, 0),
super(key: key) {}
handleAdd(SpriteBoxEvent event) {
final _whitesquare = SpriteSquare(
const Size(50.0, 50.0),
const Color(0xFFFFFFFF),
handleRemoveSelf,
event.pointerEvent.localPosition.dy - 25,
event.pointerEvent.localPosition.dx - 25,
);
_background.addChild(_whitesquare);
return true;
}
handleRemoveSelf(SpriteBoxEvent event) {
print('hello');
return true;
}
@override
Widget build(BuildContext context) {
_background.handler = handleAdd;
return SpriteWidget(_background);
}
}
With these changes it's working correctly now.