플러터는 모바일 애플리케이션 개발을 위한 크로스 플랫폼 프레임워크로, 쉽고 간편한 개발을 지원합니다. RxDart는 플러터와 함께 사용할 수 있는 반응형 프로그래밍 라이브러리로, 비동기 작업을 더욱 편리하게 처리할 수 있게 해줍니다. 이번 글에서는 RxDart를 사용하여 간단한 게임을 개발하는 방법을 살펴보겠습니다.
게임 개요
우리의 게임은 간단한 숫자 맞추기 게임입니다. 게임 화면에는 1부터 100까지의 숫자 중 하나가 랜덤으로 표시되며, 사용자는 입력 창에 숫자를 입력하여 맞춰야 합니다. 맞추기 총 시도 횟수가 제한되어 있으며, 정답을 맞추거나 시도 횟수를 모두 사용하면 게임이 종료됩니다.
프로젝트 설정
먼저, Flutter 프로젝트를 생성하고 RxDart 라이브러리를 추가해야 합니다. pubspec.yaml
파일에 아래 내용을 추가해주세요.
dependencies:
rxdart: ^0.26.0
그리고 해당 프로젝트를 업데이트하기 위해 터미널에서 아래 명령어를 실행합니다.
flutter packages get
주요 클래스 및 함수
이번 프로젝트에서는 RxDart
의 PublishSubject
클래스와 BehaviorSubject
클래스, 그리고 Stream
과 StreamController
를 사용합니다.
PublishSubject
: 새로운 이벤트를 발생시키고 해당 이벤트를 구독하는 객체에게 전달합니다.BehaviorSubject
: 가장 최근의 이벤트를 구독하는 객체에게 전달합니다. 초기값을 설정할 수 있으므로, 직전 이벤트 기록을 유지할 수 있습니다.Stream
: 이벤트 발생을 알리고 상태를 전달할 수 있는 객체입니다.StreamController
: 이벤트를 생성하고 이벤트를 전달하는 컨트롤러입니다.
게임 개발
-
main.dart
파일 생성 및 기본 코드 작성먼저,
main.dart
파일을 생성하고 기본 코드를 작성합니다. 이 코드는 앱을 실행하고 화면을 구성하는 역할을 합니다.import 'package:flutter/material.dart'; void main() { runApp(GameApp()); } class GameApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Number Guessing Game', theme: ThemeData( primarySwatch: Colors.blue, ), home: GameScreen(), ); } } class GameScreen extends StatefulWidget { @override _GameScreenState createState() => _GameScreenState(); } class _GameScreenState extends State<GameScreen> { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Number Guessing Game'), ), body: Center( child: Text('Game Screen'), ), ); } }
-
게임 로직 구현
이제 게임 로직을 구현해보겠습니다. 먼저, 게임 화면에서 사용자가 입력하는
TextField
위젯을 추가합니다. 그리고 사용자가 입력한 값을 구독하고, 게임 로직에 따라 상태를 업데이트하도록 코드를 작성합니다.import 'package:rxdart/rxdart.dart'; class _GameScreenState extends State<GameScreen> { TextEditingController _inputController = TextEditingController(); PublishSubject<int>? _guessSubject; BehaviorSubject<bool>? _gameOverSubject; // 게임 로직 초기화 void _initializeGame() { _guessSubject = PublishSubject<int>(); _gameOverSubject = BehaviorSubject<bool>(); // 게임 오버 상태를 확인하여 처리 _gameOverSubject?.listen((gameOver) { if (gameOver) { _guessSubject?.close(); _gameOverSubject?.close(); } }); } @override void initState() { super.initState(); _initializeGame(); } @override void dispose() { _inputController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Number Guessing Game'), ), body: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ TextField( controller: _inputController, keyboardType: TextInputType.number, onChanged: (value) { // 사용자 입력을 발행 _guessSubject?.add(int.parse(value)); }, ), SizedBox(height: 16.0), Text('Guess Result'), ], ), ); } }
이제 사용자가 입력한 값을 게임 로직에서 처리할 수 있도록 준비가 됐습니다.
-
게임 로직 완성
지금까지 작성한 코드에 게임 로직을 추가해보겠습니다. 게임 화면에 숫자를 랜덤으로 표시하고, 사용자가 입력한 값을 비교하여 결과를 표시합니다. 또한, 게임 오버 상태를 체크하여 게임 종료를 처리합니다.
class _GameScreenState extends State<GameScreen> { // ... int _targetNumber = 0; int _attemptCount = 0; bool _gameOver = false; void _startGame() { _gameOver = false; _attemptCount = 0; _targetNumber = _generateTargetNumber(); // 사용자 입력을 구독 _guessSubject?.listen((guessNumber) { if (_gameOver) return; // 이미 게임 종료 상태일 경우 종료 _attemptCount++; if (guessNumber == _targetNumber) { // 정답일 경우 게임 종료 처리 _gameOverSubject?.add(true); } else if (_attemptCount >= 5) { // 시도 횟수 초과 시 게임 종료 처리 _gameOverSubject?.add(true); } else { // 오답일 경우 결과 표시 setState(() { _resultText = guessNumber < _targetNumber ? 'Higher' : 'Lower'; }); } }); } int _generateTargetNumber() { // 1부터 100까지의 랜덤한 숫자 생성 return Random().nextInt(100) + 1; } @override void initState() { super.initState(); _initializeGame(); _startGame(); } @override Widget build(BuildContext context) { // ... } }
이제 게임이 정상적으로 동작하도록 준비가 되었습니다.
실행 결과
위의 코드를 실행하면 다음과 같이 숫자를 맞추는 게임이 화면에 표시됩니다.
사용자는 입력 창에 숫자를 입력하고 제출할 수 있습니다. 맞춘 숫자가 맞으면 정답으로 표시되고, 시도 횟수 초과 시 게임 종료 메시지가 표시됩니다.
이처럼 RxDart를 활용하면 플러터에서 비동기 처리를 더욱 효율적으로 할 수 있습니다. 게임 개발뿐만 아니라 여러 다른 애플리케이션에서도 RxDart를 적극 활용하여 개발할 수 있습니다.
결론
이번 글에서는 플러터와 RxDart를 사용하여 간단한 게임을 개발하는 방법을 살펴보았습니다. RxDart를 사용하면 비동기 작업을 간단하게 처리할 수 있으며, 반응형 프로그래밍의 장점을 활용할 수 있습니다. 플러터로 다양한 애플리케이션을 개발할 때 RxDart를 함께 활용해보세요!