Skip to content

GDGOC-SeoulTech/GDGOC-SeoulTech-5th_Flutter_Session_13

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

4 Commits
ย 
ย 
ย 
ย 

Repository files navigation

Cat & Dino Runner๋กœ ๋ฐฐ์šฐ๋Š” Flutter ๊ธฐ์ดˆ

Flutter๋ฅผ ์ฒ˜์Œ ๋ณด๋Š” ์‚ฌ๋žŒ๋„ ์ž‘์€ ๊ฒŒ์ž„ ํ”„๋กœ์ ํŠธ๋ฅผ ๋”ฐ๋ผ ์ฝ์œผ๋ฉฐ ํ•ต์‹ฌ ๊ฐœ๋…์„ ์ตํž ์ˆ˜ ์žˆ๋„๋ก ๋งŒ๋“  ์‹ค์Šต ํ”„๋กœ์ ํŠธ์ž…๋‹ˆ๋‹ค.

์™„์„ฑ๋œ ์•ฑ์€ ํฌ๋กฌ ๊ณต๋ฃก ๊ฒŒ์ž„์ฒ˜๋Ÿผ ์ž๋™์œผ๋กœ ๋‹ฌ๋ฆฌ๋Š” ๋Ÿฌ๋„ˆ ๊ฒŒ์ž„์ž…๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž๋Š” ๊ณ ์–‘์ด ๋˜๋Š” ๊ณต๋ฃก์„ ๊ณ ๋ฅด๊ณ , ์ ํ”„ํ•˜๊ฑฐ๋‚˜ ์ˆ™์—ฌ์„œ ์žฅ์• ๋ฌผ์„ ํ”ผํ•ฉ๋‹ˆ๋‹ค. ๋ณ„๋„ ์ด๋ฏธ์ง€ ์—์…‹์ด๋‚˜ ๊ฒŒ์ž„ ์—”์ง„์€ ์‚ฌ์šฉํ•˜์ง€ ์•Š์•˜๊ณ , Flutter ๊ธฐ๋ณธ ๊ธฐ๋Šฅ๋งŒ์œผ๋กœ ํ™”๋ฉด๊ณผ ์›€์ง์ž„์„ ๋งŒ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค.

์•ฑ ์ฝ”๋“œ๋Š” dino ํด๋”์— ์žˆ์Šต๋‹ˆ๋‹ค.

๋จผ์ € ๋ณผ ํŒŒ์ผ

ํŒŒ์ผ ์—ญํ•  ์ฒ˜์Œ ๋ณผ ๋•Œ ์ง‘์ค‘ํ•  ๋‚ด์šฉ
dino/lib/main.dart ์•ฑ ์‹คํ–‰, ๊ฒŒ์ž„ ์ƒํƒœ, ์ž…๋ ฅ ์ฒ˜๋ฆฌ, ํ™”๋ฉด ๊ทธ๋ฆฌ๊ธฐ Flutter ์•ฑ์ด ์‹œ์ž‘๋˜๊ณ  ํ™”๋ฉด์ด ๋ฐ”๋€Œ๋Š” ํ๋ฆ„
dino/pubspec.yaml ํ”„๋กœ์ ํŠธ ์ด๋ฆ„, SDK ๋ฒ„์ „, ์˜์กด์„ฑ ์„ค์ • Flutter ํ”„๋กœ์ ํŠธ๊ฐ€ ์–ด๋–ค ํŒจํ‚ค์ง€๋ฅผ ์“ฐ๋Š”์ง€
dino/test/widget_test.dart ํ™”๋ฉด ๋™์ž‘ ํ…Œ์ŠคํŠธ ๋ฒ„ํŠผ ์„ ํƒ, ๊ฒŒ์ž„ ์‹œ์ž‘, ์žฌ์‹œ์ž‘์„ ์ฝ”๋“œ๋กœ ํ™•์ธํ•˜๋Š” ๋ฐฉ๋ฒ•
dino/README.md ์•ฑ ํด๋”์šฉ ๊ฐ„๋‹จ ์‹คํ–‰ ์•ˆ๋‚ด ์‹คํ–‰ ๋ช…๋ น๋งŒ ๋น ๋ฅด๊ฒŒ ํ™•์ธํ•  ๋•Œ

์ด ํ”„๋กœ์ ํŠธ์—์„œ ๋ฐฐ์šฐ๋Š” ๊ฒƒ

