Java 2D Game Key Input (Best Practice?) - java

I'm brand new to game development and have chosen to start working on a 2D top-down scroller game. I'm using the Slick2D library for this game.
My question is about best practices for taking multiple direction input for sprite movement (UP + RIGHT = Diagonal)
Currently, I have a rather ugly looking if/elseif chain to read in the input from the keyboard that is then checked in the 'Mob' class to determine how the sprite will move. The current setup works just fine, but my question is if there is another, better way of going about taking multiple inputs for diagonals (or any combo of keys, for that matter)
Here is the main class's update method that reads the input (blooper is the instance of 'Mob'):
public void update(GameContainer container, StateBasedGame arg1, int delta) throws SlickException {
Input input = container.getInput();
if(input.isKeyDown(Input.KEY_RIGHT)) { //RIGHT
if(input.isKeyDown(Input.KEY_UP)){ //RIGHT + UP
blooper.direction = 2;
} else if(input.isKeyDown(Input.KEY_DOWN)){ //RIGHT + DOWN
blooper.direction = 3;
}
else {
blooper.direction = 1;
}
} else if(input.isKeyDown(Input.KEY_LEFT)){ //LEFT
if(input.isKeyDown(Input.KEY_UP)){ //LEFT + UP
blooper.direction = 5;
} else if(input.isKeyDown(Input.KEY_DOWN)){ //LEFT + DOWN
blooper.direction = 6;
} else{
blooper.direction = 4;
}
} else if(input.isKeyDown(Input.KEY_UP)){ //UP
if(input.isKeyDown(Input.KEY_RIGHT)){ //UP + RIGHT
blooper.direction = 8;
} else if(input.isKeyDown(Input.KEY_LEFT)){ //UP + LEFT
blooper.direction = 9;
} else{
blooper.direction = 7;
}
} else if(input.isKeyDown(Input.KEY_DOWN)){ //DOWN
if(input.isKeyDown(Input.KEY_RIGHT)){ //DOWN + RIGHT
blooper.direction = 11;
} else if(input.isKeyDown(Input.KEY_LEFT)){ //DOWN + LEFT
blooper.direction = 12;
} else{
blooper.direction = 10;
}
} else{
blooper.direction = -1;
}
blooper.update(delta);
}
And here is how that input is processed in the Mob class:
public class Mob {
private final int RIGHT = 1;
private final int RIGHTUP = 2;
private final int RIGHTDOWN = 3;
private final int LEFT = 4;
private final int LEFTUP = 5;
private final int LEFTDOWN = 6;
private final int UP = 7;
private final int UPRIGHT = 8;
private final int UPLEFT = 9;
private final int DOWN = 10;
private final int DOWNRIGHT = 11;
private final int DOWNLEFT = 12;
private final int IDLE = -1;
int direction = IDLE;
int x, y;
Image sprite;
public Mob() throws SlickException{
x = 20;
y = 20;
sprite = new Image("res/blooper.png");
}
public void update(int delta){
move();
}
public void draw(){
sprite.draw(x, y);
}
public void move(){
switch(direction){
case RIGHT:
x += 1;
break;
case RIGHTUP:
x += 1;
y -= 1;
break;
case RIGHTDOWN:
x += 1;
y += 1;
break;
case LEFT:
x -= 1;
break;
case LEFTUP:
x -= 1;
y -= 1;
break;
case LEFTDOWN:
x -= 1;
y += 1;
break;
case UP:
y -= 1;
break;
case UPRIGHT:
y -= 1;
x += 1;
break;
case UPLEFT:
y -= 1;
x -= 1;
break;
case DOWN:
y += 1;
break;
case DOWNRIGHT:
y += 1;
x += 1;
break;
case DOWNLEFT:
y += 1;
x -= 1;
break;
case IDLE:
//nothing
}
}
}
Like I said...this works, but doesn't seem like the best way to go about it. Any tips?

