Rafael Almeida Barbosa

Mobile developer (Android,Flutter)

FlutterBR

Building RPG games with

Bonfire

How did Bonfire come about?

My Favorite games

  • Ragnarok
  • Word of Warcraft
  • MU Online

Game building tools

Discovering the Flame

Can I build an RPG game with this?

Building RPG game

  • Map system
  • Decoration
  • Camera system
  • Collision
  • Player movement
  • Enemy movement
  • Attack system
  • Joystick
  • Etc

My first game

(Darkness Dungeon)

Bonfire

(RPG maker) Create RPG-style or similar games with Flutter.

Is ideal for building games from the following perspectives

Bonfire



return BonfireTiledWidget(
    gameController: GameController(),
    joystick: MyJoystick()
    map: TiledWorldMap('tile/map.json', forceTileSize: tileSize), 
    player: Knight(), 
    interface: KnightInterface(),
    background: GameComponent(), 
    constructionMode: false, 
    showCollisionArea: false, 
    constructionModeColor: Colors.blue, 
    collisionAreaColor: Colors.blue, 
    lightingColorGame: Colors.black.withOpacity(0.4), 
    cameraZoom: 1,
    cameraSizeMovementWindow: Size(50,50),
    cameraMoveOnlyMapArea: false,
    showFPS: false,
    progress: Widget(),
);

How it works?

Map


TiledWorldMap(
  'tiled/map.json',
  forceTileSize: Size(32,32),
)
..registerObject(
  'orc', // object name
  (x, y, width, height){
  	return Orc(Position(x, y));
  },
)

Decoration


GameDecoration.sprite(
    Sprite sprite, {
    @required this.initPosition,
    @required this.height,
    @required this.width,
    this.frontFromPlayer = false,
    Collision collision, 
  })
  
GameDecoration.spriteMultiCollision()

GameDecoration.animation()

GameDecoration.animationMultiCollision()

Decoration


class MyDecoration extends GameDecoration {
  MyDecoration(Position position)
      : super.animation(
          FlameAnimation.Animation.sequenced(
            "animation.png",
            6,
            textureWidth: 16,
            textureHeight: 16,
          ),
          width: 32,
          height: 32,
          initPosition: position,
        );

        // do anything

    @override
    void update(double dt) {
        // do anything
        super.update(dt);
    }

    @override
    void render(Canvas canvas) {
        // do anything
        super.render(canvas);
    }
}

Enemy

SimpleEnemy

RotationEnemy

SimpleEnemy


class Goblin extends SimpleEnemy {

    Goblin(Position initPosition)
      : super(
          initPosition:initPosition, //required
          height:32, //required
          width:32, //required
          life: 100,
          speed: 100,
          collision: Collision(),
          initDirection: Direction.right,
          animIdleRight: FlameAnimation(), //required
          animIdleLeft: FlameAnimation(), //required
          animIdleTopLeft: FlameAnimation(),
          animIdleBottomLeft: FlameAnimation(),
          animIdleTopRight: FlameAnimation(),
          animIdleBottomRight: FlameAnimation(),
          animRunRight: FlameAnimation(), //required
          animRunLeft: FlameAnimation(), //required
          animRunTopLeft: FlameAnimation(),
          animRunBottomLeft: FlameAnimation(),
          animRunTopRight: FlameAnimation(),
          animRunBottomRight: FlameAnimation(),
          animIdleTop: FlameAnimation(),
          animIdleBottom: FlameAnimation(),
          animRunTop: FlameAnimation(),
          animRunBottom: FlameAnimation(),
      );
      
}

RotationEnemy


class Tank extends RotationEnemy {

    Tank(Position initPosition)
      : super(
          initPosition:initPosition, //required
          height:32, 
          width:32, 
          life: 100,
          speed: 100,
          collision: Collision(),
          currentRadAngle: -1.55,
          animIdle: FlameAnimation(), //required (TOP)
          animRun: FlameAnimation(), //required  (TOP)
      );
      
    @override
    void update(double dt) {
        super.update(dt);
    }

    @override
    void render(Canvas canvas) {
        super.render(canvas);
    }

    @override
    void receiveDamage(double damage, int from) {
        super.receiveDamage(damage, from);
    }

    @override
    void die() {
        super.die();
    }
      
}

Enemy movement


void seePlayer({
    Function(Player) observed,
    Function() notObserved,
    double radiusVision = 32,
    int interval = 500,
  })

void seeAndMoveToPlayer({
    Function(Player) closePlayer,
    double radiusVision = 32,
    double margin = 10,
  })

void seeAndMoveToAttackRange({
    Function(Player) positioned,
    double radiusVision = 32,
    double minDistanceCellsFromPlayer,
  })

void simpleAttackMelee({
    @required double damage,
    double heightArea = 32,
    double widthArea = 32,
    int id,
    int interval = 1000,
    bool withPush = false,
    double sizePush,
    Direction direction,
    FlameAnimation.Animation attackEffectRightAnim,
    FlameAnimation.Animation attackEffectBottomAnim,
    FlameAnimation.Animation attackEffectLeftAnim,
    FlameAnimation.Animation attackEffectTopAnim,
    VoidCallback execute,
  })
  
 void simpleAttackRange({...})

Movement example


  @override
  void update(double dt) {
    
    this.seeAndMoveToPlayer(
      closePlayer: (player) {
      	execAttack();
      },
      radiusVision: tileSize * 2,
    );

    super.update(dt);
  }

Movement example


  @override
  void update(double dt) {
    
    this.seeAndMoveToAttackRange(
      minDistanceFromPlayer: tileSize * 2,
      positioned: (p) {
      	execAttackRange();
      },
      radiusVision: tileSize * 5,
    );

    super.update(dt);
  }

