You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java弹跳DVD Logo碰撞边缘变色失效,求类似JS tint()的实现方法

解决Java弹跳DVD Logo碰撞变色问题

Java中没有JavaScript那样直接的tint()方法,但可以通过图像滤镜实现类似的染色效果。结合你的现有代码,只需两步就能实现碰撞边缘时Logo变色:

1. 碰撞时更新随机颜色

在actionPerformed方法中,检测到Logo碰撞边缘时生成新的RGB随机值,避免无意义的颜色刷新:

public void actionPerformed(ActionEvent e) {
    boolean collided = false;
    if (x >= PANEL_WIDTH - dvd.getWidth(null) || x < 0) {
        xVelocity *= -1;
        collided = true;
    }
    x += xVelocity;

    if (y >= PANEL_HEIGHT - dvd.getHeight(null) || y < 0) {
        yVelocity *= -1;
        collided = true;
    }
    y += yVelocity;

    // 仅在碰撞触发时更新颜色
    if (collided) {
        r = (int)(Math.random() * 255);
        g = (int)(Math.random() * 255);
        b = (int)(Math.random() * 255);
    }

    repaint();
}

2. 使用RGB滤镜给Logo染色

替换原有的paint方法为Swing标准的paintComponent(避免层次绘制问题),通过RGBImageFilter实现染色效果:

@Override
protected void paintComponent(Graphics g) {
    super.paintComponent(g); // 绘制背景
    Graphics2D gr = (Graphics2D) g;

    // 创建颜色滤镜:保留原图像透明度,替换RGB通道
    RGBImageFilter colorFilter = new RGBImageFilter() {
        @Override
        public int filterRGB(int x, int y, int rgb) {
            int alpha = (rgb >> 24) & 0xFF; // 提取原像素的透明度
            return (alpha << 24) | (r << 16) | (g << 8) | b; // 组合新颜色
        }
    };

    // 生成带滤镜的图像并绘制
    Image filteredDvd = createImage(new FilteredImageSource(dvd.getSource(), colorFilter));
    gr.drawImage(filteredDvd, x, y, null);
}

关键说明

  • 用paintComponent的原因:这是Swing组件绘制的标准方法,能确保背景和组件内容正确分层渲染,避免paint方法可能带来的绘制异常。
  • 滤镜逻辑:RGBImageFilter会遍历图像每个像素,保留原Logo的透明区域,将非透明像素的颜色替换为随机生成的RGB值,完全模拟JavaScript中tint()的染色效果。

修改后的完整代码:

import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
import java.awt.image.RGBImageFilter;
import java.awt.image.FilteredImageSource;

public class MyPanel extends JPanel implements ActionListener{

    final int PANEL_WIDTH = 500;
    final int PANEL_HEIGHT = 500;
    Image dvd;
    Timer timer;
    int xVelocity = 1;
    int yVelocity = 1;
    int x = 0;
    int y = 0;

    int r = (int)(Math.random() * 255);
    int g = (int)(Math.random() * 255);
    int b = (int)(Math.random() * 255);

    MyPanel(){
        this.setPreferredSize(new Dimension(PANEL_WIDTH, PANEL_HEIGHT));
        this.setBackground(Color.BLACK);
        dvd = new ImageIcon("dvdlogo-01.png").getImage();
        timer = new Timer(10, this);
        timer.start();
    }

    @Override
    protected void paintComponent(Graphics g){
        super.paintComponent(g);
        Graphics2D gr = (Graphics2D) g;

        RGBImageFilter colorFilter = new RGBImageFilter() {
            @Override
            public int filterRGB(int x, int y, int rgb) {
                int alpha = (rgb >> 24) & 0xFF;
                return (alpha << 24) | (r << 16) | (g << 8) | b;
            }
        };

        Image filteredDvd = createImage(new FilteredImageSource(dvd.getSource(), colorFilter));
        gr.drawImage(filteredDvd, x, y, null);
    }

    public void actionPerformed(ActionEvent e){
        boolean collided = false;
        if(x >= PANEL_WIDTH - dvd.getWidth(null) || x < 0){
            xVelocity = xVelocity * -1;
            collided = true;
        }
        x = x + xVelocity;

        if(y >= PANEL_HEIGHT - dvd.getHeight(null) || y < 0){
            yVelocity = yVelocity * -1;
            collided = true;
        }
        y = y + yVelocity;

        if(collided){
            r = (int)(Math.random() * 255);
            g = (int)(Math.random() * 255);
            b = (int)(Math.random() * 255);
        }
        repaint();
    }
}

内容的提问来源于stack exchange,提问作者gloomyside3

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 14:05:19