Make left/right and up/down movement independent. You (or the framework - I'm unfamiliar with it) seems to work with x/y coordinates, which are mathematically independent.
Thus make one function that treats the up/down movement, and one function that treats the left/right movement, and you can get rid of their 'combinations'. Is there a reason why the directions are positive integers? Try making left = -1, right = 1, and no x-direction movement 0, and then do the same for y. That should hopefully make it more intuitive.
Happy coding

Make a blooper.direction a bitwise, like:
blooper.direction=0;
if(input.isKeyDown(Input.KEY_RIGHT)) blooper.direction|=1;
if(input.isKeyDown(Input.KEY_LEFT)) blooper.direction|=2;
if(input.isKeyDown(Input.KEY_UP)) blooper.direction|=4;
if(input.isKeyDown(Input.KEY_DOWN)) blooper.direction|=8;
then in move do the move, like:
if ((blooper.direction&1)!=0) x+=1;
if ((blooper.direction&2)!=0) x-=1;
if ((blooper.direction&4)!=0) y-=1;
if ((blooper.direction&8)!=0) y+=1;

Related

libGDX why does my fori loop not update Sprite position properly?

So I created an "UpdateShopPosition" method, that should place Sprites in correct spots on the screen. However when I launch it in the render method, it seems that every Sprite shares the exact same position, not only that but the position keeps moving right and down.
I want MyX and MyY to have a different value for each shopList.get(i) . Is there a problem with the loop or is it because I placed this method in the render() section?
public class ObjectCreator {
public static int rowsX = 4;
public static int rowsY = 5;
public static void UpdateShopPosition(List<Sprite> spriteList){
for (int i = 0; i < spriteList.size(); i++) {
float myX = playerSprite.getX() + ((i + 4) * 100);
if (i > 0){
myX+= i*3;
}
float myY = playerSprite.getY() + 410;
if (i >= rowsX && i < rowsX*2 ) {
myX = myX - 400;
myY = myY - 101;
}
else if (i >= rowsX*2 && i < rowsX*3){
myX = myX - 800;
myY = myY - 202;
}
else if (i >= rowsX*3 && i < rowsX*4){
myX = myX - 1200;
myY = myY - 303;
}
else if (i >= rowsX*4 && i < rowsX*5){
myX = myX - 1600;
myY = myY - 404;
}
else if (i >= rowsX*5 && i < rowsX*6){
myX = myX - 2000;
myY = myY - 505;
}
spriteList.get(i).setPosition(myX, myY);
}
}
public static void CreateUsable(Usables name, Sprite sprite){
GameApp.shopList.add(sprite);
name.setImage(GameApp.shopList.get(0));
}
}
for (int i = 0; i < usableList.size(); i++) {
usableList.get(i).draw(batch);
usableList.get(i).setPosition(playerSprite.getX() - 1200, playerSprite.getY() + 300);
usableList.get(i).setSize(60,60);
// the next (i) should be placed on the next grid, so a little bit to the right
}
I tried to create a method that keeps placing items sprites respectively to my player sprite, I want these sprites to have the same position no matter where I move on the map

Array Index Error while swiping on the game

I have this match 3 game, but if I swiping outside the game board this error showed to me and crush the app:
java.lang.ArrayIndexOutOfBoundsException: length=9; index=11
I tried to fix this error but I don't know how to make it work when I touch outside the game board, is that way to make touch only inside the game board game or just a way to ignore this error when it's happing?
public void swap()
{
if(swapIndex > 0)
{
switch (direction){
case "right":
board[poseI][poseJ + 1].poseX -= cellWidth/ 8;
board[poseI][poseJ].poseX += cellWidth/ 8;
break;
case "left":
board[poseI][poseJ - 1].poseX += cellWidth/ 8;
board[poseI][poseJ].poseX -= cellWidth/ 8;
break;
case "up":
board[poseI - 1][poseJ].poseY += cellWidth/ 8;
board[poseI][poseJ].poseY -= cellWidth/ 8;
break;
case "down":
board[poseI + 1][poseJ].poseY -= cellWidth/ 8;
board[poseI][poseJ].poseY += cellWidth/ 8;
break;
}
swapIndex--;
}else {
Candies candies;
candies = board[poseI][poseJ];
board[poseI][poseJ] = board[newPoseI][newPoseJ];
board[newPoseI][newPoseJ] = candies;
board[poseI][poseJ].poseX = (int) (poseJ * cellWidth + drawX);
board[poseI][poseJ].poseY = (int) (poseI * cellWidth + drawY);
board[newPoseI][newPoseJ].poseX = (int) (newPoseJ * cellWidth + drawX);
board[newPoseI][newPoseJ].poseY = (int) (newPoseI * cellWidth + drawY);
swapIndex = 8;
if (gameState == GameState.swapping)
{
gameState = GameState.checkSwapping;
// count user moves
increaseUserMove();
}else {
gameState = GameState.nothing;
}
}
}
#Override
public void draw(Canvas canvas) {
super.draw(canvas);
canvas.drawColor(Color.WHITE); // Background Color
// Create Game top Background
canvas.drawBitmap(spriteSheet.topBG , 0, - cellWidth * 2, null);
// Create Game bottom Background
canvas.drawBitmap(spriteSheet.bottomBG , 0, drawY + cellWidth * 9, null);
// Create Game middle Background
canvas.drawBitmap(spriteSheet.bg_middle , 0, drawY, null);
// Create Game Cells
Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);
p.setColor(Color.BLACK); // cells color
for (int i = 0; i < 10; i++)
{
for (int j = 0; j < 9; j++)
{
canvas.drawLine(0, drawY + (i * cellWidth), cellWidth * 10, drawY + (i * cellWidth), p);
canvas.drawLine(j * cellWidth , drawY, j * cellWidth, drawY + cellWidth * 9, p);
}
}
for (Candies[] candie: board)
{
for (Candies candies: candie)
{
candies.drawCandies(canvas, spriteSheet);
}
}
for(int i = 0; i < board.length; i++)
{
for(int j = 0; j < board[0].length; j++)
{
candies.drawCandies(canvas, spriteSheet);
}
}
//canvas.drawBitmap(spriteSheet.candiesBMP, candies.poseX, candies.poseY, null);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
final int action = event.getAction();
switch (action)
{
case MotionEvent.ACTION_DOWN:
oldX = event.getX();
oldY = event.getY();
poseI = (int) (oldY - drawY) / cellWidth;
poseJ = (int) (oldX - drawX) / cellWidth;
move = true;
break;
case MotionEvent.ACTION_MOVE:
if(gameState == GameState.nothing)
{
float newX = event.getX();
float newY = event.getY();
float deltaX = Math.abs(newX - oldX);
float deltaY = Math.abs(newY - oldY);
if(move && deltaX > 30 || deltaY > 30)
{
// check how many pixels our fingers moved
// if we moved our finger more than 30 pixels we start checking in which direction
move = false;
if (Math.abs(oldX- newX) > Math.abs(oldY - newY))
{
// if the first X touch - the end of the X touch is bigger than the
// first Y touch - the end of the touch Y so the direction is in the X direction
// now we will check which is bigger the oldX or newX for know if its left or right
if(newX > oldX)
{
direction = "right";
newPoseJ = (poseJ + 1);
}else {
direction = "left";
newPoseJ = (poseJ - 1);
}
newPoseI = poseI;
}
if (Math.abs(oldY - newY) > Math.abs(oldX - newX))
{
if(newY > oldY)
{
direction = "down";
newPoseI = (poseI + 1);
}else {
direction = "up";
newPoseI = (poseI - 1);
}
newPoseJ = poseJ;
}
gameState = GameState.swapping;
}
}
break;
}
return true;
}

