public boolean onTouch(View paramView, MotionEvent paramMotionEvent)
{
ImageView localImageView = (ImageView)paramView;
dumpEvent(paramMotionEvent);
switch (0xFF & paramMotionEvent.getAction())
{
}
for (;;)
{
localImageView.setImageMatrix(this.matrix);
return true;
this.savedMatrix.set(this.matrix)
this.start.set(paramMotionEvent.getX(), paramMotionEvent.getY());
Log.d("Touch", "mode=DRAG");
this.mode = 1;
continue;
this.oldDist = spacing(paramMotionEvent);
Log.d("Touch", "oldDist=" + this.oldDist);
if (this.oldDist > 10.0F)
{
this.savedMatrix.set(this.matrix);
midPoint(this.mid, paramMotionEvent);
this.mode = 2;
Log.d("Touch", "mode=ZOOM");
continue;
this.mode = 0;
Log.d("Touch", "mode=NONE");
continue;
if (this.mode == 1)
{
this.matrix.set(this.savedMatrix);
this.matrix.postTranslate(paramMotionEvent.getX() - this.start.x, paramMotionEvent.getY() - this.start.y);
}
else if (this.mode == 2)
{
float f1 = spacing(paramMotionEvent);
Log.d("Touch", "newDist=" + f1);
if (f1 > 10.0F)
{
this.matrix.set(this.savedMatrix);
float f2 = f1 / this.oldDist;
this.matrix.postScale(f2, f2, this.mid.x, this.mid.y);
}
}
}
}
}
}
As you can see, I'm using the matrix method to be able to scroll and zoom images in the app.
However, I'm getting the error Unreachable code, in the part(the first time this statement appears)
this.savedMatrix.set(this.matrix)
Any suggestions? Thx.
because of this line..
return true;
You are returning the value..without performing any operation..so the code below your return statement is not execute any more..
so add this at the bottom of the method..
return true;
Related
I am making my first 2d game and when i move up and collide with a tile it stops and i can still move left and right but it is difficult to move through a doorway.
the image below shows where the player gets stuck they cant move right or down they also can't move up but that is intended
Sorry if i left something important out this is my first time posting a question.
Edit
to try to clarify
my collision box is set a bit smaller than my player so that the player will overlap the wall tiles a bit so when attempting to walk through a doorway to the right if the top of the player collision Box collides with the bottom of the tiles collision box it does stop the player from moving up but if the player tries to keep moving right the player would be stopped
an image of where the player is getting stuck
CollisionHandler.java (Handles all collisions)
package game.handlers;
import game.GamePanel;
import game.entities.Entity;
import game.items.Item;
import game.items.objects.*;
import game.items.misc.*;
public class CollisionHandler
{
GamePanel gp;
public CollisionHandler(GamePanel gp)
{
this.gp = gp;
}
public void checkTile(Entity entity)
{
int entityLeftWorldX = entity.worldX + entity.collisionBox.x;
int entityRightWorldX = entity.worldX + entity.collisionBox.x + entity.collisionBox.width;
int entityTopWorldY = entity.worldY + entity.collisionBox.y;
int entityBottemWorldY = entity.worldY + entity.collisionBox.y + entity.collisionBox.height;
int entityLeftCol = entityLeftWorldX / gp.tileSize;
int entityRightCol = entityRightWorldX / gp.tileSize;
int entityTopRow = entityTopWorldY / gp.tileSize;
int entityBottemRow = entityBottemWorldY / gp.tileSize;
int tileNum1, tileNum2;
switch(entity.direction)
{
case "up":
entityTopRow = (entityTopWorldY - entity.speed) / gp.tileSize;
tileNum1 = gp.tm.mapTileNum[entityLeftCol] [entityTopRow];
tileNum2 = gp.tm.mapTileNum[entityRightCol] [entityBottemRow];
if(gp.tm.tile[tileNum1].hasCollision || gp.tm.tile[tileNum2].hasCollision)
{
entity.collisionOn = true;
}
break;
case "down":
entityBottemRow = (entityBottemWorldY + entity.speed) / gp.tileSize;
tileNum1 = gp.tm.mapTileNum[entityLeftCol] [entityTopRow];
tileNum2 = gp.tm.mapTileNum[entityRightCol] [entityBottemRow];
if(gp.tm.tile[tileNum1].hasCollision || gp.tm.tile[tileNum2].hasCollision)
{
entity.collisionOn = true;
}
break;
case "left":
entityLeftCol = (entityLeftWorldX - entity.speed) / gp.tileSize;
tileNum1 = gp.tm.mapTileNum[entityLeftCol] [entityTopRow];
tileNum2 = gp.tm.mapTileNum[entityRightCol] [entityBottemRow];
if(gp.tm.tile[tileNum1].hasCollision || gp.tm.tile[tileNum2].hasCollision)
{
entity.collisionOn = true;
}
break;
case "right":
entityRightCol = (entityRightWorldX + entity.speed) / gp.tileSize;
tileNum1 = gp.tm.mapTileNum[entityLeftCol] [entityTopRow];
tileNum2 = gp.tm.mapTileNum[entityRightCol] [entityBottemRow];
if(gp.tm.tile[tileNum1].hasCollision || gp.tm.tile[tileNum2].hasCollision)
{
entity.collisionOn = true;
}
break;
default:
break;
}
}
public int checkItem(Entity entity, boolean player)
{
int index = 999;
for(Item item: gp.items)
{
if(item != null)
{
entity.collisionBox.x = entity.worldX + entity.collisionBox.x;
entity.collisionBox.y = entity.worldY + entity.collisionBox.y;
item.collisionBox.x = item.worldX + item.collisionBox.x;
item.collisionBox.y = item.worldY + item.collisionBox.y;
switch(entity.direction)
{
case "up":
entity.collisionBox.y -= entity.speed;
if(entity.collisionBox.intersects(item.collisionBox))
{
if(item.hasCollision)
{
entity.collisionOn = true;
}
if(player)
{
index = gp.items.indexOf(item);
}
}
break;
case "down":
entity.collisionBox.y += entity.speed;
if(entity.collisionBox.intersects(item.collisionBox))
{
if(item.hasCollision)
{
entity.collisionOn = true;
}
if(player)
{
index = gp.items.indexOf(item);
}
}
break;
case "left":
entity.collisionBox.x -= entity.speed;
if(entity.collisionBox.intersects(item.collisionBox))
{
if(item.hasCollision)
{
entity.collisionOn = true;
}
if(player)
{
index = gp.items.indexOf(item);
}
}
break;
case "right":
entity.collisionBox.x += entity.speed;
if(entity.collisionBox.intersects(item.collisionBox))
{
if(item.hasCollision)
{
entity.collisionOn = true;
}
if(player)
{
index = gp.items.indexOf(item);
}
}
break;
}
/*switch(entity.direction)
{
case "up":
entity.collisionBox.y -= entity.speed;
if(entity.collisionBox.intersects(item.collisionBox))
{
if(item instanceof SObject)
{
SObject object = (SObject)item;
object.interact(gp);
if(item.hasCollision)
{
entity.collisionOn = true;
}
if(player)
{
index = gp.items.indexOf(item);
}
}
else
{
if(item.hasCollision)
{
entity.collisionOn = true;
}
if(player)
{
index = gp.items.indexOf(item);
}
}
}
break;
case "down":
entity.collisionBox.y += entity.speed;
if(entity.collisionBox.intersects(item.collisionBox))
{
if(item instanceof SObject)
{
SObject object = (SObject)item;
object.interact(gp);
if(item.hasCollision)
{
entity.collisionOn = true;
}
if(player)
{
index = gp.items.indexOf(item);
}
}
else
{
if(item.hasCollision)
{
entity.collisionOn = true;
}
if(player)
{
index = gp.items.indexOf(item);
}
}
}
break;
case "left":
entity.collisionBox.x -= entity.speed;
if(entity.collisionBox.intersects(item.collisionBox))
{
if(item instanceof SObject)
{
SObject object = (SObject)item;
object.interact(gp);
if(item.hasCollision)
{
entity.collisionOn = true;
}
if(player)
{
index = gp.items.indexOf(item);
}
}
else
{
if(item.hasCollision)
{
entity.collisionOn = true;
}
if(player)
{
index = gp.items.indexOf(item);
}
}
}
break;
case "right":
entity.collisionBox.x += entity.speed;
if(entity.collisionBox.intersects(item.collisionBox))
{
if(item instanceof SObject)
{
SObject object = (SObject)item;
object.interact(gp);
if(item.hasCollision)
{
entity.collisionOn = true;
}
if(player)
{
index = gp.items.indexOf(item);
}
}
else
{
if(item.hasCollision)
{
entity.collisionOn = true;
}
if(player)
{
index = gp.items.indexOf(item);
}
}
}
break;
}*/
entity.collisionBox.x = entity.defaultCollisionBoxX;
entity.collisionBox.y = entity.defaultCollisionBoxY;
item.collisionBox.x = item.defaultCollisionBoxX;
item.collisionBox.y = item.defaultCollisionBoxY;
}
}
return index;
}
public void interact(Entity entity, int index)
{
Item item = gp.items.get(index);
if(item != null)
{
entity.collisionBox.x = entity.worldX + entity.collisionBox.x;
entity.collisionBox.y = entity.worldY + entity.collisionBox.y;
item.collisionBox.x = item.worldX + item.collisionBox.x;
item.collisionBox.y = item.worldY + item.collisionBox.y;
switch(entity.direction)
{
case "up":
entity.collisionBox.y -= entity.speed;
if(entity.collisionBox.intersects(item.collisionBox))
{
if(item.hasCollision)
{
entity.collisionOn = true;
}
}
break;
case "down":
entity.collisionBox.y += entity.speed;
if(entity.collisionBox.intersects(item.collisionBox))
{
if(item.hasCollision)
{
entity.collisionOn = true;
}
}
break;
case "left":
entity.collisionBox.x -= entity.speed;
if(entity.collisionBox.intersects(item.collisionBox))
{
if(item.hasCollision)
{
entity.collisionOn = true;
}
}
break;
case "right":
entity.collisionBox.x += entity.speed;
if(entity.collisionBox.intersects(item.collisionBox))
{
if(item.hasCollision)
{
entity.collisionOn = true;
}
}
break;
}
entity.collisionBox.x = entity.defaultCollisionBoxX;
entity.collisionBox.y = entity.defaultCollisionBoxY;
item.collisionBox.x = item.defaultCollisionBoxX;
item.collisionBox.y = item.defaultCollisionBoxY;
}
}
}
Entity.java (the class i extend all other entities from player, enemies, npcs, exc...)
package game.entities;
import game.util.Inventory;
import game.items.Item;
import java.awt.image.*;
import java.awt.Rectangle;
import java.util.ArrayList;
public abstract class Entity
{
public int health;
public int maxHealth;
public int worldX, worldY;
public int speed;
public BufferedImage up1, up2, down1, down2, left1, left2, right1, right2;
public String direction;
public int spriteCounter = 0;
public int spriteNumber = 1;
public Rectangle collisionBox;
public int defaultCollisionBoxX, defaultCollisionBoxY;
public boolean collisionOn = false;
public Inventory inv = new Inventory(this);
public Item equiped;
public ArrayList<String> diialogues = new ArrayList<String>();
public void heal(int amountToHeal)
{
health += amountToHeal;
if(health > maxHealth)
{
health = maxHealth;
}
}
public void damage(int amountToDamage)
{
health -= amountToDamage;
if(health < 0)
{
health = 0;
}
}
}
Player.java (The class containing the player of the game)
package game.entities;
import game.handlers.KeyHandler;
import game.items.Item;
import game.items.objects.SObject;
import game.GamePanel;
import java.awt.Graphics2D;
import java.awt.Color;
import java.awt.Rectangle;
import java.awt.image.*;
import java.io.*;
import javax.imageio.ImageIO;
public class Player extends Entity
{
GamePanel gp;
KeyHandler kh;
public final int screenX;
public final int screenY;
public Player(GamePanel gp, KeyHandler kh)
{
this.gp = gp;
this.kh = kh;
screenX = gp.screenWidth/2 - (gp.tileSize/2);
screenY = gp.screenHeight/2 - (gp.tileSize/2);
collisionBox = new Rectangle(8, 16, 32, 32);
defaultCollisionBoxX = collisionBox.x;
defaultCollisionBoxY = collisionBox.y;
worldX = gp.tileSize * 22;
worldY = gp.tileSize * 46; //46
speed = 4;
direction = "down";
health = 50;
maxHealth = 100;
getPlayerImage();
}
public void getPlayerImage()
{
try
{
up1 = ImageIO.read(getClass().getResourceAsStream("/Resources/Entities/Player/boy_up_1.png"));
up2 = ImageIO.read(getClass().getResourceAsStream("/Resources/Entities/Player/boy_up_2.png"));
down1 = ImageIO.read(getClass().getResourceAsStream("/Resources/Entities/Player/boy_down_1.png"));
down2 = ImageIO.read(getClass().getResourceAsStream("/Resources/Entities/Player/boy_down_2.png"));
left1 = ImageIO.read(getClass().getResourceAsStream("/Resources/Entities/Player/boy_left_1.png"));
left2 = ImageIO.read(getClass().getResourceAsStream("/Resources/Entities/Player/boy_left_2.png"));
right1 = ImageIO.read(getClass().getResourceAsStream("/Resources/Entities/Player/boy_right_1.png"));
right2 = ImageIO.read(getClass().getResourceAsStream("/Resources/Entities/Player/boy_right_2.png"));
}
catch(IOException e)
{
e.printStackTrace();
}
}
public void interactObject(int index)
{
if(gp.kh.ePressed)
{
if(index != 999)
{
SObject object = (SObject)gp.items.get(index);
object.interact(gp);
}
}
}
public void pickUpItem(int index)
{
if(index != 999)
{
if(gp.items.get(index) instanceof SObject)
{
}
else
{
//inv.items.add(gp.items.get(index));
gp.items.set(index, null);
}
}
}
public void interactNPC(int index)
{}
public void update()
{
if(kh.downPressed || kh.upPressed || kh.leftPressed || kh.rightPressed)
{
if(kh.upPressed)
{
direction = "up";
}
if(kh.downPressed)
{
direction = "down";
}
if(kh.leftPressed)
{
direction = "left";
}
if(kh.rightPressed)
{
direction = "right";
}
collisionOn = false;
gp.ch.checkTile(this);
int itemIndex = gp.ch.checkItem(this, true);
pickUpItem(itemIndex);
if(!collisionOn)
{
switch(direction)
{
case "up":
worldY -= speed;
break;
case "down":
worldY += speed;
break;
case "left":
worldX -= speed;
break;
case "right":
worldX += speed;
break;
}
}
//int objectIndex = gp.ch.checkItem(this, true);
//interactObject(objectIndex);
gp.kh.ePressed = false;
spriteCounter++;
if(spriteCounter > 12)
{
if(spriteNumber == 1)
{
spriteNumber = 2;
}
else if(spriteNumber == 2)
{
spriteNumber = 1;
}
spriteCounter = 0;
}
}
}
public void draw(Graphics2D g2d)
{
BufferedImage image = null;
switch(direction)
{
case "up":
if(spriteNumber == 1)
{
image = up1;
}
else if(spriteNumber == 2)
{
image = up2;
}
break;
case "down":
if(spriteNumber == 1)
{
image = down1;
}
else if(spriteNumber == 2)
{
image = down2;
}
break;
case "left":
if(spriteNumber == 1)
{
image = left1;
}
else if(spriteNumber == 2)
{
image = left2;
}
break;
case "right":
if(spriteNumber == 1)
{
image = right1;
}
else if(spriteNumber == 2)
{
image = right2;
}
break;
default:
break;
}
int x = screenX;
int y = screenY;
if(screenX > worldX)
{
x = worldX;
}
if(screenY > worldY)
{
y = worldY;
}
int rightOffset = gp.screenWidth - gp.player.screenX;
if(rightOffset > gp.worldWidth - gp.player.worldX)
{
x = gp.screenWidth - (gp.worldWidth - worldX);
}
int bottemOffset = gp.screenHeight - gp.player.screenY;
if(bottemOffset > gp.worldHeight - gp.player.worldY)
{
y = gp.screenHeight -(gp.worldHeight - worldY);
}
g2d.drawImage(image, x, y, gp.tileSize, gp.tileSize, null);
}
}
KeyHandler.java (handles all my key imputs)
package game.handlers;
import game.GamePanel;
import java.awt.event.KeyListener;
import java.awt.event.KeyEvent;
public class KeyHandler implements KeyListener
{
GamePanel gp;
public boolean upPressed, leftPressed, downPressed, rightPressed;
public boolean ePressed, enterPressed;
private boolean u, u2, d, d2, l, r, l2, r2;
public KeyHandler(GamePanel gp)
{
this.gp = gp;
}
#Override
public void keyTyped(KeyEvent e)
{}
#Override
public void keyPressed(KeyEvent e)
{
int input = e.getKeyCode();
if(gp.gameState == gp.playState)
{
if(input == KeyEvent.VK_W)
{
upPressed = true;
}
if(input == KeyEvent.VK_A)
{
leftPressed = true;
}
if(input == KeyEvent.VK_S)
{
downPressed = true;
}
if(input == KeyEvent.VK_D)
{
rightPressed = true;
}
//interact key
if(input == KeyEvent.VK_E)
{
ePressed = true;
}
//Dev mode
if(input == KeyEvent.VK_UP)
{
if(!u)
{
u = true;
}
else if(u)
{
u2 = true;
}
if(u && u2)
{
if(!gp.devMode)
{
gp.devMode = true;
}
else if(gp.devMode)
{
gp.devMode = false;
}
}
}
if(gp.devMode)
{
if(input == KeyEvent.VK_T)
{
gp.player.heal(5);
}
if(input == KeyEvent.VK_Y)
{
gp.player.damage(5);
}
}
}
if(gp.gameState == gp.playState || gp.gameState == gp.pauseState)
{
//Toggle Pause Menu
if(input == KeyEvent.VK_P)
{
if(gp.gameState == gp.playState)
{
gp.gameState = gp.pauseState;
}
else if(gp.gameState == gp.pauseState)
{
gp.gameState = gp.playState;
}
}
}
if(gp.gameState == gp.textState)
{
if(input == KeyEvent.VK_ENTER)
{
enterPressed = true;
}
}
}
#Override
public void keyReleased(KeyEvent e)
{
int input = e.getKeyCode();
if(input == KeyEvent.VK_W)
{
upPressed = false;
}
if(input == KeyEvent.VK_A)
{
leftPressed = false;
}
if(input == KeyEvent.VK_S)
{
downPressed = false;
}
if(input == KeyEvent.VK_D)
{
rightPressed = false;
}
}
}
I would greatly appreciate any help that can be given along with any suggestions
Answering your question about refactoring: there are many places where your code can be made much cleaner and efficient. For example, consider this part from KeyHandler.java:
if(!u)
{
u = true;
}
else if(u)
{
u2 = true;
}
if(u && u2)
{
if(!gp.devMode)
{
gp.devMode = true;
}
else if(gp.devMode)
{
gp.devMode = false;
}
}
Take a look on the first if-statement. If u is false, you enter the first branch and set it to true. Otherwise u is true and you enter the second branch. In this second branch you have a test if(u). But you can enter this branch only if u is true! It means that you don't need to check it again and it can be simplified to
if (!u) {
u = true;
} else {
u2 = true;
}
Now, you can see that after execution of this if-statement the value of u will always be true (because it was either true from the start, or it was set to true in the first branch). Thus, it can be simplified even more:
if (u) {
u2 = true;
}
u = true;
After that the next if-statement follows. The condition is if (u && u2). However, as we have seen just now the value of u at this point is always true. So the condition can be simplified to just if (u2). What is inside the if-statement? The following code:
if(!gp.devMode)
{
gp.devMode = true;
}
else if(gp.devMode)
{
gp.devMode = false;
}
Here you again perform the same excessive test as before with the u variable: there is no need for the second if(gp.devMode) check, because in order to get in this branch gp.devMode must be already true. The whole meaning of this if-statement is to toggle the value of gp.devMode: if it is true then set it to false and vice versa. You can achieve this with a simple assignment:
gp.devMode = !gp.devMode;
So, the second if-statement can be reduced to just
if (u2) {
gp.devMode = !gp.devMode;
}
And the whole block of code from which we started is reduced to
if (u) {
u2 = true;
}
u = true;
if (u2) {
gp.devMode = !gp.devMode;
}
This is just a simplification of the code, while maintaining the same logic. In many places the logic can be simplified or changed as well.
Also, the code right now is very prone to errors appearing from simple typos. For example, to specify the direction of the motion you use strings. What happens if in one of the places you accidentally type "rigth" instead of "right"? The program will compile and run, but it will not work correctly and it can be very difficult to spot the error. Much better solution in such cases is to use enumerations. So, you create a new file Direction.java:
public enum Direction {
UP,
DOWN,
LEFT,
RIGHT
}
Then in your Entity class you replace the declaration
public String direction;
with
public Direction direction;
When you need to use it you replace a string with the corresponding enumeration value, for example:
switch(direction) {
case Direction.UP:
worldY -= speed;
break;
case Direction.DOWN:
worldY += speed;
break;
case Direction.LEFT:
worldX -= speed;
break;
case Direction.RIGHT:
worldX += speed;
break;
}
This is more efficient and less error-prone. If you make a typo and write Direction.RIGTH, then the code will not compile. The compiler can also warn you now if you forget to specify all the cases in your switch statement, etc.
There are many other places where improvements can be done (e.g. you consistently break encapsulation), but let's return to your main question about collisions. It's hard to tell from the information you provided, but I think the collision box for your player looks something like the red rectangle on the following picture:
Now, consider the player is a bit to the left and up of the door, and the player wants to move to the right:
In your code for collision detection you have the following:
case "right":
entityRightCol = (entityRightWorldX + entity.speed) / gp.tileSize;
tileNum1 = gp.tm.mapTileNum[entityLeftCol] [entityTopRow];
tileNum2 = gp.tm.mapTileNum[entityRightCol] [entityBottemRow];
if(gp.tm.tile[tileNum1].hasCollision || gp.tm.tile[tileNum2].hasCollision)
{
entity.collisionOn = true;
}
break;
It says, that you calculate the position which is a bit to the right of the player's right side, and then check the left-top and the right-bottom tiles, i.e. tiles shown by green color on the previous picture. Do you see the problem now? You should check the right-top and the right-bottom tiles. However, because of your mistake the collision of the right-top corner with the wall is not detected and the player is allowed to move further, inside the wall.
Now you get this situation:
Let's say you press a down key now. The check is the following:
case "down":
entityBottemRow = (entityBottemWorldY + entity.speed) / gp.tileSize;
tileNum1 = gp.tm.mapTileNum[entityLeftCol] [entityTopRow];
tileNum2 = gp.tm.mapTileNum[entityRightCol] [entityBottemRow];
if(gp.tm.tile[tileNum1].hasCollision || gp.tm.tile[tileNum2].hasCollision)
{
entity.collisionOn = true;
}
break;
You again check the left-top and the right-bottom corners. The right-bottom corner is free, but the left-top is stuck in the wall and you can't move. The same is true for all other directions except for movement to the left.
In order to fix this you need to check in each case the two tiles which are lying in the direction of the desired movement:
case UP: check left-top and right-top;
case DOWN: check left-bottom and right-bottom;
case LEFT: check left-top and left-bottom;
case RIGHT: check right-top and right-bottom;
I am attempting to modify the pacman game from the Mason 19 website. What I have to do is make pacman run on its own and traverse any board given as fast as possible. So far I have achieved making pacman running on its own but it gets stuck in a loop at the top of the board. What I want to know is what would be the best way to make it work and not get stuck in a loop.
The program I am using code from comes from Mason19 https://cs.gmu.edu/~eclab/projects/mason/
The code I have modified is inside the Pac.java and the doPolicyStep class.
protected void doPolicyStep(SimState state)
{
if(lastAction == NOTHING)
{
if(isPossibleToDoAction(Pac.E))
{
pacman.actions[0] = Pac.E;
performAction(Pac.E);
}
else if(isPossibleToDoAction(Pac.S))
{
pacman.actions[0] = Pac.S;
performAction(Pac.S);
}
else if(isPossibleToDoAction(Pac.N))
{
pacman.actions[0] = Pac.N;
performAction(Pac.N);
}
else
{
pacman.actions[0] = Pac.W;
performAction(Pac.W);
}
}
else if(lastAction == Pac.E)
{
if(isPossibleToDoAction(Pac.E))
{
pacman.actions[0] = Pac.E;
performAction(Pac.E);
}
else if(isPossibleToDoAction(Pac.S))
{
pacman.actions[0] = Pac.S;
performAction(Pac.S);
}
else if(isPossibleToDoAction(Pac.N))
{
pacman.actions[0] = Pac.N;
performAction(Pac.N);
}
else
{
pacman.actions[0] = Pac.W;
performAction(Pac.W);
}
}
else if(lastAction == Pac.S)
{
if(isPossibleToDoAction(Pac.S))
{
pacman.actions[0] = Pac.S;
performAction(Pac.S);
}
else if(isPossibleToDoAction(Pac.W))
{
pacman.actions[0] = Pac.W;
performAction(Pac.W);
}
else if(isPossibleToDoAction(Pac.E))
{
pacman.actions[0] = Pac.E;
performAction(Pac.E);
}
else
{
pacman.actions[0] = Pac.N;
performAction(Pac.N);
}
}
else if(lastAction == Pac.W)
{
if(isPossibleToDoAction(Pac.W))
{
pacman.actions[0] = Pac.W;
performAction(Pac.W);
}
else if(isPossibleToDoAction(Pac.N))
{
pacman.actions[0] = Pac.N;
performAction(Pac.N);
}
else if(isPossibleToDoAction(Pac.S))
{
pacman.actions[0] = Pac.S;
performAction(Pac.S);
}
else
{
pacman.actions[0] = Pac.E;
performAction(Pac.E);
}
}
else if(lastAction == Pac.N)
{
if(isPossibleToDoAction(Pac.N))
{
pacman.actions[0] = Pac.N;
performAction(Pac.N);
}
else if(isPossibleToDoAction(Pac.W))
{
pacman.actions[0] = Pac.W;
performAction(Pac.W);
}
else if(isPossibleToDoAction(Pac.E))
{
pacman.actions[0] = Pac.E;
performAction(Pac.E);
}
else
{
pacman.actions[0] = Pac.S;
performAction(Pac.S);
}
}
int nextAction = pacman.getNextAction(tag);
/** The Method isPossibleToDoAction() Determines if the agent can move with the given action (N/W/S/E/NOTHING) without bumping into a wall. */
public boolean isPossibleToDoAction(int action)
{
if (action == NOTHING)
{
return false; // no way
}
IntGrid2D maze = pacman.maze;
int[][] field = maze.field;
// the Agents grid is discretized exactly on 1x1 boundaries so we can use floor rather than divide
// the agent can straddle two locations at a time. The basic location is x0, y0, and the straddled location is x1, y1.
// It may be that x0 == y0.
int x0 = (int) location.x;
int y0 = (int) location.y;
int x1 = location.x == x0 ? x0 : x0 + 1;
int y1 = location.y == y0 ? y0 : y0 + 1;
// for some actions we can only do the action if we're not straddling, or if our previous action was NOTHING
if ((x0 == x1 && y0 == y1) || lastAction == NOTHING)
{
switch (action)
{
// we allow toroidal actions
case N:
return (field[maze.stx(x0)][maze.sty(y0 - 1)] == 0);
case E:
return (field[maze.stx(x0 + 1)][maze.sty(y0)] == 0);
case S:
return (field[maze.stx(x0)][maze.sty(y0 + 1)] == 0);
case W:
return (field[maze.stx(x0 - 1)][maze.sty(y0)] == 0);
}
} // for other actions we're continuing to do what we did last time.
// assuming we're straddling, this should always be allowed unless our way is blocked
else if (action == lastAction)
{
switch (action)
{
// we allow toroidal actions
case N: // use y0
return (field[maze.stx(x0)][maze.sty(y0)] == 0);
case E: // use x1
return (field[maze.stx(x1)][maze.sty(y0)] == 0);
case S: // use y1
return (field[maze.stx(x0)][maze.sty(y1)] == 0);
case W: // use x0
return (field[maze.stx(x0)][maze.sty(y0)] == 0);
}
} // last there are reversal actions. Generally these are always allowed as well.
else if ((action == N && lastAction == S) ||
(action == S && lastAction == N) ||
(action == E && lastAction == W) ||
(action == W && lastAction == E))
{
return true;
}
return false;
}
I believe I need to use something like a BFS search to find the shortest path, I just have no idea how to do that.
Currently I have a game that I am building in Netbeans, and have been able to create a board, place the pieces and allow them to be moved anywhere using mouseveent's
But now I have ran into a problem when trying to code the pieces on the board to only do allowed actions.
The problem I am having is that every piece is still allowed to be moved but now when it is moved the selected piece disappears from the board completely ingorning all the new function in the mouse release event
The code I am trying to add is for the WhitePawn which is the only piece that should be allowed to move right now
The rest if they are tried to move should just return to there set positions regardless of where they are dragged. I have removed all code not relevant to the question and ran the debugger. From that I know a fact that the problem is somewhere in the mouse release event code, I just cant find it.
public void mouseReleased(MouseEvent e) {
if (chessPiece == null) {
return;
}
chessPiece.setVisible(false);
Boolean success = false;
Component c = chessBoard.findComponentAt(e.getX(), e.getY());
String tmp = chessPiece.getIcon().toString();
String pieceName = tmp.substring(0, (tmp.length() - 4));
Boolean validMove = false;
//Pawn Moves
//White Pawn
if (pieceName.equals("WhitePawn")) {
if (startY == 1) {
if ((startX == (e.getX() / 75)) && ((((e.getY() / 75) - startY) == 1) || ((e.getY() / 75) - startY) == 2)) {
if ((((e.getY() / 75) - startY) == 2)) {
if ((!piecePresent(e.getX(), (e.getY()))) && (!piecePresent(e.getX(), (e.getY() + 75)))) {
validMove = true;
} else {
validMove = false;
}
} else {
if ((!piecePresent(e.getX(), (e.getY())))) {
validMove = true;
} else {
validMove = false;
}
}
} else {
validMove = false;
}
} else {
int newY = e.getY() / 75;
int newX = e.getX() / 75;
if ((startX - 1 >= 0) || (startX + 1 <= 7)) {
if ((piecePresent(e.getX(), (e.getY()))) && ((((newX == (startX + 1) && (startX + 1 <= 7))) || ((newX == (startX - 1)) && (startX - 1 >= 0))))) {
if (checkWhiteOponent(e.getX(), e.getY())) {
validMove = true;
if (startY == 6) {
success = true;
}
} else {
validMove = false;
}
} else {
if (!piecePresent(e.getX(), (e.getY()))) {
if ((startX == (e.getX() / 75)) && ((e.getY() / 75) - startY) == 1) {
if (startY == 6) {
success = true;
}
validMove = true;
} else {
validMove = false;
}
} else {
validMove = false;
}
}
} else {
validMove = false;
}
}
}
if (!validMove) {
int location = 0;
if (startY == 0) {
location = startX;
} else {
location = (startY * 8) + startX;
}
String pieceLocation = pieceName + ".png";
pieces = new JLabel(new ImageIcon(getClass().getResource(pieceLocation)));
panels = (JPanel) chessBoard.getComponent(location);
panels.add(pieces);
} else {
if (success) {
int location = 56 + (e.getX() / 75);
if (c instanceof JLabel) {
Container parent = c.getParent();
parent.remove(0);
pieces = new JLabel(new ImageIcon(getClass().getResource("WhiteQueen.png")));
parent = (JPanel) chessBoard.getComponent(location);
parent.add(pieces);
} else {
Container parent = (Container) c;
pieces = new JLabel(new ImageIcon(getClass().getResource("WhiteQueen.png")));
parent = (JPanel) chessBoard.getComponent(location);
parent.add(pieces);
}
} else {
if (c instanceof JLabel) {
Container parent = c.getParent();
parent.remove(0);
parent.add(chessPiece);
} else {
Container parent = (Container) c;
parent.add(chessPiece);
}
chessPiece.setVisible(true);
}
}
}
Image showing the folder layout of My build in case I have you can see somewhere that is not linked probably
Hopefully someone can see where I am going wrong, as I just want to get one piece moving before I split the pieces away from the board.java file completely into a new java file
I've looked through some of your code, again there's too much for me to go through in its entirety, but please let me give you some suggestions.
This is brittle/dangerous code:
JLabel awaitingPiece = (JLabel) c1;
String tmp1 = awaitingPiece.getIcon().toString();
if (((tmp1.contains("White")))) {
You're using an object's toString() representation as part of your code logic which is something you should never do. You're also doing String manipulations on the String returned, and again using the returned String for code logic,
Component c = chessBoard.findComponentAt(e.getX(), e.getY());
String tmp = chessPiece.getIcon().toString();
String pieceName = tmp.substring(0, (tmp.length() - 4));
Boolean validMove = false;
again something that is dangerous to do.
Instead, you could get the Icon and compare for Icon equality via the equals(...) method. Even better though is to get your logic out of your GUI and into the Model section of your program. If you can fully separate concerns, you'll stand a much better chance of having smaller units of code that are much easier to debug for both you and for us.
Otherwise, to get a better more complete answer, you're still going to want to first work to isolate the error, and for that, I still recommend that you use an MCVE.
Also I see that you're checking if an Icon is named "WhitePawn"
chessPiece.setVisible(false);
Boolean success = false;
Component c = chessBoard.findComponentAt(e.getX(), e.getY());
String tmp = chessPiece.getIcon().toString();
String pieceName = tmp.substring(0, (tmp.length() - 4));
Boolean validMove = false;
//Pawn Moves
//White Pawn
if (pieceName.equals("WhitePawn")) {
When in actuality I'll bet that it's named something quite differently. Since your Strings are playing a key role in your program (too great a role, I fear) are you debugging your String values to see why the code doesn't work?
For instance, a few println's could do wonders:
chessPiece.setVisible(false);
Boolean success = false;
Component c = chessBoard.findComponentAt(e.getX(), e.getY());
String tmp = chessPiece.getIcon().toString();
String pieceName = tmp.substring(0, (tmp.length() - 4));
System.out.println("pieceName is: " + pieceName); // ******* Added ********
Boolean validMove = false;
Myself, I'd not use Strings for this but rather would use enums, something you know will be stable and will be exactly what you assume it to be.
#Override
public boolean onTouchEvent(MotionEvent event)
{
synchronized (getHolder())
{
int aktion = event.getAction();
if (aktion == MotionEvent.ACTION_DOWN)
{
touched = true;
bar.shareTouch(event.getX(), event.getY(), touched);
}
else if (aktion == MotionEvent.ACTION_UP)
{
touched = false;
bar.shareTouch(event.getX(), event.getY(), touched);
}
if (aktion == MotionEvent.ACTION_POINTER_DOWN)
{
touched2 = true;
bar.shareTouch2(event.getX(), event.getY(), touched2);
}
else if (aktion == MotionEvent.ACTION_POINTER_UP)
{
touched2 = false;
bar.shareTouch2(event.getX(), event.getY(), touched2);
}
}
return true;
}
This is a Code to chech if first Finger is going onto the screen or leaving it. The same for another finger.
public void shareTouch2(float xTouch2, float yTouch2, boolean touched2)
{
if (xTouch2 <= gameViewWidth/2) {
if (touched2 == true) {
touchedLeft2 = true;
}
else if(touched2 == false) {
touchedLeft2 = false;
}
}
else if (xTouch2 > gameViewWidth/2) {
if (touched2 == true) {
touchedRight2 = true;
}
else if(touched2 == false) {
touchedRight2 = false;
}
}
}
public void shareTouch(float xTouch, float yTouch, boolean touched)
{
if (xTouch <= gameViewWidth/2) {
if (touched == true) {
touchedLeft = true;
}
else if(touched == false) {
touchedLeft = false;
}
}
else if (xTouch > gameViewWidth/2) {
if (touched == true) {
touchedRight = true;
}
else if(touched == false) {
touchedRight = false;
}
}
}
private void moveRight()
{
x += 3;
}
private void moveLeft()
{
x -= 3;
}
private void checkTouch() {
if ((touchedLeft == true && touchedRight2 == false) || (touchedLeft2 == true && touchedRight == false)) {
moveLeft();
}
else if ((touchedLeft == false && touchedRight2 == true) || (touchedLeft2 == false && touchedRight == true)) {
moveRight();
}
else if ((touchedLeft == true && touchedRight2 == true) || (touchedLeft2 == true && touchedRight == true)) {
}
}
The checkTouch() is called in the onDraw() Method. Now if I place a finger on the right side of the screen it moves right. Same for left. But if I touch left and the right without removing the left finger the Object still moves left although it should stop. Now when I leave the left finger it still moves left although it should move right.
I hope you understand my problem.
Hope you can help
You can't just assume the ACTION_POINTER_UP Event will only be sent for the same finger ACTION_POINTER_DOWN was sent.
Just as the ACTION_DOWN event is always fired for the first finger to touch down, the ACTION_UP event is only fired for the last finger to lift (i.e. when there are no more fingers on the screen). All others will get an ACTION_POINTER_UP event, even if it's the finger that started the gesture.
However, the Android documentation does specify
Each pointer has a unique id that is assigned when it first goes down [and] remains valid until the pointer eventually goes up.
So in theory, your first and second finger should still have the same ID, regardless whether the Event that reports them.
The solution is simple, then: Use getPointerCount() and getPointerID() to keep track of your fingers.
This may be easier if you refactor your code to account for more than two fingers by replacing the Booleans touchedLeft and touchedLeft2 with a single counter, e.g. fingersOnLeftSide - which has the neat side effect of only needing one shareTouch() method and otherwise reducing redundancy in your code.
EDIT:
Disclaimer: This is just off the top of my head, untested and written without knowledge of any of your code other than what you posted. Not necessarily the best way to solve your problem, but the shortest I could think of.
This is the Event handler:
public boolean onTouchEvent(MotionEvent event)
{
synchronized (getHolder())
{
int aktion = event.getAction();
if (aktion == MotionEvent.ACTION_DOWN || aktion == MotionEvent.ACTION_POINTER_DOWN
|| aktion == MotionEvent.ACTION_UP || aktion == MotionEvent.ACTION_POINTER_UP)
{
bar.clearTouches();
for (int i = 0; i < event.getPointerCount(); i++) {
bar.shareTouch(event.getX(i)); // we don't need the y coordinate anyway
}
}
}
return true;
}
The rewritten shareTouch() to go along with it, as well as clearTouches() I introduced to make this simpler:
private void shareTouch(float x)
{
if (x < gameViewWidth/2) {
fingersLeft++;
} else {
fingersRight++;
}
}
private void clearTouches()
{
fingersLeft = 0;
fingersRight = 0;
}
And finally, the new checkTouch():
public void checkTouch()
{
if (fingersLeft > fingersRight) {
moveLeft();
} else if (fingersRight > fingersLeft) {
moveRight();
}
}
Im doing a pacman game. The following code is for ghosts movement and it works correctly. But I have to include a another check. The problem is that I always ruin the logic.
Current code:
public void moveGhost(Tiles target) {
if(specialIntersections()){
direction = direction; //keeps going in the same direction
}
else{
int oppDir;
if(direction == UP){
oppDir = DOWN;
}
else if(direction == DOWN){
oppDir = UP;
}
else if(direction == LEFT){
oppDir = RIGHT;
}
else{
oppDir=LEFT;
}
double minDist = 10000.0;
Tiles potentialNext;
for(int i=0; i<4; i++){
if(i!=oppDir){
potentialNext = maze.nextTile(getCurrentPos(), i);
if(!(potentialNext.wall()) && check(potentialNext)){
if(calculateDistance(target, potentialNext) < minDist){
minDist = calculateDistance(target, potentialNext);
futureDirection = i;
}
}
}
}
}
changeDirection();
timer++;
increment();
x += xinc;
y += yinc;
tunnel();
}
Another check I need to include:
//if the door is a wall (closed) the object cannot go through it
if(DoorIsWall()){
if(!(potentialNext.wall()) && !(potentialNext.door()) && check(potentialNext)){
I generally write a new method when my conditions start to get unruly:
if (isTileValid(potentialNext)) {
// do stuff
}
private boolean isTileValid(TileObject someTile) {
if (someTile.wall()) {
return false;
}
if (someTile.door()) {
return false;
}
if (! check(someTile)) {
return false;
}
return true;
}