へっぽこSEが◯時間でFlutter(iOS、android、web)で2Dゲームアプリを作ってみる(4)

どうも、すえきあおいです。

結論から言うと、今日やるチュートリアルは成功しました。フルのソースコードはこちらにあるので、面倒な人はダウンロードどうぞ。

 

前前回前回とチュートリアル選びに失敗してきた私です。

知識は身についてきましたが、まだアプリ開発自体は1ナノも前進しておりません(白目

 

これでも自分的には良いペースで進んでいる(前はハマってからず〜〜〜〜っとハマり続けて、疲れて、諦めて、ボンヤーリして気付いたら1ヶ月、みたいなペースだったw)ので、三度目の正直を信じて別のチュートリアル動画をみながらレッツトライすることにしました。

ネバーギブアップ٩( ‘ω’ )و

 

今日試したこと:もう一度。別のYouTube動画で解説みながらイチから作ってみる

Flutterはバリバリ進化中のライブラリなので、1年前のソースだともう古い(そのまま真似して実装しても動かない)んだってことがよくわかりました。休日を1日棒に振って学びました。

と、いうことで、チュートリアル動画で新しくてきちんと解説してくれているこちらの動画をチョイス!

なんかテトリス的なものを作ろうとしているみたい。

最初にイメージ図を用意して概要まで解説してくれるとは、なんて親切なんでしょう!コレは期待できますね!

 

準備

  • Android Studioで「新しいFlutterアプリを作る」でプロジェクトを新規作成(涙

 

以下、やったことは動画を見ながら真似してやったことなので、わかりにくかったら動画の方を参照してくださいな。

 

やったこと① Scaffold を使って アプリのベースを作る

まずは、main.dartのデフォルトのコードを全部消して以下のように書き直します。

lib/main.dart

import 'package:flutter/material.dart';
import 'score_bar.dart';

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

class MyApp extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return MaterialApp(home: Tetris(),);
  }
}

class Tetris extends StatefulWidget {

  @override
  State createState() => _TetrisState();
}

// 「_」をつけるとプライベートになる
class _TetrisState extends State {

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('TETRIS'),
        centerTitle: true,
        backgroundColor: Colors.indigoAccent,
      ),
      backgroundColor: Colors.indigo,
      
    );
  }
}

 

やったこと② ScoreBar(点数を表示する場所)を追加する

次に、main.dartのbodyにSafeAreaを配置し、中にScoreBarクラスを置きます。

Score Barの中身は新しいファイルに実装していきます。

lib/main.dart

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('TETRIS'),
        centerTitle: true,
        backgroundColor: Colors.indigoAccent,
      ),
      backgroundColor: Colors.indigo,
      body: SafeArea(
        child: Column(
          children:  [
            // 全てのWidgetを一つのファイルに入れると面倒になる。
            // 必要なWidgetをでばっくで見つけることも難しくなる。
            // なので、別ファイルにクラスを宣言します。
            // ScoreBarクラスはインジケータを表示するWidgetです。
            ScoreBar(),
          ],
        ),
      )
    );
  }
}

次に、ScoreBarクラスを別ファイルに実装していきます。

lib/score_bar.dart

import 'package:flutter/material.dart';

//スコアは頻繁に更新されるため、ScoreBarはStatefulWidgetである必要があります。
class ScoreBar extends StatefulWidget {
  @override
  State createState() => _ScoreBarState();
}

class _ScoreBarState extends State {
  @override
  Widget build(BuildContext context) {
    return Container(
      decoration: BoxDecoration(
        gradient: LinearGradient(
          colors: [Colors.indigo[800], Colors.indigo[500]],
        ),
      ),
      child: Row(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Padding(
            padding: EdgeInsets.all(10.0),
            child: Text(
              'Score: 0',
              style:TextStyle(
                fontSize: 20,
                fontWeight: FontWeight.bold,
                color: Colors.white,
              ),
            ),
          ),
        ],
      ),
    );
  }
}

 

BoxDecorationでグラデーションをつけてるあたり、お洒落ですね!

ここまでやったら、main.dartの最上部に以下を追記します。

lib/main.dart

import 'score_bar.dart';

コレで実行できます!

 

やったこと③ SafeAreaの残りの部分を3:1に分割する

まず、残りの部分、ということでExpandedを使っていきます。(これも過去記事で勉強した甲斐あって理解できました)

main.dart

      body: SafeArea(
        child: Column(
          children:  [
            // 全てのWidgetを一つのファイルに入れると面倒になる。
            // 必要なWidgetをでばっくで見つけることも難しくなる。
            // なので、別ファイルにクラスを宣言します。
            // ScoreBarクラスはインジケータを表示するWidgetです。
            ScoreBar(),
            Expanded( //残りの部分
              child:Row( //縦に分割したいときはRowを使う
                children: [
                  Flexible( //残りの部分を分割するので、Flexibleを使う
                    flex: 3, 
                    child: Padding(
                      padding: EdgeInsets.fromLTRB(10.0, 10.0, 5.0, 10.0),
                      child: Container(
                        color: Colors.red,
                      ),
                    ),
                  ),
                  Flexible(
                    flex: 1,
                    child: Padding(
                      padding: EdgeInsets.fromLTRB(5.0, 10.0, 10.0, 10.0),
                      child:Container(
                        color: Colors.green,
                      ),
                    ),
                  ),
                ],
              ),
            ),
          ],
        ),
      ),

 

とりあえず、ここまでうまくいきました!

動画では8:52しか経ってません(笑)

 

思ったんですが、動画ってとても勉強しやすいですね。学びも多かったです。

小技ですが、createStateって打ったらあとはエディタが入力補完してくれて、

  @override
  StatefulElement createElement() {
    // TODO: implement createElement
    return super.createElement();
  }

まで自動でコーディングされるとか知らなかったので感動しました。入力保管の域を超えている…(`・∀・´)

次回はいよいよゲームエリアを作っていきます。

進むと楽しいですね。ワクワク!

それでは!

末岐 碧衣
  • 末岐 碧衣
  • フリーランス のシステムエンジニア。独立後、一度も営業せずに月収 96 万円を達成。1986年大阪生まれ。早稲田大学理工学部卒。システムエンジニア歴 12年。
    2009年、ITコンサルティング企業に入社。3年目でコミュ障が爆発し人間関係が崩壊。うつにより休職するも、復帰後はコミュ障の自覚を持ち、「チームプレイ」を徹底的に避け、会社組織内においても「一人でできる仕事」に専念。社内外から評価を得た。
    無理に「チームプレイ」するよりも「一人でできる仕事」に専念した方が自分も周囲も幸せにできることを確信し、2015年フリーランスとして独立。