Game rope swing physics acting weird

I'm trying to implement rope swinging in my platformer, following this tutorial. Instead of swing on the rope, the player looks like he's sliding down a slope: he moves very slowly towards the bottom.
This is what it looks like now:
Instead, I want the player to have more natural movement, like he's really swinging on the rope.
This is the update method from my player class:
#Override
public final void update() {
setPosition(getNextPosition());
if (direction == Direction.LEFT && moving) {
getVelocity().x = -WALK_SPEED;
} else if (getVelocity().x < 0) {
getVelocity().x *= COEF_FRIC;
}
if (direction == Direction.RIGHT && moving) {
getVelocity().x = WALK_SPEED;
} else if (getVelocity().x > 0) {
getVelocity().x *= COEF_FRIC;
}
checkAsleep();
animations.update();
if (ropePoint != null) {
//getCenter() returns the center position of the player
if (getCenter().toPoint().distanceSq(ropePoint) > ROPE_LENGTH * ROPE_LENGTH) {
final Vec2D oldPosition = getCenter();
final Vec2D oldVelocity = getVelocity();
final Vec2D ropePosition = new Vec2D(ropePoint);
setCenter((oldPosition.subtract(ropePosition).unit().multiply(ROPE_LENGTH).add(ropePosition)));
setVelocity(oldPosition.subtract(getCenter()).unit().multiply(oldVelocity));
}
}
}
This is my implementation of getNextPosition(), if it is needed.
public final Vec2D getNextPosition() {
final int currCol = (int) (getX() / Tile.SIZE);
final int currRow = (int) (getY() / Tile.SIZE);
final double destX = getX() + moveData.velocity.x;
final double destY = getY() + moveData.velocity.y;
double tempX = getX();
double tempY = getY();
Corners solidCorners = getCornersAreSolid(getX(), destY);
boolean topLeft = solidCorners.topLeft;
boolean topRight = solidCorners.topRight;
boolean bottomLeft = solidCorners.bottomLeft;
boolean bottomRight = solidCorners.bottomRight;
framesSinceLastTopCollision += 1;
framesSinceLastBottomCollision += 1;
framesSinceLastLeftCollision += 1;
framesSinceLastRightCollision += 1;
if (moveData.velocity.y < 0) {
if (topLeft || topRight) {
moveData.velocity.y = 0;
tempY = currRow * Tile.SIZE;
framesSinceLastTopCollision = 0;
} else {
tempY += moveData.velocity.y;
}
} else if (moveData.velocity.y > 0) {
if (bottomLeft || bottomRight) {
moveData.velocity.y = 0;
tempY = (currRow + 1) * Tile.SIZE - moveData.collisionBox.getHeight() % Tile.SIZE - 1;
framesSinceLastBottomCollision = 0;
} else {
tempY += moveData.velocity.y;
}
}
solidCorners = getCornersAreSolid(destX, getY());
topLeft = solidCorners.topLeft;
topRight = solidCorners.topRight;
bottomLeft = solidCorners.bottomLeft;
bottomRight = solidCorners.bottomRight;
if (moveData.velocity.x < 0) {
if (topLeft || bottomLeft) {
moveData.velocity.x = 0;
tempX = currCol * Tile.SIZE;
framesSinceLastLeftCollision = 0;
} else {
tempX += moveData.velocity.x;
}
}
if (moveData.velocity.x > 0) {
if (topRight || bottomRight) {
moveData.velocity.x = 0;
tempX = (currCol + 1) * Tile.SIZE - moveData.collisionBox.getWidth() % Tile.SIZE - 1;
framesSinceLastRightCollision = 0;
} else {
tempX += moveData.velocity.x;
}
}
return new Vec2D(tempX, tempY);
}
What should I change in this code to get natural movement?
My first guess is that the problem lies in that first if statement:
if (direction == Direction.LEFT && moving) {
getVelocity().x = -WALK_SPEED;
} else if (getVelocity().x < 0) {
getVelocity().x *= COEF_FRIC;
}
If the first thing is true, you're going to constantly be setting the velocity to walking pace, which doesn't make sense when your guy is swinging on a rope. He should be speeding up as he goes down and slowing down on the way up.
If the first thing is false, then since he is going left, you're definitely going to go into the else if statement, and he'll be slowed down by friction. I don't see where you set that, but it seems to still be the friction he has on the ground, which would seem to explain why he's all stuttery and looks more like he's sliding than falling.
You might want to add different states instead of just "moving", (perhaps jumping, swinging, walking, running, stopped) and vary how he behaves while doing each of those things.

