플러터 앱 개발 일지 (1) - 무작정 해커톤

이정현·2023년 3월 5일
0
post-thumbnail

리액네로 게임 만들어보실?

클라 개발에 관심이 생기던 차에 친구도 같이 해보고 싶다고 해서 리액트 네이티브로 게임을 만들어 보기로 했다.
근데 생각해보니 굳이 RN으로 할 필요가 없다고 생각하던 차에, 플러터를 한번 도전해보기로 했다.

계획

가끔 친구들과 내기를 할 때 사용하는 앱이 있는데 애니멀 런이라는 앱이다.
애니멀런
플레이 화면

각각 원하는 동물을 선택하고, START 버튼을 누르면 동물들이 경주를 하는 간단한 앱인데 생각보다 박진감 넘쳐서 좋아하는 앱이다. 근데 문제는 iOS는 출시가 안되었다는 점...😢

그래서 우리가 비슷한걸 만들어서 출시하자!가 원래 계획이었다.

한계

하지만 항상 계획대로 되진 않는 법..!
막상 만들려다 보니 이런 앱을 굳이 플러터로 만들어야 할 이유도 모르겠을 뿐더러, 가장 어려운 부분은 그래픽 리소스를 가져오는 부분이었다. 그래서 계획을 바꿔서 우리가 제일 재밌게 하는 가벼운 퍼즐 게임을 만들기로 했다.


1일차

영어 단어 몇개를 가지고 퍼즐을 푸는 게임을 만들기로 하고, 시간이 늦어 기획과 어느정도 틀만 잡기로 했다.

기획회의의 흔적...

4개의 알파벳으로 이루어진 단어들 중 무작위로 4개를 뽑아 세로로 섞은 후 단어를 4개 만들어내면 되는 간단한 게임을 만들기로 했다.
단어는 인터넷에서 txt 파일로 2499개를 제공하는게 있어 우선 이걸로 String array를 만들어 사용하기로 했다.(더 많은 단어들이 있지만 2499개만 해도 1억 6천개가 넘는 조합이 나온다...🥶)

2일 차

기본적으론 내가 로직을, 친구가 뷰를 만들기로 했지만, 둘 다 클라이언트 개발은 거의 해본적이 없는 초짜라 우선 각자 해보고 먼저 끝낸 쪽의 코드를 채택하는 방식으로 진행했다.
2499개의 단어들 중 4개를 뽑아서 랜덤하게 셔플해서 state에 저장하는 함수를 먼저 만들었다.

void _setWordGrid() {
    for (int idx = 0; idx < 4; ++idx) {
      int randIdx = Random().nextInt(words.length);
      if (!_roundWords.contains(words[randIdx])) {
        var newWord = words[randIdx].toUpperCase();
        _roundWords.add(newWord);

        for (var i = 0; i < 4; i++) {
          _wordGrid[idx][i] = newWord.substring(i, i + 1);
        }
      }
    }
  }

  void _shuffleWordGrid() {
    for (int i = 0; i < 4; i++) {
      List<String> columnArr = [
        _wordGrid[0][i],
        _wordGrid[1][i],
        _wordGrid[2][i],
        _wordGrid[3][i]
      ];
      columnArr.shuffle();
      for (int j = 0; j < 4; j++) {
        _wordGrid[j][i] = columnArr[j];
      }
    }
  }

여기까진 문제 없었지만, GridView를 만드는게 제일 문제였다. 너무 다양한 GridView가 있어서 어떤걸 사용할까 고민했는데 우선 flutter_reorderable_gridview라는 패키지를 사용해보기로 했다. 그 이유는 아래와 같았다.

  1. 기획상 그리드들을 드래그 앤 드랍으로 이동할 수 있어야 하는데 손쉽게 할 수 있음
  2. 다양한 옵션으로 커스터마이징이 가능함

그렇게 ReorderableGridView를 사용해서 그리드뷰를 만들 수 있었다.

  ReorderableBuilder makeWordGrid(int idx) {
    final generatedChildren = List.generate(
      _wordGrid.length,
          (index) =>
          Container(
            key: Key(Random().nextInt(100000).toString()),
            color: Colors.lightBlue,
            alignment: Alignment.center,
            margin: EdgeInsets.all(10),
            child: Text(
              _wordGrid[index].elementAt(idx),
            ),
          ),
    );

    return ReorderableBuilder(
      scrollController: ScrollController(),
      onReorder: (List<OrderUpdateEntity> orderUpdateEntities) {},
      builder: (children) {
        return GridView(
          key: GlobalKey(),
          controller: ScrollController(),
          gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
              crossAxisCount: 1),
          children: children,
        );
      },
      enableLongPress: false,
      lockedIndices: lockIndex,
      children: generatedChildren,
    );
  }

여기에 이제 row 별로 lock과 unlock을 할 수 있는 함수를 만들어서 lock과 unlock을 가능하게 만들었다.
여기서 lockIndex는 state로 관리해서 lock, unlock 함수에서 setState로 state를 변경할 수 있게 만들었다.

  void lock(int idx) {
    var newWord = _wordGrid[idx][1] + _wordGrid[idx][1] + _wordGrid[idx][2] + _wordGrid[idx][3];
    if (words.contains(newWord.toLowerCase())) {
      print(newWord);
      setState(() {
        lockIndex.add(idx);
      });
    }
  }

  bool equalsIgnoreCase(String str1, String str2) {
    return str1.toLowerCase() == str2.toLowerCase();
  }

  void unlock(int idx) {
    setState(() {
      lockIndex.remove(idx);
    });
  }

디자인을 아무것도 신경쓰지 않은 기본적인 구조는 빨리 만들 수 있었지만, 플러터에 대한 개념이 전혀 없는 야매로 만든 앱이라 맘대로 동작해주진 않았다. 조금씩 개선해서 만들기로 하고 우선 해커톤, 아니 코딩 캠프는 종료....

배운 점

무작정 맨땅에 헤딩하듯이 만들어서 어떤식으로 앱이 그려지는지 잘 모르고 있다는게 가장 큰 문제인 것 같았다. 한동안은 플러터 앱에 대해서 기본적인걸 공부하는 시간을 가져야 할 것 같다


소스코드 : https://github.com/webdonalds/mixord

profile
안녕하세요!

0개의 댓글