Collision detection not working with my brick breaker program? - java

My program has been experiencing an odd bug i just cannot seem to fix. In summary, whenever I switch two if statements, only the one coming afte tthe first one will work.
Example: (The ball will successfully collide with the top, but won't with the bottom.)
public void update()
{
if(enemies != null)
{
for(Enemy e : enemies)
if(c.getBall().getHitbox().intersects(e.getHitbox()))
{
if(e.collidedBottom())
c.getBall().setSpeedY((c.getBall().ballSpeed));
if(e.collidedTop())
c.getBall().setSpeedY(-(c.getBall().ballSpeed));
deadEnemies.add(e);
}
enemies.removeAll(deadEnemies);
}
Now if i switched the positions of the two if statements like so;
if(e.collidedTop())
c.getBall().setSpeedY(-(c.getBall().ballSpeed));
if(e.collidedBottom())
c.getBall().setSpeedY((c.getBall().ballSpeed));
The ball will successfully react the way it should when colliding with the bottom, but not with the top. Here is the two collision methods:
public boolean collidedBottom()
{
if(c.getBall().getBallY() <= enemy.y + enemy.height &&
c.getBall().getBallX() + c.getBall().getHitbox().width >= enemy.x
&& c.getBall().getBallX() <= enemy.x + enemy.width)
return true;
return false;
}
public boolean collidedTop()
{
if(c.getBall().getBallY() + c.getBall().getHitbox().height >= enemy.y &&
c.getBall().getBallX() + c.getBall().getHitbox().width >= enemy.x
&& c.getBall().getBallX() <= enemy.x + enemy.width)
return true;
return false;
}
Enemy refers to the current focused block in the loop.

Related

Java pong ball not moving in the other direction when hitting the paddle

i am trying to make the game Pong in Java. Now i have a problem with the collision on the paddle. It is not moving the other direction. It does work when it hits the sides of the panel.
For now i just needs to go the other way when it hits the X value of the paddle.
I made a function to check the collision.
What am i doing wrong here. Can someone please explain me this?
Thanks in advance
public void checkCollision()
{
if (ball.getY() == 0)
{
moveDown = true;
moveUp = false;
}
if ((ball.getY() + ball.getHeight()) == height)
{
moveDown = false;
moveUp = true;
}
if (ball.getX() == computer.getX())
{
moveRight = false;
moveLeft = true;
}
}
class TimerHandler implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
if (counter == 0)
{
Random rand = new Random();
int random = rand.nextInt(2) + 1 ;
if (random == 1)
{
moveUp = true;
moveRight = true;
counter++;
}
else if (random == 2)
{
moveDown = true;
moveLeft = true;
counter++;
}
}
controlMovement();
checkCollision();
repaint();
}
}
I believe that your checkCollision function is incomplete... somehow, the function must have access to both paddle current positions to check if the ball hits one of the paddles...
Another suggestion is to use only one flag to indicante the movement in one axis, for example, boolean monvingUp = true indicantes that the ball is moving up at the Y-axis, when false, such flag indicates that is moving down at the Y-axis...
I changed the = to > and it fixed the problem

Finding an Object in an Array List, Defined by a Boolean

I'm working on a project that is supposed to be a maze solver. The code I have is nearly complete, except for one bit. I need to get the index of a point in my array list, but I have a boolean regulating what point I need. I need to be able to get the index of the point that will satisfy the boolean as true, but I'm not quite sure how to do that. I've attached some of the code below. I hope it's enough to show you what I mean!
Here's the boolean with the conditions for what the point will be:
public static boolean adjacent( Point p1, Point p2 )
{
int pointX1 = p1.getX();
int pointX2 = p2.getX();
int pointY1 = p1.getY();
int pointY2 = p2.getY();
while (pointY1 == pointY2)
{
if(pointX1 + 1 == pointX2)
{
return true;
}
else if(pointX1 - 1 == pointX2)
{
return true;
}
}
while (pointX1 == pointX2)
{
if(pointY1 + 1 == pointY2)
{
return true;
}
else if(pointY1 - 1 == pointY2)
{
return true;
}
}
return false;
}
Here's what I have so far for my array list:
public static boolean isSolvable( ArrayList<Point> points )
{
ArrayList<Point> second = new ArrayList<Point>();
second.add(points.get(0));
points.remove(0);
while(second.size() >= 1)
{
//if second contains adjacent point. (Add adjacent to array list, and subtract from other array list[point])
if(points.contains(adjacent(second.get(0), points.get(0))) == true)
{
}
}
return false;
}
As far as I see, you have one major problem in your adjacent(Point, Point) method. Instead using whiles (I don't know why you would use them here) change them to ifs:
if(pointY1 == pointY2)
{
if(pointX1 + 1 == pointX2
|| pointX1 - 1 == pointX2)
return true;
}
if(pointX1 == pointX2)
{
if(pointY1 + 1 == pointY2
|| pointY1 - 1 == pointY2)
return true;
}
EDIT: As #Lars says, you can write this in a one-liner function as:
return Math.abs(p1.getX() - p2.getX()) + Math.abs(p1.getY() - p2.getY()) == 1;
Also, I would try a backtracking, a greedy, or even a branch and bound algorithm to solve your maze too.

player goes through walls while jumping (JAVA)

I am trying to make a donkey kong game.
Currently, I have a boolean called jump which tells that game if the player is jumping or not, when the space bar is pressed.
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_SPACE){
StartJump();
}
}
StartJump: Makes the sprite start jumping by changing velocity. It also changes the jump boolean to true.
public void StartJump() {
if (onground) {
velocityY = -4;
onground = false;
jump = true;
}
}
KeyReleased:
public void keyReleased(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_SPACE){
EndJump();
}
}
EndJump: Sets jump to false
public void EndJump() {
if(velocityY < -6.0)
velocityY = -6;
jump = false;
}
The problem occurs when you hold down the spacebar, jump is set to true.
Which then causes the forloop which sets the Y position of Mario to not work and he falls through the floor.
Loop: bricks just contains rectangles for Mario to stand on
for(int i = 0; i < bricks.size(); i++) {
if(marHitBox.intersects(bricks.get(i)) && !mario.getClimb() && !mario.getJump() && marHitBox.intersects(jump.get(i))) {
mario.setMarY((int)bricks.get(i).getY()-40);
mario.setVeloY(0f);
mario.setOnGround(true);
}
}
It is the !mario.getJump() that is causing the problem. Is there any way to see if the spacebar is held for more than x milliseconds to make jump = false?
Try measuring the passing time between the spacebar is pressed and released, it will fit your need.
I think just a check would make it go away
public void StartJump(){
if (!jump && onground){
velocityY = -4;
onground = false;
jump = true;
}
}

