业务逻辑
我们在玩游戏时,经常会遇到需要与npc互动之类的的场景。我们需要走进一个角色到一定范围内,进入这个范围内,就可以通过右键点击,或者其他输入事件触发和该角色对话。
实现逻辑
拆解成代码逻辑就是:当触发碰撞模型(可能是不可见的碰撞盒子,实体周围的一个范围)。就展示ui提示并且增加操作按钮。
实现效果
贴近人物时
离开人物时
## 实现代码
1.增加一个问号的实体,但是需要由组件空值(WhyComponent)
package com.dam.wonder.component;
import com.almasb.fxgl.dsl.FXGL;
import com.almasb.fxgl.entity.Entity;
import com.almasb.fxgl.entity.SpawnData;
import com.almasb.fxgl.entity.component.Component;
import com.almasb.fxgl.texture.Texture;
import javafx.scene.image.ImageView;
import lombok.extern.slf4j.Slf4j;
/**
* 为实体添加一个问号
*/
@Slf4j
public class WhyComponent extends Component {
private Entity whyEntity;
@Override
public void onAdded() {
log.info("开始添加问号");
ImageView imageView = new ImageView("assets/ui/buttons/why.png");
Texture texture = new Texture(imageView.getImage());
log.info("问号生产");
whyEntity = FXGL.entityBuilder(new SpawnData(entity.getX() + 16, entity.getY() - 40))
.view(texture)
.opacity(0)
.scale(0.5,0.5)
.build();
log.info("问号加入世界");
FXGL.getGameWorld().addEntity(whyEntity);
}
public void play() {
//用不透明度作为展示与否的实现
whyEntity.setOpacity(1);
}
public void stop() {
whyEntity.setOpacity(0);
}
}
2.给npc的实体生成时加入why组件(GameEntityFactory)
@Spawns("npc")
public Entity npc(SpawnData data) {
ImageView imageView = new ImageView("assets/textures/player-drawing.png");
imageView.setFitHeight(64);
imageView.setFitWidth(64);
Entity entity = FXGL.entityBuilder(data)
.type(EntityType.NPC)
.view(imageView)
.with(new WhyComponent())
.bbox(new HitBox(new Point2D(0, 0) , BoundingShape.circle(40)))
.collidable()
.build();
return entity;
}
3.重写碰撞触发事件(PlayerCollisionHandler)
package com.dam.wonder.handler;
import com.almasb.fxgl.entity.Entity;
import com.almasb.fxgl.physics.CollisionHandler;
import com.dam.wonder.component.WhyComponent;
import com.dam.wonder.constant.EntityType;
import com.dam.wonder.factory.TalkFactory;
import com.dam.wonder.pojo.Talk;
import com.dam.wonder.ui.TalkScene;
import javafx.event.EventHandler;
import javafx.scene.input.MouseButton;
import javafx.scene.input.MouseEvent;
import lombok.extern.slf4j.Slf4j;
import java.util.List;
@Slf4j
public class PlayerCollisionHandler extends CollisionHandler {
private final EventHandler<MouseEvent> eventHandler;
/**
* 基类需要提供有参构造。制定两个实体类型
*/
public PlayerCollisionHandler() {
super(EntityType.PLANE, EntityType.NPC);
eventHandler = event -> {
//鼠标右键
if (event.getButton() == MouseButton.SECONDARY) {
List<Talk> talkList = TalkFactory.buildTalkList();
TalkScene instance = TalkScene.getInstance();
instance.show(talkList);
}
};
}
/**
* 初次碰撞时触发
*/
@Override
protected void onCollisionBegin(Entity player, Entity npc) {
//模拟点击按键p
log.info("碰撞事件开始了");
npc.getComponent(WhyComponent.class).play();
npc.getViewComponent().addOnClickHandler(eventHandler);
}
@Override
protected void onCollisionEnd(Entity player, Entity npc) {
log.info("碰撞事件结束了");
npc.getComponent(WhyComponent.class).stop();
npc.getViewComponent().removeOnClickHandler(eventHandler);
}
}
如此便完成啦。