Slick2d Java reversing the moving direction of an object - java

I'm working on this game using Java and slick2d library and I'm supposed to reverse the direction of some moving vehicles (eg:bikes) when they reach a certain x-coordinate.
Logic seems simple enough, yet some of them move right past the x-coordinate, while some reverses the direction. Confused as to why. Any help would be appreciated.
Here's my code in the update() method. getX() returns the x location from superclass as a float. BIKE_SPEED is a float, delta being the milliseconds passed since last frame.
#Override
public void update(Input input, int delta) {
if ((int)getX() == 24 || (int)getX() == 1000) {
moveRight = !moveRight;
}
move(BIKE_SPEED * delta * (moveRight ? 1 : -1), 0);
}

I'm not familiar with slick2d, but in general, it's better to use >= or <= instead of == in cases like this. The object (bike) may "jump" right past the boundaries, without triggering your change of direction condition.

Related

Implementing a Minimax Algorithm in Java for Connect 4

I'm trying to build a game of Connect 4 with minimax (and alpha beta pruning), mostly to prove to myself that I can do it. However, the one big conceptual problem I'm having is with how to actually utilize the minimax algorithm. The way I do it is that I have an AI class that has one function which is to perform the minimax algorithm that returns an int.
public int minimax(Board board, int depth, int alpha, int beta, String player) {
if(depth == 0 || board.getScore() >= 512) {
return board.getScore();
}
else if(player.equals("computer")) {
int temp = -1000000;
for(Integer[] moves : board.availableMoves) {
board.putPiece(player, moves[0]);
temp = Math.max(temp, minimax(board, depth-1, alpha, beta, "human"));
board.removePiece(moves[0], moves[1]);
alpha = Math.max(alpha, temp);
if (alpha >= beta) {
break;
}
}
return temp;
}
else {
int temp = 1000000;
for(Integer[] moves : board.availableMoves) {
board.putPiece(player, moves[0]);
temp = Math.min(temp, minimax(board, depth+1, alpha, beta, "computer"));
board.removePiece(moves[0], moves[1]);
beta = Math.min(beta, temp);
if(alpha >= beta) {
break;
}
}
return temp;
}
}
This is called by a function of the Game class called computerMove().
public int computerMove() {
Board tempBoard = board;
int bestMove = 0;
AI ai = new AI();
ai.minimax(board, difficulty, -1000000, 1000000, "computer");
return bestMove;
}
But, what do I do with the int that is returned? How do I utilize that to actually move the piece? The int that is returned is simply the best possible board I could get, right? It tells me nothing in particular about the location or board that I should do.
Any and all help is greatly appreciated.
Thanks,
The books all say to return just the score, but that's impractical for actually playing the game. Of course the overhead of maintaining the best move everywhere can really slow down the program, so generally you use a driver function that does the first level of expansion, and additionally keeps track of the best move. This is effectively wrapping the implementation in an argmax function, which is just a fancy way of saying it returns the best move at the top level instead of the score. You can see an example of this in a little project I worked on last year. The code is in C# but it's close enough to Java for you to get the idea.
Alternatively, you can modify the code to return a tuple (class with multiple fields) that has the score and the best move. This is easier (and a little cleaner IMO) than writing the argmax wrapper, but without some extra engineering this will probably result in some noticeable slow down of the minimax function because it's going to result in tons more allocations. If performance isn't your top priority, this is probably the way to go.
I should also point out, that your implementation has at least one bug. The depth should always be decreasing regardless of who is playing and in your human branch you have it increase for the human player. This means the depth will never get to 0 and the base case will only be hit when a player is determined to be the winner. Additionally, when using alpha beta, it's important that the board evaluation knows whose turn it is and who is the maximizing player, else you'll run into lots of hard to find bugs. You don't show that code here, but I want to point that out because it gets me every time.

Java Game Physics - Determine intersection and collision detection

