/*
* The MIT License (MIT)
*
* FXGL - JavaFX Game Library
*
* Copyright (c) 2015-2017 AlmasB (almaslvl@gmail.com)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.almasb.fxglgames.pacman.control;
import com.almasb.fxgl.app.FXGL;
import com.almasb.fxgl.core.math.FXGLMath;
import com.almasb.fxgl.core.math.Vec2;
import com.almasb.fxgl.ecs.AbstractControl;
import com.almasb.fxgl.ecs.Entity;
import com.almasb.fxgl.entity.Entities;
import com.almasb.fxgl.entity.component.BoundingBoxComponent;
import com.almasb.fxgl.entity.component.PositionComponent;
import com.almasb.fxglgames.pacman.PacmanApp;
import com.almasb.fxglgames.pacman.PacmanType;
import javafx.geometry.Point2D;
import java.util.List;
import java.util.Random;
/**
* @author Almas Baimagambetov (almaslvl@gmail.com)
*/
public class EnemyControl extends AbstractControl {
protected PositionComponent position;
private BoundingBoxComponent bbox;
private MoveDirection moveDir;
private Random random = new Random();
public void setMoveDirection(MoveDirection moveDir) {
this.moveDir = moveDir;
}
@Override
public void onAdded(Entity entity) {
position = Entities.getPosition(entity);
bbox = Entities.getBBox(entity);
moveDir = MoveDirection.values()[random.nextInt(MoveDirection.values().length)];
}
protected MoveDirection updateMoveDirection() {
return MoveDirection.values()[random.nextInt(MoveDirection.values().length)];
}
private double speed = 0;
@Override
public void onUpdate(Entity entity, double tpf) {
speed = tpf * 60;
switch (moveDir) {
case UP:
up();
break;
case DOWN:
down();
break;
case LEFT:
left();
break;
case RIGHT:
right();
break;
}
if (position.getX() < 0) {
position.setX(PacmanApp.BLOCK_SIZE * PacmanApp.MAP_SIZE - bbox.getWidth() - 5);
}
if (bbox.getMaxXWorld() > PacmanApp.BLOCK_SIZE * PacmanApp.MAP_SIZE) {
position.setX(0);
}
}
public void up() {
move(0, -5 * speed);
}
public void down() {
move(0, 5 * speed);
}
public void left() {
move(-5 * speed, 0);
}
public void right() {
move(5 * speed, 0);
}
private List<Entity> blocks;
private void move(Point2D vector) {
if (!getEntity().isActive())
return;
if (blocks == null) {
blocks = FXGL.getApp().getGameWorld().getEntitiesByType(PacmanType.BLOCK);
}
long length = Math.round(vector.magnitude());
Point2D unit = vector.normalize();
for (int i = 0; i < length; i++) {
position.translate(unit);
boolean collision = blocks.stream()
.map(b -> Entities.getBBox(b))
.filter(box -> box.isCollidingWith(bbox))
.findAny()
.isPresent();
if (collision) {
position.translate(unit.multiply(-1));
moveDir = updateMoveDirection();
break;
}
}
}
private Vec2 velocity = new Vec2();
private void move(double dx, double dy) {
if (!getEntity().isActive())
return;
if (blocks == null) {
blocks = FXGL.getApp().getGameWorld().getEntitiesByType(PacmanType.BLOCK);
}
velocity.set((float) dx, (float) dy);
int length = FXGLMath.roundPositive(velocity.length());
velocity.normalizeLocal();
for (int i = 0; i < length; i++) {
position.translate(velocity.x, velocity.y);
boolean collision = false;
for (int j = 0; j < blocks.size(); j++) {
if (Entities.getBBox(blocks.get(j)).isCollidingWith(bbox)) {
collision = true;
break;
}
}
if (collision) {
position.translate(-velocity.x, -velocity.y);
moveDir = updateMoveDirection();
break;
}
}
// double mag = Math.sqrt(dx * dx + dy * dy);
// long length = Math.round(mag);
//
// double unitX = dx / mag;
// double unitY = dy / mag;
//
// for (int i = 0; i < length; i++) {
// position.translate(unitX, unitY);
//
// boolean collision = false;
//
// for (int j = 0; j < blocks.size(); j++) {
// if (Entities.getBBox(blocks.get(j)).isCollidingWith(bbox)) {
// collision = true;
// break;
// }
// }
//
// if (collision) {
// position.translate(-unitX, -unitY);
// moveDir = updateMoveDirection();
//
// break;
// }
// }
}
}