์ด ํ”„๋กœ์ ํŠธ๋Š” Flutter์˜ ๊ธฐ์ดˆ ์œ„์ ฏ ์•ฑ์—์„œ ํ•œ ๋‹จ๊ณ„ ๋” ๋‚˜์•„๊ฐ€ โ€œ์ง์ ‘ ๊ทธ๋ฆฌ๋Š” ํ™”๋ฉดโ€๊ณผ โ€œ์‹œ๊ฐ„์— ๋”ฐ๋ผ ์›€์ง์ด๋Š” ์ƒํƒœโ€๋ฅผ ๋‹ค๋ฃน๋‹ˆ๋‹ค.

  • MaterialApp, Scaffold: Flutter ์•ฑ์˜ ๊ธฐ๋ณธ ๊ป๋ฐ๊ธฐ ๋งŒ๋“ค๊ธฐ
  • StatefulWidget, setState: ์ ์ˆ˜, ์œ„์น˜, ๊ฒŒ์ž„ ์ƒํƒœ์ฒ˜๋Ÿผ ๋ฐ”๋€Œ๋Š” ๊ฐ’ ๊ด€๋ฆฌํ•˜๊ธฐ
  • GestureDetector, Focus: ํ„ฐ์น˜์™€ ํ‚ค๋ณด๋“œ ์ž…๋ ฅ ๋ฐ›๊ธฐ
  • AnimationController: ๋งค ํ”„๋ ˆ์ž„ ๊ฒŒ์ž„ ์ƒํƒœ ๊ฐฑ์‹ ํ•˜๊ธฐ
  • CustomPainter: ์ด๋ฏธ์ง€ ์—†์ด ์บ”๋ฒ„์Šค์— ์บ๋ฆญํ„ฐ์™€ ์žฅ์• ๋ฌผ ๊ทธ๋ฆฌ๊ธฐ
  • Rect.overlaps: ์บ๋ฆญํ„ฐ์™€ ์žฅ์• ๋ฌผ์˜ ์ถฉ๋Œ ํŒ์ •ํ•˜๊ธฐ
  • flutter_test: ํ™”๋ฉด์— ์›ํ•˜๋Š” ๋ฌธ๊ตฌ์™€ ๋ฒ„ํŠผ์ด ๋‚˜์˜ค๋Š”์ง€ ํ…Œ์ŠคํŠธํ•˜๊ธฐ

ํด๋” ๊ตฌ์กฐ

GDGOC-SeoulTech-5th_Flutter_Session_13/
  README.md
  dino/
    lib/
      main.dart
    test/
      widget_test.dart
    pubspec.yaml
    macos/
    web/
    android/
    ios/
    windows/
    linux/

Flutter๋Š” ํ•˜๋‚˜์˜ ์ฝ”๋“œ๋กœ ์—ฌ๋Ÿฌ ํ”Œ๋žซํผ์„ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ํ”„๋กœ์ ํŠธ๋„ web, macos, windows, linux, android, ios ํด๋”๊ฐ€ ํ•จ๊ป˜ ์ƒ์„ฑ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ์‹ค์ œ ๊ฒŒ์ž„ ๋กœ์ง์€ ๋Œ€๋ถ€๋ถ„ dino/lib/main.dart์— ๋“ค์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

์•ฑ์ด ์‹œ์ž‘๋˜๋Š” ํ๋ฆ„

Flutter ์•ฑ์€ main() ํ•จ์ˆ˜์—์„œ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค.

void main() {
  runApp(const MyApp());
}

runApp์€ Flutter์—๊ฒŒ โ€œ์ด ์œ„์ ฏ์„ ํ™”๋ฉด์— ์˜ฌ๋ ค๋ผโ€๋ผ๊ณ  ์•Œ๋ ค์ฃผ๋Š” ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ๋Š” MyApp์ด ์•ฑ์˜ ๊ฐ€์žฅ ๋ฐ”๊นฅ ์œ„์ ฏ์ž…๋‹ˆ๋‹ค.

MyApp์€ MaterialApp์„ ๋งŒ๋“ค๊ณ , ์‹ค์ œ ๊ฒŒ์ž„ ํ™”๋ฉด์ธ DinoGamePage๋ฅผ ์ฒซ ํ™”๋ฉด์œผ๋กœ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค.

์ƒํƒœ ๊ด€๋ฆฌ: ํ™”๋ฉด์ด ๋ฐ”๋€Œ๋Š” ์ด์œ 

