adding and removing shapes continuously in a loop? - java

I'm trying to write a program that displays 10 randomly colored and randomly located boxes, but according to the assignment, "Only the last 10 random boxes are to be displayed on the screen. That is, when the 11th box is drawn, remove the 1st box that was drawn. When the 12th box is drawn, remove the 2nd box, and so on".
I'm not sure how to do this, as the farthest I can get is to use a for loop to display 10 random boxes.
This is what I have so far:
package acm.graphics;
import acm.graphics.*;
import acm.program.*;
import java.awt.*;
import java.util.Random;
import javax.swing.*;
public class ShootingStar extends GraphicsProgram
{
public void run()
{
final int width = 800;
final int height = 600;
final int boxWidth = 50;
final int maxBoxes = 10;
this.setSize(width, height);
Random random = new Random();
for( int i = 0; i<=maxBoxes ;i++) {
float r = random.nextFloat();
float b = random.nextFloat();
float g = random.nextFloat();
Color randColor = new Color(r,g,b);
GRect r1 = new GRect(boxWidth, boxWidth);
r1.setFilled(true);
r1.setColor(randColor);
GPoint x = new GPoint(random.nextInt(width),
random.nextInt(height));
add(r1, x);
}
this.pause(100);
}
}
please any tips or advice would be greatly appreciated

One way to do it would be:
public class Test {
private int boxWidth, boxHeight = 50;
private GRect[] rects;
private int first;//keep track of oldest rectangle
public Test()
{
this.rects = new GRect[10];
this.first = 0;
}
void drawRects()
{
//for each rectangle, draw it
}
void addRect()
{
this.rects[first] = new GRect(boxWidth, boxHeight);
first++;
first = first % 10; //keeps it within 0-9 range
}
}
Just call addRect() whenever a new rectangle needs to be added and the new one will replace the oldest one.

