Java Tetris - Confused on grid[row][col] and coordinates (x, y) - java

I'm making Tetris in java for fun... I pretty much had everything working... but later found out that when I wanted to change the dimensions so it was square ([10 row][10 col] matrix, but instead a [12 row][10 col] matrix), that I started getting Index Out of Bound exceptions... see here: Java Tetris - weird row clearing issue
So I tried fixing everything so that the rows and columns weren't flip flopped... But am now getting hung up on the fact that the grid takes [row][col], but I’m moving around the tiles as (x, y) coordinates…
What’s confusing me is that row = y and col = x… which is reversed… so when I pass in coordinates I’m not sure when to swap them.
I know it’s a simple thing, but it’s confusing the hell out of me and I keep getting out of bounds exceptions whenever I think I have it right.
I'm not sure where the exact issue is, so I'm posting a full Sscce of my program... I think the issue is in the Board class...
Here, the block should still be able to move down... but if it tries to go down further than this...
I get:
Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: 10
at Board.getTileAt(Board.java:177)
at Tile.collision(Tile.java:31)
at Piece.isCollision(Piece.java:172)
at Board.collisionCheck(Board.java:192)
at Piece.movePieceCheck(Piece.java:87)
at Board.keyPressed(Board.java:160)
Sscce:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Toolkit;
import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class MainSscce extends JPanel {
static MainSscce runMe;
BoardSscce gameBoard, scoreBoard;
public MainSscce() { //creates a new frame window and sets properties
JFrame f = new JFrame("Tetris");
//width (height), length, tilesize
gameBoard = new BoardSscce(12, 10, 35);
// scoreBoard = new BoardSscce(10, 10, 35);
f.add(gameBoard);
f.setSize(gameBoard.getWidth(), gameBoard.getHeight());
f.setVisible(true);
f.setResizable(false);
f.setVisible(true);
f.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
Dimension screensize = Toolkit.getDefaultToolkit().getScreenSize();
//set j frame location to appear in middle of screen
f.setLocation( (screensize.width - f.getWidth())/2,
(screensize.height - f.getHeight())/2-100 );
}
public static void main(String[] args) {
runMe = new MainSscce();
}
}
import java.awt.Graphics;
import java.awt.Color;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JPanel;
import javax.swing.Timer;
import java.awt.event.*; // for ActionListener and ActionEvent
import java.util.Random;
public class BoardSscce extends JPanel implements KeyListener {
private TileSscce grid[][];
private int totalRows, totalCols, tilesize, level, totalScore;
private final int changeLevelMultiplier;
private PieceSscce newPiece, nextPiece;
private String randomPiece;
private boolean gameLost;
public BoardSscce(int r, int c, int ts) {
totalRows = r;
totalCols = c;
tilesize = ts;
//set grid size to [# rows][# columns], aka [height][width]
grid = new TileSscce[totalRows][totalCols];
gameLost = false;
System.out.println("TotalRows: " + totalRows + ", " + "TotalCols: " + totalCols);
//multiplier to determine what score the level changes, which is:
//level * changeLevelMultiplier;
changeLevelMultiplier = 40;
//initialize score to 0
totalScore = 0;
//initialize level to 0
level = 0;
newPiece = new PieceSscce(this, randomPiece(), getColor());
addKeyListener(this);
setFocusable(true);
//getTranspose();
timer();
}
public String randomPiece() {
String[] Pieces = {"L", "O", "Z", "RevZ", "Bar", "T", "RevL"};
int rand = (int) (Math.random() * Pieces.length);
randomPiece = Pieces[rand];
return randomPiece;
}
public Color getColor() {
Color color;
if (randomPiece.equals("L"))
color = new Color(17, 255, 0);
else if(randomPiece.equals("O"))
color = new Color(117, 168, 255);
else if(randomPiece.equals("Z"))
color = new Color(255, 187, 82);
else if(randomPiece.equals("RevZ"))
color = new Color(206, 27, 72);
else if(randomPiece.equals("Bar"))
color = new Color(50, 216, 219);
else if(randomPiece.equals("T"))
color = new Color(252, 148, 240);
else
color = new Color(255, 255, 52);
//Random rand = new Random();
//float r = rand.nextFloat();
//float g = rand.nextFloat();
//float b = rand.nextFloat();
//Color randomColor = new Color(r, g, b);
return color;
}
//dimensions of board = width * tilesize
public int getWidth() {
return totalCols * tilesize;
}
public int getHeight() {
return totalRows * tilesize;
}
public int getTileSize() {
return tilesize;
}
public void paintComponent(Graphics g) {
g.setColor(Color.black);
g.fillRect(0, 0, getWidth(), getHeight());
for(int row = 0; row < grid.length; row++) {
for(int col = 0; col < grid[row].length; col++) {
//System.out.println(row + ", " + col);
g.drawString("[" + row + "][" + col + "]", col * tilesize, row * tilesize+10);
System.out.println(row + ", " + col);
//if there is a non-null space, that is a Tetris piece... fill it
if(grid[row][col] != null) {
g.setColor(grid[row][col].getColor());
g.fillRect(row * tilesize, col * tilesize, tilesize, tilesize);
g.setColor(Color.WHITE);
}
}
}
// g.drawString("Level: " + level, this.getWidth()/2, this.getHeight()/2-130);
// g.drawString("Score: " + totalScore, this.getWidth()/2, this.getHeight()/2-100);
if (gameLost == true) {
g.drawString("Way to go, loser...", this.getWidth()/2, this.getHeight()/2);
messageTimer();
}
}
//Auto move piece
public void timer () {
int interval;
switch (level) {
//each level increases drop speed by .10 seconds
case 1: interval = 800;
break;
case 2: interval = 700;
break;
case 3: interval = 600;
break;
case 4: interval = 500;
break;
default: interval = 1000;
break;
}
Timer t = new Timer(interval, new ActionListener() {
public void actionPerformed(ActionEvent e) {
//newPiece.autoMove();
//repaint();
}
});
t.start();
}
public void messageTimer() {
Timer t = new Timer(5000, new ActionListener() {
public void actionPerformed(ActionEvent e) {
gameLost = false;
}
});
t.start();
}
//move piece on key input
public void keyPressed(KeyEvent e) {
newPiece.movePieceCheck(e.getKeyCode());
repaint();
}
public void keyReleased(KeyEvent e) {
}
public void keyTyped(KeyEvent e) {
}
public boolean isValidCoordinate(int x, int y) {
return x >= 0 && y >= 0 && x < totalCols && y < totalRows;
}
// returns the tile at (x, y) or null if empty
public Tile getTileAt(int x, int y) {
if(isValidCoordinate(x, y))
return grid[x][y];
return null;
}
// sets the tile at (x, y) to tile
public void setTileAt(Tile tile, int x, int y) {
if(isValidCoordinate(x, y))
grid[x][y] = tile;
}
public boolean isOpen(int x, int y) {
return isValidCoordinate(x, y) && (getTileAt(x, y) == null);
}
public void collisionCheck() {
if (newPiece.isCollision()){
newPiece = new PieceSscce(this, randomPiece(), getColor());
}
}
public void changeLevel () {
int max = (level+1)*changeLevelMultiplier;
if (totalScore >= max) {
System.out.println(max + "reached... next level");
level++;
totalScore = 0;
timer();
}
}
public int tallyScore(int totalLines) {
int score = 0;
switch (totalLines) {
case 1: score = 40 * (level + 1);
break;
case 2: score = 100 * (level + 1);
break;
case 3: score = 300 * (level + 1);
break;
case 4: score = 1200 * (level + 1);
break;
default: break;
}
return score;
}
//loop through all rows starting at bottom (12 rows)
public void checkBottomFull() {
int lines = 0;
for(int row = 12; row > 0; row--) {
/* while (isFull(row)) {
lines++;
// clearRow(row);
}*/
}
totalScore += tallyScore(lines);
//check if level needs to be changed based on current score...
changeLevel();
//reset lines after score has been incremented
lines=0;
}
//loop through all columns in that row (10 columns)
public boolean isFull(int row) {
for (int col = 0; col <= 10; col++) {
System.out.println(row + ", " + col);
if(grid[row][col] == null) {
return false;
}
}
return true;
}
public void clearRow(int rowToClear) {
for(int row = rowToClear; row > 0; row--) {
for(int col = 0; col < grid[row].length; col++) {
grid[col][row] = grid[col][row-1];
}
}
}
public void checkEndGame(int x, int y) {
//if currPiece y location = 0 AND the space below is filled...
if (y <= 2 && !isOpen(x, y+1)) {
gameLost = true;
level = 0;
totalScore = 0;
//reset timer
timer();
for(int row = 0; row < grid.length; row++) {
for(int col = 0; col < grid[row].length; col++) {
grid[row][col] = null;
}
}
}
}
}
import java.awt.Color;
import java.awt.event.KeyEvent;
public class PieceSscce {
public int[] pieceCoordinates;
public String shape, currRotation;
public Color color;
public BoardSscce board;
public int rotationsCounter;
public TileSscce tile[];
public int[] newPositionX, newPositionY, currPositionX, currPositionY;
//don't need to pass in board because I'm already utilizing the Tiles class, which knows about the board
public Piece(Board b, String randomPiece, Color randomColor) {
shape = randomPiece;
color = randomColor;
board = b;
newPositionX = new int[4];
newPositionY = new int[4];
currPositionX = new int[4];
currPositionY = new int[4];
pieceCoordinates = new int[8];
//set pieceCoordinates global variable
getShape(shape);
tile = new TileSscce[4];
int counterX = 0, counterY = 1;
System.out.print("\"" + shape + "\" Coordinates: ");
//generate 4 new Tiles at specified coordinates that will compose the Piece
for (int i = 0; i < tile.length; i++) {
tile[i] = new TileSscce(board, pieceCoordinates[counterX], pieceCoordinates[counterY]);
System.out.print("(" + pieceCoordinates[counterX] + ", " + pieceCoordinates[counterY] + ") ");
//increment by 2 because x,y values are next to each other in array
counterX+=2;
counterY+=2;
}
System.out.println("\n");
for (int i = 0; i < tile.length; i++) {
tile[i].setColor(color);
}
}
public void calcNewPosition(int newX, int newY, int currTile) {
newPositionX[currTile] = newX;
newPositionY[currTile] = newY;
}
public void clearCurrPosition() {
for (int i = 0; i < tile.length; i++) {
currPositionX[i] = tile[i].getX();
currPositionY[i] = tile[i].getY();
board.setTileAt(null, currPositionX[i], currPositionY[i]);
}
}
public void autoMove() {
for (int i = 0; i < tile.length; i++) {
calcNewPosition(tile[i].getX(), tile[i].getY()+1, i);
}
clearCurrPosition();
for (int i = 0; i < tile.length; i++) {
board.checkEndGame(tile[i].getX(), tile[i].getY());
System.out.println("Checking..." + tile[i].getX() + ", " + tile[i].getY());
}
board.checkBottomFull();
board.collisionCheck();
move();
}
public void movePieceCheck(int keycode) {
if (keycode == KeyEvent.VK_DOWN) {
for (int i = 0; i < tile.length; i++) {
calcNewPosition(tile[i].getX(), tile[i].getY()+1, i);
}
clearCurrPosition();
for (int i = 0; i < tile.length; i++) {
board.checkEndGame(tile[i].getX(), tile[i].getY());
System.out.println("Checking..." + tile[i].getX() + ", " + tile[i].getY());
}
board.checkBottomFull();
board.collisionCheck();
move();
}
if (keycode == KeyEvent.VK_RIGHT) {
for (int i = 0; i < tile.length; i++) {
calcNewPosition(tile[i].getX()+1, tile[i].getY(), i);
}
clearCurrPosition();
move();
}
if (keycode == KeyEvent.VK_LEFT) {
for (int i = 0; i < tile.length; i++) {
calcNewPosition(tile[i].getX()-1, tile[i].getY(), i);
}
clearCurrPosition();
move();
}
//rotate left
if (keycode == KeyEvent.VK_A) {
int[] rotatedCoords = calcRotation("left");
clearCurrPosition();
rotate(rotatedCoords, "left");
}
//rotate right
if (keycode == KeyEvent.VK_D) {
int[] rotatedCoords = calcRotation("right");
clearCurrPosition();
rotate(rotatedCoords, "right");
}
}
public boolean movePieceValid() {
boolean valid = true;
for (int i = 0; i < tile.length; i++) {
if(!tile[i].checkNewLocation(newPositionX[i], newPositionY[i]))
valid = false;
}
return valid;
}
public boolean validRotation(int[] rotatedCoordinates) {
boolean valid = true;
int counterX = 0, counterY = 1;
for (int i = 0; i < tile.length; i++) {
if(!tile[i].checkNewLocation(rotatedCoordinates[counterX], rotatedCoordinates[counterY]))
valid = false;
counterX +=2;
counterY +=2;
}
return valid;
}
public void move() {
if (movePieceValid()) {
for (int i = 0; i < tile.length; i++) {
tile[i].setLocation(newPositionX[i], newPositionY[i]);
}
} else {
for (int i = 0; i < tile.length; i++) {
tile[i].setLocation(currPositionX[i], currPositionY[i]);
}
}
}
public void rotate(int[] rotatedCoordinates, String rotation) {
int counterX = 0, counterY = 1;
if (validRotation(rotatedCoordinates)) {
for (int i = 0; i < tile.length; i++) {
tile[i].setLocation(rotatedCoordinates[counterX], rotatedCoordinates[counterY]);
counterX+=2;
counterY+=2;
}
//else, if not valid move set the original location
} else {
for (int i = 0; i < tile.length; i++) {
tile[i].setLocation(currPositionX[i], currPositionY[i]);
}
}
}
public boolean isCollision() {
boolean collision = false;
for (int i = 0; i < tile.length; i++) {
if(tile[i].collision(newPositionX[i], newPositionY[i])) {
collision = true;
}
}
return collision;
}
//calc curr coordinates, send them to getRotation... which will create new piece based on coords
public int[] calcRotation(String direction) {
for (int i = 0; i < tile.length; i++) {
currPositionX[i] = tile[i].getX();
currPositionY[i] = tile[i].getY();
System.out.println("Current position: (" + currPositionX[i] + "," + currPositionY[i]+")");
}
return getRotation(currPositionX, currPositionY, direction);
}
public int[] getRotation (int coordinatesX[], int coordinatesY[], String direction) {
int[] rotationDirection;
int[] coordinates = new int[8];
int[] origin = new int[2];
int[] newCoordinates = new int[8];
int[] resultCoordinates = new int[8];
int[] finalCoordinates = new int[8];
int vectorMatrix[][] = new int[2][4];
//set either R(90) or R(-90) rotation matrix values:
if (direction.equals("right")) {
rotationDirection = new int[] {0, -1, 1, 0};
}
else {
rotationDirection = new int[] {0, 1, -1, 0};
}
int counterX = 0, counterY = 1, x = 0;
while (counterY < coordinates.length) {
//add arrays coordinatesX and coordinatesY into a single array: coordinates
coordinates[counterX] = coordinatesX[x];
coordinates[counterY] = coordinatesY[x];
counterX+=2;
counterY+=2;
x++;
}
//set origin so it rotates around center...
if (shape.equals("RevZ")) {
origin[0] = coordinates[6];
origin[1] = coordinates[7];
}
else if (shape.equals("T")) {
origin[0] = coordinates[4];
origin[1] = coordinates[5];
}
else {
origin[0] = coordinates[2];
origin[1] = coordinates[3];
}
//subtract origin from vectors
System.out.println();
counterX = 0;
counterY = 1;
while (counterY < newCoordinates.length) {
//System.out.println(coordinates[counterX] + ", " + coordinates[counterY]);
newCoordinates[counterX] = coordinates[counterX] - origin[0];
newCoordinates[counterY] = coordinates[counterY] - origin[1];
System.out.println("Translated coordinates: (" + newCoordinates[counterX] + ", " + newCoordinates[counterY] + ")");
counterX+=2;
counterY+=2;
}
System.out.println();
System.out.println("vector matrix:");
//fill up vectorMatrix with coordinates
int k = 0;
for (int col = 0; col < 4; col++) {
for (int row = 0; row < 2; row++) {
vectorMatrix[row][col] = newCoordinates[k++];
}
}
//print vectorMatrix:
for (int i = 0; i < vectorMatrix.length; i++) {
System.out.print("[");
for (int j = 0; j < vectorMatrix[i].length; j++) {
System.out.print(vectorMatrix[i][j]);
}
System.out.println("]");
}
int rotationMatrix[][] = new int[2][2];
//fill up rotationMatrix
System.out.println();
System.out.println("multiplicative matrix:");
k = 0;
for (int row = 0; row < 2; row++) {
System.out.print("[");
for (int col = 0; col < 2; col++) {
rotationMatrix[row][col] = rotationDirection[k++];
System.out.print(rotationMatrix[row][col]);
}
System.out.println("]");
}
//perform matrix multiplication
int[][] result = multiplyMatrices(rotationMatrix, vectorMatrix);
//print resulting matrix
System.out.println();
System.out.println("result matrix:");
for (int i = 0; i < result.length; i++) {
System.out.print("[");
for (int j = 0; j < result[i].length; j++) {
System.out.print(result[i][j]);
}
System.out.println("]");
}
//load new matrix coordinates back into array
k = 0;
for (int col = 0; col < 4; col++) {
for (int row = 0; row < 2; row++) {
resultCoordinates[k] = result[row][col];
k++;
}
}
System.out.println();
System.out.println("result coordinates:");
counterX = 0;
counterY = 1;
while (counterY < resultCoordinates.length) {
finalCoordinates[counterX] = resultCoordinates[counterX] + origin[0];
finalCoordinates[counterY] = resultCoordinates[counterY] + origin[1];
System.out.print("("+finalCoordinates[counterX] + ", " + finalCoordinates[counterY]+")");
counterX+=2;
counterY+=2;
}
return finalCoordinates;
}
public int[][] multiplyMatrices(int rotationMatrix[][], int vectorMatrix[][]) {
int mA = rotationMatrix.length;
int nA = rotationMatrix[0].length;
int mB = vectorMatrix.length;
int nB = vectorMatrix[0].length;
if (nA != mB) throw new RuntimeException("Illegal matrix dimensions.");
int[][] C = new int[mA][nB];
for (int i = 0; i < mA; i++) {
for (int j = 0; j < nB; j++) {
for (int k = 0; k < nA; k++) {
C[i][j] += (rotationMatrix[i][k] * vectorMatrix[k][j]);
}
}
}
return C;
}
public int[] getShape(String shape) {
if (shape.equals("L")) {
//pieceCoordinates = new int[] {0, 1, 0, 2, 1, 2, 2, 2};
pieceCoordinates = new int[] {4, 0, 4, 1, 5, 1, 6, 1};
}
else if (shape.equals("O")) {
pieceCoordinates = new int[] {0, 1, 1, 1, 0, 2, 1, 2};
}
else if (shape.equals("Z")) {
pieceCoordinates = new int[] {0, 1, 1, 1, 1, 2, 2, 2};
}
else if (shape.equals("RevZ")) {
pieceCoordinates = new int[] {1, 1, 2, 1, 0, 2, 1, 2};
}
else if (shape.equals("Bar")) {
//pieceCoordinates = new int[] {0, 1, 1, 1, 2, 1, 3, 1};
pieceCoordinates = new int[] {0, 1, 1, 1, 2, 1, 3, 1};
}
else if (shape.equals("T")) {
pieceCoordinates = new int[] {1, 1, 0, 2, 1, 2, 2, 2};
}
else if (shape.equals("RevL")) {
pieceCoordinates = new int[] {0, 2, 1, 2, 2, 2, 2, 1};
}
return pieceCoordinates;
}
}
import java.awt.Color;
import java.util.Random;
public class TileSscce {
private BoardSscce board;
private int currX, currY;
private Color color;
public TileSscce(BoardSscce b, int x, int y) {
board = b;
//when Tile is instantiated, set its position
setLocation(x, y);
}
public int getX() {
return currX;
}
public int getY() {
return currY;
}
public boolean checkNewLocation(int newX, int newY) {
boolean newLocationOK = board.isOpen(newX, newY);
return newLocationOK;
}
public boolean collision(int newX, int newY) {
boolean collision = this.getY() == ((board.getHeight()/board.getTileSize()))-2 || board.getTileAt(newX, newY) != null;
return collision;
}
public void setLocation(int newX, int newY) {
// board.setTileAt(null, currX, currY);
currX = newX;
currY = newY;
board.setTileAt(this, currX, currY);
}
public Color getColor() {
return setColor(color);
}
public Color setColor(Color myColor) {
color = myColor;
return color;
}
}
Thanks!
EDIT----------
I've tried implementing both ValarDohaeris and Svend Hansen's suggestions... Now the block is moving right when I press down, up when I press left, and down when I press right...
It seems to have to do with these methods in Board class which get and set tile locations...
// returns the tile at (x, y) or null if empty
public Tile getTileAt(int row, int col) {
System.out.println("getTileAt: " + row + ", " + col);
if(isValidCoordinate(row, col))
return grid[row][col];
return null;
}
// sets the tile at (x, y) to tile
public void setTileAt(Tile tile, int row, int col) {
System.out.println("setTileAt: " + row + ", " + col);
if(isValidCoordinate(row, col))
grid[row][col] = tile;
}
And in Piece class... movements are defined as:
public void movePieceCheck(int keycode) {
if (keycode == KeyEvent.VK_DOWN) {
for (int i = 0; i < tile.length; i++) {
calcNewPosition(tile[i].getRow()+1, tile[i].getCol(), i);
}
clearCurrPosition();
for (int i = 0; i < tile.length; i++) {
board.checkEndGame(tile[i].getRow(), tile[i].getCol());
}
board.checkBottomFull();
if (isCollision()) board.createNewPiece();
move();
}
if (keycode == KeyEvent.VK_RIGHT) {
for (int i = 0; i < tile.length; i++) {
calcNewPosition(tile[i].getRow(), tile[i].getCol()+1, i);
}
clearCurrPosition();
move();
}
if (keycode == KeyEvent.VK_LEFT) {
for (int i = 0; i < tile.length; i++) {
calcNewPosition(tile[i].getRow(), tile[i].getCol()-1, i);
}
clearCurrPosition();
move();
}

You have
grid = new TileSscce[totalRows][totalCols];
So when you want to access grid[x][y], you should check
x >= 0 && y >= 0 && x < totalRows && y < totalCols
in isValidCoordinate(x, y).

Emm... Quite interesting question. So to find out where the problem(s) may be I'll try to analyze your code a little bit...
You paste stack trace as
Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: 10
at Board.getTileAt(Board.java:177)
...
and at the same time the getTileAt()
// returns the tile at (x, y) or null if empty
public Tile getTileAt(int row, int col) {
System.out.println("getTileAt: " + row + ", " + col);
if(isValidCoordinate(row, col))//isValidCoordinate()?
return grid[row][col];
return null;
}
public boolean isValidCoordinate(int x, int y) {
return x >= 0 && y >= 0 && x < totalCols && y < totalRows;
}
... so the isValidCoordinate method return terms as
x >= 0 && y >= 0 && x < totalCols && y < totalRows
...the method doesn't allow to avoid array out-of-bounds problems; Seems like you put wrong array element indexes.
A. As I can notice, you trying to put a classic math matrix on Java [][] arrays as
public void clearRow(int rowToClear) {
for(int row = rowToClear; row > 0; row--) {
for(int col = 0; col < grid[row].length; col++) {//<-- ?
grid[col][row] = grid[col][row-1];
}
}
}
... and here I must say that you should know that in [][] arrays x,y are backwards and it is y,x because :
y (or classic i) - sub-array index (vertical)
x (or classic j) - sub-array's element index (horizontal)
so you should use array index something this way grid[y][x] or grid[i][j]
As a useful tip, I recommend you to analyze your code for logic errors in this field...
B. According to your app screenshot as
... it seems like the x,y problem takes place here too because you trying to control y (vertical) coordinates but (in real) you control x (horizontal) coordinates only :S It is still because of the row,col instead of a classic Java (col,row or y,x) [][] array index positions.
C. And again concerning to the wrong directions...
...up when I press left, and down when I press right...
if (keycode == KeyEvent.VK_RIGHT) {
for (int i = 0; i < tile.length; i++) {
calcNewPosition(tile[i].getRow(), tile[i].getCol()+1, i);
}
clearCurrPosition();
move();
}
Here I'll try to analyze the event as (you press right but move down)...
OK... according to one of your tasks you need to move by x coordinate (horizontally) but look closer... you make tile[i].getCol()+1 so it is newY and, of course, it moves vertically :S In your case it really moves down because you make increment as y++ ...
public void calcNewPosition(int newX, int newY, int currTile) {
newPositionX[currTile] = newX;
newPositionY[currTile] = newY;
}
public void clearCurrPosition() {
for (int i = 0; i < tile.length; i++) {
currPositionX[i] = tile[i].getX();
currPositionY[i] = tile[i].getY();
board.setTileAt(null, currPositionX[i], currPositionY[i]);
}
}
public void move() {
if (movePieceValid()) {
for (int i = 0; i < tile.length; i++) {
tile[i].setLocation(newPositionX[i], newPositionY[i]);//<-- !
}
} else {
for (int i = 0; i < tile.length; i++) {
tile[i].setLocation(currPositionX[i], currPositionY[i]);
}
}
}
...as a conclusion, I may recommend to change code (move right) something this way...
if (keycode == KeyEvent.VK_RIGHT) {
for (int i = 0; i < tile.length; i++) {
calcNewPosition(tile[i].getRow()+1, tile[i].getCol(), i);
}
clearCurrPosition();
move();
}
I hope my tips will help you to figure out what to look closer. Anyway, if you have some additional information please do comment my answer
Report if that helped you

This is based on x corresponds to columns and y corresponds to rows.
However grid is indexed by [row][col].
TileSscce grid[][] = new TileSscce[totalRows][totalCols]; // 12 => totalRows, 10 => totalCols
public int getWidth() {
return totalCols * tilesize;
}
public int getHeight() {
return totalRows * tilesize;
}
Following changes (based on your initial code - Sscce: - without later edits) will get rid of the exception and allow drawing till bottom of the board.
public void paintComponent(Graphics g) {
for (int row = 0; row < grid.length; row++) {
for (int col = 0; col < grid[row].length; col++) {
if (grid[row][col] != null) {
g.setColor(grid[row][col].getColor());
g.fillRect(col * tilesize, row * tilesize, tilesize, tilesize); // changed, check below snippet from fillRect documentation
g.setColor(Color.WHITE);
}
}
}
}
public TileSscce getTileAt(int x, int y) {
if (isValidCoordinate(x, y))
return grid[y][x]; // changed to [y][x] as grid is indexed by [row][col]
return null;
}
public void setTileAt(TileSscce tile, int x, int y) {
if (isValidCoordinate(x, y))
grid[y][x] = tile; // changed to [y][x] as grid is indexed by [row][col]
}
From fillRect documentation.
public abstract void fillRect(int x, int y, int width, int height)
The left and right edges of the rectangle are at x and x + width - 1.
The top and bottom edges are at y and y + height - 1.
This is correct.
public boolean isValidCoordinate(int x, int y) {
return x >= 0 && y >= 0 && x < totalCols && y < totalRows;
}

Related

Rotating game in JPanel

I created a very simple shooting game utilizing JPanel as shown in the code below. I also wanted to experiment with rotating the game and trying it out. I have one issue, where the game I was able to successfully rotate the game but the dimension seems to cut out, and I have to set each position of the enemy and myself to the rotated position.
I was wondering if there was a way to rotate the result as a whole, instead of simply rotating the shape so that the position of the ship and the missiles would also rotate all at once.
Edited code: added three lives to the player and tried implementing heart image with BufferedImage.
public class game extends JFrame{
public game(){
}
public static void main(String[] args){
new game();
}
public class MyJPanel extends JPanel implements ActionListener, MouseListener,
MouseMotionListener,KeyListener
{
//variables for player
int my_x;
int player_width,player_height;
private int lives = 3;
int heart_width, heart_height;
//variables for player's missiles
int my_missile_x, my_missile_y;
int missile_flag;
public static final int MY_Y = 600;
//variables for enemies' missiles
int e_missile_flag[];
int e_missile_x[];
int e_missile_y[];
int e_missile_move[];
Image image,image2;
Timer timer;
private BufferedImage heart;
public MyJPanel(){
missile_flag = 0;
/*** initialize enemies' info ***/
ImageIcon icon2 = new ImageIcon("enemy.jpg");
image2 = icon2.getImage();
enemy_width = image2.getWidth(this);
enemy_height = image2.getHeight(this);
try {
heart = ImageIO.read(getClass().getResource("heart.jpg"));
}catch(IOException e) {
}
heart_width = heart.getWidth(this);
heart_height = heart.getHeight(this);
n = 14; //number of enemies
enemy_x = new int[n];
enemy_y = new int[n];
enemy_move = new int[n];
enemy_alive = new int[n];
int distance = 40;
e_missile_flag = new int[n];
e_missile_x = new int[n];
e_missile_y = new int[n];
e_missile_move = new int[n];
// place enemies in 7x2
for (int i = 0; i < 7; i++) {
enemy_x[i] = (enemy_width + distance) * i + 50;
enemy_y[i] = 50;
}
for (int i = 7; i < n; i++) {
enemy_x[i] = (enemy_width + distance) * (i - 5) + 50;
enemy_y[i] = 100;
}
for (int i = 0; i < n; i++) {
enemy_alive[i] = 1; //all alive
enemy_move[i] = -10; //moves to left
}
for (int i = 0; i < n; i++) {
e_missile_flag[i] = 0;
e_missile_x[i] = 0;
e_missile_y[i] = 0;
e_missile_move[i] = 7 + n%3;
}
/*** setup system ***/
setBackground(Color.black);
setFocusable(true);
addMouseListener(this);
addMouseMotionListener(this);
addKeyListener(this);
timer = new Timer(50, this);
timer.start();
}
private void updateEnemiesPosition(){
//update enemies' position
Dimension dim = getSize();
for (int i = 0; i < n; i++) {
enemy_x[i] += enemy_move[i];
if ((enemy_x[i] < 0) || (enemy_x[i] > (dim.width - enemy_width))) {
enemy_move[i] = -enemy_move[i];
}
}
}
private void updateMyPosition() {
if(my_x < 0) {
my_x = 800;
}
if(my_x > 800) {
my_x = 0;
}
}
private void activateMyMissile(){
//shoot a missile
if(missile_flag == 0){
my_missile_x = my_x + player_width / 2;
my_missile_y = MY_Y; //MY_Y=400
missile_flag = 1;
}
}
private void updateMyMissile(){
//update missile position if alive
if (missile_flag == 1) {
my_missile_y -= 15;
if (0 > my_missile_y) {
missile_flag = 0;
}
}
}
private void activateEnemiesMissile(){
//activate enemies' missile if enemy is alive and its missile is not alive
for(int i = 0; i < n; i++){
if (enemy_alive[i] == 1 && e_missile_flag[i] == 0) {
e_missile_x[i] = enemy_x[i] + enemy_width/2;
e_missile_y[i] = enemy_y[i];
e_missile_flag[i] = 1;
}
}
}
private void updateEnemiesMissile(){
//update enemies' missile position if alive
Dimension dim = getSize();
for(int i = 0; i < n; i++){
if (e_missile_flag[i] == 1) {
e_missile_y[i] += e_missile_move[i];
if (e_missile_y[i] > dim.height) {
e_missile_flag[i] = 0;
}
}
}
}
private void checkHitToEnemy(){
for(int i = 0; i < n; i++){
if(missile_flag == 1 && enemy_alive[i] == 1){
if(
my_missile_x > enemy_x[i] &&
my_missile_x < (enemy_x[i] + enemy_width) &&
my_missile_y > enemy_y[i] &&
my_missile_y < (enemy_y[i] + enemy_height)
){
//hit
missile_flag = 0;
enemy_alive[i] = 0;
}
}
}
}
private boolean checkClear(){
int cnt = 0;
for(int i = 0; i < n; i++){
if(enemy_alive[i] == 0) cnt++;
}
return (n == cnt);
}
if(lives>0) {
int x = 0;
int y = getHeight()- heart.getHeight();
for(int index = 0; index < lives; index++) {
g.drawImage(heart, x, y, this);
x += heart.getWidth();
}
}
g2d.dispose();
}
public void actionPerformed(ActionEvent e){
if (e.getSource() == timer) {
updateEnemiesPosition();
updateMyPosition();
updateMyMissile();
updateEnemiesMissile();
activateEnemiesMissile();
if(checkHitToPlayer()){
System.out.println("===== Game Over =====");
System.exit(0);
}
checkHitToEnemy();
if(checkClear()){
System.out.println("===== Game Clear =====");
System.exit(0);
}
repaint();
}
}
public void mouseClicked(MouseEvent me)
{ }
public void mousePressed(MouseEvent me)
{
activateMyMissile();
}
public void mouseReleased(MouseEvent me)
{ }
public void mouseExited(MouseEvent me)
{ }
public void mouseEntered(MouseEvent me)
{ }
public void mouseMoved(MouseEvent me)
{ }
public void mouseDragged(MouseEvent me)
{ }
public void keyReleased(KeyEvent e){
}
public void keyTyped(KeyEvent e){
}
}
}
The original size of the component is going to be less then 800x500 (I say less then, because the actual size will be 800x500 - the frame decorations - this is why you should be setting the size of the window directly).
When you rotate it 90 degrees, it becomes (less then) 500x800. So, no, there's no "easy" way to resolve this, without making the game square.
I added...
g2d.setColor(Color.DARK_GRAY);
g2d.fillRect(0, 0, getWidth(), getHeight());
after the rotation, which highlights the issue.
To do this, you should override getPreferredSize of the JPanel and the call pack on the frame. This will ensure that that game canvas is sized to it's preferred size and the window decorations are then packed around it.
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
public class Lec12 extends JFrame {
public Lec12() {
setTitle("Game Example");
setDefaultCloseOperation(EXIT_ON_CLOSE);
MyJPanel myJPanel = new MyJPanel();
Container c = getContentPane();
c.add(myJPanel);
pack();
setVisible(true);
}
public static void main(String[] args) {
new Lec12();
}
public class MyJPanel extends JPanel implements ActionListener, MouseListener,
MouseMotionListener, KeyListener {
//variables for player
int my_x;
int player_width, player_height;
//variables for enemies
int enemy_width, enemy_height;
int n;
int enemy_x[];
int enemy_y[];
int enemy_move[];
int enemy_alive[];
//variables for player's missiles
int my_missile_x, my_missile_y;
int missile_flag;
public static final int MY_Y = 400;
//variables for enemies' missiles
int e_missile_flag[];
int e_missile_x[];
int e_missile_y[];
int e_missile_move[];
Image image, image2;
Timer timer;
public MyJPanel() {
/**
* * initialize player's info **
*/
my_x = 250;
ImageIcon icon = new ImageIcon("player.jpg");
image = icon.getImage();
player_width = image.getWidth(this);
player_height = image.getHeight(this);
missile_flag = 0;
/**
* * initialize enemies' info **
*/
ImageIcon icon2 = new ImageIcon("enemy.jpg");
image2 = icon2.getImage();
enemy_width = image2.getWidth(this);
enemy_height = image2.getHeight(this);
n = 14; //number of enemies
enemy_x = new int[n];
enemy_y = new int[n];
enemy_move = new int[n];
enemy_alive = new int[n];
int distance = 40;
e_missile_flag = new int[n];
e_missile_x = new int[n];
e_missile_y = new int[n];
e_missile_move = new int[n];
// place enemies in 7x2
for (int i = 0; i < 7; i++) {
enemy_x[i] = (enemy_width + distance) * i + 50;
enemy_y[i] = 50;
}
for (int i = 7; i < n; i++) {
enemy_x[i] = (enemy_width + distance) * (i - 5) + 50;
enemy_y[i] = 100;
}
for (int i = 0; i < n; i++) {
enemy_alive[i] = 1; //all alive
enemy_move[i] = -10; //moves to left
}
for (int i = 0; i < n; i++) {
e_missile_flag[i] = 0;
e_missile_x[i] = 0;
e_missile_y[i] = 0;
e_missile_move[i] = 7 + n % 3;
}
/**
* * setup system **
*/
setBackground(Color.black);
setFocusable(true);
addMouseListener(this);
addMouseMotionListener(this);
addKeyListener(this);
timer = new Timer(50, this);
timer.start();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(800, 800);
}
private void updateEnemiesPosition() {
//update enemies' position
Dimension dim = getSize();
for (int i = 0; i < n; i++) {
enemy_x[i] += enemy_move[i];
if ((enemy_x[i] < 0) || (enemy_x[i] > (dim.width - enemy_width))) {
enemy_move[i] = -enemy_move[i];
}
}
}
private void updateMyPosition() {
if (my_x < 0) {
my_x = 800;
}
if (my_x > 800) {
my_x = 0;
}
}
private void activateMyMissile() {
//shoot a missile
if (missile_flag == 0) {
my_missile_x = my_x + player_width / 2;
my_missile_y = MY_Y; //MY_Y=400
missile_flag = 1;
}
}
private void updateMyMissile() {
//update missile position if alive
if (missile_flag == 1) {
my_missile_y -= 15;
if (0 > my_missile_y) {
missile_flag = 0;
}
}
}
private void activateEnemiesMissile() {
//activate enemies' missile if enemy is alive and its missile is not alive
for (int i = 0; i < n; i++) {
if (enemy_alive[i] == 1 && e_missile_flag[i] == 0) {
e_missile_x[i] = enemy_x[i] + enemy_width / 2;
e_missile_y[i] = enemy_y[i];
e_missile_flag[i] = 1;
}
}
}
private void updateEnemiesMissile() {
//update enemies' missile position if alive
Dimension dim = getSize();
for (int i = 0; i < n; i++) {
if (e_missile_flag[i] == 1) {
e_missile_y[i] += e_missile_move[i];
if (e_missile_y[i] > dim.height) {
e_missile_flag[i] = 0;
}
}
}
}
private void checkHitToEnemy() {
for (int i = 0; i < n; i++) {
if (missile_flag == 1 && enemy_alive[i] == 1) {
if (my_missile_x > enemy_x[i]
&& my_missile_x < (enemy_x[i] + enemy_width)
&& my_missile_y > enemy_y[i]
&& my_missile_y < (enemy_y[i] + enemy_height)) {
//hit
missile_flag = 0;
enemy_alive[i] = 0;
}
}
}
}
private boolean checkHitToPlayer() {
for (int i = 0; i < n; i++) {
if (e_missile_flag[i] == 1) {
if (e_missile_x[i] > my_x
&& e_missile_x[i] < (my_x + player_width)
&& e_missile_y[i] > MY_Y
&& e_missile_y[i] < (MY_Y + player_height)) {
e_missile_flag[i] = 0;
return true;
}
}
}
return false;
}
private boolean checkClear() {
int cnt = 0;
for (int i = 0; i < n; i++) {
if (enemy_alive[i] == 0) {
cnt++;
}
}
return (n == cnt);
}
public void paintComponent(Graphics g) {
super.paintComponent(g); //reset graphics
Graphics2D g2d = (Graphics2D) g.create();
System.out.println(getWidth() + "x" + getHeight());
int w2 = getWidth() / 2;
int h2 = getHeight() / 2;
g2d.rotate(-Math.PI / 2, w2, h2);
g2d.setColor(Color.DARK_GRAY);
g2d.fillRect(0, 0, getWidth(), getHeight());
//draw player
g2d.setColor(Color.BLUE);
g2d.fillRect(my_x, 400, 10, 10);
// g.drawImage(image, my_x, 400, this);
//draw enemies
for (int i = 0; i < n; i++) {
if (enemy_alive[i] == 1) {
g2d.setColor(Color.RED);
g2d.fillRect(enemy_x[i], enemy_y[i], 10, 10);
// g.drawImage(image2, enemy_x[i], enemy_y[i], this);
}
}
//draw players missiles
if (missile_flag == 1) {
g2d.setColor(Color.white);
g2d.fillRect(my_missile_x, my_missile_y, 2, 5);
}
//draw enemies' missiles
for (int i = 0; i < n; i++) {
if (e_missile_flag[i] == 1) {
g2d.setColor(Color.white);
g2d.fillRect(e_missile_x[i], e_missile_y[i], 2, 5);
}
}
g2d.dispose();
}
public void actionPerformed(ActionEvent e) {
if (e.getSource() == timer) {
updateEnemiesPosition();
updateMyPosition();
updateMyMissile();
updateEnemiesMissile();
activateEnemiesMissile();
if (checkHitToPlayer()) {
System.out.println("===== Game Over =====");
System.exit(0);
}
checkHitToEnemy();
if (checkClear()) {
System.out.println("===== Game Clear =====");
System.exit(0);
}
repaint();
}
}
public void mouseClicked(MouseEvent me) {
}
public void mousePressed(MouseEvent me) {
activateMyMissile();
}
public void mouseReleased(MouseEvent me) {
}
public void mouseExited(MouseEvent me) {
}
public void mouseEntered(MouseEvent me) {
}
public void mouseMoved(MouseEvent me) {
}
public void mouseDragged(MouseEvent me) {
}
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
switch (key) {
case KeyEvent.VK_S:
my_x = my_x + 10;
break;
case KeyEvent.VK_W:
my_x = my_x - 10;
break;
case KeyEvent.VK_DOWN:
my_x = my_x + 10;
break;
case KeyEvent.VK_UP:
my_x = my_x - 10;
break;
case KeyEvent.VK_X:
if (missile_flag == 0) {
my_missile_x = my_x + player_width / 2;
my_missile_y = MY_Y;// MY_Y=400
missile_flag = 1;
}
break;
}
}
public void keyReleased(KeyEvent e) {
}
public void keyTyped(KeyEvent e) {
}
}
}
Also, beware, transformations of this nature are accumulative. You should, instead, take a snapshot of the Graphics context and dispose of it once you're done (see the above for an example).
Also, have look at How to Use Key Bindings as it will help resolve the focus issues related to KeyListener

