How to create your own story game with flutter.


How to create your own story game with flutter. 

- Special thanks to #homebrew flutter course in Udemy from @angela yu


Step-1

First, we will go to draw.io and design a free story diagram for our app. In this case, my diagram looks like this. Of course, you can have as much as long story you want but let's keep it short this time.


Step-2

Now, we are going to create scene for our game! Does it sound crazy, if I told you it took me just 5 minutes to build scenes for these 6 phase?

Let me show you,
This https://www.storyboardthat.com/ site gives super flexibility to create story scene in just a few minutes!

I've created scene there and downloaded separated jpg with their free watermark version.

Below is the board what I've created for our 6 phase


Step-3

Now we will be finally building our flutter game.

phase.dart on (lib folder of flutter project)

import 'package:flutter/cupertino.dart';

class Phase{
  int phaseImage;
  String phaseTitle;
  String choice1;
  String choice2;
  int phaseOnChoice1;
  int phaseOnChoice2;

  Phase({@required int img, @required String t, @required String c1, String c2, int c1NextPhase, int c2NextPhase}){
    this.phaseImage = img;
    this.phaseTitle = t;
    this.choice1 = c1;
    this.choice2 = c2;
    this.phaseOnChoice1 = c1NextPhase;
    this.phaseOnChoice2 = c2NextPhase;
  }
}


On the root dir of flutter project creating a folder named "images"
images/

|--
   |-- phase (1).png
   |-- phase (2).png
   |-- phase (3).png
   |-- phase (4).png
   |-- phase (5).png
   |-- phase (6).png


story_logic.dart

import 'package:storygame/phase.dart';
class StoryLogic {
  // Works like a cursor in the stroy  int _currentPhase = 0;
  // Joining these phase we'll make a story  List<Phase> storyPhases = [
    Phase(
      //phase 1      img: 1,      t: 'The alarm clock is ringing, it\'s just like a regular school day morning.',      c1: 'Snooze it.',      c2: 'Wake up and brush teeth.',      c1NextPhase: 3,      c2NextPhase: 2,    ),    Phase(
      //phase 2      img: 2,      t: 'Mom: Good morning son, break fast is ready. Eat and prepare for school bus.',      c1: 'Okay, Mom.',      c2: 'I won\'t go school today.',      c1NextPhase: 5,      c2NextPhase: 6,    ),    Phase(
      //phase 3      img: 3,      t: 'Mom: Why are you still sleeping? Wake up right now. Brush your teeth and go to school.',      c1: 'I\'m feeling sick.',      c2: 'Alright.',      c1NextPhase: 4,      c2NextPhase: 5,    ),    Phase(
        //phase 4        img: 4,        t: 'Okay, take rest. Let me prepare some soup for you. Then I\'ll take you to the the doctor.',        c1: 'RESTART',        c2: ''),    Phase(
      //phase 5      img: 5,      t: 'Mom: Very good.',      c1: 'RESTART',      c2: '',    ),    Phase(
      //phase 6      img: 6,      t: 'Mom: No excuse.',      c1: 'RESTART',      c2: '',    ),  ];
  //this will move the story screen  void nextPhase(int choice){



    if(choice==1){
        _currentPhase = storyPhases[_currentPhase].phaseOnChoice1-1;
    }else{
      _currentPhase = storyPhases[_currentPhase].phaseOnChoice2-1;
    }

  }

  bool hasNext(){
    if(storyPhases[_currentPhase].phaseOnChoice1 != null){
      print('HAS NEXT : TRUE');      return true;    }else{
      print('HAS NEXT : FALSE');      return false;    }
  }

  void restart(){
    _currentPhase = 0;  }

  int getPhaseImage() {
    return storyPhases[_currentPhase].phaseImage;  }

  String getPhaseTitle() {
    return storyPhases[_currentPhase].phaseTitle;  }

  String getChoice1() {
    return storyPhases[_currentPhase].choice1;  }

  String getChoice2() {
    return storyPhases[_currentPhase].choice2;  }
}

main.darrt

import 'package:flutter/material.dart';
import 'package:storygame/story_logic.dart';

StoryLogic storyLogic = StoryLogic();

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData.dark(),
      home: MyGamePage(),
    );
  }
}

class MyGamePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Morning Story Game'),
      ),
      body: SafeArea(
        child: Padding(
          padding: EdgeInsets.all(10),
          child: GameBody(),
        ),
      ),
    );
  }
}

class GameBody extends StatefulWidget {
  @override
  _GameBodyState createState() => _GameBodyState();
}

class _GameBodyState extends State<GameBody> {
  choicePressed(int choice) {

    //if can go next then next else restart
    if(storyLogic.hasNext()){
      setState(() {
        storyLogic.nextPhase(choice);
      });
    }else{
      setState(() {
        storyLogic.restart();
      });
    }

    //if game has been finished show a (Bottom Message)
    if(!storyLogic.hasNext()){
      SnackBar snackBar = SnackBar(content: Text('Game finished! Restart to play again.'));
      Scaffold.of(context).showSnackBar(snackBar);
    }

  }

  @override
  Widget build(BuildContext context) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.stretch,
      children: <Widget>[
        Expanded(
          flex: 6,
          child: Image(
            image:
                AssetImage('images/phase (${storyLogic.getPhaseImage()}).png'),
          ),
        ),
        SizedBox(height: 5),
        Expanded(
          flex: 2,
          child: Text(
            storyLogic.getPhaseTitle(),
            style: TextStyle(fontSize: 20),
          ),
        ),
        Expanded(
          child: FlatButton(
            color: Colors.orange,
            child: Text(storyLogic.getChoice1()),
            onPressed: () {
              choicePressed(1);
            },
          ),
        ),
        SizedBox(height: 15),
        Expanded(
          child: Visibility(
            visible: storyLogic.hasNext(),
            child: FlatButton(
              color: Colors.deepOrangeAccent,
              child: Text(storyLogic.getChoice2()),
              onPressed: () {
                choicePressed(2);
              },
            ),
          ),
        ),
      ],
    );
  }
}



Find me on:
https://twitter.com/naimurhasanrwd



Comments