Custom enemy


class MyCustomEnemy extends Enemy{}


void moveTop(double speed);
void moveBottom(double speed);
void moveLeft(double speed);
void moveRight(double speed);
void moveFromAngleDodgeObstacles(double speed, double angle,{Function notMove});
void moveFromAngle(double speed, double angle);
void receiveDamage(double damage, int from);
void addLife(double life);
void die();

Player

SimplePlayer

RotationPlayer

SimplePlayer


class Kinght extends SimplePlayer {

    Kinght(Position initPosition)
      : super(
          initPosition:initPosition, //required
          height:32, //required
          width:32, //required
          life: 100,
          speed: 100,
          collision: Collision(),
          initDirection: Direction.right,
          animIdleRight: FlameAnimation(), //required
          animIdleLeft: FlameAnimation(), //required
          animIdleTopLeft: FlameAnimation(),
          animIdleBottomLeft: FlameAnimation(),
          animIdleTopRight: FlameAnimation(),
          animIdleBottomRight: FlameAnimation(),
          animRunRight: FlameAnimation(), //required
          animRunLeft: FlameAnimation(), //required
          animRunTopLeft: FlameAnimation(),
          animRunBottomLeft: FlameAnimation(),
          animRunTopRight: FlameAnimation(),
          animRunBottomRight: FlameAnimation(),
          animIdleTop: FlameAnimation(),
          animIdleBottom: FlameAnimation(),
          animRunTop: FlameAnimation(),
          animRunBottom: FlameAnimation(),
      );
}

RotationPlayer


class PlayerTank extends RotationEnemy {

    PlayerTank(Position initPosition)
      : super(
          initPosition:initPosition, //required
          height:32, 
          width:32, 
          life: 100,
          speed: 100,
          collision: Collision(),
          currentRadAngle: -1.55,
          animIdle: FlameAnimation(), //required
          animRun: FlameAnimation(), //required
      );
      
}

Player extensions



void simpleAttackMelee(...);

void simpleAttackRange(...);

void showDamage(...);

void seeEnemy(...);

void addFastAnimation(FlameAnimation.Animation animation);

Player joystick interaction



@override
void joystickChangeDirectional(JoystickDirectionalEvent event) {
  // do anything with event of the joystick
  super.joystickChangeDirectional(event);
}

@override
void joystickAction(JoystickActionEvent event) {
  // do anything with event of the joystick
  super.joystickAction(event);
}

Custom player



class MyCustomPlayer extends Player{}

void moveTop(double speed);
void moveBottom(double speed);
void moveLeft(double speed);
void moveRight(double speed);
void moveFromAngle(double speed, double angle);
void receiveDamage(double damage, int from);
void addLife(double life);
void die();

return BonfireTiledWidget(
  lightingColorGame: Colors.black.withOpacity(0.4),
);

class Torch extends Gamedecoration with Lighting{

  MyDecoration(){

    lightingConfig = LightingConfig(
      color: Colors.yellow.withOpacity(0.1),
      radius: 40,
      blurBorder: 20,
      withPulse: true,
      pulseVariation: 0.1,
      pulseCurve: Curves.decelerate,
      pulseSpeed: 1,
    );

  }
}

class MyInterface extends GameInterface {

  @override
  void resize(Size size) {
    add(BarLifeComponent());
    add(
      InterfaceComponent(
        sprite: Sprite('blue_button1.png'),
        spriteSelected: Sprite('blue_button2.png'),
        height: 40,
        width: 40,
        id: 5,
        position: Position(150, 20),
        onTapComponent: () {
          print('Test button');
        },
      ),
    );
    super.resize(size);
  }
}

Custom InterfaceComponent


class BarLifeComponent extends InterfaceComponent {

  BarLifeComponent(int id, Position position)
  : super(
    id: id,
    position: position,
    width: 120,
    height: 40,
  );
        
  @override
  void update(double t) {
    super.update(t);
  }

  @override
  void render(Canvas c) {
    super.render(c);
  }
  
  @override
  void onTap() {
    super.onTap();
  }
  
}

Joystick


Joystick(
  keyboardEnable: false,
  directional: JoystickDirectional(
    spriteBackgroundDirectional: Sprite('joystick_background.png'),
    spriteKnobDirectional: Sprite('joystick_knob.png'), 
    color: Colors.black,
    size: 100, 
    isFixed: false,
  ),
  actions: [
    JoystickAction(
      actionId: 1, //(required)
      sprite: Sprite('joystick_atack_range.png'), 
      spritePressed: Sprite('joystick_atack_range.png'), 
      spriteBackgroundDirection: Sprite('joystick_background.png'), 
      enableDirection: true, 
      align: JoystickActionAlign.BOTTOM_RIGHT,
      color: Colors.blue,
      size: 50,
      margin: EdgeInsets.only(bottom: 50, right: 160),
    )
  ],
)

Joystick (Directional)


Joystick(
  directional: JoystickDirectional(),
)

Joystick (Actions)


Joystick(
  actions: [
    JoystickAction(
      actionId: 1,
      size: 80,
      margin: EdgeInsets.only(
      	bottom: 50, 
      	right: 50,
      ),
    )
    JoystickAction(
      actionId: 2,
      enableDirection: true,
      size: 50,
      margin: EdgeInsets.only(
        bottom: 50, 
        right: 160,
      ),
    )
  ],
)

Hands On

Games Examples

Games Examples

Multi Scenes

PRs are Welcome

Rafael Almeida Barbosa

Thanks!!!

Building RPG games with Bonfire

By Rafael Almeida Barbosa

Building RPG games with Bonfire

  • 250