简体   繁体   中英

How to repaint over images in Java game

Hello everyone I am having trouble with painting over coins that the user intersects with. What I want this code to do is when the user sprite intersects with any of the ten coin images it paints over the coin so that it no longer appears on the screen (also need to add in some kind of counter so that when the user collects all ten coins it will stop the thread, and say "You Win!"). My question is how would I go about doing this because I have tried using repaint() in the if statements, and it is not compiling correctly anymore. Any help on how to paint over the coins, and possibly even add some kind of counter (thinking a for loop would come in handy) would be greatly appreciated! Here is the code:

public void paint(Graphics g)
{
    g.clearRect(0, 0, this.getWidth(), this.getHeight());
    one.paintComponent(g);
    two.paintComponent(g);
    three.paintComponent(g);
    four.paintComponent(g);
    five.paintComponent(g);
    six.paintComponent(g);
    seven.paintComponent(g);
    eight.paintComponent(g);
    nine.paintComponent(g);
    ten.paintComponent(g);
    monster.setLocation(r.nextInt(10) - 5 + monster.x, r.nextInt(10 - 5 + monster.y));
    monster.paintComponent(g);
    user.paintComponent(g);
    if(user.intersects(one))
    {
    }
    if(user.intersects(two))
    {
    }
    if(user.intersects(three))
    {
    }
    if(user.intersects(four))
    {
    }
    if(user.intersects(five))
    {
    }
    if(user.intersects(six))
    {
    }
    if(user.intersects(seven))
    {
    }
    if(user.intersects(eight))
    {
    }
    if(user.intersects(nine))
    {
    }
    if(user.intersects(ten))
    {
    }
    if(user.intersects(monster))
    {
            g.setFont(new Font("Serif", Font.BOLD, 35));
            g.drawString("YOU HAVE DIED, YOU LOSE!", 100, 100); //Prints this when you lose
            thread.interrupt(); //Stopping the thread if you die
    }
}

At first, you should put the coins in a list. Then, if there's an interection, you simply remove the item (coin) of the list. Like this:

private List<Coin> coins;

public ClassConstructor() {
    coins = new ArrayList();
    coins.add(new Coin(type value,...)); //this ten times if every Coin is different from other
    //or this if every Coin are same:
    for (int i = 0; i < 10; i++) {
        coins.add(new Coin(type value,...));
    }
}

public void update() {
    //whatever
    for (int i = coins.size(); i >= 0; i--) {
        if (user.intersects(coins.get(i))) {
            coins.remove(i);
            //...
        }
    }

}

public void paint(Graphics g) {
    for (int i = coins.size(); i >= 0; i--) {
        coins.get(i).paintComponent(g);
    }
}

Now, you shouldnt end a Thread with thread.interrupt(). If that thread is your game loop, you should send a flag that ends the loop. The Thread of you game loop:

@Override
public void run() {
    while (running) { //boolean running
        update();
        paint(g);
    }}

And, finally, your update will be like:

public void update() {
    //whatever
    for (int i = coins.size(); i >= 0; i--) {
        if (user.intersects(coins.get(i))) {
            coins.remove(i);
            //...
        }
    }
    if (user.intersects(monster)) {
        youThread.setRunning(false);
        try {
            gameLoopThread.join(); //"wait" until thread ends
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

Off the top of my head, put while(true) within your Run() method (you said you were using a thread) and call repaint() within the loop, at the end of the loop (within a try/catch) put something like //thread//.sleep(allotted time) This will stop the thread for the set amount of Milliseconds. Within the Javadoc of repaint() you'll see that it calls the nearest paint(Graphics g) method. By doing this you can access your paint() method from wherever you are in your program.

My suggestion to the coin's is make it it's own class. The class would look similar to this:

public class Coin{
int x;
int y;
public void Coin(int x, int y, Graphics g){
    Graphics2D g2 = (Graphics2D) g;
    Image img1 = (//File Location);
    g2.drawImage(img1, x, y, //this);
    //If you have trouble with the ImageObserver (this part) try //class name of the applet.this
    this.x = x;
    this.y = y;

    g2.finalize();
}
public int getX(){
    return x;
}
public int getY(){
    return y;
}
}

After that, in your paint method you could make 10 Coin objects and use g which you instantiate in the parameters. You could then make an array of Coin objects and add 10 Coin s that you make in your paint method manually (yeah, it's a pain) (you have to make them in paint to pass the Graphics variable)

Coin[] coins = new Coin[10];

Is how you make the array, by the way. After you make the array of coin's, then make a for loop in your paint method. It should look something like this:

        for(int i = 0; i < coins.length; i++){
            if(coins[i].getX == //user X && coins[i].getY == //user Y){
                    g.clearRect(coins[i].getX, coins[i].getY, //Coin radius, //Coin radius);
            }

        }

This will make a clear rectangle be drawn over wherever the Coin is at if the user's X and Y is equal to the Coin's X and Y.

This code is taken from my current project (that is working), I tried adjusting it to your project.

private void render () {
    BufferStrategy bufferstrategy = getBufferStrategy ();

    if (bufferstrategy == null) {
        createBufferStrategy(3);
        return;
    }

    Graphics g = bufferstrategy.getDrawGraphics();

    g.setColor(Color.white);
    g.fillRect(0, 0, getWidth(), getHeight());

    paint (g);

    g.dispose();
    bufferstrategy.show();
}

render() is called from run(), where the Thread is.

Let's break it down and see if it can help you.

  1. It gets a BufferStrategy for how many images to have ready. It can be set to anything like you like within reason. 2 - 4 will do the trick. One can even work.
  2. It sets your current BufferStrategy to your Graphics .
  3. It then fills the screen with the color of white (could be a clear as well).
  4. Then it paints all components, in your case it calls paint (Graphics g) while in my case it iterates through all drawable objects.
  5. It re-renders everything as it now should look.

Hope you take some points out from this.

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