remove vision_challenge

vision_challenge doesn't build on the dev channel
pull/697/head
John Ryan 4 years ago
parent fa674cc85f
commit 5ced85b7eb

@ -9,7 +9,6 @@ directories:
- particle_background/web
- slide_puzzle/web
- timeflow/web
- vision_challenge/web
- form_app/web
- web_dashboard/web
- place_tracker/web

@ -524,24 +524,6 @@ samples:
web: web/timeflow
type: demo
- name: Vision Challenge
author: Yukkei Choi
screenshots:
- url: images/vision_challenge1.png
alt: Vision Challenge screenshot
- url: images/vision_challenge2.png
alt: Vision Challenge screenshot
source: https://github.com/flutter/samples/tree/master/web/vision_challenge
description: >
A fun game to test your color perception abilities.
difficulty: advanced
widgets: []
packages: []
platforms: ['web']
tags: ['demo', 'game']
web: web/vision_challenge
type: demo
- name: Dice
author: Jaime Blasco
screenshots:

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 438 KiB

@ -1,25 +0,0 @@
Copyright 2019 Yukkei Choi
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

@ -1,55 +0,0 @@
A fun game to test your color perception abilities.
Contributed as part of the Flutter Create 5K challenge by Yukkei Choi.
## How to play
Tap the unique color block as fast as possible.
## Features
1. Each round when user taps the unique color block, score will be increased by one.
2. Timer: 30 seconds countdown.
3. Color difference will be stepwise reduced when user reached a higher score.
4. If it is difficult to distinguish the unique color block, user can "SHAKE" the device to shift to another theme color, while the position of the unique color block still keep the same.
5. Provide a restart button at the end, user can infinitely play again without relaunching the app.
6. After each replay, game board's theme color will be different from the previous play.
7. Give user a grade based on the final score:
| score range | grade |
|-------------|-------|
| 0 - 9 | Fail |
| 10 - 19 | D |
| 20 - 29 | C |
| 30 - 34 | B |
| 35 - 39 | B+ |
| 40 - 44 | A |
| 45 or above | A+ |
## Graphics
1. I created all graphics used on the app by using Photoshop.
2. Flutter is great and now I'm able to demonstrate my artwork on the app into practice.
## Techniques used
1. Use stateful widget to run the timer countdown animation.
2. Since only 5kb is allowed, the grade is calculated by using math, instead of writing if-else statement.
3. Use redux to store the game states:
| state | description | data type |
|-------|----------------------------------------------------------|-------------------|
| score | Store the player score | int |
| board | Locate the position of unique color block | [[int],[int],...] |
| count | Count the no. of replay, for switching the theme color | int |
| page | Current page / game status | int |
| page | description |
|------|----------------------------------------------------------------|
| -1 | First launch the app, show the welcome screen with instruction |
| 0 | Game in progress |
| 1 | Game end, show result |
## Limitation
Limited to portrait view.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 117 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 113 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 112 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 113 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 116 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 111 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 114 KiB

@ -1,10 +0,0 @@
[
{
"family": "MaterialIcons",
"fonts": [
{
"asset": "https://fonts.gstatic.com/s/materialicons/v42/flUhRq6tzZclQEJ-Vdg-IuiaDsNcIhQ8tQ.woff2"
}
]
}
]

Binary file not shown.

Before

Width:  |  Height:  |  Size: 703 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 343 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

