Moving an object to another on a random path - java

I have a program which creates multiple randomly placed objects(balls) at the beginning, now im trying to move the player ball towards the closest object automatically until their centres are the same. I have determined the distance of the closest object stored in an array called distance with index of 'closest', and set the speed as variable delta initialised somewhere else, how do i get the direction right? Right now
It moves just diagonally but not towards the closest ball
coordinatex[closest] and coordinatey[closest] are the x and y coordinates of the closest object.
playerObject.getX and playerObjectgetY gives me the coordinates of the player onject
public void move(int delta) {
for(int i=0; i<distance[closest]; i++) {
if (x<coordinatex[closest] && y<coordinatey[closest]) {
playerObject.setX(playerObject.getX() + 0.1*delta);
playerObject.setY(playerObject.getY() + 0.1*delta);
} else if(x>coordinatex[closest] && y>coordinatey[closest]) {
playerObject.setX(playerObject.getX() - 0.1*delta);
playerObject.setY(playerObject.getY() - 0.1*delta);
} else if(x>coordinatex[closest] && y<coordinatey[closest]) {
playerObject.setX(playerObject.getX() - 0.1*delta);
playerObject.setY(playerObject.getY() + 0.1*delta);
} else if (x<coordinatex[closest] && y>coordinatey[closest]) {
playerObject.setX(playerObject.getX() + 0.1*delta);
playerObject.setY(playerObject.getY() - 0.1*delta);
}
}
}

Something very similar to this:
angle=atan2(ClosestBally-player_y,closestBallx-player_x);
dxperframe = cos(angle);
dyperframe = sin(-angle);

I see your handlers for the four semi-cardinal (diagonal) directions, but not the four cardinal directions. In this game, for example, enemies approach the player in a step-wise manner using the move(int row, int col) method, shown here, from any of eight directions.

Related

Sudoku backtracking algorithm (Java)

