So here's where I am stuck... I got it to go to the end of the window horizontally, then go down, but I don't know how to make it go left after it reaches the bottom of the window and then go up when it reaches the left side of the screen.
Thanks,
import javax.swing.*;
import java.awt.*;
public class AnimatedImageApplet extends JApplet implements Runnable {
private static final long serialVersionUID = 1L;
private Thread t = null;
private Image image;
private int x = 0;
private int y = 0;
private static final int vx = 1;
private static final int vy= 1;
private boolean horizontal = true;
private boolean vertical = true;
public void init() {
image = getImage(getDocumentBase(), "face.png");
}
public void start() {
if (t == null) {
t = new Thread(this);
t.start();
}
}
public void paint(Graphics canvas) {
canvas.fillRect(0,0,getWidth(),getHeight());
synchronized (this) {
canvas.drawImage(image, x, y, this);
}
}
#Override
public void run() {
int direction = 1;
while (true) {
synchronized (this) {
x += vx * direction;
y += vy * (horizontal ? 0 : 1);
if (x + image.getWidth(this) == getWidth()) {
horizontal = false;
direction = 0;
}
}
repaint();
try {
Thread.sleep(15);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
Conceptually, the idea is simple enough. When you reach one of your edges, you need to change the direction of your movement.
if x + image.width > width then go down
else if x < 0 then go up
else if y + image.height > height then go left
else if y < 0 then go right
for clock wise motion.
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class MoveTest {
public static void main(String[] args) {
new MoveTest();
}
public MoveTest() {
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 BufferedImage img;
private int xDelta = 2;
private int yDelta = 0;
private int x, y = 0;
public TestPane() {
try {
img = ImageIO.read(...);
} catch (IOException ex) {
ex.printStackTrace();
}
Timer timer = new Timer(15, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
x += xDelta;
y += yDelta;
if (x + img.getWidth() > getWidth()) {
x = getWidth() - img.getWidth();
xDelta = 0;
yDelta = 2;
} else if (x < 0) {
x = 0;
xDelta = 0;
yDelta = -2;
}
if (y + img.getHeight() > getHeight()) {
y = getHeight() - img.getHeight();
xDelta = -2;
yDelta = 0;
} else if (y < 0) {
y = 0;
xDelta = 2;
yDelta = 0;
}
repaint();
}
});
timer.start();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.drawImage(img, x, y, this);
g2d.dispose();
}
}
}
You should be careful of threads in Swing as Swing is not thread save. Have a look at Concurrency in Swing and How to use Swing Timers for more details
Related
I don't understand why after i get over the first half of a ball that when the ball I control hits the right half of a moving ball that it doesn't activate the collision code to kill the program.
I have it set to measure the distance between the ball that you control then the ball that is passing by. I am still confused why I can land on the second half of the ball without the program closing itself out.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import java.awt.event.ActionListener;
import java.awt.event.KeyListener;
import javax.swing.ImageIcon;
public class JumpingSprite extends JPanel implements KeyListener {
//public int yPos;
public static void main(String[] args) {
new JumpingSprite();
}
public JumpingSprite() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Mr.Baird");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
TestPane testPane = new TestPane();
frame.add(testPane);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
int getyPos(){
return yPos;
}
protected static final int SPRITE_HEIGHT = 60;
protected static final int SPRITE_WIDTH = 60;
private float vDelta;
private float rbDelta;
private float rbDegDelta;
public int yPos;
private float gDelta; // Gravity
private Timer engine;
private boolean bounce = false;
int ballx = 1000;
int bally = 500;
int ballw = 100;
int ballh = 100;
int ball2x = 1500;
int ball2y = 480;
int ball2w = 120;
int ball2h = 120;
int ball3x = 2500;
int ball3y = 0;
int ball3w = 600;
int ball3h = 600;
public TestPane() {
yPos = getPreferredSize().height - SPRITE_HEIGHT;
vDelta = 0;
gDelta = 3f;
rbDegDelta = 30f; //affects how many bounces mang
InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW);
ActionMap am = getActionMap();
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0), "jump");
am.put("jump", new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
if (yPos + SPRITE_HEIGHT == getHeight()) {
vDelta = -40 ;
rbDelta = vDelta;
bounce = true;
}
}
});
engine = new Timer(15, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
int height = getHeight();
if (height > 0) {
if (bounce) {
yPos += vDelta;
vDelta += gDelta;
// If the sprite is not on the ground
if (yPos + SPRITE_HEIGHT >= height) {
// put on le ground
yPos = height - SPRITE_HEIGHT;
if (rbDelta >= 0) {
// Stop bouncin
bounce = false;
} else {
// Add the re-bound degregation delta to the re-bound delta
rbDelta += rbDegDelta;
// Set the vDelta...
vDelta = rbDelta;
}
}
}
}
if (Math.sqrt((Math.pow((500 - (ballx)), 2)) + Math.pow((yPos - bally), 2)) <= (50)) {
System.exit(0);
}
if (Math.sqrt((Math.pow((500 - (ball2x)), 2)) + Math.pow((yPos - ball2y), 2)) <= (60)) {
System.exit(0);
}
if (Math.sqrt((Math.pow((500 - (ball3x)), 2)) + Math.pow((yPos - ball3y), 2)) <= (350)) {
System.exit(0);
}
ballx = ballx-8;
ball2x = ball2x-8;
ball3x = ball3x-8;
repaint();
}
});
engine.start();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(1000, 600);
}
#Override
protected void paintComponent(Graphics g) {
//addin all them pretty colors to le object
super.paintComponent(g);
//Graphics2D g2d = (Graphics2D) g.create();
g.setColor(Color.black);
g.fillRect(0,0,1000,1000);
int width = getWidth() - 1;
int xPos = (width - SPRITE_WIDTH) / 2;
g.setColor(Color.blue);
g.fillOval(xPos, yPos, SPRITE_WIDTH, SPRITE_HEIGHT);
//g.dispose();
g.setColor(Color.red);
g.fillOval(ballx, bally, ballw, ballh);
g.setColor(Color.green);
g.fillOval(ball2x, ball2y, ball2w, ball2h);
g.setColor(Color.pink);
g.fillOval(ball3x, ball3y, ball3w, ball3h);
}
}
#Override
public void keyPressed(KeyEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void keyReleased(KeyEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void keyTyped(KeyEvent arg0) {
// TODO Auto-generated method stub
}
}
The general solution to this problem is to calculate the (Euclidean) distance between the centers of both balls/circles, and determine if that length is less than their combined radii. The other way you could do this is to create java.awt.Areas from your Shapes, and use Area.intersect(Area) != null;
Alright, so my first class creates the Frame and also places a red rectangle in it which I can move. Now what i'm doing is, creating another class for a blue rectangle.
Now in my attempt i have created the second class and also extended the first class unto it; which doesn't seem to do the job.
Summery:
What do I need to do so they share the same frame? Is there a method for this?
SOLVED VERSION
My Code(First Class): EDITED
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
public class MyGame extends JPanel implements ActionListener, KeyListener {
Timer t = new Timer(5, this);
int x = 0, y = 0, velx =0, vely =0, g = 0;
private Color color;
public MyGame() {
t.start();
addKeyListener(this);
setFocusable(true);
setFocusTraversalKeysEnabled(false);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(color);
g.fillRect(x, y, 50, 30);
}
#Override
public void actionPerformed(ActionEvent e) {
if (x < 0) //stops us from going backwards past x = 0
{
velx = 0;
x = 0;
}
if (y < 0) //stops us from going to the sky
{
vely = 0;
y = 0;
}
if (y > 330) // stops us from going through the ground
{
vely = 0;
y = 330;
}
x += velx;
y += vely;
repaint();
}
#Override
public void keyPressed(KeyEvent e) {
int code = e.getKeyCode();
{
if (code == KeyEvent.VK_DOWN) {
vely = 1; // removing velx = 0 allows us to go vertically and horizontlly at the same time
}
if (code == KeyEvent.VK_UP) {
vely = -1; // same goes for here
}
if (code == KeyEvent.VK_LEFT) {
velx = -1;
}
{
if (code == KeyEvent.VK_RIGHT) {
velx = 1;
}
}
}
}
#Override
public void keyTyped(KeyEvent e) {
}
#Override
public void keyReleased(KeyEvent e) {
velx = 0;
vely = 0;
}
public static void main (String arge[]){
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new Incoming());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
(Second Class): EDITED
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
public class Incoming extends MyGame {
private Color color;
int x = 0, y = 0, velx = 0, vely = 0;
public Incoming() {
color = Color.BLUE;
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(color);
g.fillRect(x, y, 50, 30);
}
#Override
public void actionPerformed(ActionEvent e) {
super.actionPerformed(e);
if (x < 0) //stops us from going backwards past x = 0
{
velx = 0;
x = 0;
}
if (y < 0) //stops us from going to the sky
{
vely = 0;
y = 0;
}
if (y > 330) // stops us from going through the ground
{
vely = 0;
y = 330;
}
x += velx;
y += vely;
repaint();
}
#Override
public void keyPressed(KeyEvent e) {
super.keyPressed(e);
int code = e.getKeyCode();
{
if (code == KeyEvent.VK_S) {
vely = 1; // removing velx = 0 allows us to go vertically and horizontlly at the same time
}
if (code == KeyEvent.VK_NUMPAD8) {
vely = -1; // same goes for here
}
if (code == KeyEvent.VK_NUMPAD4) {
vely = 0;
velx = -1;
}
{
if (code == KeyEvent.VK_NUMPAD6) {
vely = 0;
velx = 1;
}
}
}
}
#Override
public void keyReleased(KeyEvent e) {
super.keyReleased(e);
velx = 0;
vely = 0;
}
}
Thank you
You could either take advantage of the color property support of the component or supply your own color property which could set and retrieved through the use of setters and getters
The following example simply uses the components existing foreground property...
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class GameExample {
public static void main(String[] args) {
new GameExample();
}
public GameExample() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
MyGame game = new MyGame();
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(game);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class MyGame extends JPanel implements ActionListener {
Timer t = new Timer(5, this);
int x = 0, y = 0, velx = 0, vely = 0, g = 0;
public MyGame() {
t.start();
setFocusTraversalKeysEnabled(false);
setForeground(Color.RED);
InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW);
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0, false), "up-pressed");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0, false), "down-pressed");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0, false), "left-pressed");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0, false), "right-pressed");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0, true), "up-released");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0, true), "down-released");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0, true), "left-released");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0, true), "right-released");
ActionMap am = getActionMap();
am.put("up-pressed", new YDelatAction(-1));
am.put("down-pressed", new YDelatAction(1));
am.put("left-pressed", new XDelatAction(-1));
am.put("right-pressed", new XDelatAction(1));
am.put("up-released", new YDelatAction(0));
am.put("down-released", new YDelatAction(0));
am.put("left-released", new XDelatAction(0));
am.put("right-released", new XDelatAction(0));
}
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(getForeground());
g.fillRect(x, y, 50, 30);
}
#Override
public void actionPerformed(ActionEvent e) {
if (x < 0) //stops us from going backwards past x = 0
{
velx = 0;
x = 0;
}
if (y < 0) //stops us from going to the sky
{
vely = 0;
y = 0;
}
if (y > 330) // stops us from going through the ground
{
vely = 0;
y = 330;
}
x += velx;
y += vely;
repaint();
}
public class XDelatAction extends AbstractAction {
private int value;
public XDelatAction(int value) {
this.value = value;
}
#Override
public void actionPerformed(ActionEvent e) {
vely = 0;
velx = value;
}
}
public class YDelatAction extends AbstractAction {
private int value;
public YDelatAction(int value) {
this.value = value;
}
#Override
public void actionPerformed(ActionEvent e) {
vely = value;
}
}
}
}
This would allow you to create a new instance that use a different color by doing...
MyGame game = new MyGame();
game.setForeground(Color.BLUE);
Or you could create a new subclass using something like...
public class MyBlueGame extends MyGame {
public MyBlueGame () {
setForeground(Color.BLUE);
}
}
Generally speaking, you should favour the key bindings API over KeyListener as it provides more control over the level of focus required to generate key events and generally produces more re-usable and configurable code (IMHO)
Updated
So, based on you example code...
Each class is going to need it's own color property, which independent of the other, otherwise the inheritance is going to get in the way (and the parent will want to use the value of the child)
You will also need to change the keyPressed and keyReleased methods for the child class so that the two rectangles can move independently of each other.
This is not my preferred solution. I would have a single game surface which was capable of rendering the state of the overall game (all the entities) and would provide a means by which the gaming elements could be added (and possibly removed) from the surface and some kind of controller that would be able to control the way in which those elements are updated...but that's just me...
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class GameTest {
public static void main(String[] args) {
new GameTest();
}
public GameTest() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new Incoming());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class MyGame extends JPanel implements ActionListener, KeyListener {
Timer t = new Timer(5, this);
int x = 0, y = 0, velx = 0, vely = 0, g = 0;
private Color color;
public MyGame() {
color = Color.RED;
t.start();
addKeyListener(this);
setFocusable(true);
setFocusTraversalKeysEnabled(false);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(color);
g.fillRect(x, y, 50, 30);
}
#Override
public void actionPerformed(ActionEvent e) {
if (x < 0) //stops us from going backwards past x = 0
{
velx = 0;
x = 0;
}
if (y < 0) //stops us from going to the sky
{
vely = 0;
y = 0;
}
if (y > 330) // stops us from going through the ground
{
vely = 0;
y = 330;
}
x += velx;
y += vely;
repaint();
}
#Override
public void keyPressed(KeyEvent e) {
int code = e.getKeyCode();
{
if (code == KeyEvent.VK_DOWN) {
vely = 1; // removing velx = 0 allows us to go vertically and horizontlly at the same time
}
if (code == KeyEvent.VK_UP) {
vely = -1; // same goes for here
}
if (code == KeyEvent.VK_LEFT) {
velx = -1;
}
{
if (code == KeyEvent.VK_RIGHT) {
velx = 1;
}
}
}
}
#Override
public void keyTyped(KeyEvent e) {
}
#Override
public void keyReleased(KeyEvent e) {
velx = 0;
vely = 0;
}
}
public class Incoming extends MyGame {
private Color color;
int x = 0, y = 0, velx = 0, vely = 0;
public Incoming() {
color = Color.BLUE;
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(color);
g.fillRect(x, y, 50, 30);
}
#Override
public void actionPerformed(ActionEvent e) {
super.actionPerformed(e);
if (x < 0) //stops us from going backwards past x = 0
{
velx = 0;
x = 0;
}
if (y < 0) //stops us from going to the sky
{
vely = 0;
y = 0;
}
if (y > 330) // stops us from going through the ground
{
vely = 0;
y = 330;
}
x += velx;
y += vely;
repaint();
}
#Override
public void keyPressed(KeyEvent e) {
super.keyPressed(e);
int code = e.getKeyCode();
{
if (code == KeyEvent.VK_NUMPAD2) {
vely = 1; // removing velx = 0 allows us to go vertically and horizontlly at the same time
}
if (code == KeyEvent.VK_NUMPAD8) {
vely = -1; // same goes for here
}
if (code == KeyEvent.VK_NUMPAD4) {
vely = 0;
velx = -1;
}
{
if (code == KeyEvent.VK_NUMPAD6) {
vely = 0;
velx = 1;
}
}
}
}
#Override
public void keyReleased(KeyEvent e) {
super.keyReleased(e);
velx = 0;
vely = 0;
}
}
}
i think all what you have to do is to set the colour as a parameter for your class MyGame , to add a field colour to your class.
private Color colour;
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Colour);
g.fillRect(x,y,70,40);
}
JFrame f = new JFrame();
MyGame s = new MyGame();
s.setCoulor(Color.RED) // s.setCoulor(Color.BLUE)
f.add(s);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(600,400);
f.setVisible(true);
A little rough with java but can someone tell me how I take a draw method from a list of objects, say there's more than 1 box, and put it in the actionPerform so I could modify the getter of X and Y to repaint() them and make them move?
From Box Class:
public void draw(Graphics g) {
g.setColor(Color.BLUE);
g.fillRect((int) (getX() - (width/2)), (int) (getY() - (height/2)), getWidth(), getHeight());
}
actionPerform method: (This is in another class)
public void actionPerformed(ActionEvent e){
timer.start();
}
The basic idea is...
When actionPerformed is called...
Iterate through the list of objects and update them in some meaningful way
Call repaint...
Then within your components paintComponent method, iterate the list and paint them
The following is a very basic concept...
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class FlyingBoxes {
public static void main(String[] args) {
new FlyingBoxes();
}
public interface Drawable {
public void update(JComponent comp);
public void draw(Graphics g);
}
public class Box implements Drawable {
private int x;
private int y;
private int width = 10;
private int height = 10;
private int xDelta;
private int yDelta;
public Box(int x, int y) {
this.x = x;
this.y = y;
xDelta = random();
yDelta = random();
}
#Override
public void update(JComponent comp) {
x += xDelta;
y += yDelta;
if (x < 0) {
x = 0;
xDelta *= -1;
} else if (x + width > comp.getWidth()) {
x = comp.getWidth() - width;
xDelta *= -1;
}
if (y < 0) {
y = 0;
yDelta *= -1;
} else if (y + height > comp.getHeight()) {
y = comp.getHeight() - height;
yDelta *= -1;
}
}
#Override
public void draw(Graphics g) {
g.setColor(Color.BLUE);
g.fillRect(x, y, width, height);
}
protected int random() {
int value = 0;
do {
value = -2 + (int)(Math.random() * 4);
} while (value == 0);
return value;
}
}
public FlyingBoxes() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private List<Drawable> drawables;
public TestPane() {
drawables = new ArrayList<>(25);
for (int index = 0; index < 25; index++) {
int x = (int) (Math.random() * 190);
int y = (int) (Math.random() * 190);
drawables.add(new Box(x, y));
}
Timer timer = new Timer(40, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
for (Drawable d : drawables) {
d.update(TestPane.this);
}
repaint();
}
});
timer.start();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
for (Drawable d : drawables) {
d.draw(g);
}
}
}
}
I'm trying to draw Images with Graphics2D on JFrame.
But this code only displays blank background.
How to do that?
Java Version: SE-1.6
IDE: Eclipse
My code looks like this:
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.image.BufferStrategy;
import java.awt.geom.Line2D;
import java.util.TimerTask;
import javax.swing.JFrame;
public class GraphicTest extends JFrame{
public static void main(String[] args) {
GraphicTest gt = new GraphicTest();
gt.start();
}
JFrame frame;
BufferStrategy strategy;
GraphicTest(){
int width = 320;
int height = 240;
this.frame = new JFrame("test");
this.frame.setSize(width, height);
this.frame.setLocationRelativeTo(null);
this.frame.setLocation(576, 336);
this.frame.setDefaultCloseOperation(javax.swing.JFrame.EXIT_ON_CLOSE);
this.frame.setUndecorated(true);
this.frame.setBackground(new Color(0, 0, 0, 50));
this.frame.setVisible(true);
this.frame.setIgnoreRepaint(true);
this.frame.createBufferStrategy(2);
this.strategy = this.frame.getBufferStrategy();
}
public void onExit(){
System.exit(0);
}
void start(){
java.util.Timer timer = new java.util.Timer();
timer.schedule(new RenderTask(), 0, 16);
}
class RenderTask extends TimerTask{
int count = 0;
#Override
public void run() {
GraphicTest.this.render();
}
}
void render() {
// Some moving images
Graphics2D g2 = (Graphics2D)this.strategy.getDrawGraphics();
g2.setStroke(new BasicStroke(5.0f));
Line2D line = new Line2D.Double(20, 40, 120, 140);
g2.draw(line);
this.strategy.show();
}
}
Thank you for any help you can provide.
BufferStrategy is normally associated with heavy weight components, which don't have any concept of transparency.
Transparent and translucent (per alpha pixeling) is not "officially" supported under Java 6
Making a window translucent effects anything else painted to it...this very annoying, regardless if you are using Java 6 or 7
The secret is to make the Window transparent to begin with, then overlay a transparent component that has a special "translucent" paint effect.
Under Java 6 (update 10 I think), there became available a private API called AWTUtilities which provide the ability to make a window transparent or translucent, the following example is based on that API.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Window;
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.lang.reflect.Method;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class TransparentWindowAnimation {
public static void main(String[] args) {
new TransparentWindowAnimation();
}
public TransparentWindowAnimation() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
if (supportsPerAlphaPixel()) {
try {
JFrame frame = new JFrame("Testing");
frame.setUndecorated(true);
setOpaque(frame, false);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new PaintPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
} catch (Exception exp) {
exp.printStackTrace();
}
} else {
System.err.println("Per pixel alphering is not supported");
}
}
});
}
public static boolean supportsPerAlphaPixel() {
boolean support = false;
try {
Class<?> awtUtilsClass = Class.forName("com.sun.awt.AWTUtilities");
support = true;
} catch (Exception exp) {
}
return support;
}
public static void setOpaque(Window window, boolean opaque) throws Exception {
try {
Class<?> awtUtilsClass = Class.forName("com.sun.awt.AWTUtilities");
if (awtUtilsClass != null) {
Method method = awtUtilsClass.getMethod("setWindowOpaque", Window.class, boolean.class);
method.invoke(null, window, opaque);
}
} catch (Exception exp) {
throw new Exception("Window opacity not supported");
}
}
public class PaintPane extends JPanel {
private BufferedImage img;
private int xPos, yPos = 100;
private int xDelta = 0;
private int yDelta = 0;
public PaintPane() {
while (xDelta == 0) {
xDelta = (int)((Math.random() * 8)) - 4;
}
while (yDelta == 0) {
yDelta = (int)((Math.random() * 8)) - 4;
}
setOpaque(false);
try {
img = ImageIO.read(new File("AngryBird.png"));
} catch (IOException ex) {
ex.printStackTrace();
}
Timer timer = new Timer(40, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
xPos += xDelta;
yPos += yDelta;
if (xPos - (img.getWidth() / 2) <= 0) {
xPos = img.getWidth() / 2;
xDelta *= -1;
}
if (xPos + (img.getWidth() / 2) >= getWidth()) {
xPos = getWidth() - (img.getWidth() / 2);
xDelta *= -1;
}
if (yPos - (img.getHeight() / 2) <= 0) {
yPos = img.getHeight() / 2;
yDelta *= -1;
}
if (yPos + (img.getHeight() / 2) >= getHeight()) {
yPos = getHeight() - (img.getHeight() / 2);
yDelta *= -1;
}
repaint();
}
});
timer.start();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setColor(new Color(128, 128, 128, 128));
g2d.fillRect(0, 0, getWidth(), getHeight());
int x = xPos - (img.getWidth() / 2);
int y = yPos - (img.getHeight()/ 2);
g2d.drawImage(img, x, y, this);
g2d.dispose();
}
}
}
Another way can be seen here. It can be accomplished by
frame.setBackground(new Color(0, 0, 0, 0));
....
setOpaque(false); //for the JPanel being painted on.
I am creating a 6x6 grid memory game. Its requirements is to use an image in a panel as a replacement for the buttons.
210 x 70
The project requires to implement MouseListeners on the following conditions:
The button will show first pokebell.
When the mouse hovers over the pokeball, it changes into the second pokeball.
When the mouse moves away from the pokeball, it reverts back to the first pokeball.
When the mouse clicks the pokeball, it changes to the 3rd pokeball.
Grid MouseEvents
public void mouseEntered(MouseEvent e) {
for(i = 0; i < 36; i++){
if(e.getSource() == pkm[i]){
pkb[i].repaint();
}
}
}
public void mouseExited(MouseEvent e) {
for(i = 0; i < 36; i++){
if(e.getSource() == pkm[i]){
pkb[i].repaint();
}
}
}
PokeBall class
int start = 0;
int ht = 0, wt = 0;
URL url;
BufferedImage img, sp1;
public PokeBall(String imgLink, int w, int h, int x){
wt = w;
ht = h;
start = x;
url = this.getClass().getResource(imgLink);
try{
img = ImageIO.read(url);
}
catch(Exception e){
}
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D)g;
sp1 = img.getSubimage(start, 0, wt, ht);
g2d.drawImage(sp1,20,10,null);
if(start == 70) {
start = 0;
}
else {
start += 70;
}
}
My thought was that the change of sprite will be invoked on the corresponding mouse event, but instead I got the whole pokeball to animate in an infinite loop even when the mouse didn't invoke any event.
I need some ideas or suggestions on how to stop it from looping by itself and to actually call the designated pokeball.
Basically, the responsibility for painting the balls is the PokeBall class, it needs to know when the state has changed, so it makes sense to apply an MouseListener and MouseMotionListener to it. Then you don't need to care about trying to update grid locations and other fun stuff.
On your GridPane, I would then attach another MouseListener so you can detect when a ball is clicked and take appropriate action there...
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
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.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class MyPokeBalls {
public static void main(String[] args) {
new MyPokeBalls();
}
public MyPokeBalls() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new PokeBall());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class PokeBall extends JPanel {
private BufferedImage balls;
private int ballWidth = 70;
private int ballHeight = 70;
private int ballOffset = 0;
public PokeBall() {
try {
balls = ImageIO.read(new File("PokeBalls.png"));
} catch (IOException ex) {
ex.printStackTrace();
}
MouseAdapter ma = new MouseAdapter() {
private boolean isIn = false;
#Override
public void mouseEntered(MouseEvent e) {
ballOffset = 1;
isIn = true;
repaint();
}
#Override
public void mouseExited(MouseEvent e) {
ballOffset = 0;
isIn = true;
repaint();
}
#Override
public void mousePressed(MouseEvent e) {
ballOffset = 2;
repaint();
}
#Override
public void mouseReleased(MouseEvent e) {
if (isIn) {
ballOffset = 1;
} else {
ballOffset = 2;
}
repaint();
}
};
addMouseListener(ma);
addMouseMotionListener(ma);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(ballWidth, ballHeight);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (balls != null) {
Graphics2D g2d = (Graphics2D) g.create();
BufferedImage ball = balls.getSubimage(ballWidth * ballOffset, 0, ballWidth, ballHeight);
int x = (getWidth() - ball.getWidth()) / 2;
int y = (getHeight() - ball.getHeight()) / 2;
g2d.drawImage(ball, x, y, this);
g2d.dispose();
}
}
}
}
AbstractButton b=new JToggleButton(firstIcon);
b.setContentAreaFilled(false);
b.setFocusable(false);
b.setBorder(BorderFactory.createEmptyBorder());
b.setRolloverEnabled(true);
b.setRolloverIcon(secondIcon);
b.setSelectedIcon(thirdIcon);
Why reinventing the wheel?
Creating a grid of such buttons is quite simpleā¦