How to backtrace in a maze...?

So I'm writing a program to make a robot explore a maze to find a specified cavern. There are four types of Cells: Cavern, Start, Wall, and Passage. Robots can only move to a passage or a cavern. I implemented my method so that a robot can't move to a visited cell or go out of bounds. But once it moves to a cell where there isn't a valid adjacent cell, the program stops. So how do I make my robot backtrace to where there is a valid cell? I'm using a recursion for this. Below is my code. Any help will be great. Thank you!
public void explore (Cell cavern, Maze maze) throws InterruptedException {
// for debugging
System.out.println(row + " " + col);
System.out.println(cavern.getRow() + " " + cavern.getCol());
System.out.println(visited.toString());
TimeUnit.MILLISECONDS.sleep(10); // delay program
//base case
if (row == cavern.getRow() && col == cavern.getCol()) {
foundCavern = true;
return;
}
else {
// move right
if ((col+1) < maze.getNumCols() && !visited.contains(maze.getCell(row, col+1)) && (maze.getCell(row, col+1).isPassage() || maze.getCell(row, col+1).isCavern())) {
visited.add(maze.getCell(row, col+1));
setRobotLocation(row,col+1);
explore(cavern, maze);
}
// move down
else if ((row+1) < maze.getNumRows() && !visited.contains(maze.getCell(row+1, col)) && (maze.getCell(row+1, col).isPassage() || maze.getCell(row+1, col).isCavern())) {
visited.add(maze.getCell(row+1, col));
setRobotLocation(row+1,col);
explore(cavern, maze);
}
// move left
else if ((col-1) >= 0 && !visited.contains(maze.getCell(row, col-1)) && (maze.getCell(row, col-1).isPassage() || maze.getCell(row, col-1).isCavern())) {
visited.add(maze.getCell(row, col-1));
setRobotLocation(row,col-1);
explore(cavern, maze);
}
// move up
else if ((row-1) >= 0 && !visited.contains(maze.getCell(row-1, col)) && (maze.getCell(row-1, col).isPassage() || maze.getCell(row-1, col).isCavern())) {
visited.add(maze.getCell(row-1, col));
setRobotLocation(row-1,col);
explore(cavern, maze);
}
else {
foundCavern = false;
return;
}
}
}
I think you are in the right direction.
What I think you should do is keep checking for all direction unless you found the cavern.
Right now you are checking for only one direction in each iteration because of the else clause. So when the call to explore returns you can't keep checking a different direction and essentially you don't backtrack.
If you make your explore function return a Boolean field indicating whether you reached the cavern changing your code like this may work:
// move right
if ... // your condition to check if moving right is possible and you didn't visit
// code to move right
found = explore()
//move down if didn't find cavern
if (!found) // and moving down is possible and didn't visit
// code to move down
found = explore()
// keep checking other directions

Only trigger proximity detector when object enters the range, not when he moves within range