You're only iterating ten times, which only makes ten boxes, right? Let's start there. maxBoxes should be larger than 10 (I don't know the specifics of what you're trying to do, so I can't say what maxBoxes should be)
Basically, you want to store the information for these boxes somewhere, and then pull the last ten items out. You could use an array of arrays for this. If you're pushing to then end of the main array, then you just have to pop off the last ten, then draw the boxes.

Related

How do I make Random generating objects come on my Screen?

This is my background Image that i have usedI am a New programmer and I am still learning to code. I am tring to create a flappy bird game but my code does not seem to work. What I am tring to do is create code that generates random pipes within my program and tring to make them have collision with the red Ball.
I have tried to look around for flappy bird games that explain to me how it works but it does not work within my code or it is very very complicated I can not understand.
Hey Thanks for the help but I had tried to implement your code and I got this error. I am trying to fix this. As for your other comments I was trying to make a game called flappy bird in which I must generate random pipes with varying heights of pipes with the same amount of space in between. This is what is happening:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.Color;
import java.awt.Font;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import java.util.Random;
import java.awt.Rectangle;
/**
* Auto Generated Java Class.
*/
public class Game extends JFrame implements ActionListener{
static final int NUMBER_OF_OBSTACLES = 30; // pre-assign the number of obstacles to be generated
// setup our objects for our game
JLabel[] columns = new JLabel [NUMBER_OF_OBSTACLES];
public Rectangle bird;
public final int WIDTH = 100, HEIGHT = 100;
public Random rand;
int number;
ImageIcon lblBackground = new ImageIcon("Test1.jpg");
ImageIcon lblBackground2 = new ImageIcon("Background2.jpg");
static int randomNumber;
int xLocation = 0;
int yLocation = 0;
int wLocation = 450;
int xForRect = 300;
int yForBall = 300;
int xForRectTop = 300;
static int randY;
int xSpeed = 1;
int ySpeed = 1;
int delay = 5;
Rectangle rect;
public Game() {
Rectangle column [];
column = new Rectangle [150];
setLayout(null);
setSize (404, 600);
setVisible(true); //sets everything to visable
}
private void generateRectangles() {
for (int i = 0; i < columns.length; i ++ ) {
columns[i] = new JLabel("" + i); // the name of the object will be shown as the number it is
columns[i].setBackground(Color.green);
columns[i].setOpaque(true);
columns[i].setBounds(randomRect());
}
}
private Rectangle randomRect() {
// create a rectangle to store the bounds of our new object
Rectangle rect = new Rectangle();
rect.height = randomizer(5, 100); // random height 1 to 100
rect.width = randomizer(5, 100); // random width 1 to 100
return rect;
}
private static int randomizer(int min, int max) {
Random random = new Random(); // create new randomizer
int number = random.nextInt(max - min); //randomizes a number from 0 to dist between them (for example if we are generating from 50 to 100 it will run from 0 to 50)
number = number + min; // then add 50 to match the bottom range
return number; // return this random number to the method that called for it
}
public void makeColumn(Graphics g, Rectangle column) {
g.setColor(Color.green);
g.fillRect(column.x, column.y, column.width, column.height);
}
public static int addRandomColumn() {
randomNumber = (int)(Math.random() * 300 + 250);
randomNumber = randY;
return randY;
}
public void paint(Graphics g){
super.paint(g);
for (int p = 0; p < 9999999; p = p+1) {
for (int i = 0; i <=630; i= i + 1){
lblBackground.paintIcon(this,g, xLocation, yLocation);
System.out.println(xLocation);
xLocation = xLocation - xSpeed;
g.setColor(Color.red);
g.fillRect(150, yForBall, 20, 20);
yForBall = yForBall + 1;
rect = new Rectangle(xForRect,450,50,number);
makeColumn(g,rect);
rect = new Rectangle(xForRectTop,0,50,number);
makeColumn(g,rect);
xForRect = xForRect -1;
xForRectTop = xForRectTop -1;
try {
Thread.sleep(delay);
}
catch (Exception error) {
}
}
}
}
public void actionPerformed(ActionEvent evt){
}
public static void main(String[] args) {
new Game();
}
}
That I what I have so far. Hope you can help me
What I was planing to do was generate pipes in in the program with varying heights.
I will address you question in 2 areas.
1. Firstly project design
It is good to have an idea of what you want before you ask a question or begin writing your program. From the sounds of it I assume you are trying to make a game where you control a bird which must avoid obstacles.
Currently you are generating your game by drawing the components onto the frame. This is a good option but I prefer to generate the components as objects (usually JLabels so that it is easy to give them graphics). By creating objects it allows you to only modify the object on the screen if you want to move it during the game rather than repainting all the components.
Java is an object oriented programming language so it is best if you design your program with a modular structure.
Here are the key features of your program which must be created:
Background JFrame
Obstacle creator
Input listener
Collision checker
I will address merely the obstacle creator because that is what you have asked about in your question.
When writing the obstacle creator you want to write it in a way that is robust and easy to use multiple times. Ideally this will come in the form of a class or function which can be called and returns and object on your screen. This will allow for maximum flexibility.
Also it is worth noting that unless you plan on using your procedures in other classes the modifier public is unnecessary, using private void is better practice.
2. Writing Code
Here I have re-written your program in a simpler way. By not overriding the paint method you save yourself much hassle.
Note the key changes I have made:
I am now generating your game components as JLabels. They are created by the procedures in the Game() method.
The rectangles are no longer painted which will allow easier collision detecting when you write that part of the program
Notice how I created a function which randomly generates numbers. I can now easily call this function from other places in the program later.
Lastly I removed your delay Thread.sleep(delay); code. It is better to use a timer thread to handle your events rather than a delay. I would recommend you create a timer thread which runs parallel to your program. Ever half second when the thread runs you can move the bird in the direction of the input and then check if it has collided with an object from columns array.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.Random;
import java.awt.Rectangle;
public class Game extends JFrame implements ActionListener{
static final int NUMBER_OF_OBSTACLES = 30; // pre-assign the number of obstacles to be generated
// setup our objects for our game
JLabel[] columns = new JLabel [NUMBER_OF_OBSTACLES];
JLabel bird;
public Game() {
// setup the frame
setLayout(null);
setSize (404, 600);
setVisible(true); //sets everything to visable
setDefaultCloseOperation(EXIT_ON_CLOSE);
generateRectangles();
placeBird();
}
private void placeBird() {
// create the new bird
bird = new JLabel("B");
bird.setBackground(Color.red); // set background
bird.setOpaque(true); // make the label's background color not invisible but opaque
bird.setBounds(this.getWidth()/2, 0 , 30, 30); // place bird at top midpoint of screen, its size is a 30,30 square
this.add(bird); // add the bird to our frame
bird.setVisible(true); // show the bird on our frame
}
private void generateRectangles() {
for (int i = 0; i < columns.length; i ++ ) {
columns[i] = new JLabel("" + i); // the name of the object will be shown as the number it is
columns[i].setBackground(Color.green);
columns[i].setOpaque(true);
columns[i].setBounds(randomRect());
this.add(columns[i]);
columns[i].setVisible(true);
}
}
private Rectangle randomRect() {
// create a rectangle to store the bounds of our new object
Rectangle rect = new Rectangle();
rect.height = randomizer(5, 100); // random height 1 to 100
rect.width = randomizer(5, 100); // random width 1 to 100
rect.x = randomizer(1, this.getWidth()); // random x position up to the width of the frame
rect.y = randomizer(30, this.getHeight()); // random y position from 30 up to the height of the frame (NOTE: the 30 gap is so no obstacles start on top of the bird)
return rect;
}
private static int randomizer(int min, int max) {
Random random = new Random(); // create new randomizer
int number = random.nextInt(max - min); //randomizes a number from 0 to dist between them (for example if we are generating from 50 to 100 it will run from 0 to 50)
number = number + min; // then add 50 to match the bottom range
return number; // return this random number to the method that called for it
}
// main runs on startup creating our frame
public static void main(String[] args) {
Game game = new Game(); // start a new game
}
#Override
public void actionPerformed(ActionEvent e) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}

Java: Drawing "Random" Stars

I'm trying to take this code I finally got working for drawing one star and am confused on how to get it working for drawing 25 different stars (such as different sides and spikinness but I am unsure how to go about it exactly. I assume I would make a new random variable int randomStars = (int)(Math.random()*25+1); // Variable for 25 Random Stars to randomly generate the stars but I'm kind of confused where to take it from there.
I'd appreciate the help.
My Code (Using DrawingPanel.java):
import java.awt.*;
public class StarSampler {
public static void main(String[] args)
{
DrawingPanel panel = new DrawingPanel(500, 500);
Graphics2D g = panel.getGraphics();
g.setColor(Color.BLUE);
panel.setBackground(new Color(250, 0, 0));
fillStar(g, 250, 250, 150, 5, .3); // How to rotate it to start at center?
}
public static void fillStar(Graphics2D g, int ctrX, int ctrY, int radius, int nPoints, double spikiness)
{
double xDouble[] = new double[2*nPoints];
double yDouble[] = new double[2*nPoints];
int xPoint[] = new int[2*nPoints];
int yPoint[] = new int[2*nPoints];
nPoints = (int) (nPoints * 2);
int randomStars = (int)(Math.random()*25+1); // Variable for 25 Random Stars
// Would Nestest loop go here? for (randomStars++; randomStars < 25; randomStars++)
for (int i = 0; i < nPoints; i++)
{
double iRadius = (i % 2 == 0) ? radius : (radius * spikiness);
double angle = (270) + (i * 360.0) / (nPoints);
xPoint[i] = (int) (ctrX + iRadius * Math.cos(Math.toRadians(angle)));
yPoint[i] = (int) (ctrY + iRadius * Math.sin(Math.toRadians(angle)));
}
g.fillPolygon(xPoint, yPoint, nPoints); // Creates polygon
}
}
My Output:
Build up slowly. First concentrate on positioning two stars, just two. Pick the coordinates for the centre of the stars and place them. Adjust to get it right (your first attempt will probably have errors). Test, fix, test again, fix again. Repeat.
Then play with the spikiness and other changes so the stars aren't identical. When, and only when, that is tested and working move on to three, four etc. stars. With more stars you will have to be more careful to avoid overlaps.

Why wont squares show up after repaint()?

I posted this question a bit earlier and was told to make it SSCCE so here goes (if I can make any improvements feel free to let me know):
I'm wondering why when my button "confirm" is clicked the old squares disappear and the redrawn squares do not appear on my GUI (made with swing). The Squares class draws 200 spaced out squares with an ID (0, 1, 2, or 3 as String) inside obtained from a different class (for the purpose of this question, let's assume it is always 0 and not include that class). For clarification: Squares draws everything perfectly the first time (also retrieves the correct IDs), but I want it to redraw everything once the button is clicked with new IDs.
Code for Squares:
import javax.swing.*;
import java.awt.*;
import java.awt.geom.*;
import java.util.ArrayList;
public class Squares extends JPanel{
private ArrayList<Rectangle> squares = new ArrayList<Rectangle>();
private String stringID = "0";
public void addSquare(int x, int y, int width, int height, int ID) {
Rectangle rect = new Rectangle(x, y, width, height);
squares.add(rect);
stringID = Integer.toString(ID);
if(ID == 0){
stringID = "";
}
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
FontMetrics fm = g2.getFontMetrics();
int fontAscent = fm.getAscent();
g2.setClip(new Rectangle(0,0,Integer.MAX_VALUE,Integer.MAX_VALUE));
for (Rectangle rect : squares) {
g2.drawString(stringID, rect.x + 7, rect.y + 2 + fontAscent);
g2.draw(rect);
}
}
}
Code for GUI:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class GUIReserver extends JFrame implements Runnable{
private int myID;
private JButton confirm = new JButton("Check Availability and Confirm Reservation");
private JFrame GUI = new JFrame();
private Squares square;
public GUIReserver(int i) {
this.myID = i;
}
#Override
public void run() {
int rows = 50;
int seatsInRow = 4;
confirm.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent evt) {
GUI.getContentPane().remove(square);
square = new Squares();
int spaceNum = 0;
int rowNum = 0;
int offsetX = 200;
int offsetY = 0;
for(int i = 0; i < rows * seatsInRow; i++){
square.addSquare(rowNum * 31 + offsetX,spaceNum * 21 + 50 + offsetY,20,20, 0); //normally the 4th parameter here would retrieve the ID from the main class
rowNum++;
if(rowNum == 10){
rowNum = 0;
spaceNum++;
}
if(spaceNum == 2){
spaceNum = 3;
rowNum = 0;
}
if(spaceNum == 5){
spaceNum = 0;
offsetY += 140;
}
}
GUI.getContentPane().add(square); //this does not show up at all (could be that it wasn't drawn, could be that it is out of view etc...)
GUI.repaint(); //the line in question
}
});
GUI.setLayout(new FlowLayout());
GUI.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
GUI.setLocation(0,0);
GUI.setExtendedState(JFrame.MAXIMIZED_BOTH);
square = new Squares();
int spaceNum = 0;
int rowNum = 0;
int offsetX = 200;
int offsetY = 0;
for(int i = 0; i < rows * seatsInRow; i++){
square.addSquare(rowNum * 31 + offsetX,spaceNum * 21 + 50 + offsetY,20,20, 0); //normally the 4th parameter here would retrieve the ID from the main class
rowNum++;
if(rowNum == 10){
rowNum = 0;
spaceNum++;
}
if(spaceNum == 2){
spaceNum = 3;
rowNum = 0;
}
if(spaceNum == 5){
spaceNum = 0;
offsetY += 140;
}
}
GUI.getContentPane().add(square); //this shows up the way I wish
GUI.add(confirm);
GUI.pack();
GUI.setVisible(true);
}
}
Code for main:
public class AircraftSeatReservation {
static AircraftSeatReservation me = new AircraftSeatReservation();
private final int rows = 50;
private final int seatsInRow = 4;
private int seatsAvailable = rows * seatsInRow;
private Thread t3;
public static void main(String[] args) {
GUIReserver GR1 = new GUIReserver(3);
me.t3 = new Thread(GR1);
me.t3.start();
}
}
One major problem: Your Squares JPanels preferred size is only 20 by 20, and will likely actually be that size since it seems to be added to a FlowLayout-using container. Next you seem to be drawing at locations that are well beyond the bounds of this component, and so the drawings likely will never be seen. Consider allowing your Squares objects to be larger, and make sure to only draw within the bounds of this component.
Note also there is code that doesn't make sense, including:
private int myID;
private JTextField row, column, instru draft saved // ???
package question2;ction1, instruction2, seatLabel, rowLabel; // ???
I'm guessing that it's
private int myID;
private JTextField row, column, instruction1, instruction2, seatLabel, rowLabel;
And this won't compile for us:
int rows = AircraftSeatReservation.getRows();
int seatsInRow = AircraftSeatReservation.getSeatsInRow(); // and shouldn't this take an int row parameter?
since we don't have your AircraftSeatReservation class (hopefully you don't really have static methods in that class).
And we can't compile or run your current code. We don't want to see your whole program, but rather you should condense your code into the smallest bit that still compiles, has no extra code that's not relevant to your problem, but still demonstrates your problem. So as Andrew Thompson recommends, for better help, please create and post your Minimal, Complete, and Verifiable example or Short, Self Contained, Correct Example.
I would try to OOP-ify your problem as much as possible, to allow you to divide and conquer. This could involve:
Creating a SeatClass enum, one with possibly two elements, FIRST and COACH.
Creating a non-GUI Seat class, one with several fields including possibly: int row, char seat ( such as A, B, C, D, E, F), a SeatClass field to see if it is a first class seat or coach, and a boolean reserved field that is only true if the seat is reserved.
This class would also have a getId() method that returns a String concatenation of the row number and the seat char.
Creating a non-GUI Airplane class, one that holds two arrays of Seats, one for SeatClass.FIRST or first-class seats, and one for SeatClass.COACH.
It would also have a row count field and a seat count (column count) field.
After creating all these, then work on your GUI classes.
I'd create a GUI class for Seats, perhaps GuiSeat, have it contain a Seat object, perhaps have it extend JPanel, allow it to display its own id String that it gets from its contained Seat object, have it override getBackground(...) so that it's color will depend on whether the seat is reserved or not.
etc.....

