I'm having trouble simulating a race between two competitors. This is your typical race program where you use a random number generator to determine what "moves" the competitors use. As seen in my code below, the track is composed of 50 rectangles, and the filled in rectangle shows the location of each competitor on the track. Some "moves" make the competitor jump 9 squares to the right, or 2 squares back, for example. When I run the applet, only the initial starting position is displayed; the applet doesn't work. I realize it's a lot of code, but what do I need to do to fix my problem? I'm really stuck at this point. Any help is appreciated. I have can only use AWT, not swing. This is an assignment for class :/ Here is the code:
import java.awt.*;
import java.applet.*;
public class Example extends Applet
{
Image tortoise, hare;
int tortX = 250, hareX = 250;
final int tortY = 100, hareY = 300, WIDTH = 15, HEIGHT = 50;
int turn; String turnNum;
int move; String tMove, hMove;
public void init()
{
tortoise = getImage( getDocumentBase(), "images/tortoise.gif" );
hare = getImage( getDocumentBase(), "images/hare.gif" );
move = 0; turn = 0;
}
public void control()
{
while (( tortX < 985 ) || ( hareX < 985 ))
{
move = (int)(10 * Math.random());
switch (move)
{
case 1:
case 2:
tortX += (3 * WIDTH);
hareX += (9 * WIDTH);
tMove = "Fast Plod"; hMove = "Big Hop";
break;
case 3:
case 4:
case 5:
tortX += (3 * WIDTH);
hareX += WIDTH;
tMove = "Fast Plod"; hMove = "Small Hop";
break;
case 6:
tortX += WIDTH;
if (hareX == 250) {} // DO NOTHING
else if (hareX <= (250 + (11 * WIDTH)))
hareX = 250;
else
hareX -= (12 * WIDTH);
tMove = "Slow Plod"; hMove = "Big Slip";
break;
case 7:
case 8:
tortX += (1 * WIDTH);
if (hareX == 250) {} // DO NOTHING
else if (hareX <= (250 + (WIDTH)))
hareX = 250;
else
hareX -= (2 * WIDTH);
tMove = "Slow Plod"; hMove = "Small Slip";
break;
case 9:
case 10:
if (tortX == 250) {} // DO NOTHING
else if (tortX <= (250 + (5 * WIDTH)))
tortX = 250;
else
tortX -= (6 * WIDTH);
tMove = "Slip"; hMove = "Fall Asleep. Zzz...";
break;
// Hare falls asleep. No action.
}
turn++; turnNum = (turn + "");
repaint();
for (int i = 1; i <= 10; i++)
{
delay();
}
}
tortX = 985; hareX = 985;
repaint();
}
public void paint( Graphics screen )
{
drawRace(screen);
if (tortX >= 985)
{
screen.setFont(new Font("Times New Roman", Font.ITALIC, 48));
screen.drawString("Tortoise Wins", 650, 240);
clearCurrent(screen);
fillNext(screen);
}
else if (hareX >= 985)
{
screen.setFont(new Font("Times New Roman", Font.ITALIC, 48));
screen.drawString("Tortoise Wins", 650, 240);
clearCurrent(screen);
fillNext(screen);
}
else
{
screen.drawString(("Turn " + turnNum), 621, 55);
screen.setFont(new Font("Times New Roman", Font.ITALIC, 12));
screen.drawString(tMove, 59, 65); screen.drawString(hMove, 66, 255);
clearCurrent(screen);
fillNext(screen);
}
stop();
}
public void clearCurrent( Graphics s )
{
s.clearRect(tortX+1, tortY+1, WIDTH-1, HEIGHT-1);
s.clearRect(hareX+1, hareY+1, WIDTH-1, HEIGHT-1);
}
public void fillNext( Graphics s )
{
s.fillRect(tortX+1, tortY+1, WIDTH-1, HEIGHT-1);
s.fillRect(hareX+1, hareY+1, WIDTH-1, HEIGHT-1);
}
public void drawRace( Graphics s )
{
// GENERATES INITIAL GRAPHICS FOR RACE
s.drawRect(250, 100, 750, 50);
s.drawRect(250, 300, 750, 50);
int lineX = 265, lineYi = 100, lineYf = 150;
for (int i = 1; i <= 98; i++)
{
if (lineX == 1000)
{
lineX = 265; lineYi = 300; lineYf = 350;
}
s.drawLine(lineX, lineYi, lineX, lineYf);
lineX += 15;
}
s.fillRect(tortX+1, tortY+1, WIDTH-1, HEIGHT-1);
s.fillRect(hareX+1, hareY+1, WIDTH-1, HEIGHT-1);
s.drawImage(tortoise, 59, 80, this);
s.drawImage(hare, 66, 271, this);
s.setFont(new Font("Times New Roman", Font.BOLD, 24));
s.drawString("Race", 250, 55);
}
public void delay()
{
for (int i = 0; i < 90000000; i++)
{
}
}
public void stop()
{
}
}
Your first problem is you actually never "start" the race...Sure your init the applet, but then, nothing...
Your second problem is the control method is block the Event Dispatching Thread, this means, they while you are in this method NOTHING will get painted to the screen. This is because the Event Dispatching Thread is also responsible for dispatching repaint requests.
You third problem is your violating the paint contact. You have a responsibility to call super.paint(screen) - paint is a complex method and should never ignore it unless you have a REALLY good reason do to so.
Your fourth problem is, you using an Applet instead of a JApplet. Better to ignore the AWT controls in favor of the Swing controls. Swing are more flexible and easier to extend.
Your fifth problem is you painting onto a top level container, this is never recommended. You are better using something like JPanel and overriding it's paintComponent method (don't forget to call super.paintComponent). Apart from everything else, it's double buffered and will reducing flicking as the screen is updated.
Take a look at...
Concurrency in Swing and How to use Swing Timer to solve you EDT blocking issues...
Performing Custom Painting for ideas about painting in Swing
Related
I am working on a simple game which requires 1 player (the square) and some enemies that spawn randomly inside the play-area. I am running into an issue currently, because when I run my program, pressing any arrow key will repaint not only the player's new location, but it will also re-spawn all the enemies into the new locations.
I have gone through my code a few times and I am still stumped as to why this is happening. Any help would be greatly appreciated.
P.S. I am not a very experienced programmer, so some of this code may not be as efficient as possible and some things may be incorrect; feel free to point out any errors besides the issue at hand. Thanks!
Main Class
public class Eat {
public static void main(String[] args) {
// Creating the main frame
JFrame main = new JFrame("Eat 'Em All - Version 1.0.2");
main.setSize(497, 599);
main.setLocationRelativeTo(null);
main.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
main.setResizable(false);
// Colours and borders
Border areaBorder = new LineBorder(Color.LIGHT_GRAY, 3);
// Creating main JPanel
JPanel area = new JPanel();
area.setLayout(new BoxLayout(area, BoxLayout.PAGE_AXIS));
area.setBackground(Color.WHITE);
main.setContentPane(area);
// Creating the drawing/image/player
DrawPlayer player = new DrawPlayer();
player.setPreferredSize(new Dimension(497, 539));
player.setOpaque(false);
// Enemies
DrawEnemy enemy = new DrawEnemy();
enemy.setPreferredSize(new Dimension(497, 539));
enemy.setBackground(Color.WHITE);
// Creating the control panel for buttons, etc
JPanel control = new JPanel();
control.setPreferredSize(new Dimension(497, 60));
control.setLayout(new GridLayout(1, 2, 0, 0));
control.setBorder(areaBorder);
JLabel welcome = new JLabel(" Welcome to Eat 'Em All |--| Press 'Start'");
JButton start = new JButton("Start");
// Adding it all to the frame
main.add(enemy);
enemy.add(player);
control.add(welcome);
control.add(start);
area.add(control);
// Adding keylistener and making button false
player.addKeyListener(player);
player.setFocusable(true);
start.setFocusable(false);
enemy.setFocusable(false);
// Bring frame to front and visible
main.toFront();
main.setVisible(true);
System.out.println(player.getWidth() / 2);
System.out.println(player.getHeight() / 2);
}
}
Drawing Player Class
public class DrawPlayer extends JPanel implements KeyListener {
long xPosition = 0;
long yPosition = 0;
public void paintComponent(Graphics g) {
super.paintComponent(g);
// Making loop to get points and move it
// Center of area is x: 245 y: 255
int xPoints[] = {235, 255, 255, 235, 235, 255};
int yPoints[] = {265, 265, 245, 245, 265, 245};
for (int i = 0; i < xPoints.length; i++) {
xPoints[i] += xPosition;
yPoints[i] += yPosition;
}
g.setColor(Color.BLUE);
g.drawPolygon(xPoints, yPoints, xPoints.length);
}
public void keyPressed(KeyEvent e) {
switch (e.getKeyCode()) {
case KeyEvent.VK_DOWN:
if (yPosition == 245) {
yPosition -= 5;
} else {
yPosition += 5;
}
break;
case KeyEvent.VK_UP:
if (yPosition == -245) {
yPosition += 5;
} else {
yPosition -= 5;
}
break;
case KeyEvent.VK_LEFT:
if (xPosition == -235) {
xPosition += 5;
} else {
xPosition -= 5;
}
break;
case KeyEvent.VK_RIGHT:
if (xPosition == 235) {
xPosition -= 5;
} else {
xPosition += 5;
}
break;
}
repaint();
}
public void keyReleased(KeyEvent e) {
}
public void keyTyped(KeyEvent e) {
}
}
Drawing Enemies Class
public class DrawEnemy extends JPanel {
public void paintComponent(Graphics f) {
super.paintComponent(f);
for (int i = 0; i < 10; i++ ){
f.setColor(Color.RED);
f.drawOval((int)(Math.random() * ((440 - 0) + 0) + 0), (int)(Math.random() * ((500 - 0) + 0) + 0), 50, 50);
}
}
}
Your have a problem here:
public void paintComponent(Graphics f) {
super.paintComponent(f);
for (int i = 0; i < 10; i++ ){
f.setColor(Color.RED);
f.drawOval((int)(Math.random() * ((440 - 0) + 0) + 0), (int)(Math.random() * ((500 - 0) + 0) + 0), 50, 50);
}
}
You've got program logic inside of a painting method, something you should never do, since you never have full control over when or even if a painting method will be called. The solution, get the randomization out of the paintComponent method and into its own separate method, one that you call if and only if you want to randomize the enemies, and not every time you repaint.
Other issues:
Separate your program logic from your GUI.
For instance you should have a non-GUI Enemy class, one that has fields for its own position, its size, its movement, perhaps a move() method, perhaps a collision(Player p) method.
You should have only one JPanel that does drawing and this should be its only job.
Again, you don't tie movement of anything to the painting method.
You would want a game loop of some sort, perhaps a Swing Timer. This will generate regularly spaced ticks that will prod Enemies and Players to move.
Get rid of KeyListener code and favor Key Bindings. The latter is much less kludgy when it comes to component focus. Do check the tutorial for this.
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.BLACK);
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.BLACK);
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.BLACK);
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.BLACK);
g.drawOval(735, 130, 50, 50); // right black small line eye
g.setColor(Color.BLACK);
g.fillOval(650, 145, 20, 20); // left black iris
g.setColor(Color.BLACK);
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
I have to do this thing for my Java class where I make an applet displaying a tortoise & hare race. Here is the assignment:
This project involves writing an applet to simulate a tortoise and hare race. The
contenders will each race along a horizontal course that contains a lane for each
of them. The course should have at least 50 squares or positions…you may add
more if you wish. The race begins with each contender at position 1 of their
respective lanes. The contender that first reaches or passes the last square of
the course is the winner of the race.
The following table indicates the types of moves that each contender can make.
Contender Type of Move Percentage of Time Result of Move
Tortoise Fast plod 50% 3 squares to right
Slow plod 30% 1 square to right
Slip 20% 6 squares to left
Hare Big hop 20% 9 squares to right
Small hop 30% 1 square to right
Big slip 10% 12 squares to left
Small slip 20% 2 squares to left
Fall asleep 20%
Each contender starts at position 1. When a contender slips, they can’t slip any
further left than position 1. You will use a random number generator to simulate
the percentages of each type of move indicated in the table.
Generate a random integer, n, in the range 1 ≤ n ≤ 10. For the tortoise, perform a
fast plod if the number is 1-5, a slow plod if the number is 6-8, and a slip if the
number is 9-10. For the hare, perform a big hop if the number is 1-2, a small hop
if the number is 3-5, a big slip if the number is 6, a small slip if the number is 7-8,
and fall asleep if the number is 9-10.
You must keep track of each contender’s position and display each contender’s
position using a graphics image. Graphics images for the tortoise and hare can
be found in the course downloads folder. You may have to adjust the length of
the course and the size of the applet window to get just the right look.
Hint: Get the overall logic for the program working before you deal with the
graphics. You might find it helpful (but it is not absolutely necessary) to structure
the overall control flow based on a simulation clock. Each time the clock “ticks”
the contenders move.
My program doesn't give an error message, but when I try to run it, I get a blank image of two rectangles with a bunch of divisions, it says "Race" and "Turn Null." I have tried the best I could to find what's wrong, but I think it could use a different pair of eyes. Please help if possible!
Here is my code:
import java.awt.*;
import java.applet.*;
public class TortoiseAndHareProject extends Applet {
Image tortoise, hare; //creates two images, tortoise and hare
int tortX = 250, hareX = 250; //sets them both to start at pixel 250
final int tortY = 100, hareY = 300, WIDTH = 15, HEIGHT = 50; //sets finals tortY, hareY, WIDTH, and HEIGHT = variables to use in the race
//WIDTH will serve as a counter for distance
int turn;
String turnNum;
int move;
String tMove, hMove;
public void init() {
tortoise = getImage(getDocumentBase(), "tortoise.gif");
hare = getImage(getDocumentBase(), "hare.gif");
move = 0;
turn = 0;
}
public void control() throws InterruptedException {
while ((tortX < 985) || (hareX < 985)) { //while neither has won the race yet (985 = finish)
move = (int) (10 * Math.random());
switch (move) {
case 1:
case 2:
tortX += (3 * WIDTH);
hareX += (9 * WIDTH);
tMove = "Fast Plod";
hMove = "Big Hop";
break;
case 3:
case 4:
case 5:
tortX += (3 * WIDTH);
hareX += WIDTH;
tMove = "Fast Plod";
hMove = "Small Hop";
break;
case 6:
tortX += WIDTH;
if (hareX == 250) { //nothing happens, the hare just doesn't move
} else if (hareX <= (250 + (11 * WIDTH))) //if hare is less than 12 squares ahead of 250
hareX = 250; //the hare just goes back to 250
else
hareX -= (12 * WIDTH); //the hare just moves back 12 * WIDTH
tMove = "Slow Plod";
hMove = "Big Slip";
break;
case 7:
case 8:
tortX += (1 * WIDTH);
if (hareX == 250) { //nothing happens, the hare just doesn't move
} else if (hareX <= (250 + (WIDTH))) //if hare is less than 2 squares ahead of 250
hareX = 250; //the hare just goes back to 250
else
hareX -= (2 * WIDTH); //the hare just moves back 2 * WIDTH
tMove = "Slow Plod";
hMove = "Small Slip";
break;
case 9:
case 10:
if (tortX == 250) { //nothing happens
} else if (tortX <= (250 + (5 * WIDTH))) //if the tortoise is less than 6 squares ahead of 250
tortX = 250; //the tortoise just goes back to 250
else
tortX -= (6 * WIDTH);
tMove = "Slip";
hMove = "Fall Asleep.";
break;
}
turn++;
turnNum = (turn + "");
repaint();
Thread.sleep(30);
}
tortX = 985;
hareX = 985;
repaint();
}
public void paint(Graphics screen) {
drawRace(screen);
if (tortX >= 985) {
screen.setFont(new Font("Times New Roman", Font.ITALIC, 48));
screen.drawString("Tortoise Wins", 650, 240);
clearCurrent(screen);
fillNext(screen);
} else if (hareX >= 985) { //if hareX has gotten greater than 985
screen.setFont(new Font("Times New Roman", Font.ITALIC, 48));
screen.drawString("Hare Wins", 650, 240);
clearCurrent(screen);
fillNext(screen);
} else {
screen.drawString(("Turn " + turnNum), 621, 55);
screen.setFont(new Font("Times New Roman", Font.ITALIC, 12));
if (tMove != null) {
screen.drawString(tMove, 59, 65);
}
if (hMove != null) {
screen.drawString(hMove, 66, 255);
}
clearCurrent(screen);
fillNext(screen);
}
stop();
}
public void clearCurrent(Graphics s) {
s.clearRect(tortX + 1, tortY + 1, WIDTH - 1, HEIGHT - 1);
s.clearRect(hareX + 1, hareY + 1, WIDTH - 1, HEIGHT - 1);
//in order to get a new screen
}
public void fillNext(Graphics s) {
s.fillRect(tortX + 1, tortY + 1, WIDTH - 1, HEIGHT - 1);
s.fillRect(hareX + 1, hareY + 1, WIDTH - 1, HEIGHT - 1);
//in order to fill the screen with the tortoise & hare
}
public void drawRace(Graphics s) {
s.drawRect(250, 100, 750, 50); //draws a rectangle for the race
s.drawRect(250, 300, 750, 50); //draws another rectangle for the race
int lineX = 265, lineYi = 100, lineYf = 150;
for (int i = 1; i <= 98; i++) { //for the duration of the race
if (lineX == 1000) {
lineX = 265;
lineYi = 300;
lineYf = 350;
}
s.drawLine(lineX, lineYi, lineX, lineYf);
lineX += 15;
}
s.fillRect(tortX + 1, tortY + 1, WIDTH - 1, HEIGHT - 1);
s.fillRect(hareX + 1, hareY + 1, WIDTH - 1, HEIGHT - 1);
s.drawImage(tortoise, 59, 80, this);
s.drawImage(hare, 66, 271, this);
s.setFont(new Font("Times New Roman", Font.BOLD, 24));
s.drawString("Race", 250, 55);
}
public void stop() {
}
}
The Purpose:
I have an assignment that involves a race between a tortoise and a hare. Basically, I have two .gif files, one of a tortoise and one of a hare, that are to be displayed in an applet and race each other by advancing along the x axis. In the process, I must use a random number generator to generate different "moves" in which the animal (image file) moves forward or backwards a certain number of positions. This loop must be repeated until one of the animals reach the 50th position. There also must be a time delay of some sort in between each move that the two animals make.
The Code:
import java.util.Random;
import java.awt.Graphics;
import java.applet.Applet;
import java.awt.Image;
import java.awt.Color;
public class ProjectTwo extends Applet
{
Image tortoise, hare;
Random generator = new Random();
int[] positions = new int [50];
int[] randoms = new int[50];
public int t = 0;
public int h = 0;
public int s = 0;
public void init()
{
for (int i = 0; i < positions.length; i++)
{
positions[i] = ((i * 145) + 10);
}
for (int x = 0; x < randoms.length; x++)
{
randoms[x] = generator.nextInt(6) + 1;
}
tortoise = getImage( getDocumentBase(), "images/tortoise.gif" );
hare = getImage( getDocumentBase(), "images/hare.gif" );
}
public void delay()
{
for(int g = 0; g <= 90000000; g++) ;
}
public void paint (Graphics g)
{
g.drawImage (tortoise, positions[0], 10, this);
g.drawImage (hare, positions[0], 137, this);
delay();delay();delay();
do
{
switch (randoms[s])
{
case 1:
case 2:
t += 3;
h += 9;
if (t >= 50)
{
g.drawImage (tortoise, positions[50], 10, this);
}
else
{
g.drawImage (tortoise, positions[t], 10, this);
}
if (h >= 50)
{
g.drawImage (hare, positions[50], 137, this);
}
else
{
g.drawImage (hare, positions[h], 137, this);
}
s++;
break;
case 3:
case 4:
case 5:
t += 3;
h += 1;
if (t >= 50)
{
g.drawImage (tortoise, positions[50], 10, this);
}
else
{
g.drawImage (tortoise, positions[t], 10, this);
}
if (h >= 50)
{
g.drawImage (hare, positions[50], 137, this);
}
else
{
g.drawImage (hare, positions[h], 137, this);
}
s++;
break;
case 6:
t += 1;
h -= -12;
if (t >= 50)
{
g.drawImage (tortoise, positions[50], 10, this);
}
else
{
g.drawImage (tortoise, positions[t], 10, this);
}
if (h <= 0)
{
g.drawImage (hare, positions[0], 137, this);
t = 0;
}
else
{
g.drawImage (hare, positions[h], 137, this);
}
s++;
break;
case 7:
case 8:
t += 1;
h -= 2;
if (t >= 50)
{
g.drawImage (tortoise, positions[50], 10, this);
}
else
{
g.drawImage (tortoise, positions[t], 10, this);
}
if (h <= 0)
{
g.drawImage (hare, positions[0], 137, this);
t = 0;
}
else
{
g.drawImage (hare, positions[h], 137, this);
}
s++;
break;
case 9:
case 10:
t -= 6;
if (t <= 0)
{
g.drawImage (tortoise, positions[0], 10, this);
t = 0;
}
else
{
g.drawImage (tortoise, positions[t], 10, this);
}
g.drawImage (hare, positions[h], 137, this);
s++;
break;
}
} while (t >= 50 | h >= 50);
}
}
The Expected Result:
The tortoise.gif file appears at (10, 10) and the hare.gif file appears at (10, 137)
There is a short delay until the random number generator rolls a 4 (It doesn't matter to me where/when the numbers are created as long as they are in between 1-10)
The tortoise advances 3 positions (formula for positions is 145x + 10, making the tortoise's new coordinates (445, 10)
The hare advances 1 position, making it's new coordinates (155, 10)
Repeat process until one advances to the 50th position(see additional information for what should happen for every random number)
What Actually Happens
The tortoise and the hare show up in their appropriate places, but do not move.
The Problem
I want the tortoise and the hare to advance their positions according to a timer, but after compiling the code and launching the applet, due to some kind of mistake in my code, they do not.
What I Think Might Be Wrong
I believe the problem might have to do with how I implemented the delay, my using an element in an array as the x value for the images, or conflicting variables in my do-while loop and/or my case statement, although I do not know what is wrong nor what I should fix. However, I now realize that if the program does work, due to my use of randoms.length as a constructor in my for loop near the top, the tortoise and the hare will only change positions 50 times before stopping no matter what. I don't know how to fix this problem either.
Additional Information
Here is a chart on how far the animals should move according to the random number chosen:
1-2 = Tortoise moves +3 positions, Hare moves + 9
3-5 = Tortoise moves +3 positions, Hare moves +1
6 = Tortoise moves +1 position, Hare moves back -12
7-8 = Tortoise moves +1 position, Hare moves back -2
9-10 = Tortoise moves back -6 positions, Hare does not move at all
An animal can move no farther back than the original position (positions[0]). If the number goes below, the animal must stay at that position. This rule also applies for positions greater than 50.
This code compiles fine, but the applet doesn't function as attempted.
I apologize if this code seems very messy, as I am fairly new to coding with Java as well as working with applets.
Seems you should change
while (t >= 50 | h >= 50)
to
while (t <= 50 | h <= 50)
since t and h both start out at 0,and you want to loop while they are lower or equal to 50, not while they are higher or equal to 50.
I am making a graph of a sound speed profile with java graphics. I have the static graph drawn (the one that pops up when you run the program), but I am trying to implement it such that if the user clicks on either the x or y axis, then it will zoom in so you can look at the sound speed profile more closely. I don't have the sound speed profile in the graph yet (I already know how to do that, I'm just saving the effort of drawing it until I have the zoom feature figured out). Does anyone have any ideas as to how to make this work? I have seen people trying to use the Affine Transform for similar tasks, but I am not sure that's the right thing to do or if I'm even doing this correctly. The particular code to look at is the paint(), zoomIn(), and mouseClicked() method. Ideas would be much apprecaited!
public class SoundSpeedProfile extends JPanel implements MouseListener, ActionListener {
private String title;
private String subTitle;
private JFrame frame;
private Graphics g;
.
.
.
/**Draws the sound speed profile and surrounding graphics
* #param Graphics g - graphics object
*/
public void paint(Graphics g){
this.g = g;
super.paint(g); //the super knows how to draw "standard" components like squares, rectangles, circles, etc
g.setColor(Color.DARK_GRAY);
//1) Set up the graph the sound speed profile lives in
//X-Axis for Speeds
g.drawLine(100, 150, 450, 150);//the graphics display has 0,0 in the upper left corner versus the lower left corner
int i = 120;
int k = 1460;
while (i<440){
g.drawString("|", i, 155);
g.drawString("" + k + "", i-2, 140);
k = k + 20;
i = i + 60;
}
//Y-Axis
g.drawLine(100, 500, 100, 150);
k= 7000;
int j = 500;
while (j>160){
g.drawString("" + k, 60, j);
g.drawString("--", 94, j);
k = k - 1000;
j = j - 50;
}
Font f1 = new Font("Serif", 4, 15);
g.setFont(f1);
g.drawString(this.title, 200,30);//Graph Title
g.drawString(this.subTitle, 225, 50);
Font f2 = new Font("Serif", 2, 15);
g.setFont(f2);
g.drawString("Sound Speed ", 200, 110);//x-axis label
g.drawString("(" + spdUnits + ")", 290, 110); //Units label--taken from input array
g.drawString("Depth", 10, 180); //y-axis label
g.drawString("(" + depUnits + ")", 07, 200); //Units label--taken from input array
//((Graphics2D)g).scale(20, 20);
}
/**Creates and shows the GUI drawing of the sound speed profile in a JFrame
*/
private void createAndShowGUI(){
frame = new JFrame("Sound Speed Profile");
canvas = new Canvas();
frame.add(canvas);
frame.addMouseListener(this);
frame.setBackground(Color.cyan);
frame.setSize(600,800);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLayout(new BorderLayout());
frame.add(this, BorderLayout.CENTER);//add the sound speed profile graphic and set a Border Layout
//frame.pack();
frame.setVisible(true);
}
/**
* Runs test cases
* #param args
*/
public static void main (String [] args){
ssp.setTitle("Sound Speed Profile 1");
ssp.setSubtitle("June 1, 2012");
ssp.createAndShowGUI();
ssp.repaint(); //necessary?
}
#Override
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void mouseClicked(MouseEvent arg0) {
int x = arg0.getX();
//System.out.println("x: " + x);
int xMin = x - 50;
int xMax = x + 50;
int y = arg0.getY();
//System.out.println("y: " + y);
int yMin = y-50;
int yMax = y + 50;
//If the user clicked on the x-axis
if ( 160<y && y<180 && 100<x && x<450){
System.out.println("About to zoom in on the x-axis");
zoomIn(x, y);
//System.out.println("zooming in on the x-axis");
}
//If the user clicked on the y-axis
if (90<x && x<110 && 150 <y && y<500){
//System.out.println("zooming in on the y-axis");
}
}
public void zoomIn(int x, int y){
AffineTransform old = ((Graphics2D) g).getTransform();
for (double zoom = 1; zoom >=0.1; zoom=-0.1){
AffineTransform tr2 =AffineTransform.getTranslateInstance(-x, -y);
AffineTransform tr= AffineTransform.getScaleInstance(zoom,zoom);
tr.concatenate(tr2); tr2=tr;
tr =AffineTransform.getTranslateInstance(x, y);
tr.concatenate(tr2); tr2=tr;
tr= new AffineTransform(old);
tr.concatenate(tr2); tr2=tr;
((Graphics2D)g).setTransform(tr2);
((Graphics2D)g).drawRect(x, y, 10, 10);
((Graphics2D)g).setTransform(old);
}
}