Why does my applet flash for every repaint? - java

I found some Java game code online and I am trying to modify it. I converted it from JFrame to Applet, but then my game started to blink every time I repaint screen. I tried double buffering but no difference.
Source:
private void paintDisks(Graphics g) {
try {
for (Disk d : disk)
paintDisk(g, d);
} catch (Exception ex) {
//System.out.println(ex.getMessage());
paintDisks(g); // retry so the disks never not get painted
}
}
private void paintDisk(Graphics g, Disk d) {
if (d == null)
return;
if (diskimg[d.player] == null) {
g.setColor(colour[d.player]);
g.fillOval((int)d.x - 1, (int)d.y - 1, 32, 32);
} else {
g.drawImage(diskimg[d.player],
(int)d.x - 1, (int)d.y - 1,
32, 32, this);
}
}
#Override
public void paint(Graphics g) {
// paint real panel stuff
super.paint(g);
Graphics gr;
if (offScreenBuffer==null ||
(! (offScreenBuffer.getWidth(this) == this.size().width
&& offScreenBuffer.getHeight(this) == this.size().height)))
{
offScreenBuffer = this.createImage(size().width, size().height);
}
gr = offScreenBuffer.getGraphics();
gr.clearRect(0,0,offScreenBuffer.getWidth(this),offScreenBuffer.getHeight(this));
// paint the disks
paintDisks(gr);
// paint the curser ontop of the disks
paintCurser(gr);
g.drawImage(offScreenBuffer, 0, 0, this);
}
#Override
public void run() {
while (true) {
repaint();
try {
Thread.sleep(9, 1);
} catch (InterruptedException ex) {
System.out.println(ex.getMessage());
}
}
}
}

Short answer: do not call super.paint() in your Board.paint() method.
Long answer: Applet is also a container with its own display properties including a background color which you set via setBackground(Color.WHITE); as part of your constructor. By invoking super.paint(g) you are causing the applet to paint its white background to the display graphics, as well as invoke any contained component painting. This is the cause of the flicker - each paint cycle, it is painting the on-screen display white then copying your offscreenBuffer image to the on-screen display.
Probably it is best to be explicit, forget about the Applet background, remove super.paint(g), and just do all the paint steps yourself. You'll need to replace clearRect() with setColor() and fillRect().
Also you should implement update() as well.
#Override
public void update(Graphics g) { paint(g); }
#Override
public void paint(Graphics g) {
// no super.paint(g)
if (offScreenBuffer==null ||
(! (offScreenBuffer.getWidth(this) == this.size().width
&& offScreenBuffer.getHeight(this) == this.size().height)))
{
offScreenBuffer = this.createImage(size().width, size().height);
}
Graphics gr = offScreenBuffer.getGraphics();
// blank the canvas
gr.setColor(Color.WHITE);
gr.fillRect(0,0,offScreenBuffer.getWidth(this),offScreenBuffer.getHeight(this));
// paint the disks
paintDisks(gr);
// paint the curser ontop of the disks
paintCurser(gr);
g.drawImage(offScreenBuffer, 0, 0, this);
}

Take a look at the game engine Bonsai from Ivo Wetzel. I like it a lot.
It uses BufferStrategy, which is, I think the best way to double buffer.

Related

Java JPanel doesnt get painted

I'm coding a simple top-down-shooter and I'm trying to render the graphics the active way so the JPanel doesn't get repainted by the OS and I can control the repainting.
I have a Level class which calls the render() with the x and y position and the BufferedImage of the level or entity in the Screen class (JPanel). My problem now is the the paintComponents() method in the Screen class never gets called. I have tried a couple of variants to fix the problem. I have also tried it with Canvas but either the entites started blinking or I got an Exception on createBufferStrategy(3). Anyway this is my source code now and I really don't know whats the problem now.
EDIT
Here is the important part of the code which is not working, repaint doesn't call paintComponent...
public void render(){
if(graphics != null){
graphics.dispose();
}
repaint();
}
public void paintComponent(Graphics g){
super.paintComponent(g);
g.drawImage(offScreen.getSubimage(0, 0, getWidth(), getHeight()), 0, 0, null);
g.dispose();
Toolkit.getDefaultToolkit().sync();
offScreen.flush();
}
public void render(int x, int y, BufferedImage image) {
graphics = offScreen.createGraphics();
graphics.drawImage(image, x, y, null);
// offScreenGraphics.dispose();
}
The problem is that paintComponent doesn't get called, repaint() calls nothing, the debugger just goes over it.
Canvas attempt
This is my attempt with Canvas, the problem there is that I can't create a bufferStrategy in the outcommented code. In the other render method it's working but its useless there.
public void render() {
// if (buffer == null) {
// createBufferStrategy(2);
// buffer = getBufferStrategy();
// }
Graphics g = buffer.getDrawGraphics();
g.drawImage(offScreen, 0, 0, null);
if (g != null) {
g.dispose();
}
if(!buffer.contentsLost()){
buffer.show();
}
}
public void render(int x, int y, BufferedImage image) {
if (buffer == null) {
createBufferStrategy(2);
buffer = getBufferStrategy();
}
Graphics g = offScreen.getGraphics();
g.drawImage(image, x, y, null);
}
I hope you can help me and thank you also for helping me.
If you have other improvements I would also like to hear about it.
Your render method on the JPanel should only update state, and call for a repaint. The painting will be done in paintComponent as a result of the call to repaint.

