因此,我已经在游戏中重构了架构(避免障碍-从天空播放器掉下来的障碍物必须左右左右躲避),以便在LibGDX(Android Studio项目)中使用ashley。我设法在屏幕是一种生命,它只是一个更大的障碍。
我的问题是从逻辑上看,我似乎无法记录与续航和玩家之间的冲突-实体只是直接穿过玩家,没有续航声音,也没有登录到控制台,这导致我认为问题出在符合逻辑。
我需要它登录到控制台,播放声音和生成的频率不像障碍物那样多,每10秒一次(此刻似乎与障碍物一样生成)。
LifeComponent
public class LifeComponent implements Component, Pool.Poolable {
public boolean hit;
@Override
public void reset() {
hit = false;
}
}
生命实体
public class Life extends GameObjectBase implements Pool.Poolable {
private float ySpeed = GameConfig.EASY_OBSTACLE_SPEED;
private boolean hit;
public Life(){
super(GameConfig.OBSTACLE_BOUNDS_RADIUS);
setSize(GameConfig.OBSTACLE_SIZE, GameConfig.OBSTACLE_SIZE);
}
public void update(){
setY(getY() - ySpeed);
}
public boolean isPlayerColliding(Player player) {
Circle playerBounds = player.getBounds();
boolean overlaps = Intersector.overlaps(playerBounds, getBounds());
hit = overlaps;
return overlaps;
}
public boolean isNotHit(){
return !hit;
}
public void setYSpeed(float ySpeed) {
this.ySpeed = ySpeed;
}
@Override
public void reset() {
hit = false;
}
}
碰撞侦听器
public interface CollisionListener {
void hitObstacle();
}
CollisionSystem
public class CollisionSystem extends EntitySystem {
private static final Logger log = new Logger(CollisionSystem.class.getName(), Logger.DEBUG);
private static final Family PLAYER_FAMILY = Family.all(
PlayerComponent.class,
BoundsComponent.class
).get();
private static final Family OBSTACLE_FAMILY = Family.all(
ObstacleComponent.class,
BoundsComponent.class
).get();
private static final Family LIFE_FAMILY = Family.all(
BoundsComponent.class,
LifeComponent.class
).get();
private final CollisionListener listener;
private final LifeCollision lifeListener;
public CollisionSystem(CollisionListener listener, LifeCollision ll){
this.listener = listener;
this.lifeListener = ll;
}
@Override
public void update(float deltaTime) {
ImmutableArray<Entity> players = getEngine().getEntitiesFor(PLAYER_FAMILY);
ImmutableArray<Entity> obstacles = getEngine().getEntitiesFor(OBSTACLE_FAMILY);
ImmutableArray<Entity> lives = getEngine().getEntitiesFor(LIFE_FAMILY);
for(Entity playersEntity : players){
for(Entity obstacleEntity : obstacles) {
ObstacleComponent obstacle = Mappers.OBSTACLE.get(obstacleEntity);
if(obstacle.hit){
continue;
}
if(checkCollision(playersEntity, obstacleEntity)){
obstacle.hit = true;
log.debug("collision with obstacle");
listener.hitObstacle();
}
for(Entity lifeEntity : lives){
LifeComponent life = Mappers.LIFE.get(lifeEntity);
if(life.hit){
if(checkCollision(playersEntity, lifeEntity)){
life.hit = true;
log.debug("lifeup");
lifeListener.hitLife();
}}
}
}
}
}
private boolean checkCollision(Entity player, Entity obstacle){
BoundsComponent playerBounds = Mappers.BOUNDS.get(player);
BoundsComponent obstacleBounds = Mappers.BOUNDS.get(obstacle);
return Intersector.overlaps(playerBounds.bounds, obstacleBounds.bounds);
}
}
生命碰撞
public interface LifeCollision {
void hitLife();
}
LifeSpawnSystem
public class LifeSpawnSystem extends IntervalSystem {
private final EntityFactory factory;
public LifeSpawnSystem(EntityFactory factory){
super(GameConfig.LIFE_SPAWN_TIME);
this.factory = factory;
}
@Override
protected void updateInterval() {
float lifeMin = 0;
float lifeMax = 3;
float lifeX = MathUtils.random(lifeMin , lifeMax);
float lifeY = GameConfig.WORLD_HEIGHT;
factory.addLife(lifeX, lifeY);
}
}
GameScreen
public class GameScreen implements Screen {
private static final Logger log = new Logger(GameScreen.class.getName(), Logger.DEBUG);
private final ObstacleAvoidGame game;
private final AssetManager assetManager;
private Viewport viewport;
private ShapeRenderer renderer;
private PooledEngine engine;
private OrthographicCamera camera;
private EntityFactory factory;
private Viewport hudViewport;
private Sound hit;
private Sound lifeUpSound;
private boolean reset;
private static final boolean DEBUG = false;
public GameScreen(ObstacleAvoidGame game) {
this.game = game;
assetManager = game.getAssetManager();
}
@Override
public void show() {
log.debug(" show()");
camera = new OrthographicCamera();
viewport = new FitViewport(GameConfig.WORLD_WIDTH, GameConfig.WORLD_HEIGHT, camera);
hudViewport = new FitViewport(GameConfig.HUD_WIDTH, GameConfig.HUD_HEIGHT);
renderer = new ShapeRenderer();
engine = new PooledEngine();
factory = new EntityFactory(engine, assetManager);
BitmapFont font = assetManager.get(AssetDescriptors.FONT);
hit = assetManager.get(AssetDescriptors.HIT_SOUND);
lifeUpSound = assetManager.get(AssetDescriptors.LIFE_UP);
CollisionListener listener = new CollisionListener() {
@Override
public void hitObstacle() {
GameManager.INSTANCE.decrementLives();
hit.play();
if (GameManager.INSTANCE.isGameOver()) {
GameManager.INSTANCE.updateHighScore();
} else {
engine.removeAllEntities();
reset = true;
}
}
};
LifeCollision lifeListener = new LifeCollision() {
@Override
public void hitLife() {
GameManager.INSTANCE.addLife();
lifeUpSound.play();
}
};
engine.addSystem(new PlayerSystem());
engine.addSystem(new MovementSystem());
engine.addSystem(new WorldWrapSystem(viewport));
engine.addSystem(new BoundsSystem());
engine.addSystem(new ObstacleSpawnSystem(factory));
engine.addSystem(new LifeSpawnSystem(factory));
engine.addSystem(new CleanUpSystem());
engine.addSystem(new CollisionSystem(listener, lifeListener));
engine.addSystem(new ScoreSystem());
engine.addSystem(new RenderSystem(viewport, game.getBatch()));
engine.addSystem(new HudRenderSystem(hudViewport, game.getBatch(), font));
if(DEBUG) {
engine.addSystem(new GridRenderSystem(viewport, renderer));
engine.addSystem(new DebugRenderSystem(viewport, renderer));
engine.addSystem(new DebugCameraSystem(camera, GameConfig.WORLD_CENTER_X, GameConfig.WORLD_CENTER_Y));
}
addEntities();
}
@Override
public void render(float delta) {
GdxUtils.clearScreen();
engine.update(delta);
if(GameManager.INSTANCE.isGameOver()){
GameManager.INSTANCE.reset();
game.setScreen(new MenuScreen(game));
}
if(reset){
reset = false;
addEntities();
}
}
private void addEntities(){
factory.addBackground();
factory.addPlayer();
}
@Override
public void resize(int width, int height) {
viewport.update(width, height, true);
hudViewport.update(width, height, true);
}
@Override
public void pause() {
}
@Override
public void resume() {
}
@Override
public void hide() {
dispose();
}
@Override
public void dispose() {
renderer.dispose();
}
}
实体工厂
public class EntityFactory {
private final PooledEngine engine;
private final AssetManager assetManager;
private final TextureAtlas gamePlayAtlas;
public EntityFactory(PooledEngine engine, AssetManager assetManager ) {
this.engine = engine;
this.assetManager = assetManager;
gamePlayAtlas = assetManager.get(AssetDescriptors.GAME_PLAY);
}
public void addPlayer(){
float x = (GameConfig.WORLD_WIDTH - GameConfig.PLAYER_SIZE) / 2f;
float y = 1 - GameConfig.PLAYER_SIZE / 2f;
PositionComponent position = engine.createComponent(PositionComponent.class);
position.x = x;
position.y = y;
BoundsComponent bounds = engine.createComponent(BoundsComponent.class);
bounds.bounds.set(x, y, GameConfig.PLAYER_BOUNDS_RADIUS);
MovementComponent movement = engine.createComponent(MovementComponent.class);
PlayerComponent player = engine.createComponent(PlayerComponent.class);
WorldWrapComponent worldWrap = engine.createComponent(WorldWrapComponent.class);
TextureComponent texture = engine.createComponent(TextureComponent.class);
texture.region = gamePlayAtlas.findRegion(RegionNames.PLAYER);
DimensionComponent dimension = engine.createComponent(DimensionComponent.class);
dimension.width = GameConfig.PLAYER_SIZE;
dimension.height = GameConfig.PLAYER_SIZE;
Entity entity = engine.createEntity();
entity.add(bounds);
entity.add(movement);
entity.add(player);
entity.add(position);
entity.add(worldWrap);
entity.add(texture);
entity.add(dimension);
engine.addEntity(entity);
}
public void addObstacle(float x, float y){
BoundsComponent bounds = engine.createComponent(BoundsComponent.class);
bounds.bounds.set(x, y, GameConfig.OBSTACLE_BOUNDS_RADIUS);
MovementComponent movement = engine.createComponent(MovementComponent.class);
movement.ySpeed = -GameManager.INSTANCE.getDifficultyLevel().getObstacleSpeed();
PositionComponent position = engine.createComponent(PositionComponent.class);
position.x = x;
position.y = y;
CleanUpComponent cleanUp = engine.createComponent(CleanUpComponent.class);
ObstacleComponent obstacle = engine.createComponent(ObstacleComponent.class);
TextureComponent texture = engine.createComponent(TextureComponent.class);
texture.region = gamePlayAtlas.findRegion(RegionNames.OBSTACLE);
DimensionComponent dimension = engine.createComponent(DimensionComponent.class);
dimension.width = GameConfig.OBSTACLE_SIZE;
dimension.height = GameConfig.OBSTACLE_SIZE;
Entity entity = new Entity();
entity.add(bounds);
entity.add(movement);
entity.add(position);
entity.add(cleanUp);
entity.add(obstacle);
entity.add(texture);
entity.add(dimension);
engine.addEntity(entity);
}
public void addLife(float x, float y){
BoundsComponent bounds = engine.createComponent(BoundsComponent.class);
bounds.bounds.set(x, y, GameConfig.OBSTACLE_BOUNDS_RADIUS);
LifeComponent life = engine.createComponent(LifeComponent.class);
TextureComponent texture = engine.createComponent(TextureComponent.class);
texture.region = gamePlayAtlas.findRegion(RegionNames.OBSTACLE);
texture.region.flip(true, false);
PositionComponent position = engine.createComponent(PositionComponent.class);
position.x = x;
position.y = y;
MovementComponent movement = engine.createComponent(MovementComponent.class);
movement.ySpeed = -GameManager.INSTANCE.getDifficultyLevel().getObstacleSpeed();
DimensionComponent dimension = engine.createComponent(DimensionComponent.class);
dimension.width = GameConfig.OBSTACLE_SIZE * 1.5f;
dimension.height = GameConfig.OBSTACLE_SIZE * 1.2f;
CleanUpComponent cleanUp = engine.createComponent(CleanUpComponent.class);
Entity entity = new Entity();
entity.add(life);
entity.add(movement);
entity.add(position);
entity.add(cleanUp);
entity.add(texture);
entity.add(dimension);
engine.addEntity(entity);
}
public void addBackground(){
TextureComponent texture = engine.createComponent(TextureComponent.class);
texture.region = gamePlayAtlas.findRegion(RegionNames.BACKGROUND);
PositionComponent position = engine.createComponent(PositionComponent.class);
position.x = 0;
position.y = 0;
DimensionComponent dimension = engine.createComponent(DimensionComponent.class);
dimension.width = GameConfig.WORLD_WIDTH;
dimension.height = GameConfig.WORLD_HEIGHT;
Entity entity = engine.createEntity();
entity.add(texture);
entity.add(position);
entity.add(dimension);
engine.addEntity(entity);
}
}
https://github.com/BenMohammad/obstacle-avoid-ashley
生命从屏幕的高度开始从天而降-应该是可收藏的,可以为玩家增加生命,目前它频繁地产生,就像我说的逻辑我错了。认为它不会登录到控制台。
谢谢