Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
So I am making a simple tic tac toe game and ran into a problem at the last minute
I am trying to draw a line at the win location but on the final win location(index), the line gets hidden behind the JButton not entirly sure why it is doing this.
I know alot of people say do not use getGraphics(), and I am wondering if that is the source of my issues they say to override the paintComponent method but that is not working for me either
I have attached a pic of what the result is looking like and code snips of how I am trying to perform these actions
PS I am using a JFrame, if any more code is needed I will be glad to show it
if(win[i] == 264){ // if one of the the combinations equal 'X','X','X' which equals 264, then there is a winner
System.out.println("X is the winner!!!");
System.out.println("Game Over!");
number = i;
draw(); }// call draw method
private void draw(){ // drawing a line at winning location
Graphics2D g1 = (Graphics2D) GUI.getFrame().getGraphics(); // declaring graphics on our Jframe
Stroke stroke3 = new BasicStroke(12f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_MITER); // make our strokes cap off round
if(number == 0){ // statements will determine the win location, so at win0, XXX,
g1.setStroke(stroke3); // we will add stroke to our line
g1.drawLine(0,104,500,104); // draw the line starting at the 0,104 and end it at coordinates 500,104
}
here is a more runnable code, it is alot though
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.Stroke;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.ButtonModel;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.border.Border;
import javax.swing.border.LineBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class tic implements Runnable {
final static int row = 3; // our rows
final static int col = 3; // our col
final static int sizeOfBoard = row * col;
// the size of our board is not going to change so we make it final
static JButton[] clickButton;
char[] templateOfBoard; // our board, TicTacToe field, static
char userTurn; // users turn , only one letter, tracks whether it is a X or O
int count; // keeps track of user moves
static JFrame frame; // our JFrame
int number;
public tic(JFrame frame) {
tic.frame = new JFrame("TicTacToe GAME");
clickButton = new JButton[9];
count = 0; // number of turns starts at 0;
number = 0;
setUserTurn('X'); // first turn will always be X
setTemplateOfBoard(new char[sizeOfBoard]); // size of the board we are going to make it
try{
for(int spaces=0; spaces<sizeOfBoard; spaces++){ // size of Board is in the GUI class
getTemplateOfBoard()[spaces] = ' '; // the board is being created, looping through all rows and col
//every index of the board not has a char value equal to a space
//determine if everything came out correctly
//should equal of a total of 9
// 3x3
}
System.out.println("Board template created"); // means the board now has all spaces
}
catch(Exception e){
System.out.println("Could not initalize the board to empty char");
e.printStackTrace();
}
}
public static void main(String[] args){
try{
SwingUtilities.invokeLater(new tic(frame)); // run
}
catch(Exception e){ // wanted to test to ensure that Runnable could be invoked
System.out.println("Could not excute Runnable application");
e.printStackTrace();
}
}
public void run() {
setup(); // going to run out setup method, what our game is made out of
}
public void setup() {
// setting up the Board
// board is composed of JButton
// and a 3x3 frame
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // when the user closes the window JFrame will exit
//going to design the board now
//the dimensations of the board = sizeOfBoard
getFrame().setLayout(new GridLayout(row, col)); // this is the outline rows * col
// sizes out row * col based on what we define those numbers as
//i.e 3x3
getFrame().setBounds(0,0,500,500); // location at 0,0, size 500 x 500
Border border = new LineBorder(Color.DARK_GRAY, 2); // color of JButton border
System.out.println("Your board game is being created!");
try{
getFrame().setVisible(true); // shows the board,
// this is going to display everything to the screen
System.out.println("Board is now visable");
}
catch(Exception e){
System.out.println("Board was not displayed");
}
// 9 different buttons, for every index there will be a button
for(int i =0; i<sizeOfBoard;i++){ // going to fill the board with clickableButtons by looping through every index and placing a button there
final int move = i;
clickButton[i] = new JButton(); // at a certain index there is a new button
clickButton[i].setSize(250,250); // size of each button
clickButton[i].setBackground(Color.WHITE); // color of the JButton
getFrame().add(clickButton[i]); // we are going to add the actual the button at that index on the frame
clickButton[i].setFont(new Font("Arial", Font.BOLD, 70)); // size of the text
clickButton[i].setBorder(border); // adding border
clickButton[i].getModel().addChangeListener(new ChangeListener() { //going to overRide what happens when we rollover and press a Butotn
public void stateChanged(ChangeEvent e) {
ButtonModel button = (ButtonModel) e.getSource(); // manages the state of the button, i.e lets me control what happens to the button
if(clickButton[move] != null){ // if we do not include this argument
// the buttons are not made yet on the new game, meaning clickButton[i] = null
//so boolean(!button.isRollover()) will return true, since on the new game you can not have your mouse hovered over
// but when it returns true, it will return a null value, giving a null pointer exception
// so best thing to do, is to only run these cases below when the buttons are not null
if (button.isRollover()) { // when the mouse hovers over the index
clickButton[move].setBackground(Color.BLACK); // color will equal black
}
else if(!button.isRollover()){ // when the button is not hovered over
clickButton[move].setBackground(Color.WHITE); // color will be whte, just like our background
}
}
}
});
clickButton[i].addActionListener(new ActionListener() {
//our click events, going to override to let it know what we want to happen
//once we click on the button
public void actionPerformed(ActionEvent e) {
clickButton[move].setEnabled(false); //going to disable the button after it is clicked
//ORDER: button gets clicked first, then the test is added
mouseListener(e, move); // our mouseListenerEvent in game class
//
}
});
}
}
public static void playAgain() {
try{
System.out.println("NEW GAME");
SwingUtilities.invokeLater(new tic(frame)); // run the run(class) again
}
catch(Exception e){ // wanted to test to ensure that Runnable could be invoked
System.out.println("Could not excute Runnable application");
e.printStackTrace();
}
}
public static JFrame getFrame() {
return frame;
}
public tic userMove(int moveMade){
getTemplateOfBoard()[moveMade] = getUserTurn();
// index of the board, or in simpler terms, where the user
// inserts there turn i.e X or O, 0-8
//System.out.println(userMove);
//boolean statement to determine the turns
// So user X starts first
//if the turn is X, the nextTurn is now O,
if(getUserTurn() == 'X'){
setUserTurn('O');
}
else {
setUserTurn('X');
}
count++;
return this; // going to return the userTurn
// issue actually entering the userTurn is not giving right value, but using 'this' does
}
// for some odd reason the toString is causing some issues, keep getting #hash code
//saw online to override it like this
// will make the board out of emepty strings
// going to return a string representation of an object
public String toString(){
return new String(getTemplateOfBoard());
}
public void mouseListener(ActionEvent e, int moveMade){
// mouse click events
// what happens after a button is clicked
if(getTemplateOfBoard()[moveMade] == ' '){ // the user can only space a click, so an letter on the field if it is empty
((JButton)e.getSource()).setText(Character.toString(getUserTurn())); // when the button is clicked, we want an X placed there
if (getUserTurn() == 'X'){
UIManager.getDefaults().put("Button.disabledText",Color.RED); // when the but gets disabled the test will turn red
}
else{
UIManager.getDefaults().put("Button.disabledText",Color.BLUE);
}
//calling the method userTurn to determine who goes next
//problem is that is expects a String
//going to override the toString method
userMove(moveMade); // calling userMove in moveMade, moveMade is the index at which the user put either an X or a O
winner(); // we want to check each time to ensure there was/was not a winner
}
}
public tic winner() { // determines who is the winner
//list below defines all the possible win combinations
// the index of where a X or O can be place
// placed the locations to a int value
int win1 = templateOfBoard[0] + templateOfBoard[1] + templateOfBoard[2];
int win2 = templateOfBoard[3] + templateOfBoard[4] + templateOfBoard[5];
int win3 = templateOfBoard[6] + templateOfBoard[7] + templateOfBoard[8];
int win4 = templateOfBoard[0] + templateOfBoard[3] + templateOfBoard[6];
int win5 = templateOfBoard[1] + templateOfBoard[4] + templateOfBoard[7];
int win6 = templateOfBoard[2] + templateOfBoard[5] + templateOfBoard[8];
int win7 = templateOfBoard[0] + templateOfBoard[4] + templateOfBoard[8];
int win8 = templateOfBoard[2] + templateOfBoard[4] + templateOfBoard[6];
int[] win = new int[]{win1,win2,win3,win4,win5,win6,win7,win8};
// making a array to go through all the possibile wins
//possible total of wins is 8
for(int i = 0;i<win.length;i++){
// looping through the win possibilities
if(win[i] == 264){ // if one of the the combinations equal 'X','X','X' which equals 264, then there is a winner
System.out.println("X is the winner!!!");
System.out.println("Game Over!");
number = i;
draw(); // call draw method
return this; // if statement is true, it will return this(gameOver)
}
else if(win[i] == 237 ){ // if one of the the combinations equal 'O','O','O' which equals 234, then there is a winner
System.out.println("O is the winner!!!");
System.out.println("Game Over!");
number = i;
//draw(); // call draw method
return this;
}
if (count == 9) {
// if none of the statements above are true, it automatically comes done to here
//so if there is nine moves and no win, it is a draw
}
}
return this;
// going to return this method ;
}
private void draw(){ // drawing a line at winning location
Graphics2D g1 = (Graphics2D) getFrame().getGraphics(); // declaring graphics on our Jframe
Stroke stroke3 = new BasicStroke(12f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_MITER); // make our strokes cap off round
if(number == 0){ // statements will determine the win location, so at win0, XXX,
g1.setStroke(stroke3); // we will add stroke to our line
g1.drawLine(0,104,500,104); // draw the line starting at the 0,104 and end it at coordinates 500,104
}
else if(number == 1){
g1.setStroke(stroke3);
g1.drawLine(0,257,500,257);
}
else if(number == 2){
g1.setStroke(stroke3);
g1.drawLine(0,411,500,411);
}
else if(number == 3){
g1.setStroke(stroke3);
g1.drawLine(88,0,88,500);
}
else if(number == 4){
g1.setStroke(stroke3);
g1.drawLine(250,0,250,500);
}
else if(number == 5){
g1.setStroke(stroke3);
g1.drawLine(411,0,411,500);
}
else if(number == 6){
g1.setStroke(stroke3);
g1.drawLine(-22,0,500,500);
}
else if(number == 7){
g1.setStroke(stroke3);
g1.drawLine(520,0,0,500);
}
}
// want to be able to access the private variables
//so we will make getter and setter methods for the ones that we need
public char getUserTurn() { // getter method for userTurn
return userTurn;
}
public void setUserTurn(char userTurn) { // setter method
this.userTurn = userTurn;
}
public char[] getTemplateOfBoard() { //getter method
return templateOfBoard;
}
public void setTemplateOfBoard(char[] templateOfBoard) { // setter method
this.templateOfBoard = templateOfBoard;
}
}
Painting over the top of components can be troublesome, you can't override the paintComponent method of the container which contains the components, because this paints in the background, you can't override the paint method of the container, as child components can be painted without the parent container been notified...
You could add a transparent component over the whole lot, but this just introduces more complexity, especially when a component already already exists ...
public class ConnectTheDots {
public static void main(String[] args) {
new ConnectTheDots();
}
public ConnectTheDots() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception ex) {
}
PaintPane pp = new PaintPane();
JFrame frame = new JFrame("Test");
frame.setGlassPane(pp);
pp.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new DotsPane(pp));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class PaintPane extends JPanel {
private List<JButton[]> connections;
private JButton lastSelected;
public PaintPane() {
setOpaque(false);
connections = new ArrayList<>(25);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
if (lastSelected != null) {
g2d.setColor(Color.RED);
int x = lastSelected.getX() + ((lastSelected.getWidth() - 8) / 2);
int y = lastSelected.getY() + ((lastSelected.getHeight() - 8) / 2);
g2d.fillOval(x, y, 8, 8);
}
for (JButton[] group : connections) {
g2d.setColor(Color.BLUE);
Point startPoint = group[0].getLocation();
Point endPoint = group[1].getLocation();
startPoint.x += (group[0].getWidth() / 2);
startPoint.y += (group[1].getHeight()/ 2);
endPoint.x += (group[0].getWidth() / 2);
endPoint.y += (group[1].getHeight()/ 2);
g2d.draw(new Line2D.Float(startPoint, endPoint));
}
g2d.dispose();
}
protected void buttonClicked(JButton btn) {
if (lastSelected == null) {
lastSelected = btn;
} else {
connections.add(new JButton[]{lastSelected, btn});
lastSelected = null;
}
revalidate();
repaint();
}
}
public class DotsPane extends JPanel {
private PaintPane paintPane;
public DotsPane(final PaintPane pp) {
paintPane = pp;
ActionListener al = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
JButton btn = (JButton) e.getSource();
paintPane.buttonClicked(btn);
}
};
setLayout(new GridLayout(6, 6));
for (int index = 0; index < 6 * 6; index++) {
JButton btn = new JButton(".");
add(btn);
btn.addActionListener(al);
}
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
}
}
Take a look at How to Use Root Panes for more details
Related
I'm making a chess program for a school project using swing. this is my first time using swing however I've had a lot of experience with tkinter in python which feels similar. I've gotten the pieces loaded onto board and can load in FEN strings.
The basic board when loaded in
Now I've been trying to move on to allowing the player to capture other pieces. currently I'm not worried about the rules of how pieces can move and I'm just trying to allow them to capture anything.
A little bit of extra knowledge that may be useful is that I have two 2d arrays for the board. one contains a 2d array of 64 buttons (one for each square). the other contains a 2d int array and contains the numerical value of each piece in each square.
the following code is my code for attempting to capture pieces. My thinking behind this implementation is to first find when we select a piece that we want to move. when we click on this piece we store it in selected and set isSelecting equal to true. then the next piece we click on we should capture. The way I've been trying to tackle this is by finding the square we want to capture and changing the piece icon to the icon of the piece we stored in selected. then setting the selected pieces icon to a empty icon. then doing the same for the int array.
public boolean isSelecting;
public JButton selected;
public int[] findSpot(JButton but){
for (int i = 0 ; i < board.length; i++)
for (int j = 0 ; j < board.length; j++)
{
if ( board[i][j] == but)
{
return new int[]{i,j};
}
}
return new int[]{-1,-1};
}
#Override
public void mouseReleased(MouseEvent e) {
System.out.println(1);
System.out.println(isSelecting);
if (!isSelecting) {
System.out.println(2);
selected = (JButton) e.getSource();
System.out.println(e.getSource());
} else {
System.out.println(3);
int[] temp = findSpot(selected);
ImageIcon i = new ImageIcon(pieceFiles.get(intBoard[temp[0]][temp[1]]));
Image img = i.getImage() ;
Image newimg = img.getScaledInstance(75, 75, java.awt.Image.SCALE_SMOOTH ) ;
i = new ImageIcon( newimg );
((JButton) e.getSource()).setIcon(i);
int[]temp2 = findSpot(((JButton) e.getSource()));
intBoard[temp[0]][temp[1]] = intBoard[temp2[0]][temp2[1]];
selected.setIcon(new ImageIcon());
intBoard[temp[0]][temp[1]] = none;
selected = null;
}
isSelecting = !isSelecting;
}
This code, however, isn't working and I can't figure out why. The specific problem is the isSelecting variable on becomes false when you click the same piece twice. Clicking two separate pieces does nothing however clicking the same piece twice removes said piece.
The output after clicking the first three pawns
The output after clicking those three pawns for a second time
I'm going to leave my full code here. I'm not sure if I should since it's long but I hope it can give you a better scope of the project.
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.Hashtable;
import javax.swing.*;
public class Chess implements MouseListener {
static int none = 0;
static int king = 1;
static int pawn = 2;
static int knight = 3;
static int bishop = 4;
static int rook = 5;
static int queen = 6;
static int black = 8;
static int white = 16;
public boolean isSelecting;
public JButton selected;
static JButton[][] board = new JButton[8][8];
static int[][] intBoard = new int[8][8];
static JFrame frame = new JFrame("Big Willy's Chess");
static Hashtable<Integer, String> pieceFiles = new Hashtable<>();
public static void cTable() {
String folder = "C:\\Users\\bookr\\IdeaProjects\\CSA\\src\\pieces";
pieceFiles.put(king + black, folder + "\\Chess_kdt60.png");
pieceFiles.put(king + white, folder + "\\Chess_klt60.png");
pieceFiles.put(pawn + black, folder + "\\Chess_pdt60.png");
pieceFiles.put(pawn + white, folder + "\\Chess_plt60.png");
pieceFiles.put(knight + black, folder + "\\Chess_ndt60.png");
pieceFiles.put(knight + white, folder + "\\Chess_nlt60.png");
pieceFiles.put(bishop + black, folder + "\\Chess_bdt60.png");
pieceFiles.put(bishop + white, folder + "\\Chess_blt60.png");
pieceFiles.put(rook + black, folder + "\\Chess_rdt60.png");
pieceFiles.put(rook + white, folder + "\\Chess_rlt60.png");
pieceFiles.put(queen + black, folder + "\\Chess_qdt60.png");
pieceFiles.put(queen + white, folder + "\\Chess_qlt60.png");
}
public static boolean isNumeric(String str) {
try {
Double.parseDouble(str);
return true;
} catch(NumberFormatException e) {
return false;
}
}
public static void loadFenPos(String fen){
Hashtable<String, Integer> pieceNumbs = new Hashtable<>();
pieceNumbs.put("k", king);
pieceNumbs.put("p", pawn);
pieceNumbs.put("n", knight);
pieceNumbs.put("b", bishop);
pieceNumbs.put("r", rook);
pieceNumbs.put("q", queen);
int rank = 0;
int file = 0;
for (String symbol:fen.split("")) {
if (symbol.equals("/")) {
file = 0;
rank++;
}
else {
if (!isNumeric(symbol)) {
int pieceColor = Character.isUpperCase(symbol.charAt(0)) ? white : black;
int pieceType = pieceNumbs.get(symbol.toLowerCase());
ImageIcon i = new ImageIcon(pieceFiles.get(pieceType+pieceColor));
Image img = i.getImage();
Image newimg = img.getScaledInstance(75, 75, java.awt.Image.SCALE_SMOOTH);
i = new ImageIcon(newimg);
intBoard[rank][file] = pieceType+pieceColor;
board[rank][file].setIcon(i);
file++;
} else {
file += Integer.parseInt(symbol);
}
}
}
}
public void start (){
cTable();
JPanel panel = new JPanel();
panel.setLayout(new GridLayout(8, 8));
Color lightSquareColor = new Color(240, 240, 240);
Color darkSquareColor = new Color(128, 128, 128);
for (int row = 0; row < 8; row++) {
for (int col = 0; col < 8; col++) {
JButton button = new JButton();
button.setOpaque(true);
button.setBorderPainted(false);
button.setFocusPainted(false);
if ((row + col) % 2 == 0) {
button.setBackground(lightSquareColor);
} else {
button.setBackground(darkSquareColor);
}
button.addMouseListener(new Chess());
panel.add(button);
board[row][col] = button;
}
}
// ImageIcon i = new ImageIcon("C:\\Users\\bookr\\IdeaProjects\\CSA\\src\\pawn.png");
//
//
// Image img = i.getImage() ;
// Image newimg = img.getScaledInstance(75, 75, java.awt.Image.SCALE_SMOOTH ) ;
// i = new ImageIcon( newimg );
// board[6][7].setIcon(i);
loadFenPos("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR");
frame.add(panel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setSize(600, 600);
frame.setVisible(true);
}
public static void main(String[] args) {
Chess game = new Chess();
game.start();
}
public int[] findSpot(JButton but) {
for (int i = 0 ; i < board.length; i++)
for(int j = 0 ; j < board.length; j++)
{
if ( board[i][j] == but)
{
return new int[]{i,j};
}
}
return new int[]{-1,-1};
}
#Override
public void mouseClicked(MouseEvent e) {
}
#Override
public void mousePressed(MouseEvent e) {
}
#Override
public void mouseReleased(MouseEvent e) {
System.out.println(1);
System.out.println(isSelecting);
if (!isSelecting) {
System.out.println(2);
selected = (JButton) e.getSource();
} else {
System.out.println(3);
int[] temp = findSpot(selected);
ImageIcon i = new ImageIcon(pieceFiles.get(intBoard[temp[0]][temp[1]]));
Image img = i.getImage() ;
Image newimg = img.getScaledInstance(75, 75, java.awt.Image.SCALE_SMOOTH ) ;
i = new ImageIcon( newimg );
((JButton) e.getSource()).setIcon(i);
int[]temp2 = findSpot(((JButton) e.getSource()));
intBoard[temp[0]][temp[1]] = intBoard[temp2[0]][temp2[1]];
selected.setIcon(new ImageIcon());
intBoard[temp[0]][temp[1]] = none;
selected = null;
}
isSelecting = !isSelecting;
}
#Override
public void mouseEntered(MouseEvent e) {
}
#Override
public void mouseExited(MouseEvent e) {
}
}
I've tried messing changing around the isSelecting variable, how I assign the selected variable, and how I update the 2d arrays.
I am trying to get my Asteroids game in Java to have the ArrayList container be removed once it's off screen. I figured out how to stop having it print when off screen, but can see in my console the array continues to grow. Not sure where to go from here.
I think the way I can get them to be removed when off screen is by either using the remove or set feature with arrayLists. Visually everything is disappearing right, but in the console my ArrayList is still growing. I thought about setting a limit of how long it can be, but not sure if there is a better way than that.
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import java.util.Iterator;
public class AsteroidGame extends Frame {
private int FrameWidth = 500;
private int FrameHeight = 400;
static public void main(String[] args) {
AsteroidGame world = new AsteroidGame();
world.show();
world.run();
}
public AsteroidGame() {
setTitle("Asteroid Game0");
setSize(FrameWidth, FrameHeight);
addKeyListener(new keyDown());
addWindowListener(new CloseQuit());
}
public void run() {
while (true) {
movePieces();
repaint();
try {
Thread.sleep(100);
} catch (Exception e) {
}
}
}
private ArrayList asteroids = new ArrayList();
private ArrayList rockets = new ArrayList();
private Station station = new Station(FrameWidth / 2, FrameHeight - 20);
public void paint(Graphics g) {
station.paint(g);
Iterator astIt = asteroids.iterator();
while (astIt.hasNext()) {
Asteroid rock = (Asteroid) astIt.next();
if (rock.y >= 400 || rock.x >= 500){
rock = null;
} else {
rock.paint(g);
}
}
Iterator rocIt = rockets.iterator();
while (rocIt.hasNext()) {
Rocket rock = (Rocket) rocIt.next();
if (rock.y >= 400 || rock.x >= 500) {
rock = null;
} else {
rock.paint(g);
}
}
}
public void movePieces() {
if (Math.random() < 0.3) {
Asteroid newRock = new Asteroid(FrameWidth * Math.random(), 20, 10 * Math.random() - 5, 3 + 3 * Math.random());
if (newRock.y >= 500 || newRock.x >= 500){
asteroids.remove(0);
} else{
asteroids.add(newRock);
}
System.out.println(asteroids.size());
}
Iterator astIt = asteroids.iterator();
while (astIt.hasNext()) {
Asteroid rock = (Asteroid) astIt.next();
if (rock.y >= 400 || rock.x >= 500) {
rock = null;
} else {
rock.move();
station.checkHit(rock);
}
}
Iterator rocIt = rockets.iterator();
while (rocIt.hasNext()) {
Rocket rock = (Rocket) rocIt.next();
if (rock.y >= 400 || rock.x >= 500) {
rock = null;
} else {
rock.move(asteroids);
}
}
}
private class gameMover extends Thread {
public void run() {
while (true) {
movePieces();
repaint();
try {
sleep(100);
} catch (Exception e) {
}
}
}
}
Change:
rock = null;
to:
astIt.remove();
Assigning null to the variable that has been assigned the value of an element of a List does absolutely nothing to either the List or the element in it; it only affects the value that the variable holds.
As an aside, nice variable name choice of rock - it is appropraite for both types of object - either an abbreviation of "rocket" or a reasonable synonym for an astroid.
Change rock = null; to asteroids.remove(rock); or astIt.remove();
and it should be fine, also no need to set the variable to null as the garbage collector will take care of it for you.
EDIT
Actually asteroids.remove(rock); will throw an exception as said in the comments of this answer, so nevermind it and use the other.
Also I think when in movePieces() you create a new rock and you check if this new rock is outside the screen, I don't think removing the first asteroid in the ArrayList is correct as you will not add the new rock (which may be right if the rock can actually randomly spawn outside the screen) but you will also remove a maybe fine working asteroid from the ArrayList (and thus from the game and the screen).
So, personally I would change that part of code to:
if (Math.random() < 0.3) {
Asteroid newRock = new Asteroid(FrameWidth * Math.random(), 20, 10 * Math.random() - 5, 3 + 3 * Math.random());
if (!(newRock.y >= 500 || newRock.x >= 500)){
asteroids.add(newRock);
}
System.out.println(asteroids.size());
}
But tell me if this works for you.
I'm developing a simple game where all the images are randomized. I've noticed that some of the image are repeated although I have put the random code. I'm still new to Java. I hope that someone can help me solve my problem. Below is my coding.
import java.awt.*;
import java.awt.event.*;
import java.sql.*;
import java.util.Random;
import javax.swing.*;
public class Task1 extends JFrame implements KeyListener,ActionListener {
JFrame frame = new JFrame("FYP");
JTextField textField = new JTextField();
JButton btnNext = new JButton("NEXT");
int sum=0;
int Error=0;int total_test = 0;
static String inputID;
static int index;
String[] imgFileHP = {"1.jpg","3.jpg","4.jpg","7.jpg","9.jpg","10.jpg","12.jpg","16.jpg","17.jpg","18.jpg"};
String[] imgNo = {"5","4","6","3","5","3","4","4","6","6"};
int randomNo;
Random rand = new Random();
public Task1(String inputID)
{
frame.setSize(2200,2500);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
frame.getContentPane().setLayout(new BorderLayout(0, 0));
Task(inputID);
}
public void Task(String inputID)
{
JPanel panel = new JPanel();
JLabel labelUsername = new JLabel("");
frame.getContentPane().add(panel, BorderLayout.CENTER);
panel.setBackground(Color.WHITE);
Collections.shuffle(Arrays.asList(imgFileHP));
Set<Integer> uniqueList = new HashSet<Integer>();//This would create list with the number 0 to 9
for(int count=0;count<imgFileHP.length;count++){
uniqueList.add(count);
labelUsername.setIcon(new ImageIcon(getClass().getResource("/image/" + imgFileHP[count])));
if(!uniqueList.isEmpty()){
index = (int) (Math.random() * (upper - lower)) + lower;
if(uniqueList.contains(index)){
uniqueList.remove(index);//particular number is delete from the list so that duplicate images doesnt show up
System.out.println(imgFileHP[r]);//This printf statement is just for your reference
}
}
}
textField.setText("");
textField.setColumns(10);
textField.addKeyListener(this);
btnNext.addActionListener(this);
panel.add(labelUsername);
panel.add(textField);
panel.add(btnNext);
frame.setVisible(true);
}
public void actionPerformed(ActionEvent ae)
{
if(!textField.getText().equals("")){
total_test += 1;
if(isNumeric(textField.getText())){
//********************Correct Integer**********************
if(Integer.valueOf(imgNo[randomNo])==Integer.valueOf(textField.getText())){
//********************Correct Answer**********************
System.out.println("Correct");
sum+=1;
}else{
//********************Incorrect Answer**********************
System.out.println("Incorrect");
Error+=1;
}
refreshFrame();
}else{
//********************Incorrect Integer/Alphabet**********************
System.out.println("Invalid");
Error+=1;
refreshFrame();
}
}else{
System.out.println("Null Input");
}
//System.out.println(Integer.valueOf(imgNo[randomNo]));
}
public void refreshFrame(){
if(total_test>=10){
// add result page to see how many score
//Task2(sum, Error);
System.out.println("Correct: "+sum+" Incorrect: "+Error);
frame.dispose();
}else{
btnNext.removeActionListener(this);
frame.getContentPane().removeAll();
getContentPane().removeAll();
Task(inputID);
}
}
public static void main(String args[]) {
Task1 a = new Task1(inputID);
}
#Override
public void keyPressed(KeyEvent e) {
// TODO Auto-generated method stub
}
#Override
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub
}
#Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
}
public static boolean isNumeric(String str)
{
try
{
Integer.valueOf(str);
}
catch(NumberFormatException nfe)
{
return false;
}
return true;
}
}
EDIT part (But some of the image is still repeating.)
Collections.shuffle(Arrays.asList(imgFileHP));
Set<Integer> uniqueList = new HashSet<Integer>();//This would create list with the number 0 to 9
for(int count=0;count<imgFileHP.length;count++){
uniqueList.add(count);
}
if(!uniqueList.isEmpty()){
index = (int) (Math.random() * (upper - lower)) + lower;
randomNo = index;
if(uniqueList.contains(index)){
labelUsername.setIcon(new ImageIcon(getClass().getResource("/image/" + imgFileHP[index])));
uniqueList.remove(index);//particular number is delete from the list so that duplicate images doesnt show up
System.out.println(imgFileHP[r]);//This printf statement is just for your reference
}
}
Here is how Random works. Even though you have mentioned rand.nextInt(10);but everytime it gets called, there is not pre-defined rule in java that it has to generate unique numbers and not the duplicate the previously generated ones.
For Example:
when you call -
int index = rand.nextInt(10); // Index could be 2
index = rand.nextInt(10); // Now again the value could be 2 as well
So what you need to do is you have to add an extra piece of code to check the uniqueness every time random is called.
Since you want to generate numbers between 0 to 10. Try the following code, it might help you understand.
String[] imgFileHP = {"1.jpg","3.jpg","4.jpg","7.jpg","9.jpg","10.jpg","12.jpg","16.jpg","17.jpg","18.jpg"};
int upper = imgFileHP.length;
int lower = 0;
int r=0;
int index=0;
Set<Integer> uniqueList = new HashSet<Integer>();//This would create list with the number 0 to 9
for(int count=0;count<imgFileHP.length;count++){
uniqueList.add(count);
}
if(!uniqueList.isEmpty()){
index = (int) (Math.random() * (upper - lower)) + lower;
if(uniqueList.contains(index)){
uniqueList.remove(index);//particular number is delete from the list so that duplicate images doesnt show up
System.out.println(imgFileHP[r]);//This printf statement is just for your reference
}
}
Another easier method is to use Collections.Shuffle as shown below:
Collections.shuffle(Arrays.asList(imgFileHP));
Example of Collection.shuffle().
Lets say you have an array String[] arr = {"abc","def","xyz","bla"}
when you do Collections.shuffle(Arrays.asList(arr));
then print array from index 0 to 3. Array might be shuffled something like this: {"def","bla","abc","xyz"}
**EDIT 2:**Solution based on your edit in main code:
for(int count=0;count<imgFileHP.length;count++){//first add the counters into List
uniqueList.add(count);
}
if(!uniqueList.isEmpty()){
index = (int) (Math.random() * (upper - lower)) + lower;
if(uniqueList.contains(index)){
labelUsername.setIcon(new ImageIcon(getClass().getResource("/image/" + imgFileHP[index])));
uniqueList.remove(index);//particular number is delete from the list so that duplicate images doesnt show up
System.out.println(imgFileHP[r]);//This printf statement is just for your reference
}
}
Hi every one i am having a bit of trouble with my java game, it is very simply made as i am new to java. and the game works fine well as good as i can achieve. But i am stuck on how i can change the images in real time. I am trying to figure out how to make my Monsters face me "the hero frylark" when they chase me. i have made 2 simple methods in my monster class. left and right How could i apply these methods to make the image change from image = getImage("/Game/images/police-right.png"); to image = getImage("/Game/images/police-left.png");.
Oh and in my project library is golden_0_2_3.jar which contains some game engine stuff.
Please.
Many thanks from edwin.
import com.golden.gamedev.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.Random;
import java.awt.event.KeyEvent;
public class MyGame extends Game {
// set the values
public Random random;
private Hero frylark;
private Monster[] monsters = new Monster[3];
private Token coin;
private GameBackGround grass;
private BufferedImage image;
public void initResources() {
// set a new random number
random = new Random();
// get the background image.
image = getImage("/Game/images/background.png");
// set the name "grass" to background and given the image from the image set above.
grass = new GameBackGround("grass", image);
// get the monsters image.
image = getImage("/Game/images/police.png");
// give the monsters their names "" and set them their image from the image set above.
monsters[0] = new Monster("Monster", image);
monsters[1] = new Monster("Monster2", image);
monsters[2] = new Monster("Monster3", image);
// get the tokens image.
image = getImage("/Game/images/donut.png");
// set the name "coin" for the token, then its x and y position, and set the image from the image set above.
coin = new Token("coin", 400, 300, image);
// get the heros image.
image = getImage("/Game/images/snake.png");
// set the name "frylark" for the hero, then his score "0" and lives "5".
frylark = new Hero("Frylark", 0, 5);
//set the monsters random x and y positions.
monsters[0].setX(random.nextInt(750));
monsters[0].setY(random.nextInt(550));
monsters[1].setX(random.nextInt(750));
monsters[1].setY(random.nextInt(550));
monsters[2].setX(random.nextInt(750));
monsters[2].setY(random.nextInt(550));
}
// update method
public void update(long elapsedTime) {
// Pause the hero "frylark" on hold of the space bar.
if (!keyDown(KeyEvent.VK_SPACE)){
// if dead stop frylark moving on the 5 second game over sequence, being displays details and playing the game over sound.
if (Hero.dead(frylark)){
if(keyDown(KeyEvent.VK_LEFT))
{
// Move left
frylark.moveLeft();
}
if (keyDown(KeyEvent.VK_RIGHT))
{
// Move right
frylark.moveRight();
}
if (keyDown(KeyEvent.VK_UP))
{
// Move up on press of up key
frylark.moveUp();
}
if (keyDown(KeyEvent.VK_DOWN))
{
// Move down on press of down key
frylark.moveDown();
}
}
if (keyDown(KeyEvent.VK_ESCAPE))
{
// Exit game on press of esc key.
System.exit(0);
}
}
if (!keyDown(KeyEvent.VK_SPACE))
{
// Pause the monsters on hold of the space bar
monsters[0].chase(frylark);
monsters[1].chase(frylark);
monsters[2].chase(frylark);
}
// if monster 0 has eaten frylark move to a random position and lose a life, plus play the lose life sound.
if (monsters[0].eaten(frylark)) {
monsters[0].setX(random.nextInt(750));
monsters[0].setY(random.nextInt(550));
frylark.loseLife();
playSound("/Game/sounds/lost_a_life.wav");
}
// if monster 1 has eaten frylark move to a random position and lose a life, plus play the lose life sound.
if (monsters[1].eaten(frylark)) {
monsters[1].setX(random.nextInt(750));
monsters[1].setY(random.nextInt(550));
frylark.loseLife();
playSound("/Game/sounds/lost_a_life.wav");
}
// if monster 2 has eaten frylark move to a random position and lose a life, plus play the lose life sound.
if (monsters[2].eaten(frylark)) {
monsters[2].setX(random.nextInt(750));
monsters[2].setY(random.nextInt(550));
frylark.loseLife();
playSound("/Game/sounds/lost_a_life.wav");
}
// if coin is collected increase score and move to a random position, and play the coin collect sound.
if (coin.collected(frylark)) {
coin.setX (random.nextInt(750));
coin.setY (random.nextInt(550));
frylark.increaseScore();
playSound("/Game/sounds/coin.wav");
}
}
public void render(Graphics2D g) {
// draw all the monsters, hero, and coin and background.
g.drawImage(grass.getImage(),grass.getX(),grass.getY(),null);
g.drawImage(monsters[0].getImage(), monsters[0].GetX(), monsters[0].GetY(), null);
g.drawImage(monsters[1].getImage(), monsters[1].GetX(), monsters[1].GetY(), null);
g.drawImage(monsters[2].getImage(), monsters[2].GetX(), monsters[2].GetY(), null);
g.drawImage(image,frylark.getX(),frylark.getY(),null);
g.drawImage(coin.getImage(),coin.getX(),coin.getY(),null);
// if monster 0 overlaps another monster mover him back
if (monsters[0].overlap(monsters)){
monsters[0].x -=20;
monsters[0].y -=70;
}
// if monster 1 overlaps another monster mover him back
if (monsters[1].overlap(monsters)){
monsters[1].x -=21;
monsters[1].y -=70;
}
// if monster 2 overlaps another monster mover him back
if (monsters[2].overlap(monsters)){
monsters[2].x -=22;
monsters[2].y -=70;
}
// draw the lives bar, and set the font colour and size
g.setColor(Color.RED);
g.setFont(new Font("default", Font.BOLD, 18));
for (int i = 0; i < frylark.getLives(); i++) {
g.fillRect( (i + 1) * 15, 10, 10, 10);
}
// draw the score
g.setColor(Color.GREEN);
g.drawString("Score: " + frylark.getScore(), 10, 50);
// draw the level
g.setColor(Color.YELLOW);
g.drawString("level: " + frylark.getScoreNum(), 10, 80);
// game over sequence, changes the font to size 40 and displays game over, as well as the payers score and level reached plus the game over sound.
if (frylark.getLives() ==0){
g.setColor(Color.RED);
g.setFont(new Font("override", Font.BOLD, 40));
g.drawString("Game over !", 280, 290);
playSound("/Game/sounds/game_over.wav");
g.drawString("You reached Level " + frylark.getScoreNum() + " Your Score: " + frylark.getScore(), 60, 330);
}
}
// main method which after all classes have been read and checked, "Game development environment OK! " will be printed to the console.
// then a new game is created and given dimensions and launched.
public static void main(String args[]) {
System.out.println("Game development environment OK! ");
GameLoader gameLoader = new GameLoader();
MyGame myGame = new MyGame();
gameLoader.setup(myGame,new Dimension(800,600),false);
gameLoader.start();
}
}
and my Monster class
import java.util.Random;
import java.awt.image.BufferedImage;
public class Monster {
private String name;
int x;
int y;
private BufferedImage image;
Random rand;
public Monster (String nameIn, BufferedImage imageIn)
{
name = nameIn;
x = 0;
y = 0;
image = imageIn;
}
public void chase(Hero hero) {
if (hero.getX() < x) { // if hero is to the left
x--;
}
if (hero.getX() > x) { // if hero is to the right
x++ ;
}
if (hero.getY() < y) { // if hero is to the above
y--;
}
if (hero.getY() > y) { // if hero is to the below
y++;
}
}
public boolean overlap(Monster monsters[]){
if (monsters[0].x == monsters[1].x && monsters[0].y == monsters[1].y || monsters[0].x == monsters[2].x && monsters[0].y == monsters[2].y ||
monsters[1].x == monsters[0].x && monsters[1].y == monsters[0].y || monsters[1].x == monsters[2].x && monsters[1].y == monsters[2].y ||
monsters[2].x == monsters[0].x && monsters[2].y == monsters[0].y || monsters[2].x == monsters[1].x && monsters[2].y == monsters[1].y) {
return true;
}
else{
return false;
}
}
public boolean eaten(Hero hero) {
if (hero.getX() == x && hero.getY() == y) {
return true;
}
else {
return false;
}
}
public BufferedImage getImage() {
return image;
}
public int GetX(){
return x;
}
public int GetY(){
return y;
}
public String getName()
{
return this.name;
}
public void setX(int xIn) {
x = xIn;
}
public void setY(int yIn) {
y = yIn;
}
public boolean left(Hero hero) {
if (hero.getX() < x) {
return true;
}
else {
return false;
}
}
public boolean right(Hero hero) {
if (hero.getX() > x) {
return true;
}
else {
return false;
}
}
}
I would modify your Monster constructor to accept both images. Then modify Monster.getImage() to call left() and return the correct one based on the result. You probably don't need to call right() as well, since if the monster is not facing left then you know it needs to face right. Unless you want to get more sophisticated and also add a view facing straight forward or backward.
I am trying to accomplish the above functionality, and am having little success.
I am using GridLayout with 2 columns and 2 rows to show the user a puzzle-like game, where there are 4 (200x200 pixel) JPanels (3 colored, 1 default bgColor) which fill the whole contentPane. Clicking on a colored panel resolves in an assessment if the panel is next to the gray panel. If so, they should swap. I have accomplished every step to the last one, where they swap. Here's the code:
public class MainClass extends JFrame {
//Generated
private static final long serialVersionUID = 4710628273679698058L;
private SpecialPanel redPanel;
private SpecialPanel greenPanel;
private SpecialPanel yellowPanel;
private SpecialPanel grayPanel;
public MainClass() {
super("Puzzle");
initPanels();
setSize(410, 410);
setLayout(new GridLayout(2, 2));
this.add(redPanel);
this.add(greenPanel);
this.add(grayPanel);
this.add(yellowPanel);
}
private void initPanels() {
redPanel = new SpecialPanel();
greenPanel = new SpecialPanel();
yellowPanel = new SpecialPanel();
grayPanel = new SpecialPanel();
grayPanel.setGreyPanel(true);
redPanel.setBackground(Color.RED);
greenPanel.setBackground(Color.GREEN);
yellowPanel.setBackground(Color.YELLOW);
grayPanel.setBackground(this.getBackground());
redPanel.setSize(200, 200);
greenPanel.setSize(200, 200);
yellowPanel.setSize(200, 200);
grayPanel.setSize(200, 200);
MouseAdapter ma = new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent arg0) {
super.mouseClicked(arg0);
SpecialPanel sp = (SpecialPanel) arg0.getComponent();
if (sp.getIsGray()) {
//Do nothing
} else if (checkIfNeighbourToGray(sp, grayPanel)) {
//Swap them
System.out.println("Swap notification");
swap(sp, grayPanel);
//Update UI
} else {
//Again, do nothing for the clicked panel is diagonal to the gray panel
}
}
private boolean checkIfNeighbourToGray(SpecialPanel sp, SpecialPanel grayPanel) {
Point startPointSp = sp.getLocation();
double x = startPointSp.getX();
double y = startPointSp.getY();
double width = sp.getWidth();
double height = sp.getHeight();
Point grayPoint = grayPanel.getLocation();
double xG = grayPanel.getX();
double yG = grayPanel.getY();
double widthG = grayPanel.getWidth();
double heightG = grayPanel.getHeight();
//Gray panel is RIGHT of clicked one
if (x + width == xG && y + height == yG + heightG) {
return true;
}
//Gray panel is LEFT of clicked one
else if (x - width == xG && y + height == yG + heightG) {
return true;
}
//Gray panel is ABOVE of clicked one
else if (x == xG && x + width == xG + widthG) {
return true;
}
//Gray panel is UNDER of clicked one
else if (xG == x && yG + widthG == x + width) {
return true;
}
return false;
}
private void swap(SpecialPanel sp, SpecialPanel grayPanel) {
//Swap logic
}
};
redPanel.addMouseListener(ma);
greenPanel.addMouseListener(ma);
yellowPanel.addMouseListener(ma);
grayPanel.addMouseListener(ma);
}
public static void main(String[] args) {
MainClass mc = new MainClass();
mc.setVisible(true);
}
}
The class SpecialPanel is extending JPanel with just a new Boolean property IsGrayPanel initially set to false + getter and setter.
NOTE: This is being done in a "I have basic Swing skills" manner, although I have learned more in the meantime about java swing, I was just limited back then with basic swing functionality, so I should keep it that way.
Therefore my question is how to properly swap the two panels which are next to each other, including UI update?
there wouldn't need to move with JPanels into container, otherwise you woud need to use bunch of quite useless code to remove two JPanels from from contianer with two indexes then to layout back to container with swaping indexes,
(if is about Color only) only to swap setBackground(Color.Xxx) betweens two JPanels
puzzle-like game is about Images, puzzle or minesweaper is about, (not clear from your ...)
put Images as Icon/ImageIcons to JLabel instead of JPanel and on Mouse Events to switch (setIcon()) with Icons betweens JLabels, load Icons to local variables
(easiest of ways) JToggleButton and Icon, there is logic similair as for JLabel, but about showing Icon on setPressedIcon()
I'm not sure if this works. It looks too easy.
JPanel tempPanel = sp;
sp = grayPanel;
grayPanel = tempPanel;
this.setVisible(false);
this.setVisible(true);
this.validate(); //try this first
this.repaint(); // if it doesnt work, add this function.