Connecting a maze/grid's walls so all are interconnected

I have a 2d grid that I'm trying to create links between all walls.
The grid is constructed like so:
grid = new State[8][8];
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
grid[i][j] = State.blank;
}
}
I have a robot that should be able to pass through the walls to the opposite side like on a game of snake.
So for example if the robot is facing NORTH and is in position x[0]y[1] then it should connect to x[7]y[1].
The robot should also be able to read whats in the three blocks in front of it, one to the left, one to the right and one directly infront.
# x = empty space
# R = robot
# S = spaces robots sensors pick up
If it were facing north this is what the robot would pick up:
[S][S][S][x][x][x][x][x]
[x][R][x][x][x][x][x][x]
[x][x][x][x][x][x][x][x]
[x][x][x][x][x][x][x][x]
[x][x][x][x][x][x][x][x]
[x][x][x][x][x][x][x][x]
[x][x][x][x][x][x][x][x]
[x][x][x][x][x][x][x][x]
Like wise if the robot was facing east this is what it would pick up:
[x][x][S][x][x][x][x][x]
[x][R][S][x][x][x][x][x]
[x][x][S][x][x][x][x][x]
[x][x][x][x][x][x][x][x]
[x][x][x][x][x][x][x][x]
[x][x][x][x][x][x][x][x]
[x][x][x][x][x][x][x][x]
[x][x][x][x][x][x][x][x]
The problem I'm having is finding the right algorithm to make sure that the robot can not only pass through walls but also read sensors through the walls.
If the robot was in the top left corner and facing NORTH then it would read through the wall like so:
[R][x][x][x][x][x][x][x]
[x][x][x][x][x][x][x][x]
[x][x][x][x][x][x][x][x]
[x][x][x][x][x][x][x][x]
[x][x][x][x][x][x][x][x]
[x][x][x][x][x][x][x][x]
[x][x][x][x][x][x][x][x]
[S][S][x][x][x][x][x][S]
As you can imagine I've already tried doing length chunks of IF statements but there is too many possiblities to cover them all without going insane!
I've also wrote down the changes to X & Y on paper when placed in certain circumstances but I can't really see any pattern that hints toward an algorithm.
Any help would be appreciated!
public class Robot {
public int x;
public int y;
public Robot(int x,int y) {
this.x = x;
this.y = y;
}
public void move(int direction, int steps) {
switch(direction) {
case 1: //north
int temp1 = (x-steps)%8;
x = temp1<0?(temp1+8):temp1;
break;
case 2: //south
x = (x+steps)%8;
break;
case 3: //west
int temp3 = (y-steps)%8;
y = temp3<0?(temp3+8):temp3;
break;
case 4: //east
y = (y+steps)%8;
break;
default:
System.out.println("I'm not smart enough to handle the direciton provided!");
}
}
public static void main(String[] args) {
int[][] grid = new int[8][8];
Robot robot = new Robot(0,0);
System.out.println("I'm starting at (0,0).");
robot.move(3, 9);
System.out.println("I'm moving west by 9 steps.");
System.out.println("I've arrived at ("+robot.x+","+robot.y+").");
}
}
Hope the code above gives an idea. I've tested it. Feel free to have a try. The computation of the three blocks in front of the robot is similar. You can figure it out on your own.
Use an iterator like x = (x + 1) % array.length
(or x = (x - 1) % array.length)
I'll try to break it down into different parts, hopefully that will help you.
So, you have a 8x8 grid, represented by X and Y coordinates, with (0,0) being the top left corner and (7,7) being the bottom right corner.
Your algorithm will look like this:
walking through walls:
N -> x = x, y = (y==0)?7:y-1
S -> x = x, y = (y==7)?0:y+1
E -> x = (x==7)?0:x+1, y = y
W -> x = (x==0)?7:x-1, y = y
Look ahead
N -> LH1 = x=x, y=y-1
LH2 = x=x-1, y=y-1
LH3 = x=x+1, y=y-1
S -> LH1 = x=x, y=y+1
LH2 = x=x-1, y=y+1
LH3 = x=x+1, y=y+1
E -> LH1 = x=x+1, y=y
LH2 = x=x+1, y=y-1
LH3 = x=x+1, y=y+1
W -> LH1 = x=x-1, y=y
LH2 = x=x-1, y=y-1
LH3 = x=x-1, y=y+1
Now if I convert this algorithm into java methods, they will look like this:
public int getNextX (int currentX, String direction)
{
if ("N".equals (direction) || "S".equals (direction))
{
return currentX;
}
else if ("E".equals (direction))
{
return ((currentX==7) ? 0 : currentX + 1);
}
else if ("W".equals (direction))
{
return ((currentX==0) ? 7 : currentX - 1);
}
}
public int getNextY (int currentY, String direction)
{
if ("E".equals (direction) || "W".equals (direction))
{
return currentY;
}
else if ("S".equals (direction))
{
return ((currentY==7) ? 0 : currentY + 1);
}
else if ("N".equals (direction))
{
return ((currentY==0) ? 7 : currentY - 1);
}
}
public ArrayList getLookAheads (int currentX, int currentY, String direction)
{
ArrayList lookAheads = new ArrayList ();
int x[3];
int y[3];
if ("N".equals (direction))
{
// LH1
x[0] = currentX;
y[0] = currentY - 1;
// LH2
x[1] = currentX - 1;
y[1] = currentY - 1;
// LH3
x[2] = currentX + 1;
y[2] = currentY - 1;
}
else if ("S".equals (direction))
{
// LH1
x[0] = currentX;
y[0] = currentY + 1;
// LH2
x[1] = currentX - 1;
y[1] = currentY + 1;
// LH3
x[2] = currentX + 1;
y[2] = currentY + 1;
}
else if ("E".equals (direction))
{
// LH1
x[0] = currentX + 1;
y[0] = currentY;
// LH2
x[1] = currentX + 1;
y[1] = currentY - 1;
// LH3
x[2] = currentX + 1;
y[2] = currentY + 1;
}
else if ("E".equals (direction))
{
// LH1
x[0] = currentX - 1;
y[0] = currentY;
// LH2
x[1] = currentX - 1;
y[1] = currentY - 1;
// LH3
x[2] = currentX - 1;
y[2] = currentY + 1;
}
for (int i=0;i < 3;i++)
{
HashMap h = new HashMap ();
h.put ("X", new Integer (getNextX (x[i], direction)));
h.put ("Y", new Integer (getNextY (y[i], direction)));
lookAheads.add (h);
}
return lookAheads;
}
I didn't test the syntax of the methods (I just wrote them in a notepad), so pardon me if there are some compilation errors, but you should be able to figure that out.
Hope that helps.
This can be solved quite simply, by using the modulus operator (%). Modulo cycles values around under a certain upper bound. So if the robot's x value steps over the maximum boundary, it simply jumps back to 0. This way the robot can move through one wall on the right, and the x co-ordinate is reset back to 0 and they will appear on the left side of the stage.