Keyboard Input Movement on Applet

I'm creating a very basic game using applet and I'm not sure how to write the code for the computer to register the arrows as movement (up, down, left, right).
How can I get the yellow Pacman looking character to move based on keyboard inputs?
This is my code:
import java.applet.*;
import java.awt.*;
public class GameShopRoofCashOut extends Applet
{
public void paint(Graphics g)
{
// Setup the board
int rows = 20;
int columns = 20;
int cellSize = 30;
int board [ ][ ] = new int [rows][columns];
int dirt = 12;
int lightstone = 13;
int darkstone = 17;
int slotx = 12;
int sloty = 0;
int linex = 30;
int liney = 390;
int layer = 0;
// Store objects in the board
board[11][4] = 7;
board[11][5] = 7;
board[10][14] = 8;
board[11][14] = 9;
board[0][19] = 10;
while (sloty<20)
{
while (slotx<20)
{
for (int r=0; r< board.length; r++)
{
for (int c=0; c< board[r].length; c++)
{
//store objects in the board
board[dirt][sloty] = 1;
board[lightstone][sloty] = 2;
board[darkstone][sloty]= 3;
if (lightstone<17)
{
lightstone++;
}
if (darkstone<19)
{
darkstone++;
}
// Draw the board
if (board [r][c] == 1)
{
g.setColor(Color.blue);
g.fillRect(c*cellSize,r*cellSize,cellSize,cellSize);
layer++;
}
if (board [r][c] == 2)
{
g.setColor(Color.lightGray);
g.fillRect(c*cellSize,r*cellSize,cellSize,cellSize);
layer++;
}
if (board [r][c] == 3)
{
g.setColor(Color.darkGray);
g.fillRect(c*cellSize,r*cellSize,cellSize,cellSize);
layer++;
}
if (board [r][c] == 7)
{
g.setColor(Color.magenta);
g.fillRect(c*cellSize,r*cellSize,cellSize,cellSize);
layer++;
}
if (board[r][c] == 8)
{
int x = c*cellSize;
int y = r*cellSize;
Polygon p = new Polygon();
p.addPoint(x+cellSize/2,y);
p.addPoint(x+cellSize, y+cellSize);
p.addPoint(x, y+cellSize);
p.addPoint(x+cellSize/2,y);
g.setColor(Color.orange);
g.fillPolygon(p);
}
if (board[r][c] == 9)
{
g.setColor(Color.orange);
g.fillRect(c*cellSize,r*cellSize,cellSize,cellSize);
}
if (board [r][c] == 10)
{
g.setColor(Color.yellow);
g.fillArc(c*cellSize,r*cellSize,cellSize,cellSize,30,300);
}
}
}
slotx++;
}
lightstone = 13;
darkstone = 17;
slotx=12;
sloty++;
}
g.setColor(Color.black);
g.drawString("Shop",420,295);
g.drawString("Cash Out",120,320);
while (linex<600)
{
g.setColor(Color.black);
g.drawLine(linex,360,linex,600);
g.drawLine(0,liney,600,liney);
linex+=30;
liney+=30;
}
}
}

