简体   繁体   中英

Java - change transparency of image over time

I am trying to make a game object that can be made semitransparent during the game's runtime.

My semitransparency filter works fine when I apply it to my object's image before entering the game's timer loop (inside the loadImages() method). Inside the game's timer loop (the timerLoop() method), though, it doesn't work and it makes my object's image completely transparent. What am I doing wrong?

I am using the java.awt library for drawing and I'm using an RGBImageFilter to apply the semitransparency.

public class MyMainJPanel extends JPanel
{
    // essential members
    private Timer timer;
    private Camera camera;

    // image data

    Image bulletImg;
    Image bulletSemiTransImg;

    MenuBackgroundsSprite menuBg, menuBg2;



    public MyMainJPanel()
    {
        this.setBackground(Color.black);

        this.setFocusable(true);

        // load images

        this.loadImages();

        // set up the timer

        TimerListener timerListener = new TimerListener();

        timer = new Timer(0,timerListener);
        this.setFPS(60);
        timer.start();
    }


    private boolean loadImages()
    {
        ... 

        loads some other graphics

        ...

        // LOAD BULLET GRAPHICS

        // get our default toolkit

        Toolkit tk = Toolkit.getDefaultToolkit();

        // load our bullet images

        Image preImg = tk.getImage("graphics/basicBullet.png");

        bulletImg = ColorFilters.setTransparentColor(preImg, new Color(0xFF00FF)); // pink
    //  bulletSemiTransImg = ColorFilters.setSemiTransparency(bulletImg, 0.5); // My semitransparency works here outside the timer loop


        ...

        loads Camera object

        ...

        return true;
    }


    /** 
    *   setFPS()
    *   Preconditions: fps is a quantity of frames per second
    *   Postconditions: Sets the timer's refresh rate so that it fires fps times per second.
    **/

    public void setFPS(int fps)
    {
        int mspf = (int) (1000.0 /fps + 0.5);
        timer.setDelay(mspf);
    }



    // Event listener for the timer objects

    private class TimerListener implements ActionListener
    {

        public void actionPerformed(ActionEvent e)
        {
            Object source = e.getSource();

            if(source == timer)
            {
                // perform a loop through the game's logic
                timerLoop();        // Enters timer loop step here

            }
        }
    }


    public void timerLoop()
    {

        // bullet dynamic semitransparency test

        bulletSemiTransImg = ColorFilters.setSemiTransparency(bulletImg, 0.5); // This is where I'm having my problem. It makes all the bullets completely transparent 
                                                                                                        // if I try to apply semitransparency to them inside my timer loop.

        // repaint after game logic has completed.
        this.repaint();
    }

    public void paintComponent(Graphics g)
    {
            super.paintComponent(g);

            Graphics2D g2D = (Graphics2D) g;
            // test data

            // Camera transform

            g2D.setTransform(camera.getTransform()); 

            // Draw graphics

            ...

            Draw some stuff before the bullets

            ...

            // Here's where I draw my bullets

            for(int i = 0; i < 10; i++)
            {
                for(int j = 0; j < 10; j++)
                {
                    g2D.translate((i+1)*32,(j+1)*32);

                    g2D.drawImage(bulletSemiTransImg, null, null); 

                    g2D.setTransform(camera.getTransform()); // reset the Graphics context's transform
                }
            }


    }

}



/**
*   ColorFilters.java
*   A class of static methods used to apply color filters to images.
**/

public class ColorFilters
{

    public static Image setTransparentColor(Image srcImg, final Color tColor) // method accepts a transparent color.
                                                                     // It'll transform all pixels of the transparent color to transparent.
    {   
        ImageFilter filter = new RGBImageFilter() // overriding part of the RGBImageFilterClass to produce a specialized filter.
        {
            public int testColor = tColor.getRGB() | 0xFF000000; // establish the transparent color as a hexidecimal value for bit-wise filtering.

            public int  filterRGB(int x, int y, int rgb) // overriden method
            {
                if((rgb | 0xFF000000 ) == testColor) // if transparent color matches the color being tested, make it transparent.
                {
                    return rgb & 0x00FFFFFF; // alpha bits set to 0 yields transparency.
                }
                else // otherwise leave it alone.
                    return rgb;
            }
        };

        ImageProducer ip = new FilteredImageSource(srcImg.getSource(),filter);
        Image result = Toolkit.getDefaultToolkit().createImage(ip);

        return result;
    }


    // Here is the static method used to apply the semitransparency

    public static Image setSemiTransparency(Image srcImg, double semiTrans) // method accepts a transparent color.
                                                                     // It'll transform all pixels of the transparent color to transparent.
    {   
        if(semiTrans > 1.0) 
            semiTrans = 1.0;
        if(semiTrans < 0.0)
            semiTrans = 0.0;
        final int alpha = (int) (255 * (1.0 - semiTrans));

        ImageFilter filter = new RGBImageFilter() // overriding part of the RGBImageFilterClass to produce a specialized filter.
        {
            public int  filterRGB(int x, int y, int rgb) // overriden method
            {
                System.out.println(alpha);
                if((rgb & 0xFF000000) != 0)
                    return (rgb & 0x00FFFFFF) + (alpha << 24); // alpha bits set to 0 yields transparency.  
                else
                    return rgb;
            }
        };

        ImageProducer ip = new FilteredImageSource(srcImg.getSource(),filter);
        Image result = Toolkit.getDefaultToolkit().createImage(ip);

        return result;
    }

}

I found a solution to my problem a while ago. I ended up using a MediaTracker object to wait for the altered image to load before rendering. It works now.

Here's a short tutorial for using MediaTrackers: http://www.javacoffeebreak.com/articles/mediatracker/index.html

(near bottom:)

return (rgb & 0x00FFFFFF) + (alpha << 24); // alpha bits set to 0 yields transparency.

Shouldn't this be (rgb & 0x00FFFFFF) | (alpha << 24) (rgb & 0x00FFFFFF) | (alpha << 24) ?

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