Making a grid, how to make each grid have its own int value? JAVA

I want to create a small grid (let's say 2 x 2) where each individual point in the grid (4 points total) will have its own value of integer. I will also want to be able to call on the values of each point by its location. This is because I want each point's integer to be affected by its neighboring points. What is the best way that I can get each point to have its own values and then be able to call upon those values?
I have this so far, which only makes the grid and displays its values. In the end, I will also want to display its neighbors' values in its location. Thanks!
edit: just looking for best approach to solving this problem to guide me in right direction to go about this.
import javax.swing.JFrame;
import javax.swing.JButton;
import java.awt.GridLayout;
public class Grid {
JFrame frame = new JFrame(); // create frame
JButton[][] grid; // name grid
// constructor
public Grid (int width, int length) {
frame.setLayout(new GridLayout(width, length));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
// create grid
grid = new JButton[width][length]; // allocate size
for (int y = 0; y < length; y++) {
for (int x = 0; x < width; x++) {
grid[x][y] = new JButton("value");
frame.add(grid[x][y]);
}
}
}
public static void main (String[] args) {
// DIMENSION
int d = 2;
// LENGTH
int l = 2;
// WIDTH
int w = 2;
new Grid(l,w); // create new Grid with parameters
}
}
Use a nested int array to make a grid.
int[][]grid = new int[2][2];
for(int x=0; x<2;x++){
for(int y=0; y<2; y++){
grid[x][y] = value;
}
}
This will return a grid you can address (call the value of) by calling int val = grid[x][y]

Iterating through a Java collection to make these balls bounce, any hints?

Apologies if the question isn't clear but I couldn't think of another way to phrase it.
This is for a class assignment which I've been working at in BlueJ all weekend. I have to change a method (bounce) to let a user choose how many balls should be bouncing.
Other requirements are: the balls should be of different sizes and should be displayed in a row along the top of the screen BEFORE they bounce.
In order to do this I have to use a collection (ArrayList, HashMap, HashSet). So far I've used HashMap and have been able to have the user choose a number of "balls" of random sizes which place themselves in random positions in the top half of the screen.
When I try to have each ball bounce from its position at the top of the screen, ending at the right hand side I come up stuck. I can make the code draw one ball, bounce it then draw another ball, bounce it etc until the user selected number of balls has looped round.
There are two other classes, one to draw the canvas and one to draw the balls and move them. Both of which I'm not allowed to touch.
What I'm doing the wrong way is probably right in front of me but i've been staring at this code so long I thought I'd ask.
My current version of the code looks like this:
import java.awt.Color;
import java.util.HashMap;
import java.util.Random;
import java.util.Iterator;
public class BallDemo
{
private Canvas myCanvas;
private HashMap<Integer, BouncingBall> ballMap;
private int n;
private int j;
private BouncingBall ball;
/**
* Create a BallDemo object. Creates a fresh canvas and makes it visible.
*/
public BallDemo()
{
myCanvas = new Canvas("Ball Demo", 600, 500);
}
And the method I have to edit to bounce the balls:
public void bounce(int numBalls)
{
ballMap = new HashMap<Integer, BouncingBall>();
int ground = 400; // position of the ground line
Random randomD1 = new Random();
Random xpos = new Random();
myCanvas.setVisible(true);
// draw the ground
myCanvas.drawLine(50, ground, 550, ground);
// add balls to HashMap
for(n = 0; n < numBalls; n++) {
ballMap.put(numBalls, (ball = new BouncingBall(xpos.nextInt(300), 50, randomD1.nextInt(200), Color.BLUE, ground, myCanvas)));
//
for(j= 0; j < ballMap.size(); j++) {
ball.draw();
boolean finished = false;
while(!finished) {
myCanvas.wait(50); // small delay
ball.move(); // bounce the ball
// stop once ball has travelled a certain distance on x axis
if(ball.getXPosition() >= 550) {
finished = true;
}
}
}
}
}
}
Am I even on the right lines using a HashMap? The combination of keys, values seemed the best way to go. I think I need to somehow iterate through the items placed in the collection to make them bounce using the move() method. But first I need the balls to stay in a row at the top of the screen, no matter how many the user defines.
I'm new to programming and I'm just coming up stumped.
Thanks for any help!
#16dots is partly right, except ballMap.put(numBalls, ball); will over write the same value in the hash map each time, as numBalls does not change...
The key should be unique.
It should read...
for (int n; n < numBalls; n++) {
BouncingBall ball = new BouncingBall(xpos.nextInt(300), 50,
randomD1.
nextInt(200), Color.BLUE, ground, myCanvas);
ballMap.put(n, ball);
}
boolean finished = false;
while (!finished) {
finished = true;
for (int j = 0; j < ballMap.size(); j++) {
BouncingBall selectedBall = ballMap.get(j);
selectedBall.draw();
// Only move the ball if it hasn't finished...
if (selectedBall.getXPosition() < 550) {
selectedBall.move(); // bounce the ball
// stop once ball has travelled a certain distance on x axis
if (selectedBall.getXPosition() < 550) {
finished = false;
}
}
}
myCanvas.wait(50); // small delay
}

Categories

Resources