@ -1,207 +0,0 @@
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:flutter_redux/flutter_redux.dart';
import 'package:redux/redux.dart';
setText(text, size, color) => Text(text,
style: TextStyle(
fontSize: size,
color: color,
fontWeight: FontWeight.bold,
decoration: TextDecoration.none));
pad(double left, double top) => EdgeInsets.fromLTRB(left, top, 0, 0);
setBg(name) => BoxDecoration(
image: DecorationImage(
fit: BoxFit.cover,
alignment: Alignment.topLeft,
image: AssetImage(name)));
class Game extends StatelessWidget {
final Store<AppState> store;
Game(this.store);
_grade(int score) => [10, 20, 30, 35, 40, 45, 99]
.where((i) => i > score)
.reduce(min)
.toString();
_createBoard(double size, List<List<int>> blocks, int depth,
MaterialColor color) =>
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: blocks
.map((cols) => Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: cols
.map((item) => Flexible(
child: GestureDetector(
onTap: () {
if (item == 1) store.dispatch(Action.next);
},
child: Container(
width: size,
height: size,
color: item > 0 ? color[depth] : color)),
))
.toList()))
.toList());
@override
Widget build(BuildContext context) => StoreConnector<AppState, AppState>(
// onInit: (state) => ShakeDetector.autoStart(
// onPhoneShake: () => store.dispatch(Action.shake)),
converter: (store) => store.state,
builder: (context, state) {
var w = MediaQuery.of(context).size.height / 16 * 9,
size = w / (state.board.length + 1),
depth = [1 + state.score ~/ 5, 4].reduce(min) * 100,
colors = [
Colors.blue,
Colors.orange,
Colors.pink,
Colors.purple,
Colors.cyan
];
return Scaffold(
backgroundColor: Color(0xFFBCE1F6),
body: Center(
child: SizedBox(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.height / 16 * 9,
child: Container(
decoration: setBg(state.page < 0 ? 'p0.jpg' : 'p1.jpg'),
child: state.page >= 0
? Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Container(
height: w * 0.325,
padding: pad(0, w * 0.145),
child: setText(state.score.toString(),
w * 0.2, Colors.white)),
Container(
height: w * 0.35,
padding: pad(w * 0.69, state.page * 7.0),
child: state.page < 1
? Timer(
onEnd: () =>
store.dispatch(Action.end),
width: w)
: setText('End', w * 0.08, Colors.red)),
state.page < 1
? Container(
width: w,
height: w * 1.05,
padding: pad(0, w * 0.05),
child: _createBoard(
size,
state.board,
depth,
colors[
state.count % colors.length]))
: Container(
width: w,
height: w,
decoration:
setBg(_grade(state.score) + '.png'))
])
: Container()),
),
),
floatingActionButton: state.page != 0
? Container(
// width: w * 0.2,
// height: w * 0.2,
child: FloatingActionButton(
child: Icon(
state.page < 1 ? Icons.play_arrow : Icons.refresh),
onPressed: () => store.dispatch(Action.start)))
: Container());
});
}
class Timer extends StatefulWidget {
Timer({this.onEnd, this.width});
final VoidCallback onEnd;
final double width;
@override
_TimerState createState() => _TimerState();
}
class _TimerState extends State<Timer> with TickerProviderStateMixin {
Animation _animate;
int _sec = 31;
@override
void initState() {
super.initState();
_animate = StepTween(begin: _sec, end: 0).animate(
AnimationController(duration: Duration(seconds: _sec), vsync: this)
..forward(from: 0.0))
..addStatusListener((AnimationStatus s) {
if (s == AnimationStatus.completed) widget.onEnd();
});
}
@override
Widget build(BuildContext context) => AnimatedBuilder(
animation: _animate,
builder: (BuildContext context, Widget child) => setText(
_animate.value.toString().padLeft(2, '0'),
widget.width * 0.12,
Colors.green));
}
//REDUX
@immutable
class AppState {
final int score, page, count;
final List<List<int>> board;
AppState({this.score, this.page, this.board, this.count});
AppState.init()
: score = 0,
page = -1,
count = 0,
board = newBoard(0);
}
enum Action { next, end, start, shake }
AppState reducer(AppState s, act) {
switch (act) {
case Action.next:
return AppState(
score: s.score + 1,
page: s.page,
count: s.count,
board: newBoard(s.score + 1));
case Action.end:
return AppState(
score: s.score, page: 1, count: s.count + 1, board: s.board);
case Action.start:
return AppState(score: 0, page: 0, count: s.count, board: newBoard(0));
case Action.shake:
return AppState(
score: s.score, page: s.page, count: s.count + 1, board: s.board);
default:
return s;
}
}
List<List<int>> newBoard(score) {
var size = score < 7 ? score + 3 : 10,
rng = Random(),
bingoRow = rng.nextInt(size),
bingoCol = rng.nextInt(size);
List<List<int>> board = [];
for (var i = 0; i < size; i++) {
List<int> row = [];
for (var j = 0; j < size; j++)
row.add(i == bingoRow && j == bingoCol ? 1 : 0);
board.add(row);
}
return board;
}

@ -1,20 +0,0 @@
import 'package:flutter/material.dart';
import 'package:flutter_redux/flutter_redux.dart';
import 'package:redux/redux.dart';
import 'game.dart';
void main() {
final store = Store<AppState>(
reducer,
initialState: AppState.init(),
);
runApp(
StoreProvider<AppState>(
store: store,
child: MaterialApp(
home: Game(store),
),
),
);
}

@ -1,64 +0,0 @@
# Generated by pub
# See https://dart.dev/tools/pub/glossary#lockfile
packages:
characters:
dependency: transitive
description:
name: characters
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.0-nullsafety.5"
collection:
dependency: transitive
description:
name: collection
url: "https://pub.dartlang.org"
source: hosted
version: "1.15.0-nullsafety.5"
flutter:
dependency: "direct main"
description: flutter
source: sdk
version: "0.0.0"
flutter_redux:
dependency: "direct main"
description:
name: flutter_redux
url: "https://pub.dartlang.org"
source: hosted
version: "0.5.4"
meta:
dependency: transitive
description:
name: meta
url: "https://pub.dartlang.org"
source: hosted
version: "1.3.0-nullsafety.6"
redux:
dependency: "direct main"
description:
name: redux
url: "https://pub.dartlang.org"
source: hosted
version: "3.0.0"
sky_engine:
dependency: transitive
description: flutter
source: sdk
version: "0.0.99"
typed_data:
dependency: transitive
description:
name: typed_data
url: "https://pub.dartlang.org"
source: hosted
version: "1.3.0-nullsafety.5"
vector_math:
dependency: transitive
description:
name: vector_math
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.0-nullsafety.5"
sdks:
dart: ">=2.12.0-0 <3.0.0"

@ -1,25 +0,0 @@
name: vision_challenge
author: Yukkei Choi
environment:
sdk: ">=2.10.0 <3.0.0"
dependencies:
flutter:
sdk: flutter
redux: ^3.0.0
flutter_redux: ^0.5.3
flutter:
uses-material-design: true
assets:
- 10.png
- 20.png
- 30.png
- 35.png
- 40.png
- 45.png
- 99.png
- p0.jpg
- p1.jpg
- preview.png

@ -1,11 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title></title>
<script defer src="main.dart.js" type="application/javascript"></script>
</head>
<body>
</body>
</html>
Loading…
Cancel
Save