ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Flutter/Flame 2D 횡 스크롤 게임 만들기 예시 1 (Flutter/Flame 2D Horizontal Scroll Game Example 1)
    DEV/flutter (dart) 2023. 3. 8. 17:39

    1. 시작

    Flutter를 시작하면서 게임을 만들어 보고 싶었다.

    (사실 바닐라JS로 하려고 했었는데... Flutter 시작한 김에 만들어 보려고 한다.)

     

    프로젝트 이전에 Flame와 친해질 필요가 있었고 (당장 Flutter랑도 안 친함...)

     

    작게 2D 횡 스크롤 게임 하나, X-Y축 이동이 가능한 2D 게임 하나 틀을 만들어 보려고 한다.

     

    (2D 횡 디펜스 게임도 만들 고 싶고, 2D 픽셀 게임도 만들어 보고 싶어서... 그리고 적당한 한글 tutorial이 없었음!)

     

    공부는 안 하고 욕심은 참 많다.

     

    그래서 해당 글은 완벽한 게임을 만드는 것은 아니고

     

    그전에 맛을 볼 겸 좌, 우 이동이 가능하고 점프가 가능한 2D 게임 기능 구현까지만 해볼 생각이다.

     

    참고로 해당 글은 모바일(Android, IOS)에 최적화 하여 구현하지 않는다.

    웹 브라우저 기반으로 작성하나 기능적으로 크게 다르지 않아 참고하기에는 나쁘지 않다. 

     

    즉 해당 글에서 확인할 수 있는 것을 미리 정리하면 다음과 같다.

    • 스프라이트 이미지를 이용한 움직이는 케릭터 구현 (이미지 등록)
    • 케릭터 좌, 우 이동 및 점프 (키보드 입력 이벤트)
    • 케릭터가 이동하는 방향에 따른 스프라이트 이미지 좌/우 반전
    • 케릭터가 이동 중 좌/우 벽에 닿는 경우에 대한 처리 (넘어가지 못하게)
    • (배경 이미지 등록이 가능할지도...?)

     

    해당 글을 통해 완성한 게임 데모

    귀엽다...

     

     

    * 사실 Flame Tutorial을 기반으로 한다. 즉, 공식 문서를 보는게 더 쉬울 수 있다.

    (이미지도 공식 문서에 있는 이미지를 참조하였음)

    Ref : https://docs.flame-engine.org/1.6.0/tutorials/platformer/step_1.html

     

    1. Preparation — Flame

    Before you begin any kind of game project, you need an idea of what you want to make and I like to then give it a name. For this tutorial and game, Ember will be on a quest to gather as many (GitHub) stars as possible and I will call the game, Ember Quest.

    docs.flame-engine.org

     

    2. 개발환경

    해당 글은 23년 3월 8일 기준으로 작성되었습니다.

    Windows 10

    Flutter (Android Studio)

    Flame 1.6.0

     

     

    3. 코드

    사실 본인은 설명을 잘 못한다.

     

    그래서 그냥 코드 땋 놓고 주석 땋 달아놓고 끝내려고 했다.

    (그리고 당장 코드를 다 작성한 이후에는 작성 순서도 까먹는다.)

     

    근데 다른 블로그 읽을 때, 순서대로 설명 안해놓으면 답답하더라.

     

    그래서 개인적으로 서순이 명확한 글이 좋고 Full code를 따로 개시한 글이 좋더라.

    (덤으로 개발자 블로그임에도 복붙 안되는 사이트 이해X, 개인적인 의견...)

     

    순서대로 작성해 보고 정 아니다 싶으면 그냥 던저놓겠다...(?)

     

    3.1) Flame 1.6.0 Pub get

    우선 Flame 엔진을 설치해야 한다.

     

    Android Studio(VS code를 써도 상관 없다.)에서 Flutter project를 새로 생성한 뒤

     

    pubspec.yaml 파일의 dependencies의 flame을 등록하고 pub get 하여 다운받아주자,.

     

    1.6.0 버전을 사용할끄임
    참고로 pub get은 flame: 1.6.0 작성 후 마우스 올리면 나옴

     

    3.2) 파일구성

    다음 파일을 구성해보자.

     

    본인은 다음과 같이 구성하였다.

    (수정한 부분만 작성함, 기본적으로 install 되는 폴더들은 생략하였다.)

    - project_folder (본인이 생성한 프로젝트)
        - assets (생성하셈)
        	- images (생성하셈)
            	-emver.png (케릭터 넣어주셈, 튜토리얼 페이지에 이미지 있음)
        - lib
        	- main.dart
            - seokbongRoom.dart (생성하셈, 나는 파일 이름을 잘 못 만든거 같음)
        	- components (생성하셈)
    			- player (생성하셈)
    				- player.dart (생성하셈)

     

    생성하셈 << 이거 써있는 것만 생성하면 된다.

     

    폴더와 파일명은 다르게 해도 된다.

     

    하지만 다르게 생성한다면, 해당 폴더를 import 하거나 경로 지정에 대해서는 본인이 잘 맞춰서 작성하면 된다.

     

    3.3) main.dart

    처음 프로젝트를 생성하면 main.dart에 sample 코드가 들어있다.

     

    모두 지워주고 다음처럼 만들자.

    import 'package:flutter/widgets.dart';
    
    void main() {
      runApp();
    }

     

    3.4) seokbongRoom.dart

    Flame 엔진의 FlameGame을 상속하여 게임의 업데이트 및 렌더링 로직을 구현해야한다.

     

    해당 파일의 기본 틀은 잡아주자.

     

    기본 틀을 잡으면서 이미지 하나만 추가하겠다.

     

    (본인은 Flame tutorial의 assets 이미지 샘플을 사용하였다. 하단 링크에 이미지를 다른 이름으로 저장하여 사용하였다.)

    https://docs.flame-engine.org/1.6.0/tutorials/platformer/step_1.html

     

    1. Preparation — Flame

    Before you begin any kind of game project, you need an idea of what you want to make and I like to then give it a name. For this tutorial and game, Ember will be on a quest to gather as many (GitHub) stars as possible and I will call the game, Ember Quest.

    docs.flame-engine.org

     

    에러나 경고는 우선 무시하자.

    import 'dart:ui';
    import 'package:flame/components.dart';
    import 'package:flame/game.dart';
    import 'components/player/player.dart';
    import 'package:flame/events.dart';
    
    // FlameGame을 상속하고 HasKeyboardHandlerComponents를 구현함.
    // 해당 클래스는 게임의 업데이트 및 랜더링 로직 구현
    class SeokbongRoom extends FlameGame with HasKeyboardHandlerComponents {
      SeokbongRoom();
    
      // onLoad() : 게임이 로드되면 실행, 게임 오브젝트를 초기화하고 리소스를 로드함.
      @override
      Future<void> onLoad() async 
        // 이미지 리소스 로드
        await images.loadAll([
          'ember.png',
        ]);
        
      	// 나중에 할거임.
      }
    }

     

    이미지를 사용하려면 pubspec.yaml에서 등록해야 사용이 가능하다.

     

    pubspec.yaml 파일을 열어서 다음과 같이 수정해주자.

    (들여쓰기 예민함 주의)

    - assets/images/ 폴더를 허용해주자.

     

    3.5) player.dart

    기본적인 Player 객체 세팅을 해보자.

    import 'package:flame/components.dart';
    import 'package:flutter/services.dart';
    import '../../seokbongRoom.dart';
    
    // SpriteAnimationComponent : Flame 엔진에서 스프라이트 에니메이션을 처리하는 데 사용.
    // KeyboardHandler : 키보드 이벤트를 처리하기 위한 메소드 구현. (미리 추가해주자)
    class Player extends SpriteAnimationComponent with KeyboardHandler, HasGameRef<SeokbongRoom> {
      Player({
        required super.position,
      }) : super(size: Vector2.all(64), anchor: Anchor.center);
    
      // SpriteAnimation 초기화 및 로드 (게임 오브젝트가 로드되면 호출)
      @override
      Future<void> onLoad() async {
        // SpriteAnimation : 스프라이트 시퀀스를 처리하고 애니메이션을 구현하는 데 사용.
        // SpriteAnimation.fromFrameData() : SpriteAnimation 객체 생성.
        // game.images.fromCache() : 이미지 로드.
        animation = SpriteAnimation.fromFrameData(
          game.images.fromCache('ember.png'),
          SpriteAnimationData.sequenced(
            amount: 4,    // 스프라잍트 수
            stepTime: 0.12,   //스프라이트의 시간 간격
            textureSize: Vector2.all(16),   // 스프라이트 텍스처 사이즈
          ),
        );
      }
    
      // 게임 오브젝트가 업데이트 될 때마다 호출됨.
      @override
      void update(double dt) {
        // 스프라이트 애니메이션 업데이트
        super.update(dt);
      }
    }

     

    3.6) 화면에 케릭터를 추가 (seokbongRoom.dart)

    케릭터 객체를 활용하여 화면에 추가해보자.

    (주석이 된 부분이 추가된 부분임)

    class SeokbongRoom extends FlameGame with HasKeyboardHandlerComponents {
      SeokbongRoom();
    
      // 나중에 초기화(late)
      late Player _player;
      
      @override
      Future<void> onLoad() async {
        await images.loadAll([
          'ember.png',
        ]);
    
        // Player 오브젝트 생성, _player 초기화.
        _player = Player(
          // Player의 초기 위치 (바닥은 해당 값을 기준으로 계산함)
          position: Vector2(128, canvasSize.y -70),
        );
    
        // add : 해당 메서드를 사용하여 게임에 추가.
        // add(_background);
        add(_player);
      }
    }

     

    3.7) 게임 위젯 실행 (main.dart)

    import 'package:flame/game.dart';
    import 'package:flutter/widgets.dart';
    
    import 'seokbongRoom.dart';
    
    void main() {
      runApp(
        // controlled : 해당 값은 'true'로 설정되면 게임 루프가 제어되고 고정된 FPS로 실행됨.
        // gameFactory : 'SeokbongRoom' 객체를 만들기 위한 팩토리 함수 지정
        // SeokbongRoom 게임 오브젝트를 생성 -> GameWidget 초기화 -> 어플리케이션 실행(RunApp), controlled가 true 이므로 게임 루프가 제어되고 고정된 FPS로 게임이 실행됨.
        const GameWidget<SeokbongRoom>.controlled( gameFactory: SeokbongRoom.new ),
      );
    }

     

    코드에 대한 설명은 주석을 읽어보면 된다.

     

    아마 위 코드까지 작성이 완료되었다면 검정 화면에 케릭터가 뿅 하고 나타났을 것이다.

    (귀찮지만 직접 돌려보고 옴)

     


     

    생각보다 글이 길어졌다.

     

    케릭터를 움직이는 기능은 다음 글에 이어서 작성하도록 하겠다.

     

    2편 (쓰고 나니 그냥 합본으로 만들껄 이라는 생각이 드는...)

    https://seokbong.tistory.com/185

     

    Flutter/Flame 2D 횡 스크롤 게임 만들기 예시 2

    지난 글... https://seokbong.tistory.com/184 Flutter/Flame 2D 횡 스크롤 게임 만들기 예시 1 1. 시작 Flutter를 시작하면서 게임을 만들어 보고 싶었다. (사실 바닐라JS로 하려고 했었는데... Flutter 시작한 김에 만

    seokbong.tistory.com

     

    댓글

Designed by Tistory.