Draw multiple moving graphics - java

I have already made this program able to draw an instance of a small ball bouncing around a screen using these two classes
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Ellipse2D;
import javax.swing.JPanel;
import javax.swing.Timer;
public class move extends JPanel implements ActionListener
{
Timer t = new Timer(7, this);
int x = 10, y = 10, velX = 7, velY = 7;
public void paintComponent(Graphics g, Graphics h)
{
super.paintComponent(h);
super.paintComponent(g);
System.out.println(g);
Graphics2D g2 = (Graphics2D) g;
Ellipse2D circle = new Ellipse2D.Double(x, y, 40, 40);
g2.fill(circle);
t.start();
}
public void actionPerformed(ActionEvent e) {
if(x<0 || x > getWidth())
{
velX = -velX;
}
if(y < 0 || y > getHeight())
{
velY = -velY;
}
x += velX;
y += velY;
repaint();
}
}
This class just simply draws the ball and provides the logic for the timer and such
import java.awt.Color;
import javax.swing.JFrame;
public class Gui {
public static void main(String[] args)
{
move s = new move();
JFrame f = new JFrame("move");
f.add(s);
f.setVisible(true);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(1000, 1000);
f.setTitle("Moving Circle");
f.setBackground(Color.GREEN);
}
}
This next class just puts it all in a JFrame, very simple stuff I know but I'm just trying to draw multiple instances within the same JFrame. I'm just trying to experiment with my knowledge of code, some sample of code to implement would be great.
How to draw multiple moving graphics?

This code could have a class Ball class that knows its position & size and how to draw itself to a Graphics.
As each ball is created, they are added to a list. At time of paint, iterate the list and paint each Ball.

Related

Bouncing ball. Ball is laggy. repaint() too slow