Swing double Buffering and Animation

I am trying to prevent redrawing an animation by the EDT. The first thing i have done is excluding the actual drawing tasks into a different thread, writing into a VolatileImage, which gets redrawn by EDT within paintComponent method of my corresponding JPanel.
If i exclude the repaint into another thread, this works properly. Nevertheless, i do have positioned a couple of other panels above my animation.
In result, having called the repaint method of my painter (animation) panel, has caused the others to also get redrawn without flickering.
Therefore to redraw the other panels, calling repaint on painter, results in flickering. Repaint of a single panel results in an opaque redraw with rarely flickering.
Does somebody know, how to synchronize an own repaint of a jpanel, for instance into my already available bufferimage. Id say the repaint triggered to EDT results in flickering, since its not synchronized.
My repaint call to animation
#Override
public void KeyframeChanged(Keyframe frame) {
if (painter.isVisible()) {
map.getMainMap().doPaintComponent(painter.getBuffer().getGraphics());
painter.renderAnimation();
painter.updateScreen();
}
}
painter methods:
public void updateScreen() {
Graphics g = this.getGraphics();
if (g != null) // component already visible?
{
// is there a backBuffer to draw?
if (backBuffer != null) {
g.drawImage(backBuffer, 0, 0, null);
} else {
// if not, create one and render on it
createBackBuffer();
renderAnimation();
}
}
}
public void renderAnimation() {
// Do drawing stuff here
}
#Override
protected void paintComponent(Graphics g) {
// super.paintComponent(g);
}// end of paint
Thanks
Thanks for answers and links. I still need to read a few of them. Nevertheless in order to illustrate the current behavior, this small SSCCE shall help.
package repaintexample;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.image.VolatileImage;
import javax.swing.JFrame;
import javax.swing.JLayeredPane;
import javax.swing.JPanel;
class Painter extends JPanel {
private VolatileImage backBuffer;
private Graphics2D g2d;
public Painter() {
setDoubleBuffered(false);
setOpaque(false);
}
#Override
public boolean isOptimizedDrawingEnabled() {
return false;
}
private void createBackBuffer() {
backBuffer = this.getGraphicsConfiguration().createCompatibleVolatileImage(1920, 1200);
}
public void adjustBackBufferSize() {
if (backBuffer != null) {
if (getWidth() > backBuffer.getWidth() || getHeight() > backBuffer.getHeight()) {
createBackBuffer();
}
}
}
public void updateScreen(Graphics g) {
if (g != null) // component already visible?
{
// is there a backBuffer to draw?
if (backBuffer != null) {
g.drawImage(backBuffer, 0, 0, null);
} else {
// if not, create one and render on it
createBackBuffer();
}
}
}
public void renderAnimation(int i, int j) {
if (backBuffer == null) {
createBackBuffer();
}
do {
if (backBuffer.validate(getGraphicsConfiguration()) == VolatileImage.IMAGE_INCOMPATIBLE) {
createBackBuffer();
}
g2d = (Graphics2D) backBuffer.getGraphics();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setColor(Color.white);
g2d.fillRect(0, 0, getWidth(), getHeight());
g2d.setColor(Color.red);
g2d.fillOval(i, j, 50, 50);
} while (backBuffer.contentsLost());
}
#Override
protected void paintComponent(Graphics g) {
// super.paintComponent(g);
updateScreen(g);
}// end of paint
public VolatileImage getBuffer() {
return backBuffer;
}
}
class ContainerFrame extends JFrame {
private Painter mapPainter;
private JPanel informationPanel; // covers a lot of metainformation - Actually own JTable instance updating the same objects for repainting in each circle
private JPanel controller; // Maptools
private JPanel tabbedPabe; // Change redraw content
public ContainerFrame() {
this.setSize(1600, 1024);
this.setVisible(true);
initComponents();
initPositions();
Thread animation = new Thread(new Runnable() {
#Override
public void run() {
// My application is a mapping application, in which i first draw the tiles, before goin on with the "real" animated stuff
// clearing backbuffer content with g.fillRect(0, 0, getWidth(), getHeight());
while (true) {
for (int i = 0; i < mapPainter.getWidth(); i += 100) {
for (int j = 0; j < mapPainter.getHeight(); j += 5) {
mapPainter.renderAnimation(i, j);
int repaintCase = 2;
switch (repaintCase) {
case 0:
// Default case redrawing via EDT, triggering the others in proper order
mapPainter.repaint();
break;
case 1:
// case repainting by current Thread - necessity of repainting above positioned panels
// results in flickering, since not synchronized
mapPainter.updateScreen(mapPainter.getGraphics());
informationPanel.repaint();
controller.repaint();
tabbedPabe.repaint();
break;
case 2:
// painting components on buffer
// Results in rarely flickering and opague repaint
// is there any common way, to manually repaint onto anything - like image
informationPanel.paintAll(mapPainter.getBuffer().getGraphics());
controller.paintAll(mapPainter.getBuffer().getGraphics());
tabbedPabe.paintAll(mapPainter.getBuffer().getGraphics());
mapPainter.updateScreen(mapPainter.getGraphics());
break;
}
}
}
try {
Thread.sleep(30);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
animation.start();
}
private void initComponents() {
mapPainter = new Painter();
mapPainter.setSize(this.getSize());
informationPanel = new JPanel();
informationPanel.setSize(new Dimension(360, 800));
controller = new JPanel();
controller.setSize(new Dimension(500, 250));
tabbedPabe = new JPanel();
tabbedPabe.setSize(new Dimension(300, 300));
this.getLayeredPane().add(mapPainter, JLayeredPane.DEFAULT_LAYER);
this.getLayeredPane().add(controller, JLayeredPane.MODAL_LAYER);
this.getLayeredPane().add(tabbedPabe, JLayeredPane.MODAL_LAYER);
this.getLayeredPane().add(informationPanel, JLayeredPane.MODAL_LAYER);
}
private void initPositions() {
controller.setLocation(mapPainter.getWidth() - controller.getWidth(), mapPainter.getHeight() - controller.getHeight());
tabbedPabe.setLocation(this.getWidth() - tabbedPabe.getWidth(), mapPainter.getHeight() - controller.getHeight() - tabbedPabe.getHeight() - 400);
informationPanel.setLocation(10, mapPainter.getHeight() - informationPanel.getHeight() - 200);
}
}
public class RepaintExample {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
// TODO code application logic here
ContainerFrame f = new ContainerFrame();
}
}
I do use case 0 at the moment and do see having either great or pretty bad fps - either 30 or around 6. I am not certain, how that may be possible and i may be able to find sth. in the already posted links. I thought making sure to relieve the EDT at best, could become a proper solution.
Additionally the content of the 3 panels, i illustrated do not need a repaint in the same frequency as the animation does. Unfortunately i haven't found a proper way to prevent the repaint. The only way i have used for quite a while was a paintimmediately in an invokelater call for those areas, which are known as "animated". A common repaint(Rectangle rec) has not been working, since single calls have been summarized to a big one, covering more pixels, than i have passed in.
public void drawCachedSprite(Graphics2D g, CachedSprites sprites, int zoom, double cog, double x, double y, double w, double h) {
try{
pos_x = x;
pos_y = y;
RenderingUtil.getRenderQuality();
transform.setToIdentity();
// Compute the corner, the drawing needs to start with
transform.translate(x - (w / 2.0), y - (h / 2.0));
g.drawImage(sprites.getSprite(DefaultResources.getType(), spriteColor, zoom, cog), transform, null);
} catch (IllegalArgumentException e) {
e.printStackTrace();
System.out.println("width or height not set properly");
}
}

How to tell when Graphics.drawImage() has actually completed

This is my first time asking a question on here, and I'm hoping I get an answer or an idea that will help me.
I am drawing a large image and scaling it down with drawImage(). I then immediately draw another image with drawImage() that I expect to be drawn on top of the previous one (second). The problem is that drawImage returns immediately, even if it takes ~50 ms to scale and render the first image. Most of the time the second image ends up underneath the first one because it's painted first while the big first one is being processed. Basically is there anyway to force drawImage() to block until it's done, or to somehow check when it has completed?
I'm aware of the ImageObserver parameter, which works fine when downloading an image from the Internet or something, but when using an already-loaded BufferedImage, it never fires ImageUpdate() just after scaling and drawing. Basically since the first image is already "loaded" it never contacts the ImageObserver, it just takes like ~50 ms in it's own thread to process, never notifying when it completes.
Does anyone know how to either force it to block or wait until it's completely done scaling and blitting an image? And obviously using Thread.sleep(xx) is a complete hack and not viable due to differences between computer speeds. All this rendering is happened on the Event thread inside the paint(Graphics g) method.
Thanks!
EDIT: The following is code I currently have to give you an idea of the issue:
public void paint(Graphics window)
{
window.setColor(Color.WHITE);
window.fillRect(0, 0, Settings.width * Settings.aaFactor, Settings.height * Settings.aaFactor);
Graphics2D window2D = (Graphics2D) window;
window2D.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
window2D.drawImage(this.image, 0, 0, Settings.width, Settings.height, null);
try
{
Thread.sleep(50);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
window2D.drawImage(this.image2, 0, 0, null);
repaint();
}
EDIT 2: To better explain the problem I'm talking about, I made some sample code that does better what I'm trying to explain. Run it and you will see it flickering where sometimes the first image is on bottom (like it's supposed to be), but most of the time it will be one top (second), which is wrong. Just change the File paths to a small image and a large image.
public class Main extends Applet implements ImageObserver
{
private BufferedImage imageA;
private BufferedImage imageB;
#Override
public void init()
{
try
{
this.imageA = ImageIO.read(new File("C:\\LargeImage.jpg"));
this.imageB = ImageIO.read(new File("C:\\SmallImage.jpg"));
}
catch (IOException e)
{
e.printStackTrace();
}
}
#Override
public void update(Graphics g)
{
paint(g);
}
#Override
public void paint(Graphics g)
{
Graphics2D w = (Graphics2D) g;
w.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
w.drawImage(this.imageA, 0, 0, 50, 50, this);// This takes a while to do (scaling down and drawing)...
w.drawImage(this.imageB, 10, 10, null);// While this is drawn quickly, before A is done.
repaint();
}
#Override
public boolean imageUpdate(Image img, int infoflags, int x, int y, int width, int height)
{
System.out.println("ImageObserver fired, done drawing image. NEVER CALLED!");
return false;
}
}
The last argument to drawImage (where you pass null) is an ImageObserver. If you provide your own implementation of that interface (see JavaDoc), you will be informed when the image has been actually drawn.
It is impossible to know when Swing will actually render the contents of a Graphics object to the screen. What is know is it won't happen until AFTER the paint methods return (as the Graphics object hasn't been finalised for rendering until it does).
What you should do is let the Component you are painting to make the decision as to when something needs to updated, this is the way it was designed...(Component implements ImageObserver)
The below example continuously re-scales the master background image as the frame is resized
public class TestPaint03 {
public static void main(String[] args) {
new TestPaint03();
}
public TestPaint03() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception ex) {
}
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new PaintPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class PaintPane extends JPanel {
private BufferedImage background;
private BufferedImage foreground;
private Image scaled;
public PaintPane() {
try {
background = ImageIO.read(new File("/path/to/background/image));
foreground = ImageIO.read(new File("path/to/foreground/image"));
} catch (Exception e) {
}
}
#Override
public void invalidate() {
scaled = null;
super.invalidate();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (background != null) {
if (scaled == null) {
int size = Math.min(getWidth(), getHeight());
scaled = background.getScaledInstance(-1, size, Image.SCALE_SMOOTH);
}
int x = (getWidth() - scaled.getWidth(this)) / 2;
int y = (getHeight() - scaled.getHeight(this)) / 2;
g.drawImage(scaled, x, y, this);
x = (getWidth() - foreground.getWidth()) / 2;
y = (getHeight() - foreground.getHeight()) / 2;
g.drawImage(foreground, x, y, this);
}
}
}
}
While I'm sure you have your reasons, personally I would avoid Applet in favor of JApplet and in fact, I would personally avoid applets or together. I started my career coding applets, they are simply a pain, especially when all you're trying to do is test an idea.

JTextField on Key Entered flashing black

I am making a game canvas using swing and decided to use JTextField's for the input of a username and password into the panel.
I am buffering an image then rendering it onto the screen instead of drawing everything directly onto the panel real-time.
I have ran into a problem though, I paint a background and have set both of my text fields to opaque, but it seems that whenever I go to enter something into those text field's it flashes a black box where the JTextField is.
It happens in both of my username and password fields. Any idea of what the cause of this could be?
Other helpful information: Whenever I click on a text box, both of the components flash black where the first character would be.
EDIT -- I just noticed that the login button I have also flashes black when MOUSE_ENTERED and MOUSE_EXIT.
public class GamePanel extends JPanel implements Runnable {
public GamePanel(int width, int height) {
this.pWidth = width;
this.pHeight = height;
setController(new LoginGameController(this));
setPreferredSize( new Dimension(pWidth, pHeight));
setBackground(Color.BLACK);
setFocusable(true);
requestFocus(); // the JPanel now has focus, so receives key events
// create game components
addMouseListener(this);
addKeyListener(this);
setLayout(null);
startGame();
}
private void startGame()
// initialise and start the thread
{ if (animator == null) {
animator = new Thread(this);
animator.start();
}
}
public void run() {
while(true) {
gameUpdate();
if(getGraphics() != null){
gameRender(); // render the game to a buffer
paintScreen(); // draw the buffer on-screen
}
try {
Thread.sleep(28);
} catch (InterruptedException e) {}
}
}
private void paintScreen() {
Graphics2D g = (Graphics2D) getGraphics();
if ((g != null) && (img != null))
g.drawImage(img, 0, 0, null);
Toolkit.getDefaultToolkit().sync();
g.dispose();
}
private void gameRender() {
if(getWidth() > 0 && getHeight() > 0)
img = createImage(getWidth(), getHeight());
if(img != null) {
Graphics2D g = (Graphics2D) img.getGraphics();
g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
g.setColor(Color.BLACK);
g.fillRect(0, 0, pWidth, pHeight);
getController().render(img);
paintComponents(img.getGraphics());
}
}
}
Here is text fields: (from a seperate class entirely calling to the GamePanel using getPanel()...)
//Setup Login fields
usernameTF = new JTextField();
usernameTF.setOpaque(false);
usernameTF.getCaret().setBlinkRate(0);
usernameTF.setForeground(Color.WHITE);
usernameTF.setBounds(USERNAME_FIELD);
usernameTF.setBorder(null);
getPanel().add(usernameTF);
passwordTF = new JPasswordField();
passwordTF.setOpaque(false);
passwordTF.getCaret().setBlinkRate(0);
passwordTF.setForeground(Color.WHITE);
passwordTF.setBounds(PASSWORD_FIELD);
passwordTF.setBorder(null);
getPanel().add(passwordTF);
loginBtn = new JButton();
loginBtn.setOpaque(false);
loginBtn.setBackground(null);
loginBtn.setBorder(null);
loginBtn.setBounds(LOGIN_BUTTON);
loginBtn.addMouseListener(getPanel());
getPanel().add(loginBtn);
Thanks!
The basic problem is, you circumventing Swings repaint process and not honoring the EDT when you up-date your graphics.
JComponent#getGraphics is a temporary/scratch buffer which will be re-draw on the next repaint. Also, if you didn't create the graphics, you shouldn't dispose it!
public void run() {
while(true) {
gameUpdate();
if(getGraphics() != null){
gameRender(); // render the game to a buffer
try {
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
paintScreen(); // draw the buffer on-screen
}
});
} catch (Exception exp) {
exp.printStackTrace(); // please clean this up
}
}
try {
Thread.sleep(28);
} catch (InterruptedException e) {}
}
}
I don't know if this will fix it, but it can't hurt. (This WILL effect you FPS and you should be taking into consideration how long it took to paint and how long you want to wait)
Alternativly, rather then calling paintScreen(), you could call repaint (or have paintScreen do it) and override the paintComponent method to paint your buffer.
This would allow Swing to resume control over the paint process properly.
A window or component has at least three ways to repaint.
on demand from the operating system when it has lost a part of the window buffer.
on demand from a library component when it has changed its state.
manually by manipulating its own frame buffer.
normally, the following pathway is active:
The operating system may request a particular rectangle to be updated. This is picked up by the toolkit. Additionally, a component may signal its change to the toolkit as well through its repaint method. The toolkit keeps collecting an merging incoming repaint requests for a while then asks the window to repaint a particular rectangle. The default action for the window is to paint itself by calling its paintComponent method where it doesn't overlap with solid children and then paint its components recursively.
If you do your own rendering, the toolkit is doing it as well. Since you didn't override your paintComponent, when this method runs, it acts as default. The default action is to do nothing. The toolkit then picks up the empty frame buffer and paints the button (which doesn't paint its background) over it.
You can disable the toolkit's rendering process and do all rendering yourself (grab a buffer, paint into it, then submit). You can call the setIgnoreRepaint(true) method to ignore the requests by OS.

How to use double Buffered AWT Animations in Java

I have recently begun working with double buffering in Java. I have read tutorials that have shown me how to display images and move them using mouse and keyboard events. However this is where I become confused. My program is simple, there is a rectangle at the bottom of my window that is movable by LEFT and RIGHT key events. However I can not figure out for the life of my how to draw another shape onto the screen by an event and continue buffering it.
I would like to be able to push a key to draw a "missile" (which in my case would be a small Oval) at the X and Y position of the rectangle I have drawn already, and have it fire upwards. Much like any classic space shooter.
This however is not as much of a specific, concrete problem of mine, but a concept I do not understand. I learned how to do many of the similar things in Lua, however when it came to drawing new images after initialization or an image upon key events, I was stumped.
My question is this: In what order of Java's init(), stop(), destroy(), start(), run(), paint(), and update() cycle do I use to buffer a new shape/image onto the screen from a key event?
I have searched many tutorials with example code, but with no avail. I have been learning Java for nearly 8 months now, but no matter how basic or simple I try to understand something, it's as if even the most primordial tutorial requires prerequisite knowledge.
My code is as follows.
import java.applet.*;
import java.awt.*;
public class SquareApplet extends Applet implements Runnable
{
int x_pos = 10;
int y_pos = 400;
int rectX = 50;
int rectY = 20;
int x_speed = 5;
private Image dbImage;
private Graphics dbg;
public void init( ) { }
//public void start() { }
public void stop( ) { }
public void destroy( ) { }
//public void run ( ) { }
//public void paint (Graphics g) { }
public void start()
{
// define a new thread
Thread th = new Thread (this);
// start this thread
th.start ();
}
public void run ()
{
// lower ThreadPriority
Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
// run a long while (true) this means in our case "always"
while (true) //Runtime
{
if (x_pos > this.getSize().width - rectX) {x_pos = this.getSize().width - rectX;}
if (x_pos < 0) {x_pos = 0 ;}
// repaint the applet
repaint();
try
{
// Stop thread for 20 milliseconds
Thread.sleep (20);
}
catch (InterruptedException beepis)
{
// do nothing
}
// set ThreadPriority to maximum value
Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
}
}
public void paint (Graphics g)
{
// set background color
g.setColor(Color.black);
g.fillRect(0,0,this.getSize().width,this.getSize().height);
// set player color
g.setColor (Color.white);
// paint a filled colored rectangle
g.fillRect(x_pos, y_pos, rectX,rectY );
}
public void update (Graphics g)
{
// initialize buffer
if (dbImage == null)
{
dbImage = createImage (this.getSize().width, this.getSize().height);
dbg = dbImage.getGraphics ();
}
// clear screen in background
dbg.setColor (getBackground ());
dbg.fillRect (0, 0, this.getSize().width, this.getSize().height);
// draw elements in background
dbg.setColor (getForeground());
paint (dbg);
// draw image on the screen
g.drawImage (dbImage, 0, 0, this);
}
//KEY EVENTS
public boolean keyDown(Event e, int key)
{
//Up Down Left Right
if (key == Event.LEFT)
{
x_pos -= x_speed;
}
if (key == Event.RIGHT)
{
x_pos += x_speed;
}
return true;
}
}

Categories