I've created a Sudoku solver that will solve a Sudoku as a human might- by checking possibilities + definite values in squares corresponding to the square being checked.
(Source: http://pastebin.com/KVrXUDBF)
However, I would like to create a random Sudoku generator (from a blank grid), and so have decided to use a backtracking algorithm. I understand the concept of backtracking, but am confused about one thing:
How do I know which previous node to return to (and change) once I know a certain solution is not allowed?
Should I simply return to the previous node and cycle through all possibilities? (And then if this yields no correct answers, return to the value before, etc.). This seems like a viable method, but also quite inefficient. Is this the correct way of implementing a backtracking method or is there a better way to go about it?
Thanks in advance.
More can be found about backtracking here: http://en.wikipedia.org/wiki/Backtracking
Sudoku Puzzle can be reduced to graph coloring problem which can be solved using simple backtracking like assigning colors to node (1-9) till the there is no violation that all directly connected nodes have no same color.
Constructing Graph from Sudoku : -
There is an direct edge between two grid points if they are in same
row or column or square.
Backtracking :-
Assign one color (1-9) to node
Check if there is no other directly connected node with same color
If valid color move to next node.
else change the color and recheck.
If all color exhausted backtrack to previous node.
Do recursion till all nodes are color.
Once You are done with it you can start removing numbers from the grid at random till you think the problem is unsolvable if any more numbers are removed.
A simple way to generate random Sudoku is that
1) generate a random completing Sudoku, that is, generate random Sudoku no square is blank.
2) Remove numbers from squares of 1).
3) Solve Sudoku of 2). If there are many solutions, then add a number removed at 2).
If there are still many solutions, then repeat 3).
1) sample source code:
public int[][] generateRandomCompleteSudoku() {
int[][] sudoku = new int[10];
for(int i = 1; i <= 9; i++) {
sudoku[i] = new int[10];
Arrays.fill(sudoku[i], 0);
}
generateRandomCompleteSudoku(sudoku, 1, 1);
return sudoku;
}
private boolean generateRandomCompleteSudoku(int[][] sudoku, int x, int y) {
if(x > 9) {
x = 1;
y++;
}
//sudoku of the argument is completing sudoku.
//so return true
if(y > 9) {
return true;
}
// enumerate the possible numbers of the pos(x,y).
List<Integer> possibleNumbers = new ArrayList<Integer>();
for(int i = 1; i <= 9; i++) {
boolean possible = true;
//check i is a possible number.
//check there isn't i in the raw of y .
for(int j = 1; j <= x - 1; j++) {
if(sudoku[j][y] == i) {
possible = false;
break;
}
}
//check there isn't i in the column of x(omitted).
//check there isn't i in the group of x,y(omitted).
if(possible) {
possibleNumbers.add(i);
}
}
//sudoku is wrong so return false.(There is no solution of sudoku)
if(possibleNumbers.size() <= 0) {
return false;
}
Collections.shuffle(possibleNumbers);// This gives sudoku randomness.
for(Integer possibleNumber : possibleNumbers) {
sudoku[x][y] = possibleNumber;
// a sudoku is generated, so return true
if(generateRandomCompleteSudoku(sudoku, x + 1, y)) {
return true;
}
}
// No sudoku is generated, so return false
return false;
}
For a backtracking solution, the first step is to define the state. So for this problem, I think the most straightforward way is (x,y, blank , num) with x , y is the position of the current state, blank is the number of blank position left, and num is the value you want to fill in that position (from 0 to 9 and 0 means blank).
And the return type should be boolean, which determine whether the move is valid or not (which means is there any valid solution for this move).
So, the state transition is column by column, row by row: x, y to x , (y + 1) or x , y to (x + 1), 0.
Similarly, the blank will be from a -> a - 1-> ... 0.
We have a draft solution here:
public boolean move(int x, int y, int blank, int num, int[][]sudoku){
sudoku[x][y] = num;
//checking condition and return if x,y is the last position, code omitted
if(y == sudoku[x].length){
x++;
y = 0;
}else{
y++;
}
for(int i = 1; i < 10; i++){
if(move(x,y,blank,i,sudoku){//Backtrack here
return true;
}
}
if(blank > 0){
if(move(x,y,blank - 1, 0, sudoku){//Backtrack here
return true;
}
}
return false;
}
So when ever there is a false return from the current state, it will backtrack to the last state , and the last state will continue to check for the next num until it find a correct solution (or return false).

Java game - run code sequentially in the game loop

I am creating a Java game within which the user can enter the commands of up, left, right, or down to move the character in that location for a certain amount of pixels. Within the Player class I am receiveing the commands from the user in an ArrayList of JTextFields after they have pressed the start button. I then use a for loop to go through all the inputs from the user and create x and y targets within a multi-dimensional array for the x and y amount of distance that the player needs to move. Finally I have a function called updatePosition() which is called within the main game loop. Within this function I loop through the multi-dimensional array of targets and have an if statement to check if the target has been reached or not. However when this method is executed and the user has input the commands of up and right for example, then the character moves diagonally up. I want a way which will move the character in the direction that the user has specified, executing them one after another.
Here is the code:
moveSpeed = 1;
private double moveAmt = 20;
private Double[][] targetCoordinates = null;
private ArrayList<JTextField> userInputTextFields = new ArrayList<JTextField>();
With method below I acquire the ArrayList of JTextFields within which the user has entered the commands and store it in a local ArrayList. I also instatiate an Array in the size of the amount of JTextFields that the user has entered the commands in. This array will be used to store the x and y targets for the character. I then lastly call the moveChar(); method which will set the target x and y.
public void getInputText(ArrayList<JTextField> textFields){
this.userInputTextFields = textFields;
targetCoordinates = new Double[userInputTextFields.size()][2];
moveChar();
}
This method will check if the commands that the user has enetered and set the x and y targets within the targetCoordinates array.
private void moveChar(){
for (int i = 0; i < userInputTextFields.size(); i++) {
if(userInputTextFields.get(i).getText().equals("up")){
targetCoordinates[i][0] = x;
targetCoordinates[i][1] = y - moveAmt;
} else if(userInputTextFields.get(i).getText().equals("down")){
targetCoordinates[i][0] = x;
targetCoordinates[i][1] = y + moveAmt;
} else if(userInputTextFields.get(i).getText().equals("left")){
targetCoordinates[i][0] = x - moveAmt;
targetCoordinates[i][1] = y;
} else if(userInputTextFields.get(i).getText().equals("right")){
targetCoordinates[i][0] = x + moveAmt;
targetCoordinates[i][1] = y;
}
}
}
Finally, this is the method which gets called within the main game loop. It goes through the targetCoordinates array and checks if the targets have been met. If not then incriment or decrement the character's x and y position accordingly.
public void updatePosition(){
if(targetCoordinates != null){
for (int i = 0; i < targetCoordinates.length; i++) {
if(y >= targetCoordinates[i][1]) {
moveCharacter(x, y - moveSpeed);
} else if(y < targetCoordinates[i][1]) {
moveCharacter(x, y + moveSpeed);
} else if(x > targetCoordinates[i][0]) {
moveCharacter(x - moveSpeed, y);
} else if(x <= targetCoordinates[i][0]) {
moveCharacter(x + moveSpeed, y);
}
}
}
}
At present you use all the available commands to create a single target position and use that to direct your motion (or possibly move towards all target positions simultaneously).
Instead you want a "hopper" of commands that survive beyond a specific game loop and a new command is only fetched after the current one is completed. New commands go in the top and out the bottom to be excecuted.
This would most likely look something like this
public class Player {
//holding commands as strings is a little bug prone, consider creating a custom class or enum
ArrayList<String> commandsHopper=new ArrayList<String>();
//replace with some sort of Vector2i as improvement
double[] targetCoOrdinates=new double[2];
public void addCommand(String command){
commandsHopper.add(command); //commands added at the top of arraylist
}
public void update(double timeSlice){
//Called once, every game loop
if (isAtTarget()){
getNextTarget();
}
moveTowardsTarget(timeSlice);
}
public void getNextTarget(){
if (commandsHopper.isEmpty()==false){
//commands used from bottom of the arraylist
targetCoOrdinates=determineTargetFromCommand(commandsHopper.get(0));
commandsHopper.remove(0); //inefficient with arraylist, consider other collections
}
}
}

Java Click on a object and output a message

Im currently making a game in my spare time to improve my java but im having trouble with one of the things i want to do. Ive made the game so i can put a item into a certain position. In this example its a tower in a certain location. When this tower is placed in this location and i click on the tower i want it to output a message. However ive tried many ways to do this and i havent been able to find a solution. The code i have for this is:
public static void click(int X, int Y){
System.out.println("X. " + X + " Y. " + Y);
if(Screen.room.block[X][Y].airID == Value.tower){
System.out.println("Tower clicked");
}
}
When the tower is placed in a location the code i use for this is:
if(holdsItem){
for(int y=0; y<Screen.room.block.length; y++){
for(int x=0; x<Screen.room.block[0].length; x++){
if(Screen.room.block[y][x].contains(Screen.mse)){
if(Screen.room.block[y][x].groundID != Value.ground && Screen.room.block[y][x].airID == Value.tower){
Screen.room.block[y][x].airID = heldID;
}
}
}
}
}
When i put down a tower by:
System.out.println(Screen.room.block[y][x]);
i get
Block[x=243,y=260,width=52,height=52]
This works fine and the tower is placed. I then wanted to use the location of what the tower is placed and then if that location is pressed the message would print in the console. However this doesnt happen. Can anyone help me fix this problem.
I use a mouse listener which is:
public void mouseClicked(MouseEvent e) {
e.getX();
e.getY();
Block.click(e.getX(), e.getY());
}
When i click on a location i get:
System.out.println("X. " + X + " Y. " + Y);
X. 257 Y. 298
if this helps.
Right now you are using pixels to get the location of your object, so you need to check more than the exact "origin" pixel for each block.
public static void click(int X, int Y){
System.out.println("X. " + X + " Y. " + Y);
//Look for every block in the matrix
for ( int i = 0; i<Screen.room.block.length; i++ ) {
for ( int j = 0; j<Screen.room.block[0].length; j++ ) {
if(Screen.room.block[i][j].airID == Value.tower){
//Check if we hit within the block's bounds
if ( X >= i && X <= i+blockWidth &&
Y >= j && Y <= j+blockHeight )
System.out.println("Tower clicked");
return;
}
}
}
}
A common practice is to store your objects in some kind of list or uni-dimensional array, so that you can avoid the
for ( int i = 0; i<Screen.room.block.length; i++ ) {
for ( int j = 0; j<Screen.room.block[0].length; j++ ) {
and just do
for ( int i = 0; i<Screen.room.blocks.length; i++ ) {
to check for every block and to avoid having such a big matrix when you must check every block anyway.
Another approach: you could give each block a place in a checkers-like matrix and then transform the mouse clicked event coordinates from pixels to "block" coordinates:
public void mouseClicked(MouseEvent e) {
int x = e.getX() / widthOfABlockInPixels;
int y = e.getY() / heightOfABlockInPixels;
Block.click(x, y);
}
Say your objects are 100x100 pixels, then this would give you the right block coordinates for
(160, 150) => (1, 1)
(60, 50) => (0, 0)
and so on.
This might sound a little over-simplified, but, then again, I'm just spit-balling here. Have you thought about implementing the message into a JOptionPane.showMessageDialog? Not sure if that would be what you're looking for.

Fixing error that occurs when a lot of sprites are colliding

In the game that I am making I have made it so that the zombies can't go through each other. I did this with this code.
for(int i = 0; i < zombies.size(); i++){
Zombie z = (Zombie) zombies.get(i);
zombieMovement();
for(int j = i + 1; j < zombies.size(); j++){
Zombie z2 = (Zombie) zombies.get(j);
Rectangle r1 = z.getBounds();
Rectangle r2 = z2.getBounds();
if(r1.intersects(r2)){
z.setX(z.getX() - 1);
z.setY(z.getY() - 1);
z2.setX(z2.getX() + 1);
z2.setY(z2.getY() + 1);
}
}
}
the zombieMovement method looks like this.
public void zombieMovement(){
for(int i = 0; i < zombies.size(); i++){
Zombie z = (Zombie) zombies.get(i);
if(z.getY() > player.getY()){
z.setY(z.getY() - .01);
}
if(z.getY() < player.getY()){
z.setY(z.getY() + .01);
}
if(z.getX() > player.getX()){
z.setX(z.getX() - .01);
}
if(z.getX() < player.getX()){
z.setX(z.getX() + .01);
}
if(z.isAlive()){
z.move();
}else{
zombies.remove(i);
}
}
}
Because the zombies move 10 times as fast when they are in contact with each other the first couple of zombies move alot faster than the ones that come later because they are in contact with more zombies (I can't set how fast they move when they are in contact with each other to any less because then they will still be able to be inside each other and I don't want the zombies to move any faster than what they are already doing).
Are there any simple ways to fix this error in?
Rather than trying to fix zombies that overlap you should prevent the problem in the first place in your zombieMovement() method. When working out where a zombie moves to you should test to see if its new position (the +/- .01 bit) is already occupied, if so then don't move the zombie to that location.
/**
* Returns true if the point x,y is already occupied by a zombie
*/
boolean isOccupied(double x, double y) {
for (Zombie z : zombies) {
if (z.getBounds().contains(new Point(x,y))) {
return true;
}
}
return false;
}
You can then test in your movement method like this;
if (z.getY() > player.getY()) {
double newY = z.getY() - .01;
if (!isOccupied(z.getX(), newY) {
z.setY(newY);
{
}
What happens when a zombie is surrounded on all sides and you have to move it?
For a really robust solution, I'd do a simultaneous constraint solver. Essentially, you can think of it like putting a spring in between each colliding zombie and iterating until everyone is no longer intersecting. You'd probably want to put caps on displacement to make sure you don't accidentally have zombies shooting off into space as well.
Unfortunately, this approach requires complicated math. I think Box2d has some slides online explaining the basis of its algorithms. Or you could just use an existing physics engine, like Box2d.

Finding the closest object (barrier) to the player

I have a program that checks distance and whether or not the player has collided with a barrier. I now am trying to calculate which barrier in the array of barriers is the closest to the moving player, then returning the index of that barrier.
Here is what I have so far:
public static int closestBarrier(GameObject object, GameObject[] barriers)
// TODO stub
{
int closest = 0;
for (int i = 0; i < barriers.length - 1; i++) {
if (Math.sqrt((object.getX() - barriers[i].getX())
* (object.getX() - barriers[i].getX()))
+ ((object.getY() - barriers[i].getY()) * (object.getY() - barriers[i]
.getY())) <= Math
.sqrt((object.getX() - barriers[i + 1].getX())
* (object.getX() - barriers[i + 1].getX()))
+ ((object.getY() - barriers[i + 1].getY()) * (object
.getY() - barriers[i + 1].getY()))) {
closest = i;
} else
closest = i + 1;
}
return closest;
}
I am still new to java so I understand what I already have probably isn't very efficient or the best method of doing it (or even right at all!?).
I'd refactor it a wee bit simpler like so:
public static int closestBarrier(GameObject object, GameObject[] barriers)
{
int closest = -1;
float minDistSq = Float.MAX_VALUE;//ridiculously large value to start
for (int i = 0; i < barriers.length - 1; i++) {
GameObject curr = barriers[i];//current
float dx = (object.getX()-curr.getX());
float dy = (object.getY()-curr.getY());
float distSq = dx*dx+dy*dy;//use the squared distance
if(distSq < minDistSq) {//find the smallest and remember the id
minDistSq = distSq;
closest = i;
}
}
return closest;
}
This way you're doing less distance checks (your version does two distance checks per iteration) and also you only need the id, not the actual distance, so you can gain a bit of speed by not using Math.sqrt() and simply using the squared distance instead.
Another idea I can think of depends on the layout. Say you have a top down vertical scroller, you would start by checking the y property of your obstacle. If you have a hash of them or a sorted list, for an object at the bottom of the screen you would start loop from the largest y barrier to the smallest. Once you found the closest barriers on the Y axis, if there are more than 1 you can check for the closest on the x axis. You wouldn't need to use square or square root as you're basically splitting the checks from 1 in 2D per barrier to 2 checks in 1D, narrowing down your barrier and discarding far away barriers instead of checking against every single object all the time.
An even more advanced version would be using space partitioning but hopefully you won't need it for a simple game while learning.

Categories

Resources