Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
31 |
Tags
- 복권번호예측 #Flutter #플러터 #Provider
- 복권번호예측기 #Flutter #adMob #광고배너 #리워드형광고
- 초성게임앱 #플러터앱 #플러터카운트다운
- AAB
- 플레이스토어 앱등록
- 유니티게임 #상점만들기 #뽑기구현 #케이디리듬게임
- flutter #android #androidstudio
- Flutter #플러터 #모바일앱만들기 #GetX
- 앱번들
- GetX #CustomScrollView #Flutter
- 플러터 #Flutter #파이어베이스 #firebase #firestore #파이어스토어
- Flutter #플러터 #프로젝트 #파이어베이스 #파이어스토어 #Firebase #FireStore
Archives
- Today
- Total
이코노딩
Flutter Project : 오프라인 게임 지원 앱 만들기 -4 본문
▶Game3(몸으로말해요)
옵션 페이지
몸으로 말해요 게임은 분 단위로 타이머 지정과 게임의 난이도를 위해 주제를 선정 할 수 있게 만들었다.
랜덤은 모든 주제를 섞인채로 진행되게 모든 리스트를 하나의 List로 만들어서 선택창에 넣었다.
●필수 기능
1. 타이머 지정
2. 주제지정
▶코드
class Game3Option extends StatefulWidget {
const Game3Option({Key? key}) : super(key: key);
@override
Game3OptionMenu createState() => Game3OptionMenu();
}
class Game3OptionMenu extends State<Game3Option>{
final List<String>_ListCon = ['동물', '음식', '스포츠', '랜덤'];
final List<String> _ListAnimal = ['캥거루','코알라','하마','토끼','쥐','판다','호랑이','사자','원숭이','뱀'
,'거북이','말','늑대','낙타','치타','고양이','악어','소','고릴라','기린','거위','햄스터','수달','코뿔소','다람쥐','물개','도마뱀','사슴','펭귄','딱따구리','부엉이','앵무새'
,'고슴도치','여우','개구리','타조','돼지','돌고래','상어','오리','양','닭','독수리','백조','까치','곰','두더지','나무늘보','귀뚜라미','토끼','나비','달팽이','사마귀','스컹크','이구아나','모기',
'코끼리','플라밍고','바퀴벌레','벌','고라니'];
final List<String> _ListFood = ['닭발','회','마라탕','브라우니','피자','연어','막창','과일','치킨','타꼬야끼','껍데기','초밥','비빔밥','버블티','김치찌개','냉면','국수','새우','갈비','삼겹살','햄버거'
,'조개구이','떡','쫄면','붕어빵','샤브샤브','호떡','떡볶이','마카롱','카레','돈가스','스테이크','만두','케이크','아이스\n아메리카노','사과','딸기','포도','오이','짜장면','수박','참외','방울\n토마토',
'민트초코','엄마는\n외계인','아몬드\n봉봉','코카콜라','맥주','피자','소주','파인애플','오렌지','레몬','상추','김치','치즈스틱','감자튀김'];
final List<String> _ListSports = ['축구','야구','피구','피겨\n스케이팅','스키','스노보드','미식축구','리듬체조','마라톤','탁구','테니스','배드민턴','농구','봅슬레이','수영','배구','복싱',
'핸드볼','비치\n발리볼','사격','사이클','서핑','스케이트\n보드','스켈레톤','스키점프','승마','아이스\n하키','소프트볼','양궁','역도','유도','컬링','태권도','검도','합기도','펜싱','풋살','다이빙','쿵푸'
,'씨름','도마','철봉','스쿼시','당구','골프','볼링','다트','수구','등산','줄다리기','경마','낚시','장기','체스','바둑','오목','오델로','포커'];
final List<int> _timerList = [1,2,3];
String _selectedCon = '동물';
int _selectedTimer = 1;
void chkList(){
if(_selectedCon == '동물'){
currentList = _ListAnimal;
}else if(_selectedCon == '음식'){
currentList = _ListFood;
}else if(_selectedCon == '스포츠'){
currentList = _ListSports;
}else{//랜덤 리스트 선택시 새로운 List생성
List<String> _randList = [..._ListAnimal, ..._ListSports, ..._ListFood];
currentList = _randList;
}
}
//선택타이머 초단위 계산
void chkTime(){
_currentTimer = _selectedTimer * 60;
}
@override
Widget build(BuildContext context) {
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp, DeviceOrientation.portraitDown]);
return Scaffold(
body: Padding(
padding: EdgeInsets.fromLTRB(20, 40, 20, 0),
child: Column(
children: [
Image.asset("assets/images/logo.png"),
Divider(
height: 30,
color: Colors.lightGreenAccent[400],
),
Stack(children: [
Image.asset("assets/images/mommal.png" ,width: 400, height: 250,),
Positioned(
top: 160,
left: 10,
child: Text("몸으로말해요",
style: TextStyle(
fontSize: 60,
backgroundColor: Colors.white,
color: Colors.tealAccent[700],
fontWeight: FontWeight.bold,
),)),
//howtoplay
Positioned(
top: 80,
left: 280,
child: IconButton(
onPressed: () {
showModalBottomSheet<void>(
context: context,
builder: (BuildContext context) {
return Container(
height: 500,
color: Colors.amber,
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
const Text('1. 타이머와 주제를 지정해주세요, 랜덤 주제는 모든주제가 섞인 모드입니다. \n\n '
'2. 게임시작 버튼을 누르 후 시작버튼을 누릅니다. \n\n'
'3. 주제에따른 단어가 뜨면 몸으로 설명하면서 게임을 즐겨보세요.\n\n'
'4. 맞으면 정답을 모르겠으면 Pass버튼을 눌러주세요.\n\n'
'5. 타이머가 종료되면 맞춘 정답 수가 뜨며 게임오버\n\n'
'Tip 게임 진행 중 멈추고 싶다면 상단 중앙 일시정지 버튼을 눌러주세요.',style: TextStyle(fontSize: 18), textAlign: TextAlign.center,),
ElevatedButton(
child: const Text('닫기'),
onPressed: () => Navigator.pop(context),
)
],
),
),
);
},
);
},
icon: ImageIcon(AssetImage('assets/images/q_mark.png'), size: 80),
iconSize: 80,
color: Colors.lightGreenAccent[400],
),
)
],
),
Container(
padding: EdgeInsets.all(40),
child: Column(
children: [
Row(
children: [
Text("타이머"
, style: TextStyle(
fontSize: 30,
),),
Container(
width: 200,
padding: EdgeInsets.only(left: 20),
child:
DropdownButton(
isExpanded: true,
value: _selectedTimer,
items: _timerList.map((value) {
return DropdownMenuItem(
value: value,
child: Text('$value 분',
textAlign: TextAlign.center,
style: TextStyle(fontSize: 30),),);
}).toList(),
onChanged: (dynamic value){
setState(() {
_selectedTimer = value;
});
},)
)
],
),
Row(
children: [
Text("주제 "
, style: TextStyle(
fontSize: 30,
),),
Container(
width: 190,
padding: EdgeInsets.only(left: 20),
child:
DropdownButton(
isExpanded: true,
value: _selectedCon,
items: _ListCon.map((value) {
return DropdownMenuItem(
value: value,
child: Text('$value',
style: TextStyle(fontSize: 30),),);
}).toList(),
onChanged: (dynamic value){
setState(() {
_selectedCon = value;
});
},)
)
],
),
Container(
padding: EdgeInsets.only(top:60),
child: TextButton(onPressed: () {
SystemChrome.setPreferredOrientations([DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight]);
Navigator.push(
context, MaterialPageRoute(builder: (context) => new PlayInGame3()),
);
chkList();
chkTime();
currentList.shuffle(); //시작 시 List섞어주기
},
child: Text("게임시작",
style: TextStyle(
fontSize: 30.0,
color: Colors.black,
),
),
style: ElevatedButton.styleFrom(
minimumSize: Size(200, 50),
elevation: 10,
primary: Colors.lightGreenAccent[400],
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20)
)
),
),
),
Container(
padding: EdgeInsets.only(top: 40),
child:
TextButton(onPressed: () {
Navigator.pop(context);
Navigator.push(context, MaterialPageRoute(builder: (context) => SelectMenu()));
},
child: Text("뒤로가기",
style: TextStyle(
fontSize: 30.0,
color: Colors.black,
),
),
style: ElevatedButton.styleFrom(
minimumSize: Size(200, 50),
elevation: 10,
primary: Colors.lightGreenAccent[400],
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20)
)
),
),)
],
)
),
]),
)
);
}
}
var currentList; //선택된리스트
var _currentTimer; //선택된타이머
◐ 막힌부분
1. 랜덤 리스트를 생성할 때, List들 밑에 넣은 후 [ ..list,..list] 같이 합치니 에러가 났다. 왜 그런지는 모르겠지만, 함수 안에 넣어 랜덤 선택 시에만 생성하게 해주니 에러없이 잘동작 함.
인게임 페이지
인 게임은 글자가 잘 보이게하기 위해 가로로 진행 함.
●필수기능
1. 게임 진입 시 가로화면 고정
2. 시작 버튼 눌렀을 때 단어 등장
3. 타이머 기능 (초성 게임, 폭탄 게임과 같은 동작)
4. 정답 수 저장 기능
5. 정답 버튼과 Pass버튼
▶코드
class PlayInGame3 extends StatelessWidget {
const PlayInGame3({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: InGame3(),
);
}
}
class InGame3 extends StatefulWidget{
const InGame3({Key? key}) : super(key: key);
@override
InGame3View createState() => InGame3View();
}
//몸으로말해요 게임 창
class InGame3View extends State<InGame3> {
var _playIcon = Icons.play_arrow;
var _playCol = Colors.grey;
var _currentState = '시작';
var correctCnt = 0;
bool checkst = false;
int i = 0;
String con = currentList[0];
int _correct =0;
//정답 수 증가
void incCorrect(){
setState((){
if(isPlaying)
_correct++;
});
}
//단어 넘김
void Next(){
setState((){
if(isPlaying) {
if(currentList.length >= i) {
i++;
con = currentList[i];
}
}
});
}
// 타이머 구성
var time = _currentTimer;
Timer? timer;
var isPlaying = false;
@override
void dispose(){
timer?.cancel();
super.dispose();
}
void start() {
timer = Timer.periodic(Duration(milliseconds: 1000), (timer) {
setState(() {
isPlaying = true;
if(time > 0) {
time--;
}
else if(time == 0){
gameover();
}
});
});
}
void pause(){
timer?.cancel();
setState((){
isPlaying = false;
});
}
//표시되는 글자 수에 따른 폰트 사이즈 지정
double chkFontSize(){
if(con.length == 4)
return 150;
else if(con.length >= 5)
return 120;
else
return 200;
}
//뒤로가기
void back(){
pause();
setState((){
isPlaying = false;
_playIcon =Icons.play_arrow;
_playCol = Colors.grey;
_currentState = '다시시작';
});
showDialog(
context: context,
barrierDismissible: false,
builder: (BuildContext ctx){
return AlertDialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
title: Column(
children: [
new Text('Warning'),
],
),
content: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
Text('게임진행을 멈추고 나가시겠습니까?')
],
),
actions: [
new FlatButton(
child: new Text("나가기"),
onPressed:(){
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp, DeviceOrientation.portraitDown]);
Navigator.pop(ctx);
Navigator.of(context).pop();
Navigator.push(
context, MaterialPageRoute(builder: (context) => Game3()),
);
},
),
new FlatButton(
child: new Text("계속하기"),
onPressed:(){
Navigator.pop(ctx);
},
),
],
);
});
}
//타이머 텍스트
Widget TimerTxt(){
if(time == -100){
return Text(' ',
style: TextStyle(
fontSize: 25,
color: Colors.black,
)
);
}
else{
return Text('$time',
style: TextStyle(
fontSize: 25,
color: Colors.black,
)
);
}
}
//단어 표시 텍스트
Widget GameTxt(){
if(!checkst){ //시작 안 했을때는 아무것도 표시하지 않음
return Text(' ',
style: TextStyle(
fontSize: chkFontSize(),
),);
}else{
return Text('$con',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: chkFontSize(),
));
}
}
//게임오버
void gameover(){
timer?.cancel();
time = -100;
showDialog(
context: context,
barrierDismissible: false,
builder: (BuildContext ctx){
return AlertDialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
title: Column(
children: [
new Text('Result'),
],
),
content: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
Text('정답: $_correct 개')
],
),
actions: [
new FlatButton(
child: new Text("다시하기"),
onPressed:(){
Navigator.of(context).pop();
Navigator.push(
context, MaterialPageRoute(builder: (context) => Game3()),
);
},
),
],
);
});
}
//게임내 필요요소
void _clickTimer(){
setState(() {
if(_playIcon == Icons.play_arrow){
checkst = true;
_playIcon = Icons.pause;
_playCol = Colors.amber;
_currentState = '일시정지';
start();
}else{
_playIcon =Icons.play_arrow;
_playCol = Colors.grey;
_currentState = '다시시작';
pause();
}}
);
}
@override
Widget build(BuildContext context){
SystemChrome.setPreferredOrientations([DeviceOrientation.landscapeLeft,DeviceOrientation.landscapeRight],);
return Scaffold(
body: Padding(
padding: EdgeInsets.fromLTRB(20, 40, 20, 0),
child: Column(
children: [
Row(children: [
Icon(Icons.timer,
size: 50),
Container(
width: 50,
child:TimerTxt(),
),
Container(
padding: EdgeInsets.only(left:40),
child:
TextButton.icon(onPressed: () {
_clickTimer();
},
label: Text('$_currentState',
style: TextStyle(
color: Colors.black,
),
),
icon: Icon(
_playIcon,
size: 30,
color: Colors.black,
),
style: ElevatedButton.styleFrom(
minimumSize: Size(100, 30),
elevation: 10,
primary: _playCol,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(90)
)
),
)
),
Container(
padding: EdgeInsets.only(left: 100),
child: Text('정답: $_correct 개',
style: TextStyle(
fontSize: 30,
color: Colors.blue,
),),
),
Container(
padding: EdgeInsets.only(left: 200),
child:
IconButton(
onPressed: back,
icon: Icon(Icons.arrow_back,
color: Colors.greenAccent[400],),
iconSize: 30,
)),
],),
Center(
child: Container(
height: 260,
child: GameTxt(),)
),
Positioned(
child: Row(
children: [
TextButton(onPressed: () {
incCorrect();
Next();
},
child: Text("정답",
style: TextStyle(
fontSize: 30.0,
color: Colors.black,
),
),
style: ElevatedButton.styleFrom(
minimumSize: Size(200, 50),
elevation: 10,
primary: Colors.blue,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20)
)
),
),
Container(
padding: EdgeInsets.only(left: 300),
child: TextButton(onPressed: () {
Next();
},
child: Text("PASS",
style: TextStyle(
fontSize: 30.0,
color: Colors.white,
),
),
style: ElevatedButton.styleFrom(
minimumSize: Size(200, 50),
elevation: 10,
primary: Colors.redAccent,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20)
)
),
),
)
],
),
)
],
),
)
);
}
}
◐막힌 부분
1. 화면 스크린 회전, 게임 시작시 화면을 회전 시킨채로 고정해야하는 데 옵션창까지는 세로 고정이고 게임 진입 만 가로 고정하는게 막혔었다. 일단 버튼 클리시 화면 전환으로 지정했으나 게임 진행하는동안 고정이 안 되서 게임진행할때도 따로 고정시키고 돌아갈 때 원상복구 시키는 코드를 여러번 넣어줬더니 조금 움직임이 어색하긴하지만, 되긴 함...
게시판은 방학동안 파이어베이스 공부하면서 제작해 볼 예정
'언어 > Dart & Flutter' 카테고리의 다른 글
[Flutter] 내가 보려고 정리한 Provider 예시 (0) | 2022.12.14 |
---|---|
[Flutter] connectivity_plus 네트워크 상태 읽기 (0) | 2022.11.21 |
Flutter Project : 오프라인 게임 지원앱 만들기 -3 (0) | 2022.06.06 |
Flutter Project : 오프라인 게임 지원앱 만들기 -2 (0) | 2022.06.06 |
Flutter Project : 오프라인 게임 지원 앱 만들어보기 (0) | 2022.06.05 |