简体   繁体   中英

Java Applet repaint from another class

I am learning Java game development and I am having an issue understanding why the "Robot" is not moving. I know the issue is with the repaint but I can not figure it out.

please help

Thank

Game Class

     public class GameMain extends Applet implements KeyListener  {


private Image image, character;
private Graphics gpx;
private Droid droid;
private URL base;
private static Background bg1, bg2;

@Override
public void init() {

    setSize(800, 480);
    setBackground(Color.BLACK);
    setFocusable(true);
    addKeyListener(this);
    Frame frame = (Frame) this.getParent().getParent();
    frame.setTitle("My First Game");

    droid = new Droid();
    base = getDocumentBase();
    character = getImage(base, "data/char.png");

}

@Override
public void start() {


    GameThread thread = new GameThread();
    thread.start();
    System.out.println("Thread Started");
}

@Override
public void stop() {


}


@Override
 public void destroy() {

 }
@Override
public void update(Graphics g) {

    if(image == null){
        image = createImage(this.getWidth(), this.getHeight());
        gpx = image.getGraphics();
    }

    gpx.setColor(getBackground());
    gpx.fillRect(0, 0, getWidth(), getHeight());
    gpx.setColor(getForeground());
    paint(gpx);

    g.drawImage(image, 0, 0, this);
}

@Override
public void paint(Graphics g) {
    g.drawImage(character, droid.getPositionX() - 61, droid.getPositionY()- 63, this);
}

@Override
public void keyPressed(KeyEvent key) {

    switch(key.getKeyCode() ){
    case KeyEvent.VK_UP:

        break;
    case KeyEvent.VK_DOWN:

        break;
    case KeyEvent.VK_LEFT:
        droid.moveLeft();
        break;
    case KeyEvent.VK_RIGHT:
        droid.moveRight();
        break;
    case KeyEvent.VK_SPACE:
        droid.jump();
        break;
    }

}

@Override
public void keyReleased(KeyEvent key) {
    switch(key.getKeyCode() ){
    case KeyEvent.VK_UP:

        break;
    case KeyEvent.VK_DOWN:

        break;
    case KeyEvent.VK_LEFT:
        droid.stop();
        break;
    case KeyEvent.VK_RIGHT:
        droid.stop();
        break;
    case KeyEvent.VK_SPACE:

        break;
    }
}



@Override
public void keyTyped(KeyEvent key) {
    // TODO Auto-generated method stub

}

 }

Thread Class

    public class GameThread extends Thread  {

GameMain game;
Droid droid;

private static Background bg1, bg2;

public GameThread(){

    bg1 = new Background(0,0);
    bg2 = new Background(2160, 0);


}



@Override
public void run() {
    game = new GameMain();
    droid = new Droid();
    //Game while loop
    while(true){

        droid.update();
        game.repaint();
    //bg1.update();
    //bg2.update();


    try {
        Thread.sleep(17);
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}
 }


 }

Droid Class

      public class Droid {

private int positionX = 100;
private int positionY = 382;

private int speedX = 0;
private int speedY = 1;

private boolean jump = false;

    public void update(){

    //Update X Position
    if(speedX < 0){
        positionX += speedX;

    }else if(speedX == 0){
        System.out.println("Do not scroll the background.");
    }else{

        if(positionX <= 150){
            positionX += speedX;

        }else{
            System.out.println("Scroll Background Here");
        }
    }
    //Update Y Position
    if(positionY + speedY >= 382){
        positionY = 382;
    }else{
        positionY += speedY;
    }

    //update Jump

    if(jump == true){
        speedY += 1;

        if(positionY + speedY >= 382){
            positionY = 382;
            speedY = 0;
            jump = false;
        }
    }
}

   public void moveRight(){
speedX = 6;
System.out.println(speedX);
  }

  public void moveLeft(){
speedX = -6;
System.out.println(speedX);
  }

 public void stop(){
speedX = 0;
 }
 public void jump(){
if(jump == false){
    speedY = -15;
    jump = true;
}
   }



public void setPositionX(int positionX){

    this.positionX = positionX;
}

public int getPositionX(){
    return positionX;
}

    public void setPositionY(int positionY){

    this.positionY = positionY;
}

public int getPositionY(){
    return positionY;
}

public void setSpeedX(int speedX){
    this.speedX = speedX;
}

public int getSpeedX(){
    return speedX;
}

public void setSpeedY(int speedY){
    this.speedY = speedY;
}

public int getSpeedY(){
    return speedY;
}


      }

The problem is, the droid you're updating isn't the droid you're painting...in fact, the GameMain you're repainting isn't the one that is one the screen...

public class GameMain extends Applet implements KeyListener {

    //...
    private Droid droid;
    //...

    @Override
    public void init() {
        //...
        droid = new Droid();
        //...
    }

    @Override
    public void paint(Graphics g) {
        g.drawImage(character, droid.getPositionX() - 61, droid.getPositionY()- 63, this);
    }

And then in you GameThread ;

public class GameThread extends Thread {

    GameMain game;
    Droid droid;

    //...

    @Override
    public void run() {
        // Created a new GameMain
        game = new GameMain();
        // Created a new Droid...
        droid = new Droid();
        //Game while loop
        while (true) {

            droid.update();
            game.repaint();
            //...

You create new instances of GameMain and Droid , these have no connection what so ever to the screen.

Instead, you should be passing a reference of GameMain to the GameThread and GameThread should be telling GameMain to update the game state...

For example...

Add the method updateGameState

public class GameMain extends Applet implements KeyListener {
    //...

    public void updateGameState() {
        droid.update();
        repaint();
    }

    //...

Then in GameMain 's start method, pass a reference of GameMain to GameThread ...

GameThread thread = new GameThread(this);
thread.start();

Then in GameMain , store the reference you are passed and remove any reference to Droid

public class GameThread extends Thread {

    //...
    private GameMain gameMain;

    public GameThread(GameMain gameMain) {
        this.gameMain = gameMain;
        //...

Then in GameTread#run , call gameMain.updateGameState(); ...

public void run() {
    while (true) {
        gameMain.updateGameState();
        try {
            Thread.sleep(17);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

As a side note...

  1. Applet is outdated, you should be using JApplet
  2. I'd be very careful using this.getParent().getParent() , you may not like the results if you deployed this in a browser..
  3. And when you start using JApplet , move you game rendering to something like JPanel , overriding it's paintComponent method, this will give you automatic double buffering and use the Key binding API over KeyListener . It's more easily, programmatically, updatable and doesn't suffer from the same focus related issues as KeyListener

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM