上一次使用 forge2d 实现了人物移动 边界碰撞 以及 场景建筑物的添加 juejin.cn/post/744251…
这次我们实现人物能发射回旋镖。
在实现这个功能的过程中纠正了几个问题:
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
}
下一篇 实现随机出现怪物,并能射杀。