๊ฒŒ์ž„์€ ๊ณ„์† ์ƒํƒœ๊ฐ€ ๋ฐ”๋€๋‹ˆ๋‹ค. ์‹œ์ž‘ ์ „์ธ์ง€, ํ”Œ๋ ˆ์ด ์ค‘์ธ์ง€, ๊ฒŒ์ž„ ์˜ค๋ฒ„์ธ์ง€์— ๋”ฐ๋ผ ํ™”๋ฉด๊ณผ ์ž…๋ ฅ ๋™์ž‘์ด ๋‹ฌ๋ผ์ง‘๋‹ˆ๋‹ค.

์ด ์ƒํƒœ๋Š” DinoGameStatus enum์œผ๋กœ ํ‘œํ˜„ํ•ฉ๋‹ˆ๋‹ค.

enum DinoGameStatus { idle, playing, gameOver }
  • idle: ์•„์ง ์‹œ์ž‘ํ•˜์ง€ ์•Š์€ ์ƒํƒœ
  • playing: ๊ฒŒ์ž„์ด ์ง„ํ–‰ ์ค‘์ธ ์ƒํƒœ
  • gameOver: ์ถฉ๋Œํ•ด์„œ ๋‹ค์‹œ ์‹œ์ž‘์„ ๊ธฐ๋‹ค๋ฆฌ๋Š” ์ƒํƒœ

์บ๋ฆญํ„ฐ ์„ ํƒ์€ RunnerCharacter enum์œผ๋กœ ๊ด€๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

enum RunnerCharacter { cat, dino }

์‚ฌ์šฉ์ž๊ฐ€ ๊ณ ์–‘์ด ๋˜๋Š” ๊ณต๋ฃก์„ ์„ ํƒํ•˜๋ฉด ์ œ๋ชฉ, ์บ๋ฆญํ„ฐ ๊ทธ๋ฆผ, ์žฅ์• ๋ฌผ ๋ชจ์–‘์ด ํ•จ๊ป˜ ๋ฐ”๋€๋‹ˆ๋‹ค.

StatefulWidget๊ณผ setState

Flutter์—์„œ ํ™”๋ฉด์— ๋ณด์ด๋Š” ๊ฐ’์ด ๋ฐ”๋€Œ์–ด์•ผ ํ•˜๋ฉด ๋ณดํ†ต StatefulWidget์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ด ํ”„๋กœ์ ํŠธ์˜ ํ•ต์‹ฌ ํ™”๋ฉด์ธ DinoGamePage๊ฐ€ ๊ทธ ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค.

๊ฒŒ์ž„ ์ƒํƒœ๋Š” _DinoGamePageState ์•ˆ์˜ ๋ณ€์ˆ˜๋“ค๋กœ ๊ด€๋ฆฌ๋ฉ๋‹ˆ๋‹ค.

DinoGameStatus _status = DinoGameStatus.idle;
RunnerCharacter _character = RunnerCharacter.cat;
double _dinoLift = 0;
double _velocityY = 0;
double _obstacleX = 980;
double _speed = _baseSpeed;
double _distance = 0;
int _highScore = 0;
bool _isDucking = false;

๊ฐ ๋ณ€์ˆ˜๋Š” ๋‹ค์Œ ์˜๋ฏธ๋ฅผ ๊ฐ€์ง‘๋‹ˆ๋‹ค.

  • _status: ํ˜„์žฌ ๊ฒŒ์ž„ ์ƒํƒœ
  • _character: ์„ ํƒํ•œ ์บ๋ฆญํ„ฐ
  • _dinoLift: ์บ๋ฆญํ„ฐ๊ฐ€ ๋ฐ”๋‹ฅ์—์„œ ๋–  ์žˆ๋Š” ๋†’์ด
  • _velocityY: ์ ํ”„ ์ค‘ ์œ„์•„๋ž˜ ์†๋„
  • _obstacleX: ์žฅ์• ๋ฌผ์˜ ๊ฐ€๋กœ ์œ„์น˜
  • _speed: ๊ฒŒ์ž„ ์†๋„
  • _distance: ์ ์ˆ˜๋ฅผ ๊ณ„์‚ฐํ•˜๊ธฐ ์œ„ํ•œ ๋ˆ„์  ๊ฑฐ๋ฆฌ
  • _highScore: ์ตœ๊ณ  ์ ์ˆ˜
  • _isDucking: ์ˆ™์ด๊ณ  ์žˆ๋Š”์ง€ ์—ฌ๋ถ€

๊ฐ’์ด ๋ฐ”๋€ ๋’ค ํ™”๋ฉด๋„ ๋‹ค์‹œ ๊ทธ๋ ค์•ผ ํ•  ๋•Œ๋Š” setState๋ฅผ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค. Flutter๋Š” setState๊ฐ€ ํ˜ธ์ถœ๋˜๋ฉด ํ•„์š”ํ•œ ๋ถ€๋ถ„์„ ๋‹ค์‹œ ๊ทธ๋ฆฝ๋‹ˆ๋‹ค.

