Repaint leaves trail - java

I know that this isn't the first time that this question has been asked, but the responses haven't helped me much, so I am helping I am finally going to get my answer
I have made this little game where I have made a car drive around a track (using rectangles was mandatory). When I use the repaint() metod the rectangle representing the car repaints in the new location, but leaves a trail behind.
I have this code:
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.net.URL;
import javax.swing.JFrame;
import javax.swing.JPanel;
#SuppressWarnings("serial")
public class MAP extends JFrame
{
//constant for the screen size and used for the drawing the terrain
final int WIDTH = 900, HEIGHT = 650;
//the URL and Img designed for the images
URL cLeft,cRight,cUp;
Image img1,img2,img3;
//these will keep track of each player’s speed:
double p1Speed =.5;
//these are ints that represent directions:
final int UP = 0, RIGHT = 1, DOWN = 2, LEFT = 3;
//these will keep track of the player’s directions (default = up)
int p1Direction = 0;
JPanel panel;
//draw the terrain
Rectangle left = new Rectangle(0,0,WIDTH/9,HEIGHT);
Rectangle right = new Rectangle((WIDTH/9)*9,0,WIDTH/9,HEIGHT);
Rectangle top = new Rectangle(0,0,WIDTH, HEIGHT/9);
Rectangle bottom = new Rectangle(0,(HEIGHT/9)*9,WIDTH,HEIGHT/9);
Rectangle center = new Rectangle((int)((WIDTH/9)*2.5),(int)((HEIGHT/9)*2.5),(int)((WIDTH/9)*5),(HEIGHT/9)*4);
//these obstacles will obstruct the path and make navigating harder
Rectangle obstacle = new
Rectangle(WIDTH/2,(int)((HEIGHT/9)*7),WIDTH/10,HEIGHT/9);
Rectangle obstacle2 = new
Rectangle(WIDTH/3,(int)((HEIGHT/9)*5),WIDTH/10,HEIGHT/4);
Rectangle obstacle3 = new
Rectangle(2*(WIDTH/3),(int)((HEIGHT/9)*5),WIDTH/10,HEIGHT/4);
Rectangle obstacle4 = new Rectangle(WIDTH/3,HEIGHT/9,WIDTH/30,HEIGHT/9);
Rectangle obstacle5 = new Rectangle(WIDTH/2,(int)((HEIGHT/9)*1.5),WIDTH/30,HEIGHT/4);
Rectangle finish = new Rectangle(WIDTH/9,(HEIGHT/2)-HEIGHT/9,(int)((WIDTH/9)*1.5),HEIGHT/70);
Rectangle lineO=new Rectangle(WIDTH/9,HEIGHT/2,(int)((WIDTH/9)*1.5)/2,HEIGHT/140);
Rectangle lineI = new Rectangle(((WIDTH/9)+((int)((WIDTH/9)*1.5)/2)),(HEIGHT/2)+(HEIGHT/10),(int)((WIDTH/9)*1.5)/2, HEIGHT/140);
//this is the rectangle for player 1’s (outer) car:
Rectangle p1 = new Rectangle(WIDTH/9,HEIGHT/2, WIDTH/30,WIDTH/30);
public MAP(){
super("Radical Racing");
setSize(WIDTH,HEIGHT);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
setResizable(false);
setVisible(true);
setLocationRelativeTo(null);
//the following code creates the JFrame
try
{
cUp = this.getClass().getResource("carUp.jpg");
cLeft = this.getClass().getResource("carLeft.jpg");
cRight = this.getClass().getResource("carRight.jpg");
}catch(Exception e)
{}
//attach the URLs to the images
img1 = Toolkit.getDefaultToolkit().getImage(cUp);
img2 = Toolkit.getDefaultToolkit().getImage(cLeft);
img3 = Toolkit.getDefaultToolkit().getImage(cRight);
panel=new JPanel(){
public void paint(Graphics g)
{
//super.paint(g);
//draw the background for the racetrack
g.setColor(Color.DARK_GRAY);
g.fillRect(0,0,WIDTH,HEIGHT);
//when we draw, the border will be green
g.setColor(Color.GREEN);
//fill rectangle
g.fillRect(left.x,left.y,left.width,left.height);
g.fillRect(right.x,right.y,right.width,right.height);
g.fillRect(top.x,top.y,top.width,top.height);
g.fillRect(bottom.x,bottom.y,bottom.width,bottom.height);
g.fillRect(center.x,center.y,center.width,center.height);
g.fillRect(obstacle.x,obstacle.y,obstacle.width,obstacle.height);
g.fillRect(obstacle2.x,obstacle2.y,obstacle2.width,obstacle2.height);
g.fillRect(obstacle3.x,obstacle3.y,obstacle3.width,obstacle3.height);
g.fillRect(obstacle4.x,obstacle4.y,obstacle3.width,obstacle4.height);
g.fillRect(obstacle5.x,obstacle5.y,obstacle5.width,obstacle5.height);
//set the starting line color to white
g.setColor(Color.WHITE);
//now draw the starting line
g.fillRect(lineO.x,lineO.y,lineO.width,lineO.height);
g.fillRect(lineI.x,lineI.y,lineI.width,lineI.height);
//set the color of the finish line to yellow
g.setColor(Color.YELLOW);
//now draw the finish line
g.fillRect(finish.x,finish.y,finish.width,finish.height);
//set the color to blue for p1
g.setColor(Color.WHITE);
//now draw the actual player
g.fill3DRect(p1.x,p1.y,p1.width,p1.height,true);
//draw the images for the player
if(p1Direction==UP)
g.drawImage(img1,p1.x,p1.y,this);
if(p1Direction==LEFT)
g.drawImage(img2,p1.x,p1.y,this);
if(p1Direction==RIGHT)
g.drawImage(img3,p1.x,p1.y,this);
}
};
panel.setPreferredSize(new Dimension(950,600));
this.add(panel);
pack();
Move1 move=new Move1();
move.start();
}
private class Move1 extends Thread implements KeyListener
{
public void run()
{
//now, this should all be in an infinite loop, so the process
//repeats
addKeyListener(this);
while(true)
{
//now, put the code in a try block. This will let the
//program exit
//if there is an error.
try
{
//increase speed a bit
// if(p1Speed<=5)
// p1Speed+=.2;
//p1.y-=(int) p1Speed;
if(p1.intersects(left) || p1.intersects(right) || p1.intersects(top) ||
p1.intersects(bottom) || p1.intersects(obstacle) || p1.intersects(obstacle2)||
p1.intersects(obstacle3) || p1.intersects(obstacle4) || p1.intersects(obstacle5))
{
p1Speed = -5;
}
//if the car hits the center, do the same as above
//but make the speed -2.5.
if(p1.intersects(center))
{
p1Speed = -2.5;
}
//increase speed a bit
if(p1Speed<=5)
p1Speed+=.2;
//these will move the player based on direction
if(p1Direction==UP)
{
p1.y-=(int)p1Speed;
}
if(p1Direction==DOWN)
{
p1.y+=(int)p1Speed;
}
if(p1Direction==LEFT)
{
p1.x-=(int)p1Speed;
}
if(p1Direction==RIGHT)
{
p1.x+=(int)p1Speed;
}
panel.repaint();
//this delays the refresh rate:
Thread.sleep(200);
}
catch(Exception e)
{
//if there is an exception (an error), exit the loop.
break;
}
}
}
#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 event) {
if(event.getKeyChar()=='a')
{
p1Direction = LEFT;
}
if(event.getKeyChar()=='s')
{
p1Direction = DOWN;
}
if(event.getKeyChar()=='d')
{
p1Direction = RIGHT;
}
if(event.getKeyChar()=='w')
{
p1Direction = UP;
}
}
}
//this starts the program by calling the constructor:
public static void main (String[ ] args)
{
new MAP();
}
}

