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)
{
开发者_如何学JAVA // 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)
?
精彩评论