My question can actually be broken down into two parts. The first, is what is a reasonable method for determining collision in a Java game? My second, is how to find the point of collision for use later?
Originally I was implementing a rudimentary collision system using a thread I found earlier with a simple method for finding a collision in a polygon. I have posted the code below. However as best I can tell, this will not show me the collision point, and I would have to do something separate to find it.
public boolean collisionDetection(int charX, int charY) {
if(boundry == null)
return false;
int numVert = boundry.length;
boolean ret = false;
for(int i = 0, j = numVert - 1; i < numVert; j = i++) {
if (((boundry[i].y >= charY) != (boundry[j].y >= charY)) && (charX <= (boundry[j].x -boundry[i].x) * (charY - boundry[i].y) / (boundry[j].y - boundry[i].y) + boundry[i].x)) {
ret = !ret;
}
}
return ret;
}
But I had a thought while working on this... Let us presume that I input my coordinates into the system as Points. I did them in order (e.g. point 1 -> point 2 -> point 3 -> point 1).
Knowing the points are in a connected order (e.g. they form the boundary of the object), is it then logical to say I could just use a number of line intersection methods to find if the character intersected with the border of my polygon? I know the characters current position, as well as the intended position.
Any thoughts, or if you have a suggestion a better implementation method?
you need to be doing either point to pint or box to box collision See my answer here
this explains two methods of collision detection. its in 3D but just drop the third axis and can be used for 2D. Hope this helps

pathfinding in an 2D Array

I know this is an question that get asked alot. I also stuck at it and looking for some help with it.
I do have a small Applikation where Monster should work to the Charakter. Its Gridbased so it's just possible to walk left right up down. I do have an Array where all blockd areas of the map are. All i need to get is the next step to get to the Character(left right up down of it). It would be great if they walk around trees for example. (simple -1 inside of the array)
Is there any simple solution for it or do i need to implement a A*(i tried but i totaly stuck at this)
I simply stared with this:
#Override
public Status getNextMove(int posX, int posY) {
if (checkIfAggroRange(posX, posY)) {
if (checkIfBeside(posX, posY))
//turn to the character
return getIdleStatus(posX, posY);
else
//here id like to add the algo and get the value
} else {
return moveRnd();
}
}
private boolean checkIfAggroRange(int posX, int posY) {
return Math.abs(this.screen.character.mapPos.x - posX) <= range
&& Math.abs(this.screen.character.mapPos.y - posY) <= range;
}
private boolean checkIfBeside(int posX, int posY) {
return (Math.abs(this.screen.character.mapPos.x - posX) <= 1 && Math
.abs(this.screen.character.mapPos.y - posY) <= 1);
}
It does already start aggro when they are in range of the monster and also turns the monster to the character so it can hit the character.
I do get the map simple by screen.map.maparray (int[xsize][ysize]). xpos/yposare the pos inside of the array.
If you need more information about it please let me know.
I suggest using A*, it uses simple heuristics to give you a path from a to b. As its a grid you can just use x,y coordinates which is then quite easy to implement A* with. So what i suggest doing is reading these 2,
http://wiki.gamegardens.com/Path_Finding_Tutorial
http://www.cokeandcode.com/main/tutorials/path-finding/
This should explain to you how A* works.The first article is well structured and you should definitely full read and try to understand before attempting to implement the algorithm. it will also give you ideas on tackling obstacles such as trees in your case
The second one is great, as the A* algorithm implemented is done well and has comments explaining all of it. It is a little over complicated and can be done with just 2-3 classes rather than the amount shown but it will certainly give you an idea of how everything works

Need help detecting collision between two objects

I'm having some issue regarding collision detection in a game i am making. I have the distance between the two objects using this:
double b1Dist = Math.sqrt((obOneX - obTwoX) * (obOneX - obTwoX)
+ ((obOneY - obTwoY) * (obOneY - obTwoY)));
double b1DistTwo = b1Dist - objectOneRadius;
b1DistFinal = b1DistTwo - objectTwoRadius;
and I was attempting to do collision detection with this:
if (b1DistFinal <= objectOneRadius && b1DistFinal <= objectTwoRadius ) {
return false;
}
else
return true;
}
I'm new to java so i'm sure theres probably much better/more efficient ways to write the above, however could anyone please help me out or point me in the right direction?
Thanks
There's nothing wrong with the efficiency of that. However, if obOneX, obOneY, etc are the x and y coordinates of the centers of the objects, then your formula is wrong.
The variable b1DistFinal is the distance between the outer edges of the two objects. If it's zero, those objects have collided.
Try:
if (Math.abs(b1DistFinal) < 0.001) {
return true;
} else {
return false;
}
Note: Rather than checking if it is exactly zero, I am checking if it is close to zero to allow for some rounding error during the double arithmetic.