Issue with Random numbers in Java

I wrote a piece of code to move an object in a Random Direction in Java. There are two functions.
FindRandomDirection - Gets a random direction from 8 possible directions (Directions are represented by the numbers 1,2,3,4,6,7,8,9 in a numpad). Check is done to see if the object is near any of the borders. If so the object will move in a direction away from the border.
MoveObject - Changes the (X, Y) co-ordinates of the object by moving by a constant STEP.
But what ever values I give for X, Y; after repeating the process several times (700 or more), the values of X, Y becomes {X: 20-50} and {Y: 450-465}.
I.e.
Case 1: (x:35,y:65) becomes (x:35, y:465)
Case 2: (x:30, y:455) becomes (x:30, y:460)
Case 3: (x:435, y:65) becomes (x:25, y:460)
Case 4: (x:430, y:465) becomes (x:40, y:460)
I would like to why the after several iterations the x, y points converge towards these values even though I generate the numbers at random.
Below is the code for the same.
import java.io.*;
public class bug
{
//public static int x = 35;
//public static int y = 60;
//public static int x = 35;
//public static int y = 460;
//public static int x = 435;
//public static int y = 60;
public static int x = 435;
public static int y = 460;
public static final int NORTH = 8;
public static final int EAST = 6;
public static final int WEST = 4;
public static final int SOUTH = 2;
public static final int NORTHEAST = 9;
public static final int NORTHWEST = 7;
public static final int SOUTHWEST = 1;
public static final int SOUTHEAST = 3;
public static final int STEP = 5;
//Function to move the object in a specified direction.
public static void moveObject(int direction)
{
double nX = 0, nY=0;
switch(direction)
{
case NORTH:
nY = y- STEP;
nX = x;
break;
case SOUTH:
nY = y+ STEP;
nX = x;
break;
case EAST:
nY = y;
nX = x + STEP;
break;
case WEST:
nY = y;
nX = x- STEP;
break;
case NORTHEAST:
nX = x + STEP;
nY = y- STEP;
break;
case NORTHWEST:
nX = x- STEP;
nY = y- STEP;
break;
case SOUTHEAST:
nX = x + STEP;
nY = y+ STEP;
break;
case SOUTHWEST:
nX = x- STEP;
nY = y+ STEP;
break;
}
x = (int) nX;
y = (int) nY;
System.out.println("Direction: "+direction+"; X: "+x+"; Y: "+y);
}
//Function to move the object in a random direction
//Also if wall(Border) is present the object should move in proper direction
public static int findRandomDirection(int objObjectX, int objObjectY)
{
int[] move = {1,2,3,4,0,6,7,8,9};
int randDir=0;
//Generate a random direction to move. Generate new direction if the objected can not be moved in a direction
do
{
java.util.Random randomGenerator = new java.util.Random();
randDir = randomGenerator.nextInt(8);
//If the object lies near East Border, it can not move in that direction
if(objObjectX <= 25)
{
move[0] = 0;
move[3] = 0;
move[6] = 0;
}
//If the object lies near West Border, it can not move in that direction
if(objObjectX >= 465)
{
move[2] = 0;
move[5] = 0;
move[8] = 0;
}
//If the object lies near North Border, it can not move in that direction
if(objObjectY <= 25)
{
move[6] = 0;
move[7] = 0;
move[8] = 0;
}
//If the object lies near South Border, it can not move in that direction
if(objObjectY >= 465)
{
move[0] = 0;
move[1] = 0;
move[2] = 0;
}
} while(move[randDir]==0);
return move[randDir];
}
public static void main(String[] args)
{
for(int i = 0; i<1000;i++)
{
int dir=findRandomDirection(x,y);
moveObject(dir);
}
}
}
So over time, my object moves towards the lower left corner of the board. Kindly help me in finding the bug.
Since you are using nextInt(8), the value returned will always be between 0 and 7 (inclusive). Since 8 is never returned, movement is biased towards the opposite direction. You probably want to use nextInt(9), to return a value between 0 and 8 (inclusive).
edit: To clarify, since "8" is never chosen as your random direction, and moves[8]==9, the object never moves in the NORTHEAST direction, which means over time it will tend to travel SOUTHWEST.
Also, as #Joey said above, you shouldn't reinitialize the Random object every time, but that isn't what was causing the drifting behavior.
When you select a direction, you select a value between 0 and 7 inclusive. These values (in your mapping) correspond to:
public static final int SOUTHWEST = 1;
public static final int SOUTH = 2;
public static final int SOUTHEAST = 3;
public static final int WEST = 4;
public static final int EAST = 6;
public static final int NORTHWEST = 7;
public static final int NORTH = 8;
But note that this will never be chosen:
public static final int NORTHEAST = 9;
So, it's not surprising to me that your code seems biased toward the southeast...
The nextInt(n) method return numbers from zero, inclusive, to n, exclusive. Since you are passing the value 8, the results are from the set of 8 values, 0–7. Thus, the ninth element of the array, which represents the northeast direction, is never selected.
This bias against the northeast results in an eventual migration to the southwest.

Categories