๊ฒŒ์ž„ ๋ฃจํ”„: AnimationController

์ผ๋ฐ˜ ์•ฑ์€ ์‚ฌ์šฉ์ž๊ฐ€ ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅผ ๋•Œ๋งŒ ํ™”๋ฉด์ด ๋ฐ”๋€Œ๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๊ฒŒ์ž„์€ ์‚ฌ์šฉ์ž๊ฐ€ ์•„๋ฌด๊ฒƒ๋„ ํ•˜์ง€ ์•Š์•„๋„ ๋งค ์ˆœ๊ฐ„ ์บ๋ฆญํ„ฐ์™€ ์žฅ์• ๋ฌผ์ด ์›€์ง์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์ด ํ”„๋กœ์ ํŠธ๋Š” AnimationController๋ฅผ ๊ฒŒ์ž„ ๋ฃจํ”„์ฒ˜๋Ÿผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

_gameLoop = AnimationController(
  vsync: this,
  duration: const Duration(days: 1),
)..addListener(_tick);

addListener(_tick) ๋•Œ๋ฌธ์— ์• ๋‹ˆ๋ฉ”์ด์…˜์ด ์ง„ํ–‰๋˜๋Š” ๋™์•ˆ _tick์ด ๋ฐ˜๋ณตํ•ด์„œ ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค.

_tick์—์„œ๋Š” ๋‹ค์Œ ์ผ์„ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

  • ์ด์ „ ํ”„๋ ˆ์ž„๊ณผ ํ˜„์žฌ ํ”„๋ ˆ์ž„์˜ ์‹œ๊ฐ„ ์ฐจ์ด ๊ณ„์‚ฐ
  • ์ค‘๋ ฅ ์ ์šฉ
  • ์ ํ”„ ์œ„์น˜ ๊ฐฑ์‹ 
  • ์žฅ์• ๋ฌผ ์ด๋™
  • ํ”Œ๋ ˆ์ด ๊ฐ€๋Šฅํ•œ ์ตœ์†Œ ์žฅ์• ๋ฌผ ๊ฐ„๊ฒฉ ๋ณด์žฅ
  • ์ ์ˆ˜ ์ฆ๊ฐ€
  • ์†๋„ ์ฆ๊ฐ€
  • ์ถฉ๋Œ ๊ฒ€์‚ฌ
  • ๊ฒŒ์ž„ ์˜ค๋ฒ„ ์ฒ˜๋ฆฌ

์—ฌ๊ธฐ์„œ ์ค‘์š”ํ•œ ์ ์€ โ€œํ”„๋ ˆ์ž„ ์ˆ˜โ€๊ฐ€ ์•„๋‹ˆ๋ผ โ€œ์ง€๋‚œ ์‹œ๊ฐ„โ€์„ ๊ธฐ์ค€์œผ๋กœ ์›€์ง์ž„์„ ๊ณ„์‚ฐํ•œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ๊ธฐ๊ธฐ ์„ฑ๋Šฅ์ด ๋‹ฌ๋ผ๋„ ๊ฒŒ์ž„ ์†๋„๊ฐ€ ๋น„๊ต์  ์ผ์ •ํ•˜๊ฒŒ ์œ ์ง€๋ฉ๋‹ˆ๋‹ค.

๋‚œ์ด๋„์™€ ์žฅ์• ๋ฌผ ๊ฐ„๊ฒฉ

์žฅ์• ๋ฌผ์€ ํ•œ ๋ฒˆ์— ํ•˜๋‚˜์”ฉ ๋“ฑ์žฅํ•ฉ๋‹ˆ๋‹ค. ์žฅ์• ๋ฌผ์ด ํ™”๋ฉด ์™ผ์ชฝ ๋ฐ–์œผ๋กœ ๋‚˜๊ฐ€๋ฉด _resetObstacle์ด ๋‹ค์Œ ์žฅ์• ๋ฌผ์„ ํ™”๋ฉด ์˜ค๋ฅธ์ชฝ ๋ฐ”๊นฅ์— ๋‹ค์‹œ ๋ฐฐ์น˜ํ•ฉ๋‹ˆ๋‹ค.

