flutter flame forge2d 实现任务发射回旋镖

173 阅读2分钟

上一次使用 forge2d 实现了人物移动 边界碰撞 以及 场景建筑物的添加 juejin.cn/post/744251…

这次我们实现人物能发射回旋镖。

output.webp

在实现这个功能的过程中纠正了几个问题:

1 人物的移动之前是直接add在BodyComponent中。因为body可以设置刚体,以此来来实现碰撞到其他刚体的时候能停止前进。这样写的问题是刚体不能叠加。会相互排斥,比如这里想添加一个回旋镖,如果回旋镖也是刚体,就会跟人物冲突,他俩没法重合。

2 为了解决回旋镖跟人物能重合的问题,这里设置回旋镖是SpriteComponent类型。

3 当回旋镖是SpriteComponent类型,人物是body类型的时候。发现碰撞机制失效了(或者说错乱了)。 在Flame中 是使用CollisionCallbacks来处理碰撞,在forge2d(body类型)是通过ContactCallbacks处理碰撞的。如果把 SpriteComponent 添加到body中且还是使用 CollisionCallbacks来处理碰撞,会发现SpriteComponent在处理碰撞的时候用的区域永远是(0,0,size.width,size.height)

所以最后我的处理方法是body + SpriteComponent,body跟SpriteComponent是平级。动态修改body的坐标,在body坐标更改的时候,依据body的坐标修改SpriteComponent的坐标。

玩家 回旋镖 添加逻辑 关键代码

  //玩家
  late GamePlayer gamePlayer;
  //玩家脚底黑暗圈
  late PlayerFooterAura playerFooterAura;
  @override
  Future<void> onLoad() async{
    await super.onLoad();
    playerFooterAura = PlayerFooterAura();
    playerFooterAura.position = body.position;
    world.add(playerFooterAura);
    // add(PlayerFooterAura());
    gamePlayer = GamePlayer();
    gamePlayer.position = body.position;
    world.add(gamePlayer);
    startShoot();
  }

  void startShoot() async{
    //每间隔1s 添加一个回旋镖 并移动
    while(true){
      await Future.delayed(const Duration(seconds: 1));
      var hxb = HXBSkillComponent();
      hxb.position = body.position;
      world.add(hxb);
      var direction = WeaponDirection.left;
      if(gamePlayer.currentDirection == PlayDirection.left){
        direction = WeaponDirection.left;
      }else if(gamePlayer.currentDirection == PlayDirection.right){
        direction = WeaponDirection.right;
      }else if(gamePlayer.currentDirection == PlayDirection.bottom){
        direction = WeaponDirection.bottom;
      }else if(gamePlayer.currentDirection == PlayDirection.top){
        direction = WeaponDirection.top;
      }
      hxb.move(direction, body);
    }
  }

回旋镖移动逻辑



import 'dart:async';
import 'dart:math';

import 'package:flame/collisions.dart';
import 'package:flame/components.dart';
import 'package:flame/effects.dart';
import 'package:flame_forge2d/flame_forge2d.dart';
import 'package:flutter/cupertino.dart';
import 'package:gamemowing/generated/assets.dart';

import '../player/game_player.dart';

class HXBSkillComponent extends SpriteComponent with CollisionCallbacks {

  @override
  Future<void> onLoad() async{
    sprite = await Sprite.load(Assets.imagesIconHxb);
    size = Vector2(50, 50);
    anchor = Anchor.center;
    debugMode = true;
    add(RectangleHitbox());
    return super.onLoad();
  }

  var moveDistance = 500.0;
  var moveTime = 2.0;
  void move(WeaponDirection direction,Body target){
    isMoveBack = false;
    var centerX = target.position.x;
    //回旋镖旋转
    add(RotateEffect.by(
      pi * 2 * 3,
      EffectController(
        duration: 1,
        // reverseDuration: 1,
        curve: Curves.linear,
        infinite: true,
      ),
    ),);
    //回旋镖 上下左右移动
    switch(direction){
      case WeaponDirection.left:
        add(MoveByEffect(Vector2(centerX - moveDistance, 0), LinearEffectController(moveTime),onComplete:(){
          onMoveComplete(target);
        }));
        break;
      case WeaponDirection.right:
        add(MoveByEffect(Vector2(moveDistance, 0), LinearEffectController(moveTime),onComplete: (){
          onMoveComplete(target);
        }));
        break;
      case WeaponDirection.bottom:
        add(MoveByEffect(Vector2(0, moveDistance), LinearEffectController(moveTime),onComplete: (){
          onMoveComplete(target);
        }));
        break;
      case WeaponDirection.top:
        add(MoveByEffect(Vector2(0, -moveDistance), LinearEffectController(moveTime),onComplete: (){
          onMoveComplete(target);
        }));
        break;
    }
  }

  var speed = 300;
  var eachTime = 0.1;
  var isMoveBack = false;
  //回旋镖 开始往回飞
  void onMoveComplete(Body target) async{
    isMoveBack = true;
    while(true){
      await doMove(target);
    }
  }
  //每eachTime 计算一次移动 知道移动到玩家身边
  Future doMove(Body target) async{
    var completer = Completer<bool>();
    var distance = speed * eachTime;
    var xOffset = target.position.x - position.x;
    var yOffset = target.position.y - position.y;

    var totalDistance = sqrt(xOffset * xOffset + yOffset * yOffset);
    var cons = xOffset / totalDistance;
    var sin = yOffset / totalDistance;
    var moveX = distance * cons;
    var moveY = distance * sin;
    add(MoveByEffect(Vector2(moveX,moveY), LinearEffectController(eachTime),onComplete: (){
      completer.complete(true);
    }));
    return completer.future;
  }
  @override
  void onCollisionStart(Set<Vector2> intersectionPoints, PositionComponent other) {
    super.onCollisionStart(intersectionPoints, other);
    debugPrint("========HXBSkillComponent=onCollisionStart===${other}");
    //当回旋镖跟玩家碰撞 直接移除
    if(other is GamePlayer && isMoveBack){
      removeFromParent();
    }
  }
}

enum WeaponDirection {
  left,
  right,
  bottom,
  top
}

下一篇 实现随机出现怪物,并能射杀。