How to create multiple objects from the same place in java - java

I'm trying to make a tower defense game and I'm having trouble making it so that when I click on one of the tower buttons at the bottom and drag to the playing area it creates a new object Tower. I have tried using an arraylist, but everytime I drag to make a new tower the previous tower erases and the new tower stays drawn on the screen.
There are a couple of classes so I will only post the ones I think are relevant. If you need the others I can put them. Sorry in advance for the length of my post.
This is the class where the events are handled
package addison;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.util.ArrayList;
import javax.swing.JPanel;
import javax.swing.Timer;
#SuppressWarnings("serial")
public class Controls extends JPanel implements MouseListener, MouseMotionListener, ActionListener {
Timer timer;
public static int x; //mouse's x pos
public static int y; //mouse's y pos
public static int iteration = 0;
public static String button = ""; //identifies pressed button
public static boolean pressed = false; //true if a button was pressed and not a random space
public static boolean created = false;
public static ArrayList<Tower> tower = new ArrayList<Tower>(); //arraylist of tower objects
public Controls() {
timer = new Timer(5, this); //creates a 5ms timer
timer.start(); //starts timer
addMouseListener(this);
addMouseMotionListener(this);
setFocusable(true);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Map.paint(g); //draws map
Hud.paint(g); //draws HUD
TextDisplay.paint(g); //displays text
}
public void actionPerformed(ActionEvent e) {
repaint(); //redraws graphics every 5ms
}
#Override
public void mouseClicked(MouseEvent e) {
}
#Override
public void mouseEntered(MouseEvent e) {
}
#Override
public void mouseExited(MouseEvent e) {
}
#Override
public void mousePressed(MouseEvent e) {
if (Hud.getButton()) {
pressed = true;
} else {
pressed = false;
}
System.out.println(pressed);
}
#Override
public void mouseReleased(MouseEvent e) {
x = e.getX(); //gets mouse's x pos
y = e.getY(); //gets mouse's y pos
if (pressed) { // if the button pressed was gun man
tower.add(iteration, new Tower(TextDisplay.description, x, y, 100, 100, 25)); //add a new tower object to the end of the arraylist
System.out.println(tower.get(0).x);
created = true;
pressed = false;
}
iteration++;
}
#Override
public void mouseDragged(MouseEvent e) {
}
#Override
public void mouseMoved(MouseEvent e) {
x = e.getX(); //get mouse's x pos
y = e.getY(); //get mouse;s y pos
if (Hud.getButton()) {
TextDisplay.hovering = true;
} else {
TextDisplay.hovering = false;
}
}
}
package addison;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Rectangle;
this is the class where everything is drawn
public class Map {
public static Rectangle mouse; //location of cursor
public Map() {
}
public static void paint(Graphics g) {
g.setColor(new Color(255, 0, 0)); //makes mouse hit box transparent
mouse = new Rectangle(Controls.x, Controls.y, 5, 5); //create mouse hit box
g.fillRect(mouse.x, mouse.y, mouse.width, mouse.height); //draw mouse hit box
g.drawRect(0, 0, 800, 450); //play area
g.drawRect(0, 0, 800, 500); //options area
if (Controls.created) {
g.fillRect(Controls.tower.get(Controls.iteration).x, Controls.tower.get(0).y, 50, 50);
}
}
}
This is the class where the buttons are:
package addison;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Rectangle;
public class Hud {
public static Rectangle gunman;
public static Rectangle laserTower;
public static Rectangle rocketLauncher;
public static Rectangle emBomb;
public static Rectangle soundGun;
public Hud() {
}
public static void paint(Graphics g) {
gunman = new Rectangle(0, 450, 50, 50); //create gun man button
g.fillRect(gunman.x, gunman.y, gunman.width, gunman.height); //draw gun man button
g.setColor(Color.BLUE);
laserTower = new Rectangle(50, 450, 50, 50); //create laser tower button
g.fillRect(laserTower.x, laserTower.y, laserTower.width, laserTower.height); //draw laser tower button
g.setColor(Color.CYAN);
rocketLauncher = new Rectangle(100, 450, 50, 50); //create rocket launcher tower
g.fillRect(rocketLauncher.x, rocketLauncher.y, rocketLauncher.width, rocketLauncher.height); //draw rocket launcher button
g.setColor(Color.DARK_GRAY);
emBomb = new Rectangle(150, 450, 50, 50); //creates em bomb button
g.fillRect(emBomb.x, emBomb.y, emBomb.width, emBomb.height); //draw em bomb button
g.setColor(Color.GREEN);
soundGun = new Rectangle(200, 450, 50, 50); //create sound gun button
g.fillRect(soundGun.x, soundGun.y, soundGun.width, soundGun.height); //draw sound gun button
}
public static boolean getButton() {
if(Map.mouse.intersects(Hud.gunman)) {
TextDisplay.description = "Gunman";
return true;
} else if (Map.mouse.intersects(Hud.laserTower)) {
TextDisplay.description = "Laser Tower";
return true;
} else if (Map.mouse.intersects(Hud.rocketLauncher)) {
TextDisplay.description = "Rocket Launcher";
return true;
} else if (Map.mouse.intersects(Hud.emBomb)) {
TextDisplay.description = "E.M. Bomb";
return true;
} else if (Map.mouse.intersects(Hud.soundGun)) {
TextDisplay.description = "Sound Gun";
return true;
} else {
TextDisplay.description = "";
return false;
}
}
}
This is the class that makes the Tower objects:
package addison;
public class Tower {
public static String type = ""; //type of tower e.g. gunman or laser tower
public static int x = 0;
public static int y = 0;
public static int range = 0; //tower range
public static int speed = 0; //tower speed
public static int sRange = 0; //tower's shrapnel range
public Tower(String a, int b, int c, int d, int e, int f) {
type = a;
x = b;
y = c;
range = d;
speed = e;
sRange = f;
}
}
Thank you.