์ ์ˆ˜๊ฐ€ ๋†’์•„์งˆ์ˆ˜๋ก ๊ธฐ๋ณธ ๊ฐ„๊ฒฉ์€ ์ค„์–ด๋“ค์ง€๋งŒ, ๋„ˆ๋ฌด ์ด˜์ด˜ํ•ด์ ธ์„œ ํ”ผํ•  ์ˆ˜ ์—†๋Š” ์ƒํ™ฉ์ด ์ƒ๊ธฐ์ง€ ์•Š๋„๋ก ์ตœ์†Œ ํšŒ๋ณต ์‹œ๊ฐ„์„ ๋‘ก๋‹ˆ๋‹ค.

final playableGap = _speed * _minimumObstacleRecoverySeconds;
_obstacleX = _viewportWidth + max(difficultyGap, playableGap);

_minimumObstacleRecoverySeconds๋Š” ๋‹ค์Œ ์žฅ์• ๋ฌผ๊นŒ์ง€ ์ตœ์†Œํ•œ ํ™•๋ณดํ•  ์‹œ๊ฐ„์„ ๋œปํ•ฉ๋‹ˆ๋‹ค. ํ˜„์žฌ ๊ฐ’์€ 0.9์ดˆ์ž…๋‹ˆ๋‹ค. ์†๋„๊ฐ€ ๋นจ๋ผ์งˆ์ˆ˜๋ก ํ•„์š”ํ•œ ๊ฑฐ๋ฆฌ๋„ ๊ฐ™์ด ๋Š˜์–ด๋‚˜๊ธฐ ๋•Œ๋ฌธ์—, ๋‚œ์ด๋„๋Š” ์˜ฌ๋ผ๊ฐ€๋”๋ผ๋„ ๊ธฐ๋ณธ์ ์œผ๋กœ ๋ฐ˜์‘ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฐ„๊ฒฉ์€ ์œ ์ง€๋ฉ๋‹ˆ๋‹ค.

์ž…๋ ฅ ์ฒ˜๋ฆฌ: ํ„ฐ์น˜์™€ ํ‚ค๋ณด๋“œ

ํ„ฐ์น˜ ์ž…๋ ฅ์€ GestureDetector๊ฐ€ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

GestureDetector(
  onTap: _handleAction,
  onLongPressStart: (_) => _setDucking(true),
  onLongPressEnd: (_) => _setDucking(false),
)
  • ํƒญ: ์‹œ์ž‘, ์ ํ”„, ์žฌ์‹œ์ž‘
  • ๊ธธ๊ฒŒ ๋ˆ„๋ฅด๊ธฐ: ์ˆ™์ด๊ธฐ

ํ‚ค๋ณด๋“œ ์ž…๋ ฅ์€ _onKeyEvent์—์„œ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

  • Space, Enter, ArrowUp: ์‹œ์ž‘, ์ ํ”„, ์žฌ์‹œ์ž‘
  • ArrowDown, S: ์ˆ™์ด๊ธฐ

์ ํ”„ ๋กœ์ง์€ _jump์— ์žˆ๊ณ , ์ˆ™์ด๊ธฐ ๋กœ์ง์€ _setDucking์— ์žˆ์Šต๋‹ˆ๋‹ค.

์ถฉ๋Œ ํŒ์ •

๊ฒŒ์ž„ ์˜ค๋ฒ„๋Š” ์บ๋ฆญํ„ฐ์™€ ์žฅ์• ๋ฌผ์ด ๊ฒน์น  ๋•Œ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. ์ด ํ”„๋กœ์ ํŠธ๋Š” ๋ณต์žกํ•œ ๋ฌผ๋ฆฌ ์—”์ง„ ๋Œ€์‹  Flutter์˜ Rect๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

์ถฉ๋Œ ๊ฒ€์‚ฌ๋Š” _hasCollision์—์„œ ํ•ฉ๋‹ˆ๋‹ค.

final dinoRect = Rect.fromLTWH(
  _dinoX,
  _groundY - _dinoHeight - _dinoLift,
  _dinoWidth,
  _dinoHeight,
).deflate(7);

์บ๋ฆญํ„ฐ์™€ ์žฅ์• ๋ฌผ์„ ๊ฐ๊ฐ ์‚ฌ๊ฐํ˜•์œผ๋กœ ๋ณด๊ณ , ๋‘ ์‚ฌ๊ฐํ˜•์ด ๊ฒน์น˜๋ฉด ์ถฉ๋Œ์ž…๋‹ˆ๋‹ค. deflate๋Š” ์ถฉ๋Œ ์˜์—ญ์„ ์กฐ๊ธˆ ์ค„์ด๋Š” ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค. ์‹ค์ œ ๊ทธ๋ฆผ๋ณด๋‹ค ์ถฉ๋Œ ๋ฐ•์Šค๊ฐ€ ์‚ด์ง ์ž‘์•„์ ธ์„œ ํ”Œ๋ ˆ์ด ๊ฐ๊ฐ์ด ๋” ์ž์—ฐ์Šค๋Ÿฌ์›Œ์ง‘๋‹ˆ๋‹ค.