I'm making a text-based radar for Minecraft. If a player comes within 20 blocks of you, it will say in chat. As of now, it spams the chat. How can I get it to only write to chat about that player ONCE? Even if you don't play the game, it should be easy to understand.
if (Camb.radar)
{
for (Entity e: (List < Entity > ) mc.theWorld.loadedEntityList)
{
if (e instanceof EntityPlayer)
{
EntityPlayer player = (EntityPlayer) e;
if (player == mc.thePlayer || mc.thePlayer.getDistanceToEntity(e) > 20.0)
continue;
mc.thePlayer.addChatMessage("\2479[CAMB] \247e" + player.getEntityName() + " has entered your 20 block radius!"); //Write to chat, only want this line done once for every player
}
}
}
You'll need to keep track of when the player leaves the range and set a flag, so you'll know when they're transitioning from "out of range" to "in range". Might also want to add a timer so that you can only alert once every N seconds.
You could try creating a List or Array of nearby players, and add them to that list when they are within 20 blocks. When you find an entity within range, check to see if its in your list. If not, notify and add it to the list, if so, game on :)
For removing items from your list, check the entities in your list and compare them to the players position. If they are out of range, remove them. This may need to happen in a separate loop.
If you make a class PlayerData, it can contain a hashmap of playernames mapped to booleans. You give each player a PlayerData object and then when somebody enters the radius of that player, you toggle his/her boolean.
public class PlayerData {
public Player thePlayer;
public HashMap<String,boolean> inRadius = new HashMap<String,boolean>();
public PlayerData(Player thePlayer) {
this.thePlayer = thePlayer;
}
public void checkRadius(P Entity player) {
/**function that checks radius and if a new player is there, notify thePlayer*/
if(inRadius.get(player.getEntityName()) == true || thePlayer == player || thePlayer.getDistanceToEntity(player) > 20.0) return;
else {
thePlayer.addChatMessage("whatever you want to say");
inRadius.put(player.getEntityName(), true);
}
for(Iterator<String> key=inRadius.keySet().Iterator();key.hasNext()) {
String name = key.next();
/**Check to see if that player is still within 20 meters. If not, set value to false*/
/** also be careful to check if player is online*/
}
}
}
Add a boolean flag to EntityPlayer detected with getter/setter methods.
Inside your loop:
if (Camb.radar) {
for (....) {
if (e instanceof EntityPlayer) {
EntityPlayer player = (EntityPlayer) e;
if (player.isDetected() || player == mc.thePlayer || mc.thePlayer.getDistanceToEntity(e) > 20.0) {
continue;
}
if (!player.isDetected()) {
mc.thePlayer.addChatMessage(....);
player.setDetected(true); // reset this flag when player goes out of radar
}
}
}
}
You need to store outside of that method that you have alerted the player already.
A Map is perfect for this. Even better a WeakHashMap in case you don't want to leak those Entities
private final Set<EntityPlayer> playersInRange = Collections
.newSetFromMap(new WeakHashMap<EntityPlayer, Boolean>());
void onMove() {
if (Camb.radar) {
for (Entity e : (List<Entity>) mc.theWorld.loadedEntityList) {
if (e instanceof EntityPlayer) {
EntityPlayer player = (EntityPlayer) e;
if (player == mc.thePlayer || mc.thePlayer.getDistanceToEntity(e) > 20.0) {
// make sure player is (no longer) in set
playersInRange.remove(player);
continue;
}
if (!playersInRange.contains(player)) {
playersInRange.add(player);
mc.thePlayer.addChatMessage("\2479[CAMB] \247e" + player.getEntityName()
+ " has entered your 20 block radius!");
}
}
}
}
}
You could also store a time along with them to re-alert every X time.
private static final long WAIT_BETWEEN_ALERTS = 30000;
private final WeakHashMap<EntityPlayer, Long> map = new WeakHashMap<EntityPlayer, Long>();
void onMove() {
if (Camb.radar) {
for (Entity e : (List<Entity>) mc.theWorld.loadedEntityList) {
if (e instanceof EntityPlayer) {
EntityPlayer player = (EntityPlayer) e;
if (player == mc.thePlayer || mc.thePlayer.getDistanceToEntity(e) > 20.0) {
// clear alerts
map.remove(player);
continue;
}
Long lastTimeAlerted = map.get(player);
long minimumLastAlert = System.currentTimeMillis() - WAIT_BETWEEN_ALERTS;
if (lastTimeAlerted == null || lastTimeAlerted < minimumLastAlert) {
map.put(player, System.currentTimeMillis());
mc.thePlayer.addChatMessage("\2479[CAMB] \247e" + player.getEntityName()
+ " has entered your 20 block radius!");
} // else, already alerted recently.
}
}
}
}
I suggest doing as following:
int radius = 0;
if (Camb.radar) for (Entity e : (List <Entity>) mc.theWorld.loadedEntityList)
if (e instanceof EntityPlayer) {
EntityPlayer player = (EntityPlayer) e;
if (player == mc.thePlayer || mc.thePlayer.getDistanceToEntity(e) > 20.0)
continue;
while (radius < 1) {
mc.thePlayer.addChatMessage("\2479[CAMB] \247e" + player.getEntityName() + " has
entered your 20 block radius!");
}
}

Categories

Resources