I can't succeed in making the enemies move from node to node.
I managed to set up the whole pathfinding, I'm getting a full path to the player and the position of the next node all the way to the end.
How do I move the box2d body from node to node?
Or even simpler - how do I move a box2d body to a certain position?
I tried applying impulses, forces weren't able to do it.
Here is my simplified code. Both Monster and Player classes extend Sprite:
public class B2dSteeringEntity implements Steerable<Vector2>, Updateable {
public static final String TAG = B2dSteeringEntity.class.getName();
Body body;
boolean tagged;
float maxLinearSpeed, maxLinearAcceleration;
float maxAngularSpeed, maxAngularAcceleration;
float boundingRadius;
SteeringBehavior<Vector2> behavior;
SteeringAcceleration<Vector2> steeringOutput;
public B2dSteeringEntity(Body body, float boundingRadius) {
this.body = body;
this.boundingRadius = boundingRadius;
this.maxLinearSpeed = 250;
this.maxLinearAcceleration = 200;
this.maxAngularSpeed = 0;
this.maxAngularAcceleration = 0;
this.tagged = false;
this.steeringOutput = new SteeringAcceleration<Vector2>(new Vector2());
}
#Override
public Vector2 getLinearVelocity() {
return body.getLinearVelocity();
}
#Override
public float getAngularVelocity() {
return body.getAngularVelocity();
}
#Override
public float getBoundingRadius() {
return 0;
}
#Override
public boolean isTagged() {
return tagged;
}
#Override
public void setTagged(boolean tagged) {
this.tagged = tagged;
}
#Override
public float getZeroLinearSpeedThreshold() {
return 0;
}
#Override
public void setZeroLinearSpeedThreshold(float value) {
}
#Override
public float getMaxLinearSpeed() {
return maxLinearSpeed;
}
#Override
public void setMaxLinearSpeed(float maxLinearSpeed) {
this.maxLinearSpeed = maxLinearSpeed;
}
#Override
public float getMaxLinearAcceleration() {
return maxLinearAcceleration;
}
#Override
public void setMaxLinearAcceleration(float maxLinearAcceleration) {
this.maxLinearAcceleration = maxLinearAcceleration;
}
#Override
public float getMaxAngularSpeed() {
return maxAngularSpeed;
}
#Override
public void setMaxAngularSpeed(float maxAngularSpeed) {
this.maxAngularSpeed = maxAngularSpeed;
}
#Override
public float getMaxAngularAcceleration() {
return maxAngularAcceleration;
}
#Override
public void setMaxAngularAcceleration(float maxAngularAcceleration) {
this.maxAngularAcceleration = maxAngularAcceleration;
}
#Override
public Vector2 getPosition() {
return body.getPosition();
}
#Override
public float getOrientation() {
return body.getAngle();
}
#Override
public void setOrientation(float orientation) {
}
#Override
public float vectorToAngle(Vector2 vector) {
return SteeringUtils.vectorToAngle(vector);
}
#Override
public Vector2 angleToVector(Vector2 outVector, float angle) {
return SteeringUtils.angleToVector(outVector, angle);
}
#Override
public Location<Vector2> newLocation() {
return null;
}
public Body getBody() {
return body;
}
public void setBehavior(SteeringBehavior<Vector2> behavior) {
this.behavior = behavior;
}
public SteeringBehavior<Vector2> getBehavior() {
return behavior;
}
private void applySteering(float deltaTime) {
boolean anyAccelerations = false;
if(!steeringOutput.linear.isZero()) {
Vector2 force = steeringOutput.linear.scl(deltaTime);
body.applyForceToCenter(force, true);
anyAccelerations = true;
}
if(anyAccelerations) {
Vector2 velocity = body.getLinearVelocity();
float currentSpeedSquare = velocity.len2();
if(currentSpeedSquare > maxLinearSpeed * maxLinearSpeed) {
body.setLinearVelocity(velocity.scl(maxLinearSpeed / (float) Math.sqrt(currentSpeedSquare)));
}
if (body.getAngularVelocity() > maxAngularSpeed) {
body.setAngularVelocity(maxAngularSpeed);
}
}
}
#Override
public void update(float deltaTime) {
if (behavior != null) {
behavior.calculateSteering(steeringOutput);
applySteering(deltaTime);
}
}
}
public Skeleton(B2WorldCreator creator, GameScreen screen, float x, float y, State state, HeroKnight player) {
super(creator, screen, x, y, state, player);
controller = screen.getController();
setBounds(x, y, 150 / Constants.PPM, 150 / Constants.PPM);
enemyAgentComponent = new EnemyAgentComponent(b2body, b2dSteeringEntity, controller, player);
}
And here is the EnemyAgentComponent class:
public class EnemyAgentComponent implements Component, Telegraph, Updateable, Pather<Node> {
public static final String TAG = EnemyAgentComponent.class.getName();
public StateMachine<EnemyAgentComponent, EnemyState> stateMachine;
public boolean isInProximity() {
return inProximity;
}
public boolean inProximity = false;
public boolean lowHP = false;
public boolean isShot = false;
private boolean isRequested = false;
private boolean requestingMovement;
private Steering wayPoint;
private Body body;
private Controller controller;
private HeroKnight player;
private Node startNode, endNode, previousStartNode, previousEndNode;
private Vector2 goal;
private PathfindingTarget newGoal;
private float impulseMag;
private boolean nodeReached;
private boolean pathGenerated;
private Arrive<Vector2> arriveSB;
private Steering waypoint;
private B2dSteeringEntity steering;
private IndexedAStarPathFinder<Node> pathFinder;
private GraphPathImp resultPath = new GraphPathImp();
private float pathfindingTimer;
private boolean firstPathGenerated;
public boolean isTouchingPlayer() {
return touchingPlayer;
}
public void setTouchingPlayer(boolean touchingPlayer) {
this.touchingPlayer = touchingPlayer;
}
private boolean touchingPlayer;
public EnemyAgentComponent(Body body, B2dSteeringEntity steering, Controller controller, HeroKnight player) {
construct(body, steering, controller, player);
}
public void construct(Body body, B2dSteeringEntity steering, Controller controller, HeroKnight player) {
this.steering = steering;
this.controller = controller;
this.body = body;
this.player = player;
stateMachine = new DefaultStateMachine<>(this, EnemyState.SEEKING);
MessageManager.getInstance().addListener(this, Messages.PLAYER_IN_SIGHT);
MessageManager.getInstance().addListener(this, Messages.PLAYER_ATTACKED_ENEMY);
MessageManager.getInstance().addListener(this, Messages.LOW_HP);
MessageManager.getInstance().addListener(this, Messages.PLAYER_OUT_OF_SIGHT);
MessageManager.getInstance().addListener(this, Messages.TOUCHING_PLAYER);
pathFinder = new IndexedAStarPathFinder<Node>(LevelManager.groundGraph, false);
requestingMovement = false;
goal = null;
nodeReached = false;
pathGenerated = false;
firstPathGenerated = false;
pathfindingTimer = 0;
touchingPlayer = false;
}
public Vector2 getGoal() {
return goal;
}
public boolean isRequestingMovement() {
return requestingMovement;
}
public void setRequestingMovement(boolean requestingMovement) {
this.requestingMovement = requestingMovement;
}
public boolean isPathGenerated() {
return pathGenerated;
}
public GraphPathImp getResultPath() {
return resultPath;
}
public void generatePath() {
previousEndNode = endNode;
previousStartNode = startNode;
resultPath.clear();
pathFinder.searchNodePath(startNode, endNode, new HeuristicImp(), resultPath);
newGoal = new PathfindingTarget(resultPath.get(0).getNodePosition());
pathGenerated = true;
}
public void update(float deltaTime) {
startNode = LevelManager.groundGraph.getNodeByXY(body.getPosition().x, body.getPosition().y);
endNode = LevelManager.groundGraph.getNodeByXY(player.b2body.getPosition().x, player.b2body.getPosition().y);
//If player gets in certain range of the enemy and is not touching the enemy, enemy's path is being generated
if (inProximity) {
if (!firstPathGenerated && !touchingPlayer)
if ((pathfindingTimer == 0)) {
generatePath();
previousStartNode = startNode;
previousEndNode = endNode;
firstPathGenerated = true;
}
//If a path was already created, a new path is being requested only if player's position changes
if (firstPathGenerated && (previousEndNode != endNode) && pathfindingTimer == 0 && !touchingPlayer) {
generatePath();
}
if (firstPathGenerated)
pathfindingTimer += deltaTime;
//Paths are generated every 2 seconds
if (pathfindingTimer >= 2) {
pathfindingTimer = 0;
}
//If enemy touches the player pathfinding ends
if (touchingPlayer) {
pathfindingTimer = 0;
pathGenerated = false;
resultPath.clear();
body.setLinearVelocity(0, 0);
}
}
//The arrive behaviour is set, newGoal being the position of next node
if (steering.getLinearVelocity().x == 0 && steering.getLinearVelocity().y == 0 && newGoal != null) {
steering.setBehavior(new Arrive<Vector2>(steering, newGoal));
}
steering.update(deltaTime);
//Updating the next node position based on the enemy reaching a node
if (pathGenerated)
if (Math.abs(body.getPosition().x - newGoal.getPosition().x) <= 0.1f && Math.abs(body.getPosition().y - newGoal.getPosition().y) <= 51 / 2f / Constants.PPM)
{
updatePath();
}
}
public void updatePath() {
//Setting the next target position
if (resultPath.getCount() > 0) {
resultPath.removeIndex(0);
if (!touchingPlayer && resultPath.getCount() > 0) {
newGoal.setPosition(resultPath.get(0).getNodePosition());
requestingMovement = true;
nodeReached = false;
}
}
}
#Override
public boolean handleMessage(Telegram telegram) {
if (telegram.message == Messages.PLAYER_IN_SIGHT) {
inProximity = true;
return true;
}
if (telegram.message == Messages.PLAYER_OUT_OF_SIGHT) {
inProximity = false;
firstPathGenerated = false;
pathGenerated = false;
pathfindingTimer = 0;
resultPath.clear();
}
if (telegram.message == Messages.LOW_HP) {
lowHP = true;
return true;
}
if (telegram.message == Messages.PLAYER_ATTACKED_ENEMY) {
isShot = true;
return true;
}
if (telegram.message == Messages.TOUCHING_PLAYER) {
touchingPlayer = true;
return true;
}
return false;
}
#Override
public void acceptPath(PathFinderRequest<Node> request) {
if (request.pathFound) {
resultPath = (GraphPathImp) request.resultPath;
}
}
}
Skeleton class is being updated and drawn using skeleton.update(deltaTime) and skeleton.draw(deltaTime).
EDIT2:
Now tried using linear impulses, movement is very clunky:
if (newGoal != null) {
Vector2 direction = new Vector2(newGoal.getPosition().x - body.getPosition().x, newGoal.getPosition().y - body.getPosition().y).nor();
float speed = Constants.SKELETON_SPEED;
Vector2 velocity = new Vector2(speed * direction.x, speed * direction.y);
body.applyLinearImpulse(velocity.x * body.getMass(), velocity.y * body.getMass(), body.getWorldCenter().x, body.getWorldCenter().y, true);
}
if (pathGenerated)
if (Math.abs(body.getPosition().x - newGoal.getPosition().x) <= 0.1f && Math.abs(body.getPosition().y - newGoal.getPosition().y) <= 51 / 2f / Constants.PPM)
{
Gdx.app.debug(TAG, "Node reached!");
updatePath();
}
Moving an entity is not directly related to AI. The AI just finds a way, the entity follows it.
With box2d, you have to apply forces or impulses into the right directions, make sure your box2d world's step() method is being called and update your entites rendering coordinates (e.g. the sprite) to match the box2d's body coordinates. Then call your AI from the new coordinates in the next loop again, determine in which direction you have to move now and apply your forces again.
So the loop looks like
Find a way via AI
Find direction to the next node from your position
Apply forces/impulses
box2d world step
Adapt the entities rendering coordinates to match the box2d body position
Repeat
Giving you a more detailed answer requires more knowledge about how you render your entities and what your loop looks like. Please share some example code.
Edit: After you added some code I find it still unclear what you actual problem is. Can you move your entity but fail to stop it? Does it move at all? Do you call world.step()? The only obvious issue I could find after a quick look is that you scale applyForceToCenter with deltaTime which is not needed as world.step already takes a timeStep as a parameter.
Related
I'm looking to add an object called "player" to a binary search tree based on how high the score of the player is, essentially like a scoreboard, but I'm not entirely certain how to add players to the binary tree; I'm curious how to go about writing the method, so I hope this question makes sense.
Here's a part of my BinaryTree class:
import java.util.Iterator;
public class BinaryTree implements Iterable<Player> {
private BinNode root;
public BinaryTree() {
root = null;
}
public boolean isEmpty() {
return root == null;
}
// TODO: add the given player to the binary tree based on the player's game score
public void add(final Player player) {
if (isEmpty())
root = new BinNode(player);
// this is SUUUPER placeholder
} ...
Here's the player class, :
public class Player implements Comparable<Player> {
private String name;
private int score;
private static final int MIN_SCORE = 0;
public Player(final String name, int score) {
this.name = name;
if (score < MIN_SCORE)
this.score = 0;
else
this.score = score;
}
public Player(final String name) {
this(name, MIN_SCORE);
}
public String getName() {
return name;
}
public int getScore() {
return score;
}
#Override
public String toString() {
return name + ": " + score;
}
// TODO: compare player objects based on their scores
#Override
public int compareTo(Player other) {
return score - other.score;// I think this is a step in the right direction???
}
}
Here's my Binary Node class:
public class BinNode {
private Player player;
private BinNode left, right;
public BinNode() {
player = null;
left = right = null;
}
public BinNode(final Player player) {
this.player = player;
left = right = null;
}
public Player getPlayer() {
return player;
}
public BinNode getLeft() {
return left;
}
public BinNode getRight() {
return right;
}
public void setPlayer(final Player data) {
this.player = player;
}
public void setLeft(BinNode left) {
this.left = left;
}
public void setRight(BinNode right) {
this.right = right;
}
#Override
public String toString() {
return player.toString();
}
}
I recommend you not to use your own trees in production, but if you are just learn, then that's fine. To add a new entity to your tree, you have to find a place for it. In this code we search for it by comparing scores of players.
public void add(final Player player){
if (isEmpty()){
root = new BinNode(player);
}
else{
BinNode node = root;
while (true){
if (player.getScore() <= node.getPlayer().getScore()){
if (node.getLeft() == null){
node.getLeft() = new BinNode(player);
return;
}
else{
node = node.getLeft();
}
}
else{
if (node.getRight() == null){
node.getRight() = new BinNode(player);
return;
}
else {
node = node.getRight();
}
}
}
}
}
So I've been working on this chess app for about a week now (a few hours a day)-- and I seem to have hit a snag. All of the pieces move as they should, with collision and all-- I have promotion and castling working, and I can successfully check for being in check.
However, I can't seem to check if a move legally gets out of check. My current approach is to move the piece-- check if the person is still in check, and if not then the move is legal.
It seems that when I do this, however, it doesn't correctly calculate the check after the faux-move.
Any help would be great.
public abstract class Piece {
private Type type = Type.BLANK;
private int locX, locY, preX, preY;
private Player player;
private boolean moved = false;
Piece(Type type, int locX, int locY, Player player) {
this.locX = locX;
this.locY = locY;
this.player = player;
this.type = type;
}
public void movePiece(int x, int y) {
if (player.isTurn()) {
if (isLegalMove(x, y)) {
if (checkCollision(x, y)) {
if (clearsCheck(x, y)) {
preX = locX;
preY = locY;
setLoc(x, y);
specialPreMove(x, y);
moved = true;
Chess.chessBoard.bitBoard[preX][preY] = null;
if (Chess.chessBoard.bitBoard[x][y] != null) {
Chess.chessBoard.bitBoard[x][y].getPlayer().pieces.remove(Chess.chessBoard.bitBoard[x][y]);
}
Chess.chessBoard.bitBoard[x][y] = this;
specialPostMove(x, y);
Chess.chessBoard.getGui().repaint();
Chess.changeTurns();
}
}
}
}
}
protected void specialPreMove(int x, int y) {}
protected void specialPostMove(int x, int y) {}
protected abstract boolean checkCollision(int x, int y);
protected abstract boolean isLegalMove(int x, int y);
private boolean clearsCheck(int x, int y) {
boolean checkCk = false;
preX = locX;
preY = locY;
setLoc(x, y);
Piece locPiece = null;
Chess.chessBoard.bitBoard[preX][preY] = null;
if (Chess.chessBoard.bitBoard[x][y] != null) {
locPiece = Chess.chessBoard.bitBoard[x][y];
Chess.chessBoard.bitBoard[x][y].getPlayer().pieces.remove(Chess.chessBoard.bitBoard[x][y]);
System.out.println("Piece there: " + locPiece);
}
Chess.chessBoard.bitBoard[x][y] = this;
System.out.println(Chess.chessBoard.bitBoard[x][y]);
Chess.chessBoard.getGui().repaint();
Chess.checkCheck();
checkCk = !player.inCheck();
setLoc(preX, preY);
Chess.chessBoard.bitBoard[preX][preY] = this;
if (locPiece != null) {
Chess.chessBoard.bitBoard[x][y] = locPiece;
Chess.chessBoard.bitBoard[x][y].getPlayer().pieces.add(Chess.chessBoard.bitBoard[x][y]);
} else {
Chess.chessBoard.bitBoard[x][y] = null;
}
System.out.println(checkCk);
return checkCk;
}
public ArrayList<Move> getLegalMoves() {
ArrayList<Move> moves = new ArrayList<Move>();
for (int row = 0; row < 8; row++) {
for (int col = 0; col < 8; col++) {
if (isLegalMove(row, col) && checkCollision(row, col)) {
moves.add(new Move(row, col));
}
}
}
return moves;
}
is the piece class, and then the check method
public static void checkCheck() {
for (Move m : player1.getLegalMoves()) {
if (m.getX() == player2.getKing().getLocX()
&& m.getY() == player2.getKing().getLocY()) {
player2.setCheck(true);
System.out.println("IN CHECK PLAYER 2");
break;
}
}
for (Move m : player2.getLegalMoves()) {
if (m.getX() == player1.getKing().getLocX()
&& m.getY() == player1.getKing().getLocY()) {
player1.setCheck(true);
System.out.println("IN CHECK PLAYER 1");
break;
}
}
}
and then here is some other stuff that is useful
public class Player {
private Color color;
private Direction direction;
private boolean turn;
private boolean check = false;
public ArrayList<Piece> pieces = new ArrayList<>();
public Player(Color color, Direction direction) {
this.color = color;
this.turn = false;
this.direction = direction;
}
public ArrayList<Move> getLegalMoves() {
ArrayList<Move> moves = new ArrayList<>();
for (Piece p : pieces) {
for (Move m : p.getLegalMoves()) {
moves.add(m);
}
}
return moves;
}
public Piece getKing() {
for (Piece p : pieces) {
if (p.getType() == Type.KING) {
return p;
}
}
return null;
}
Looks like once you set a player in check you're not setting his status later on to unchecked.
public static void checkCheck() {
boolean isInCheck = false;
for (Move m : player1.getLegalMoves()) {
if (m.getX() == player2.getKing().getLocX()
&& m.getY() == player2.getKing().getLocY()) {
isInCheck = true;
System.out.println("IN CHECK PLAYER 2");
break;
}
}
player2.setCheck(isInCheck);
isInCheck = false;
for (Move m : player2.getLegalMoves()) {
if (m.getX() == player1.getKing().getLocX()
&& m.getY() == player1.getKing().getLocY()) {
isInCheck = true;
System.out.println("IN CHECK PLAYER 1");
break;
}
}
player1.setCheck(isInCheck);
}
Hello I am new in Java and I have stuck. I am trying to make chess game, I made everything except check and checkmate method, and if you have any suggestions I will be happy to read them. Here is my work till now:
This is the board class where we play the game:
public class Board {
public static final int COLOR_WHITE = 1;
public static final int COLOR_BLACK = 2;
public static PlayingPiece[][] board;
private boolean isFirstMove;
private int color;
public Board() {
this.setBoard(new PlayingPiece[8][8]);
this.isFirstMove = true;
this.initializePieces();
}
// Initialize the chess pieces
public void initializePieces() {
for (int i = 0; i < 8; i++) {
board[1][i] = new Pawn(1, i, COLOR_WHITE);
}
for (int i = 0; i < 8; i++) {
board[6][i] = new Pawn(6, i, COLOR_BLACK);
}
board[0][0] = new Rook(0, 0, COLOR_WHITE);
board[0][7] = new Rook(0, 7, COLOR_WHITE);
board[7][0] = new Rook(7, 0, COLOR_BLACK);
board[7][7] = new Rook(7, 7, COLOR_BLACK);
board[0][1] = new Knight(0, 1, COLOR_WHITE);
board[0][6] = new Knight(0, 6, COLOR_WHITE);
board[7][1] = new Knight(7, 1, COLOR_BLACK);
board[7][6] = new Knight(7, 6, COLOR_BLACK);
board[0][2] = new Officer(0, 2, COLOR_WHITE);
board[0][5] = new Officer(0, 5, COLOR_WHITE);
board[7][2] = new Officer(7, 2, COLOR_BLACK);
board[7][5] = new Officer(7, 5, COLOR_BLACK);
board[0][3] = new Queen(3, 0, COLOR_WHITE);
board[0][4] = new King(4, 0, COLOR_WHITE);
board[7][3] = new Queen(7, 3, COLOR_BLACK);
board[7][4] = new King(7, 4, COLOR_BLACK);
this.printBoard();
}
public boolean play(int color, int fromX, int fromY, int toX, int toY) {
boolean isTrue = false;
// Check if this is the first turn and only white can move
if (isFirstMove && color == COLOR_WHITE) {
isTrue = true;
} else if (isFirstMove && color == COLOR_BLACK) {
return false;
}
// check if player plays 2 times in a raw and if you move the piece from
// current possition
if (color == this.color || (toX == fromX && toY == fromY)) {
return false;
}
isTrue = true;
if (isTrue == true) {
this.isFirstMove = false;
// Check if player plays with his own color
if (((board[fromX][fromY]).getColor() != color)) {
return false;
}
// Check the isLegal movement of every chess piece
if ((board[fromX][fromY]).move(toX, toY)) {
board[toX][toY] = board[fromX][fromY];
board[fromX][fromY] = null;
}
this.printBoard();
}
return isTrue;
}
public PlayingPiece[][] getBoard() {
return board;
}
public void setBoard(PlayingPiece[][] board) {
Board.board = board;
}
This is the Pieces class with all kind of pieces:
package com.chess.www;
public class PlayingPiece {
public static final int COLOR_WHITE = 1;
public static final int COLOR_BLACK = 2;
public static final char BLACK_PAWN = '\u265F';
public static final char BLACK_ROOK = '\u265C';
public static final char BLACK_KNIGHT = '\u265E';
public static final char BLACK_BISHOP = '\u265D';
public static final char BLACK_QUEEN = '\u265B';
public static final char BLACK_KING = '\u265A';
public static final char WHITE_PAWN = '\u2659';
public static final char WHITE_ROOK = '\u2656';
public static final char WHITE_KNIGHT = '\u2658';
public static final char WHITE_BISHOP = '\u2657';
public static final char WHITE_QUEEN = '\u2655';
public static final char WHITE_KING = '\u2654';
public static final char NO_PIECE = ' ';
private int x, y;
private boolean isAlive;
private int color;
private char symbol;
protected PlayingPiece (int newX, int newY, int newColor) {
this.setX(newX);
this.setY(newY);
this.color = newColor;
this.isAlive = true;
}
protected PlayingPiece(int newX, int newY) {
this.setX(newX);
this.setY(newY);
}
protected PlayingPiece() {
}
public int getX() {
return x;
}
public void setY(int y) {
this.y = y;
}
public int getY() {
return y;
}
public void setX(int x) {
this.x = x;
}
protected boolean moveIsLegal (int newX, int newY) {
boolean isLegal = false;
if ((0 <= newX && newX <= 7) && (0 <= newY && newY <= 7)){
isLegal = true;
}
return isLegal;
}
public boolean move (int newX, int newY) {
if (moveIsLegal(newX, newY)) {
setX(newX);
setY(newY);
return true;
}
return false;
}
public int getColor() {
return color;
}
public boolean isAlive() {
return isAlive;
}
public void setAlive(boolean isAlive) {
this.isAlive = isAlive;
}
public char getSymbol() {
return symbol;
}
public void setSymbol(char symbol) {
this.symbol = symbol;
}
}
And here is the King class:
package com.chess.www;
public class King extends PlayingPiece {
public King(int newX, int newY, int color) {
super(newX, newY, color);
if (color == COLOR_BLACK) {
this.setSymbol(BLACK_KING);
} else {
this.setSymbol(WHITE_KING);
}
}
#Override
protected boolean moveIsLegal(int newX, int newY) {
int newPositionX = newX - getX();
int newPositionY = newY - getY();
int checkX = this.getX();
int checkY = this.getY();
if (super.moveIsLegal(newX, newY)) {
if ((Math.abs(newPositionX) == 1) && (newY == getY())) {
while (checkX != newX) {
if (this.isValidTraceX(checkX, newY, newX)) {
return true;
}
if (checkX > newX) {
checkX--;
} else if (this.getX() < newX) {
checkX++;
}
}
} else if ((newX == getX()) && (Math.abs(newPositionY) == 1)) {
while (checkY != newY) {
if (this.isValidTraceY(newX, checkY, newY)) {
return true;
}
if (checkY > newY) {
checkY--;
} else if (this.getY() < newY) {
checkY++;
}
}
} else if ((Math.abs(newPositionY) == 1) == (Math.abs(newPositionX) == 1)) {
while (checkX != newX && checkY != newY) {
if (this.isValidTrace(checkX, checkY, newX, newY)) {
return true;
}
if (checkX > newX) {
checkX--;
} else if (this.getX() < newX) {
checkX++;
}
if (checkY > newY) {
checkY--;
} else if (this.getY() < newY) {
checkY++;
}
}
}
}
return false;
}
public boolean isValidTraceX(int newX, int newY, int lastX) {
boolean isValid = true;
if ((Board.board[newX][newY]) != null) {
isValid = false;
}
if (((Board.board[lastX][newY]) != null)) {
if (Board.board[lastX][newY].getColor() == this.getColor()) {
isValid = false;
} else {
isValid = true;
}
}
return isValid;
}
public boolean isValidTraceY(int newX, int newY, int lastY) {
boolean isValid = true;
if ((Board.board[newX][newY]) != null) {
isValid = false;
}
if (((Board.board[newX][lastY]) != null)) {
if (Board.board[newX][lastY].getColor() == this.getColor()) {
isValid = false;
} else {
isValid = true;
}
}
return isValid;
}
public boolean isValidTrace(int newX, int newY, int lastX, int lastY) {
boolean isValid = true;
if ((Board.board[newX][newY]) != null) {
isValid = false;
}
if (((Board.board[lastX][lastY]) != null)) {
if (Board.board[lastX][lastY].getColor() == this.getColor()) {
isValid = false;
} else {
isValid = true;
}
}
return isValid;
}
}
I want to implement the method for check in board class do you have any suggestions?
The way I would implement would be just a method in the King class called something like, isChecked.
boolean isChecked() {
/* Check straight lines */
for (directions) { // up, down, left and right
for (square in direction) { // square by square from the king and out in the current direction
if (square contains opponent rook or queen)
return true;
else if (square contains friendly piece)
continue;
/* Check diagonals */
for (directions) { // left-up, left-down, right-up and right-down
for (square in direction) { // square by square from the king and out in the current direction
if (square contains opponent bishop or queen)
return true;
else if (square contains friendly piece)
continue;
/* Check pawns */
if (squares where pawns would threaten the king contains pawns)
return true;
/* Check king, this is to find if a square is legal to move to only */
if (squares where a king would threaten the king contains king)
return true;
/* Check knights */
if (squares where knights would threaten the king contains knights)
return true;
Sorry, I haven't really got time to write the entire code now, but the pseudo code should be enough to understand the concept. If you need I could fix it later today.
The principle is just, check every possible way a king can be checked.
If a king is checked and all possible moves are also checked, it is a checkmate.
Hope it helps :)
import java.util.Arrays;
public class KingsChecker {
public static void main(String[] args) {
int n = Integer.parseInt(args[0]);
String[][] chess = new String[n][n];
print(chess,n);
}
public static void print (String[][] chess,int n) {
for(int i = 0; i< chess.length; i++) {
double random = Math.random()*n; //to generate a random number.
for(int j = 0; j < chess[i].length; j++) {
int column = (int)random;
int[] count = new int[n];
chess[i][j]= "+";
count[column]++;
if (count[column]<=1){
chess[i][column]="k";
System.out.print(chess[i][j]);
}
}
System.out.println();
}
}
}
I wrote an event system for a game engine I'm working on, which adds en event to a tile in a map which when the player intersects it, it does something. Whatever that something is. In this test case, it loads a new map.
The problem is that the frame rate when starting the game is about 30 right up until I begin the event by walking over it, which starts the event and brings the fps up to about 60.
EDIT: it seems that this issue only popped up after I added events. However, I added another similar warping event to see if the fps dropped even more, it didn't. And after I finished the first event, the fps went to normal and I still used the second event fine.
Here is the event class:
public class Event {
//Warping variables
private int newX, newY;
private Map _map, _mapOverlay;
private String eventType;
private String _name;
public Event(String name, String type) {
_name = name;
eventType = type;
}
public void setWarp(Map map, Map overlay, int x, int y) {
_map = map;
_mapOverlay = overlay;
newX = x;
newY = y;
}
public Map getMap() { return _map; }
public Map getOverlay() { return _mapOverlay; }
public int getNewX() { return newX; }
public int getNewY() { return newY; }
public String getEventType() { return eventType; }
public String getname() { return _name; }
}
This is the algorithm that is called when a warp event is collided with:
if(spr.spriteType() == "player" && tile.hasEvent()) {
if(tile.event().getEventType() == "warp") {
tiles().clear();
currentMap = tile.event().getMap();
currentOverlay = tile.event().getOverlay();
for(int i = 0; i < currentMap.getWidth() * currentMap.getHeight(); i++){
tiles().add(currentMap.accessTile(i));
tiles().add(currentOverlay.accessTile(i));
}
playerX = tile.event().getNewX();
playerY = tile.event().getNewY();
tile.endEvent();
}
}
This is the section inside of the tile class which contains methods that have to do with adding an event.
public void addEvent(Event event) {
this.event = event;
hasEvent = true;
}
public Event event() { return event; }
public boolean hasEvent() { return hasEvent; }
public void endEvent() {
event = null;
hasEvent = false;
}
Lastly, here are the three lines used to add an event to an existing tile in a map:
warp1 = new Event("testWarp", "warp");
warp1.setWarp(city, cityOverlay, -200, 0);
city.accessTile(204).addEvent(warp1);
I am having a problem making an entity controllable in minecraft. I am are able to mount it, and it will move, but a few seconds after you move it, it just jumps back to where it was before you moved it. Here is my Entity class:
package net.minecraft.src;
public class mod_EntityMech extends EntityMob // this to make mob hostile
{
public boolean stationary;
public mod_EntityMech(World par1World)
{
super(par1World);
isImmuneToFire = false;
}
public int func_82193_c(Entity par1Entity) //the amount of damage
{
return 4;
}
protected void fall(float par1)
{}
public int getMaxHealth() // Mob health
{
return 1000;
}
protected int getDropItemId()
{
return 0;
}
protected boolean canDespawn()
{
return false;
}
public boolean interact(EntityPlayer entityplayer)
{
if (riddenByEntity == null || riddenByEntity == entityplayer)
{
entityplayer.mountEntity(this);
return true;
}
else
{
return false;
}
}
protected boolean isMovementCeased()
{
return stationary;
}
public void moveEntity(double d, double d1, double d2)
{
if (riddenByEntity != null)
{
this.prevRotationYaw = this.rotationYaw = this.riddenByEntity.rotationYaw;
this.rotationPitch = this.riddenByEntity.rotationPitch * 0.5F;
this.setRotation(this.rotationYaw, this.rotationPitch);
this.rotationYawHead = this.renderYawOffset = this.rotationYaw;
stationary = true;
motionX += riddenByEntity.motionX * 10; // * 0.20000000000000001D;
motionZ += riddenByEntity.motionZ * 10; // * 0.20000000000000001D;
if (isCollidedHorizontally)
{
isJumping = true;
}
else
{
isJumping = false;
}
super.moveEntity(motionX, motionY, motionZ);
}
else
{
stationary = false;
super.moveEntity(d, d1, d2);
}
}
public void onUpdate()
{
super.onUpdate();
if (riddenByEntity != null) //check if there is a rider
{
//currentTarget = this;
this.randomYawVelocity = 0; //try not to let the horse control where to look.
this.rotationYaw = riddenByEntity.rotationYaw;
}
}
protected boolean isAIEnabled() //Allow your AI task to work?
{
return true;
}
}
P.S. I am using ModLoader
You need to add client-server-sync by using message-handling. I recommend using this tutorial: http://www.minecraftforge.net/forum/index.php/topic,20138.0.html