I try to do my first graphical program in java - bouncing ball. Actually it should be brick breaker according to tutorial. But for now it is bouncing ball. The ball should bounce from the frames of the window. So far I programmed it. The issue is that the ball is laggy, it does not move fluently at all. If I press and hold a keyboard key the ball moves fluently. Firstly I though it might by problem with my graphical card and linux system(AMD Ryzen 5 integrated graphic, Ubuntu 20.04)? But why it works correctly when I press and hold a keyboard button. Any ideas?
package com.company;
import javax.swing.JFrame;
public class Main {
public static void main(String[] args) {
JFrame obj=new JFrame();
Gameplay gamePlay = new Gameplay();
obj.setBounds(10,10,700,600);
obj.setTitle("Breakout Ball");
obj.setResizable(false);
obj.setVisible(true);
obj.setDefaultCloseOperation(obj.EXIT_ON_CLOSE);
obj.add(gamePlay);
}
}
package com.company;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class Gameplay extends JPanel implements ActionListener {
private boolean play=false;
private int totalBrics=21;
private Timer timer;
private int delay=8;
private int playerX=310;
private int ballposX=120;
private int ballposY=350;
private int ballXdir=-1;
private int ballYdir=-2;
public Gameplay(){
setFocusable(true);
setFocusTraversalKeysEnabled(false);
timer=new Timer(delay, this);
timer.start();
}
public void paint (Graphics g){
//background
g.setColor(Color.black);
g.fillRect(1,1,692,592);
//borders
g.setColor(Color.yellow);
g.fillRect(0,0,3,592);
g.fillRect(0,0,692,3);
g.fillRect(691,0,3,592);
// paddle
g.setColor(Color.green);
g.fillRect(playerX, 550,100,8);
//ball
g.setColor(Color.yellow);
g.fillOval(ballposX, ballposY,20,20);
//g.dispose();
}
public void actionPerformed(ActionEvent f) {
//timer.start();
play=true;
if (play){
if(new Rectangle(ballposX, ballposY, 20,20).intersects(new Rectangle(playerX,550,100,8))){
ballYdir=-ballYdir;
}
ballposX+=ballXdir;
ballposY+=ballYdir;
if(ballposX<0){
ballXdir=-ballXdir;
}
if(ballposY<0){
ballYdir=-ballYdir;
}
if(ballposY>570){
ballYdir=-ballYdir;
}
if(ballposX>670){
ballXdir=-ballXdir;
}
}
repaint();
}
}
I ran your exact code and it worked fine. There was no real lag or some better behavior while pressing a key. Hence there is a problem with you hardware maybe?
I did not notice any lag but you were doing several things incorrectly which I have fixed.
You should be overriding paintComponent and not paint for a JPanel
You should invoke super.paintComponent as the first statement. When you do that it will then set the background color for you and clear the screen each time. It also does some other processing in the parent paintComponent method.
I also set the size for the JPanel which made the yellow borders appear (although a little off on the right). And the paddle was raised off the bottom edge a tad.
I then packed the frame and centered it on the screen.
I used RenderingHints via Graphics2D to smooth out the edges of the graphics.
All in all you did a pretty nice job. I am not certain why you would be having a delay. You might want to try increasing your x and y increment values and slowing down the timer. But it worked fine for me as is.
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
class Gameplay extends JPanel implements ActionListener {
private boolean play = false;
private int totalBrics = 21;
private Timer timer;
private int delay = 8;
private int playerX = 310;
private int ballposX = 120;
private int ballposY = 350;
private int ballXdir = -1;
private int ballYdir = -2;
public static void main(String[] args) {
JFrame obj = new JFrame();
Gameplay gamePlay = new Gameplay();
gamePlay.setPreferredSize(new Dimension(700,600));
obj.setTitle("Breakout Ball");
obj.setResizable(false);
obj.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
obj.add(gamePlay);
gamePlay.setBackground(Color.black);
obj.pack();
// center on screen
obj.setLocationRelativeTo(null);
obj.setVisible(true);
}
public Gameplay() {
setFocusable(true);
setFocusTraversalKeysEnabled(false);
timer = new Timer(delay, this);
timer.start();
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
// borders
g2d.setColor(Color.yellow);
g2d.fillRect(0, 0, 3, 592);
g2d.fillRect(0, 0, 692, 3);
g2d.fillRect(691, 0, 3, 592);
// paddle
g2d.setColor(Color.green);
g2d.fillRect(playerX, 550, 100, 8);
// ball
g2d.setColor(Color.yellow);
g2d.fillOval(ballposX, ballposY, 20, 20);
g2d.dispose();
}
public void actionPerformed(ActionEvent f) {
// timer.start();
play = true;
if (play) {
if (new Rectangle(ballposX, ballposY, 20, 20).intersects(
new Rectangle(playerX, 550, 100, 8))) {
ballYdir = -ballYdir;
}
ballposX += ballXdir;
ballposY += ballYdir;
if (ballposX < 0) {
ballXdir = -ballXdir;
}
if (ballposY < 0) {
ballYdir = -ballYdir;
}
if (ballposY > 570) {
ballYdir = -ballYdir;
}
if (ballposX > 670) {
ballXdir = -ballXdir;
}
}
repaint();
}
}
Problem solved,
just found answer here:Java window lagging on Ubuntu but not windows when code isn't lagging
Problem is with Linux's graphics scheduling, adding
Toolkit.getDefaultToolkit().sync();
after
repaint();
caused, that everything works fluently now.

How to rotate something upwards based on mouse position in Java