ํ™”๋ฉด ๊ทธ๋ฆฌ๊ธฐ: CustomPainter

๋ณดํ†ต Flutter ํ™”๋ฉด์€ Text, Container, Column, Row ๊ฐ™์€ ์œ„์ ฏ์„ ์กฐํ•ฉํ•ด์„œ ๋งŒ๋“ญ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๊ฒŒ์ž„์ฒ˜๋Ÿผ ์ž‘์€ ๋ฌผ์ฒด๊ฐ€ ๋งค ํ”„๋ ˆ์ž„ ์›€์ง์ด๋Š” ํ™”๋ฉด์€ ์บ”๋ฒ„์Šค์— ์ง์ ‘ ๊ทธ๋ฆฌ๋Š” ๋ฐฉ์‹์ด ๋” ๋‹จ์ˆœํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด ํ”„๋กœ์ ํŠธ๋Š” DinoGamePainter๊ฐ€ ํ™”๋ฉด ๋Œ€๋ถ€๋ถ„์„ ์ง์ ‘ ๊ทธ๋ฆฝ๋‹ˆ๋‹ค.

paint ๋ฉ”์„œ๋“œ ์•ˆ์—์„œ ๋‹ค์Œ ์š”์†Œ๊ฐ€ ๊ทธ๋ ค์ง‘๋‹ˆ๋‹ค.

  • ๋‚ฎ/๋ฐค ๋ฐฐ๊ฒฝ
  • ๊ตฌ๋ฆ„
  • ์ง€๋ฉด
  • ๊ณ ์–‘์ด ๋˜๋Š” ๊ณต๋ฃก
  • ํ„ธ์‹ค๊ณต ๋˜๋Š” ์„ ์ธ์žฅ
  • ๋‚ ์•„์˜ค๋Š” ์žฅ๋‚œ๊ฐ ๋˜๋Š” ์ต๋ฃก

์บ๋ฆญํ„ฐ ๊ทธ๋ฆผ์€ ์ด๋ฏธ์ง€ ํŒŒ์ผ์ด ์•„๋‹™๋‹ˆ๋‹ค. _drawCat๊ณผ _drawDino์—์„œ ์‚ฌ๊ฐํ˜•๊ณผ ์›์„ ์กฐํ•ฉํ•ด ํ”ฝ์…€ ์Šคํƒ€์ผ๋กœ ์ง์ ‘ ๊ทธ๋ฆฝ๋‹ˆ๋‹ค.

๋‹ฌ๋ฆฌ๊ธฐ ๋‹ค๋ฆฌ ๋ชจ์–‘๊ณผ ๊ณต์ค‘ ์žฅ์• ๋ฌผ์˜ ๋‚ ๊ฐœ ๋ชจ์–‘์€ _animationTime์„ ๊ธฐ์ค€์œผ๋กœ ์ฒœ์ฒœํžˆ ๋ฐ”๋€๋‹ˆ๋‹ค. ์ ์ˆ˜๋กœ ์• ๋‹ˆ๋ฉ”์ด์…˜ ํ”„๋ ˆ์ž„์„ ๋ฐ”๊พธ๋ฉด ์ ์ˆ˜๊ฐ€ ๋นจ๋ฆฌ ์˜ค๋ฅผ์ˆ˜๋ก ์›€์ง์ž„๋„ ๊ณผํ•˜๊ฒŒ ๋นจ๋ผ์งˆ ์ˆ˜ ์žˆ์–ด์„œ, ์‹ค์ œ ์ด๋™ ์†๋„์™€ ๊ทธ๋ฆผ ํ”„๋ ˆ์ž„ ์ „ํ™˜ ์†๋„๋ฅผ ๋ถ„๋ฆฌํ–ˆ์Šต๋‹ˆ๋‹ค.

ํ…Œ์ŠคํŠธ๋Š” ๋ฌด์—‡์„ ํ™•์ธํ•˜๋‚˜

ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋Š” dino/test/widget_test.dart์— ์žˆ์Šต๋‹ˆ๋‹ค.

