I want to use 4 threads in my applet and used Runnable interface wants to move all the threads around required position.
When in my applet, clouds image walks from o to 750 at y axis and the helicopter starts walking when clouds comes at 150 in y axis and helicopter walks upto it reaches to the 350 and then this thread stops.
And then when my helicopter reaches to the 200 then a man image comes out and walks to the x axis, it will stop when it has walked 5 to 10 milliseconds.
following is my code:
import java.applet.* ;
package com.pack;
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
public class HelicopterScene extends Applet {
Image a, b, c;
int i, j, h, p;
public void init() {
i = 20;
j = 750;
h = 0;
a = getImage(getCodeBase(), "HelicopterAttack.jpg");
b = getImage(getCodeBase(), "pppp.png");
c = getImage(getCodeBase(), "helicopter1.png");
}
public void paint(Graphics g) {
showStatus(" Helicopter Scene Applet is started.....");
g.drawImage(a, 0, 0, this);
if (i <= 750 && j >= 20) {
if (i >= 150) {
g.drawImage(c, h, 255, 150, 35, this);
h++;
repaint();
try {
Thread.sleep(20);
} catch (InterruptedException w) {
}
}
g.drawImage(b, j, 120, 90, 70, this);
g.drawImage(b, i, 180, 120, 70, this);
i++;
j--;
repaint();
try {
Thread.sleep(10);
if (i == 750 && j == 20) {
p = h;
g.drawImage(c, p, 255, 150, 35, this);
h++;
repaint();
try {
Thread.sleep(20);
} catch (InterruptedException w) {
}
i = 20;
j = 750;
}
} catch (InterruptedException e) {
}
}
}
}
First of all, you never want to sleep on the UI thread. Second, you never want to paint off the UI thread. You should investigate SwingUtilities.invokeLater().
Related
I am working on a small Java Applet that has 3 balls bounce around on screen. When they collide with the walls they make one sound and when they collide with eachother they make another sound.
My issue is that the balls flicker for some reason and I am not sure why. If someone can explain why they are flickering and how I can go about fixing the issue that would be greatly appreciated.
Here is my code:
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
public class ass3 extends Applet implements Runnable {
int[] positionX = {0, 0, 0};
int[] positionY = {0, 0, 0};
int[] incrementX = {3, 7, 4};
int[] incrementY = {8, 4, 5};
Thread t;
AudioClip sound;
AudioClip collide;
public void init(){
sound = getAudioClip(getDocumentBase(), "Audio1.au");
collide = getAudioClip(getDocumentBase(), "Audio2.au");
}
public void start() {
t = new Thread(this);
t.start();
}
public void paint(Graphics g) {
g.fillOval(getWidth()-50-positionX[0], getHeight()-50-positionY[0], 50, 50);
g.fillOval(getWidth()-450-positionX[1], getHeight()-450-positionY[1], 50, 50);
g.fillOval(getWidth()-450-positionX[2], getHeight()-50-positionY[2], 50, 50);
}
public void run() {
while (true) {
try {
Thread.sleep(30);
} catch (InterruptedException e) {}
for (int i=0; i < 3; i++) {
positionX[i] += incrementX[i];
positionY[i] += incrementY[i];
}
// ball 1
if (positionX[0] > 500 || positionX[0] < 0) {
incrementX[0] = -incrementX[0];
sound.play();
}
repaint();
if (positionY[0] > 500 || positionY[0] < 0) {
incrementY[0] = -incrementY[0];
sound.play();
}
repaint();
// ball 2
if (positionX[1] > 100 || positionX[1] < -400) {
incrementX[1] = -incrementX[1];
sound.play();
}
repaint();
if (positionY[1] > 100 || positionY[1] < -400) {
incrementY[1] = -incrementY[1];
sound.play();
}
repaint();
// ball 3
if (positionX[2] > 100 || positionX[2] < -400) {
incrementX[2] = -incrementX[2];
sound.play();
}
repaint();
if (positionY[2] > 500 || positionY[2] < 0) {
incrementY[2] = -incrementY[2];
sound.play();
}
repaint();
// collision
if (Math.sqrt(((getWidth()-50-positionX[0])-(getWidth()-450-positionX[1]))*((getWidth()-50-positionX[0])-(getWidth()-450-positionX[1])) + ((getHeight()-50-positionY[0])-(getHeight()-450-positionY[1]))*((getHeight()-50-positionY[0])-(getHeight()-450-positionY[1]))) <= 50) {
incrementX[0] = -incrementX[0];
incrementY[0] = -incrementY[0];
incrementX[1] = -incrementX[1];
incrementY[1] = -incrementY[1];
collide.play();
}
repaint();
if (Math.sqrt(((getWidth()-50-positionX[0])-(getWidth()-450-positionX[2]))*((getWidth()-50-positionX[0])-(getWidth()-450-positionX[2])) + ((getHeight()-50-positionY[0])-(getHeight()-50-positionY[2]))*((getHeight()-50-positionY[0])-(getHeight()-50-positionY[2]))) <= 50) {
incrementX[0] = -incrementX[0];
incrementY[0] = -incrementY[0];
incrementX[2] = -incrementX[2];
incrementY[2] = -incrementY[2];
collide.play();
}
repaint();
if (Math.sqrt(((getWidth()-450-positionX[2])-(getWidth()-450-positionX[1]))*((getWidth()-450-positionX[2])-(getWidth()-450-positionX[1])) + ((getHeight()-50-positionY[2])-(getHeight()-450-positionY[1]))*((getHeight()-50-positionY[2])-(getHeight()-450-positionY[1]))) <= 50) {
incrementX[2] = -incrementX[2];
incrementY[2] = -incrementY[2];
incrementX[1] = -incrementX[1];
incrementY[1] = -incrementY[1];
collide.play();
}
repaint();
}
}
}
Simple, stop calling repaint multiple times. (You're calling it multiple times in your while loop).
I am trying to make a little mini game, where u can move around. I have written a code, which did work. But when I tried to shorten my code and make it looks nicer, I stumble upon a error I could not solve by myself.
Main:
package eksamenstest;
import javax.swing.JFrame;
public class Eksamenstest extends JFrame {
public Eksamenstest() throws InterruptedException
{
JFrame SOJ = new JFrame("Sword Of Justice");
SOJ.pack();
SOJ.setSize(1000,700);
SOJ.setVisible(true);
SOJ.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
SOJ.add(new Grafik());
}
public static void main(String[] args) throws InterruptedException
{
new Eksamenstest();
new Musik();
new SpillerOne();
}
}
Graphics:
package eksamenstest;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;
import javax.swing.JPanel;
public class Grafik extends JPanel
{
int Menu = 1;
int Player1Liv = 3;
int Player2Liv = 3;
int DødP1 = 1;
int DødP2 = 1;
int WeaponON2;
int WeaponON1;
int Skjold;
int Skjold1;
int x = 100;
int y = 360;
int x_1 = 820;
int y_1 = 360;
public Grafik(){}
public void paint(Graphics g)
{
//Grafikken af banen
Image Bane2 = Toolkit.getDefaultToolkit().getImage("Bane2.png");
g.drawImage(Bane2, 0, 0, 1000, 800, this);
Image Plank = Toolkit.getDefaultToolkit().getImage("Plank.jpg");
g.drawImage(Plank, 100, 500, 800, 10, this);
Image lava = Toolkit.getDefaultToolkit().getImage("lava.png");
g.drawImage(lava, 0, 520, 1000, 260, this);
if(Menu == 1)
{
Image Menu2 = Toolkit.getDefaultToolkit().getImage("Menu.png");
g.drawImage(Menu2, 100, -30, 900, 700, this);
}
//Player 1 - Grafikken der viser hvordan spilleren står.
if(WeaponON1 == 0){
Image PlayerStå = Toolkit.getDefaultToolkit().getImage("Stå.png");
g.drawImage(PlayerStå, x, y, 80, 140, this);
}
if(WeaponON1 == 1){
Image PlayerSværdOP = Toolkit.getDefaultToolkit().getImage("OP.png");
g.drawImage(PlayerSværdOP, x, y, 80, 140, this);
}
if(WeaponON1 == 2){
Image PlayerSværdFrem = Toolkit.getDefaultToolkit().getImage("Frem.png");
g.drawImage(PlayerSværdFrem, x, y, 80, 140, this);
}
if(Skjold == 1){
Image Player1Skjold = Toolkit.getDefaultToolkit().getImage("Player1Skjold.png");
g.drawImage(Player1Skjold, x, y, 80, 140, this);
}
if(Player1Liv == 0){
Image DødP = Toolkit.getDefaultToolkit().getImage("DødP.png");
g.drawImage(DødP, x, y, 80, 140, this);
}
if(Player2Liv == 0){
Image Jubel = Toolkit.getDefaultToolkit().getImage("Jubel.png");
g.drawImage(Jubel, x, y, 80, 140, this);
}
//Player 2 - Grafikken der viser hvordan spilleren står.
if(WeaponON2 == 0){
Image PlayerStå1 = Toolkit.getDefaultToolkit().getImage("Stå1.png");
g.drawImage(PlayerStå1, x_1, y_1, 80, 140, this);
}
if(WeaponON2 == 1){
Image PlayerSværdOP1 = Toolkit.getDefaultToolkit().getImage("OP1.png");
g.drawImage(PlayerSværdOP1, x_1, y_1, 80, 140, this);
}
if(WeaponON2 == 2){
Image PlayerSværdFrem1 = Toolkit.getDefaultToolkit().getImage("Frem1.png");
g.drawImage(PlayerSværdFrem1, x_1, y_1, 80, 140, this);
}
if(Skjold1 == 1){
Image Player2Skjold = Toolkit.getDefaultToolkit().getImage("Player2Skjold.png");
g.drawImage(Player2Skjold, x_1, y_1, 80, 140, this);
}
if(Player2Liv == 0){
Image DødPA = Toolkit.getDefaultToolkit().getImage("DødP.png");
g.drawImage(DødPA, x_1, y_1, 80, 140, this);
}
if(Player1Liv == 0){
Image Jubel = Toolkit.getDefaultToolkit().getImage("Jubel.png");
g.drawImage(Jubel, x_1, y_1, 80, 140, this);
}
//Health Bars / Stamina / Navne / Win
//Player 1
Image PlayerNavn = Toolkit.getDefaultToolkit().getImage("Player1Navn.png");
g.drawImage(PlayerNavn, 30, 50, 70, 30, this);
if(Player1Liv == 3){
Image Liv100B = Toolkit.getDefaultToolkit().getImage("Liv100B.png");
g.drawImage(Liv100B, 30, 80, 120, 40, this);
}
if(Player1Liv == 2){
Image Liv75B = Toolkit.getDefaultToolkit().getImage("Liv75B.png");
g.drawImage(Liv75B, 30, 80, 120, 40, this);
}
if(Player1Liv == 1){
Image Liv50B = Toolkit.getDefaultToolkit().getImage("Liv25B.png");
g.drawImage(Liv50B, 30, 80, 120, 40, this);
}
if(Player1Liv == 0){
Image Liv0B = Toolkit.getDefaultToolkit().getImage("Liv0B.png");
g.drawImage(Liv0B, 30, 80, 120, 40, this);
DødP1 = 0;
Image Player2Win = Toolkit.getDefaultToolkit().getImage("Player2Wins.png");
g.drawImage(Player2Win, 350, 80, 350, 110, this);
}
// Player 2
Image PlayerNavn1 = Toolkit.getDefaultToolkit().getImage("Player2Navn.png");
g.drawImage(PlayerNavn1, 900, 50, 70, 30,this);
if(Player2Liv == 3){
Image Liv100R = Toolkit.getDefaultToolkit().getImage("Liv100R.png");
g.drawImage(Liv100R, 850, 80, 120, 40, this);
}
if(Player2Liv == 2){
Image Liv75R = Toolkit.getDefaultToolkit().getImage("Liv75R.png");
g.drawImage(Liv75R, 850, 80, 120, 40, this);
}
if(Player2Liv == 1){
Image Liv50R = Toolkit.getDefaultToolkit().getImage("Liv25R.png");
g.drawImage(Liv50R, 850, 80, 120, 40, this);
}
if(Player2Liv == 0){
Image Liv0R = Toolkit.getDefaultToolkit().getImage("Liv0R.png");
g.drawImage(Liv0R, 850, 80, 120, 40, this);
DødP2 = 0;
Image Player1Win = Toolkit.getDefaultToolkit().getImage("Player1Wins.png");
g.drawImage(Player1Win, 350, 80, 350, 110, this);
}
}
}
Player Movement
package eksamenstest;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JFrame;
public class SpillerOne extends JFrame implements ActionListener, KeyListener {
int x = 100;
int y = 360;
int xHøjre;
int xVenstre;
int DødP1;
int Player1Liv;
int iLava;
int x_1;
int Player2Liv;
int Skjold1;
int WeaponON1;
int Menu = 1;
int SværdTid;
int Sværd;
int Skjold;
public SpillerOne()
{
addKeyListener(this);
setFocusable(true);
setFocusTraversalKeysEnabled(false);
}
#Override
public void actionPerformed(ActionEvent e)
{
PlayerOneMove();
repaint();
}
#Override
public void keyTyped(KeyEvent e) {
}
#Override
public void keyPressed(KeyEvent e) {
int c = e.getKeyCode();
//Menu
if(c == KeyEvent.VK_O){
Menu = 1;
}
if(c == KeyEvent.VK_P){
Menu = 0;
}
// Player
if(DødP1 == 1){
if(c == KeyEvent.VK_A){
xVenstre = 1;
WeaponON1 = 0;
Sværd = 0;
}
if(c == KeyEvent.VK_D){
xHøjre = 1;
WeaponON1 = 0;
}
if(WeaponON1 == 1){
if(SværdTid < 3){
if(c == KeyEvent.VK_W){
WeaponON1 = 2;
SværdTid++;
}
}
}
if(c == KeyEvent.VK_S){
WeaponON1 = 1;
Sværd = 1;
}
if(c == KeyEvent.VK_Q){
Skjold = 1;
SværdTid++;
}
}
if(c == KeyEvent.VK_E){
SværdTid--;
WeaponON1 = 0;
}
}
#Override
public void keyReleased(KeyEvent e)
{
int c = e.getKeyCode();
// Spiller 1
if(c == KeyEvent.VK_A){
xVenstre = 0;
}
if(c == KeyEvent.VK_D){
xHøjre = 0;
}
if(c == KeyEvent.VK_Q){
Skjold = 0;
SværdTid = SværdTid;
}
if(c == KeyEvent.VK_W){
if(Sværd == 1)
WeaponON1 = 1;
}
if(c == KeyEvent.VK_E){
SværdTid = SværdTid;
WeaponON1 = 0;
}
}
public void PlayerOneMove()
{
// Spiller et Bevægelse
x = x + xHøjre; //Højre
x = x - xVenstre; //Venstre
if(WeaponON1 == 2){ //Tjekker om spilleren har våbnet fremme og hvis ja, så tjekker den om modspilleren har skjold på, hvis ikke, mister person 2 liv.
if(Skjold1 == 0){
if(x > x_1-80 && x < x_1 + 80){
x = 100;
x_1 = 820;
Player2Liv--;
}
}
if(WeaponON1 == 2){
if(Skjold1 == 1){
if(x > x_1-80 && x < x_1 + 80){
x_1 = x_1 + 60;
}
}
}
}
// Falder ned i lava
if(x < 100 && 100 > x + 80){ //Tjekker om player 1 er i lava ved venstre side.
DødP1 = 0;
Player1Liv = 0;
iLava = 1;
if(y < 500){
y++;
}
}
if(x > 900){ //Tjekker om player 1 er i lava ved højre side.
DødP1 = 0;
Player1Liv = 0;
iLava = 1;
if(y < 500){
y++;
}
}
}
}
I have a feeling that this error is caused because I have not repainted somewhere.
So, a list of issues...
First
There are two JFrames - which one is actually been used for what? As far as I can tell, SpillerOne is never displayed, so there is no possible way for it to be able to react to key events. Equally, your ActionListener doesn't seem to be attached to anything which can actually generate actions.
This also raises a bunch of questions about the relationship between SpillerOne and Grafik. They seem to be sharing variable names, but there is no way for them to be sharing state, so even if the KeyListener worked, Grafik would never reflect the changes in SpillerOnes state
Second
You've implemented your custom painting the wrong way. It's highly discouraged to override paint, instead, you should be overriding paintComponent AND calling super.paintComponent to ensure that requirements of the paint chain are upheld
See Performing Custom Painting and Painting in AWT and Swing for more details
You also seem to be putting a lot of state logic into your Grafik class, this is going to become exponentially more difficult to maintain as the complexity increases. Instead, each distinct operation should be it's own class, focused on performing as few dedicated operations as possible
Thirdly
KeyListener is a poor choice for monitoring for key events. While there are "hacks" that attempt to "solve" the focus related issues with KeyListener, none of them can achieve a reliable result.
If you do any research into KeyListener related issues, you will quickly find that the Key bindings API is often sighted as the most reliable solution to the problem
Overall
You code makes no sense. Why are there two frames? What is the ActionListener for and how is it attached to something that generates actions? Why doesn't the Grafik act as the key/action listener?
I think you have some significant thinking and redesigning to do
Im almost finished with this car project im working on but cant seem to get the key events to work. I think it has to do with my action listener with my timer but im not sure. When I press the up arrow key the timer delay is supposed to decrease and vice versa for the down arrow key. I have the commands written but they are not registering input. If anyone could give me some pointers I'd appreciate it
Code:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class RaceCar extends JFrame{
public RaceCar(){
add(new CarPic());
}
public static void main(String[] args){
JFrame frame = new RaceCar();
frame.setTitle("Brady Kedge: Race Car");
frame.setSize(300, 150);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
public class CarPic extends JPanel implements KeyListener
{
private int x = 0;
private int y = 150;
private int z = 300;
Timer mytimer = new Timer(50, new ActionListener());
public CarPic()
{
mytimer.start();
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
y = getHeight();
z = getWidth();
g.setColor(Color.WHITE);
g.fillRect(0, 0, z, y);
Polygon polygon = new Polygon();
polygon.addPoint(x + 10, y - 20);
polygon.addPoint(x + 20, y - 30);
polygon.addPoint(x + 30, y - 30);
polygon.addPoint(x + 40, y - 20);
if(x < z - 40)
{
g.setColor(Color.BLACK);
g.fillOval(x + 10, y - 10, 10, 10);
g.fillOval(x + 30, y - 10, 10, 10);
g.setColor(Color.BLUE);
g.fillRect(x, y - 20, 50, 10);
g.setColor(Color.BLUE);
g.fillPolygon(polygon);
}
else
x = 0;
}
public void actionPerformed(ActionEvent e){
x+=10;
repaint();
}
#Override
public void keyTyped(KeyEvent k) {
//Fill
}
#Override
public void keyPressed(KeyEvent k) {
int delay = mytimer.getDelay();
if(k.getKeyCode() == KeyEvent.VK_UP)
mytimer.setDelay(delay > 10 ? delay - 10 : 0);
else if(k.getKeyCode() == KeyEvent.VK_DOWN)
mytimer.setDelay(delay < 5000 ? delay + 10 : 5000);
}
#Override
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub
}
}
}
First of all, you never register a KeyListener with your component (implementing KeyListener isn't enough).
Second of all, KeyListener will only raise KeyEvents if the component it is registered to has focus and is focusable.
A better solution would be to use the key bindings API, which provides you with the means to configure the focus level at which a component will trigger key events.
Also, personally, instead of modifying the Timer delay, I would have use a speed modifier (of type double) which would be percentage of the speed you want. In this way 1 would normal speed, 0.5 half speed and 2 double speed, for example.
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.
first of all thanks for taking the time to read my question!
I'm developing a 2D java game, with a tile based map. When my character moves around,
everthing is fine, although when he moves left, vertical white lines, also know as artifacting/tearing, appear on the screen. Same thing happens when he moves up, though the lines are horizontal and much smaller in width. Oddly enough, this doesn't happen when I move right or down. I have searched around on internet to find a solution, though I haven't encountered anything that fit my problem.
Here's the code, although I've heavily downsized and simplified it for the sake of testing. It can therefore be run without any images. Thank you for any answer you provide!
package adriana;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import javax.swing.JFrame;
/**
*
* #author Christophe
*/
public class Main extends JFrame implements Runnable{
public Image dbImage;
public Graphics dbGraphics;
//Image + Array size
final static int listWidth = 500, listHeight = 500;
//Move Variables
int playerX = 320, playerY = 240, xDirection, yDirection;
//Sprites
BufferedImage spriteSheet;
//Lists for sprite sheet: 1 = STILL; 2 = MOVING_1; 3 = MOVING_2
BufferedImage[] ARCHER_NORTH = new BufferedImage[4];
BufferedImage[] ARCHER_SOUTH = new BufferedImage[4];
BufferedImage[] ARCHER_EAST = new BufferedImage[4];
BufferedImage[] ARCHER_WEST = new BufferedImage[4];
Image[] TILE = new Image[12];
//Animation Variables
int currentFrame = 0, framePeriod = 150;
long frameTicker = 0l;
Boolean still = true;
Boolean MOVING_NORTH = false, MOVING_SOUTH = false, MOVING_EAST = false, MOVING_WEST = false;
BufferedImage player;
//World Tile Variables
//20 X 15 = 300 tiles
Rectangle[][] blocks = new Rectangle[listWidth][listHeight];
int tileX = 250, tileY = 250;
Rectangle playerRect = new Rectangle(playerX + 4,playerY+20,32,20);
//Map Navigation
static final byte PAN_UP = 0, PAN_DOWN = 1, PAN_LEFT = 2, PAN_RIGHT = 3;
final int speed = 8;
public Main(){
this.setTitle("JAVA4K");
this.setSize(640,505);
this.setResizable(false);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
addKeyListener(new AL());
for(int y = 0; y < listHeight; y++){
for(int x = 0; x < listWidth; x++){
blocks[x][y] = new Rectangle(x*32-8000, y*32-8000, 32, 32);
}
}
}
//Key Listener
public class AL extends KeyAdapter{
public void keyPressed(KeyEvent e){
int keyInput = e.getKeyCode();
still = false;
if(keyInput == e.VK_LEFT){
navigateMap(PAN_RIGHT);
}if(keyInput == e.VK_RIGHT){
navigateMap(PAN_LEFT);
}if(keyInput == e.VK_UP){
navigateMap(PAN_DOWN);
}if(keyInput == e.VK_DOWN){
navigateMap(PAN_UP);
}
}
public void keyReleased(KeyEvent e){
int keyInput = e.getKeyCode();
setYDirection(0);
setXDirection(0);
if(keyInput == e.VK_LEFT){
}if(keyInput == e.VK_RIGHT){
}if(keyInput == e.VK_UP){
}if(keyInput == e.VK_DOWN){
}
}
}
public void moveMap(){
for(int a = 0; a < 500; a++){
for(int b = 0; b < 500; b++){
if(blocks[a][b] != null){
blocks[a][b].x += xDirection;
blocks[a][b].y += yDirection;
}
}
}
}
public void navigateMap(byte pan){
switch(pan){
default:
System.out.println("Unrecognized pan!");
break;
case PAN_UP:
setYDirection(-1 * speed);
break;
case PAN_DOWN:
setYDirection(+1 * speed);
break;
case PAN_LEFT:
setXDirection(-1 * speed);
break;
case PAN_RIGHT:
setXDirection(+1 * speed);
break;
}
}
public void setXDirection(int xdir){
xDirection = xdir;
if(blocks[0][0] != null) tileX = ((playerRect.x - blocks[0][0].x) / 32)-1;
}
public void setYDirection(int ydir){
yDirection = ydir;
if(blocks[0][0] != null) tileY = ((playerRect.y - blocks[0][0].y) / 32)-1;
}
public void paint(Graphics g){
dbImage = createImage(getWidth(), getHeight());
dbGraphics = dbImage.getGraphics();
paintComponent(dbGraphics);
g.drawImage(dbImage, 0, 25, this);
}
public void paintComponent(Graphics g){
requestFocus();
//Draws tiles and rectangular boundaries for debugging
for(int a = tileX - 18; a < tileX + 20; a++){
for(int b = tileY - 15; b < tileY + 17; b++){
g.setColor(Color.RED);
g.fillRect(blocks[a][b].x, blocks[a][b].y, 32, 32);
g.setColor(Color.BLACK);
g.drawRect(blocks[a][b].x, blocks[a][b].y, 32, 32);
}
}
//Draw player
g.drawRect(playerX, playerY, 40, 40);
repaint();
}
public void run(){
try{
System.out.println("Running");
while(true){
moveMap();
Thread.sleep(13);
}
}catch(Exception e){
e.printStackTrace();
}
}
public static void main(String[] args) {
Main main = new Main();
//Threads
Thread thread1 = new Thread(main);
thread1.start();
}
}
You have no synchronization between the thread updating the map and the drawing. So the map can be in inconsistent state during drawing.
A quick fix would be wrapping the map updating and drawing in a synchronized block:
synchronized(blocks) {
// drawing or modification here
}
(or just making the whole methods synchronized)
Also, the other fields (like those modified in the key listener) are also susceptible being in inconsistent state.
There are other problems too:
Don't override paint() of a frame. Instead override paintComponent() of a JPanel. There's no need to create an image at every redraw, the swing painting mechanism is by default double buffered. See custom painting in swing.
Use KeyBindings instead of a KeyListener
Swing components must be accessed (and created) only in the event dispatch thread.