How do I make objects *not* move when I have animation? - java

In swing graphics, I need to make something where the stick figure moves back and forth, but something stays put. I'm using the blue horizontal line as a test. It doesn't move, but it disappears in time with the stick figure's sword. How do I stop that?
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.util.*;
public class AnimatedBoxman extends JApplet implements Runnable,ActionListener
{
int size=50;
int x = 0;
int y =300;
int side2side = 50;
Thread t;
boolean sworddrawn = false;
JButton myButton = new JButton("Change");
static Random myRan = new Random();
public void init()
{
Container content = getContentPane();
content.setBackground(Color.red);
setLayout(new FlowLayout());
add(myButton);
myButton.addActionListener(this);
}
public void actionPerformed (ActionEvent ae)
{
side2side= -side2side;
Container content = getContentPane();
content.setBackground(new Color
(Math.abs(myRan.nextInt())%256,
Math.abs(myRan.nextInt())%256,
Math.abs(myRan.nextInt())%256));
repaint();
}
public void run( )
{
while( true )
{
x+= side2side;
if (x > this.getSize().width-50 || x < 0)
side2side = -side2side;
if (x%3 == 0)
sworddrawn = !sworddrawn;
repaint( );
try {
Thread.sleep(900);
}
catch( Exception e ) { }
}
}
public void start( )
{
t = new Thread(this);
t.start( );
}
public void paint ( Graphics g )
{
super.paint( g );
g.setColor(Color.blue);
g.drawLine(x-10, y, x-30,y);
g.drawLine(x-30, y, x-30, y-20);
g.drawLine(x-10, y-20, x-10, y);
g.drawLine(x-10, y-20, x+10, y-20);
g.drawLine(x-10, y-20, x+10, y-20);
g.drawLine(x-10, y, x+10, y);
g.drawLine(x-10, y, x-10, y+20);
g.drawLine(x, y+20, x, y);
g.drawLine(x+10, y+20,x+10, y);
g.drawLine(x+10, y, x+30, y);
g.drawLine(x+30, y, x+30, y-20);
g.drawLine(x+10, y-20, x+10, y);
g.drawLine(x, y+20, x+10, y+20);
g.drawLine(x-10, y+20, x-10, y+30);
g.drawLine(x-10, y+30, x, y+30);
g.drawLine(x, y+30, x, y+20);
g.drawLine(x, y+30, x+10, y+30);
g.drawLine(x+10, y+30, x+10, y+20);
g.drawLine(x-10, y+20, x, y+20);
g.drawOval(x-7, y-20, 5, 5);
g.drawOval(x+1, y-20, 5, 5);
g.drawLine(x-4, y-8, x-5, y-5);
g.drawLine(x-5, y-8, x+6, y-8);
g.drawLine(x+6, y-5, x+6, y-8);
if( sworddrawn )
{
g.drawLine(500, 400, 700, 400);
}
else
{
Polygon myPolygon2;
myPolygon2=new Polygon();
myPolygon2.addPoint(x-42,y-184);
myPolygon2.addPoint(x-32,y-195);
myPolygon2.addPoint(x-21,y-184);
g.fillPolygon(myPolygon2);
g.fillRect(x-41, y-184, 20, 100);
g.fillArc(x-50, y-104, 40, 20, 180, 180);
g.fillArc(x-35, y-94, 20, 35, 90, 180);
g.drawLine(x-30, y-164, x-30, y-24);
g.drawOval(x-40, y-24, 20, 30);
}
}
}

The blue horizontal line can be outside of the content pane, in which case it is not drawn. You can check the size of the content pane by adding a line to the init method:
System.out.println("getSize(): " + getSize());
On my laptop, the size is 400 by 300 pixels:
getSize(): java.awt.Dimension[width=400,height=300]
This results in an invisible blue horizontal line:
g.drawLine(500, 400, 700, 400);
With lower values for x and y coordinates, the line is visible:
g.drawLine(50, 40, 70, 40);
Finally, when you ask a question it can be useful to add a screenshot of your application with some additional text to explain what your problem is (for example, what you expect versus what you see).

Related

Forming Concentric Circles in Java