Good afternoon guys, I'm trying to rotate an polygon based on my mouse position, but I can't figure out how to rotate the polygon upwards based on my mouse y. I'm using MouseMotionListener. I've tried to do this until now:
public void mouseMoved(MouseEvent m){
int yantes= m.getY();
while (true){
int y = m.getY();
repaint();
if (y - yantes > 0){
rotation++;
if (rotation > 360) rotation = 0;
repaint();
break;
} else {
rotation--;
if (rotation < 0) rotation = 359;
repaint();
break;
}
}
}
The yantes variable tries to calculate the y before the move, and y the y in after the movement.
In your comment, you wrote:
I am using a book that used Java 6
Are you referring to the book Beginning Java SE 6 Game Programming, Third Edition ?
A java applet is a Container and so is a JPanel, so you can achieve the same results by extending class JPanel rather than extending Applet. That means you can write a regular java application without the need for HTML or a Web browser.
Instead of overriding method paint() in Applet, you need to override method paintComponent() in class JPanel.
The below code demonstrates rotating a square by moving the mouse. It rotates the square around the center point of the square. When you place the mouse inside the JPanel and move it to the left, the square rotates anti-clockwise. When you move the mouse to the right, the square rotates clockwise. If you move the mouse up and down, i.e. parallel to the y-axis, the square does not rotate.
import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.WindowConstants;
public class Rotating extends JPanel implements Runnable, MouseMotionListener {
private int theta;
private int lastX = Integer.MIN_VALUE;
private BasicStroke stroke;
private JFrame frame;
/**
* Creates and returns instance of this class.
*/
public Rotating() {
stroke = new BasicStroke(2.0f);
addMouseMotionListener(this);
setPreferredSize(new Dimension(600, 600));
}
/* Start 'MouseMotionListener' interface methods. */
#Override // javax.swing.event.MouseInputListener
public void mouseDragged(MouseEvent mousEvnt) {
// Do nothing.
}
#Override // javax.swing.event.MouseInputListener
public void mouseMoved(MouseEvent mousEvnt) {
int newX = mousEvnt.getX();
if (lastX == Integer.MIN_VALUE) {
lastX = newX;
}
if (newX < lastX) {
theta--;
if (theta < 0) {
theta = 359;
}
}
else if (newX > lastX) {
theta++;
if (theta > 360) {
theta = 0;
}
}
lastX = newX;
repaint();
}
/* End 'MouseMotionListener' interface methods. */
/* Start 'Runnable' interface methods. */
#Override
public void run() {
showGui();
}
/* End 'Runnable' interface methods. */
#Override // javax.swing.JComponent
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (g instanceof Graphics2D) {
Graphics2D g2d = (Graphics2D) g;
g2d.rotate(Math.toRadians(theta), 300, 300);
g2d.setStroke(stroke);
g2d.drawRect(200, 200, 200, 200);
}
}
private void showGui() {
frame = new JFrame("Rotating");
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.add(this, BorderLayout.CENTER);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Rotating());
}
}
Note that when overriding method paintComponent() you nearly always need to first call method paintComponent() in the super class.

How to draw a taper profile using java awt.Graphics2D

So I'm trying to draw a curve that has a taper profile like this : y=
Since I'm using awt.Graphics2D, I only have the ability to draw shapes.
One way to draw curves is to draw curves is use use BĀ“ezier curves. Is there a way convert this or a awt trick I'm not familiar with ?
One option to draw a curve is point by point :
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Curve extends JPanel {
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(Color.RED);
for (int x = 1; x <= 100; x++) {
int y = getY(x);
//2g does not support drawing a point so you draw a line
g2d.drawLine(x, y, x, y);
}
}
/**
*#param x
*#return
*/
private int getY(int x) {
//change to the function you want
return 50+ (100/(1+ (3* x)));
}
public static void main(String[] args) {
Curve points = new Curve();
JFrame frame = new JFrame("Curve");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(points);
frame.setSize(350, 300);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}

How to repaint another image from the ending coordinates of first image?

I am just trying to make a simple aquarium type application. The fish moves from left to right. (the mouth of fish is faced towards right). When it reaches the end of the JFrame, it returns back. What I wanted is that it must face towards left when it returns.(goes back) So, I have decided to paint with a new image when the fish reaches at the specific coordinate. How to do it? Please.
image 1 = fish of image whose mouth is right faced
image 2 = fish of image whose mouth is left faced
package aquarium;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.util.Random;
import javax.swing.Timer;
public class Aquarium extends JPanel implements ActionListener{
Random r = new Random();
Timer t = new Timer(5, this);
int x = 0, y= 30;
int velX = 1 ,velY =1;
ImageIcon image = new ImageIcon(getClass().getResource("../res/aquarium.gif"));
ImageIcon image1 = new ImageIcon(getClass().getResource("../res/smallFish.gif"));
ImageIcon image2 = new ImageIcon(getClass().getResource("../res/new.gif"));
int numberFish = 12;
Aquarium() {
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
image.paintIcon(this, g, 0, 0);
image1.paintIcon(this, g, x, y);
t.start();
}
#Override
public void actionPerformed(ActionEvent e){
Graphics g = null;
if(x<0 || x>465) {
velX = -velX;
}
x += velX;
repaint();
}
public static void main(String[] args) {
Aquarium a = new Aquarium();
JFrame f = new JFrame();
f.setTitle("The Aquarium");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
f.setResizable(false);
f.setBounds(500,200,500,300); //left,top,width,height
f.add(a);
}
}
Use velX to check which fish it is and draw it:
public void paintComponent(Graphics g){
super.paintComponent(g);
image.paintIcon(this, g, 0, 0);
if (velX > 0) { // moving right
image1.paintIcon(this, g, x, y);
} else { // moving left
image2.paintIcon(this, g, x, y);
}
t.start();
}

