I am having trouble with my Java project for school.
The plan was to make a simple game where you need to catch the ball and if you catch the ball you will get points.
At the moment I have 2 problems:
I have no idea how I make the balls appear at a random width and make it stay at that width (cause random value is constantly changing ).
How can I make a statement that checks if the catcher caught the ball?
This is my current code:
import instruct.*;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import javax.imageio.ImageIO;
import javax.swing.Timer;
public class opdracht extends WindowPanel implements MouseMotionListener {
List<comet> comets;
Image afb1;
Image afb2;
Image comet;
int xmuis;
int score;
int random;
int h;
int plaats;
static int randomNum;
private static final int D_W = 700;
private static final int X_INC = 10;
public opdracht() throws IOException {
score = 0;
h = -100;
afb1 = ImageIO.read(new File("afb/space.jpg"));
afb2 = ImageIO.read(new File("afb/pipe.png"));
BufferedImage cometbuf = ImageIO.read(new File("afb/comet.png"));
File output = new File("comet.png");
ImageIO.write(cometbuf, "png", output);
comet = ImageIO.read(new File("comet.png"));
addMouseMotionListener(this);
try {
drawcomet();
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
plaats = randomNum;
comets = new LinkedList<>();
Timer timer = new Timer(40, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
Iterator<comet> it = comets.iterator();
while (it.hasNext()) {
comet ball = it.next();
if (ball.h > D_W) {
it.remove();
System.out.println(comets.size());
} else {
ball.h += X_INC;
repaint();
}
}
}
});
timer.start();
}
public void paintComponent(Graphics g) {
g.drawImage(afb1, 0, 0, 1200, 800, this);
g.setColor(Color.yellow);
g.setFont(new Font("TimesRoman", Font.PLAIN, 30));
g.drawString("score = " + score, 1020, 30);
for (comet ball : comets) {
ball.drawcomet(g);
}
g.drawImage(afb2, xmuis, 730, 70, 75, this);
}
public static void randInt(int min, int max) {
// NOTE: Usually this should be a field rather than a method
// variable so that it is not re-seeded every call.
Random rand = new Random();
// nextInt is normally exclusive of the top value,
// so add 1 to make it inclusive
randomNum = rand.nextInt((max - min) + 1) + min;
System.out.print(randomNum);
}
public void drawcomet() throws InterruptedException {
ScheduledExecutorService exec = Executors.newSingleThreadScheduledExecutor();
exec.scheduleAtFixedRate(new Runnable() {
#Override
public void run() {
comets.add(new comet(comet));
}
}, 0, 2, TimeUnit.SECONDS);
}
public class comet {
protected int h;
Image comet;
public comet(Image image) {
comet = image;
}
public void drawcomet(Graphics g) {
g.drawImage(comet, plaats, h, 75, 50, null);
}
}
public void mouseMoved(MouseEvent e) {
xmuis = e.getX();
repaint();
}
public void mouseDragged(MouseEvent e) {
// do something
}
public static void main(String[] a) throws IOException {
new opdracht().createGUI();
}
}
package instruct;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class WindowPanel extends JPanel {
JFrame frame;
public WindowPanel() {
this.setPreferredSize(new Dimension(1200, 800));
this.setFocusable(true);
this.requestFocusInWindow();
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
// System.out.println( "class: "+ getClass().getName() );
frame.setTitle("Space Game");
}
protected void createAndShowGUI() {
frame = new JFrame();
frame.setSize(1200, 800);
frame.setLocation(300, 100);
frame.setResizable(false);
frame.add(this);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
BufferedImage cursorImg = new BufferedImage(16, 16, BufferedImage.TYPE_INT_ARGB);
// Create a new blank cursor.
Cursor blankCursor =
Toolkit.getDefaultToolkit().createCustomCursor(cursorImg, new Point(0, 0),
"blank cursor");
// Set the blank cursor to the JFrame.
frame.getContentPane().setCursor(blankCursor);
}
public void createGUI() {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
public JFrame getFrame() {
return frame;
}
}
First question: "I have no idea how i make the ball's appear at a random width."
I assume you want to give the ball (= an instance of the comet class) a random x position (= the plaats field)? You could make the following changes (which make the randomNum field no longer required, this could now be a local variable):
//plaats = randomNum;
plaats = randInt(0, 1200);
// more code...
//public static void randInt(int min, int max) {
public static int randInt(int min, int max) {
// more code...
return randomNum;
}
Second question: "And how can make a statement that checks if catcher cached ball."
To determine whether the ball is catched, you could compare xmuis to plaats when the y coordinate of the ball (the h field?) is equal to the top of the pipe (around 730).
Related
I'm trying to draw over a vlcj (java binding of the VLC library) panel so that I can play a video and draw over it. And I have encounter some issues. Here is the full base code:
Code-listing 1: AppOverlay.java
package app;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.HeadlessException;
import java.awt.Window;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;
import com.sun.jna.platform.WindowUtils;
#SuppressWarnings("serial")
public class AppOverlay extends Window implements Runnable {
private final boolean isRunning;
private final int fps;
private BufferedImage graphics;
private BufferedImage img;
private int x, y;
private boolean ltr;
public AppOverlay(Window owner) {
super(owner, WindowUtils.getAlphaCompatibleGraphicsConfiguration());
setBackground(new Color(0,0,0,0));
graphics = new BufferedImage(1280,800, BufferedImage.TYPE_INT_ARGB);
isRunning = true;
img = null;
ltr = true;
fps = 60;
x = 0;
y = 0;
}
#Override
public void run(){
while(isRunning){
try{
Thread.sleep(1000/fps);
} catch(InterruptedException e){
e.printStackTrace();
}
if(ltr) {
if(x < 1280) x++;
else ltr = false;
} else {
if(x < 0) ltr = true;
else x--;
}
repaint();
}
}
public void createAndShowGUI() {
setVisible(true);
Thread thread = new Thread(this);
thread.start();
String path = "Drive:\\path\\to\\image.png";
try {
img = ImageIO.read(new java.io.FileInputStream(path));
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public void paint(Graphics g) {
Graphics2D g2d = (Graphics2D)g;
Graphics2D gfx = graphics.createGraphics();
gfx.setColor(new Color(255,255,255,0));
gfx.clearRect(0, 0, 1280, 800);
if(img != null) gfx.drawImage(img, x, y, null);
gfx.dispose();
g2d.drawImage(graphics, 0, 0, null);
}
}
Code-listing 2: AppPlayer.java
package app;
import uk.co.caprica.vlcj.player.component.EmbeddedMediaPlayerComponent;
#SuppressWarnings("serial")
public class AppPlayer extends EmbeddedMediaPlayerComponent {
}
Code-listing 3: AppFrame.java
package app;
import java.awt.Dimension;
import javax.swing.JFrame;
#SuppressWarnings("serial")
public class AppFrame extends JFrame {
private AppPlayer appPlayer;
private AppOverlay overlay;
public AppFrame(){
super();
}
public void createAndShowGUI() {
appPlayer = new AppPlayer();
appPlayer.setPreferredSize(new Dimension(1280,800));
getContentPane().add(appPlayer);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setTitle("App");
setVisible(true);
pack();
overlay = new AppOverlay(this);
appPlayer.mediaPlayer().overlay().set(overlay);
appPlayer.mediaPlayer().overlay().enable(true);
overlay.createAndShowGUI();
}
}
Code-listing 4: Main.java
package main;
import javax.swing.SwingUtilities;
import app.AppFrame;
public class Main {
public static void main(String[] args) {
final AppFrame app = new AppFrame();
SwingUtilities.invokeLater( new Runnable() {
#Override
public void run() {
app.createAndShowGUI();
}
});
}
}
with that and the vlcj-4 library you should be able to test my code yourself. My issue is that the Overlay (AppOverlay class that extends the Window class) doesn't display or refresh the animation unless I deselect the window (I click on another window or on the desktop or the OS toolbar) so that the window (application) is inactive then select the window (the application) again. It will only load one frame and that's it. I have to deselect and reselect the window again for it to load another frame (this is only the case for the Overlay i.e. if I play a video in the AppPlayer class the video will be playing just fine.
What I want is to be able to draw some animated graphics on the overlay. I know that with the JPanel class there is the paintComponent() method but the Window class doesn't have that method (only the paint() and repaint() methods are available).
What should I do to fix this?
EDIT:
I tried adding a JPanel on which I draw instead of drawing directly on the AppOverlay
Code-listing 5: AppPanel.java
package app;
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JPanel;
public class AppPanel extends JPanel implements Runnable {
private int x, y;
private boolean ltr;
public AppPanel() {
x = 0;
y = 0;
ltr = true;
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(new Color(0,0,0,0));
g.clearRect(0, 0, 1280, 800);
g.setColor(Color.RED);
g.fillRect(x, y, 100, 100);
}
#Override
public void run() {
while(true){
try{
Thread.sleep(1000/60);
} catch(InterruptedException e){
e.printStackTrace();
}
if(ltr) {
if(x < 1280) x++;
else ltr = false;
} else {
if(x < 0) ltr = true;
else x--;
}
repaint();
}
}
}
then adding it to the AppOverlay.
Code-listing 6: AppOverlay.java with partial modification
public class AppOverlay extends Window implements Runnable {
//previous field declaration above ...
AppPanel panel;
AppPlayer player = null;
public AppOverlay(Window owner) {
//previous constructor instructions above...
panel = new AppPanel();
add(panel);
}
public void createAndShowGUI(AppPlayer player) {
setVisible(true);
/*
Thread thread = new Thread(this);
thread.start();
String path = "Drive:\\path\\to\\image.png";
try {
img = ImageIO.read(new java.io.FileInputStream(path));
} catch (IOException e) {
e.printStackTrace();
}
*/
Thread panelThread = new Thread(panel);
panelThread.start();
}
}
Doing this will display the graphics of the JPanel and animate them as needed.
If you know a way to make the JPanel background transparent (so that we can see through it) while still letting it display its graphics. That would solve the issue for sure.
I played around a bit with your example and came up with something working, but I wouldn't call it a nice solution.
The main issue seems to be that there is no way to tell the overlay to refresh (or I just have not found it). Just repainting the overlay does not update it on screen, so the workaround I used is to hide and show it again.
For the timeing of the update interval I used a javax.swing.Timer.
(In a real version you probably want to start and stop the timer via the MediaPlayerEventListener).
As a side effect the repaint method is called and the x coordinate is adjusted to move the image around the screen.
In the simplified example below (use your main to run it), I moved a red rectangle with the x coordinate instead of some unknown image.
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.HeadlessException;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.Timer;
import com.sun.jna.platform.WindowUtils;
import uk.co.caprica.vlcj.player.component.EmbeddedMediaPlayerComponent;
import uk.co.caprica.vlcj.player.embedded.OverlayApi;
public class AppFrame extends JFrame {
private static final long serialVersionUID = -1569823648323129877L;
public class Overlay extends Window {
private static final long serialVersionUID = 8337750467830040964L;
private int x, y;
private boolean ltr = true;
public Overlay(Window owner) throws HeadlessException {
super(owner, WindowUtils.getAlphaCompatibleGraphicsConfiguration());
setBackground(new Color(0,0,0,0));
}
#Override
public void paint(Graphics g) {
super.paint(g);
if (ltr) {
if (x < 1180)
x += 1;
else
ltr = false;
} else {
if (x < 0)
ltr = true;
else
x -= 1;
}
g.setColor(Color.RED);
g.fillRect(x, y, 100, 100);
String s = Integer.toString(x);
g.setColor(Color.WHITE);
g.drawChars(s.toCharArray(), 0, s.length(), x+10, y+50);
}
}
private EmbeddedMediaPlayerComponent appPlayer;
public void createAndShowGUI() {
appPlayer = new EmbeddedMediaPlayerComponent();
appPlayer.setPreferredSize(new Dimension(1280, 800));
getContentPane().add(appPlayer);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setTitle("App");
setVisible(true);
pack();
Overlay overlay = new Overlay(this);
OverlayApi api = appPlayer.mediaPlayer().overlay();
api.set(overlay);
api.enable(true);
//appPlayer.mediaPlayer().media().play(" ... ");
Timer timer = new Timer(0, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
api.enable(false);
api.enable(true);
}
});
timer.setRepeats(true);
timer.setDelay(200);
timer.start();
}
}
If that is an option for you, it might be far easier to use an animated gif instead. At least that is working on its own (no need for the Timer).
Update:
As you figured out using a JPanel seems to work better.
Just use setOpaque(false) to make it transparent.
Here an adjusted example.
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.HeadlessException;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import uk.co.caprica.vlcj.player.component.EmbeddedMediaPlayerComponent;
import uk.co.caprica.vlcj.player.embedded.OverlayApi;
public class AppFrame2 extends JFrame {
private static final long serialVersionUID = -1569823648323129877L;
public class OverlayPanel extends JPanel {
private static final long serialVersionUID = 8070414617530302145L;
private int x, y;
private boolean ltr = true;
public OverlayPanel() {
this.setOpaque(false);
}
#Override
public void paint(Graphics g) {
super.paint(g);
if (ltr) {
if (x < 1180)
x += 1;
else
ltr = false;
} else {
if (x < 0)
ltr = true;
else
x -= 1;
}
g.setColor(Color.RED);
g.fillRect(x, y, 100, 100);
String s = Integer.toString(x);
g.setColor(Color.WHITE);
g.drawChars(s.toCharArray(), 0, s.length(), x+10, y+50);
}
}
public class Overlay extends Window {
private static final long serialVersionUID = 8337750467830040964L;
OverlayPanel panel;
public Overlay(Window owner) throws HeadlessException {
super(owner);
setBackground(new Color(0,0,0,0));
panel = new OverlayPanel();
this.add(panel);
}
}
private EmbeddedMediaPlayerComponent appPlayer;
public void createAndShowGUI() {
appPlayer = new EmbeddedMediaPlayerComponent();
appPlayer.setPreferredSize(new Dimension(1280, 800));
getContentPane().add(appPlayer);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setTitle("App");
setVisible(true);
pack();
Overlay overlay = new Overlay(this);
OverlayApi api = appPlayer.mediaPlayer().overlay();
api.set(overlay);
api.enable(true);
//appPlayer.mediaPlayer().media().play(" ... ");
Timer timer = new Timer(0, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
overlay.panel.repaint();
}
});
timer.setRepeats(true);
timer.setDelay(17);
timer.start();
}
}
You have already done the bulk of the work. Simply repaint the frame every time you draw over it by calling app.repaint();
You can use the following methods from JComponent: ( http://download.oracle.com/javase/6/docs/api/javax/swing/JComponent.html )
void repaint(long tm, int x, int y, int width, int height)
//**Adds the specified region to the dirty region list if the component is showing.*//
void repaint(Rectangle r)
/**Adds the specified region to the dirty region list if the component is showing.*//
You can call those before redraw()
The Program use a rectangle in which a Ball can be caught from a JLabel with an Image.
The problem is in the Timer class, in which a counter counts, the time. While it counts the time is shown on a JLabel. But the Image that should catch the Ball, jumps every time to the start position, creating a tremble.
I tried to remove the JLabel and use instead System.out.println(), and it worked as well.
Perhaps the Swing Timer doesn't like calls for JLabel, what could be the cause?
SimpleDateFormat df = new SimpleDateFormat("mm:ss:SSS");
timeL.setText("Time :" + df.format(duration - clockTime));
//System.out.println("Time :" + df.format(duration - clockTime));
The Code was modified a bit, it works as expected, I hope it's correct.
Now the Image may be moved around independently of the Ball's Speed, and the Image stays at the moved position.
To add the Picture, add in the Project Folder a new Folder, named "resources". I tested it with Netbeans 8.2 .
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class ImageMoveTest implements ActionListener {
JPanel panel;
Image rimg;
Thread t;
int x;
int y;
int v;
int z;
int n;
public static void main(String[] args) throws InterruptedException, IOException {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
try {
new ImageMoveTest().startApp();
} catch (InterruptedException ex) {
Logger.getLogger(ImageMoveTest.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(ImageMoveTest.class.getName()).log(Level.SEVERE, null, ex);
}
}
});
}
public void startApp() throws InterruptedException, IOException {
panel = new DrawPanel();
InputStream inStream = this.getClass().getClassLoader().getResourceAsStream("i6.jpeg");
BufferedImage img = ImageIO.read(inStream);
rimg = img.getScaledInstance(150, 150, Image.SCALE_SMOOTH);
MoveMouse mm = new MoveMouse();
panel.addMouseMotionListener((MouseMotionListener) mm);
JFrame f = new JFrame();
f.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE);
f.getContentPane().add(panel).setBackground(Color.white);
f.setSize(750, 750);
f.setResizable(false);
f.setVisible(true);
f.setLocationRelativeTo(null);
MathC mc = new MathC();
t = new Thread(mc);
t.start();
}
class MoveMouse extends JPanel implements MouseMotionListener {
#Override
public void mouseDragged(MouseEvent e) {
v=e.getX();
z=e.getY();
this.repaint();
}
#Override
public void mouseMoved(MouseEvent e) {
}
}
class MathC implements Runnable {
#Override
public void run() {
while(true) {
// x,y here
x = (int) (Math.random() * panel.getWidth());
y = (int) (Math.random() * panel.getHeight());
panel.repaint();
try {
t.sleep(700);
} catch (InterruptedException ex) {
Logger.getLogger(ImageMoveTest.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
#Override
public void actionPerformed(ActionEvent e) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
class DrawPanel extends JPanel {
public void update(Graphics g) {
super.paintChildren(g);
}
public void paintChildren( Graphics g) {
super.paintChildren(g);
drawIt(g);
// repaint the backround to see the single circle moving
// draw the Ball
g.setColor(Color.red);
g.fillOval(x, y, 35, 35);
g.drawOval(x, y, 35, 35);
this.repaint();
}
public void drawIt(Graphics g) {
super.paintChildren(g);
// draw Rectangle
g.drawRect(0,0,this.getWidth(),this.getHeight());
// draw the Image
g.drawImage(rimg, v, z, this);
this.repaint();
}
}
}
I'm new to Java Programming. Recently I'm developing a mini game with JSWing. However, after coding for awhile the in-game FPS dropped terribly. When I tracked it on Task Manager I had result like this:
Can someone tell me what's wrong? I only used loops, JLabel with icons, Paint Graphics methods, mouseMotionEvent in my code.
Here is the code in the main game
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;
public class Game extends JPanel {
int numb = 2;
int pts = 5;
Kitty[] Kitties = new Kitty[4];
public Game() {
for (int i = 0; i < Kitties.length; i++)
Kitties[i] = new Kitty();
}
#Override
public void paint(Graphics graphics) {
BufferedImage img = null;
try {
img = ImageIO.read(getClass().getResourceAsStream("city.jpg"));
} catch (IOException e) {
System.out.println("java io");
}
graphics.drawImage(img, 0, 0, null);
//paints square objects to the screen
for (int i = 0; i < numb;i++) {
Kitties[i].paint(graphics);
}
}
public void update(TheJPanel frame) {
if (frame.a >= 0 && frame.a < 500) numb = 2;
if (frame.a>= 500) numb = 3;
for (int i = 0; i< numb; i++) {
int disty = 500 - Kitties[i].squareYLocation;
int distx = Kitties[i].squareXLocation - frame.x;
if ( Kitties[i].squareYLocation < 600 && disty <= 5 && disty >= -80 && distx < 260 && distx > -100){
frame.a +=pts;
if (Kitties[i].kittype == 6) frame.a += pts;
if (frame.a >= 500) {
Kitties[i].fallSpeed = Kitties[i].FallSpeedlvl2();
pts = 10;
}
Kitties[i].squareYLocation = -200;
Kitties[i].generateKittype();
Kitties[i].generateRandomXLocation();
Kitties[i].generateRandomFallSpeed();
frame.point.setText("Point:" + String.valueOf(frame.a));
frame.lives.setText("Lives:" + String.valueOf(frame.count));
}
if(Kitties[i].squareYLocation > 610){
frame.count--;
Kitties[i].generateKittype();
Kitties[i].generateRandomXLocation();
Kitties[i].generateRandomFallSpeed();
Kitties[i].squareYLocation = -200;
}
if (Kitties[i].squareYLocation >=605) frame.catFall(Kitties[i].squareXLocation);
if(Kitties[i].squareYLocation <= 610){
Kitties[i].squareYLocation += Kitties[i].fallSpeed;
}
}
}
public static void main(String[] args) throws InterruptedException {
Game game = new Game();
TheJPanel frame = new TheJPanel();
frame.add(game);
frame.setVisible(true);
frame.setSize(1000, 1000);
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setTitle("Saving kitties");
frame.setResizable(false);
frame.setLocationRelativeTo(null);
while (frame.count>0) {
game.update(frame);
game.repaint();
Thread.sleep(4);
}
if (frame.count == 0) {
JOptionPane.showMessageDialog(null, "You lost!", "Game over!", JOptionPane.ERROR_MESSAGE);
game.setVisible(false);
frame.getContentPane().removeAll();
frame.getContentPane().repaint();
frame.bask.setVisible(false);
frame.background.setVisible(false);
}
}
}
Here is the code for the main Jframe
package game;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Timer;
/**
*
* #author Imba Store
*/
public class TheJPanel extends JFrame implements MouseMotionListener {
protected int x;
protected int a = 0;
protected int count = 20;
protected JLabel bask = new JLabel();
protected JLabel background = new JLabel();
protected JLabel point = new JLabel();
protected JLabel lives = new JLabel();
Timer fall;
protected int time =0;
public TheJPanel() {
this.addMouseMotionListener(this);
InitContent();
}
protected void InitContent() {
Icon img = new ImageIcon(getClass().getResource("basket.png"));
bask.setIcon(img);
Icon themes = new ImageIcon(getClass().getResource("city2.png"));
background.setIcon(themes);
background.setBounds(0, 699, 1000, 300);
point.setFont(new java.awt.Font("Trebuchet MS", 1, 35));
point.setText("Point:" + String.valueOf(a));
point.setBounds(20,908,240,50);
point.setForeground(Color.white);
lives.setBounds(800, 908,200,50);
lives.setFont(new java.awt.Font("Trebuchet MS", 1, 35));
lives.setForeground(Color.white);
lives.setText("Point:" + String.valueOf(count));
point.setOpaque(false);
add(point);
add(lives);
add(bask);
add(background);
bask.setSize(400,148);
}
#Override
public void mouseMoved (MouseEvent me)
{
x = me.getX();
background.setBounds(0, 699, 1000, 300);
bask.setBounds(x, 700, 400, 148);
}
#Override
public void mouseDragged (MouseEvent me)
{
}
public void catFall(int getX){
Icon fell = new ImageIcon(getClass().getResource("kitty-fall.png"));
JLabel fellcat = new JLabel();
fellcat.setIcon(fell);
fellcat.setBounds(getX, 760, 220, 220);
add(fellcat);
add(background);
fall = new Timer(1500, new ActionListener(){
#Override
public void actionPerformed(ActionEvent ae) {
getContentPane().remove(fellcat);
}
});
fall.setRepeats(false);
fall.start();
}
}
And this is the class for the falling cats
package game;
/**
*
* #author Imba Store
*/
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Random;
import javax.imageio.ImageIO;
public final class Kitty extends JLabel {
protected int squareXLocation;
protected int squareYLocation = -200;
protected int fallSpeed = 1;
protected int kittype;
Random rand = new Random();
public int generateRandomXLocation(){
return squareXLocation = rand.nextInt(800);
}
public int generateRandomFallSpeed(){
return fallSpeed = rand.ints(3, 4).findFirst().getAsInt();
}
public int FallSpeedlvl2() {
return fallSpeed = rand.ints(3,7).findFirst().getAsInt();
}
public int generateKittype() {
return kittype = rand.ints(1,8).findFirst().getAsInt();
}
#Override
public void paint(Graphics g) {
BufferedImage img = null;
BufferedImage thugcat = null;
try {
img = ImageIO.read(getClass().getResourceAsStream("kitty.png"));
thugcat = ImageIO.read(getClass().getResourceAsStream("thug-kitty.png"));
} catch (IOException e) {
System.out.println("Java IO");
}
if (kittype == 6) {
g.drawImage(thugcat, squareXLocation, squareYLocation, null);
}
else g.drawImage(img, squareXLocation,squareYLocation,null);
}
public Kitty(){
generateRandomXLocation();
generateRandomFallSpeed();
generateKittype();
}
public void paint(Graphics graphics) {
BufferedImage img = null;
try {
img = ImageIO.read(getClass().getResourceAsStream("city.jpg"));
Custom painting is done by overriding paintComponent(...) not paint(). The first statement should then be super.paintComponent().
A painting method is for painting only. Don't do I/O in the painting method. This will cause the image to be read every time you repaint the panel.
Thread.sleep(4);
Sleeping for 4ms is not enough. That will attempt to repaint 250 times a second which is too often. There is no need for the frame rate to be that fast.
Kitty[] Kitties = new Kitty[4];
Variable names should not start with an upper case character. Most of your names are correct. Be consistent!
point.setBounds(20,908,240,50);
Don't use setBounds(). Swing was designed to be used with layout managers. Set a layout manager for you background and then add the components.
public int FallSpeedlvl2() {
Methods should NOT start with an upper case character. Again, most are correct. Be Consistent!!!
I am having trouble generating multiple oval shapes when clicking the panel of the frame. What I want is that it will generate many oval shapes and those shapes will move downward. One of the requirement is to use two multi threading. However in my case, the program I created is that, it will only generate one oval shape and the position is randomly changing. Can anyone please help me one this.
package ovalrandomcolors;
import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.util.List;
import java.awt.Shape;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Ellipse2D;
import java.util.ArrayList;
import java.util.Collections;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class OvalRandomColors extends JPanel{
private int ovalX = 50;
private int ovalY =50;
private int ovalPositionX = 250;
private int ovalPositionY = 250;
private Color color = Color.YELLOW;
public OvalRandomColors(){
setBackground(Color.DARK_GRAY);
}
#Override
public void paintComponent(Graphics g){
super.paintComponent(g);
g.setColor(color);
g.fillOval(ovalPositionX, ovalPositionY, ovalX, ovalY);
g.setColor(color);
g.fillOval(ovalPositionX, ovalPositionY, ovalX, ovalY);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable(){
#Override
public void run() {
JFrame frame = new JFrame();
final OvalRandomColors oval = new OvalRandomColors();
oval.addMouseListener(new MouseAdapter(){
#Override
public void mouseClicked(MouseEvent e){
OvalWithThreading firstThread = new OvalWithThreading(oval);
OvalWithThreading secondThread = new OvalWithThreading(oval);
Thread first = new Thread(firstThread);
Thread second = new Thread(secondThread);
second.start();
first.start();
}
});
frame.add(oval);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(500,700);
frame.setVisible(true);
}
});
}
public void updateOval(){
int r = (int)(Math.random() * 255);
int g = (int) (Math.random() * 255);
int b = (int)(Math.random() * 255);
color = new Color(r,g,b);
ovalPositionX = (int)(Math.random() * 78);
ovalPositionY = (int) (Math.random() * 245);
animateOval();
repaint();
}
public void animateOval(){
// ovalPositionX += 30;
ovalPositionY += 30;
}
public static class OvalWithThreading implements Runnable{
private final OvalRandomColors ovalShape;
public OvalWithThreading(OvalRandomColors oS){
this.ovalShape = oS;
}
#Override
public void run() {
for(;;){
ovalShape.updateOval();
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
Logger.getLogger(OvalRandomColors.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
}
Let's start with, Swing is not Thread safe, so having another Thread which update the state of objects which the UI depends to render requires some serious considerations. Normally, I'd recommend using a Swing Timer or SwingWorker to accomplish this, but those aren't the "requirements"
In order to render multiple objects, you need some way to store them, so you can update their states and renderer them. The simplest solution is a List, you can see Collections Trail for more details.
Now, if you also need to manage color, you can take a look at how I managed the deltas for each shape and should give you one idea for doing that
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.locks.ReentrantLock;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private ReentrantLock shapesLock = new ReentrantLock();
private List<Ellipse2D> shapes;
public TestPane() {
shapes = new ArrayList<>(25);
addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
shapesLock.lock();
try {
shapes.add(new Ellipse2D.Double(e.getX() - 5, e.getY() - 5, 10, 10));
} finally {
shapesLock.unlock();
}
}
});
Thread t = new Thread(new Runnable() {
private Map<Shape, Double> deltas = new HashMap<>();
#Override
public void run() {
while (true) {
try {
shapesLock.lock();
try {
Rectangle containerBounds = getBounds();
containerBounds.setLocation(0, 0);
Iterator<Ellipse2D> it = shapes.iterator();
while (it.hasNext()) {
Ellipse2D shape = it.next();
Rectangle2D bounds = shape.getBounds2D();
double y = bounds.getY();
Double delta = deltas.get(shape);
if (delta == null) {
delta = 0d;
}
y += delta;
shape.setFrame(bounds.getX(), y, bounds.getWidth(), bounds.getHeight());
if (containerBounds.contains(shape.getBounds())) {
delta = Math.min(delta + 0.25, 6d);
deltas.put(shape, delta);
} else {
it.remove();
}
}
} finally {
shapesLock.unlock();
}
repaint();
Thread.sleep(40);
} catch (InterruptedException ex) {
}
}
}
});
t.setDaemon(false);
t.start();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
shapesLock.lock();
try {
for (Ellipse2D shape : shapes) {
g2d.fill(shape);
}
} finally {
shapesLock.unlock();
}
g2d.dispose();
}
}
}
I am trying to paint JFrame when music is played , these shapes are created on random no calculation and when a there is some music played there pops up a JFrame and these shapes are painted there, problem is that when i run this code there is no musical sound and shapes drawn but just a frame pops up and nothing else , Plase check this code and help me to correct it ..
public class MusicBeatsDrawing {
static JFrame frame;
DrawPanel dp =new DrawPanel();
public static void main(String[] args)
{
MusicBeatsDrawing mbd= new MusicBeatsDrawing();
mbd.go();
}
public void SetGui(){
frame= new JFrame("Simple frame ; ");
frame.setBounds(100, 100, 200, 200);
frame.setContentPane(dp);
frame.setVisible(true);
}
public void go()
{
SetGui();
try
{
Sequencer sequencer = MidiSystem.getSequencer();
sequencer.open();
Sequence seq= new Sequence(Sequence.PPQ, 4);
sequencer.addControllerEventListener(dp,new int [] {127});
Track track = seq.createTrack();
int r = 0;
for (int i = 0; i < 60 ; i+= 4) {
r = (int) Math.random()*50;
track.add(MakeEvent(144,1,r,100,i));
track.add(MakeEvent(176,1,127,0,i));
track.add(MakeEvent(128,1,r,100,i ));
}
sequencer.setSequence(seq);
sequencer.start();
}
catch(Exception e)
{e.printStackTrace(); }
}
public MidiEvent MakeEvent(int one , int two , int three , int four , int tick)
{
MidiEvent event= null;
try
{
ShortMessage sm= new ShortMessage();
sm.setMessage(one,two, three, four);
event= new MidiEvent(sm , tick );
} catch (InvalidMidiDataException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return event;
}
class DrawPanel extends JPanel implements ControllerEventListener
{
boolean msg= false ;
public void paintComponent(Graphics g)
{
if(msg){ Graphics2D g2d= (Graphics2D) g;
int red= (int) (Math.random()*255);
int green= (int) (Math.random()*255) ;
int blue= (int) (Math.random()*255);
g.setColor(new Color(red, green , blue));
int height= (int)Math.random()*255;
int width= (int)Math.random()*255;
int x= (int)Math.random()*255;
int y= (int)Math.random()*255;
g.fillRect(height, width, x, y);
msg = false;
}
}
#Override
public void controlChange(ShortMessage event) {
msg= true;
repaint();
}}
}
Swing GUI objects should be constructed and manipulated only on the event dispatch thread. With this change, your program works. A telltale symptom is that the program runs when you resize the frame, which causes the system to invoke repaint() repeatedly.
Addendum: Some additional issues merit attention,
Make setVisible() last.
The sequencer startup latency may be worth moving to the background.
Use named constants, e.g. ShortMessage.NOTE_ON, rather than magic numbers.
Instantiate Random for later use.
Follow Java naming conventions.
Revised SSCCE:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.util.Random;
import javax.sound.midi.ControllerEventListener;
import javax.sound.midi.InvalidMidiDataException;
import javax.sound.midi.MidiEvent;
import javax.sound.midi.MidiSystem;
import javax.sound.midi.MidiUnavailableException;
import javax.sound.midi.Sequence;
import javax.sound.midi.Sequencer;
import javax.sound.midi.ShortMessage;
import javax.sound.midi.Track;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
/**
* #see http://stackoverflow.com/a/17767350/230513
*/
public class MidiDrawing {
private static final Random R = new Random();
public static void main(String[] args) {
EventQueue.invokeLater(new MidiDrawing()::display);
}
public void display() {
JFrame frame = new JFrame("Midi Drawing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
DrawPanel dp = new DrawPanel();
frame.add(dp);
Sequencer sequencer = initSequencer(dp);
JPanel p = new JPanel(new FlowLayout(FlowLayout.RIGHT));
p.add(new JButton(new AbstractAction("Start") {
#Override
public void actionPerformed(ActionEvent e) {
sequencer.setTickPosition(0);
sequencer.start();
}
}));
frame.add(p, BorderLayout.SOUTH);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
private Sequencer initSequencer(DrawPanel dp) {
try {
Sequencer sequencer = MidiSystem.getSequencer();
Sequence seq = new Sequence(Sequence.PPQ, 3);
Track track = seq.createTrack();
int n = 60; // middle C
for (int i = 0; i < 3 * 12; i += 3) {
track.add(new MidiEvent(new ShortMessage(ShortMessage.CONTROL_CHANGE, 0, 0, n), i));
track.add(new MidiEvent(new ShortMessage(ShortMessage.NOTE_ON, 0, n, 127), i));
track.add(new MidiEvent(new ShortMessage(ShortMessage.NOTE_ON, 0, n + 3, 127), i));
track.add(new MidiEvent(new ShortMessage(ShortMessage.NOTE_OFF, 0, n, 127), i + 3));
track.add(new MidiEvent(new ShortMessage(ShortMessage.NOTE_OFF, 0, n + 3, 127), i + 3));
n++;
}
sequencer.open();
sequencer.setSequence(seq);
sequencer.addControllerEventListener(dp, new int[]{0});
return sequencer;
} catch (InvalidMidiDataException | MidiUnavailableException e) {
e.printStackTrace(System.err);
}
return null;
}
private static class DrawPanel extends JPanel implements ControllerEventListener {
private final Font font = this.getFont().deriveFont(24f);
private int data;
#Override
public void paintComponent(Graphics g) {
g.setColor(Color.getHSBColor(R.nextFloat(), 1, 1));
g.fillRect(0, 0, getWidth(), getHeight());
g.setFont(font);
g.setColor(Color.black);
g.drawString(String.valueOf(data), 8, g.getFontMetrics().getHeight());
}
#Override
public void controlChange(ShortMessage event) {
data = event.getData2();
repaint();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(256, 128);
}
}
}