My sorting algorithms are only going through once

I am writing a program that sorts 2 arrays of the same values by using two different algorithms. It loops through the arrays once each time a button is clicked. My problem is that it only sorts the first time you click the button. Every other time nothing happens. I put a count incrementer to see if the code was running and it was. I'm stumped. Any help will be appreciated.
I fixed the selection sort.
public class TwoSortsPanel extends JPanel
{
private int width = 10, gap = 3, x = 200, y = 50;
private int[] ranArr1 = new int[15], ranArr2 = new int[15];
private Color blue = Color.blue, red = Color.red, pink = Color.pink, gray = Color.gray;
public static int count = 0, indexSel = 0;
{
for(int i = 0; i < ranArr1.length-1; i++)
{
ranArr1[i] = (int) (Math.random() * 15);
ranArr2[i] = ranArr1[i];
}
}
public TwoSortsPanel()
{
printArray(ranArr1);
setBackground(pink);
setPreferredSize (new Dimension (400,300));
JButton sort = new JButton ("Sort");
sort.addActionListener(new ButtonListener());
add (sort);
}
public static void printArray(int[] c)
{
System.out.println(Arrays.toString(c));
}
public void paintComponent (Graphics page)
{
super.paintComponent(page);
page.drawString("" + count, 10, 12);
if (insertion() == false || selection() == false)
{
int yPlus = 50;
for(int i = 0; i < ranArr1.length; i++)
{
page.setColor(blue);
page.fillRect(x, yPlus, ranArr1[i]*10, width);
yPlus += width + gap;
}
yPlus = 50;
for(int i = 0; i < ranArr2.length; i++)
{
page.setColor(red);
page.fillRect(x, yPlus, -ranArr2[i]*10, width);
yPlus += width + gap;
}
}
else
{
int yPlus = 50;
for(int i = 0; i < ranArr1.length; i++)
{
page.setColor(gray);
page.fillRect(x, yPlus, ranArr1[i]*10, width);
yPlus += width + gap;
}
yPlus = 50;
for(int i = 0; i < ranArr2.length; i++)
{
page.setColor(gray);
page.fillRect(x, yPlus, -ranArr2[i]*10, width);
yPlus += width + gap;
}
}
}
private class ButtonListener implements ActionListener
{
public void actionPerformed (ActionEvent e)
{
displaySelection(ranArr1);
displayInsertion(ranArr2);
count++;
printArray(ranArr1);
repaint();
}
}
public static void displaySelection(int[] a)
{
int temp;
int min = indexSel;
for (int scan = indexSel+1; scan < a.length ; scan++)
if (a[scan] < a[min])
min = scan;
temp = a[min];
a[min] = a[indexSel];
a[indexSel] = temp;
count++;
indexSel++;
}
public static void displayInsertion(int[] b)
{
int index = 1;
int key = b[index];
int position = index;
while (position > 0 && b[position-1] > key )
{
b[position] = b[position-1];
position--;
}
b[position] = key;
}
public boolean selection()
{
for (int i = 0; i < ranArr1.length-1; i++)
{
if(ranArr1[i] > ranArr1[i+1])
{
return false;
}
}
return true;
}
public boolean insertion()
{
for (int i = 0; i < ranArr2.length-1; i++)
{
if(ranArr2[i] > ranArr2[i+1])
{
return false;
}
}
return true;
}
}
Sorry. I didn't want the post to look too busy and I guess it lost meaning.