So I am having trouble drawing Concentric Circles(think of a Bull's eye Target). My issue is that each circle I draw is not centered, instead shifts position from the original circle. Here is my code:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.JPanel;
public class TargetPanel extends JPanel {
public TargetPanel() {
this.setPreferredSize(new Dimension(800,800));
}//end constructor
public void paintComponent(Graphics g) {
Color blue = new Color(0, 100, 0);
Color yellow = new Color(100, 0, 0);
super.paintComponent(g);
int dimension = 800;
int partition = 75;
drawCirlce(g, Color.WHITE, Color.BLACK, dimension);
}//end draw circle
private void drawCirlce(Graphics g, Color blue, Color yellow, int dimension) {
g.setColor(Color.WHITE);
g.fillOval((getHeight()- (dimension))/2, (getWidth()-(dimension))/2, dimension, dimension);
g.setColor(Color.BLACK);
g.drawOval((getHeight() - (dimension))/2, (getWidth()-(dimension))/2, dimension, dimension);
g.drawOval((getHeight()- (dimension))/2, (getWidth()- (dimension))/2, dimension-30, dimension-30);
}//end drawCircle
}//end main
I think I know what the issue is: the -30 shifts it, that being the case how do I form smaller cirlces with the origin of the circles being centered?
I think you need to subtract 30 from the dimension and then update the dimension value, like so:
private void drawCirlce(Graphics g, Color blue, Color yellow, int dimension) {
g.setColor(Color.WHITE);
g.fillOval((getHeight() - (dimension)) / 2, (getWidth() - (dimension)) / 2, dimension, dimension);
g.setColor(Color.BLACK);
g.drawOval((getHeight() - (dimension)) / 2, (getWidth() - (dimension)) / 2, dimension, dimension);
// Updated code here:
dimension -= 30;
g.drawOval((getHeight() - (dimension)) / 2, (getWidth() - (dimension)) / 2, dimension, dimension);
}//end drawCircle
Like this you should get the different circles at a regular distance.
The code below can be run and displays two circle lines at the same distance:
import javax.swing.*;
import java.awt.*;
public class Circles extends JFrame {
public Circles() throws HeadlessException {
this.setLayout(new BorderLayout());
final Dimension dimension = new Dimension(600, 600);
this.setSize(new Dimension(dimension.width + 50, dimension.height + 50));
this.add(new TargetPanel(dimension), BorderLayout.CENTER);
}
public static void main(String[] args) {
Circles circles = new Circles();
circles.setLocationRelativeTo(null);
circles.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
circles.setVisible(true);
}
}
class TargetPanel extends JPanel {
public TargetPanel(Dimension dimension) {
this.setPreferredSize(dimension);
}//end constructor
public void paintComponent(Graphics g) {
Color blue = new Color(0, 100, 0);
Color yellow = new Color(100, 0, 0);
super.paintComponent(g);
int dimension = this.getPreferredSize().width;
int partition = 75;
drawCircle(g, Color.WHITE, Color.BLACK, dimension);
}//end draw circle
private void drawCircle(Graphics g, Color blue, Color yellow, int dimension) {
g.setColor(Color.WHITE);
final int yCenter = (getHeight() - (dimension)) / 2;
final int xCenter = (getWidth() - (dimension)) / 2;
g.fillOval(xCenter, yCenter, dimension, dimension);
g.setColor(Color.BLACK);
g.drawOval(xCenter, yCenter, dimension, dimension);
dimension -= 30;
g.drawOval((getWidth() - (dimension)) / 2, (getHeight() - (dimension)) / 2, dimension, dimension);
}//end drawCircle
}//end main

Animation not working Java Graphics

Completing a graphics program in Java, I'm trying to animate rain falling using a timer. Right now I am testing my code with a big blue rectangle so I can see where it's going but the animation isn't working for me. I'm very new to Java graphics so I could be making mistakes that just aren't clear to me.
When I try to repaint the square to move, and the paint function is called the whole screen blinks, this may be because I was using recursive functions to draw fractal trees, but I'm not sure. Is there a way to keep everything I have drawn from being repainted and just call repaint on the rain? Any guidance or tips would be appreciated.
import java.awt.*;
import javax.swing.*;
import java.lang.Math;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class FractalTree extends JFrame {
private int frameWidth = 1440;
private int frameHeight = 850;
private int rainX = 0;
private int rainY = 0;
public FractalTree()
{
setBounds(1000, 1000, frameWidth, frameHeight ); //graphics window size
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
ActionListener listener = new TimerListener();
final int DELAY = 1500;
Timer t = new Timer(DELAY, listener);
t.start();
setResizable(false);
}
public void setRain(int newRainX, int newRainY)
{
rainX = newRainX;
rainY = newRainY;
}
public void setSkyGround(Graphics g)
{
Color sky = new Color(180, 225, 255);
g.setColor(sky);
g.fillRect(0, 0, frameWidth, 550);
Color sun = new Color(225, 225, 150);
g.setColor(sun);
g.fillOval(1380, -40, 100, 100);
g.drawLine(frameWidth, 0, 1350, 550);
g.drawLine(frameWidth, 0, 1450, 550);
g.drawLine(1350, 550, 1450, 550);
int xpoints[] = {frameWidth, 1450, 1350};
int ypoints[] = {0, 550, 550};
int npoints = 3;
g.fillPolygon(xpoints, ypoints, npoints);
g.drawLine(frameWidth, 0, 1080, 550);
g.drawLine(frameWidth, 0, 880, 550);
g.drawLine(880, 550, 1080, 550);
int xpoints2[] = {frameWidth, 1080, 880};
int ypoints2[] = {0, 550, 550};
int npoints2 = 3;
g.fillPolygon(xpoints2, ypoints2, npoints2);
g.drawLine(frameWidth, 0, 480, 550);
g.drawLine(frameWidth, 0, 280, 550);
g.drawLine(480, 550, 280, 550);
int xpoints3[] = {frameWidth, 480, 280};
int ypoints3[] = {0, 550, 550};
int npoints3 = 3;
g.fillPolygon(xpoints3, ypoints3, npoints3);
g.drawLine(frameWidth, 0, 0, 430);
g.drawLine(frameWidth, 0, 0, 300);
g.drawLine(0, 430, 0, 300);
int xpoints4[] = {frameWidth, 0, 0};
int ypoints4[] = {0, 430, 300};
int npoints4 = 3;
g.fillPolygon(xpoints4, ypoints4, npoints4);
g.drawLine(frameWidth, 0, 0, 100);
g.drawLine(frameWidth, 0, 0, 0);
g.drawLine(0, 100, 0, 0);
int xpoints5[] = {frameWidth, 0, 0};
int ypoints5[] = {0, 0, 100};
int npoints5 = 3;
g.fillPolygon(xpoints5, ypoints5, npoints5);
Color grassBackground = new Color(150, 255, 170);
g.setColor(grassBackground);
g.fillRect(0, 550, frameWidth, frameHeight);
}
public void drawTree(Graphics g, int x1, int y1, double angle, int depth, int red, int green, int blue)
{
if (depth == 0)
{
Color doodle = new Color(red, green, blue);
g.setColor(doodle);
g.fillOval(x1, y1, 10, 10);
}
else
{
Graphics2D g2 = (Graphics2D) g;
g2.setStroke(new BasicStroke(depth));
Color brown = new Color(100, 25, 0);
g.setColor(brown);
int x2 = x1 + (int) (Math.cos(Math.toRadians(angle)) * depth * 10);
int y2 = y1 + (int) (Math.sin(Math.toRadians(angle)) * depth * 10);
g.drawLine(x1, y1, x2, y2);
drawTree(g, x2, y2, angle - 40, depth - 1, red, green, blue);
drawTree(g, x2, y2, angle + 20, depth - 1, red, green, blue);
}
}
public void realFlowers(Graphics g, int x, int y, int lenWid, int petals)
{
//calculates the increment
double inc = (2*Math.PI/petals);
g.setColor(Color.YELLOW);
//draws petals
for(int i = 0; i < petals; i++){
//keeps spacing consistent depandng on number of petals
double value = i * inc;
//draws petals with calculated spacing relative to number of petals
g.fillOval((int)((lenWid)*Math.cos(value)+x-lenWid/4),(int)((lenWid)*Math.sin(value)+y-lenWid/4), lenWid + lenWid/2, lenWid + lenWid/2);
}
//draws middle flower bud;
g.setColor(Color.ORANGE);
g.fillOval(x - lenWid/4, y - lenWid/4, lenWid + lenWid/2 , lenWid + lenWid/2);
}
public void drawGrass(Graphics g, int width, int height, int interval, int red, int green, int blue)
{
height = frameHeight - height;
Color grass = new Color(red, green, blue);
for(int i = 0; i < width; i= i + interval)
{
for(int j = frameHeight; j > height; j = j - interval)
{
g.setColor(grass);
g.fillRect(i, j, 3, 5);
}
}
}
public void rainDrops(Graphics g, int x, int y, int w, int h)
{
setRain(x, y);
Color rain = new Color(0, 76, 153);
g.setColor(rain);
g.fillRect(x, y, w, h);
}
public void moveRainBy(int dx, int dy)
{
rainX = rainX + dx;
rainY = rainY + dy;
repaint();
}
class TimerListener implements ActionListener
{
public void actionPerformed(ActionEvent event)
{
moveRainBy(1, 1);
}
}
public void paint(Graphics g) {
setSkyGround(g);
drawGrass(g, 1440, 315, 5, 0, 255, 0);
drawGrass(g, 1430, 310, 10, 0, 204, 0);
drawTree(g, 1085, 730, -90, 10, 255, 102, 102);
drawTree(g, 250, 600, -90, 8, 255, 255, 255);
drawTree(g, 1110, 740, -90, 4, 255, 102, 102);
drawTree(g, 1060, 745, -90, 2, 255, 102, 102);
realFlowers(g, 700,700, 8, 8);
rainDrops(g, 200, 200, 30, 30);
}
public static void main(String[] args) {
new FractalTree().setVisible(true);
}
}
When I try to repaint the square to move, and the paint function is called the whole screen blinks
This is because you've override paint of the a top level container (JFrame) which is not double buffered.
As a general recommendation, you should be basing your core functionality around a JPanel and override it's paintComponent method. Take a look at Performing Custom Painting and Painting in AWT and Swing for more details
You might like to also have a look at How to get the EXACT middle of a screen, even when re-sized and How can I set in the midst? for more details why it's not recommended to extend directly from JFrame and try to paint to it.
Is there a way to keep everything I have drawn from being repainted and just call repaint on the rain?
Painting is destructive, that is, each time paint/paintComponent is called, you are expected to repaint the entire state of the component from scratch.
You could use a buffering technique, using something like BufferedImage to paint your state to and simply have the paint methods draw the image, but that would depend on how complex a solution you want. If you were to use buffering technique, I would consider which elements are "static" and which elements are "dynamic". Painting those static elements to the buffer and then, when paint is called, painting the dynamic elements over the top the buffer

How to hide JToolTip background when exceeding borders?

I've created this custom JToolTip for my application. When the tooltip is entirely diplayed inside a JFrame, no background is visible (expected), but when the tooltip is displayed outside the JFrame, the background will be visible. How can I have it removed either way?
I've tried setBackground(new Color(255, 255, 255, 0)); with the '0' alpha value to make sure the background is transparent, but that didn't do the trick.
The tooltip inside the frame, as expected:
The tooltip exceeding the JFrame, with the unwanted background:
The custom JTooltip:
public class DefaultToolTip extends JToolTip {
public DefaultToolTip() {
setOpaque(false);
setPreferredSize(new Dimension(275, 30));
setBackground(new Color(255, 255, 255, 0));
}
#Override
public void addNotify() {
super.addNotify();
setOpaque(false);
Component parent = this.getParent();
if (parent != null) {
if (parent instanceof JComponent) {
JComponent jparent = (JComponent) parent;
jparent.setOpaque(false);
}
}
}
#Override
public void paint(Graphics g) {
String text = getComponent().getToolTipText();
addNotify();
Graphics2D g2d = drawComponent(g);
drawText(text, g2d);
g2d.dispose();
}
private void drawText(String text, Graphics2D g2d) {
//Draw the text
int cHeight = getComponent().getHeight();
FontMetrics fm = g2d.getFontMetrics();
g2d.setColor(Color.WHITE);
if (cHeight > getHeight())
g2d.drawString(text, (getWidth() - fm.stringWidth(text)) / 2, (getHeight() + fm.getAscent()) / 2 + 2);
else
g2d.drawString(text, (getWidth() - fm.stringWidth(text)) / 2, (cHeight + fm.getAscent()) / 2 + 2);
}
private Graphics2D drawComponent(Graphics g) {
//Create a round rectangle
Shape round = new RoundRectangle2D.Float(0, 8, getWidth(), getHeight(), 8, 8);
//Draw the background
Graphics2D g2d = (Graphics2D) g.create();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setColor(Color.GRAY);
g2d.fill(round);
//Draw the left triangle
Point p1 = new Point(getWidth() / 2, getHeight() - 30);
Point p2 = new Point(getWidth() / 2 + 8, getHeight() - 20);
Point p3 = new Point(getWidth() / 2 - 8, getHeight() - 20);
int[] xs = {p1.x, p2.x, p3.x};
int[] ys = {p1.y, p2.y, p3.y};
Polygon triangle = new Polygon(xs, ys, xs.length);
g2d.fillPolygon(triangle);
return g2d;
}
}
Solution
A few things have changed to have the tooltip behave as expected. the paint method has been replaced by the paintComponent method, the addNotify call was removed, the method updated to fetch the window of the component and to give it a transparent background. setBorder(BorderFactory.createEmptyBorder()); was also needed to remove the components default border.
public class DefaultToolTip extends JToolTip {
public DefaultToolTip() {
setOpaque(false);
setPreferredSize(new Dimension(275, 30));
setBackground(new Color(255, 255, 255, 0));
setBorder(BorderFactory.createEmptyBorder());
}
#Override
public void addNotify() {
super.addNotify();
setOpaque(false);
Component parent = this.getParent();
if (parent != null) {
if (parent instanceof JComponent) {
JComponent jparent = (JComponent) parent;
jparent.setOpaque(false);
}
}
Window window = SwingUtilities.windowForComponent(this);
try {
window.setBackground(new Color(255, 255, 255, 0));
} catch (IllegalComponentStateException e) {
//Do nothing
}
}
#Override
public void paintComponent(Graphics g) {
//super.paintComponent(g);
String text = getComponent().getToolTipText();
Graphics2D g2d = drawComponent(g);
drawText(text, g2d);
g2d.dispose();
}
private void drawText(String text, Graphics2D g2d) {
//Draw the text
int cHeight = getComponent().getHeight();
FontMetrics fm = g2d.getFontMetrics();
g2d.setColor(Color.WHITE);
if (cHeight > getHeight())
g2d.drawString(text, (getWidth() - fm.stringWidth(text)) / 2, (getHeight() + fm.getAscent()) / 2 + 2);
else
g2d.drawString(text, (getWidth() - fm.stringWidth(text)) / 2, (cHeight + fm.getAscent()) / 2 + 2);
}
private Graphics2D drawComponent(Graphics g) {
//Create a round rectangle
Shape round = new RoundRectangle2D.Float(0, 8, getWidth(), getHeight(), 8, 8);
//Draw the background
Graphics2D g2d = (Graphics2D) g.create();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setColor(Color.GRAY);
g2d.fill(round);
//Draw the left triangle
Point p1 = new Point(getWidth() / 2, getHeight() - 30);
Point p2 = new Point(getWidth() / 2 + 8, getHeight() - 20);
Point p3 = new Point(getWidth() / 2 - 8, getHeight() - 20);
int[] xs = {p1.x, p2.x, p3.x};
int[] ys = {p1.y, p2.y, p3.y};
Polygon triangle = new Polygon(xs, ys, xs.length);
g2d.fillPolygon(triangle);
return g2d;
}
}
A note however, super.paintComponent(g) was commented out, since it would draw text another time.
Don't know if any of these will help but:
Don't override paint(...). Custom painting is done by overriding paintComponent(...).
Invoke super.paintComponent(...) as the first statement
Don't invoke addNotify() in a painting method. A painting method is for painting only.
with the '0' alpha value to make sure the background is transparent,
Swing components don't know how to handle transparent backgrounds. Just make the component non-opaque.
When the tooltip overlaps the component. The tooltip is actually added to a JWindow before it is displayed. So in your addNotify() logic, you can search for the window and make it transparent.
Check out:
Window window = SwingUtilities.windowForComponent(...);

Weird result when trying to draw a semi-transparent square over 1 of the 6 buttons in an ArrayList

So I Have an ArrayList of buttons that I created, for the most part they work fine except this one thing. I'll go through the steps to reach the part that is giving me problems.
The ArrayList Creation and Update
private ArrayList<PressButton> buttons;
public CharacterSelectionMenu()
{
buttons = new ArrayList<PressButton>();
addButtons();
}
public void update()
{
updateButtons();
}
private void updateButtons()
{
for(PressButton b : buttons)
{
b.update();
}
}
private void addButtons()
{
buttons.add(new CreateCharacterButton(100, 100, 64, 64));
buttons.add(new CreateCharacterButton(200, 100, 64, 64));
buttons.add(new CreateCharacterButton(300, 100, 64, 64));
buttons.add(new CreateCharacterButton(100, 200, 64, 64));
buttons.add(new CreateCharacterButton(200, 200, 64, 64));
buttons.add(new CreateCharacterButton(300, 200, 64, 64));
}
The method in the PressButton superclass that draws the square when hovering over the button
public void update()
{
input();
draw();
hover();
}
protected void hover()
{
if(Collision.mouseAABBButton(this))
{
drawQuadColor(1, 1, 1, 0.3f, x, y, width, height);
}
}
The drawQuadColor method (Just in case, this works everywhere I use it, I don't think it is the cause of the problem)
public static void drawQuadColor(float r, float g, float b, float a, float x, float y,
float width, float height)
{
glDisable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glColor4f(r, g, b, a);
glBegin(GL_QUADS);
glVertex2f(x, y);
glVertex2f(x + width, y);
glVertex2f(x + width, y + height);
glVertex2f(x, y + height);
glEnd();
glDisable(GL_BLEND);
}
So here is the weird problem, I'm guessing it's very simple and has to do with the order of the updating in the ArrayList, but I'm too stupid to figure it out.
If I hover over the last button in the ArrayList it works just fine, like this:
But if I hover over any other button, the one that is being hovered over works like it should but the ones that are next in the ArrayList get a non-transparent square over them (shouldn't the "bugged" squares be transparent at least?), like this:
I have also tried using an Array instead but that did not help.
How do I fix this and why does it happen?
Can you try replacing your drawQuadColor by
{
glDisable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glColor4f(r, g, b, a);
glBegin(GL_QUADS);
glVertex2f(x, y);
glVertex2f(x + width, y);
glVertex2f(x + width, y + height);
glVertex2f(x, y + height);
glEnd();
glDisable(GL_BLEND);
}
and update your question please ?

How to move this eye applet or to make it blink?

Please help me how to make this eye move or to make it blink using repaint, thread and implements runnable. I don't know where to place the right codes to make it work. Please help me guys! Thank you!
Here is the code:
import java.awt.*;
import java.applet.*;
public class Pucca extends Applet {
public Pucca(){
setSize(700, 700); }
//paint method
public void paint(Graphics g){
Color white = new Color(255,255,255);
g.setColor(white);
g.fillOval(600, 100, 125, 125); //left white fill eye
g.setColor(Color.BLA­CK);
g.drawOval(600, 100, 125, 125); // left big black line eye
g.setColor(white);
g.fillOval(700, 100, 125, 125); //right white fill eye
g.setColor(Color.BLA­CK);
g.drawOval(700, 100, 125, 125); //right big black line eye
Color blue = new Color(0, 160, 198);
g.setColor(blue);
g.fillOval(635, 130, 51, 51); // left blue fill eye
g.setColor(Color.BLA­CK);
g.drawOval(635, 130, 50, 50); // left black small line eye
g.setColor(blue);
g.fillOval(735, 130, 51, 51); // right blue fill eye
g.setColor(Color.BLA­CK);
g.drawOval(735, 130, 50, 50); // right black small line eye
g.setColor(Color.BLA­CK);
g.fillOval(650, 145, 20, 20); // left black iris
g.setColor(Color.BLA­CK);
g.fillOval(750, 145, 20, 20); // right black iris
}
}
When it comes to animation, everything becomes variable. You also have a lot of repeated code (seriously, if you can paint one eye, you can paint lots).
The first thing you need to is make all the values of the eye as variable as possible.
The follow makes the eye size and position variable and the iris and pupil a scaled value of the eye size, which makes the whole process simpler to animate.
Next, you need an updated loop, which can update the state of the values you want to change. To keep it simple, I've set it up so that the pupil has a variable offset, which is changed over time.
import java.applet.Applet;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Rectangle;
public class Pucca extends Applet {
public Pucca() {
setSize(700, 700);
Thread t = new Thread(new Runnable() {
private int xDelta = -1;
private int yDelta = 0;
private int blinkCount = 0;
#Override
public void run() {
while (true) {
try {
Thread.sleep(40);
} catch (InterruptedException ex) {
}
xOffset += xDelta;
double irisSize = eyeSize.width * irisScale;
double range = ((eyeSize.width - irisSize) / 2);
if (xOffset <= -range) {
xOffset = -(int) range;
xDelta *= -1;
} else if (xOffset >= range) {
xOffset = (int) range;
xDelta *= -1;
}
blinkCount++;
if (blink && blinkCount > 10) {
blink = false;
blinkCount = 0;
} else if (blinkCount > 25) {
blink = true;
blinkCount = 0;
}
repaint();
}
}
});
t.setDaemon(true);
t.start();
}
private boolean blink = false;
private int xOffset, yOffset = 0;
private Dimension eyeSize = new Dimension(125, 125);
private Point left = new Point(20, 20);
private Point right = new Point(left.x + 100, left.y);
private double irisScale = 0.4;
private double pupilScale = 0.16;
//paint method
#Override
public void paint(Graphics g) {
super.paint(g);
paintEye(g, new Rectangle(left, eyeSize));
paintEye(g, new Rectangle(right, eyeSize));
}
protected void paintEye(Graphics g, Rectangle bounds) {
Color white = new Color(255, 255, 255);
if (blink) {
g.setColor(Color.YELLOW);
} else {
g.setColor(white);
}
g.fillOval(bounds.x, bounds.y, bounds.width, bounds.height); //left white fill eye
g.setColor(Color.BLACK);
g.drawOval(bounds.x, bounds.y, bounds.width, bounds.height); // left big black line eye
if (!blink) {
Color blue = new Color(0, 160, 198);
paintEyePartAt(g, bounds, irisScale, blue);
paintEyePartAt(g, bounds, pupilScale, Color.BLACK);
}
}
private void paintEyePartAt(Graphics g, Rectangle bounds, double delta, Color color) {
int width = (int) (bounds.width * delta);
int height = (int) (bounds.height * delta);
g.setColor(color);
g.fillOval(
xOffset + bounds.x + ((bounds.width - width) / 2),
yOffset + bounds.y + ((bounds.height - height) / 2),
width, height); // left blue fill eye
g.setColor(Color.BLACK);
g.drawOval(
xOffset + bounds.x + ((bounds.width - width) / 2),
yOffset + bounds.y + ((bounds.height - height) / 2),
width,
height); // left blue fill eye
}
}
This complicates things, as painting can occur for any number of reasons, many of which you don't have control over or will be notified about, so you should be very careful about where and when you change values.
You should also have a look at Java Plugin support deprecated and Moving to a Plugin-Free Web and Why CS teachers should stop teaching Java applets.
Applets are simply a dead technology and given the inherent complexities involved in using them, you should instead focus you should probably attention towards window based programs.
Personally, I'd start with having a look at Painting in AWT and Swing and Performing Custom Painting

Categories

Resources