I'm writing a program taken from the TV show, THE OFFICE, when they're sitting in the conference room and watching the bouncing DVD logo on the screen try to hit the corner. The square is supposed to change color when it hits an edge.
However, I'm running into a few issues.
Issue one: The Square sometimes bounces off an edge. Other times it sinks, and I can't figure out why.
Issue two: I'm not sure how to change the color of the square when it hits the edge.
Issue three: I'm trying to learn how to make a JFRAME fullscreen. And not just fullscreen on my screen but on anyone's.
THE CODE HAS BEEN POSTED TO AN ONLINE IDE FOR EASIER READING. That can be found HERE
Otherwise if you're too busy for that link. Here it is posted below.
import java.util.Random;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class BouncingMischievousSquare extends JPanel implements ActionListener {
private static final int SQUARE_SIZE = 40;
private static final int SPEED_OF_SQUARE = 6;
private int xPosit, yPosit;
private int xSpeed, ySpeed;
BouncingMischievousSquare(){
//speed direction
xSpeed = SPEED_OF_SQUARE;
ySpeed = -SPEED_OF_SQUARE;
//a timer for repaint
//http://docs.oracle.com/javase/tutorial/uiswing/misc/timer.html
Timer timer = new Timer(100, this);
timer.start();
}
public void actionPerformed(ActionEvent e){
//Screensize
int width = getWidth();
int height = getHeight();
xPosit += xSpeed;
yPosit += ySpeed;
//test xAxis
if(xPosit < 0){
xPosit = 0;
xSpeed = SPEED_OF_SQUARE;
}
else if(xPosit > width - SQUARE_SIZE){
xPosit = width - SQUARE_SIZE;
xSpeed = -SPEED_OF_SQUARE;
}
if(yPosit < 0){
yPosit = 0;
ySpeed = SPEED_OF_SQUARE;
}
else if(yPosit > height - SQUARE_SIZE){
xPosit = height - SQUARE_SIZE;
xSpeed = -SPEED_OF_SQUARE;
}
//ask the computer gods to redraw the square
repaint();
}
public void paintComponent(Graphics g){
super.paintComponent(g);
g.fillRect(xPosit, yPosit, SQUARE_SIZE, SQUARE_SIZE );
}
}
MAIN CLASS
import javax.swing.*;
public class MischievousMain {
public static void main(String[] args) {
JFrame frame = new JFrame("Bouncing Cube");
frame.setSize(500, 500);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// mischievous square input
frame.add(new BouncingMischievousSquare());
frame.setVisible(true);
}
}
Anyways, Thanks for taking the time to read through my code. It's appreciated. I'm really interested in different ways to go about this.
Issue one: The Square sometimes bounces off an edge. Other times it
sinks, and I can't figure out why.
You'll hate yourself for this, but
} else if (yPosit > height - SQUARE_SIZE) {
xPosit = height - SQUARE_SIZE;
xSpeed = -SPEED_OF_SQUARE;
}
Should be...
} else if (yPosit > height - SQUARE_SIZE) {
yPosit = height - SQUARE_SIZE;
ySpeed = -SPEED_OF_SQUARE;
}
You were using xPosyit and xSpeed instead of yPosyit and ySpeed...
Issue two: I'm not sure how to change the color of the square when it
hits the edge.
Basically, whenever you detect a edge collision and change direction, simple change the panel's foreground color to something else...
This might require you to have a list of colors from which you can randomly pick or simply randomly generate the color
Then in your paintComponent method, simple use g.setColor(getForeground()) before you fill the rect...
...ps...
To make life easier, you could just write a method that either generates a random color or sets the foreground to a random color, for example...
protected void randomiseColor() {
int red = (int) (Math.round(Math.random() * 255));
int green = (int) (Math.round(Math.random() * 255));
int blue = (int) (Math.round(Math.random() * 255));
setForeground(new Color(red, green, blue));
}
Issue three: I'm trying to learn how to make a JFRAME fullscreen. And
not just fullscreen on my screen but on anyone's.
Take a look at Full-Screen Exclusive Mode API
Related
I've been learning Java from a book called "Introduction to Java by David Eck". In that book, there is a Graphic with GUI chapter where the Rectangles are moved to the center. The book was explaining the stuff that was going on, but most importantly it says that "the drawFrame() subroutine will automatically be called about 60 times per second.". So, how can we lower the number of times the drawFrame() is called. The reason is I want to see the rectangles moving in slow motion.
This is the complete code:
package com.example.ch3movingrects;
import javafx.animation.AnimationTimer;
import javafx.application.Application;
import javafx.scene.layout.BorderPane;
import javafx.scene.Scene;
import javafx.stage.Stage;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.paint.Color;
/**
* When run as a program, this class opens a window on the screen that
* shows a set of nested rectangles that seems to be moving infinitely
* inward towards the center. The animation continues until the user
* closes the window.
*/
public class ch3MovingRects extends Application {
/**
* Draws a set of nested rectangles. This subroutine is called 60 times per
* second and is responsible for redrawing the entire drawing area. The
* parameter g is used for drawing. The frameNumber starts at zero and
* increases by 1 each time this subroutine is called. The parameters width
* and height give the size of the drawing area, in pixels.
* The sizes and positions of the rectangles that are drawn depend
* on the frame number, giving the illusion of motion.
*/
public void drawFrame(GraphicsContext g, int frameNumber, double elapsedSeconds, int width, int height) {
g.setFill(Color.WHITE);
g.fillRect(0,0,width,height); // Fill drawing area with white.
double inset; // Gap between edges of drawing area and the outer rectangle.
double rectWidth, rectHeight; // The size of one of the rectangles.
g.setStroke(Color.BLACK); // Draw the rectangle outlines in black.
inset = frameNumber % 15 + 0.5; // The "+ 0.5" is a technicality to produce a sharper image.
rectWidth = width - 2*inset;
rectHeight = height - 2*inset;
while (rectWidth >= 0 && rectHeight >= 0) {
g.strokeRect(inset, inset, rectWidth, rectHeight);
inset += 15; // rectangles are 15 pixels apart
rectWidth -= 30;
rectHeight -= 30;
}
}
//------ Implementation details: DO NOT EXPECT TO UNDERSTAND THIS ------
public void start(Stage stage) {
int width = 800; // The width of the image. You can modify this value!
int height = 600; // The height of the image. You can modify this value!
Canvas canvas = new Canvas(width,height);
drawFrame(canvas.getGraphicsContext2D(), 0, 0, width, height);
BorderPane root = new BorderPane(canvas);
root.setStyle("-fx-border-width: 4px; -fx-border-color: #444");
Scene scene = new Scene(root);
stage.setScene(scene);
stage.setTitle("Infinte Moving Rects"); // STRING APPEARS IN WINDOW TITLEBAR!
stage.show();
stage.setResizable(false);
AnimationTimer anim = new AnimationTimer() {
private int frameNum;
private long startTime = -1;
private long previousTime;
public void handle(long now) {
if (startTime < 0) {
startTime = previousTime = now;
drawFrame(canvas.getGraphicsContext2D(), 0, 0, width, height);
}
else if (now - previousTime > 0.95e9/60) {
// The test in the else-if is to make sure that drawFrame() is
// called about once every 1/60 second. It is required since
// handle() can be called by the system more often than that.
frameNum++;
drawFrame(canvas.getGraphicsContext2D(), frameNum, (now-startTime)/1e9, width, height);
previousTime = now;
}
}
};
anim.start();
}
public static void main(String[] args) {
launch();
}
} // end MovingRects
Any ideas on how can we lower the number of calls to drawFrame subroutine?
I am currently working on a 3 cushion billiards game project. I have added two balls on the table so far. I am trying to move one of the balls but I am having a hard time doing that. Should I use a timer? If so then could you tell me an effective way to use the timer on my code so I can move my balls?
Your help would be much appreciated.
Thanks in advance.
Farhan Hasan
I have tried to create a move function for the class balls. But I am not sure what I should put inside the function, I have added the xSpeed and ySpeed. The xLocation and the yLocation changes depending on the xSpeed and ySpeed.
public class Balls
{
private Color ballFillColor;
private Color ballBorderColor;
private int ballX = 0;
private int ballY = 0;
private int xSpeed = 5;
private int ySpeed = 0;
private int ballWidth = 0;
private int ballHeight = 0;
Timer t;
public boolean fillBall = false;
private static Balls ballArray[]; //Required for drawMultipleBalls
Balls(){ //Constructor
ballBorderColor = Color.black;
}
Balls(int ballX, int ballY, int ballWidth, int ballHeight, Color ballBorderColor, JFrame window){ //Constructor
// X , Y , Width, Height, Border Colour, container
this.setBallBorderColor(ballBorderColor);
this.setBallWidth(ballWidth);
this.setBallHeight(ballHeight);
this.setBallX(ballX);
this.setBallY(ballY);
this.drawBall(window);
}
//Here is the move function. I am not really sure what to do here.
public void move()
{
if(this.ballX < 1000 - this.ballWidth)
{
this.ballX += this.xSpeed;
}
try
{
Thread.sleep(1);
}
catch(Exception e)
{
}
}
//GET AND SET FUNCTIONS HERE
//HERE ARE THE FUNCTIONS WHICH ARE RESPONSIBLE FOR DRAWING MY BALLS IN JFRAME
public void drawBall(JFrame frame)
{
frame.getContentPane().add(new MyComponent());
}
public void drawMultipleBalls(JFrame frame, Balls[] balls)
{
ballArray = balls;
frame.getContentPane().add(new MyComponent2());
}
private class MyComponent extends JComponent{
public void paintComponent(Graphics g){
if (fillBall) //Fill first, and then draw outline.
{
g.setColor(ballFillColor);
g.fillOval(getBallX(),getBallY(), getBallHeight(),getBallWidth());
}
g.setColor(getBallBorderColor());
g.drawOval(getBallX(),getBallY(), getBallHeight(),getBallWidth());
}
}
private class MyComponent2 extends JComponent{
public void paintComponent(Graphics g){
for (int i = 0; i < ballArray.length; i++)
{
if (ballArray[i].fillBall) //Fill first, and then draw outline.
{
g.setColor(ballArray[i].ballFillColor);
g.fillOval(ballArray[i].getBallX(),ballArray[i].getBallY(), ballArray[i].getBallHeight(),ballArray[i].getBallWidth());
}
g.setColor(ballArray[i].getBallBorderColor());
g.drawOval(ballArray[i].getBallX(),ballArray[i].getBallY(), ballArray[i].getBallHeight(),ballArray[i].getBallWidth());
}
}
}
Hopefully, I can have two movable balls for the game, the should bounce back as the hit the edge of the screen and they should be able to slow down over time. For that, I am thinking to use a damper (I will multiply the xSpeed and ySpeed with a number less than 1, eventually it will slow down the ball)
Here is a simple example I came up with to show a ball moving and bouncing off the edges.
The direction changes based on the boundary. Left and top edges just check for 0. Bottom and right edges need to include the diameter of the ball.
The x and y increments are independent. And these amounts in conjunction with the timer can change the movement. Notice however, that to have objects bounce off of each other (as in a pool game) is more complicated due to angle of trajectories, etc. And the distances bounced will vary and slow with time based on frictional values. Everything else is documented in the Java API.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class MovementDemo extends JPanel implements ActionListener {
JFrame frame = new JFrame("Movement Demo");
int size = 500;
int x = 50;
int y = 200;
int diameter = 50;
int yinc = 2;
int xinc = 2;
int xdirection = 1;
int ydirection = 1;
public MovementDemo() {
setPreferredSize(new Dimension(size, size));
frame.add(this);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> new MovementDemo().start());
}
public void start() {
Timer timer = new Timer(100, this);
timer.setDelay(5);
timer.start();
}
public void actionPerformed(ActionEvent ae) {
if (x < 0) {
xdirection = 1;
}
else if (x > size - diameter) {
xdirection = -1;
}
if (y < 0) {
ydirection = 1;
}
else if (y > size - diameter) {
ydirection = -1;
}
x = x + xdirection * xinc;
y = y + ydirection * yinc;
repaint();
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setColor(Color.BLUE);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2d.fillOval(x, y, diameter, diameter);
}
}
It seems in general there are a few things you need to figure out:
has the ball collided with another ball
has the ball collided with a wall
otherwise just figure out what is the ball's new position based on its velocity
Below is some sample code that stubs some of this out. You can first compare the current ball's position to all others (not including the current ball of course). If there are any equal positions, process a collision with a ball. If the ball is at the window border i.e it hit a wall, process a collision with a wall. Otherwise just calculate its new position based on its current velocity.
The process collision part is just to apply physics mechanics to whatever degree of complexity you require. One general suggested change would be to update the velocity of the balls then apply it to the position after. The specific calculations for velocity changes you could apply as needed and as you can imagine it can get pretty involved which is why I suggest using a separate method and possibly a sub class for velocity instead of managing each part of the velocity vector in the ball itself. I used the wall as an object because of this. The composition, weights, velocities etc of the object's colliding can affect the resulting collision, but how complex you want that processing to be is up to you.
Sorry I'm no physics expert but I hope this sends you in the right direction in terms of code! Also this might help with the specific calculations you might want to use:
https://www.khanacademy.org/science/physics/one-dimensional-motion/displacement-velocity-time/v/calculating-average-velocity-or-speed
public void move()
{
// check if balls are on same position not including this ball
for(Ball b: ballArray){
if (this.position == b.position && this != b){
processCollision(this, b, null);
} else{
// if the ball hasn't collided with anything process its movement based on speed
// this assumes a 1000 x 1000 window for keeping objects inside it
if(this.ballX < 1000 - this.ballWidth && this.ballY < 1000 - this.ballHeight){
this.ballX += this.xSpeed;
this.ballY += this.ySpeed;
}else {
processCollision(this, null, new Wall());
}
}
}
try
{
Thread.sleep(1);
}
catch(Exception e)
{
}
}
public void processCollision(Ball b1, Ball b2, Wall w){
// if ball hasn't collided with a wall, process a ball - ball collision
if(w == null){
// apply physics mechanics according the complexity desired for ball collisions
b1.xSpeed -= b2.xSpeed;
b1.ySpeed -= b2.ySpeed;
// ball 2 would end up slowing down
b2.xSpeed -= b1.xSpeed;
b2.ySpeed -= b1.ySpeed;
}
// if ball hasn't collided with a ball, process a ball - wall collision
if(b2 == null){
// apply physics mechanics for hitting a wall
// e.g as below: just send ball in opposite direction
b1.xSpeed = b1.xSpeed * -1;
b1.ySpeed = b1.ySpeed * -1;
}
// either way, process ball's new position based on its new speed
b1.ballX += b1.xSpeed;
b1.ballY += b1.ySpeed;
b2.ballX += b2.xSpeed;
b2.ballY += b2.ySpeed;
}
So I have a program that I'm trying to create for a class, and I need to create a country scene with a farm and a sun. The sun has to bounce up and down. The current problem I'm facing is that the sun keeps going down, and won't bounce up. Here is my code:
import javax.swing.*;
import java.awt.*;
/**
* Date: Oct 14, 2016
* Author:
* Description: Shows a country side with a farm and a sun bouncing up and down.
*/
public class WeAreInThePictures extends JFrame
{
ImageIcon sun, farm, bG; //assigns sun, farm and background to an image variable
static int x = 0, y = -50; //starting position of the sun
static int ySpeed = 10; //speed in y direction
static double delay = 1.0;
public WeAreInThePictures() {
super ("We Are In The Pictures!");
setSize (852, 480);
bG = new ImageIcon ("1.jpg");
sun = new ImageIcon ("sun.png");
farm = new ImageIcon ("farm.png");
setVisible (true);
}
public static void main(String[] args) {
new WeAreInThePictures ();
}
public void paint (Graphics g)
{
for (int i = 0; i < 1000; i++)
{
bG.paintIcon (this, g, 0, 0);
farm.paintIcon (this, g, 500, 50);
y = y + ySpeed;
if (ySpeed > 0)
{
sun.paintIcon (this, g, x, y);
for (int j = 0; j < 550000; j++)
{
delay = Math.pow (delay, 1);
}
}
else if (y > 50)
{
ySpeed = ySpeed - 1;
}
else if (y <= 0)
{
ySpeed = ySpeed - 1;
}
}
}
}
Can someone explain to me what is wrong, how i should fix it and why the problem is occurring?
Your problem is that you appear to have written this code without looking at any Swing Graphics tutorial or similar question on this site regarding Swing animation (why?). You're drawing directly in the JFrame, something that you shouldn't be doing, you've got object mutation code within a paint method, again something that you shouldn't be doing.
Instead do as you recommended in the tutorials, and most any other similar question on this site, in fact, search the problem before asking:
Draw in the paintComponent method of a JPanel that is displayed in a JFrame.
Use a Swing Timer for your animation loop
Change the speed's direction in the timer's ActionListener, not in a paintComponent method.
I'm a noob programmer, and I'm working on a little project that involves a 2D grid of 1000 x 1000 boolean values that change based on an instruction pattern. "After x instructions, how many values in the grid are true?" That kind of thing.
I want to put a little spin on it and render the values as a grid of pixels which are black if their corresponding values are false and white if they're true and that animates in real time as instructions are processed, but I'm pretty lost -- I've never dabbled with 2D graphics in Java. I've read through Oracle's tutorial, which helped, but the way I'm doing things is sufficiently different from its demo that I still feel lost.
My most immediate problem is that I can't even seem to initialize a grid of 1000 x 1000 black pixels using a BufferedImage. Running my code yields a very tiny window with nothing (grayness) in it. Can anyone tell me what I'm doing wrong and suggest how to proceed? My code follows:
import java.awt.image.BufferedImage;
import java.awt.Color;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class PixelGrid extends JPanel {
private BufferedImage grid;
// Ctor initializing a grid of binary (black or white) pixels
public PixelGrid(int width, int height) {
grid = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_BINARY);
}
/**
* Fill an area with a given color
* #param color 0 for black; 1 for white
* #param x1 Starting x coordinate
* #param y1 Starting y coordinate
* #param x2 Ending x coordinate
* #param y2 Ending y coordinate
*/
public void toggleBlock(int color, int x1, int y1, int x2, int y2) {
if (color == 0) {
color = Color.BLACK.getRGB();
}
else {
color = Color.WHITE.getRGB();
}
for (int x = x1; x <= x2; x++) {
for (int y = y1; y <= y2; y++) {
grid.setRGB(x, y, color);
}
}
}
// Clear the grid (set all pixels to black)
public void clear() {
toggleBlock(0, 0, 0, grid.getWidth() - 1, grid.getHeight() - 1);
}
public static void main(String[] args) {
int width = 1000;
int height = 1000;
PixelGrid aGrid = new PixelGrid(width, height);
JFrame window = new JFrame("A Wild Pixel Grid Appears!");
window.add(aGrid); // Incorporates the pixel grid into the window
window.pack(); // Resizes the window to fit its content
window.setVisible(true); // Makes the window visible
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
Note that it doesn't yet deal at all with an actual 2D array of booleans or instruction processing; I'm pretty sure I can handle that on my own, but, for now, I'm just trying to understand how to set up the graphical component.
Your code creates a BufferedImage, but then doesn't do anything with it (graphically). A few options:
Option 1: Override paintComponent of the PixelGrid class and draw the image to the JPanel
#Override
public void paintComponent(Graphics g){
super.paintComponent(g);
g.drawImage(grid, 0, 0, this);
}
Option 2: Use a JLabel and ImageIcon
JLabel label = new JLabel(new ImageIcon(grid));
add(label);
In either case, you will have to call repaint on the Component every time the BufferedImage is changed
//some code
grid.setRGB(x, y, color);
//some more code
repaint();//or label.repaint() if Option 2
Hey Guys I have succesfully made a GUI in java that will scale polygons and circles using a slider. Everything works but I was wondering if there is a way to change the Origin point(Where it scales from). Right now it scales from the corner and I would like it to scale from the middle so I can start it in the middle and it scales out evenly. Also, If anyone could tell me an easy way to replace the Rectangle I have with an Image of some kind so you can scale the Picture up and down would be great! Thank you! Here is my code:
import javax.swing.*;
public class Fred
{
public static void main(String[] args)
{
TheWindow w = new TheWindow();
w.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //X wont close the window with out this line
w.setSize(375,375);
w.setVisible(true);
}
}
import java.awt.*;
import javax.swing.*;
import javax.swing.event.*;
public class TheWindow extends JFrame
{
private JSlider slider; //declare slider
private drawRect myPanel; //declare/ create panel
public TheWindow()
{
super("Slider Example"); //make title
myPanel = new drawRect();
myPanel.setBackground(Color.green); //change background color
slider = new JSlider(SwingConstants.VERTICAL, 0, 315, 10);// restrains the slider from scaling square to 0-300 pixels
slider.setMajorTickSpacing(20); //will set tick marks every 10 pixels
slider.setPaintTicks(true); //this actually paints the ticks on the screen
slider.addChangeListener
(
new ChangeListener()
{
public void stateChanged(ChangeEvent e)
{
myPanel.setD(slider.getValue()); //Wherever you set the slider, it will pass that value and that will paint on the screen
}
}
);
add(slider, BorderLayout.WEST); //similar to init method, adds slider and panel to GUI
add(myPanel, BorderLayout.CENTER);
}
}
import java.awt.*;
import javax.swing.*;
public class drawRect extends JPanel
{
private int d = 25; //this determines the beginning length of the rect.
public void paintComponent(Graphics g)//paints circle on the screen
{
super.paintComponent(g); //prepares graphic object for drawing
g.fillRect(15,15, d, d); //paints rectangle on screen
//x , y, width, height
}
public void setD(int newD)
{
d = (newD >= 0 ? newD : 10); //if number is less than zero it will use 10 for diameter(compressed if statement)
repaint();
}
public Dimension getPrefferedSize()
{
return new Dimension(200, 200);
}
public Dimension getMinimumSize()
{
return getPrefferedSize();
}
}
Changing the "origin point" so it becomes the center of the "zoom" is basically just the process of subtract half of d from the center point.
So, assuming the the center point is 28 ((25 / 2) + 15), you would simply then subtract d / 2 (25 / 2) from this point, 28 - (25 / 2) = 15 or near enough...
I modified the paintComponent method for testing, so the rectangle is always at the center of the panel, but you can supply arbitrary values in place of the originX and originY
#Override
public void paintComponent(Graphics g)//paints circle on the screen
{
super.paintComponent(g); //prepares graphic object for drawing
int originX = getWidth() / 2;
int originY = getHeight() / 2;
int x = originX - (d / 2);
int y = originY - (d / 2);
System.out.println(x + "x" + y);
g.fillRect(x, y, d, d); //paints rectangle on screen
//x , y, width, height
}
As for scaling an image, you should look at Graphics#drawImage(Image img, int x, int y, int width, int height, ImageObserver observer), beware though, this will scaling the image to the absolute size, it won't keep the image ratio.
A better solution might be to use a double value of between 0 and 1 and multiple the various elements by this value to get the absolute values you want