์ด ํŒŒ์ผ์€ ์•ฑ์„ ์‹ค์ œ๋กœ ์‹คํ–‰ํ•˜์ง€ ์•Š๊ณ ๋„ ํ™”๋ฉด์˜ ์ฃผ์š” ํ๋ฆ„์„ ๊ฒ€์‚ฌํ•ฉ๋‹ˆ๋‹ค.

  • ์‹œ์ž‘ ํ™”๋ฉด์— ์ ์ˆ˜์™€ ์•ˆ๋‚ด ๋ฌธ๊ตฌ๊ฐ€ ๋ณด์ด๋Š”์ง€
  • ๊ณ ์–‘์ด/๊ณต๋ฃก ์„ ํƒ ๋ฒ„ํŠผ์ด ์žˆ๋Š”์ง€
  • ๊ณต๋ฃก ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด ์ œ๋ชฉ์ด DINO RUNNER๋กœ ๋ฐ”๋€Œ๋Š”์ง€
  • ๊ฒŒ์ž„ ํ™”๋ฉด์„ ํƒญํ•˜๋ฉด ๊ฒŒ์ž„์ด ์‹œ์ž‘๋˜๋Š”์ง€
  • ๊ฒŒ์ž„ ์˜ค๋ฒ„ ์ƒํƒœ์—์„œ ๋‹ค์‹œ ์‹œ์ž‘ํ•  ์ˆ˜ ์žˆ๋Š”์ง€

์˜ˆ๋ฅผ ๋“ค์–ด tester.tap์€ ํ…Œ์ŠคํŠธ ์ค‘ ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋Š” ๋™์ž‘์„ ๋Œ€์‹ ํ•ฉ๋‹ˆ๋‹ค.

์‹คํ–‰ ๋ฐฉ๋ฒ•

๋จผ์ € Flutter SDK๊ฐ€ ์„ค์น˜๋˜์–ด ์žˆ๊ณ  flutter doctor์—์„œ ์‚ฌ์šฉํ•  ๋Œ€์ƒ ๊ธฐ๊ธฐ ๋˜๋Š” ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์žกํžˆ๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.

flutter doctor

ํ”„๋กœ์ ํŠธ ๋ฃจํŠธ์—์„œ ์•ฑ ํด๋”๋กœ ์ด๋™ํ•ฉ๋‹ˆ๋‹ค.

cd dino

์›น ๋ธŒ๋ผ์šฐ์ €์—์„œ ๊ฐœ๋ฐœ ๋ชจ๋“œ๋กœ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.

flutter run -d chrome

macOS ๋ฐ์Šคํฌํ†ฑ ์•ฑ์œผ๋กœ ์‹คํ–‰ํ•˜๋ ค๋ฉด macOS ํ™˜๊ฒฝ์—์„œ ์•„๋ž˜ ๋ช…๋ น์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

flutter run -d macos

์—ฐ๊ฒฐ๋œ ์‹คํ–‰ ๋Œ€์ƒ์„ ํ™•์ธํ•˜๋ ค๋ฉด ์•„๋ž˜ ๋ช…๋ น์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

flutter devices

์›น ๋””๋ฒ„๊ทธ ์‹คํ–‰์—์„œ ๋นˆ ํ™”๋ฉด์ด ๋ณด์ด๋ฉด ์ •์  ์›น ๋นŒ๋“œ๋กœ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.

flutter build web
cd build/web
python -m http.server 5178 --bind 127.0.0.1

Windows์—์„œ python ๋ช…๋ น์ด ๋™์ž‘ํ•˜์ง€ ์•Š์œผ๋ฉด py -m http.server 5178 --bind 127.0.0.1์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

๋ธŒ๋ผ์šฐ์ €์—์„œ ์•„๋ž˜ ์ฃผ์†Œ๋ฅผ ์—ฝ๋‹ˆ๋‹ค.

http://127.0.0.1:5178

๊ฒ€์ฆ ๋ช…๋ น

์•ฑ ํด๋”์ธ dino ์•ˆ์—์„œ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.

dart format lib/main.dart test/widget_test.dart
flutter analyze
flutter test
flutter build web

๊ฐ ๋ช…๋ น์˜ ์˜๋ฏธ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  • dart format: Dart ์ฝ”๋“œ ์Šคํƒ€์ผ ์ •๋ฆฌ
  • flutter analyze: ๋ฌธ๋ฒ•, ํƒ€์ž…, ๊ถŒ์žฅ ๊ทœ์น™ ๊ฒ€์‚ฌ
  • flutter test: ํ…Œ์ŠคํŠธ ์‹คํ–‰
  • flutter build web: ์›น ๋ฐฐํฌ์šฉ ๋นŒ๋“œ ์ƒ์„ฑ

