hello im new in programming and we have a project.We created a simple racing game with a moving background but I'm stuck on my code and i don't know how to do it. i need a moving background when the game starts please somebody help me. I'm begging T_T
here is my code:
public class Game extends JFrame implements KeyListener, ActionListener {
Random s = new Random();
int x = 0, y = 50, a = 0, b = 250, f = 900, a1 = 0, b2 = 350, a2 = 0, b3 = 150;
int Move;
int value;
JLabel spriteLabel1 = new JLabel(new ImageIcon("ss.gif"));
JLabel spriteLabel2 = new JLabel(new ImageIcon("ss.gif"));
JLabel spriteLabel3 = new JLabel(new ImageIcon("ss.gif"));
JLabel spriteLabel4 = new JLabel(new ImageIcon("ss.gif"));
JLabel background = new JLabel(new ImageIcon("geren.png"));
Timer T1 = new Timer(5000, this);
Timer T = new Timer(5, this);
public static void main(String args[]) {
new Game();
}
public Game() {
Container c = getContentPane();
c.setLayout(null);
c.add(spriteLabel1);
c.add(spriteLabel2);
c.add(spriteLabel3);
c.add(spriteLabel4);
c.add(background);
background.setBounds(0, 0, 1024, 768);
addKeyListener(this);
setSize(1000, 750);
setVisible(true);
}
public void paint(Graphics g) {
super.paint(g);
spriteLabel1.setBounds(x, y, 60, 1000);
spriteLabel2.setBounds(a, b, 60, 800);
spriteLabel3.setBounds(a1, b2, 60, 500);
spriteLabel4.setBounds(a2, b3, 60, 650);
}
public void keyPressed(KeyEvent e) {
String k = e.getKeyText(e.getKeyCode());
if (k.equals("D")) {
if (a != f) {
x = x + 15;
spriteLabel1.setIcon(new ImageIcon("ss.gif"));
repaint();
if (x > f) {
x = f;
spriteLabel1.setIcon(new ImageIcon("ss.gif"));
//JOptionPane.showMessageDialog(null,"Congratulations!!
//Sanji wins!","Result",JOptionPane.PLAIN_MESSAGE,
//new ImageIcon("evolve sanji.gif"));
//System.exit(0);
}
repaint();
}
}
T.stop();
}
if(k.equals (
"D"))
{
if (x != f) {
T.start();
Move = 3;
}
}
public void keyReleased(KeyEvent e) {
}
public void keyTyped(KeyEvent e) {
}
public void actionPerformed(ActionEvent e) {
if (Move == 3) {
a = a + (s.nextInt(3));
a = a + value;
if (a > f) {
a = f;
}
spriteLabel2.setIcon(new ImageIcon("ss.gif"));
spriteLabel2.setBounds(a, b, 100, 800);
}
if (a == f) {
if (Move == 3) {
a1 = a1 + (s.nextInt(3));
a1 = a1 + value;
if (a1 > f) {
a1 = f;
}
spriteLabel3.setIcon(new ImageIcon("ss.gif"));
spriteLabel3.setBounds(a1, b2, 100, 500);
}
if (Move == 3) {
a2 = a2 + (s.nextInt(5));
a2 = a2 + value;
if (a2 > f) {
a2 = f;
}
spriteLabel4.setIcon(new ImageIcon("ss.gif"));
spriteLabel4.setBounds(a2, b3, 100, 650);
}
}
}
}
Here's the spoiler
Here's the meat
There a a few things I see you doing wrong:
Constantly creating new Images. Just use the same image.
I would, instead of using label, just paint an Image/BufferedImage onto the painting surface.
Forget two timers. You can make due with one. It's just how you manage your state.
Don't do any logic in the paint method. In your current case, since are not even painting anything, you don't even need it. In my example though I do paint the image.
Don't Paint on JFrame and override paint. Override paintComponent instead in a JPanel and add that panel to the frame.
Finally, the key ingredient, use the method (from Graphics) -
public abstract boolean drawImage(Image img,
int dx1,
int dy1,
int dx2,
int dy2,
int sx1,
int sy1,
int sx2,
int sy2,
ImageObserver observer)
You can get a better explanation about it in this post. Basically, the s points are the source image, so you can just move the sx1 and sx2 during the animation, and it will move the part of the image to be drawn at the d points of the painting surface.
If you don't know how to really do custom painting, I suggest you run through Performing Custom Painting
Here's the full example
(Note the image I used for the background was 2000x350)
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class MovingBackgroundDemo {
public MovingBackgroundDemo() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new AnimatingPanel());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
private class AnimatingPanel extends JPanel {
private static final int DIM_W = 350;
private static final int DIM_H = 350;
private static final int INCREMENT = 10;
private BufferedImage backgroundImage;
private Image runnerImage;
private int dx1, dy1, dx2, dy2;
private int srcx1, srcy1, srcx2, srcy2;
private int IMAGE_WIDTH;
public AnimatingPanel() {
initImages();
initImagePoints();
Timer timer = new Timer(40, new ActionListener() {
public void actionPerformed(ActionEvent e) {
moveBackground();
repaint();
}
});
timer.start();
FlowLayout layout = (FlowLayout)getLayout();
layout.setHgap(0);
layout.setVgap(0);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.WHITE);
g.fillRect(0, 0, getWidth(), getHeight());
g.drawImage(backgroundImage, dx1, dy1, dx2, dy2, srcx1, srcy1,
srcx2, srcy2, this);
g.drawImage(runnerImage, 0, 0, getWidth(), getHeight(), this);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(350, 350);
}
private void initImagePoints() {
dx1 = 0;
dy1 = 0;
dx2 = DIM_W;
dy2 = DIM_H;
srcx1 = 0;
srcy1 = 0;
srcx2 = DIM_W;
srcy2 = DIM_H;
}
private void initImages() {
try {
runnerImage = new ImageIcon(getClass().getResource("runner.gif")).getImage();
backgroundImage = ImageIO.read(getClass().getResource(
"background.png"));
IMAGE_WIDTH = backgroundImage.getWidth();
System.out.println(IMAGE_WIDTH);
} catch (Exception ex) {
ex.printStackTrace();
}
}
private void moveBackground() {
if (srcx1 > IMAGE_WIDTH) {
srcx1 = 0 - DIM_W;
srcx2 = 0;
} else {
srcx1 += INCREMENT;
srcx2 += INCREMENT;
}
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new MovingBackgroundDemo();
}
});
}
}
Related
For some reason, my KeyListener works just fine and fires off the Booleans to make down and up true and false and the y value changes according to those Booleans exactly how I want it to. My problem is that for some reason, the red rectangle appears to grow in size rather than move, and I'm pretty sure that it's because the previous frame is not cleared. I tried to use super.paintComponent(g); to clear the frame but this accomplishes nothing. Here's the code:
JFrame:
import java.awt.*;
import javax.swing.*;
public class H extends JFrame
{
public H()
{
super("Atlas Blade");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setResizable(false);
pack();
P p = new P();
Insets frameInsets = getInsets();
int frameWidth = p.getWidth() +
(frameInsets.left + frameInsets.right);
int frameHeight = p.getHeight() + (
frameInsets.top + frameInsets.bottom);
setPreferredSize(new Dimension(frameWidth, frameHeight));
setLayout(null);
add(p);
pack();
setVisible(true);
}
}
JPanel:
import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyListener;
import java.awt.event.KeyEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseEvent;
import java.awt.image.*;
public class P extends JPanel implements KeyListener, Runnable
{
private long updateCount=0;
private long paintCount=0;
private int updatesPerSecond = 50;
private boolean aLeft,aRight,aDown,aUp=false;
private boolean up,down,left,right=false;
int x = 20;
int y=20;
Hb box = new Hb(x,y);
Rectangle rect = new Rectangle(0,300,300,50);
BufferedImage buffer;
public P()
{
super();
setSize(600,350);
//setSize(50,50);
buffer = new BufferedImage (600,350,BufferedImage.TYPE_4BYTE_ABGR);
addKeyListener(this);
Thread jim = new Thread(this);
jim.start();
}
public void run()
{
int waitToUpdate = 1000/updatesPerSecond;
long startTime = System.nanoTime();
while(true)
{
boolean shouldRepaint = false;
long currentTime = System.nanoTime();
long updatesNeeded = (((currentTime-startTime) / 1000000))/ waitToUpdate;
for(long x = updateCount; x< updatesNeeded; x++)
{
updateGame();
shouldRepaint=true;
updateCount++;
}
if(shouldRepaint)
{
paintCount++;
repaint();
}
try
{
Thread.sleep(5);
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
#Override
public void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics bg = buffer.getGraphics();
bg.setColor(Color.BLACK);
bg.drawRect(0,300,300,50);
bg.setColor(Color.RED);
bg.fillRect(x,y,35,35);
g.drawImage(buffer,0,0,null);
}
public void updateGame()
{
box.updateHitbox(x,y);
if(down)
{
if(!box.center.intersects(rect))
{
y++;
//y=y+40;
}
}
else if(up)
{
if(!box.center.intersects(rect))
{
y--;
}
}
}
public void keyPressed(KeyEvent e)
{
int code = e.getKeyCode();
if(code==KeyEvent.VK_A)
{
left=true;
right=false;
aLeft=true;
aRight=false;
aDown=false;
aUp=false;
}
if(code==KeyEvent.VK_D)
{
left=false;
right=true;
aLeft=false;
aRight=true;
aDown=false;
aUp=false;
}
if(code==KeyEvent.VK_S)
{
System.out.println(y);
down=true;
up=false;
aLeft=false;
aRight=false;
aDown=true;
aUp=false;
}
if(code==KeyEvent.VK_W)
{
down=false;
up=true;
aLeft=false;
aRight=false;
aDown=false;
aUp=true;
}
repaint();
}
public void keyTyped(KeyEvent e)
{
}
public void keyReleased(KeyEvent e)
{
int code = e.getKeyCode();
if(code==e.VK_A)
{
left=false;
aLeft=false;
}
if(code==e.VK_D)
{
right=false;
aRight=false;
}
if(code==e.VK_S)
{
down=false;
aDown=false;
}
if(code==e.VK_W)
{
up=false;
aUp=false;
}
}
public void addNotify()
{
// call super so the method still does what it was built to do
super.addNotify();
// requests focus so that key inputs are sent to this screen
requestFocus();
}
}
And the Hb class:
import java.awt.Rectangle;
public class Hb
{
public Rectangle center,left,right,up,down;
public Hb(int x, int y)
{
center = new Rectangle(x,y,50,50);
left = new Rectangle(x-1,y+1,1,48);
right = new Rectangle(x+50,y+1,1,48);
up = new Rectangle(x+1,y-1,48,1);
down = new Rectangle(x+1,y+50,48,1);
}
public void updateHitbox(int x, int y)
{
center = new Rectangle(x,y,50,50);
left = new Rectangle(x-1,y+1,1,48);
right = new Rectangle(x+50,y+1,1,48);
up = new Rectangle(x+1,y-1,48,1);
down = new Rectangle(x+1,y+50,48,1);
}
}
Your problem is that you're doing all your drawing in the BufferedImage, and that doesn't allow erasure of "dirty" pixels. Instead, only draw in the BufferedImage that which should be a static and unchanging part of the image, usually the background. The foreground image that moves should be painted directly in paintComponent using the Graphcis object given to the method by the JVM.
public P() {
super();
setSize(600, 350); // not recommended
buffer = new BufferedImage(600, 350, BufferedImage.TYPE_4BYTE_ABGR);
Graphics bg = buffer.getGraphics();
bg.setColor(Color.BLACK);
bg.drawRect(0, 300, 300, 50);
bg.dispose();
// ....
}
and
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(buffer, 0, 0, null);
g.setColor(Color.RED);
g.fillRect(x, y, 35, 35);
}
I am having problem with the JFrame textfield.
I am trying to make a word game, but the problem is that when I try to create textfield to set an input and then check if it's the right word, I have got the word thing covered.
The problem is that when I try to add Textfield, it disappears when i render things to JFrame.
public teksti() {
setTitle("Hirsipuu");
setSize(leveys,korkeus);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setResizable(false);
setVisible(true);
setLocationRelativeTo(null);
setBackground(Color.white);
jp.add(tf); // adding JtextField (JTextField tf = new JTextField(30);)
add(jp);
}
and my render() is like this (just for testing purpose).
private void render() {
BufferStrategy bs = this.getBufferStrategy(); // tehdään uusi bufferi
if (bs == null) {
createBufferStrategy(3);
return;
}
int R = (int) (Math.random( )*256);
int G = (int)(Math.random( )*256);
int B= (int)(Math.random( )*256);
Color randomColor = new Color(R, G, B);
Graphics g = bs.getDrawGraphics();
g.drawString("Arvaa sana", 100 , 100);
g.setColor(Color.white);
g.fillRect(0, 50, leveys, korkeus);
g.setColor(randomColor);
g.setFont(h);
// g.drawLine(0,0,liikey*2-1,liikex);
for(int i = 0; i < salat.size(); i ++) {
g.drawString(salat.get(i),liikex+rand.nextInt(50),liikey+rand.nextInt(50));
}
System.out.println(liikex + " " + liikey);
g.dispose();
bs.show();
g.dispose();
}
I can get the textfield to be displayed on top at the start, but then it disappears.
Anyone knows if there is a better way to do this?
Don't draw directly in a JFrame
Instead, if you need to draw a background image, do so in the paintComponent method of a JPanel. This will likely work much better than using BufferStrategy for your purposes.
Then you can add components, such as your JTextField to this JPanel.
And then add this JPanel to your JFrame.
Always call the super's paintComponent method in your own paintComponent method override.
Be careful to never dispose of a Graphics object given to you from the JVM, such as the one passed into your paintComponent method.
For example:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Paint;
import javax.swing.*;
public class BackgroundPanel extends JPanel {
private static final int PREF_W = 800;
private static final int PREF_H = 600;
private static final Font PROMPT_FONT = new Font(Font.SANS_SERIF, Font.BOLD,
24);
private Paint gradientPaint;
private JTextField textField = new JTextField(20);
public BackgroundPanel() {
int red = (int) (Math.random() * 256);
int green = (int) (Math.random() * 256);
int blue = (int) (Math.random() * 256);
Color color1 = new Color(red, green, blue);
red = (int) (Math.random() * 256);
green = (int) (Math.random() * 256);
blue = (int) (Math.random() * 256);
Color color2 = new Color(red, green, blue);
gradientPaint = new GradientPaint(0, 0, color1, 20, 20, color2, true);
JLabel promptLabel = new JLabel("Input:");
promptLabel.setFont(PROMPT_FONT);
add(promptLabel);
add(textField);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setPaint(gradientPaint);
g.fillRect(0, 0, getWidth(), getHeight());
g.setColor(Color.black);
g.setFont(PROMPT_FONT);
g.drawString("Arvaa sana", 100, 100);
}
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
private static void createAndShowGui() {
BackgroundPanel mainPanel = new BackgroundPanel();
JFrame frame = new JFrame("BackgroundPanel");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
this is basically whole thing i got done now.
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.image.BufferStrategy;
import java.io.BufferedReader;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.Random;
import java.util.Scanner;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class teksti extends JFrame implements Runnable {
/**
*
*/
private static final long serialVersionUID = 1L;
ArrayList<String> sanat = new ArrayList<String>();
ArrayList<String> salat = new ArrayList<String>();
String dir = System.getProperty("user.dir");
String pathname = dir + "\\src\\kotus_sanat.txt";
Random rand = new Random();
Scanner lukija = new Scanner(System.in);
String syote,salasana,salasana2;
int leveys=500,korkeus=500;
int liikex=300, liikey=300;
Font h = new Font("Helvetica", Font.PLAIN, 18);
JTextField tf = new JTextField(30);
JPanel jp = new JPanel();
JFrame jf = new JFrame();
public teksti() {
setTitle("Hirsipuu");
setSize(leveys,korkeus);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setResizable(false);
setVisible(true);
setLocationRelativeTo(null);
setBackground(Color.white);
jp.add(tf);
add(jp);
}
public static void main(String args[]){
teksti teksti = new teksti();
teksti.start();
}
private void start() {
run();
}
public void run() {
sanat = lataa();
System.out.println(pathname);
System.out.println(sanat.size() + " sanaa ladattu..");
int sanoja=sanat.size();
for (int i = 0; i < 10; i++){
salat.add(sanat.get(rand.nextInt(sanoja)));
}
System.out.println("salasana on " + salasana);
long lastTime = System.nanoTime(); // fps sälää
long timer = System.currentTimeMillis();
final double ns = 1000000000.0 / 60.0;
double delta = 0;
int frames = 0;
int updates = 0;
requestFocus();
boolean running=true;
while (running){
long now = System.nanoTime();
delta += (now-lastTime) / ns;
lastTime = now;
while ( delta >= 1) {
update();
updates++;
delta--;
}
render();
frames++;
if (System.currentTimeMillis() - timer > 1000){
timer += 1000;
setTitle("Hirsipuu"+ " | " + updates + " ups " + frames + " fps" );
updates = 0;
frames = 0;
}
}
}
private void update() {
liikex = liikex + 1;
liikey= liikey - 4;
if (liikey>korkeus)
liikey = 1;
if (liikex>leveys)
liikex= 1;
if (liikey<20)
liikey = korkeus;
}
private void render() {
BufferStrategy bs = this.getBufferStrategy(); // tehdään uusi bufferi
if (bs == null) {
createBufferStrategy(3);
return;
}
int R = (int) (Math.random( )*256);
int G = (int)(Math.random( )*256);
int B= (int)(Math.random( )*256);
Color randomColor = new Color(R, G, B);
Graphics g = bs.getDrawGraphics();
g.drawString("Arvaa sana", 100 , 100);
g.setColor(Color.white);
g.fillRect(0, 50, leveys, korkeus);
g.setColor(randomColor);
g.setFont(h);
// g.drawLine(0,0,liikey*2-1,liikex);
for(int i = 0; i < salat.size(); i ++) {
g.drawString(salat.get(i), liikex+rand.nextInt(50),liikey+rand.nextInt(50));
}
System.out.println(liikex + " " + liikey);
g.dispose();
bs.show();
g.dispose();
}
private void stop() {
}
private void vertaa() {
System.out.println("Anna sana niin tarkastaan onko se oikea suomenkielinen sana: ");
syote = lukija.next();
boolean oikea = false;
int i = 0;
int z = 0;
while (i < sanat.size()) {
if (syote.equals(sanat.get(i))) {
oikea = true;
System.out.println (syote + " on oikea suomalainen sana.");
break;
}
else{
}
}
if (!oikea) {
System.out.println(syote + " ei ole oikea suomalainen sana.");
}
}
public ArrayList<String> lataa() {
String line = null;
try {
BufferedReader reader = new BufferedReader(new FileReader(pathname));
while((line = reader.readLine()) != null){
sanat.add(line);
}
} catch (Exception e) {
e.printStackTrace();
}
return sanat;
}
}
vertaa() is not used.
I have this really crappy sprite sheet that I made, which is basically just a bunch of circles and ovals so I can grasp Sprite animation.
import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.Timer;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.*;
public class CircleSprite extends JFrame implements ActionListener, Runnable{
BufferedImage circles;
BufferedImage[] test;
Timer timer;
int cycle = 0;
Graphics g = getGraphics();
public void asd(){
setSize(500,500);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
try {
circles = ImageIO.read(new File("CircleTest.png"));
} catch (IOException e) {
e.printStackTrace();
}
final int width = 206;
final int height = 206;
final int rows= 2;
final int columns = 3;
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
test = new BufferedImage[rows * columns];
try{
for(int i = 0; i < rows; i++)
for(int j = 0;j<columns;j++)
{
test[i*columns + j] = circles.getSubimage(j * width, i * height, width, height);
}
}catch(Exception e){
e.printStackTrace();
}
timer = new Timer(500, this);
setVisible(true);
}
public void actionPerformed(ActionEvent e){
//0, 1, 2, 3, 4, 5, 4, 3, 2, 1, 0, 1, 2, etc.
repaint();
g.drawImage(test[cycle], 25, 25, null);
if(cycle >= 5){
cycle--;
}
if(cycle <=0){
cycle++;
}
}
public void run(){
asd();
while(timer.isRunning() == false && this.isVisible() == true){
timer.start();
try {
CircleSpriteRun.t1.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
The error occurs here: g.drawImage(test[cycle], 25, 25, null);
At first I though it had to do with the ImageObserver being null, and looking further into it, I was wrong. Now, I think it might be because of the timer, but I don't really know too much about Timers, let alone the swing one.
This all runs on a Thread being executed in another class, and it could also have to do with the while statement in the run method, since that also involves the timer.
Since you didn't provide a runnable example, I created one to show how to properly code a Swing application.
First, you must start a Swing application with the SwingUtilities.invokeLater method. Here's how I started the CircleSprite class.
public static void main(String[] args) {
SwingUtilities.invokeLater(new CircleSprite());
}
Second, you should use a JPanel for drawing, not a JFrame. Here's the DrawingPanel I created. My version of CircleSprite draws a circle in a random location every 2 seconds.
public class DrawingPanel extends JPanel {
private static final long serialVersionUID = -4603711384104715819L;
private int x;
private int y;
private BufferedImage image;
public DrawingPanel(BufferedImage image) {
this.image = image;
this.x = 0;
this.y = 0;
setPreferredSize(new Dimension(500, 500));
}
public void setPoint(int x, int y) {
this.x = x;
this.y = y;
repaint();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image, x, y, null);
}
}
Third, you create the Swing GUI before you do anything with the Swing GUI. Here's the run method from the CircleSprite class. I create the GUI, then I start the thread that does the random drawing.
public void run() {
circle = createCircle();
frame = new JFrame("Circle Sprite");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
drawingPanel = new DrawingPanel(circle);
frame.add(drawingPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
new Thread(new RandomDraw(drawingPanel)).start();
}
Fourth, you only extend a Swing component when you want to override a method, like I did in the DraawingPanel class. You use Swing Components otherwise.
Here's the entire, runnable, CircleSprite class. You can use this as a model for future Swing applications.
package com.ggl.testing;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class CircleSprite implements Runnable {
private BufferedImage circle;
private DrawingPanel drawingPanel;
private JFrame frame;
#Override
public void run() {
circle = createCircle();
frame = new JFrame("Circle Sprite");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
drawingPanel = new DrawingPanel(circle);
frame.add(drawingPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
new Thread(new RandomDraw(drawingPanel)).start();
}
private BufferedImage createCircle() {
BufferedImage image = new BufferedImage(100, 100,
BufferedImage.TYPE_INT_RGB);
Graphics g = image.getGraphics();
g.setColor(Color.WHITE);
g.fillRect(0, 0, 100, 100);
g.setColor(Color.BLUE);
g.fillOval(10, 10, 80, 80);
g.dispose();
return image;
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new CircleSprite());
}
public class DrawingPanel extends JPanel {
private static final long serialVersionUID = -4603711384104715819L;
private int x;
private int y;
private BufferedImage image;
public DrawingPanel(BufferedImage image) {
this.image = image;
this.x = 0;
this.y = 0;
setPreferredSize(new Dimension(500, 500));
}
public void setPoint(int x, int y) {
this.x = x;
this.y = y;
repaint();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image, x, y, null);
}
}
public class RandomDraw implements Runnable {
private DrawingPanel drawingPanel;
private Random random;
public RandomDraw(DrawingPanel drawingPanel) {
this.drawingPanel = drawingPanel;
this.random = new Random();
}
#Override
public void run() {
while (true) {
sleep();
int x = random.nextInt(400);
int y = random.nextInt(400);
drawingPanel.setPoint(x, y);
}
}
private void sleep() {
try {
Thread.sleep(2000L);
} catch (InterruptedException e) {
}
}
}
}
So right now when you press go it just moves across the screen, but I also want it to move its legs so its doing something and not just standing still. Any tips on how to do that? I know it would be moving the 2nd leg pointers back and forth but I'm not sure how to do that
Class Stick2 :
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Stick2 extends JFrame implements ActionListener {
// Declares constants
public static final int FRAME_WIDTH = 500;
private static final int FRAME_HEIGHT = 500;
private static final int FRAME_X_ORIGIN = 150;
private static final int FRAME_Y_ORIGIN = 200;
private static final int BUTTON_WIDTH =80;
private static final int BUTTON_HEIGHT = 30;
JPanel buttonPanel, panel;
MovingBanner2 myBanner;
JButton startButton, stopButton;
Thread thrd;
public static void main(String[] args)
{
Stick2 frame = new Stick2();
frame.setVisible(true);
}
public Stick2(){
Container contentPane= getContentPane();
// Sets Frame
setSize(FRAME_WIDTH,FRAME_HEIGHT);
setResizable(false);
setTitle("Animation");
setLocation(FRAME_X_ORIGIN, FRAME_Y_ORIGIN);
// Sets layout manager
contentPane.setLayout(new BorderLayout(10,0));
buttonPanel = new JPanel();
JButton startButton = new JButton("Start");
startButton.setSize(BUTTON_WIDTH, BUTTON_HEIGHT);
buttonPanel.add(startButton);
startButton.addActionListener(this);
JButton stopButton = new JButton("Stop");
stopButton.setSize(BUTTON_WIDTH,BUTTON_HEIGHT);
buttonPanel.add(stopButton);
stopButton.addActionListener(this);
contentPane.add (buttonPanel, BorderLayout.SOUTH);
// Creates a balloon
myBanner = new MovingBanner2();
panel = myBanner;
panel.setBorder(BorderFactory.createLineBorder(Color.BLUE));
contentPane.add(panel, BorderLayout.CENTER);
}
public void actionPerformed (ActionEvent event){
JButton clickedButton = (JButton) event.getSource();
String buttonText = clickedButton.getText();
if (buttonText.equals("Stop")) {
myBanner.stopAnimation();
thrd = null;
}
else {
myBanner.startAnimation();
thrd = new Thread (myBanner);
thrd.start();
}
}
}
Class MovingBanner2:
class MovingBanner2 extends JPanel implements Runnable {
private int x;
private Boolean animate;
int bodyX = 250;
int bodyY1 = 160;
int bodyY2 = 210;
int armHeight = 190;
int armLength = bodyX + 30;
int armLength1 = bodyX - 30;
int legY = 340;
public MovingBanner2() {
x=10;
animate = true;
}
// Draws the String
public void paintComponent (Graphics g) {
super.paintComponent(g);
g.setColor(Color.RED);
//g.drawString("I love Java", x,50);
g.drawLine(bodyX + x, bodyY1, bodyX + x, bodyY2); //body
g.drawOval(bodyX + x - 15, bodyY1 - 40, 40, 40); //head
g.drawLine(armLength + x,armHeight, armLength1 + x, armHeight); //arms
g.drawLine(bodyX + x, bodyY2, bodyX + 20 + x,legY); //leg
g.drawLine(bodyX + x, bodyY2, bodyX - 20 + x, legY); //leg
}
public void run() {
while (animate) {
changeX();
repaint();
try {Thread.sleep(100); } catch(Exception e){};
}
}
public void changeX() {
if (x <= Stick2.FRAME_WIDTH - 240)
x++;
else x = 10;
}
public void stopAnimation() {
animate = false;
}
public void startAnimation() {
animate = true;
}
}
There are probably many answers to the question. The best I can come up with is basically to devise some kind of "cycle".
A cycle is a known period of time over which animation can run. In this example, it's 1 second.
You then need to provide a series of Animatable objects that are notified of a change to the cycle over time, which allows them to make changes accordingly. You can also ignore the cycle for those elements that don't need to cycle.
The intention is provide a single animation engine that can be responsible for updating the entire state in one go, rather then trying to use multiple threads/timers which may reduce the systems performance.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class TestAnimation06 {
public static void main(String[] args) {
new TestAnimation06();
}
public TestAnimation06() {
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 interface Animatable {
public void update(float progress);
}
public class AnimationEngine {
private List<Animatable> animations;
private int cycleTime = 1000;
private long startTime = -1;
public AnimationEngine() {
animations = new ArrayList<>(25);
Timer timer = new Timer(40, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (startTime < 0) {
startTime = System.currentTimeMillis();
}
long duration = System.currentTimeMillis() - startTime;
float progress = (float)duration / (float)cycleTime;
if (duration >= cycleTime) {
progress = 1f;
startTime = System.currentTimeMillis();
}
for (Animatable animatable : animations) {
animatable.update(progress);
}
}
});
timer.setRepeats(true);
timer.setCoalesce(true);
timer.start();
}
public void add(Animatable animatable) {
animations.add(animatable);
}
}
public class TestPane extends JPanel {
private AnimationEngine engine;
public TestPane() {
setLayout(null);
engine = new AnimationEngine();
Legs legs = new Legs();
Walker walker = new Walker(legs);
engine.add(legs);
engine.add(walker);
walker.setSize(walker.getPreferredSize());
add(walker);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.dispose();
}
}
public class Walker extends JPanel implements Animatable {
private int speed = 2;
public Walker(Legs legs) {
setLayout(new GridBagLayout());
add(legs);
}
#Override
public void update(float progress) {
Container parent = getParent();
int width = parent.getWidth();
int xPos = getX() + speed;
if (xPos <= 0) {
speed *= -1;
xPos = 0;
} else if (xPos + getWidth() >= width) {
speed *= -1;
xPos = width - getWidth();
}
System.out.println(xPos);
setLocation(xPos, (parent.getHeight() - getHeight()) / 2);
repaint();
}
}
public class Legs extends JPanel implements Animatable {
private float frameProgress;
public Legs() {
setOpaque(false);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(25, 50);
}
#Override
public void update(float progress) {
frameProgress = progress;
repaint();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
int width = getWidth();
int height = getHeight();
g.setColor(Color.BLACK);
g.drawLine(width / 2, 0, (int)(width * frameProgress), height);
g.drawLine(width / 2, 0, width - (int)(width * frameProgress), height);
}
}
}
I have displayed an image(ball) inside the JApplet, now I want the image to move in a vertical way (up and down). The problem is I don't know how to do it.
Could someone has an idea about this matter?
You need to set the position of that image to some calculated value (means you caculate the vertical position using time, speed and maybe other restrictions).
How you'd set that position depends on how you draw the image.
Example, based on drawing in the applet's (or a nested component's) paint(Graphics g) method:
//first calculate the y-position
int yPos += timeSinceLastPaint * speed; //increment the position
if( (speed > 0 && yPos > someMaxY) || (speed < 0 && yPos <0 ) ) {
speed *= -1; //if the position has reached the bottom (max y) or the top invert the direction
}
//in your paint(Graphics g) method:
g.drawImage(image, yPos, x, null);
Then you'd have to constantly repaint the applet.
More information on animations in applets can be found here: http://download.oracle.com/javase/tutorial/uiswing/components/applet.html
another example for javax.swing.Timer with moving Ojbects created by paintComponent(Graphics g), and I have lots of Start, not some blurred Mikado :-)
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import javax.swing.Timer;
public class AnimationBackground {
private Random random = new Random();
private JFrame frame = new JFrame("Animation Background");
private final MyJPanel panel = new MyJPanel();
private JLabel label = new JLabel("This is a Starry background.", JLabel.CENTER);
private JPanel stopPanel = new JPanel();
private JPanel startPanel = new JPanel();
public AnimationBackground() {
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
panel.setBackground(Color.BLACK);
for (int i = 0; i < 50; i++) {
Star star = new Star(new Point(random.nextInt(490), random.nextInt(490)));
star.setColor(new Color(100 + random.nextInt(155), 100 + random.nextInt(155), 100 + random.nextInt(155)));
star.setxIncr(-3 + random.nextInt(7));
star.setyIncr(-3 + random.nextInt(7));
panel.add(star);
}
panel.setLayout(new GridLayout(10, 1));
label.setForeground(Color.WHITE);
panel.add(label);
stopPanel.setOpaque(false);
stopPanel.add(new JButton(new AbstractAction("Stop this madness!!") {
private static final long serialVersionUID = 1L;
#Override
public void actionPerformed(ActionEvent e) {
panel.stopAnimation();
}
}));
panel.add(stopPanel);
startPanel.setOpaque(false);
startPanel.add(new JButton(new AbstractAction("Start moving...") {
private static final long serialVersionUID = 1L;
#Override
public void actionPerformed(ActionEvent e) {
panel.startAnimation();
}
}));
panel.add(startPanel);
frame.add(panel);
frame.pack();
frame.setLocation(150, 150);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
AnimationBackground aBg = new AnimationBackground();
}
});
}
private class Star extends Polygon {
private static final long serialVersionUID = 1L;
private Point location = null;
private Color color = Color.YELLOW;
private int xIncr, yIncr;
static final int WIDTH = 500, HEIGHT = 500;
Star(Point location) {
int x = location.x;
int y = location.y;
this.location = location;
this.addPoint(x, y + 8);
this.addPoint(x + 8, y + 8);
this.addPoint(x + 11, y);
this.addPoint(x + 14, y + 8);
this.addPoint(x + 22, y + 8);
this.addPoint(x + 17, y + 12);
this.addPoint(x + 21, y + 20);
this.addPoint(x + 11, y + 14);
this.addPoint(x + 3, y + 20);
this.addPoint(x + 6, y + 12);
}
public void setColor(Color color) {
this.color = color;
}
public void move() {
if (location.x < 0 || location.x > WIDTH) {
xIncr = -xIncr;
}
if (location.y < 0 || location.y > WIDTH) {
yIncr = -yIncr;
}
translate(xIncr, yIncr);
location.setLocation(location.x + xIncr, location.y + yIncr);
}
public void setxIncr(int xIncr) {
this.xIncr = xIncr;
}
public void setyIncr(int yIncr) {
this.yIncr = yIncr;
}
public Color getColor() {
return color;
}
}
private class MyJPanel extends JPanel {
private static final long serialVersionUID = 1L;
private ArrayList<Star> stars = new ArrayList<Star>();
private Timer timer = new Timer(20, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
for (Star star : stars) {
star.move();
}
repaint();
}
});
public void stopAnimation() {
if (timer.isRunning()) {
timer.stop();
}
}
public void startAnimation() {
if (!timer.isRunning()) {
timer.start();
}
}
#Override
public void addNotify() {
super.addNotify();
timer.start();
}
#Override
public void removeNotify() {
super.removeNotify();
timer.stop();
}
MyJPanel() {
this.setPreferredSize(new Dimension(512, 512));
}
public void add(Star star) {
stars.add(star);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
((Graphics2D) g).setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
for (Star star : stars) {
g.setColor(star.getColor());
g.fillPolygon(star);
}
}
}
}
How to move the image inside the JApplet ..?
Pretty much exactly the same way you might do it in a JFrame, JComponent or JPanel or...
Or to put that another way, nothing to do with applets and everything to do with Graphics2D. For more details, see the 2D Graphics Trail of the Java Tutorial.
When you've figured how to move an image and paint it to a Graphics2D, implement that logic in a JComponent or JPanel's paintComponent(Graphics) method and drop the component with moving image into a JApplet or JFrame (or a JPanel etc.).
For the animation side of it, use a javax.swing.Timer as seen in this example. This example does not extend any component. Instead, it creates a BufferedImage and adds it to a JLabel that is displayed to the user. When the timer fires, the code grabs the Graphics object of the image, and proceeds from there to draw the bouncing lines.
import java.awt.image.BufferedImage;
import java.awt.event.*;
import java.awt.geom.*;
import java.awt.*;
import javax.swing.*;
import java.util.Random;
class LineAnimator {
public static void main(String[] args) {
final int w = 640;
final int h = 480;
final RenderingHints hints = new RenderingHints(
RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON
);
hints.put(
RenderingHints.KEY_ALPHA_INTERPOLATION,
RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY
);
final BufferedImage bi = new BufferedImage(w,h, BufferedImage.TYPE_INT_ARGB);
final JLabel l = new JLabel(new ImageIcon(bi));
final BouncingLine[] lines = new BouncingLine[100];
int factor = 1;
for (int ii=0; ii<lines.length; ii++) {
lines[ii] = new BouncingLine(w*factor,h*factor);
}
final Font font = new Font("Arial", Font.BOLD, 30);
ActionListener al = new ActionListener() {
int count = 0;
long lastTime;
String fps = "";
private final BasicStroke stroke = new BasicStroke(6);
public void actionPerformed(ActionEvent ae) {
count++;
Graphics2D g = bi.createGraphics();
g.setRenderingHints(hints);
g.setColor(new Color(55,12,59));
g.fillRect(0,0,w,h);
g.setStroke(stroke);
for (int ii=0; ii<lines.length; ii++) {
lines[ii].move();
lines[ii].paint(g);
}
if ( System.currentTimeMillis()-lastTime>1000 ) {
lastTime = System.currentTimeMillis();
fps = count + " FPS";
count = 0;
}
g.setColor(Color.YELLOW);
g.setFont(font);
g.drawString(fps,5,h-5);
l.repaint();
g.dispose();
}
};
Timer timer = new Timer(25,al);
timer.start();
JOptionPane.showMessageDialog(null, l);
//System.exit(0);
timer.stop();
}
}
class BouncingLine {
private final Color color;
private static final Random random = new Random();
Line2D line;
int w;
int h;
int x1;
int y1;
int x2;
int y2;
BouncingLine(int w, int h) {
line = new Line2D.Double(random.nextInt(w),random.nextInt(h),random.nextInt(w),random.nextInt(h));
this.w = w;
this.h = h;
this.color = new Color(
random.nextInt(255)
,random.nextInt(255)
,random.nextInt(255)
,64+random.nextInt(128)
);
x1 = (random.nextBoolean() ? 1 : -1);
y1 = (random.nextBoolean() ? 1 : -1);
x2 = -x1;
y2 = -y1;
}
public void move() {
int tx1 = 0;
if (line.getX1()+x1>0 && line.getX1()+x1<w) {
tx1 = (int)line.getX1()+x1;
} else {
x1 = -x1;
tx1 = (int)line.getX1()+x1;
}
int ty1 = 0;
if (line.getY1()+y1>0 && line.getY1()+y1<h) {
ty1 = (int)line.getY1()+y1;
} else {
y1 = -y1;
ty1 = (int)line.getY1()+y1;
}
int tx2 = 0;
if (line.getX2()+x2>0 && line.getX2()+x2<w) {
tx2 = (int)line.getX2()+x2;
} else {
x2 = -x2;
tx2 = (int)line.getX2()+x2;
}
int ty2 = 0;
if (line.getY2()+y2>0 && line.getY2()+y2<h) {
ty2 = (int)line.getY2()+y2;
} else {
y2 = -y2;
ty2 = (int)line.getY2()+y2;
}
line.setLine(tx1,ty1,tx2,ty2);
}
public void paint(Graphics g) {
Graphics2D g2 = (Graphics2D)g;
g2.setColor(color);
//line.set
g2.draw(line);
}
}
Update 1
I want to do it in JApplet(1) using the image(2), is it possible(3)?
The examples by mKorbel and myself feature either an image in a JLabel or custom rendering in a JPanel. In our case, we added the components to a JOptionPane & a JFrame. Either example could be just as easily added to a JApplet, or a JDialog, or as part of another panel, or.. See the Laying Out Components Within a Container lesson & Using Top-Level Containers in the Java Tutorial for more details.
Instead of the stars or lines in our examples, ..paint your image. My example goes so far as to demonstrate how to get the position to bounce around within the bounds of the container.
Sure it is possible, but "Batteries not included". Our intention is to give you some ideas that you can then adapt to your bouncing ball applet. I doubt anyone is going to create an example for you, using balls, in an applet. Though if you post an SSCCE that shows your intent and what you tried, I (and others) would often run with that source. If you want more specific answers, ask a more specific SSCCE. ;)
I want to do it in JApplet.
Why not both? You can have a hybrid application/applet as shown in this animation.