JPanel - Graphics stop while mouse is being moved?

I'm working on a little java project wherein I need to draw a small handful of shapes to the screen. I also need to capture mouse events for utility functions. Right now, I have a program that captures a click, and sends out a little ripple from that position. Whenever the mouse is moved, however, the paintComponent(Graphics g) method just stops entirely. I thought it was a buffering issue, so I implemented one, and it just slowed even more at normal rendering. Another strange thing: When the mouse is being held down, the paintComponent method doesn't care about the mouse movement anymore. It resumes as normal.
EDIT: I should also mention that the mouse events are triggered by a class that implements MouseListener. They are calling correctly. To get the mouse position, I use this:
public Point getMouse() {
Point mousePos = MouseInfo.getPointerInfo().getLocation();
SwingUtilities.convertPointFromScreen(mousePos, screen);
return mousePos;
}
package com.noneofyebidmness;
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.RenderingHints;
import java.util.ArrayList;
import javax.swing.JPanel;
import com.noneofyebidmness.Organism;
#SuppressWarnings("serial")
public class Screen extends JPanel {
private int diameter = 10;
private ArrayList<Point> ripplePositions;
private ArrayList<Point> rippleDiameters;
public Screen() {
ripplePositions = new ArrayList<Point>();
rippleDiameters = new ArrayList<Point>();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(Reference.SCREEN_WIDTH_DEFAULT, Reference.SCREEN_HEIGHT_DEFAULT);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
System.out.println("Painting");
Graphics2D g2d = (Graphics2D) g.create();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
for(Organism o : Wrapper.getInstance().getOrganisms()) {
o.draw(g2d);
}
Point mouse = Wrapper.getInstance().getMouse();
Utility.background(Utility.color(0, 150, 250), g2d, this);
g2d.setColor(Utility.color(255));
g2d.fillOval((int)mouse.getX() - diameter / 2, (int)mouse.getY() - diameter / 2, diameter, diameter);
g2d.setColor(Color.BLACK);
g2d.drawString(Wrapper.FPS_PERIODIC + "", 10, 20);
for(int i = 0; i < ripplePositions.size(); i++) {
int w = rippleDiameters.get(i).x;
g2d.setColor(Utility.color(255, Math.min(220-w, 255)));
g2d.setStroke(new BasicStroke(10));
g2d.drawOval(ripplePositions.get(i).x - w / 2, ripplePositions.get(i).y - w / 2, rippleDiameters.get(i).x, rippleDiameters.get(i).x);
if(w < 255) {
rippleDiameters.get(i).x += rippleDiameters.get(i).y;
if(rippleDiameters.get(i).y > 0)
rippleDiameters.get(i).y -= 0.01;
}
if(220-w == 0) {
ripplePositions.remove(i);
rippleDiameters.remove(i);
}
}
g2d.dispose();
}
public void addRipple() {
ripplePositions.add(Wrapper.getInstance().getMouse());
rippleDiameters.add(new Point(diameter, 20));
}
}
TL;DR:
When the mouse is moved over my JPanel, it stops calling paintComponent().
If the mouse is held down and moved, things operate as normal.
Any help is appreciated,
Carl Litchman

Categories