I trying to implement tic tac toe logic into this code. I don't want anything super fancy. It just needs to be a player vs player and must show winner and ask if you want to play again. I've been trying to make this work for a while now and I've had no success.
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
public class TicTacToe {
public static void main(String[] args) {
JFrame frame = new JFrame(" TicTacToe");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(290, 300);
Board board = new Board();
frame.add(board);
frame.setResizable(false);
frame.setVisible(true);
}
}
class Board extends JComponent {
private int w = 265, h = 265;
char player = 'X';
public Board() {
addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent me) {
int x = me.getX();
int y = me.getY();
int sideWidth = w / 3;
int sideHeight = h / 3;
int a = x / sideWidth;
int b = y / sideHeight;
int xStart = sideWidth * a + 10;
int yStart = sideHeight * b + +sideHeight - 10;
Graphics g = getGraphics();
g.setFont(new Font("monospaced", Font.PLAIN, 110));
g.drawString(player + "", xStart, yStart);
if (player == 'X') {
player = 'O';
} else {
player = 'X';
}
if
}
});
}
public void paint(Graphics g) {
g.drawLine(90, 0, 90, 300);
g.drawLine(185, 0, 185, 300);
g.drawLine(0, 85, 300, 85);
g.drawLine(0, 175, 300, 175);
}
}
Say who won, ask if you would like to play again.
Obviously the game logic is for you to code, but you can easily draw the board using a few loops.
I would try to get the cell index that you clicked on and store player data into a matrix. This way you can simply recall the values when you need to paint. This also adds a layer of validation as to who owns which cell.
char[][] cells = new char[3][3];
#Override
void mousePressed(MouseEvent e) {
int tileWidth = (int) Math.floor(BOARD_WIDTH / cells.length);
int tileHeight = (int) Math.floor(BOARD_HEIGHT / cells[0].length);
int col = (int) Math.floor(e.getX() / tileWidth);
int row = (int) Math.floor(e.getY() / tileHeight);
setPlayer(row, col);
}
void setPlayer(int row, int col) {
if (col < cells.length && row < cells[0].length) {
if (cells[row][col] == 0) {
cells[row][col] = player;
player = player == 'X' ? 'O' : 'X';
repaint();
}
}
}
Also, you should use paintComponent(g) instead of paint(g).
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class TicTacToe implements Runnable {
public static final String TITLE = "TicTacToe";
#Override
public void run() {
JFrame frame = new JFrame(TITLE);
Board board = new Board();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(board);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setResizable(false);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new TicTacToe());
}
private class Board extends JComponent implements MouseListener {
private static final long serialVersionUID = 5427550843122167512L;
public static final int BOARD_WIDTH = 256;
public static final int BOARD_HEIGHT = 256;
private char[][] cells = new char[3][3];
private char player = 'X';
private int fontHeight = 110;
private Font font = new Font("monospaced", Font.PLAIN, fontHeight);
public Board() {
this.setPreferredSize(new Dimension(BOARD_WIDTH, BOARD_HEIGHT));
this.addMouseListener(this);
}
#Override
protected void paintComponent(Graphics g) {
g.setFont(font);
drawBoard(g);
drawValues(g);
}
private void drawBoard(Graphics g) {
int tileWidth = BOARD_WIDTH / cells.length;
int tileHeight = BOARD_HEIGHT / cells[0].length;
g.drawRect(0, 0, BOARD_WIDTH, BOARD_HEIGHT);
for (int row = 0; row < cells.length; row++) {
g.drawLine(0, row * tileHeight, BOARD_WIDTH, row * tileHeight);
}
for (int col = 0; col < cells[0].length; col++) {
g.drawLine(col * tileWidth, 0, col * tileWidth, BOARD_HEIGHT);
}
}
private void drawValues(Graphics g) {
int tileWidth = BOARD_WIDTH / cells.length;
int tileHeight = BOARD_HEIGHT / cells[0].length;
for (int row = 0; row < cells.length; row++) {
for (int col = 0; col < cells[row].length; col++) {
String text = cells[row][col] + "";
int charWidth = g.getFontMetrics().stringWidth(text);
int xOffset = (int) Math.floor((tileWidth - charWidth) / 2);
int yOffset = (int) Math.floor((tileHeight - fontHeight) * 1.5);
int x = col * tileWidth + xOffset;
int y = row * tileHeight + fontHeight + yOffset;
System.out.println(yOffset);
g.drawString(text, x, y);
}
}
}
private void setPlayer(int row, int col) {
if (col < cells.length && row < cells[0].length) {
if (cells[row][col] == 0) {
cells[row][col] = player;
player = player == 'X' ? 'O' : 'X';
repaint();
}
}
}
#Override
public void mousePressed(MouseEvent e) {
int tileWidth = (int) Math.floor(BOARD_WIDTH / cells.length);
int tileHeight = (int) Math.floor(BOARD_HEIGHT / cells[0].length);
int col = (int) Math.floor(e.getX() / tileWidth);
int row = (int) Math.floor(e.getY() / tileHeight);
setPlayer(row, col);
}
#Override
public void mouseClicked(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseEntered(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseExited(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseReleased(MouseEvent e) {
// TODO Auto-generated method stub
}
}
}
Related
I am writing a video game GUI and I want to firstly open a frame with a menu bar and when the user clicks on play in the menu a JPanel that is in a different class gets added to the current one and it ends up with a frame containing the menu bar and the JPanel. When I run the code bellow I don't get any errors and the console initiates the process. The problem is nothing shows on the screen?? Not the initial frame or anything else.
The code for the frame that calls the class with the JPanel is:
/*-----------------------------------------------------------------------------------------------------*/
package Testes;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class Tetris extends JFrame{
private static final long serialVersionUID = 1L;
public static final int WIDTH = 250;
public static final int HEIGHT = 490;
public Tetris() {
JFrame frame = new JFrame();
TetrisBoard janela = new TetrisBoard();
JMenuBar menubar = new JMenuBar();
JMenu start = new JMenu("Start");
JMenuItem play = new JMenuItem("Play");
play.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
janela.startGame();
}
});
start.add(play);
JMenuItem exit = new JMenuItem("Exit");
exit.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
System.exit(0);
}
});
start.add(exit);
JMenu help = new JMenu("Help");
JMenuItem manual = new JMenuItem("User Manual");
manual.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
JOptionPane.showMessageDialog(null, "The goal of Tetris is to eliminate \nas many lines as possible before\n the Tetrominoes reach the top.\nControls:\n\u2190 - Move Left\n\u2192 - Move Right\n\u2193 - Drop\n" +
"C - Rotate AntiClockwise\nV - Rotate Clockwise\nP - Pause\nEsc - Quit","Instructions", JOptionPane.OK_OPTION, new ImageIcon());
}
});
help.add(manual);
JMenuItem about = new JMenuItem("About");
about.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
JLabel label = new JLabel("<html><center>Tetris made by GG<br>MEEC<br>2020<html>");
label.setHorizontalAlignment(SwingConstants.CENTER);
JOptionPane.showMessageDialog(null, label, "About", JOptionPane.INFORMATION_MESSAGE);
}
});
help.add(about);
menubar.add(start);
menubar.add(help);
frame.add(janela,BorderLayout.CENTER);
frame.add(menubar,BorderLayout.NORTH);
janela.setFocusable(true);
frame.setTitle("Tetris");
frame.setLayout(new BorderLayout());
frame.setSize(250, 490);
//setPreferredSize(new Dimension(255, 495));
frame.setResizable(false);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
frame.pack();
}
public static void main(String[] args) {
new Tetris();
}
}
/*-----------------------------------------------------------------------------------------------------*/
And the class with the JPanel is:
/*-----------------------------------------------------------------------------------------------------*/
package Testes;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Random;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingConstants;
import javax.swing.UIManager;
public class TetrisBoard extends JPanel implements KeyListener/*, ActionListener*/{
private static final long serialVersionUID = 1L;
public static final int COLOR_MIN = 35;
public static final int COLOR_MAX = 255 - COLOR_MIN;
public static final int BORDER_WIDTH = 5;
public static final int COL_COUNT = 10;
public static final int VISIBLE_ROW_COUNT = 20;
public static final int HIDDEN_ROW_COUNT = 2;
public static final int ROW_COUNT = VISIBLE_ROW_COUNT + HIDDEN_ROW_COUNT;
public static final int TILE_SIZE = 24;
public static final int SHADE_WIDTH = 4;
private static final int CENTER_X = COL_COUNT * TILE_SIZE / 2;
public static final int CENTER_Y = VISIBLE_ROW_COUNT * TILE_SIZE / 2;
public static final int PANEL_WIDTH = COL_COUNT * TILE_SIZE + BORDER_WIDTH * 2;
public static final int PANEL_HEIGHT = VISIBLE_ROW_COUNT * TILE_SIZE + BORDER_WIDTH * 2;
public static final Font LARGE_FONT = new Font("Tahoma", Font.BOLD, 16);
public static final Font SMALL_FONT = new Font("Tahoma", Font.BOLD, 12);
public static final long FRAME_TIME = 20L;
public static final int TYPE_COUNT = TileType.values().length;
public boolean isPaused;
public boolean isNewGame;
public boolean isGameOver;
public int level;
public int score;
public Random random;
public Clock logicTimer;
public TileType currentType;
public TileType nextType;
public int currentCol;
private int currentRow;
public int currentRotation;
public int dropCooldown;
public float gameSpeed;
public String difficulty = "Easy";
public int newLevel;
public int lines;
public int cleared;
public TileType[][] tiles;
public TetrisBoard() {
addKeyListener(this);
this.tiles = new TileType[ROW_COUNT][COL_COUNT];
setPreferredSize(new Dimension(PANEL_WIDTH, PANEL_HEIGHT));
setBackground(Color.BLACK);
startGame();
}
public void clear() {
for(int i = 0; i < ROW_COUNT; i++) {
for(int j = 0; j < COL_COUNT; j++) {
tiles[i][j] = null;
}
}
}
public boolean isValidAndEmpty(TileType type, int x, int y, int rotation) {
if(x < -type.getLeftInset(rotation) || x + type.getDimension() - type.getRightInset(rotation) >= COL_COUNT) {
return false;
}
if(y < -type.getTopInset(rotation) || y + type.getDimension() - type.getBottomInset(rotation) >= ROW_COUNT) {
return false;
}
for(int col = 0; col < type.getDimension(); col++) {
for(int row = 0; row < type.getDimension(); row++) {
if(type.isTile(col, row, rotation) && isOccupied(x + col, y + row)) {
return false;
}
}
}
return true;
}
public void addPiece(TileType type, int x, int y, int rotation) {
for(int col = 0; col < type.getDimension(); col++) {
for(int row = 0; row < type.getDimension(); row++) {
if(type.isTile(col, row, rotation)) {
setTile(col + x, row + y, type);
}
}
}
}
public int checkLines() {
int completedLines = 0;
for(int row = 0; row < ROW_COUNT; row++) {
if(checkLine(row)) {
completedLines++;
}
}
return completedLines;
}
public boolean checkLine(int line) {
for(int col = 0; col < COL_COUNT; col++) {
if(!isOccupied(col, line)) {
return false;
}
}
for(int row = line - 1; row >= 0; row--) {
for(int col = 0; col < COL_COUNT; col++) {
setTile(col, row + 1, getTile(col, row));
}
}
return true;
}
public boolean isOccupied(int x, int y) {
return tiles[y][x] != null;
}
public void setTile(int x, int y, TileType type) {
tiles[y][x] = type;
}
public TileType getTile(int x, int y) {
return tiles[y][x];
}
//#Override
public void paintComponent(Graphics g) {
this.paintComponent(g);
g.translate(BORDER_WIDTH, BORDER_WIDTH);
if(isPaused()) {
g.setFont(LARGE_FONT);
g.setColor(Color.GREEN);
String msg = "PAUSED";
g.drawString(msg, CENTER_X - g.getFontMetrics().stringWidth(msg) / 2, CENTER_Y);
} else if(isNewGame() || isGameOver()) {
g.setFont(LARGE_FONT);
g.setColor(Color.WHITE);
g.setColor(Color.GREEN);
String msg = isNewGame() ? "TETRIS" : "GAME OVER";
g.drawString(msg, CENTER_X - g.getFontMetrics().stringWidth(msg) / 2, 150);
g.setFont(SMALL_FONT);
msg = "Press Enter to Play" + (isNewGame() ? "" : " Again");
g.drawString(msg, CENTER_X - g.getFontMetrics().stringWidth(msg) / 2, 300);
} else {
for(int x = 0; x < COL_COUNT; x++) {
for(int y = HIDDEN_ROW_COUNT; y < ROW_COUNT; y++) {
TileType tile = getTile(x, y);
if(tile != null) {
drawTile(tile, x * TILE_SIZE, (y - HIDDEN_ROW_COUNT) * TILE_SIZE, g);
}
}
}
TileType type = getPieceType();
int pieceCol = getPieceCol();
int pieceRow = getPieceRow();
int rotation = getPieceRotation();
for(int col = 0; col < type.getDimension(); col++) {
for(int row = 0; row < type.getDimension(); row++) {
if(pieceRow + row >= 2 && type.isTile(col, row, rotation)) {
drawTile(type, (pieceCol + col) * TILE_SIZE, (pieceRow + row - HIDDEN_ROW_COUNT) * TILE_SIZE, g);
}
}
}
g.setColor(Color.DARK_GRAY);
for(int x = 0; x < COL_COUNT; x++) {
for(int y = 0; y < VISIBLE_ROW_COUNT; y++) {
g.drawLine(0, y * TILE_SIZE, COL_COUNT * TILE_SIZE, y * TILE_SIZE);
g.drawLine(x * TILE_SIZE, 0, x * TILE_SIZE, VISIBLE_ROW_COUNT * TILE_SIZE);
}
}
}
g.setColor(Color.GREEN);
g.drawRect(0, 0, TILE_SIZE * COL_COUNT, TILE_SIZE * VISIBLE_ROW_COUNT);
}
public void drawTile(TileType type, int x, int y, Graphics g) {
drawTile(type.getBaseColor(), type.getLightColor(), type.getDarkColor(), x, y, g);
}
public void drawTile(Color base, Color light, Color dark, int x, int y, Graphics g) {
g.setColor(base);
g.fillRect(x, y, TILE_SIZE, TILE_SIZE);
g.setColor(dark);
g.fillRect(x, y + TILE_SIZE - SHADE_WIDTH, TILE_SIZE, SHADE_WIDTH);
g.fillRect(x + TILE_SIZE - SHADE_WIDTH, y, SHADE_WIDTH, TILE_SIZE);
g.setColor(light);
for(int i = 0; i < SHADE_WIDTH; i++) {
g.drawLine(x, y + i, x + TILE_SIZE - i - 1, y + i);
g.drawLine(x + i, y, x + i, y + TILE_SIZE - i - 1);
}
}
public void startGame() {
this.random = new Random();
this.isNewGame = true;
if(this.difficulty.equals("Easy")) {
this.gameSpeed=1.0f;
}else if(this.difficulty.equals("Intermediate")) {
this.gameSpeed=3.0f;
}else if(this.difficulty.equals("Hard")) {
this.gameSpeed=6.0f;
}
this.level=1;
this.cleared=0;
this.newLevel=0;
this.logicTimer = new Clock(gameSpeed);
logicTimer.setPaused(true);
while(true) {
long start = System.nanoTime();
logicTimer.update();
if(logicTimer.hasElapsedCycle()) {
updateGame();
}
//Decrement the drop cool down if necessary.
if(dropCooldown > 0) {
dropCooldown--;
}
renderGame();
long delta = (System.nanoTime() - start) / 1000000L; // delta in miliseconds
if(delta < FRAME_TIME) {
try {
Thread.sleep(FRAME_TIME - delta); // sleeps the difference between the fps and the time for the game to process (delta)
} catch(Exception e) {
e.printStackTrace();
}
}
}
}
public void updateGame() {
if(isValidAndEmpty(currentType, currentCol, currentRow + 1, currentRotation)) {
currentRow++;
} else {
addPiece(currentType, currentCol, currentRow, currentRotation);
cleared = checkLines();
if(cleared > 0) {
lines += cleared;
score += 50 << cleared; // left bit shift - add the number of zeros on the right to the binary version of the number on the right
// score = score + 50 << cleared;
}
//newLevel+=cleared;
gameSpeed += 0.035f;
logicTimer.setCyclesPerSecond(gameSpeed);
logicTimer.reset();
dropCooldown = 25;
if(newLevel<10) {
newLevel+=cleared;
}else if(newLevel>=10) {
level+=1;
newLevel=0;
cleared=0;
}
spawnPiece();
}
}
public void renderGame() {
repaint();
}
public void resetGame() {
this.level = 1;
this.score = 0;
this.lines = 0;
this.newLevel = 0;
this.cleared = 0;
if(this.difficulty.equals("Easy")) {
this.gameSpeed=1.0f;
}else if(this.difficulty.equals("Intermediate")) {
this.gameSpeed=3.0f;
}else if(this.difficulty.equals("Hard")) {
this.gameSpeed=6.0f;
}
this.nextType = TileType.values()[random.nextInt(TYPE_COUNT)];
this.isNewGame = false;
this.isGameOver = false;
clear();
logicTimer.reset();
logicTimer.setCyclesPerSecond(gameSpeed);
spawnPiece();
}
public void spawnPiece() {
this.currentType = nextType;
this.currentCol = currentType.getSpawnColumn();
this.currentRow = currentType.getSpawnRow();
this.currentRotation = 0;
this.nextType = TileType.values()[random.nextInt(TYPE_COUNT)];
if(!isValidAndEmpty(currentType, currentCol, currentRow, currentRotation)) {
lose();
}
}
public void lose()
{
this.isGameOver = true;
logicTimer.setPaused(isPaused);
String info = "";
if (score>HighScore.getHighScores()[9].getScore())
{
info="You got a high score!\n<br>Please enter you name.\n<br>(Note: Only 10 characters will be saved)";
JLabel label = new JLabel("<html><center>GAME OVER\n<br>" + info);
label.setHorizontalAlignment(SwingConstants.CENTER);
String name=JOptionPane.showInputDialog(null, label,"Tetris", JOptionPane.INFORMATION_MESSAGE);
if (name!=null) {
HighScore.addHighScore(new HighScore(score,level,lines,(name.length()>10)?name.substring(0, 10):name,(difficulty.length()>12)?difficulty.substring(0, 12):difficulty));
}
}else {
info="You didn't get a high score:( \n<br>Keep trying you will get it next time!";
JLabel label = new JLabel("<html><center>GAME OVER\n<br>" + info);
label.setHorizontalAlignment(SwingConstants.CENTER);
JOptionPane.showMessageDialog(null, label, "Tetris", JOptionPane.PLAIN_MESSAGE);
}
if (JOptionPane.showConfirmDialog(null, "Do you want to play again?",
"Tetris", JOptionPane.YES_NO_OPTION)==JOptionPane.YES_OPTION) {
this.score=0;
this.level=0;
this.lines=0;
startGame();
}else
{
//If not, quit
System.exit(0);
}
}
public void rotatePiece(int newRotation) {
int newColumn = currentCol;
int newRow = currentRow;
int left = currentType.getLeftInset(newRotation);
int right = currentType.getRightInset(newRotation);
int top = currentType.getTopInset(newRotation);
int bottom = currentType.getBottomInset(newRotation);
if(currentCol < -left) {
newColumn -= currentCol - left;
} else if(currentCol + currentType.getDimension() - right >= COL_COUNT) {
newColumn -= (currentCol + currentType.getDimension() - right) - COL_COUNT + 1;
}
if(currentRow < -top) {
newRow -= currentRow - top;
} else if(currentRow + currentType.getDimension() - bottom >= ROW_COUNT) {
newRow -= (currentRow + currentType.getDimension() - bottom) - ROW_COUNT + 1;
}
if(isValidAndEmpty(currentType, newColumn, newRow, newRotation)) {
currentRotation = newRotation;
currentRow = newRow;
currentCol = newColumn;
}
}
public boolean isPaused() {
return isPaused;
}
public boolean isGameOver() {
return isGameOver;
}
public boolean isNewGame() {
return isNewGame;
}
public int getScore() {
return score;
}
public int getLevel() {
return level;
}
public String getDiff(){
return difficulty;
}
public int getLines() {
return lines;
}
public TileType getPieceType() {
return currentType;
}
public TileType getNextPieceType() {
return nextType;
}
public int getPieceCol() {
return currentCol;
}
public int getPieceRow() {
return currentRow;
}
public int getPieceRotation() {
return currentRotation;
}
//#Override
public void keyPressed(KeyEvent e) {
switch(e.getKeyCode()) {
case KeyEvent.VK_DOWN:
if(!isPaused && dropCooldown == 0) {
logicTimer.setCyclesPerSecond(25.0f);
}
break;
case KeyEvent.VK_LEFT:
if(!isPaused && isValidAndEmpty(currentType, currentCol - 1, currentRow, currentRotation)) {
currentCol--;
}
break;
case KeyEvent.VK_RIGHT:
if(!isPaused && isValidAndEmpty(currentType, currentCol + 1, currentRow, currentRotation)) {
currentCol++;
}
break;
case KeyEvent.VK_C:
if(!isPaused) {
rotatePiece((currentRotation == 0) ? 3 : currentRotation - 1);
}
break;
case KeyEvent.VK_V:
if(!isPaused) {
rotatePiece((currentRotation == 3) ? 0 : currentRotation + 1);
}
break;
case KeyEvent.VK_P:
if(!isGameOver && !isNewGame) {
isPaused = !isPaused;
logicTimer.setPaused(isPaused);
}
break;
case KeyEvent.VK_ENTER:
if(isGameOver || isNewGame) {
resetGame();
}
break;
case KeyEvent.VK_ESCAPE:
int ans = JOptionPane.showConfirmDialog(null, "Are you sure you want to quit?\n", "Tetris", JOptionPane.INFORMATION_MESSAGE);
if(ans==1 || ans==2) {
//isPaused = !isPaused;
//logicTimer.setPaused(isPaused);
return;
}else if(ans==0) {
System.exit(0);
}
}
}
}
//#Override
public void keyReleased(KeyEvent e) {
switch(e.getKeyCode()) {
case KeyEvent.VK_S:
logicTimer.setCyclesPerSecond(gameSpeed);
logicTimer.reset();
break;
}
}
#Override
public void keyTyped(KeyEvent e) {}
}
First of all, dont add a JMenuBar by frame.add(myJMenuBar,someConstraints). Do it by calling the method frame.setJMenuBar(myJMenuBar);
Secondly, you add the components into the frame (its content pane), and after that you frame.setLayout(new BorderLayout());, while you should first set the layout and AFTER add the components to it:
frame.setLayout(new BorderLayout());
frame.add(janela, BorderLayout.CENTER);
This works:
You might notice it replaces the ridiculously long & complicated TetrisBoard with a red panel with a preferred size of 400 x 200. This is how you should figure such things out. Post a minimal reproducible example in future.
import java.awt.*;
import javax.swing.*;
public class Tetris extends JFrame {
public Tetris() {
JFrame frame = new JFrame();
JPanel janela = new JPanel();
janela.setBackground(Color.RED);
janela.setPreferredSize(new Dimension(400,200));
JMenuBar menubar = new JMenuBar();
JMenu start = new JMenu("Start");
JMenuItem play = new JMenuItem("Play");
start.add(play);
JMenuItem exit = new JMenuItem("Exit");
start.add(exit);
JMenu help = new JMenu("Help");
JMenuItem manual = new JMenuItem("User Manual");
help.add(manual);
JMenuItem about = new JMenuItem("About");
help.add(about);
menubar.add(start);
menubar.add(help);
frame.add(janela, BorderLayout.CENTER);
frame.setJMenuBar(menubar);
janela.setFocusable(true);
frame.setTitle("Tetris");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
new Tetris();
}
}
The program is supposed to make a grid where all rectangles start black and if clicked or dragged they turn white. So far my program is able to make the rectangle you click or drag white, but it doesn't memorize or remember which one I clicked to make them stay white until you click them again. Maybe I would call the change using the mouse listener or maybe by creating an LinkedList , I just can't figure out the easiest solution.
public class Clicky extends JFrame {
private static class Board extends JPanel {
private double BRICK_WIDTH = 20;
private double BRICK_HEIGHT = 20;
public Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
public double width = screenSize.getWidth();
public double height = screenSize.getHeight();
private int COLS = (int)(width/BRICK_WIDTH);
private int ROWS =(int)(height/BRICK_HEIGHT);
private Color CO = Color.BLACK;
public Board() {
System.out.println("WIdth:" + COLS + "Height:" + ROWS);
setBackground(Color.BLACK);
addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
mx = e.getX();
my = e.getY();
System.out.printf("X: %d Y: %d ", mx, my);
repaint();
}
});
addMouseMotionListener(new MouseMotionListener() {
#Override
public void mouseDragged(MouseEvent e) {
mx = e.getX();
my = e.getY();
}
#Override
public void mouseMoved(MouseEvent e) {
}
});
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
drawBricks(g);
}
private double x;
private double y;
private void drawBricks(Graphics g) {
Graphics2D brick = (Graphics2D) g.create();
x = 0;
y = 0;
for (int j = 0; j <= ROWS; j++)
{
for (int a = 0; a <= COLS; a++) {
brick.setColor(Color.BLACK);
Rectangle2D.Double rect = new Rectangle2D.Double(x, y, BRICK_WIDTH, BRICK_HEIGHT);
brick.fill(rect);
if (mx > x && mx < x + BRICK_WIDTH && my > y && my < y + BRICK_HEIGHT) {
if (brick.getColor() == Color.BLACK) {
CO = Color.white;
brick.setColor(CO);
brick.fill(rect);
repaint();
}
else {
CO = Color.BLACK;
brick.setColor(CO);
brick.fill(rect);
repaint();
}
}
brick.setColor(Color.gray);
brick.draw(rect);
x += BRICK_WIDTH;
}
repaint();
x = 0;
y += BRICK_HEIGHT;
}
}
public int mx = -100;
public int my = -100;
}
public Clicky() {
setDefaultCloseOperation(EXIT_ON_CLOSE); //mai bine cu exit on close
setSize(800, 820);
add(new Board());
}
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new Clicky().setVisible(true);
}
});
}
An easy solution is to use an 2-dimensional boolean array that represents the status of rectangles. When the color changes, change the value of the array-element and set the color depending on it:
public class Clicky extends JFrame {
private static class Board extends JPanel {
private double BRICK_WIDTH = 20;
private double BRICK_HEIGHT = 20;
public Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
public double width = screenSize.getWidth();
public double height = screenSize.getHeight();
private int COLS = (int) (width / BRICK_WIDTH);
private int ROWS = (int) (height / BRICK_HEIGHT);
private Color CO = Color.BLACK;
private boolean[][] isWhite = new boolean[COLS + 1][ROWS + 1];
public Board() {
System.out.println("WIdth:" + COLS + "Height:" + ROWS);
setBackground(Color.BLACK);
addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
mx = e.getX();
my = e.getY();
System.out.printf("X: %d Y: %d ", mx, my);
isWhite[(int) (mx / BRICK_WIDTH)][(int) (my
/ BRICK_HEIGHT)] = !isWhite[(int) (mx / BRICK_WIDTH)][(int) (my / BRICK_HEIGHT)];
repaint();
}
});
addMouseMotionListener(new MouseMotionListener() {
#Override
public void mouseDragged(MouseEvent e) {
mx = e.getX();
my = e.getY();
isWhite[(int) (mx / BRICK_WIDTH)][(int) (my
/ BRICK_HEIGHT)] = !isWhite[(int) (mx / BRICK_WIDTH)][(int) (my / BRICK_HEIGHT)];
}
#Override
public void mouseMoved(MouseEvent e) {
}
});
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
drawBricks(g);
}
private double x;
private double y;
private void drawBricks(Graphics g) {
Graphics2D brick = (Graphics2D) g.create();
x = 0;
y = 0;
for (int j = 0; j <= ROWS; j++) {
for (int a = 0; a <= COLS; a++) {
if (isWhite[a][j]) {
brick.setColor(Color.WHITE);
} else {
brick.setColor(Color.BLACK);
}
Rectangle2D.Double rect = new Rectangle2D.Double(x, y, BRICK_WIDTH, BRICK_HEIGHT);
brick.fill(rect);
brick.setColor(Color.gray);
brick.draw(rect);
x += BRICK_WIDTH;
}
repaint();
x = 0;
y += BRICK_HEIGHT;
}
}
public int mx = -100;
public int my = -100;
}
public Clicky() {
setDefaultCloseOperation(EXIT_ON_CLOSE); // mai bine cu exit on close
setSize(800, 820);
add(new Board());
}
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new Clicky().setVisible(true);
}
});
}
}
I am trying to make a Mandelbrot program that allows zooming, but the zoom doesn't seem to be working, and i don't see what is wrong with the way i have implemented the zoom.I am using eclipse and the program doesn't return any errors. Here is my code:
import java.awt.Graphics;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import javax.swing.JFrame;
public class Mandelbrot extends JFrame {
private final int MAX_ITER = 570;
private static double ZOOM = 200;
private BufferedImage I;
private double zx, zy, cX, cY, tmp;
public static boolean zooming = false;
public Mandelbrot()
{
super("MandelbrotSet");
setBounds(100, 100, 800, 600);
setResizable(false);
setDefaultCloseOperation(EXIT_ON_CLOSE);
I = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_RGB);
for (int y = 0; y < getHeight(); y++) {
for (int x = 0; x < getWidth(); x++) {
zx = zy = 0;
cX = (x - 400) / ZOOM;
cY = (y - 300) / ZOOM;
int iter = MAX_ITER;
while (zx * zx + zy * zy < 4 && iter > 0) {
tmp = zx * zx - zy * zy + cX;
zy = 2.0 * zx * zy + cY;
zx = tmp;
iter--;
}
I.setRGB(x, y, iter | (iter << 8));
}
}
setVisible(true);
while(1>0)
{
if(zooming)
{
revalidate();
repaint();
System.out.println("zooming");
zooming = false;
}
} }
#Override
public void paint(Graphics g) {
g.drawImage(I, 0, 0, this);
}
public static void main(String[] args) {
new Mandelbrot().addMouseWheelListener(new MouseWheelListener(){ public void mouseWheelMoved(MouseWheelEvent
e) {
if (e.getWheelRotation() < 0) {
ZOOM=ZOOM+100;
zooming = true;
} else
{
ZOOM=ZOOM-100;
zooming = true;
} } });
} }
Your constructor contains an endless loop. It therefore never returns and your MouseWheelListener is never added to the frame.
You calculate the BufferedImage exactly once (before the endless loop), so even if you would attach the MouseWheelListener before the loop it would have no effect.
I would move the calculation of the picture into its own method, call this method once from the constructor and once from your MouseWheelListener and remove the endless loop from the constructor.
public Mandelbrot()
{
super("MandelbrotSet");
//...
I = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_RGB);
calculatePicture();
setVisible(true);
}
public void calculatePicture() {
for (int y = 0; y < getHeight(); y++) {
//...
}
repaint();
}
public static void main(String[] args) {
new Mandelbrot().addMouseWheelListener(new MouseWheelListener(){
public void mouseWheelMoved(MouseWheelEvent
e) {
//...
calculatePicture();
}
});
}
I'm programming a Game called "Kulami". It is a board game for two players.The board is build with rectangular plates different by size. I can sign all plates I need, but I can't move them, the MouseMotionListener doesn't work. A rectangular plate is signed, but there is no contact to press the mouse. I can't find the mistake. Can anyone show on my code and help me?
Thanks!
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import Model.EFieldStateMarble;
import Model.EFieldStatePlate;
public class Plate extends JPanel {
// Eigenschaften
public String plate[][];
// Konstruktor
public Plate(int r, int c, EFieldStatePlate fieldStatePlate, EFieldStateMarble fieldStateMarble) {
plate = new String[r][c];
for (r = 0; r < plate.length; r++) { // waagerecht
for (c = 0; c < plate[r].length; c++) { // senkrecht
plate[r][c] = fieldStatePlate.toString() + fieldStateMarble.toString(); // Codierung Feld
}
}
}
// Methoden
public void showPlate() { // Konsolenausgabe Spielfeldplatte
for (int r = 0; r < plate.length; r++) {
for (int c = 0; c < plate[r].length; c++) {
System.out.print(plate[r][c]);
}
System.out.println();
}
}
// Ändert Eintrage in r-ter Reihe und c-ter Spalte
public void setEntryAt(int r, int c, EFieldStatePlate fieldStatePlate, EFieldStateMarble fieldStateMarble) {
plate[r][c] = fieldStatePlate.toString() + fieldStateMarble.toString();
}
public String[][] getPlate() {
return plate;
}
// dreht das Array um 90°
public void turnPlate() {
int m = plate.length;
int n = plate[0].length;
String[][] returnPlate = new String[n][m];
for (int r = 0; r < plate.length; r++) {
for (int c = 0; c < plate[0].length; c++) {
returnPlate[c][m - 1 - r] = plate[r][c];
}
}plate = returnPlate;
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
drawPlate(g2d, 60, 60);
}
private void drawPlateField(Graphics2D g2d, int x, int y) {
int posX = x;
int posY = y;
g2d.setColor(Color.BLACK);
g2d.drawRect(posX, posY, 60, 60);
g2d.setColor(new Color(242, 203, 130));
g2d.fillRect(posX + 1, posY + 1, 59, 59);
g2d.setColor(Color.BLACK);
g2d.drawOval(x + 15, y + 15, 30, 30);
g2d.setColor(new Color(242, 203, 130));
g2d.fillOval(x + 16, y + 16, 29, 29);
}
private void drawPlate(Graphics g2d, int plateX, int plateY ) {
try {
for (int r = 0; r < plate.length; r++) {
for (int c = 0; c < plate[0].length; c++) {
drawPlateField((Graphics2D) g2d, plateX + c * 60, plateY + r * 60);
}
}
} catch (Exception e) {
System.out.print(e);
}
}
private class PlateDragged implements MouseListener, MouseMotionListener {
//Plattengröße
int platesizeX = plate.length;
int platesizeY = plate[0].length;
//Plattenkoordinaten
int plateX = 60;
int plateY = 60;
//Position, von der die Maus die Platte zieht
int dragFromX = 0;
int dragFromY = 0;
//bei "true" kann die Platte nach Mausklick gezogen werden
boolean candrag = false;
public void mousePressed(MouseEvent mmp) {
new Thread() {
#Override
public void run() {
int x = mmp.getX();
int y = mmp.getY();
if (x >= plateX && x <= (plateX + platesizeY) && y >= plateY && y <= (plateY + platesizeX)) {
candrag = true;
dragFromX = x - plateX;
dragFromY = y - plateY;
}
else {
candrag = false;
}
System.out.println("Hallo");
}
}.start();
}
#Override
public void mouseDragged(MouseEvent mmd) {
new Thread() {
#Override
public void run() {
if (candrag) {
//Plattenposition wechseln
plateX = mmd.getX() - dragFromX;
plateY = mmd.getY() - dragFromY;
//Entferne die Platte nicht aus dem Fenster
plateX = Math.max(plateX, 0);
plateX = Math.min(plateX, getWidth() - platesizeY);
plateY = Math.max(plateY, 0);
plateY = Math.min(plateY, getHeight() - platesizeX);
repaint();
}
}
}.start();
}
public void mouseExited(MouseEvent mme) {
candrag = false;
}
#Override
public void mouseMoved(MouseEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void mouseClicked(MouseEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void mouseEntered(MouseEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void mouseReleased(MouseEvent arg0) {
// TODO Auto-generated method stub
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
// Plate plate = new Plate();
#Override
public void run() {
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Plate g2d = new Plate(2, 3, EFieldStatePlate.B6, EFieldStateMarble.EMPTY);
g2d.setPreferredSize(new Dimension(650, 650));
f.add(g2d);
f.pack();
f.setLocation(200, 800);
f.setVisible(true);
}
});
}
}
No where in your code is there a call to addMouseListener(...) or addMouseMotionListener(...). You need to add a listener to a Swing component for the listener to work -- In other words, a listener has to listen to something. e.g.,
// Konstruktor
public Plate(int r, int c, EFieldStatePlate fieldStatePlate,
EFieldStateMarble fieldStateMarble) {
plate = new String[r][c];
for (r = 0; r < plate.length; r++) {
for (c = 0; c < plate[r].length; c++) {
plate[r][c] = fieldStatePlate.toString() + fieldStateMarble.toString();
}
}
// ***** added *****
PlateDragged plateDragged = new PlateDragged();
addMouseListener(plateDragged);
addMouseMotionListener(plateDragged);
}
Frankly questions of this nature, so basic with regards to MouseListener use suggest that you're coding by guessing and without studying the tutorial first. For your sake, don't do this. Please check the MouseListener Tutorial.
Other issue: why are you creating a thread off of the Swing event thread and calling code from it?
I am creating a simple game where shapes fall and the player shoots them, but I am having problems creating bullet at every click of the mouse. I have tried various logic with no help, so am just going to put the code up here so you guys can take a look at it and help me out.
The bullet I created is not been created on every click just one is created and it moves on every click which is wrong........I want one bullet to be created per click.
// My main class: mousework2
import java.awt.event.*;
import javax.swing.*;
import java.awt.*;
import java.util.*;
import java.awt.geom.*;
public class mousework2 extends JFrame
{
public static int Width = 300;
public static int Height = 400;
private JPanel p1;
private Image pixMage,gunMage;
public mousework2()
{
super("shoot-em-up");
this.setSize(Width, Height);
this.setResizable(true);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Dimension pos = Toolkit.getDefaultToolkit().getScreenSize();
int x = (pos.width - Width) / 2;
int y = (pos.height - Height) / 2;
this.setLocation(x, y);
p1 = new CreateImage();
this.add(p1);
this.getContentPane();
Thread t = new recMove(this);
t.start();
}
class recMove extends Thread
{
JFrame b;
public recMove(JFrame b)
{
this.b = b;
}
public void run()
{
while (true) {
b.repaint();
try {
Thread.sleep(50);
} catch (InterruptedException e) {
}
}
}
}
class CreateImage extends JPanel implements MouseListener
{
ArrayList<fallShape> rect = new ArrayList<fallShape>();
int x_pos = mousework.Width / 2;
int y_pos = mousework.Height - 50;
int bx_pos = mousework.Width / 2;
int by_pos = mousework.Height;
int y_speed = -10;
boolean clicked;
public CreateImage()
{
for (int i = 0; i < 10; i++) {
rect.add(new fallShape(15, 15, rect));
}
Toolkit picx = Toolkit.getDefaultToolkit();
gunMage = picx.getImage("gunner.jpg");
gunMage = gunMage.getScaledInstance(200, -1, Image.SCALE_SMOOTH);
Toolkit pic = Toolkit.getDefaultToolkit();
pixMage = pic.getImage("ballfall3.jpg");
pixMage = pixMage.getScaledInstance(200, -1, Image.SCALE_SMOOTH);
addMouseListener(this);
addMouseMotionListener(new MouseMotionAdapter() {
#Override
public void mouseMoved(MouseEvent e)
{
x_pos = e.getX() - 5;
}
});
}
public void mousePressed(MouseEvent e)
{
if (e.getButton() == 1) {
clicked = true;
}
}
public void mouseReleased(MouseEvent e)
{
if (e.getButton() == 1) {
clicked = false;
}
}
public void mouseExited(MouseEvent e)
{
}
public void mouseEntered(MouseEvent e)
{
}
public void mouseClicked(MouseEvent e)
{
}
public void paint(Graphics g)
{
super.paint(g);
g.drawImage(pixMage, 0, 0, Width, Height, null);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g.drawImage(gunMage,x_pos,y_pos,10,20,null);
if (clicked) {
by_pos += y_speed;
Shape bullet = new Rectangle2D.Float(bx_pos, by_pos, 3, 10);
g2.setColor(Color.BLACK);
g2.fill(bullet);
g2.draw(bullet);
}
g2.setColor(Color.RED);
for (fallShape b : rect) {
b.move();
g2.fill(b);
}
}
}
public static void main(String[] args)
{
java.awt.EventQueue.invokeLater(new Runnable() {
#Override
public void run()
{
new mousework2().setVisible(true);
}
});
}
}
And:
// My falling shapes class: fallShape
import java.awt.geom.*;
import java.util.*;
public class fallShape extends Rectangle2D.Float
{
public int x_speed, y_speed;
public int l, b;
public int height = mousework.Height;
public int width = mousework.Width;
public ArrayList<fallShape> fall;
public fallShape(int breadth, int length, ArrayList<fallShape> fall)
{
super((int) (Math.random() * (mousework.Width - 20) + 1), 0, breadth, length);
this.b = breadth;
this.l = length;
this.x_speed = (int) Math.random() * (10) + 1;
this.y_speed = (int) Math.random() * (10) + 1;
this.fall = fall;
}
public void move()
{
Rectangle2D rec = new Rectangle2D.Float(super.x, super.y, b, l);
for (fallShape f : fall) {
if (f != this && f.intersects(rec)) {
int rxspeed = x_speed;
int ryspeed = y_speed;
x_speed = f.x_speed;
y_speed = f.y_speed;
f.x_speed = rxspeed;
f.y_speed = ryspeed;
}
}
if (super.x < 0) {
super.x =+ super.x;
//super.y =+ super.y;
x_speed = Math.abs(x_speed);
}
if (super.x> mousework.Width - 30) {
super.x =+ super.x;
super.y =+ super.y;
x_speed =- Math.abs(x_speed);
}
if (super.y < 0) {
super.y = 0;
y_speed = Math.abs(y_speed);
}
super.x += x_speed;
super.y += y_speed;
}
}
if(clicked){
by_pos+=y_speed;
This code only draws the bullet when the mouse is down. This is because you are setting clicked to false in your mouseReleased method:
public void mouseReleased(MouseEvent e){
if(e.getButton()==1)
clicked=false;
}
If you were to remove the body of the mouseReleased method, your bullet would move properly.
However, say you wanted to have more than just one bullet. Currently, your paint method only draws one bullet at a time. To draw multiple bullets, you would need to create a list of the coordinates of the bullets, and add a new coordinate pair to the list whenever you click. Then, in the paint method, just update each position in a for loop.
ArrayList<Integer> by_poss = new ArrayList<>();
by_poss is the list of all the y-positions of your bullets.
public void mousePressed(MouseEvent e){
if(e.getButton() == 1)
by_poss.add(mousework.Height);
}
The mousePressed method adds a new "bullet", in the form of a y-position, to the coordinates.
public void mouseReleased(MouseEvent e){
//do nothing
}
Nothing needs to happen in the mouseReleased method.
//update the bullets
public void paint(Graphics g){
...
g2.setColor(Color.BLACK);
Shape bullet;
for(int i = 0; i < by_poss.size(); i++){
by_poss.set(i, by_poss.get(i) + y_speed); //move the bullet
bullet = new Rectangle2D.Float(bx_pos, by_poss.get(i), 3, 10);
g2.fill(bullet);
g2.draw(bullet);
}
...
}
The for loop in your paint method draws all the bullets, one by one, usin g the y-positions from the by_poss list.