Uncomment super.paint(g) [line 87] in your paint method.
It is responsible for clearing the canvas of any stale objects.

The reason is that in the line g.fillRect(0,0,WIDTH,HEIGHT); it actually is referring to java.awt.image.ImageObserver#WIDTH and java.awt.image.ImageObserver#HEIGHT instead of your instance variables. You can see this with any IDE.
Because of that the expected black background is painted only in a 1x2 pixel area in the top-left corner. And since the call to super.paint(g); is commented out, not even the gray background is repainted. As a result, old drawings of the car are not overdrawn.
The code needs to be changed to use MAP.this.WIDTH, or the WIDTH field needs to be renamed to something which does not conflict with the fields inherited from JPanel, or the field needs to be moved into the same JPanel to have higher precedence, or you could also use the getWidth() method from JPanel. And likewise for height.

Related

Java, Imported Images flickering even after double buffer (JFrame)

After using a double buffer which I will show below after using imported images they still occasionally flicker. The flickering occurs only in the animated GIF sprites and not in solid tiles such as the ground of the program. I thought it may be the fact that when changing image from a standing position to the moving position of the player there is a moment with no image so it disappears but that cannot be right since the player flickers even when not changing image and just moving.
Base code of the program (compressed a lot of it and removed a bunch for simplicity of reading) :
import javax.swing.*;
import java.awt.*;
public class FrontHand extends JFrame implements Runnable{
public static void main(String []args){
// Start Main Thread
FrontHand Thread1 = new FrontHand();
Thread1.run();
}
// Define Frame Properties
private FrontHand(){
ImageImport.main();
setSize(1600, 900);
setResizable(false);
setFocusable(true);
setVisible(true);
requestFocus();
addKeyListener(new AL());
addMouseListener(new ML());
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
}
// Frame Double Buffer
public void paint(Graphics g){
Image dbImage = createImage(getWidth(), getHeight());
Graphics dbg = dbImage.getGraphics();
paintComponents(dbg);
g.drawImage(dbImage, 0, 0, this);
}
// Call paint functions
public void paintComponents(Graphics g){
// draw GUI
InVar.GUI.paintIcon(this, g, 0, 0);
// draw Ground Tiles
for (int i = 0; i != 10; i++) {
for (int n = 0; n != 22; n++) {
InVar.grass_tile.paintIcon(this, g, n * 62 + 118, 106 + i * 62);
// g.drawRect(n * 62 + 118, 106 + i * 62, 62, 62);
}
}
// Draw Player
InVar.player.paintIcon(this, g, InVar.player_x, InVar.player_y);
repaint();
}
// player movement
private void move(){PRETEBD THERE IS ADDITION AND SUBTRACTION TO THE PLAYER X AND Y HERE}
// check if there is any tiles left to move too and if null then redefine as non moving
if (InVar.p_m_x_counter == 0 && InVar.p_m_y_counter == 0){
InVar.player_moving = false;
// change the sprite of the player to the corresponding stationary one to the current player's sprite
if (InVar.player == InVar.player_m_up){
InVar.player = InVar.player_s_up;
}
else if (InVar.player == InVar.player_m_down){
InVar.player = InVar.player_s_down;
}
else if (InVar.player == InVar.player_m_left){
InVar.player = InVar.player_s_left;
}
else if (InVar.player == InVar.player_m_right){
InVar.player = InVar.player_s_right;
}
}
else{
InVar.player_moving = true;
}
}
#Override
public void run(){
while (InVar.game_running){
try{
Thread.sleep(5);
move();
}catch (InterruptedException e){System.out.println("Interrupted Exception Caught, ignore");}
}
}
}
The code that is used to import images :
ImageIcon a_1 = new ImageIcon(FrontHand.class.getResource("/Sprites/Tiles/GrassTile1.jpg"));
a_1.setImage(a_1.getImage());
InVar.grass_tile = a_1;
Before I was using .getScaledInstance for the animated GIF's which is what I also thought was causing the flickering but not using it and just externally changing the size of them did not fix the issue of the flickering.

Java robot class - getting Pixel color after they're painted