because you only paint the tower in the last iteration in the following line:
g.fillRect(Controls.tower.get(Controls.iteration).x, Controls.tower.get(0).y, 50, 50);
You need to paint all towers in the paint function

It seems like you're using Control.iteration as a key into your tower list. However, every time mouseReleased is called (whether a tower is created or not), you're incrementing iteration. This means that the Controls.iteration key in your paint handler will never refer to the newly-created tower. You're also using Controls.tower.get(0).y - why does this differ from the x coord?
I hope I've understood this correctly. If you're just painting the newly-created tower, why not keep a reference to that in Controls? If you're painting them all, you should loop through from 0 to iteration - 1 and move iteration++ inside the if (pressed) block.

Related

How to use Key Bindings instead of Key Listener?

So I am creating a brick breaker game. I got the paddle moving using key listeners, however I got some advice to use key bindings instead. I've been reading and looking everywhere on this and I think I've kinda got the idea but the implementation is confusing me a bit.
For my paddle, I created it with the paint component. Hence this is what I want to be able to move left and right with the arrow keys. However, all the key bindings explanations I find seem to use JComponent which the paddle is not. Is there a way around it or will I have to make my paddle a JComponent image icon instead? If so would I just load the image into my Paddle class?
Also what's the best way of structuring my code to contain the key bindings? For instance am I better off creating a whole new class for it, or putting it in e.g. my GamePanel class
Any tips?
Here is some of my code so you can get an idea:
Main Class:
public class BrickBreakerGameApp {
public static void main(String[] args) {
int pw = 500;
int ph = 900;
GamePanel gPanel = new GamePanel(pw,ph);
GameFrame gFrame = new GameFrame();
gFrame.getContentPane().add(gPanel); //add game panel to frame
// gFrame.addKeyListener(gPanel); //adds the key listener for the game panel frame
gFrame.pack();
gFrame.setVisible(true); //make frame visible
}
}
GameFrame class:
import java.awt.Dimension;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
public class GameFrame extends JFrame {
//Global Variables
public int frameWidth = 500;
public int frameHeight = 800;
//create constructor
GameFrame () {
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //so app closes properly
this.setPreferredSize(new Dimension(frameWidth, frameHeight)); //set frame size
this.setTitle("Brick Breaker Game");
ImageIcon icon = new ImageIcon("res/brick-breaker-logo.jpg"); //create image icon
this.setIconImage(icon.getImage()); //update frame icon
this.pack();
}
}
GamePanel Class
import java.awt.Color;
import java.awt.event.*;
import javax.swing.InputMap;
import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import java.awt.*;
/**
* This class handles the game panel as a whole
*/
public class GamePanel extends JPanel {
// Global Variables
private Ball ball;
private Paddle paddle;
private Bricks bricks;
private GameFrame gameFrame;
private int width;
private int height;
private int[] bArray = new int[20];
// create a constructor
GamePanel (int gamePanelWidth, int gamePanelHeight) {
this.setWidth(gamePanelWidth);
this.setHeight(gamePanelHeight);
initialiseGame();
this.isVisible();
}
private void initialiseGame() {
ball = new Ball(10, 520, 30, 30); //create the ball object
paddle = new Paddle(this, 50, 700, 100, 10); //creates paddle object
bricks = new Bricks(10, 10, 60, 30, bArray); //creates the bricks object
//for key binding initialisation
MotionAction motion = new MotionAction(paddle, 24);
}
// paint all the elements in
public void paintComponent(Graphics g) {
super.paintComponent(g);
// background
g.setColor(Color.black);
g.fillRect(0, 0, getWidth(), getHeight());
// paddle
// g.setColor(Color.CYAN);
// g.fillRect(paddle.getPaddleX(), paddle.getPaddleY(), paddle.getPaddleWidth(), paddle.getPaddleHeight());
// ball
g.setColor(Color.MAGENTA);
g.fillOval(ball.getBallX(), ball.getBallY(), ball.getBallWidth(), ball.getBallHeight());
// brick
g.setColor(Color.GREEN);
g.fillRect(bricks.getBrickX(), bricks.getBrickY(), bricks.getBrickWidth(), bricks.getBrickHeight());
}
//add any unimplemented methods because we are using an interface
/* #Override
public void actionPerformed(ActionEvent e) {
}
#Override
public void keyPressed(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_LEFT) {
paddle.moveLeft();
}
if(e.getKeyCode() == KeyEvent.VK_RIGHT) {
paddle.moveRight();
}
this.repaint();
}
#Override
public void keyTyped(KeyEvent e) {
}
#Override
public void keyReleased(KeyEvent e) {
} */
//create get and set methods for all panel attributes
public int getWidth() {
return width;
}
public void setWidth(int pWidth) {
this.width = pWidth;
}
public int getHeight() {
return height;
}
public void setHeight(int pHeight) {
this.height = pHeight;
}
}
Paddle class:
import javax.swing.AbstractAction;
import java.awt.event.*;
public class Paddle extends AbstractAction implements ActionListener {
//Global Variables
private int paddleWidth;
private int paddleHeight;
private int paddleX; //paddle x position
private int paddleY;
private GamePanel gamePanel;
//create paddle constructor
Paddle() {
}
//create a paddle constructor based off parameters
Paddle(GamePanel gPanel, int pX, int pY, int pWidth, int pHeight) {
//set the values
this.setPaddleWidth(pWidth);
this.setPaddleHeight(pHeight);
this.setPaddleX(pX);
this.setPaddleY(pY);
this.setGamePanel(gPanel);
}
//create get and set methods for all paddle attributes
public int getPaddleWidth() {
return paddleWidth;
}
public void setPaddleWidth(int pWidth) {
this.paddleWidth = pWidth;
}
public int getPaddleHeight() {
return paddleHeight;
}
public void setPaddleHeight(int pHeight) {
this.paddleHeight = pHeight;
}
public int getPaddleX() {
return paddleX;
}
public void setPaddleX(int pX) {
this.paddleX = pX;
}
public int getPaddleY() {
return paddleY;
}
public void setPaddleY(int pY) {
this.paddleY = pY;
}
public GamePanel getGamePanel() {
return gamePanel;
}
public void setGamePanel(GamePanel gPanel) {
this.gamePanel = gPanel;
}
//move the paddle left if it is not already positoned at 0 (far left)
public void moveLeft() {
try {
if(getPaddleX() <= 0) {
setPaddleX(0);
System.out.println("less than 0, x: " + getPaddleX());
}
else if (getPaddleX() > 0) {
setPaddleX(getPaddleX()-10); //to move paddle left -10
// gamePanel.repaint(getPaddleX()+10, getPaddleY(), getPaddleWidth(), getPaddleHeight()); //repaint old position
// gamePanel.repaint(getPaddleX(), getPaddleY(), getPaddleWidth(), getPaddleHeight()); //repaint new position
System.out.println("left, x: " + getPaddleX());
}
}
catch (Exception e) {
}
}
//move the paddle right if it is not already positioned to the far right of the panel
public void moveRight() {
if(getPaddleX() >= gamePanel.getWidth() - getPaddleWidth()) { //dont move the paddle if it is on the right edge of the panel
setPaddleX(gamePanel.getWidth() - getPaddleWidth());
System.out.println("right1, x:" + getPaddleX());
}
else if ((getPaddleX()+getPaddleWidth()) <= gamePanel.getWidth()){ //if the paddle is within the panel bounds
setPaddleX(getPaddleX() + 10); //to move paddle right +10
System.out.println("right, x:" + getPaddleX());
}
}
}
Here are some of the main resources I've being trying:
This one I tried but got really confused on the best way to integrate it into my own code --> https://tips4java.wordpress.com/2013/06/09/motion-using-the-keyboard/
This one I tried until I realised I don't have jcomponent --> https://coderanch.com/t/606742/java/key-bindings
You could register the key bindings with the GamePanel, or the frame content pane (both extend from JComponent). E.g.:
public class DemoFrame extends JFrame {
public static void main(String[] args) throws Exception {
new DemoFrame().setVisible(true);
}
public DemoFrame() {
setSize(800, 600);
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
{
String actionId = "left";
KeyStroke keyStroke = KeyStroke.getKeyStroke("LEFT");
getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(keyStroke, actionId);
getRootPane().getActionMap().put(actionId, new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
actionLeft();
}
});
}
}
private void actionLeft() {
System.out.println("left");
}
}

