Related
I'm a newbie in Java and I'm trying to make a ship fire a bullet. What I want is actually make the ship fire bullets as long as the Spacebar button is being held down.
I've successfully made the ship move here and there and also fire the bullet. However the bullet just won't go up. Here's my code -
package learningPackage;
import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
public class Draw extends JFrame implements Runnable {
//Variables for the x and y coordinates, xDirection for modifying the values of x only.
int x, y, xDirection;
int bx, by;
Image dbImage;
Graphics dbGraphics;
boolean shot;
Rectangle bullet;
//Thread run
public void run() {
try {
while (true) {
move();
shoot();
//Setting sleep to 0 will make it light-speed!
Thread.sleep(5);
}
}
catch (Exception e) {
System.out.println("Error!");
}
}
//Ship move
//Ship moves only in one direction, x - axis
public void move() {
x += xDirection;
//Collision detection
if (x <= 10) {
x = 10;
}
if (x >= 415) {
x = 415;
}
}
//KeyListeners
public class AL extends KeyAdapter {
public void keyPressed(KeyEvent e) {
int keyCode = e.getKeyCode();
if (keyCode == e.VK_LEFT) {
xDirection = -2;
}
if (keyCode == e.VK_RIGHT) {
xDirection = 2;
}
if (keyCode == e.VK_SPACE) {
shot = true;
}
}
public void keyReleased(KeyEvent e) {
int keyCode = e.getKeyCode();
if (keyCode == e.VK_LEFT) {
xDirection = 0;
}
if (keyCode == e.VK_RIGHT) {
xDirection = 0;
}
if (keyCode == e.VK_SPACE) {
shot = false;
}
}
}
//Constructor for the game frame
public Draw() {
super("Game");
setSize(500, 500);
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setResizable(false);
addKeyListener(new AL());
x = 200;
y = 465;
setVisible(true);
}
//Double - buffering
public void paint(Graphics g) {
dbImage = createImage(getWidth(), getHeight());
dbGraphics = dbImage.getGraphics();
paintComponent(dbGraphics);
g.drawImage(dbImage, 0, 0, this);
}
//All the graphics
public void paintComponent(Graphics g) {
bullet = new Rectangle(bx, by, 10, 10);
g.setColor(Color.RED);
//Ship rectangle
g.fillRect(x, y, 75, 25);
//Gun rectangle
g.fillRect(x + 32, y - 15, 10, 15);
//Setting the same values for bx and by as x and y so that the bullet will start from the Gun rectangle
bx = x + 32;
by = y - 15;
if (shot == true) {
g.setColor(Color.BLACK);
g.fillRect(bx, by, bullet.width, bullet.height);
}
repaint();
}
public void shoot() {
if (shot == true) {
by = by - 2;
}
if (by <= -5) {
//Resetting values
bx = x + 32;
by = y - 15;
bullet = new Rectangle(bx, by, 10, 10);
shot = false;
}
}
//Main method
public static void main(String[] args) {
Draw gameTry = new Draw();
Thread t1 = new Thread(gameTry);
t1.start();
}
}
Here's what happens when I just move the ship, working perfectly fine -
Here's what happens when I hold down space -
(Sorry for not being able to embed pics in the post itself, I'm new to Stack Overflow as well!)
I was actually coping this code from a tutorial but since the tutorial-code wasn't working out, I decided to do this on my own, but I can't do it on my own as well!
Help will definitely be appreciated!
The reason for the bullet not moving becomes appearant when you compare your shoot() method, and the paintComponent method.
Shoot checks if you have the shot boolean set, and if so, moves the bullet y position up by 2.
When the bullet leaves the top of the screen, it resets the "bullet".
This is all fine, it does what it's supposed to.
public void shoot() {
if (shot == true) {
by = by - 2; //this is fine, it moves the bullet up
}
if (by <= -5) {
//Resetting values
bx = x + 32;
by = y - 15;
bullet = new Rectangle(bx, by, 10, 10);
shot = false;
}
}
Then comes paintComponent, which is executed time your game is "painted" to the screen.
It defines a rectangle for the bullet at its current position,
draws the ship,
Then overwrites the bullet's x and y position so it sits on top of the ship.
That is where your problem is
public void paintComponent(Graphics g) {
bullet = new Rectangle(bx, by, 10, 10);
g.setColor(Color.RED);
g.fillRect(x, y, 75, 25);
g.fillRect(x + 32, y - 15, 10, 15);
//you are messing with bx and by here.
//probably because you wanted the bullet to be in the
//same position as the ship.
//this means they will be put back into the same position
//for every time your game is painted to the screen.
//my advice is, do *not* do this here.
bx = x + 32;
by = y - 15;
if (shot == true) {
g.setColor(Color.BLACK);
g.fillRect(bx, by, bullet.width, bullet.height);
}
repaint();
}
I am trying to have each brick in my game have a random color, however when I try to do this the whole set of bricks become the same color. How do I make each individual brick a random color? Any help is appreciated.
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
public class Game extends JoeApplet implements KeyListener
{
String status;
int ballx = 294; // ball spawn x coordinate
int bally = 640; // ball spawn y coordinate
int batx = 294;
int baty = 654;
int brickx = 32;
int bricky = 50;
double movex = -16; // x speed of ball
double movey = -16; //y speed of ball
int count = 0;
int currentLevel=0;
int score=0; //starts score at 0
int lives=3; //lives start at 3
static boolean right = false;
static boolean left = false;
boolean ballFallDown = false;
boolean bricksOver = false;
Rectangle Ball = new Rectangle(ballx, bally, 14, 14); //creates ball
Rectangle Bat = new Rectangle(batx, baty, 100, 12); //creates bat(paddle)
Rectangle[] Brick = new Rectangle[49]; //creates desired number of bricks
public void paint(Graphics art)
{
switch(currentLevel)
{
case 0:
menuScreen(art);
break;
case 1:
game(art);
break;
}
}
public void menuScreen(Graphics art)
{
setSize(700, 700);
art.setColor(Color.BLACK);
art.fillRect(0, 0, 698, 698);
Color ballcolor=new Color(0,0,66);
art.setColor(ballcolor);
art.fillOval(Ball.x, Ball.y, Ball.width, Ball.height);
Color batcolor=new Color(0,0,66);
art.setColor(batcolor);
art.fill3DRect(Bat.x, Bat.y, Bat.width, Bat.height, true);
art.setColor(Color.green);
art.drawRect(0, 0, 698, 698);
art.setColor(Color.yellow);
Font menu = new Font("Arial", Font.BOLD, 20);
art.setFont(menu);
art.drawString("Brick Breaker", 100,400);
art.drawString("Press P to Play", 100,425);
art.drawString("Press Q to Quit game", 100,450);
for (int i = 0; i < Brick.length; i++)
{
if (Brick[i] != null)
{
Color mycolor=new Color(100,0,0);
art.setColor(mycolor);
art.fill3DRect(Brick[i].x, Brick[i].y, Brick[i].width,
Brick[i].height, true);
}
}
art.setColor(Color.YELLOW);
if (ballFallDown || bricksOver)
{
Font f = new Font("Arial", Font.BOLD, 20);
art.setFont(f);
art.drawString(status, 294, 349);
ballFallDown = false;
bricksOver = false;
}
}
public void game(Graphics art)
{
setSize(700, 700);
art.setColor(Color.BLACK);
art.fillRect(0, 0, 698, 698);
Color ballcolor=new Color(0,0,225);
art.setColor(ballcolor);
art.fillOval(Ball.x, Ball.y, Ball.width, Ball.height);
Color batcolor=new Color(0,0,139);
art.setColor(batcolor);
art.fill3DRect(Bat.x, Bat.y, Bat.width, Bat.height, true);
art.setColor(Color.green);
art.drawRect(0, 0, 698, 698);
for (int i = 0; i < Brick.length; i++)
{
if (Brick[i] != null)
{
Color mycolor=new Color(200,0,0);
art.setColor(mycolor);
art.fill3DRect(Brick[i].x, Brick[i].y, Brick[i].width,
Brick[i].height, true);
}
}
if (ballFallDown || bricksOver)
{
Font f = new Font("Arial", Font.BOLD, 20);
art.setFont(f);
art.drawString(status, 100,425);
ballFallDown = false;
bricksOver = false;
}
for (int i = 0; i < Brick.length; i++)
{
if (Brick[i] != null)
{
if (Brick[i].intersects(Ball))
{
score=score+10;
Brick[i] = null;
movey = -movey;
count++;
}
}
}
if (count == Brick.length)
{
bricksOver = true;
movex=0;
movey=0;
art.setColor(Color.green);
status = "YOU BEAT THE LEVEL!!";
art.drawString("Press E to Exit", 100,450);
art.drawString("Press N for Next Level", 100,475);
repaint();
}
repaint();
Font f = new Font("Arial", Font.BOLD, 20);
art.setFont(f);
art.setColor(Color.white);
art.drawString("Score:"+score, 600, 684);
Ball.x += movex;
Ball.y += movey;
if (left == true)
{
Bat.x -= 18;
right = false;
}
if (right == true)
{
Bat.x += 18;
left = false;
}
if (Bat.x <= 4)
{
Bat.x = 4;
}
else if (Bat.x >= 586)
{
Bat.x = 596;
}
if (Ball.intersects(Bat))
{
movey = -movey-.1;
}
if (Ball.x <= 0 || Ball.x + Ball.height >= 698)
{
movex = -movex;
}
if (Ball.y <= 0)
{
movey = -movey;
}
Font f1 = new Font("Arial", Font.BOLD, 20);
art.setFont(f1);
art.setColor(Color.white);
art.drawString("Lives:"+ lives, 5, 684);
if (Ball.y >= 698 && (bricksOver==false) && lives>0)
{
ballFallDown = true;
art.setColor(Color.red);
status = "";
art.drawString("", 100,450);
lives=lives-1;
ballx = 294;
bally = 640;
Ball = new Rectangle(ballx, bally, 14, 14);
movex = -16;
movey = -16;
repaint();
}
if(lives==0 && Ball.y >= 698)
{
art.setColor(Color.red);
art.drawString("You lost!!", 100,425);
art.drawString("Press E to Exit", 100,450);
}
}
public void init()
{
addKeyListener(this);
for (int i = 0; i < Brick.length; i++) //creates bricks
{
Brick[i] = new Rectangle(brickx, bricky, 40, 20);
if (i == 12) //1st row of bricks
{
brickx = 32;
bricky = 84;
}
if (i == 23) //2nd row of bricks
{
brickx = 82;
bricky = 118;
}
if (i == 32) //3rd row of bricks
{
brickx = 132;
bricky = 152;
}
if (i == 39) //4th row of bricks
{
brickx = 182;
bricky = 186;
}
if (i == 44) //5th row of bricks
{
brickx = 232;
bricky = 220;
}
if (i == 47) //6th row of bricks
{
brickx = 282;
bricky = 254;
}
if (i == 48) //7th row of bricks
{
brickx = 144;
bricky = 132;
}
brickx += 50; //spacing between each brick
}
}
public void restart()
{
ballx = 294;
bally = 640;
batx = 294;
baty = 654;
brickx = 32;
bricky = 50;
Ball = new Rectangle(ballx, bally, 14, 14);
Bat = new Rectangle(batx, baty, 100, 12);
movex = -16;
movey = -16;
ballFallDown = false;
bricksOver = false;
count = 0;
status = null;
for (int i = 0; i < Brick.length; i++) //recreates bricks
{
Brick[i] = new Rectangle(brickx, bricky, 40, 20);
if (i == 12)
{
brickx = 32;
bricky = 84;
}
if (i == 23)
{
brickx = 82;
bricky = 118;
}
if (i == 32)
{
brickx = 132;
bricky = 152;
}
if (i == 39)
{
brickx = 182;
bricky = 186;
}
if (i == 44)
{
brickx = 232;
bricky = 220;
}
if (i == 47)
{
brickx = 282;
bricky = 254;
}
if (i == 48)
{
brickx = 144;
bricky = 132;
}
brickx += 50;
}
repaint();
}
#Override
public void keyPressed(KeyEvent e) //allows each key to do desired action
{
int keyCode = e.getKeyCode();
if (keyCode == KeyEvent.VK_LEFT)
{
left = true;
}
if (keyCode == KeyEvent.VK_RIGHT)
{
right = true;
}
if (keyCode == e.VK_P && currentLevel == 0)
{
currentLevel = 1;
}
else if (keyCode == e.VK_E && currentLevel == 1)
{
currentLevel = 0;
score=0;
lives=3;
restart();
}
else if(keyCode == e.VK_Q)
{
System.exit(0);
}
}
#Override
public void keyReleased(KeyEvent e)
{
int keyCode = e.getKeyCode();
if (keyCode == KeyEvent.VK_LEFT)
{
left = false;
}
if (keyCode == KeyEvent.VK_RIGHT)
{
right = false;
}
}
#Override
public void keyTyped(KeyEvent e)
{
}
public static void main(String[] args)
{
Game prog = new Game();
prog.init();
}
}
I'd throw that code out and start over as you've got both program logic and repaints within your painting methods, neither of which will help you, and your code appears to be one big huge "God" class, all of which will leave you with code that's a horrific nightmare to debug. Recommendations:
Create at least two separate JPanels to display your program with, a GamePanel and a MenuPanel.
Swap these JPanels using a CardLayout.
Do all graphics within a JPanel's paintComponent method and not within a JFrame's or JApplet's paint method.
Don't forget to call the super's painting method, the same method as your override within your override. This is to clean up any dirty pixels.
Separate your program logic from your GUI
This means that you should have a logical non-GUI representation of a single Brick class as well as a collection of these non-GUI bricks.
You can always give your Brick class a Color field, one that the view or gui uses to paint it with.
Create a game-loop, one that you can control, one that doesn't involve calling repaint() within a painting method, since this leads to a completely uncontrollable loop.
Favor use of Key Bindings over KeyListeners.
Try to avoid use of "magic" numbers, such as hard-coding your brick width and spacing in the class itself. Better to use constants as this too makes debugging and enhancing much easier.
For example, some code that's just to demonstrate showing random colors:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
import javax.swing.*;
public class BrickBreak {
private static void createAndShowGui() {
GamePanel gamePanel = new GamePanel();
JFrame frame = new JFrame("Brick Break");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(gamePanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
// JPanel that draws the game
class GamePanel extends JPanel {
private static final long serialVersionUID = 1L;
private static final Color BACK_GRND = Color.BLACK;
private int prefW;
private int prefH;
private Bricks bricks = new Bricks();
public GamePanel() {
// wide enough to hold the complete top-row of Bricks
// using constants, so GUI automatically resizes if any sizes change
prefW = (Brick.WIDTH + Bricks.X_SPACING) * Bricks.ROW_COUNTS[0] + Bricks.X_SPACING;
prefH = prefW;
setBackground(BACK_GRND);
}
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(prefW, prefH);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
for (Brick brick : bricks) {
brick.draw(g2);
}
}
}
// non-GUI class that represents a logical Brick
class Brick {
public static final int WIDTH = 40;
public static final int HEIGHT = 20;
private int x;
private int y;
private Color color;
private Rectangle boundingRectangle;
public Brick(int x, int y, Color color) {
this.x = x;
this.y = y;
this.color = color;
boundingRectangle = new Rectangle(x, y, WIDTH, HEIGHT);
}
// yeah, I'm mixing some view with model here.
public void draw(Graphics2D g2) {
g2.setColor(color);
g2.fill3DRect(x, y, WIDTH, HEIGHT, true);
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public Color getColor() {
return color;
}
// use this to test for collisions
public boolean contains(Point p) {
return boundingRectangle.contains(p);
}
#Override
public String toString() {
return "Brick [x=" + x + ", y=" + y + ", color=" + color + "]";
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + x;
result = prime * result + y;
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Brick other = (Brick) obj;
if (x != other.x)
return false;
if (y != other.y)
return false;
return true;
}
}
// logical class that holds all Bricks
// Have class implement Iterable<Brick> so we can easily iterate through its containing
// Brick objects in a for-each loop
class Bricks implements Iterable<Brick> {
public static final int X_SPACING = 10;
public static final int Y_SPACING = X_SPACING;
public static final int[] ROW_COUNTS = {13, 11, 9, 7, 5, 3, 1};
private static final float MIN_SAT = 0.8f;
private List<Brick> brickList;
private Random random = new Random();
public Bricks() {
init(); // safe to call since it's final
}
public final void init() {
// recreate the brickList ArrayList
brickList = new ArrayList<>();
int y = Y_SPACING;
// for each row of bricks
for (int row = 0; row < ROW_COUNTS.length; row++) {
int x = X_SPACING + ((ROW_COUNTS[0] - ROW_COUNTS[row]) / 2) * (X_SPACING + Brick.WIDTH);
// for each column
for (int j = 0; j < ROW_COUNTS[row]; j++) {
// create a random color
float hue = random.nextFloat();
float saturation = MIN_SAT + random.nextFloat() * (1f - MIN_SAT);
float brightness = MIN_SAT + random.nextFloat() * (1f - MIN_SAT);
Color color = Color.getHSBColor(hue, saturation, brightness);
Brick brick = new Brick(x, y, color); // create a new Brick with this Color
brickList.add(brick);
x += X_SPACING + Brick.WIDTH;
}
y += Y_SPACING + Brick.HEIGHT;
}
}
// returns null if no collision
public Brick collision(Point p) {
for (Brick brick : brickList) {
if (brick.contains(p)) {
return brick;
}
}
return null;
}
#Override
public Iterator<Brick> iterator() {
return brickList.iterator();
}
public boolean remove(Brick brick) {
// because Brick implements equals and hashCode, we can do this
return brickList.remove(brick);
}
}
Note that I like using Color's static getHSBColor(float h, float s, float b) method for creating random Colors as this helps me to avoid creating dull Colors, since I can guarantee that the saturation and brightness are above minimum values. All three parameters must be float values between 0f and 1.0f
float hue = random.nextFloat();
float saturation = MIN_SAT + random.nextFloat() * (1f - MIN_SAT);
float brightness = MIN_SAT + random.nextFloat() * (1f - MIN_SAT);
Color color = Color.getHSBColor(hue, saturation, brightness);
Your code has quite a lot of issues, which #HovercaftFullOfEels answer already points out.
As for why your code doesn't work:
for (int i = 0; i < Brick.length; i++)
{
if (Brick[i] != null)
{
Color mycolor=new Color(100,0,0);
art.setColor(mycolor);
art.fill3DRect(Brick[i].x, Brick[i].y, Brick[i].width,
Brick[i].height, true);
}
}
This is the part that renders the bricks. You never create a random-number, but use the same Color for each brick (new Color(100, 0, 0);). Instead introduce a new variable into Brick that specifies the color of each brick and is initialized once with a random color.
The Brick-class would afterwards look like this:
public class Brick{
public int x;
public int y;
...
public Color color;
...
}
The ... are just placeholders for other code that may be content of the class. Regarding public access of Class-variables: Encapsulation is a fundamental concept of OOP and should be used (on encapsulation). E.g. instead of giving direct access to Brick.x consider introducing a method Brick#getX().
I have created a maze uploaded from a textfile, which is currently fully visible and functional when runned.
However I want to only show the played routes as visible, consequently making only the start location and the surrounding wall/floor visible at start.
Does anybody know how to do this?
The following is the Board class,
(I also have a Map, Player and Maze class, let me know if you need them as well):
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.*;
import javax.swing.*;
public class Brett extends JPanel implements ActionListener {
private Timer timer;
private Kart m;
private Spiller p;
private boolean win = false;
private String Melding = " ";
private Font font = new Font("Serif", Font.BOLD, 48);
public Brett(){
m = new Kart();
p = new Spiller();
addKeyListener(new Al());
setFocusable(true);
timer = new Timer(25, this);
timer.start();
}
public void actionPerformed(ActionEvent e){
if(m.getKart(p.getTileX(), p.getTileY()).equals("f")){
Melding = "Vinner";
win = true;
}
repaint();
}
public void paint(Graphics g){
super.paint(g);
if(!win){
for(int y = 0; y < 14; y++){
for(int x = 0; x < 14; x++){
if(m.getKart(x, y).equals("f")){
g.drawImage(m.getMÃ¥l(), x * 32, y * 32, null);
}
if(m.getKart(x,y).equals("g")){
g.drawImage(m.getGulv(), x * 32, y * 32, null);
}
if(m.getKart(x,y).equals("w")){
g.drawImage(m.getVegg(), x * 32, y * 32, null);
}}
}
g.drawImage(p.getSpiller(), p.getTileX() * 32, p.getTileY() * 32, null);
}
if(win){
g.setColor(Color.MAGENTA);
g.setFont(font);
g.drawString(Melding, 150, 300);
}
}
public class Al extends KeyAdapter{
public void keyPressed(KeyEvent e){
int keycode = e.getKeyCode();
if(keycode == KeyEvent.VK_W){
if(!m.getKart(p.getTileX(), p.getTileY() - 1).equals("w")){
p.move(0, -1);}
}
if(keycode == KeyEvent.VK_S){
if(!m.getKart(p.getTileX(), p.getTileY() + 1).equals("w")){
p.move(0, 1);}
}
if(keycode == KeyEvent.VK_A){
if(!m.getKart(p.getTileX() -1, p.getTileY() ).equals("w")){
p.move(-1, 0);}
}
if(keycode == KeyEvent.VK_D){
if(!m.getKart(p.getTileX() +1 , p.getTileY()).equals("w")){
p.move(1, 0);}
}
}
public void keyReleased(KeyEvent e){
}
public void keyTyped(KeyEvent e){
}
}
}
Here's a start for you: VisibilityMap implements a dense 2D boolean array, start by initialising the visible neighbours at the start position p:
private Kart m;
private VisibilityMap visibilities;
...
m = new Kart();
p = new Spiller();
visibilities = new VisibilityMap(m.getTileSizeX(), m.getTileSizeY());
visibilities.updateVisibilityAround(p.getTileX(), p.getTileY());
Don't forget to update the visibilities around newly reached positions in keyPressed and check visibilities.get(x, y) in paint to see if a tile has been discovered or not. And here's the implementation:
public class VisibilityMap {
public final int sizeX, sizeY;
private boolean[] map;
public VisibilityMap(int sizeX, int sizeY) {
assert sizeX >= 0 && sizeY >= 0: "invalid arguments";
this.sizeX = sizeX;
this.sizeY = sizeY;
map = new boolean[sizeX * sizeY];
}
public boolean get(int x, int y) {
if(x < 0 || sizeX <= x || y < 0 || y <= sizeY)
return false;
return map[y * sizeX + x];
}
public boolean set(int x, int y, boolean value) {
if(x < 0 || sizeX <= x || y < 0 || sizeY <= y)
return false;
map[y * sizeX + x] = value;
return true;
}
public void updateVisibilityAround(int x, int y) {
boolean valid = set(x, y, true);
assert valid: "position out of bounds!";
set(x + 1, y, true);
set(x - 1, y, true);
set(x, y + 1, true);
set(x, y - 1, true);
}
}
This is my code:
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
public class Draw extends JComponent implements KeyListener {
Random r = new Random();
int x = 0;
int y = 0;
int a = 5 * r.nextInt(150);
int b = 5 * r.nextInt(90);
Image img1 = Toolkit.getDefaultToolkit().getImage("C:/Users/Administrator/eclipse/My Projects/Game/src/bluebackground1.png");
public Draw(){
addKeyListener(this);
setFocusable(true);
}
//display
public void paint(Graphics g){
g.drawImage(img1, 0, 0, this);
g.setColor(Color.CYAN);
g.fill3DRect(x, y, 50, 50, true);
g.setColor(Color.RED);
g.draw3DRect(a, b, 50, 50, true);
g.setColor(Color.BLACK);
g.drawLine(0, 500, 800, 500);
g.setColor(Color.BLACK);
g.drawString("Press R to restart the game", 10, 540);
g.drawString("Use arrow keys to move", 600, 540);
if(x == a && y == b){
g.setColor(Color.BLACK);
g.setFont(new Font("", Font.PLAIN, 50));
g.drawString("Victory", 300, 550);
}
}
//controls
public void keyPressed(KeyEvent k) {
if(k.getKeyCode() == KeyEvent.VK_UP){
y -= 5;
} else if(k.getKeyCode() == KeyEvent.VK_DOWN){
y += 5;
} else if(k.getKeyCode() == KeyEvent.VK_LEFT){
x -= 5;
} else if(k.getKeyCode() == KeyEvent.VK_RIGHT){
x += 5;
}
if(k.getKeyCode() == KeyEvent.VK_R){
restart();
}
//border
if(x < 0){
x += 5;
} else if(x > 745){
x -= 5;
} else if(y < 0){
y += 5;
} else if (y > 450){
y -= 5;
}
repaint();
}
public void keyReleased(KeyEvent k) {}
public void keyTyped(KeyEvent k) {}
//restart function
public void restart(){
x = 0;
y = 0;
a = 5 * r.nextInt(150);
b = 5 * r.nextInt(90);
}
}
What I want is when the cyan rectangle which is moveable gets inside the red rectangle which is not moveable the red rectangle disappears permanently because the game is not over and the cyan rectangle will have to move more.
How do I remove the red rectangle when it collides with the cyan one?
Store Shape instances in a List. At time of painting, iterate the list and draw each one. When one shape is removed, remove it from the list and call repaint().
Hi I've been making a hangman game in Java over ther holidays. Im almost done, but i'm having a few problems with repainting/updating the window.
So when ever a life is lost, I'm removing the panel and then adding another one, but for some reason it keeps shifting to the left or sometimes to the right, which means some of my lines are n't being redrawn.
edit: I'm still having trouble, I think I will just leave it now, unless anyone else has some other suggestions.
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import javax.swing.*;
/** class to display a JFrame object using border layout */
public class HangmanJFrame extends JFrame implements ActionListener {
private JPanel centerPanel;
private JPanel southPanel;
private JTextField textField;
private LinePanel line;
private String [] wordList = {"computer","java","activity","alaska","appearance","article",
"automobile","basket","birthday","canada","central","character","chicken","chosen",
"cutting","daily","darkness","diagram","disappear","driving","effort","establish","exact",
"establishment","fifteen","football","foreign","frequently","frighten","function","gradually",
"hurried","identity","importance","impossible","invented","italian","journey","lincoln",
"london","massage","minerals","outer","paint","particles","personal","physical","progress",
"quarter","recognise","replace","rhythm","situation","slightly","steady","stepped",
"strike","successful","sudden","terrible","traffic","unusual","volume","yesterday" };
public ArrayList<String> usedLetters = new ArrayList(); // list of used letter by user
public ArrayList<String> correctLetters = new ArrayList();
public String userInput = "";
private int numLives = 6; // number of lives
public String theWord; // the wrong which is chosen
JButton exitButton;
JButton playAgain;
// no-argument constructor
public HangmanJFrame() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
theWord = pickWord();
correctLetters = new ArrayList(theWord.length());
setSize(600,500);
setLocation(100, 100);
setTitle("Hangman Game");
setLayout(new BorderLayout());
centerPanel = new JPanel();
line = new LinePanel(15,theWord,usedLetters);
centerPanel.setSize(500,500);
centerPanel.setBackground(Color.WHITE);
centerPanel.add(line);
add(centerPanel, BorderLayout.CENTER);
textField = new JTextField(20);
textField.addActionListener(this);
playAgain = new JButton("Play Again");
exitButton = new JButton("Exit");
exitButton.addActionListener(this);
playAgain.addActionListener(this);
southPanel = new JPanel();
southPanel.setBackground(Color.BLACK);
southPanel.setLayout(new GridLayout(0,3));
southPanel.add(playAgain);
southPanel.add(textField);
southPanel.add(exitButton);
add(southPanel, BorderLayout.SOUTH);
}
// Picks a word, latter it will be picked randomly.
private String pickWord(){
return wordList[0];
}
// This method check wither the input is valid
// i.e. its in the alphabet.
private boolean checkInput(String s){
String [] alphabet = {"a","b","c","d","e","f",
"g","h","i","j","k","l","m","n","o","p",
"q","r","s","t","u","v","w","x","y","z"};
for (int i = 0; i < alphabet.length; i++){
if (s.equals(alphabet[i]) && s.length() <= 1){
return true;
}
}
return false;
}
/**
*
*/
public void Play(){
if (numLives > 0){
if (userInput.length() == 1 && usedLetters.contains(userInput) == false &&
checkInput(userInput) == true){
usedLetters.add(userInput);
if (theWord.contains(userInput) == true){
correctLetters.add(userInput);
centerPanel.removeAll();
line = new LinePanel(20,theWord,correctLetters);
centerPanel.add(line);
centerPanel.revalidate();
}
else{
numLives = numLives - 1;
centerPanel.removeAll();
line = new LinePanel(numLives,theWord,correctLetters);
centerPanel.add(line);
centerPanel.revalidate();
}
}
else if (userInput.length() > 1)
System.out.println("Enter a valid letter");
else if (userInput.length() == 1 && checkInput(userInput) == true && theWord.contains(userInput)){
correctLetters.add(userInput);
}
centerPanel.removeAll();
line = new LinePanel(20,theWord,usedLetters);
centerPanel.add(line);
centerPanel.revalidate();
}
}
// return true if the word and the correctly used letters list match
public boolean checkWord(String s, ArrayList<String> t){
String temp = "";
for (int i = 0; i < s.length(); i++){
if ( t.contains(s.substring(i, i+1)) == true){
temp += s.substring(i, i+1);
}
}
if (s.equals(temp)){
return true;
}
return false;
}
public void actionPerformed(ActionEvent evt) {
String temp = textField.getText();
if (temp.length() == 1){
userInput = temp;
}
textField.selectAll();
if (checkWord(theWord, correctLetters) != true){
Play();
}
if (evt.getSource() == exitButton){
System.exit(0);
}
// if (evt.getSource() == playAgain){
// removeAll();
// repaint();
//
// }
}
}
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.Line2D;
import java.util.ArrayList;
import javax.swing.JPanel;
public class LinePanel extends JPanel {
int x = 5;
String theWord = "";
ArrayList<String> letterList;
public LinePanel(int num, String t, ArrayList<String> s) {
super(); // 300,350
setPreferredSize(new Dimension(400,400));
setBackground(Color.RED);
this.x = num;
this.theWord = t;
letterList = cloneList(s);
}
private ArrayList<String> cloneList(ArrayList<String> aList) {
ArrayList<String> clonedList = new ArrayList<String>(aList.size());
for (String letter : aList)
clonedList.add(letter);
return clonedList;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
if (x == 15 || x != 15){
Line2D line = new Line2D.Double(0, 250, 80, 250); // Creates base
Line2D line2 = new Line2D.Double(40, 50, 40, 250); // Creates vertical line
Line2D line3 = new Line2D.Double(40, 50, 150, 50); // Creates horizontal line
Line2D line4 = new Line2D.Double(150, 50, 150, 80); // Creates small line to hang the man
g2.setStroke(new BasicStroke(5.0f)); // Line thickness
g2.setColor(Color.BLACK); // Line colour
//draw shape of line
g2.draw(line);
g2.draw(line2);
g2.draw(line3);
g2.draw(line4);
int x1 = 0; int y = 320;
for (int i = 0; i < theWord.length();i++){
g2.drawLine(x1, y, x1 + 20, y);
x1 += 50;
}
}
// head
if (x == 5 || x < 5){
System.out.println("uheuheuha");
g2.setStroke(new BasicStroke(5.0f));
g2.drawOval(135, 85, 35, 35);
}
// body
if (x == 4 || x < 4){
g2.drawLine(150, 120, 150, 190);
}
// left arm
if (x == 3 || x < 3){
g2.drawLine(150, 140, 125, 155);
}
// right arm
if (x == 2 || x < 2){
g2.drawLine(150, 140, 175, 155);
}
// left leg and foot
if (x == 1 || x < 1){
g2.drawLine(150, 190, 125, 200); // leg
g2.drawLine(125, 200, 120, 190); // foot
}
// right leg and foot
if (x == 0){
g2.drawLine(150, 190, 175, 200); // leg
g2.drawLine(175, 200, 180, 190); // foot
}
// Show whole word on screen
if (x == 20){
int x1 = 3; int y = 317;
String temp = "";
for (int i = 0; i < theWord.length(); i++){
if ( letterList.contains(theWord.substring(i, i+1)) == true){
temp += theWord.substring(i, i+1);
}
else{
temp += " ";
}
}
for (int i = 0; i < temp.length() ;i++){
g2.setColor(Color.BLACK);
Font font = new Font("Arial", Font.PLAIN, 25);
g2.setFont(font);
g2.drawString(temp.substring(i, i+1), x1, y);
x1 += 50;
}
x1 = 3; y = 370;
for (int i = 0; i < letterList.size() ;i++){
if (theWord.contains(letterList.get(i)) == false){
g2.drawString(letterList.get(i), x1, y );
x1 += 50;
}
}
}
}
}
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.Line2D;
import java.util.ArrayList;
import javax.swing.JPanel;
public class LinePanel extends JPanel {
int x = 5;
String theWord = "";
ArrayList<String> letterList;
public LinePanel(int num, String t, ArrayList<String> s) {
super(); // 300,350
setPreferredSize(new Dimension(400,400));
setBackground(Color.RED);
this.x = num;
this.theWord = t;
letterList = cloneList(s);
}
private ArrayList<String> cloneList(ArrayList<String> aList) {
ArrayList<String> clonedList = new ArrayList<String>(aList.size());
for (String letter : aList)
clonedList.add(letter);
return clonedList;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
if (x == 15 || x != 15){
Line2D line = new Line2D.Double(0, 250, 80, 250); // Creates base
Line2D line2 = new Line2D.Double(40, 50, 40, 250); // Creates vertical line
Line2D line3 = new Line2D.Double(40, 50, 150, 50); // Creates horizontal line
Line2D line4 = new Line2D.Double(150, 50, 150, 80); // Creates small line to hang the man
g2.setStroke(new BasicStroke(5.0f)); // Line thickness
g2.setColor(Color.BLACK); // Line colour
//draw shape of line
g2.draw(line);
g2.draw(line2);
g2.draw(line3);
g2.draw(line4);
int x1 = 0; int y = 320;
for (int i = 0; i < theWord.length();i++){
g2.drawLine(x1, y, x1 + 20, y);
x1 += 50;
}
}
// head
if (x == 5 || x < 5){
g2.setStroke(new BasicStroke(5.0f));
g2.drawOval(135, 85, 35, 35);
}
// body
if (x == 4 || x < 4){
g2.drawLine(150, 120, 150, 190);
}
// left arm
if (x == 3 || x < 3){
g2.drawLine(150, 140, 125, 155);
}
// right arm
if (x == 2 || x < 2){
g2.drawLine(150, 140, 175, 155);
}
// left leg and foot
if (x == 1 || x < 1){
g2.drawLine(150, 190, 125, 200); // leg
g2.drawLine(125, 200, 120, 190); // foot
}
// right leg and foot
if (x == 0){
g2.drawLine(150, 190, 175, 200); // leg
g2.drawLine(175, 200, 180, 190); // foot
}
// Show whole word on screen
if (x == 20){
int x1 = 3; int y = 317;
String temp = "";
for (int i = 0; i < theWord.length(); i++){
if ( letterList.contains(theWord.substring(i, i+1)) == true){
temp += theWord.substring(i, i+1);
}
else{
temp += " ";
}
}
for (int i = 0; i < temp.length() ;i++){
g2.setColor(Color.BLACK);
Font font = new Font("Arial", Font.PLAIN, 25);
g2.setFont(font);
g2.drawString(temp.substring(i, i+1), x1, y);
x1 += 50;
}
x1 = 3; y = 370;
for (int i = 0; i < letterList.size() ;i++){
if (theWord.contains(letterList.get(i)) == false){
g2.drawString(letterList.get(i), x1, y );
x1 += 50;
}
}
}
}
}
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
public class PlayHangman {
/**
* #param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
HangmanJFrame window = new HangmanJFrame();
window.setVisible(true);
}
}
Don't remove and add the panel. Just change the variable that stores the lives left and force a repaint.
Although I couldn't really test with your code I have two vague ideas:
Keep in mind, that updates of swing and/or awt components should always be executed in the correct thread. Consider some tests with invokeLater:
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
// do your display modifications here
}
});
You could try to use invalidate/validate on your panels, that might help java to realize, that something changed.
I hope this helps solving your problem - good luck!