I need to create a colorPicker tool for my little ms paint app.
I originally asked how to switch from my Graphics 2D implementation to a Graphics2D-->BufferedImage one, (and then it would be easy to get the pixels) but I have instead been suggested to get the pixel colors thought the robot class.
First of all, here's my MCEVE: NB. It cannot be a single class, it won't save.
import java.awt.*;
import javax.swing.*;
public class Runner {
public static void main(String[] args){
JFrame Maiframe = new JFrame("Paint");
Canvas DrawingBoard = new Canvas();
Maiframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Maiframe.setSize(700, 500);
Maiframe.add(DrawingBoard);
Maiframe.setVisible(true);
}
}
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionAdapter;
public class Canvas extends JPanel {
public int xp; //present x
public int yp; //present y
public int xo; //old x
public int yo; //old y (Drawing from starting to new point as mouse drags)
public Canvas(){
super();
addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
xo = e.getX();
yo = e.getY();
Color col = RGBFinder();
System.out.println("RGB : Red =" + col.getRed() + "Green" + col.getGreen() + "Blue" + col.getRed());
}
});
addMouseMotionListener(new MouseMotionAdapter() { //get coords as mouse drags
#Override
public void mouseDragged(MouseEvent e) {
xp = e.getX();
yp = e.getY();
if(SwingUtilities.isLeftMouseButton(e))
repaint(); //call paintcomponent
}
public void mouseMoved(MouseEvent e1){ //keep trak of coords when mouse is not dragging
xo = e1.getX();
yo = e1.getY();
}
});
}
public void draw(int x, int y, Graphics g){ //draw the line
if(xo != 0)
g.drawLine(xo, yo, x, y);
xo = x; //old x is now present x and so on
yo = y;
}
public void paintComponent(Graphics g){
super.paintComponent(g);
draw(xp, yp, g);
}
}
public Color RGBFinder(){
try{
robot = new Robot();
}
catch(AWTException e){
System.out.println("Could not create color picker robot");
}
PointerInfo pi = MouseInfo.getPointerInfo();
Point p = pi.getLocation();
Color pixelColor = robot.getPixelColor(p.x, p.y);
//also tried robot.getPixelColor(p.getX(), p.getY());
//also tried to pass coordinates from listener to RGBFinder, and use those, no luck. (event.getX() ...)
return pixelColor;
}
And it works just fine.
I needed to implement something to get the color from any pixel, when the mouse clicks.
I did this: (adding this method to Canvas, and calling it from the mouse clicker listener)
public Color RGBFinder(){
try{
robot = new Robot();
}
catch(AWTException e){
System.out.println("Could not create color picker robot");
}
PointerInfo pi = MouseInfo.getPointerInfo();
Point p = pi.getLocation();
Color pixelColor = robot.getPixelColor(p.x, p.y);
//also tried robot.getPixelColor(p.getX(), p.getY());
//also tried to pass coordinates from listener to RGBFinder, and use those, no luck. (event.getX() ...)
return pixelColor;
}
Example of call:
//replace old mouseListener with this
addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
xo = e.getX();
yo = e.getY();
Color col = RGBFinder();
System.out.println(" da tela Red =" + col.getRed() + "Green" + col.getGreen() + "Blue" + col.getRed());
}
});
Unfortunately, from this implementation I get undefined behaviour. The color read is always 255, 255, 255. Exept if I color the hole panel, then it gets it right 9 times out of 10, but in some areas it's still missing it.
I have also tried wrapping the whole thing into a bufferedImage with robot#screenCap but that doesn't even remotely work.
What am I doing wrong here?
Thank you very much.
EDIT1:
There are doubts as to how a line can remain on screen after a second one has been drawn. I'll provide a screenshot:
NBB. This works because an instance of Canvas is create inside of a JFrame into Runnable, so the changes are saved, avoiding the need for shapes and arrayLists.
I'll also add a full version of the code which prints wrong RGB results, remember that this does not save the lines as it stands. Please refer to the two separate classes above for testing.
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionAdapter;
public class Canvas extends JPanel{
public int xp; //present x
public int yp; //present y
public int xo; //old x
public int yo; //old y (Drawing from starting to new point as mouse drags)
public Robot robot;
public static void main(String[] args){
JFrame Maiframe = new JFrame("Paint");
Canvas DrawingBoard = new Canvas();
Maiframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Maiframe.setSize(700, 500);
Maiframe.add(DrawingBoard);
Maiframe.setVisible(true);
}
public Canvas(){
super();
addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
xo = e.getX();
yo = e.getY();
Color col = RGBFinder();
System.out.println("RGB --> Red =" + col.getRed() + "Green" + col.getGreen() + "Blue" + col.getRed());
}
});
addMouseMotionListener(new MouseMotionAdapter() { //get coords as mouse drags
#Override
public void mouseDragged(MouseEvent e) {
xp = e.getX();
yp = e.getY();
if(SwingUtilities.isLeftMouseButton(e))
repaint(); //call paintcomponent
}
public void mouseMoved(MouseEvent e1){ //keep trak of coords when mouse is not dragging
xo = e1.getX();
yo = e1.getY();
}
});
}
public void draw(int x, int y, Graphics g){ //draw the line
if(xo != 0)
g.drawLine(xo, yo, x, y);
xo = x; //old x is now present x and so on
yo = y;
}
public void paintComponent(Graphics g){
super.paintComponent(g);
draw(xp, yp, g);
}
public Color RGBFinder(){
try{
robot = new Robot();
}
catch(AWTException e){
System.out.println("Could not create color picker robot");
}
PointerInfo pi = MouseInfo.getPointerInfo();
Point p = pi.getLocation();
Color pixelColor = robot.getPixelColor(p.x, p.y);
//also tried robot.getPixelColor(p.getX(), p.getY());
//also tried to pass coordinates from listener to RGBFinder, and use those, no luck. (event.getX() ...)
return pixelColor;
}
}
my little ms paint app
Well its not much of a paint app. All it does is draw a single line. Whenever you attempt to draw the second line the first will be removed.
So the first step you need to do is decide how you want the painting to work. There are two common approaches:
Store Objects you want to paint in an ArrayList and then the paintComponent(...) method will paint each Object in the List.
Paint directly to a BufferedImage and then the paintComponent(...) method can just paint the BufferedImage.
Check out Custom Painting Approaches for working examples of both of these approaches and give the pros/cons of using each approach.
I have instead been suggested to get the pixel colors thought the robot class
It depends which painting approach you want to use.
If you use the Draw on Component approach then you would use the MouseInfo and Robot to get the pixel color:
PointerInfo pi = MouseInfo.getPointerInfo();
Point p = pi.getLocation();
System.out.println( robot.getPixelColor(p.x, p.y) );
If you use the Draw on Image approach then you would get the pixel color from the BufferedImage:
int rgb = bufferedImage.getRGB(mouseEvent.getX(), mouseEvent.getY());
Color color = new Color( rgb );
System.out.println( color );
Final Update
You still have not posted a SSCCE. The code you posted does NOT draw a line. Even if it did draw a line, how do you expect us to click (with accuracy) a single pixel line.
The point of a SSCCE is to demonstrate the concept you are asking about. You are asking how to get the Color of a pixel on your panel. How the drawing gets on the panel is irrelevant to the question so the painting code should be as simple as possible.
Following is a proper SSCCE. Note:
The createAndShowGUI() and main() methods will be the same for all SSCCE. The difference is the `DrawingPanel code/class will change to demonstrate your problem.
The custom painting is hardcoded. There is no need for mouseMoved/mouseDragged logic (unless that is the problem) you are trying to solve. All you care about is having different colors to click on.
Just use a simple System.out.println(...) to display the value of the Color object.
All I did was copy the relevant pieces of code from you class and remove the irrelevant code to keep the code simple and straight forward. Anybody can do that.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class DrawingCanvas extends JPanel
{
private Robot robot;
public DrawingCanvas()
{
addMouseListener(new MouseAdapter()
{
#Override
public void mouseClicked(MouseEvent e)
{
try
{
robot = new Robot();
}
catch(Exception re) { System.out.println(re); }
PointerInfo pi = MouseInfo.getPointerInfo();
Point p = pi.getLocation();
Color pixelColor = robot.getPixelColor(p.x, p.y);
System.out.println(pixelColor);
}
});
}
#Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
g.setColor( Color.RED );
g.fillRect(0, 0, 40, 40);
g.setColor( Color.GREEN );
g.fillRect(40, 40, 40, 40);
g.setColor( Color.BLUE );
g.fillRect(80, 80, 40, 40);
}
private static void createAndShowGUI()
{
JPanel panel = new DrawingCanvas();
JFrame frame = new JFrame("DrawingCanvas");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(panel);
frame.setSize(200, 200);
frame.setLocationByPlatform( true );
frame.setVisible( true );
}
public static void main(String[] args)
{
EventQueue.invokeLater( () -> createAndShowGUI() ); // Java 8 only
/*
EventQueue.invokeLater(new Runnable()
{
public void run()
{
createAndShowGUI();
}
});
*/
}
}
Just copy/paste/compile/execute to see that the code works.
I'll let you figure out why your code doesn't appear to work.
NBB. This works because an instance of Canvas is create inside of a JFrame into Runnable, so the changes are saved, avoiding the need for shapes and arrayLists.
That statement is completely wrong. Painting done with the Graphics Object in the paintComponent() method is only temporary until the next time the paintComponent() method is invoked.
For example add the following code after the frame.setVisible() statement:
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
Graphics g = panel.getGraphics();
g.setColor( Color.YELLOW );
g.fillRect(120, 120, 40, 40);
}
});
The yellow square will disappear when the frame is resized. For permanent painting you need to use one of the two approaches I suggested in my original answer.
Edit 2:
This is the output I get when I click on the red, green, blue, background respectively:
C:\Java>java DrawingCanvas
java.awt.Color[r=255,g=0,b=0]
java.awt.Color[r=0,g=255,b=0]
java.awt.Color[r=0,g=0,b=255]
java.awt.Color[r=238,g=238,b=238]

Java - Pac-Man - GUI - Drawing Graphics issue, and general tips for an aspiring programmer

I am making Pac-Man and I'm having trouble with drawing graphics on a frame, when i draw my point image it looks like a game of snake, i tried putting my drawing methods for background and char both in the render method, but than my point image flickers
What it currently looks like, feel free to ignore the random face it was an inside joke.
Also this is my very first game so any tips on structure, pointers on what I am doing right (if anything) and what I'm doing wrong, and general tips would be extremely helpful!
Also I am aware that i have a couple unused methods
Code:
package game;
import graphics.map;
import java.awt.BorderLayout;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JFrame;
public class main extends Canvas implements Runnable{
private static final long serialVersionUID = 1L; //not sure why it wanted me to do this, maybe ask bender, or just google it later
public static boolean running = false;
public static int HEIGHT = 800;
public static int WIDTH = 600;
public static int posX = 50;
public static int posY = 50;
public static final String name = "Pac Man Alpha 1.4";
private static final double speed = 1.2;
public input input;
static BufferedImage background = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);;
static BufferedImage pacman = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);;
static BufferedImage settingsBackground = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);;
static BufferedImage level1 = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);;
static BufferedImage level2 = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);;
static BufferedImage points = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);;
static BufferedImage point = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);;
static JFrame frame;
private input keypress = new input();
private map map;
private static boolean charLoaded = false;
public static boolean MAIN_MENU = true;
public static boolean GAME = false;
public static boolean level1test = true;
public static boolean level2test = false;
public static boolean level3test = false;
public static boolean level4test = false;
static boolean drawn = false;
public static boolean key_down;
public static boolean key_up;
public static boolean key_right;
public static boolean key_left;
//private Screen screen;
JButton startButton = new JButton("Start"); //Start
JButton settingsButton = new JButton("Settings"); //Settings
JButton exitButton = new JButton("Exit"); //Exit
public main()
{
setMinimumSize(new Dimension(WIDTH , HEIGHT ));
setMaximumSize(new Dimension(WIDTH , HEIGHT )); // keeps the canvas same size
setPreferredSize(new Dimension(WIDTH, HEIGHT));
frame = new JFrame(name);
if(MAIN_MENU == true && GAME == false){
buttons(frame.getContentPane());
}
frame.setLayout(new BorderLayout());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // ends program on
// close
frame.addKeyListener(new input() );
frame.add(this, BorderLayout.CENTER);
frame.pack(); // keeps size correct
frame.setResizable(false);
frame.setVisible(true);
this.addKeyListener(keypress);
}
public static void main(String[] args)
{
try {
background = ImageIO.read(new File("res\\Background.png"));
pacman = ImageIO.read(new File("res\\pacmansprites.png"));
settingsBackground = ImageIO.read(new File("res\\Background.png"));
level1 = ImageIO.read(new File("res\\level1.png"));
//level2 = ImageIO.read(new File("res\\level2.png"));
point = ImageIO.read(new File("res\\Points for pacman.png"));
} catch (IOException e) {
}
running = true;
new main().start();
}
public void run()
{
long lastTime = System.nanoTime();
double nsPerTick = 1000000000 / 60D;
long lastTimer = System.currentTimeMillis();
double delta = 0;
int frames = 0;
int ticks = 0;
while (running == true) {
long now = System.nanoTime();
delta += (now - lastTime) / nsPerTick;
lastTime = now;
boolean render = false;
while (delta >= 1) {
ticks++;
tick();
delta -= 1;
render = true;
}
try {
Thread.sleep(3); //keep the Frames from going to high
} catch (InterruptedException e) {
e.printStackTrace();
}
if(render == true){
frames++;
render();
}
if (System.currentTimeMillis() - lastTimer >= 1000) {
lastTimer +=1000;
//System.out.println("Frames: " + frames + " Ticks: " + ticks);
frames = 0;
ticks = 0;
}
}
}
public synchronized void start()
{
new Thread(this).start();
run();
}
public synchronized void stop()
{
running = false;
}
public void tick()
{
if (key_up) posY -= speed / 2;
if (key_down) posY += speed;
if (key_left) posX -= speed / 2;
if (key_right) posX += speed;
}
public void render()
{
drawn = false;
if(MAIN_MENU == false && GAME == true)
{
drawMap();
drawChar();
}
else if(MAIN_MENU == false && GAME == false) {
Graphics g = getGraphics();
{
g.drawImage(settingsBackground,0,0,getWidth(),getHeight(),null);
g.dispose();
}
} else {
Graphics g = getGraphics();{
g.drawImage(background,0,0,getWidth(), getHeight(),null);
g.dispose(); //kill it
}
}
}
public void drawMap(){
if(level1test == true){
Graphics g = getGraphics();
{
g.drawImage(level1,0,0,getWidth(),getHeight(),null);
g.dispose();
}
}
if(level2test == true && drawn == false){
Graphics g = getGraphics();
{
g.drawImage(level2,0,0,getWidth(),getHeight(),null);
}
g.dispose();
}
drawn = true;
}
public void drawChar(){
//drawMap();
Graphics g = getGraphics();{
g.drawImage(point,posX,posY,20, 20,null);
g.dispose();
revalidate();
}
}
public void begin() {
if (key_up) System.out.println("up");
if (key_down) System.out.println("down");
if (key_left) System.out.println("left");
if (key_right) System.out.println("right");
}
public void loadMap(){
if(!drawn && level1test){
}else if(!drawn && level2test){
//draw 2nd map here
}else if(!drawn && level3test){
//draw 3rd map here
}
}
public void buttons(Container pane)
{
pane.setLayout(null);
startButton.addActionListener( new ActionListener() {
public void actionPerformed(ActionEvent ae) {
MAIN_MENU = false;
GAME = true;
frame.remove(startButton);
frame.remove(settingsButton);
frame.remove(exitButton);
frame.revalidate();
drawMap();
System.out.println("Start Button Clicked");
}
} );
settingsButton.addActionListener( new ActionListener() {
public void actionPerformed(ActionEvent ae) {
MAIN_MENU = false;
GAME = false;
frame.remove(startButton);
frame.remove(settingsButton);
frame.remove(exitButton);
frame.revalidate();
frame.repaint();
System.out.println("Settings Button Clicked");
}
} );
exitButton.addActionListener( new ActionListener() {
public void actionPerformed(ActionEvent ae) {
System.out.println("Exit Button Clicked");
System.exit(0);
}
} );
pane.add(startButton);
pane.add(settingsButton);
pane.add(exitButton);
Insets insets = pane.getInsets();
Dimension size = startButton.getPreferredSize();
startButton.setBackground(new Color(0, 0, 0));
startButton.setForeground(Color.CYAN);
startButton.setFocusPainted(false);
startButton.setFont(new Font("Calabri", Font.BOLD, 16));
settingsButton.setBackground(new Color(0, 0, 0));
settingsButton.setForeground(Color.RED);
settingsButton.setFocusPainted(false);
settingsButton.setFont(new Font("Calabri", Font.BOLD, 16));
exitButton.setBackground(new Color(0, 0, 0));
exitButton.setForeground(Color.YELLOW);
exitButton.setFocusPainted(false);
exitButton.setFont(new Font("Calabri", Font.BOLD, 16));
startButton.setBounds((WIDTH - 125) + insets.left, 10 + insets.top,
size.width + 50, size.height + 10);
settingsButton.setBounds((WIDTH - 125) + insets.left, 55 + insets.top,
size.width + 50, size.height + 10);
exitButton.setBounds((WIDTH - 125) + insets.left, 100 + insets.top,
size.width + 50, size.height + 10);
}
}
getGraphics is not how custom painting is done. You should, in your case, override the paint method, and make sure you call super.paint before doing any custom painting.
getGraphics returns the Graphics context last used to paint the component, which could be discarded on the next paint cycle, be null or no longer used by the component
Remember, painting uses the "painters canvas" approach, that is, just like painting in a physical canvas, when you paint into it, you paint over what was previously there, but not erasing it.
Now, if you override paint, you will find that you will have a flickering problem. This is because Canvas
is not double buffered
To solve this, you should consider user a BufferStrategy, which allows you to not only generate multiple buffers to paint to, but also to take control of the paint process itself
Just don't forget to clear each buffer before you paint to it...
Double buffering is the trick that allows you to have flicker-free animation. Basically you have two representations of your canvas, one that's currently being displayed and one that you can draw on. If you're finished with drawing, you copy the draw-canvas over the display-canvas. Depending on system and hardware there are more elegant ways where you can just tell the hardware to switch canvases (page flipping).
Without double buffering or a similar techniques, it is almost impossible to have flicker-free animation.
With double buffering you can afford to draw the background and then the foreground sprites. It is possibly more efficient to draw only those parts of the background that have been destroyed by the foreground sprites (there are various techniques for that as well, including of taking a snapshot image of the affected areas before you paint the sprites).
You can find a simple example for Java double buffering here. Java's BufferStrategy is a more complex solution that can use hardware features for page flipping.
I think the problem is that you only draw onto the image background, never erasing the old drawing from your image. You will need to clear the area and then start drawing in order to get your desired results.
I have never attempted to make a game but when I do simple animations I usually will do them on a JFrame or JPanel. With a JFrame you can Override the paint() method and with a JPanel, the paintComponent() method. It helps to keep everything that I'm drawing centralized, which makes it much easier for me to modify my code. When you call the respective super method in your overridden method, it will start you off with a clean slate, meaning you will have to paint the (image) background and your characters all over again. Calling the super method is also necessary to paint that component's children if you decide to add anything onto the JFrame/JPanel.
If you chose to use one of the above then I would recommend a JPanel due to it offering double buffering, which will help make your animations look smooth/fluid. Also, do not forget to call repaint();.
Here is a quick example, which can be used to duplicate your issue if you comment out super.paintComponent(g);.
*Note that I am extending and using a JPanel for this example.
Code:
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Trial extends JPanel{
public static void main(String[] args)
{
new Trial();
}
int x = 5; // will represent the x axis position for our crude animation.
javax.swing.Timer timer = new javax.swing.Timer( 500, new ActionListener(){
// Timer used to control the animation and
// the listener is used to update x position and tell it to paint every .5 seconds.
#Override
public void actionPerformed(ActionEvent e) {
x += 5;
if ( x > 250)
timer.stop();
repaint(); // will call the paintComponent method.
}
});
Trial()
{
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.add(this);
frame.setSize(300, 200);
frame.setVisible(true);
timer.start();
}
#Override
public void paintComponent(Graphics g)
{
super.paintComponent(g); // calling the super paintComponent method to paint children. can comment it
// out to duplicate your error, which happens when the frame isn't "refreshed".
Graphics2D g2d = (Graphics2D) g.create(); // creating a copy of the graphics object. // I do this to not alter the original
// Good practice and also Graphics2D
// offers a bit more to work with.
g2d.drawString("Graphics", x, 60); // painting a string.
g2d.drawRect(x, 80, 10, 10); // painting a rectangle.
}
}
Edit:
If you have a bunch of stuff to do and don't want to add it all into your paintComponent(); method you could create a method for various things and call them from inside your Overriden paint method, you could also pass them your graphics object. It will help you keep things relatively simple.

Draw in my JPanel calling a function in the "main"

I have an informatic project with JAVA langage for class and it's rated to graduate from high school.
Btw my program consists in drawing geometrical forms in the JPanel with clic control but I don't know how to put, in my main program, fonctions which draw figures as I want like drawSquare(x,y,length). For the moment the program show this window (it's a JFrame with my JPanel inside):
http://i.imgur.com/YetG3VB.png
I have a method readClick() which give to a Point point the coordinates point.x and point.y in the frame but I don't know how, in my main, I can do to call a graphical drawing.
"My problem is that I want to put in my main program something like
Point clic;
clic= Fenetre.readClick() ; // I have this method which wait me to clic on the frame
x = clic.x ; //and give to point the coordonates
y= clic.y; // point.x && point.y
clic = Fenetre.readClick();
a = clic.x ;
b = clic.y ;
"Function which draws rectangle for example"(x,y,a,b);
//It's this fonction I want to create and
// I want it to draw the rectangle in the JPanel
But I don't know how to make the function which adds a drawing in the JPanel "
My main program :
public class Geogebra {
#SuppressWarnings("unused")
public static void main(String args[]){
Fenetre fen = new Fenetre();
}}
My window class :
import java.awt.Color;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.awt.geom.Rectangle2D;
import java.util.concurrent.SynchronousQueue;
import javax.swing.JFrame;
#SuppressWarnings({ "unused", "serial" })
public class Fenetre extends JFrame {
static Panneau component = null;
private final static SynchronousQueue<MouseEvent> clicks = new SynchronousQueue<MouseEvent>();
public Fenetre(){
JFrame frame = new JFrame();
component = new Panneau();
frame.setTitle("ISNOGEBRA");
frame.setSize(900, 700); // Taille initiale de la fenetre : 900 * 700
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setContentPane(component);
frame.setVisible(true);
component.addMouseListener( new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
clicks.offer(e);
}
});
}
public static MouseEvent readMouse() {
try {
return clicks.take();
}
catch (InterruptedException e) {
throw new AssertionError();
}
}
public static Point readClick() {
return readMouse().getPoint();
}
}
My JPanel class (the two class Mathwrapper and Menu just draw the interface, I'll show them if needed but it's really long) :
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Shape;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.awt.geom.Rectangle2D;
import java.util.concurrent.ConcurrentLinkedQueue;
import javax.swing.JPanel;
#SuppressWarnings({ "serial", "unused" })
public class Panneau extends JPanel implements MouseListener {
Menu menu;
MathWrapper mw;
public Panneau(){
super();
this.setBackground(Color.WHITE);
menu = new Menu(20, 20);
mw = MathWrapper.getInstance(0, 80);
this.setOpaque(true);
this.addMouseListener(this);
}
#Override
public void paintComponent(Graphics g){
menu.draw(g);
mw.draw(g);
}
public void mouseClicked(MouseEvent e) {
//That shows a blue square behind the icon in the menu I click on
//and draws a black one on the one which was selected
if((e.getX() > 20 && e.getX() < 60) && (e.getY()) > 20 && e.getY() < 60){
menu.btns[menu.activeTool].toggleClicked();
menu.btns[0].toggleClicked();
menu.activeTool = 0;
}else if((e.getX() > 80 && e.getX() < 120) && (e.getY()) > 20 && e.getY() < 60){
menu.btns[menu.activeTool].toggleClicked();
menu.btns[1].toggleClicked();
menu.activeTool = 1;
}else if((e.getX() > 140 && e.getX() < 180) && (e.getY()) > 20 && e.getY() < 60){
menu.btns[menu.activeTool].toggleClicked();
menu.btns[2].toggleClicked();
menu.activeTool = 2;
}else if((e.getX() > 200 && e.getX() < 240) && (e.getY()) > 20 && e.getY() < 60){
menu.btns[menu.activeTool].toggleClicked();
menu.btns[3].toggleClicked();
menu.activeTool = 3;
}else if((e.getX() > 260 && e.getX() < 300) && (e.getY()) > 20 && e.getY() < 60){
menu.btns[menu.activeTool].toggleClicked();
menu.btns[4].toggleClicked();
menu.activeTool = 4;
}
mw.setActiveTool(menu.activeTool);
this.repaint();
}
public void mouseEntered(MouseEvent e) {
}
public void mouseExited(MouseEvent e) {
}
public void mousePressed(MouseEvent e) {
}
public void mouseReleased(MouseEvent e) {
}
}
Please help me I've read plents of documents about JPanel and drawing but I still don't understand ..
If I understand your question, you basically want some function from which you can
wait for user interaction and get information about it
draw something to your window
(I'm ignoring right now that you want to do it from the main method, since I'm pretty sure you'll be happy to do it from another method as well)
Basically you are facing two obstacles in that project:
Drawing in most windowing systems is event driven, i. e. if the user puts the window to front, it has to know how to draw its current state
User interaction is also event driven, i. e. you will get callbacks when the user clicks.
The first obstacle is easy to solve: Create a BufferedImage somewhere that both your UI code and the function can access, and draw inside it. (BufferedImage has a createGraphics method you can use to draw inside the image's buffer). Then the paintComponent method just draws the image whenever somebody puts the window to foreground.
The second obstacle is a bit harder. Basically you'll need threading and synchronization for it. It used to be a lot of tweaking with wait and notify and synchronized calls up to Java 1.4, but since Java 1.5 the synchronization (for this special case) can be handled by BlockingQueue class. So your UI code waits (with MouseListener) for a mouse click and adds the coordinates (as a java.awt.Point) to BlockingQueue, and your UI code will just have to wait for the next point whenever it needs one. You will still have a bit of experience using multithreaded applications (so you should know how to start a Thread and that a Thread cannot interact directly with the UI), so depending on your experience of Java it may be a steep learning curve - but certainly doable.
EDIT: I see you are already using some kind of synchronization for the mouse events, so probably the only parts you still need is starting a thread and drawing to a BufferedImage instead of the real window itself.
EDIT2: Here is a very simplified example that shows you how you can draw to a BufferedImage from a second thread. It will ask for coordinates and colors from the console (standard input) and paint them to the image, which will show in the JPanel. It is your task to combine this example with what you already have to move the mouse position across etc.
import java.awt.*;
import javax.swing.*;
import java.awt.image.BufferedImage;
import java.util.Scanner;
public class BufferedImagePainting extends JFrame {
public static void main(String[] args) {
BufferedImage img = new BufferedImage(800, 600, BufferedImage.TYPE_3BYTE_BGR);
JPanel drawPanel = new DrawPanel(img);
new InteractionThread(img, drawPanel).start();
new BufferedImagePainting(drawPanel);
}
public BufferedImagePainting(final JPanel drawPanel) {
super();
setLayout(new GridLayout(1, 1));
add(drawPanel);
pack();
setVisible(true);
}
private static class DrawPanel extends JPanel {
private BufferedImage img;
public DrawPanel(BufferedImage img) {
this.img = img;
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(img, 0, 0, this);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(img.getWidth(), img.getHeight());
}
}
private static class InteractionThread extends Thread {
private BufferedImage img;
private JPanel drawPanel;
public InteractionThread(BufferedImage img, JPanel drawPanel) {
this.img = img;
this.drawPanel = drawPanel;
}
#Override
public void run() {
#SuppressWarnings("resource")
Scanner s = new Scanner(System.in);
while (true) {
System.out.println("Enter a draw color and a fill color, separated by spaces");
System.out.println("Enter colors as 6-digit hex number, i. e. 000000 = black, ffffff = white");
Color drawColor = new Color(Integer.parseInt(s.next(), 16));
Color fillColor = new Color(Integer.parseInt(s.next(), 16));
System.out.println("Enter coordinates in form x y width height, separated by spaces");
int x = s.nextInt();
int y = s.nextInt();
int w = s.nextInt();
int h = s.nextInt();
Graphics g = img.createGraphics();
g.setColor(fillColor);
g.fillRect(x, y, w, h);
g.setColor(drawColor);
g.drawRect(x, y, w, h);
g.dispose();
drawPanel.repaint();
}
}
}
}
You must set visibility of your JFrame. Try this in your main class.
public class Geogebra {
#SuppressWarnings("unused")
public static void main(String args[]){
Fenetre fen = new Fenetre();
fen.setVisible(true);
}}

My JFrame Flickers

I'm trying to make a simple java game -- driving a car through a track. I am conditioned by my teacher to use rectangles and stuff like that . My problem is when I use the method repaint() that my frame flickers. I have tried to put the repaint method just when the car changes direction, but it doesn't do any good. Any suggestions?
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.net.URL;
import javax.swing.JFrame;
#SuppressWarnings("serial")
public class MAP extends JFrame
{
//the URL and Img designed for the images
URL cLeft,cRight,cUp;
Image img1,img2,img3;
//these will keep track of each player’s speed:
double p1Speed =.5, p2Speed =.5;
//constant for the screen size and used for the drawing the terrain
final int WIDTH = 900, HEIGHT = 650;
//these are ints that represent directions:
final int UP = 0, RIGHT = 1, DOWN = 2, LEFT = 3;
//these will keep track of the player’s directions (default = up)
int p1Direction = 0;
//this is the rectangle for player 1’s (outer) car:
Rectangle p1 = new Rectangle(WIDTH/9,HEIGHT/2, WIDTH/30,WIDTH/30);
//draw the terrain
Rectangle left = new Rectangle(0,0,WIDTH/9,HEIGHT);
Rectangle right = new Rectangle((WIDTH/9)*9,0,WIDTH/9,HEIGHT);
Rectangle top = new Rectangle(0,0,WIDTH, HEIGHT/9);
Rectangle bottom = new Rectangle(0,(HEIGHT/9)*9,WIDTH,HEIGHT/9);
Rectangle center = new Rectangle((int)((WIDTH/9)*2.5),(int)((HEIGHT/9)*2.5), (int)((WIDTH/9)*5),(HEIGHT/9)*4);
//these obstacles will obstruct the path and make navigating harder
Rectangle obstacle = new
Rectangle(WIDTH/2,(int)((HEIGHT/9)*7),WIDTH/10,HEIGHT/9);
Rectangle obstacle2 = new
Rectangle(WIDTH/3,(int)((HEIGHT/9)*5),WIDTH/10,HEIGHT/4);
Rectangle obstacle3 = new
Rectangle(2*(WIDTH/3),(int)((HEIGHT/9)*5),WIDTH/10,HEIGHT/4);
Rectangle obstacle4 = new Rectangle(WIDTH/3,HEIGHT/9,WIDTH/30,HEIGHT/9);
Rectangle obstacle5 = new Rectangle(WIDTH/2,(int)((HEIGHT/9)*1.5),WIDTH/30,HEIGHT/4);
Rectangle finish = new Rectangle(WIDTH/9,(HEIGHT/2)-HEIGHT/9,(int)((WIDTH/9)*1.5),HEIGHT/70);
Rectangle lineO=new Rectangle(WIDTH/9,HEIGHT/2,(int)((WIDTH/9)*1.5)/2,HEIGHT/140);
Rectangle lineI = new Rectangle(((WIDTH/9)+((int)((WIDTH/9)*1.5)/2)),(HEIGHT/2)+(HEIGHT/10),(int)((WIDTH/9)*1.5)/2, HEIGHT/140);
//the constructor:
public MAP() {
//the following code creates the JFrame
super("Radical Racing");
setSize(WIDTH,HEIGHT);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
setResizable(false);
try {
cUp = this.getClass().getResource("carUp.jpg");
cLeft = this.getClass().getResource("carLeft.jpg");
cRight = this.getClass().getResource("carRight.jpg");
} catch(Exception e) {
}
//attach the URLs to the images
img1 = Toolkit.getDefaultToolkit().getImage(cUp);
img2 = Toolkit.getDefaultToolkit().getImage(cLeft);
img3 = Toolkit.getDefaultToolkit().getImage(cRight);
repaint();
Move1 m1 = new Move1();
m1.start();
}
//this will draw the cars and the race track
public void paint(Graphics g) {
super.paint(g);
//draw the background for the racetrack
g.setColor(Color.DARK_GRAY);
g.fillRect(0,0,WIDTH,HEIGHT);
//when we draw, the border will be green
g.setColor(Color.GREEN);
//fill rectangle
g.fillRect(left.x,left.y,left.width,left.height);
g.fillRect(right.x,right.y,right.width,right.height);
g.fillRect(top.x,top.y,top.width,top.height);
g.fillRect(bottom.x,bottom.y,bottom.width,bottom.height);
g.fillRect(center.x,center.y,center.width,center.height);
g.fillRect(obstacle.x,obstacle.y,obstacle.width,obstacle.height);
g.fillRect(obstacle2.x,obstacle2.y,obstacle2.width,obstacle2.height);
g.fillRect(obstacle3.x,obstacle3.y,obstacle3.width,obstacle3.height);
g.fillRect(obstacle4.x,obstacle4.y,obstacle3.width,obstacle4.height);
g.fillRect(obstacle5.x,obstacle5.y,obstacle5.width,obstacle5.height);
//set the starting line color to white
g.setColor(Color.WHITE);
//now draw the starting line
g.fillRect(lineO.x,lineO.y,lineO.width,lineO.height);
g.fillRect(lineI.x,lineI.y,lineI.width,lineI.height);
//set the color of the finish line to yellow
g.setColor(Color.YELLOW);
//now draw the finish line
g.fillRect(finish.x,finish.y,finish.width,finish.height);
//set the color to blue for p1
g.setColor(Color.WHITE);
//now draw the actual player
g.fill3DRect(p1.x,p1.y,p1.width,p1.height,true);
//draw the images for the player
if(p1Direction==UP)
g.drawImage(img1,p1.x,p1.y,this);
if(p1Direction==LEFT)
g.drawImage(img2,p1.x,p1.y,this);
if(p1Direction==RIGHT)
g.drawImage(img3,p1.x,p1.y,this);
}
private class Move1 extends Thread implements KeyListener {
public void run() {
//now, this should all be in an infinite loop, so the process
//repeats
addKeyListener(this);
while(true) {
//now, put the code in a try block. This will let the
//program exit
//if there is an error.
try {
//first, refresh the screen:
repaint();
//increase speed a bit
// if(p1Speed<=5)
// p1Speed+=.2;
//p1.y-=(int) p1Speed;
if(p1.intersects(left) || p1.intersects(right) || p1.intersects(top) || p1.intersects(bottom) || p1.intersects(obstacle) || p1.intersects(obstacle2)|| p1.intersects(obstacle3) || p1.intersects(obstacle4) || p1.intersects(obstacle5)) {
p1Speed = -5;
}
//if the car hits the center, do the same as above
//but make the speed -2.5.
if(p1.intersects(center)) {
p1Speed = -5;
}
//increase speed a bit
if(p1Speed<=5)
p1Speed+=.2;
//these will move the player based on direction
if(p1Direction==UP) {
p1.y-=(int)p1Speed;
//repaint();
}
if(p1Direction==DOWN) {
p1.y+=(int)p1Speed;
//repaint();
}
if(p1Direction==LEFT) {
p1.x-=(int)p1Speed;
//repaint();
}
if(p1Direction==RIGHT) {
p1.x+=(int)p1Speed;
//repaint();
}
//this delays the refresh rate:
Thread.sleep(200);
} catch(Exception e) {
//if there is an exception (an error), exit the loop.
break;
}
}
}
#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 event) {
if(event.getKeyChar()=='a') {
p1Direction = LEFT;
repaint();
}
if(event.getKeyChar()=='s') {
p1Direction = DOWN;
repaint();
}
if(event.getKeyChar()=='d') {
p1Direction = RIGHT;
repaint();
}
if(event.getKeyChar()=='w') {
p1Direction = UP;
repaint();
}
}
}
//this starts the program by calling the constructor:
public static void main (String[ ] args) {
new MAP();
}
}
Don't draw directly in the JFrame in its paint method. Instead draw in a JPanel or JComponent and override its paintComponent method since Swing does double buffering by default, and this will allow you to take advantage of this.
You need to buffer your drawing instead of drawing right on the frame. See this related question and also the API for BufferStrategy.
You can avoid the flickering on your graphical interface by using the Double Buffering Technique. Here is an article that gives one example of double buffering.
This part of the Java Tutorial also gives further advice and examples.

Categories