Why my projectile(Image object) is not moving? Java Swing

I'm trying to make a demo spaceship shooter. Every time i press the space bar I draw a new projectile(Image) in the paintComponent(Graphics g) method and call a moveProjectile() method. The problem is the moveProjectile() method seems to be off.
MyJPanel.java
import java.awt.Cursor;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
public class MyJPanel extends JPanel implements ActionListener
{
private static final long serialVersionUID = 1L;
private Timer timer;
private Image backgroundImage;
private Image player;
private int playerX, playerY;
private int projectileX,projectileY;
private Image projectileImage;
private ArrayList<Image> projectiles = new ArrayList<Image>();
boolean flag = false;
public MyJPanel(Image backgroundImage, Image player,Image projectileImage)
{
this.backgroundImage = backgroundImage;
this.player = player;
this.projectileImage = projectileImage;
this.setLayout(null);
timer = new Timer(50, this);
timer.start();
this.addKeyListener(new KeyAdapter() // Listens for a keyboard event
{
public void keyPressed(KeyEvent e)
{
if (e.getKeyCode() == KeyEvent.VK_SPACE) // If pressing space - shoot
{
flag = true;
moveProjectile();
}
repaint();
}
});
// Mouse listener
this.addMouseMotionListener(new MouseMotionListener()
{
#Override
public void mouseMoved(MouseEvent e)
{
playerX = e.getX();
playerY = e.getY();
}
#Override
public void mouseDragged(MouseEvent e)
{
}
});
hideMouseCursor();
this.setFocusable(true);
this.setVisible(true);
} // End of JPanle constructor
public void paintComponent(Graphics graphics)
{
super.paintComponent(graphics);
graphics.drawImage(backgroundImage,0,0,this.getWidth(),this.getHeight(),null); // Draw the background
graphics.drawImage(player,playerX,playerY,null); // Draw the player
if (flag)
{
projectileX = playerX + player.getWidth(null);
projectileY = playerY + player.getHeight(null) / 2 - 27;
graphics.drawImage(projectileImage,projectileX,projectileY,null);
}
}
public void moveProjectile()
{
while (projectileX < this.getWidth())
{
this.projectileX += 2;
repaint();
}
}
public void hideMouseCursor() // Hides the mouse cursor
{
//Transparent 16 x 16 pixel cursor image.
BufferedImage cursorbackgroundImgage = new BufferedImage(16, 16, BufferedImage.TYPE_INT_ARGB);
// Create a new blank cursor.
Cursor blankCursor = Toolkit.getDefaultToolkit().createCustomCursor(
cursorbackgroundImgage, new Point(0, 0), "Blank Cursor");
// Set the blank cursor to the JPanel.
this.setCursor(blankCursor);
}
#Override
public void actionPerformed(ActionEvent actionEvent) // Without the method and the repaint() the mouse listener will not work
{
repaint();
}
public class ProjectileThread extends Thread
{
#Override
public void run()
{
projectileX = playerX + player.getWidth(null);
projectileY = playerY + player.getHeight(null) / 2;
}
}
public static void main(String[] args)
{
JFrame frame = new JFrame("A Game by me");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setExtendedState(JFrame.MAXIMIZED_BOTH); // Making the frame take a full screen
ImageIcon backgroundImageIcon = new ImageIcon("space_background_2.jpg");
Image backgroundImgage = backgroundImageIcon.getImage();
ImageIcon playerImageIcon = new ImageIcon("spaceship_1.png");
Image playerImage = playerImageIcon.getImage();
ImageIcon projectileIcon = new ImageIcon("spaceship_projectile_1.png");
Image projectileImage = projectileIcon.getImage();
frame.add(new MyJPanel(backgroundImgage,playerImage,projectileImage));
frame.setVisible(true);
}
} // End of MyJPanel
There some variables and methods i don't use so don't mind them please. The points to notice in the code:
if (e.getKeyCode() == KeyEvent.VK_SPACE) // If pressing space - shoot
{
flag = true;
moveProjectile();
}
repaint();
If pressing space -> flag = true which means
if (flag)
{
projectileX = playerX + player.getWidth(null);
projectileY = playerY + player.getHeight(null) / 2 - 27;
graphics.drawImage(projectileImage,projectileX,projectileY,null);
}
Draw the projectile and move it to the right. The problem is it's never moved to the right. Instead it's following the spaceship which moves by the mouse.
Any suggestions will be very appreciated.
public class ProjectileThread extends Thread
{
public ProjectileThread(int playerX,int playerY)
{
projectileX = playerX + player.getWidth(null);
projectileY = playerY + player.getHeight(null) / 2;
}
#Override
public void run()
{
while (projectileX < getWidth())
{
projectileX += 2;
}
}
}
public void keyPressed(KeyEvent e)
{
if (e.getKeyCode() == KeyEvent.VK_SPACE) // If pressing space - shoot
{
ProjectileThread projectileThread = new ProjectileThread(playerX,playerY);
projectileThread.start();
}
repaint();
}
Your moveProjectile method moves the projectile horizontally by adding 2 to its X coordinate
this.projectileX += 2;
However, your paint method overwrite this value with your player X coordinate:
projectileX = playerX + player.getWidth(null);
So everytime you paint your projectile, it's in the same place relative to the player. You need to draw the projectile first using the player coordinates, and then move it without resetting its X coordinate.
You have a thread that should be started when the projectile is fired. So in your handler for the space key, start the thread and pass it the player coordinate. This is your start point. Then in the run method of the thread, move the projectile and wait a bit in a loop.
while (projectileX < getWidth())
{
projectileX += 2;
}
All this does is set projectile = getWidth() + 1 (or possibly+2).
Similarly, your moveProjectile method has this:
while (projectileX < this.getWidth())
{
this.projectileX += 2;
repaint();
}
Which does the same thing. Note that the repaint() in the body of the loop essentially does nothing, since you block the event thread until the moveProjectile() method returns