(Java) Collision Detection Walls

I've been trying to use my collision detection to stop objects from going through each other. I can't figure out how to do it though.
When objects collide, I've tried reversing the direction of their velocity vector (so it moves away from where it's colliding) but sometimes the objects get stuck inside each other.
I've tried switching their velocities but this just parents objects to each other.
Is there a simple way to limit objects' movement so that they don't go through other objects? I've been using the rectangle intersects for collisions, and I've also tried circle collision detection (using distance between objects).
Ideas?
package objects;
import java.awt.Rectangle;
import custom.utils.Vector;
import sprites.Picture;
import render.Window;
// Super class (game objects)
public class Entity implements GameObject{
private Picture self;
protected Vector position;
protected Vector velocity = new Vector(0,0);
private GameObject[] obj_list = new GameObject[0];
private boolean init = false;
// Takes in a "sprite"
public Entity(Picture i){
self = i;
position = new Vector(i.getXY()[0],i.getXY()[1]);
ObjectUpdater.addObject(this);
}
public Object getIdentity() {
return this;
}
// position handles
public Vector getPosition(){
return position;
}
public void setPosition(double x,double y){
position.setValues(x,y);
self.setXY(position);
}
public void setPosition(){
position.setValues((int)Window.getWinSize()[0]/2,(int)Window.getWinSize()[1]/2);
}
// velocity handles
public void setVelocity(double x,double y){ // Use if you're too lazy to make a vector
velocity.setValues(x, y);
}
public void setVelocity(Vector xy){ // Use if your already have a vector
velocity.setValues(xy.getValues()[0], xy.getValues()[1]);
}
public Vector getVelocity(){
return velocity;
}
// inferface for all game objects (so they all update at the same time)
public boolean checkInit(){
return init;
}
public Rectangle getBounds() {
double[] corner = position.getValues(); // Get the corner for the bounds
int[] size = self.getImageSize(); // Get the size of the image
return new Rectangle((int)Math.round(corner[0]),(int)Math.round(corner[1]),size[0],size[1]); // Make the bound
}
// I check for collisions where, this grabs all the objects and checks for collisions on each.
private void checkCollision(){
if (obj_list.length > 0){
for (GameObject i: obj_list){
if (getBounds().intersects(i.getBounds()) && i != this){
// What happens here?
}
}
}
}
public void updateSelf(){
checkCollision();
position = position.add(velocity);
setPosition(position.getValues()[0],position.getValues()[1]);
init = true;
}
public void pollObjects(GameObject[] o){
obj_list = o;
}
}
Hopefully it's not too difficult to read.
Edit:
So I've been using the rectangle intersection method to calculate the position of an object and to modify velocity. It's working pretty well. The only problem is that some objects push others, but that's so big deal. Collision is pretty much an extra thing for the mini game I'm creating. Thanks a lot of the help.
All that being said, I'd still really appreciate elaboration on mentioned ideas since I'm not totally sure how to implement them into my project.
Without seeing your code, I can only guess what's happening. I suspect that your objects are getting stuck because they overshooting the boundaries of other objects, ending up inside. Make sure that each object's step is not just velocity * delta_time, but that the step size is limited by potential collisions. When there is a collision, calculate the time at which it occurred (which is somewhere in the delta_time) and follow the bounce to determine the final object location. Alternatively, just set the objects to be touching and the velocities changed according to the law of conservation of momentum.
EDIT After seeing your code, I can expand my answer. First, let me clarify some of my terminology that you asked about. Since each call to updateSelf simply adds the velocity vector to the current position, what you have in effect is a unit time increment (delta time is always 1). Put another way, your "velocity" is actually the distance (velocity * delta time) traveled since the last call to updateSelf. I would recommend using an explicit (float) time increment as part of your simulation.
Second, the general problem of tracking collisions among multiple moving objects is very difficult. Whatever time increment is used, it is possible for an object to undergo many collisions in that increment. (Imagine an object squeezed between two other objects. In any given time interval, there is no limit to the number of times the object might bounce back and forth between the two surrounding ones.) Also, an object might (within the resolution of the computations) collide with multiple objects at the same time. The problem is even more complicated if the objects actually change size as they move (as your code suggests they may be doing).
Third, you have a significant source of errors because you are rounding all object positions to integer coordinates. I would recommend representing your objects with floating-point objects (Rectangle2D.Float rather than with Rectangle; Point2D.Float rather than Vector). I would also recommend replacing the position field with a rectangular bounds field that captures both the position and size. That way, you don't have to create a new object at each call to getBounds(). If the object sizes are constant, this would also simplify the bounds updating.
Finally, there's a significant problem with having the collision detection logic inside each object: when object A discovers that it would have hit object B, then it is also the case that object B would have hit object A! However, object B does its own calculations independently of object A. If you update A first, then B might miss the collision, and vice versa. It would be better to move the entire collision detection and object movement logic to a global algorithm and keep each game object relatively simple.
One approach (which I recommend) is to write an "updateGame" method that advances the game state by a given time increment. It would use an auxiliary data structure that records collisions, which might look like this:
public class Collision {
public int objectIndex1; // index of first object involved in collision
public int objectIndex2; // index of second object
public int directionCode; // encoding of the direction of the collision
public float time; // time of collision
}
The overall algorithm advances the game from the current time to a new time defined by a parameter deltaTime. It might be structured something like this:
void updateGame(float deltaTime) {
float step = deltaTime;
do (
Collision hit = findFirstCollision(step);
if (hit != null) {
step = Math.max(hit.time, MIN_STEP);
updateObjects(step);
updateVelocities(hit);
} else {
updateObjects(step);
}
deltaTime -= step;
step = deltaTime;
} while (deltaTime > 0);
}
/**
* Finds the earliest collision that occurs within the given time
* interval. It uses the current position and velocity of the objects
* at the start of the interval. If no collisions occur, returns null.
*/
Collision findFirstCollision(float deltaTime) {
Collision result = null;
for (int i = 0; i < obj_list.length; ++i) {
for (int j = i + 1; j < obj_list.length; ++j) {
Collision hit = findCollision(i, j, deltaTime);
if (hit != null) {
if (result == null || hit.time < result.time) {
result = hit;
}
}
}
}
return result;
}
/**
* Calculate if there is a collision between obj_list[i1] and
* obj_list[i2] within deltaTime, given their current positions
* and velocities. If there is, return a new Collision object
* that records i1, i2, the direction of the hit, and the time
* at which the objects collide. Otherwise, return null.
*/
Collision findCollision(int i1, int i2, float deltaTime) {
// left as an exercise for the reader
}
/**
* Move every object by its velocity * step
*/
void updateObjects(float step) {
for (GameObject obj : obj_list) {
Point2D.Float pos = obj.getPosition();
Point2D.Float velocity = obj.getVelocity();
obj.setPosition(
pos.getX() + step * velocity.getX(),
pos.getY() + step * velocity.getY()
);
}
}
/**
* Update the velocities of the two objects involved in a
* collision. Note that this does not always reverse velocities
* along the direction of collision (one object might be hit
* from behind by a faster object). The algorithm should assume
* that the objects are at the exact position of the collision
* and just update the velocities.
*/
void updateVelocities(Collision collision) {
// TODO - implement some physics simulation
}
The MIN_STEP constant is a minimum time increment to ensure that the game update loop doesn't get stuck updating such small time steps that it doesn't make progress. (With floating point, it's possible that deltaTime -= step; could leave deltaTime unchanged.)
Regarding the physics simulation: the Wikipedia article on Elastic collision provides some nice math for this problem.

Categories