Skip to content

Commit 0bd4a56

Browse files
committed
add basic widgets
1 parent 8609bd1 commit 0bd4a56

File tree

7 files changed

+566
-6
lines changed

7 files changed

+566
-6
lines changed

lib/main.dart

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
11
import 'package:flutter/material.dart';
2+
import 'package:flutter/services.dart';
3+
import 'package:tetris/material/images.dart';
4+
import 'package:tetris/panel/screen.dart';
5+
import 'dart:ui' as ui;
26

37
void main() => runApp(MyApp());
48

@@ -11,16 +15,50 @@ class MyApp extends StatelessWidget {
1115
theme: ThemeData(
1216
primarySwatch: Colors.blue,
1317
),
14-
home: _HomePage(),
18+
home: Scaffold(
19+
body: _HomePage(),
20+
),
1521
);
1622
}
1723
}
1824

19-
class _HomePage extends StatelessWidget {
25+
class _HomePage extends StatefulWidget {
26+
@override
27+
_HomePageState createState() {
28+
return new _HomePageState();
29+
}
30+
}
31+
32+
class _HomePageState extends State<_HomePage> {
33+
@override
34+
void initState() {
35+
super.initState();
36+
_doLoadMaterial();
37+
}
38+
39+
void _doLoadMaterial() async {
40+
final bytes = await rootBundle.load("assets/material.png");
41+
final codec = await ui.instantiateImageCodec(bytes.buffer.asUint8List());
42+
final frame = await codec.getNextFrame();
43+
setState(() {
44+
material = frame.image;
45+
});
46+
}
47+
2048
@override
2149
Widget build(BuildContext context) {
50+
final size = MediaQuery.of(context).size;
51+
final screenW = size.width * 0.8;
52+
53+
Widget screen;
54+
if (material != null) {
55+
screen = Screen(width: screenW);
56+
}
2257
return Container(
23-
color: Color(0xff9ead86),
58+
color: Color(0xffefcc19),
59+
child: Center(
60+
child: screen,
61+
),
2462
);
2563
}
2664
}

lib/material/briks.dart

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import 'package:flutter/material.dart';
2+
3+
///the size of a single brik
4+
Size brikSize = Size(16, 16);
5+
6+
abstract class CombinedBriks extends StatelessWidget {
7+
final List<List<bool>> data;
8+
9+
const CombinedBriks({Key key, this.data}) : super(key: key);
10+
11+
@override
12+
Widget build(BuildContext context) {
13+
final children = data.map((row) {
14+
return Row(
15+
children: row.map((e) {
16+
return e ? Brik() : BrikNull();
17+
}).toList(),
18+
);
19+
}).toList();
20+
return Column(
21+
children: children,
22+
);
23+
}
24+
25+
CombinedBriks rotate();
26+
}
27+
28+
class BrikNull extends StatelessWidget {
29+
@override
30+
Widget build(BuildContext context) {
31+
return SizedBox.fromSize(
32+
size: brikSize,
33+
);
34+
}
35+
}
36+
37+
///the basic brik for game panel
38+
class Brik extends StatelessWidget {
39+
final bool enable;
40+
41+
const Brik({Key key, this.enable = true}) : super(key: key);
42+
43+
@override
44+
Widget build(BuildContext context) {
45+
Color color = enable ? Colors.black87 : Colors.black12;
46+
47+
return SizedBox.fromSize(
48+
size: brikSize,
49+
child: Container(
50+
margin: EdgeInsets.all(1),
51+
padding: EdgeInsets.all(2),
52+
decoration: BoxDecoration(border: Border.all(width: 2, color: color)),
53+
child: Container(
54+
color: color,
55+
),
56+
),
57+
);
58+
}
59+
}

lib/material/images.dart

Lines changed: 255 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,255 @@
1+
import 'dart:async';
2+
3+
import 'package:flutter/material.dart';
4+
import 'dart:ui' as ui;
5+
6+
GameImages gameImages = GameImages._();
7+
8+
///the image data of /assets/material.png
9+
ui.Image material;
10+
11+
const _DIGITAL_ROW_SIZE = Size(14, 24);
12+
13+
class GameImages {
14+
GameImages._();
15+
16+
Widget get number0 {
17+
return SizedBox(
18+
width: 14,
19+
height: 24,
20+
child: Transform.translate(
21+
offset: const Offset(15, 15),
22+
child: Image.asset("assets/material.png"),
23+
),
24+
);
25+
}
26+
}
27+
28+
class Number extends StatelessWidget {
29+
final int length;
30+
31+
///the number to show
32+
///could be null
33+
final int number;
34+
35+
Number({Key key, this.length = 5, @required this.number}) : super(key: key);
36+
37+
@override
38+
Widget build(BuildContext context) {
39+
String digitals = number?.toString() ?? "";
40+
if (digitals.length > length) {
41+
digitals = digitals.substring(digitals.length - length);
42+
}
43+
digitals = digitals.padLeft(length);
44+
List<Widget> children = [];
45+
for (int i = 0; i < length; i++) {
46+
children.add(Digital(int.tryParse(digitals[i])));
47+
}
48+
return Row(
49+
mainAxisSize: MainAxisSize.min,
50+
children: children,
51+
);
52+
}
53+
}
54+
55+
class IconDragon extends StatefulWidget {
56+
final bool animate;
57+
58+
const IconDragon({Key key, this.animate = false}) : super(key: key);
59+
60+
@override
61+
_IconDragonState createState() {
62+
return new _IconDragonState();
63+
}
64+
}
65+
66+
class _IconDragonState extends State<IconDragon> {
67+
Timer _timer;
68+
69+
@override
70+
void didUpdateWidget(IconDragon oldWidget) {
71+
super.didUpdateWidget(oldWidget);
72+
_initAnimation();
73+
}
74+
75+
///current frame of animation
76+
int _frame = 0;
77+
78+
@override
79+
void initState() {
80+
super.initState();
81+
}
82+
83+
void _initAnimation() {
84+
_timer?.cancel();
85+
_timer = null;
86+
if (!widget.animate) {
87+
return;
88+
}
89+
_timer = Timer.periodic(const Duration(milliseconds: 200), (t) {
90+
if (_frame > 30) {
91+
_frame = 0;
92+
}
93+
setState(() {
94+
_frame++;
95+
});
96+
});
97+
}
98+
99+
@override
100+
void dispose() {
101+
_timer?.cancel();
102+
_timer = null;
103+
super.dispose();
104+
}
105+
106+
@override
107+
Widget build(BuildContext context) {
108+
return _Material(
109+
size: const Size(80, 86),
110+
srcSize: const Size(80, 86),
111+
srcOffset: _getOffset(_frame),
112+
);
113+
}
114+
115+
Offset _getOffset(int frame) {
116+
int index = 0;
117+
if (frame < 10) {
118+
index = frame % 2 == 0 ? 0 : 1;
119+
} else {
120+
index = frame % 2 == 0 ? 2 : 3;
121+
}
122+
double dx = index * 100.0;
123+
return Offset(dx, 100);
124+
}
125+
}
126+
127+
class IconPause extends StatelessWidget {
128+
final bool enable;
129+
final Size size;
130+
131+
const IconPause({Key key, this.enable = true, this.size = const Size(18, 16)})
132+
: super(key: key);
133+
@override
134+
Widget build(BuildContext context) {
135+
return _Material(
136+
size: size,
137+
srcSize: const Size(20, 18),
138+
srcOffset: enable ? const Offset(100, 75) : const Offset(75, 75),
139+
);
140+
}
141+
}
142+
143+
class IconSound extends StatelessWidget {
144+
final bool enable;
145+
final Size size;
146+
147+
const IconSound({Key key, this.enable = true, this.size = const Size(18, 16)})
148+
: super(key: key);
149+
150+
@override
151+
Widget build(BuildContext context) {
152+
return _Material(
153+
size: size,
154+
srcSize: const Size(25, 21),
155+
srcOffset: enable ? const Offset(150, 75) : const Offset(175, 75),
156+
);
157+
}
158+
}
159+
160+
class IconColon extends StatelessWidget {
161+
final bool enable;
162+
163+
final Size size;
164+
165+
const IconColon({Key key, this.enable = true, this.size = const Size(10, 17)})
166+
: super(key: key);
167+
@override
168+
Widget build(BuildContext context) {
169+
return _Material(
170+
size: size,
171+
srcOffset: enable ? const Offset(229, 25) : const Offset(243, 25),
172+
srcSize: _DIGITAL_ROW_SIZE,
173+
);
174+
}
175+
}
176+
177+
/// a single digital
178+
class Digital extends StatelessWidget {
179+
///number 0 - 9
180+
///or null indicate it is invalid
181+
final int digital;
182+
183+
final Size size;
184+
185+
Digital(this.digital, {Key key, this.size = const Size(10, 17)})
186+
: assert(digital == null || (digital <= 9 && digital >= 0)),
187+
super(key: key);
188+
189+
@override
190+
Widget build(BuildContext context) {
191+
return _Material(
192+
size: size,
193+
srcOffset: _getDigitalOffset(),
194+
srcSize: _DIGITAL_ROW_SIZE,
195+
);
196+
}
197+
198+
Offset _getDigitalOffset() {
199+
int offset = digital ?? 10;
200+
final dx = 75.0 + 14 * offset;
201+
return Offset(dx, 25);
202+
}
203+
}
204+
205+
class _Material extends StatelessWidget {
206+
//the size off widget
207+
final Size size;
208+
209+
final Size srcSize;
210+
211+
final Offset srcOffset;
212+
213+
const _Material(
214+
{Key key,
215+
@required this.size,
216+
@required this.srcSize,
217+
@required this.srcOffset})
218+
: super(key: key);
219+
220+
@override
221+
Widget build(BuildContext context) {
222+
return CustomPaint(
223+
foregroundPainter: _MaterialPainter(srcOffset, srcSize),
224+
child: SizedBox.fromSize(
225+
size: size,
226+
),
227+
);
228+
}
229+
}
230+
231+
class _MaterialPainter extends CustomPainter {
232+
///offset to ajust the drawing
233+
final Offset offset;
234+
235+
///the size we pick from [_material]
236+
final Size size;
237+
238+
_MaterialPainter(this.offset, this.size);
239+
240+
Paint _paint = Paint();
241+
242+
@override
243+
void paint(Canvas canvas, Size size) {
244+
final src =
245+
Rect.fromLTWH(offset.dx, offset.dy, this.size.width, this.size.height);
246+
canvas.scale(size.width / this.size.width, size.height / this.size.height);
247+
canvas.drawImageRect(material, src,
248+
Rect.fromLTWH(0, 0, this.size.width, this.size.height), _paint);
249+
}
250+
251+
@override
252+
bool shouldRepaint(_MaterialPainter oldDelegate) {
253+
return oldDelegate.offset != offset || oldDelegate.size != size;
254+
}
255+
}

0 commit comments

Comments
 (0)