Java Array Loop Graphics page not functioning

edit 2: I decided that it would be easier to understand if I just put the entire code up, so that you can test it.
edit: I realize that what I said was unclear, so I will explain this as best as I can. Basically, I am drawing rectangles on a Graphics page using the fillRect method. The problem is that when I change the size of one, they all change, as they are all being redrawn everytime a new one is drawn. To correct this, I added an array that stores all of the sizes which are input via the scrollwheel in another part of the problem. Anyways, I know that the problem is isolated to the loop that supposedly draws them all a certain size, so I added a loop that in theory should give me a temporary variable each time to use that redraws all of the rectangle's sizes starting at 0 each time the main loop is run. The problem is that this does not in fact redraw the rectangles to their individual sizes, and instead draws them to the current size. I have updated the code part as well.
I am having trouble with a project in Java. What it is supposed to do is change the size of each individual rectangle object by storing it in an array, and then recreating the rectangles based off the length from the array. I (at least I think) do this by creating a variable that should be equal to the SIZE that is changed in another part of the program, and then set that equal to the particular element in the array at i. Anyhow, when I do this, I change all of the lengths to whatever the current length is when I draw a rectangle. I know that the problem is by me using i in the size part, but what would I use? Thanks in advance for any help!
Here is the code:
public class Dots
{
public static void main(String[] args)
{
JFrame frame = new JFrame("Array Rectangles");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
DotsPanel dotsPanel = new DotsPanel();
frame.getContentPane().add(dotsPanel);
//buttons
JButton btnNewButton = new JButton("RED");
btnNewButton.setHorizontalAlignment(SwingConstants.LEFT);
btnNewButton.setVerticalAlignment(SwingConstants.BOTTOM);
btnNewButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
}
});
btnNewButton.setForeground(Color.RED);
dotsPanel.add(btnNewButton);
JButton btnNewButton_1 = new JButton("GREEN");
btnNewButton_1.setForeground(Color.GREEN);
btnNewButton_1.setVerticalAlignment(SwingConstants.BOTTOM);
dotsPanel.add(btnNewButton_1);
JButton btnNewButton_2 = new JButton("BLUE");
btnNewButton_2.setForeground(Color.BLUE);
dotsPanel.add(btnNewButton_2);
JButton btnNewButton_3 = new JButton("BLACK");
btnNewButton_3.setForeground(new Color(0, 0, 0));
dotsPanel.add(btnNewButton_3);
frame.pack();
frame.setVisible(true);
}
}
import java.util.ArrayList;
import java.util.Random;
import javax.swing.JPanel;
import java.awt.*;
import java.awt.event.*;
public class DotsPanel extends JPanel
{
// radius of each dot
private int SIZE = 25;
private int SIZEAccess;
private static final Random generator = new Random();
//used to count amount of dots
private ArrayList<Point> pointList;
int[] sizes = new int [10000];
//Sets up this std. sized panel to listen for mouse events.
public DotsPanel()
{
pointList = new ArrayList<Point>();
addMouseListener (new DotsListener());
addMouseMotionListener(new DotsListener());
addMouseWheelListener(new DotsListener());
setBackground(Color.white);
setPreferredSize(new Dimension(1024, 768));
}
//used to generate a random color
public static Color randomColor() {
return new Color(generator.nextInt(256), generator.nextInt(256), generator.nextInt(256));
}
// Draws all of the dots stored in the list.
public void paintComponent(Graphics page)
{
super.paintComponent(page);
//draws a centered dot of random color
int i = 0;
for (Point spot : pointList)
{
sizes[i] = SIZE;
//SIZEAccess = SIZE;
//sizes[i] = SIZEAccess;
//page.fillRect(spot.x-SIZE, spot.y-SIZE, SIZE*2, SIZE*2);
for (int temp = 0; temp <= i; temp++)
page.fillRect(spot.x-sizes[temp], spot.y-sizes[temp], sizes[temp]*2, sizes[temp]*2);
//page.fillRect(spot.x-SIZE, spot.y-SIZE, SIZE*2, SIZE*2);
//page.setColor(randomColor());
//page.setColor(c)
i++;
}
//displays the amount of rectangles drawn at the top left of screen
page.drawString("Count: " + pointList.size(), 5, 15);
page.drawString("To change the size of the squares, use mouse scroll wheel.", 350, 15);
page.drawString("Size: " + SIZE, 950, 15);
}
// Represents the listener for mouse events.
private class DotsListener implements MouseListener, MouseMotionListener, MouseWheelListener
{
// Adds the current point to the list of points and redraws
// the panel whenever the mouse button is pressed.
public void mousePressed(MouseEvent event)
{
pointList.add(event.getPoint());
repaint();
}
// Provide empty definitions for unused event methods.
public void mouseClicked(MouseEvent event) {
}
public void mouseReleased(MouseEvent event) {
}
public void mouseEntered(MouseEvent event) {
}
public void mouseExited(MouseEvent event) {}
// Adds the current point to the list of points and redraws
// the panel whenever the mouse button is dragged.
public void mouseDragged(MouseEvent event) {
pointList.add(event.getPoint());
repaint();
}
public void mouseMoved(MouseEvent event) {
}
public void mouseWheelMoved(MouseWheelEvent event)
{
int notches = 0;
notches = event.getWheelRotation();
//int
if (notches > 0)
{
SIZE = SIZE + notches;
notches = 0;
}
else if (notches < 0)
{
int tempSIZE = SIZE;
tempSIZE = tempSIZE + notches;
//prevents the program from having dots that increase due to multiplying negatives by negatives
//by making anything less than 1 equal 1
if(tempSIZE < 1)
tempSIZE = 1;
SIZE = tempSIZE;
notches = 0;
}
}
}
//SIZE = SIZE + notches;
}
You appear to have ArrayList's interacting with arrays in a confusing mix that makes it hard for us to follow your logic. This suggests that your logic may be too complex for your own good and that your code might benefit from simplification. Why not instead create a List<Rectangle> such as an ArrayList<Rectangle>, and then simply loop through this list in your paintComponent method, and draw each Rectangle using the Graphics2D object's draw(...) or fill(...) method:
private List<Rectangle> rectangleList = new ArrayList<>();
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
for (Rectangle rectangle : rectangleList) {
g2.fill(rectangle);
}
}
For example:
import java.awt.BasicStroke;
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.awt.Stroke;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
#SuppressWarnings("serial")
public class Foo extends JPanel {
private static final int PREF_W = 600;
private static final int PREF_H = PREF_W;
private static final Color BACKGROUND = Color.black;
private static final Color FILL_COLOR = Color.pink;
private static final Color DRAW_COLOR = Color.red;
private static final Stroke STROKE = new BasicStroke(3);
private List<Rectangle> rectangleList = new ArrayList<>();
private Point pressPoint = null;
private Point dragPoint = null;
public Foo() {
setBackground(BACKGROUND);
MyMouseAdapter myMouseAdapter = new MyMouseAdapter();
addMouseListener(myMouseAdapter);
addMouseMotionListener(myMouseAdapter);
}
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
Stroke oldStroke = g2.getStroke();
g2.setStroke(STROKE);
for (Rectangle rectangle : rectangleList) {
g2.setColor(FILL_COLOR);
g2.fill(rectangle);
g2.setColor(DRAW_COLOR);
g2.draw(rectangle);
}
g2.setStroke(oldStroke);
if (pressPoint != null && dragPoint != null) {
g2.setColor(FILL_COLOR.darker());
int x = Math.min(pressPoint.x, dragPoint.x);
int y = Math.min(pressPoint.y, dragPoint.y);
int width = Math.abs(pressPoint.x - dragPoint.x);
int height = Math.abs(pressPoint.y - dragPoint.y);
g2.drawRect(x, y, width, height);
}
}
private class MyMouseAdapter extends MouseAdapter {
#Override
public void mousePressed(MouseEvent e) {
pressPoint = e.getPoint();
repaint();
}
#Override
public void mouseDragged(MouseEvent e) {
dragPoint = e.getPoint();
repaint();
}
#Override
public void mouseReleased(MouseEvent e) {
dragPoint = e.getPoint();
int x = Math.min(pressPoint.x, dragPoint.x);
int y = Math.min(pressPoint.y, dragPoint.y);
int width = Math.abs(pressPoint.x - dragPoint.x);
int height = Math.abs(pressPoint.y - dragPoint.y);
Rectangle rect = new Rectangle(x, y, width, height);
rectangleList.add(rect);
pressPoint = null;
dragPoint = null;
repaint();
}
}
private static void createAndShowGui() {
JFrame frame = new JFrame("Foo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new Foo());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}

Moving objects and timers

I have a screen with say 500 width and 400 height, and I have a vector with a bunch of shapes. let say the vector has 2 different shapes for example. I want the object to randomly pop up from the bottom of the screen reach a certain ascent and then fall back down (similar to game fruit ninja, where the fruits are my shapes).
In my main (view) I have a vector of shapes of which i instantiate the timers, add to array and place them in the buttom of the screen using the translate function. My timer takes in an action listener which basically changes the translate of the shape to move up till ascent and then down, but my problem is that all the shapes start at the same time regardless.
Something like this:
Shape f = new Shape(new Area(new Ellipse2D.Double(0, 50, 50, 50)));
f.translate(0, 400);
f.timer = new Timer( 10 , taskPerformer);
f.timer.start();
vector.add(f);
Shape f2 = new Shape(new Area(new Rectangle2D.Double(0, 50, 50, 50)));
f2.translate(200, 400);
f2.timer = new Timer( 10 , taskPerformer);
f2.timer.setInitialDelay(5000);
f2.timer.start();
vector.add(f2);
and my action listener:
Random generator = new Random();
ActionListener taskPerformer = new ActionListener() {
public void actionPerformed(ActionEvent evt) {
//...Perform a task...
for (Shape s : model.getShapes()) {
// Scale object using translate
// once reached ascent drop down
// translate to diffrenet part of the bottom of the screen
// delay its timer
}
update();
//basically repaints
}
};
I'm running into problems that all shapes follow the same timer, and begin to pop up at the same time (no delay) ...
Any suggestions on how to avoid this or if there is a different approach i should try
"I want the object to randomly pop up from the bottom of the screen reach a certain ascent and then fall back down"
See the runnable example below. What I do is pass a radomDelayedStart to the Shape. Every tick of the timer, the randomDelayedStart decreases til it reaches 0, that's when the flag to be drawn in raised. Most of the logic is in the Shape class methods, which are called in the Timers Actionlistener. Everything is done in one Timer. For the ascent, I just used a hard coded 50, but you can also pass a random ascent to the Shape. Let me know if you have any questions. I tried to made the code as clear as possible.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class RandomShape extends JPanel {
private static final int D_HEIGHT = 500;
private static final int D_WIDTH = 400;
private static final int INCREMENT = 8;
private List<Shape> shapes;
private List<Color> colors;
private Timer timer = null;
public RandomShape() {
colors = createColorList();
shapes = createShapeList();
timer = new Timer(30, new ActionListener() {
public void actionPerformed(ActionEvent e) {
for (Shape shape : shapes) {
shape.move();
shape.decreaseDelay();
repaint();
}
}
});
JButton start = new JButton("Start");
start.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
timer.start();
}
});
JButton reset = new JButton("Reset");
reset.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
shapes = createShapeList();
timer.restart();
}
});
JPanel panel = new JPanel();
panel.add(start);
panel.add(reset);
setLayout(new BorderLayout());
add(panel, BorderLayout.PAGE_START);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
for (Shape shape : shapes) {
shape.drawShape(g);
}
}
#Override
public Dimension getPreferredSize() {
return new Dimension(D_WIDTH, D_HEIGHT);
}
private List<Color> createColorList() {
List<Color> list = new ArrayList<>();
list.add(Color.BLUE);
list.add(Color.GREEN);
list.add(Color.ORANGE);
list.add(Color.MAGENTA);
list.add(Color.CYAN);
list.add(Color.PINK);
return list;
}
private List<Shape> createShapeList() {
List<Shape> list = new ArrayList<>();
Random random = new Random();
for (int i = 0; i < 20; i++) {
int randXLoc = random.nextInt(D_WIDTH);
int randomDelayedStart = random.nextInt(100);
int colorIndex = random.nextInt(colors.size());
Color color = colors.get(colorIndex);
list.add(new Shape(randXLoc, randomDelayedStart, color));
}
return list;
}
class Shape {
int randXLoc;
int y = D_HEIGHT;
int randomDelayedStart;
boolean draw = false;
boolean down = false;
Color color;
public Shape(int randXLoc, int randomDelayedStart, Color color) {
this.randXLoc = randXLoc;
this.randomDelayedStart = randomDelayedStart;
this.color = color;
}
public void drawShape(Graphics g) {
if (draw) {
g.setColor(color);
g.fillOval(randXLoc, y, 30, 30);
}
}
public void move() {
if (draw) {
if (y <= 50) {
down = true;
}
if (down) {
y += INCREMENT;
} else {
y -= INCREMENT;
}
}
}
public void decreaseDelay() {
if (randomDelayedStart <= 0) {
draw = true;
} else {
randomDelayedStart -= 1;
}
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame frame = new JFrame();
frame.add(new RandomShape());
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}

How do I draw the same moving image multiple times?

Hello I'm making a platformer game and when you press space the character shoots a fireball that moves across the screen but when you press space again the fireball's coordinates are set back to the player's coordinates rather than drawing another fireball which is what I want.
import java.awt.*;
import javax.swing.*;
public class Fire extends JPanel{
Image fireball;
private int x=155000,y=155000;
Player player = new Player();
public void paint(Graphics g){
g.drawImage(fireball, x, y, null);
}
public Fire(){
}
public void update(){
fireball = new ImageIcon("C:\\Users\\steven.greens10\\Desktop\\Programs\\Raw Java\\Platform\\res\\fireball.png").getImage();
x+=5;
if(x > 640){
x=155000;
}
}
public void shoot(Player p){
x = p.getX();
y = p.getY();
repaint();
}
}
#KevinWorkman is right. You need some kind of data structure to hold the fireballs. In the example below I used a List of Fireball.
List<Fireball> fireBalls;
...
private class Fireball {
Image fireball;
int x = 150;
int y = 125;
public Fireball(Image image) {
fireball = image;
}
public void drawFireball(Graphics g) {
g.drawImage(fireball, x, y, 50, 50, null);
}
}
To paint them, I just iterate through them. To make them move forward I just increas the x value in the timer and call repaint
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
...
for (Fireball ball : fireBalls) {
ball.drawFireball(g);
}
}
Here's the complete code
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import java.util.*;
import java.util.List;
import java.util.logging.*;
import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.Timer;
public class WannaBeStreetFighter extends JPanel {
private static final int D_W = 700;
private static final int D_H = 250;
private static final int X_INC = 10;
List<Fireball> fireBalls;
BufferedImage ryu;
BufferedImage fireball;
BufferedImage background;
public WannaBeStreetFighter() {
try {
ryu = ImageIO.read(new URL("http://www.sirlin.net/storage/street_fighter/ryu_hadoken_pose.png?__SQUARESPACE_CACHEVERSION=1226531909576"));
background = ImageIO.read(new URL("http://fightingstreet.com/folders/variousinfofolder/ehondasbath/hondasfz3stage.gif"));
fireball = ImageIO.read(new URL("http://farm6.staticflickr.com/5480/12297371495_ec19ded155_o.png"));
} catch (IOException ex) {
Logger.getLogger(WannaBeStreetFighter.class.getName()).log(Level.SEVERE, null, ex);
}
fireBalls = new LinkedList<>();
Timer timer = new Timer(40, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
Iterator<Fireball> it = fireBalls.iterator();
while (it.hasNext()) {
Fireball ball = it.next();
if (ball.x > D_W) {
it.remove();
System.out.println(fireBalls.size());
} else {
ball.x += X_INC;
repaint();
}
}
}
});
timer.start();
InputMap inputMap = getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
inputMap.put(KeyStroke.getKeyStroke("SPACE"), "hadouken");
getActionMap().put("hadouken", new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
fireBalls.add(new Fireball(fireball));
}
});
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(background, 0, 0, D_W, D_H, this);
g.drawImage(ryu, 50, 125, 150, 115, this);
for (Fireball ball : fireBalls) {
ball.drawFireball(g);
}
}
#Override
public Dimension getPreferredSize() {
return new Dimension(D_W, D_H);
}
private class Fireball {
Image fireball;
int x = 150;
int y = 125;
public Fireball(Image image) {
fireball = image;
}
public void drawFireball(Graphics g) {
g.drawImage(fireball, x, y, 75, 50, null);
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame frame = new JFrame("Best Street Fighter ever");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new WannaBeStreetFighter());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}
Did you try creating another instance of Image? For example:
Image fireball, firball2;
Now you have two Image objects. So when you call g.dawImage(...):
public void paint(Graphics g){
g.drawImage(fireball, x, y, null);
g.drawImage(fireball2, x+10, y+10, null);//just draw this other Image
}
You can just keep drawing multiple images. Also, I changed the x and y positions, so the two Image objects don't overlap.
Now if you want a bunch of Image objects, then use an ArrayList of Image objects:
ArrayList<Image> fireballs = new ArrayList<Image>();
Read more about ArrayList here.

Categories

Resources