์ถ”์ฒœ ์ฝ๋Š” ์ˆœ์„œ

์ฒ˜์Œ Flutter๋ฅผ ๋ณธ๋‹ค๋ฉด ์•„๋ž˜ ์ˆœ์„œ๋กœ ์ฝ๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.

  1. dino/pubspec.yaml์—์„œ ํ”„๋กœ์ ํŠธ ์„ค์ • ํ™•์ธ
  2. main()๊ณผ MyApp์œผ๋กœ ์•ฑ ์‹œ์ž‘ ํ๋ฆ„ ํ™•์ธ
  3. DinoGamePage์—์„œ ์ƒํƒœ ๋ณ€์ˆ˜๊ฐ€ ์–ด๋–ป๊ฒŒ ์„ ์–ธ๋˜๋Š”์ง€ ํ™•์ธ
  4. _onKeyEvent์™€ GestureDetector์—์„œ ์ž…๋ ฅ ์ฒ˜๋ฆฌ ํ™•์ธ
  5. _tick์—์„œ ๊ฒŒ์ž„์ด ๋งค ํ”„๋ ˆ์ž„ ๊ฐฑ์‹ ๋˜๋Š” ๋ฐฉ์‹ ํ™•์ธ
  6. _resetObstacle์—์„œ ์žฅ์• ๋ฌผ ๊ฐ„๊ฒฉ์„ ์กฐ์ ˆํ•˜๋Š” ๋ฐฉ์‹ ํ™•์ธ
  7. DinoGamePainter์—์„œ ํ™”๋ฉด์„ ์ง์ ‘ ๊ทธ๋ฆฌ๋Š” ๋ฐฉ์‹ ํ™•์ธ
  8. widget_test.dart์—์„œ UI ๋™์ž‘์„ ํ…Œ์ŠคํŠธํ•˜๋Š” ๋ฐฉ์‹ ํ™•์ธ

ํ•ต์‹ฌ ์ •๋ฆฌ

  • Flutter ์•ฑ์€ main()์—์„œ ์‹œ์ž‘ํ•ด ์œ„์ ฏ์„ ํ™”๋ฉด์— ์˜ฌ๋ฆฝ๋‹ˆ๋‹ค.
  • ํ™”๋ฉด์— ๋ฐ”๋€Œ๋Š” ๊ฐ’์ด ์žˆ์œผ๋ฉด StatefulWidget๊ณผ setState๋กœ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ๊ฒŒ์ž„์ฒ˜๋Ÿผ ๊ณ„์† ์›€์ง์ด๋Š” ํ™”๋ฉด์€ AnimationController๋กœ ๋ฐ˜๋ณต ๊ฐฑ์‹ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • CustomPainter๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ด๋ฏธ์ง€ ์—†์ด๋„ ์บ”๋ฒ„์Šค์— ์ง์ ‘ ์บ๋ฆญํ„ฐ์™€ ๋ฐฐ๊ฒฝ์„ ๊ทธ๋ฆด ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์žฅ์• ๋ฌผ ๊ฐ„๊ฒฉ์€ ํ˜„์žฌ ์†๋„๋ฅผ ๊ณ ๋ คํ•ด โ€œํ”ผํ•  ์ˆ˜ ์žˆ๋Š” ์ตœ์†Œ ์‹œ๊ฐ„โ€์„ ๋ณด์žฅํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  • ์›€์ง์ž„ ์• ๋‹ˆ๋ฉ”์ด์…˜์€ ์ ์ˆ˜๋ณด๋‹ค ๋ณ„๋„ ์‹œ๊ฐ„ ๊ฐ’์„ ๊ธฐ์ค€์œผ๋กœ ๋‘๋Š” ํŽธ์ด ์•ˆ์ •์ ์ž…๋‹ˆ๋‹ค.
  • ํ‚ค๋ณด๋“œ์™€ ํ„ฐ์น˜ ์ž…๋ ฅ์€ ๊ฐ๊ฐ Focus, GestureDetector๋กœ ๋ฐ›์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์ž‘์€ ๊ฒŒ์ž„์ด๋ผ๋ฉด ๋ณ„๋„ ๊ฒŒ์ž„ ์—”์ง„ ์—†์ด Flutter ๊ธฐ๋ณธ ๊ธฐ๋Šฅ๋งŒ์œผ๋กœ๋„ ์ถฉ๋ถ„ํžˆ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors