Java - 随着时间的推移改变图像的透明度
我正在尝试制作一个可以在游戏运行时变为半透明的游戏对象。
当我在进入游戏的计时器循环(在 loadImages() 方法内)之前将其应用于对象的图像时,我的半透明滤镜工作正常。但是,在游戏的计时器循环(timerLoop() 方法)内,它不起作用,并且使我的对象的图像完全透明。我做错了什么?
我使用 java.awt 库进行绘图,并使用 RGBImageFilter 来应用半透明。
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 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;
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我不久前找到了解决我的问题的方法。我最终使用 MediaTracker 对象来等待更改后的图像在渲染之前加载。现在可以了。
以下是使用 MediaTrackers 的简短教程: http://www.javacoffeebreak.com/articles/mediatracker /index.html
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
(靠近底部:)
return (rgb & 0x00FFFFFF) + (alpha << 24); // alpha 位设置为 0 会产生透明度。
这不应该是
(rgb & 0x00FFFFFF) | (阿尔法<<24)
?(near bottom:)
return (rgb & 0x00FFFFFF) + (alpha << 24); // alpha bits set to 0 yields transparency.
Shouldn't this be
(rgb & 0x00FFFFFF) | (alpha << 24)
?