2D Collision Detection

I'm creating a tile-based 2D Game in Java. Everything was fine, but I got stuck in Collision Detection. I tried this method for up collision:
public boolean getCollision(Entity en) {
try {
Rectangle i = new Rectangle(en.x, en.y, en.width, en.height);
for (int y = 0; y < image.getHeight(); y++) {
for (int x = 0; x < image.getWidth(); x++) {
if (rect[x][y] != null && tile[x][y] != null && rect[x][y].intersects(i))
return true;
}
}
} catch (ArrayIndexOutOfBoundsException e) {
}
return false;
}
It worked, but the player gets stuck. How can I fix it?
Code details:
rect is a java.awt.Rectangle[][] that represents invisible rectangles based on the tiles. It is initialized like:
for (int y = 0; y < myLevelHeight; y++) {
for (int x = 0; x < myLevelWidth; x++) {
if (rect[x][y] == null)
rect[x][y] = new Rectangle(x * myGameTileSize, y * myGameTileSize, myGameTileSize, myGameTileSize);
}
}
Entity class just holds the x and the y coordinate, width and height, of an entity.
image.getWidth() and image.getHeight() are the tile-level width/height.
Can anyone fix this collision, and create the down, left and right or create one method for that?
EDIT: A MCVE, I tried to decrease the code has much I could, but you should get the idea.
package com.game.lost;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.image.BufferStrategy;
import javax.swing.JFrame;
public class Demo extends Canvas implements Runnable {
public int tileSize = 16;
public static final int width = 400, height = 400;
public JFrame frame = new JFrame();
public int levelWidth = width / tileSize + 1, levelHeight = height / tileSize + 1;
public Color[][] tiles = new Color[levelWidth][levelHeight];
public Rectangle[][] rect = new Rectangle[levelWidth][levelHeight];
private Thread thread;
private boolean running = false;
private int x = tileSize * 10, y = tileSize * 10;
private boolean up, down = true, left, right;
public void genLevel() {
tiles[10][20] = new Color(0, 0, 0);
tiles[0][19] = new Color(0, 0, 0);
}
public void update() {
for (int y = 0; y < levelHeight; y++) {
for (int x = 0; x < levelWidth; x++) {
if (rect[x][y] == null)
rect[x][y] = new Rectangle(x * tileSize, y * tileSize, tileSize, tileSize);
else if (rect[x][y] != null)
rect[x][y].setBounds(x * tileSize, y * tileSize, tileSize, tileSize);
}
}
if (!getDownCollision() && down)
y += 2;
else if (getDownCollision() || up) {
up = true;
if (!getLeftCollision())
x -= 2;
else {
up = false;
tiles[0][19] = new Color(255, 0, 0);
}
tiles[10][20] = new Color(255, 0, 0);
down = false;
}
}
public void render() {
BufferStrategy bs = getBufferStrategy();
if (bs == null) {
createBufferStrategy(2);
return;
}
Graphics g = bs.getDrawGraphics();
g.setColor(Color.white);
g.fillRect(0, 0, width, height);
g.setColor(Color.red);
g.fillRect(x, y, tileSize, tileSize);
for (int y = 0; y < tiles[0].length; y++) {
for (int x = 0; x < tiles.length; x++) {
if (tiles[x][y] != null) {
g.setColor(tiles[x][y]);
g.fillRect(rect[x][y].x, rect[x][y].y, rect[x][y].width, rect[x][y].height);
}
}
}
g.dispose();
bs.show();
}
public void start() {
genLevel();
running = true;
thread = new Thread(this);
thread.start();
}
public void run() {
while (running) {
update();
render();
try {
Thread.sleep(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public boolean getUpCollision() {
try {
Point p1 = new Point(x, y);
for (int y = 0; y < levelHeight; y++) {
for (int x = 0; x < levelWidth; x++) {
if (rect[x][y - 1] != null && tiles[x][y - 1] != null && rect[x][y - 1].contains(p1))
return true;
}
}
} catch (ArrayIndexOutOfBoundsException e) {
}
return false;
}
public boolean getDownCollision() {
try {
Point p1 = new Point(x, y + tileSize);
for (int y = 0; y < levelHeight; y++) {
for (int x = 0; x < levelWidth; x++) {
if (rect[x][y + 1] != null && tiles[x][y + 1] != null && rect[x][y + 1].contains(p1))
return true;
}
}
} catch (ArrayIndexOutOfBoundsException e) {
}
return false;
}
public boolean getLeftCollision() {
try {
Point p1 = new Point(x, y);
for (int y = 0; y < levelHeight; y++) {
for (int x = 0; x < levelWidth; x++) {
if (rect[x][y - 1] != null && tiles[x][y - 1] != null && rect[x][y - 1].contains(p1))
return true;
}
}
} catch (ArrayIndexOutOfBoundsException e) {
}
return false;
}
public boolean getRightCollision() {
try {
Point p1 = new Point(x + tileSize, y);
for (int y = 0; y < levelHeight; y++) {
for (int x = 0; x < levelWidth; x++) {
if (rect[x][y + 1] != null && tiles[x][y + 1] != null && rect[x][y + 1].contains(p1))
return true;
}
}
} catch (ArrayIndexOutOfBoundsException e) {
}
return false;
}
public static void main(String[] args) {
Demo demo = new Demo();
demo.frame.setResizable(false);
demo.frame.add(demo);
demo.frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
demo.frame.setSize(width, height);
demo.frame.setLocationRelativeTo(null);
demo.frame.setTitle("Demo");
demo.frame.setVisible(true);
demo.start();
}
}
PS: I think that these informations are what you need to create collision, but
if you need more information to create the collision please ask in the comments.
Thanks

twosorts is only giving me an issue

it keeps making the selection sort off by at least 1,
it sorts the insertion sort fine,
but it seems like the selection sort needs more time,
i cant figure it out...
its not doing a proper sort of the selection sort method.i think that my error is either in the reorderselection method.
import java.awt.*;
import java.applet.*;
import java.awt.event.*;
import java.util.Random;
public class TwoSorts extends Applet {
private final int APPLET_WIDTH = 800, APPLET_HEIGHT = 600; // to make the applet size
private final int colNum = 15; // how many columns
int[] insertion = new int[colNum]; //insertion array for column heights
int[] selection = new int[colNum]; // selection array for column heights
public Random generator; // random numbers class
public int randomNum; // random number
public Button butn1 = new Button("Sort Arrays"); // buttons
public int selectionCount = 0; // how many times press the sort button
boolean selectionFlag, insertionFlag; // to stop looping when done
//**********************************************************************
//* initiates everything
//**********************************************************************
public void init()
{
setBackground (Color.black);
setSize(APPLET_WIDTH, APPLET_HEIGHT);
generator = new Random();
for (int column = 0; column < colNum; column++) // Creates the two arrays
{
randomNum = generator.nextInt(100) + 15;
insertion[column] = randomNum;
selection[column] = randomNum;
}
butn1.addActionListener(new Butn1Handler());
butn1.setBackground(Color.blue);
add(butn1);
}
//*************************************************************************
// Draws the columns
//************************************************************************
public void paint(Graphics g)
{
g.setColor(Color.white); // debugging code
g.drawString ("Count: " + selectionCount, 100, 495);
g.drawString("Selection Sort", 25, 220);
g.drawString("Insertion Sort", 25, 420);
int xs = 50, ys = 100, width = 40, heights = 0; // for the loops
int xi = 50, yi = 300, heighti = 0;
if ( insertionFlag == false && selectionFlag == false)
{
for (int count = 0; count < colNum + 1; count++ )
{
g.setColor(Color.green);
heights = selection[count];
heighti = insertion[count];
g.fillRect(xs, ys, width, heights);
g.fillRect(xi, yi, width, heighti);
xs = xs + width + 2;
xi = xi + width + 2;
}
}
else
{
g.setColor(Color.white);
g.drawString ("Sort is Done!", 5, 495);
for (int count = 0; count < colNum + 1; count++ )
{
g.setColor(Color.gray);
heights = selection[count];
heighti = insertion[count];
g.fillRect(xs, ys, width, heights);
g.fillRect(xi, yi, width, heighti);
xs = xs + width + 2;
xi = xi + width + 2;
}
}
}
//*****************************************************************************
//* Method to sort the array by Selection method
//******************************************************************************
public void reorderSelection()
{
int min = selectionCount;
int temp = 0;
for (int scan = (selectionCount); scan < selection.length; scan++)
{
if (selection[scan] < selection[min])
min = scan;
temp = selection[min];
selection[min] = selection[selectionCount];
selection[selectionCount] = temp;
}
}
//*****************************************************************************
//* Method to sort the arrary by Insertion method
//******************************************************************************
public void reorderInsertion()
{
int key = insertion[selectionCount];
int position = selectionCount;
while (position > 0 && key < (insertion[position-1]))
{
insertion[position] = insertion[position-1];
position--;
}
insertion[position] = key;
}
//-----------------------------------------------------
// Button 1 Listener and instructions
//-----------------------------------------------------
public class Butn1Handler implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
reorderSelection();
reorderInsertion();
repaint();
selectionCount++;
if (selectionCount > 14)
selectionFlag = true;
if (selectionCount > 15)
insertionFlag = true;
}
}
}
Your selection sort method is incorrect. You need an inner loop.
public void reorderSelection()
{
int min = selectionCount;
int temp = 0;
for( int scan = selectionCount ; scan < selection.length - 1 ; scan++ )
{
min = scan;
for(int i = scan + 1; i < selection.length ; i++)
{
if(selection[min] > selection[i]) min = i;
}
if(min != scan)
{
temp = selection[scan];
selection[scan] = selection[min];
selection[min] = temp;
}
}
}

Categories

Resources