代码之家  ›  专栏  ›  技术社区  ›  devamat

Java2D:使形状看起来不那么“扁平”

  •  0
  • devamat  · 技术社区  · 6 年前

    enter image description here

    我正在为孩子们制作一款类似命运之轮的在线英语学习游戏。问题是,图形看起来非常平坦;我想添加一些深度(之后可能会有一些像bloom或粒子)。我正在努力使它对8-12岁左右的孩子有吸引力(这个游戏将在在线课程中与老师一起使用)。背景还可以,我更关心的是车轮的切片。但任何暗示都是好的。

    我就是这样画的(我用的是彩虹色):

            int c = 0;
    
            for (int i = 0; i < this.slices.length; i++) {
    
                switch (c) {
                    case 0: g2d.setPaint(new Color(148, 0, 211)); break;
                    case 1: g2d.setPaint(new Color(75, 0, 130)); break;
                    case 2: g2d.setPaint(new Color(0, 0, 255)); break;
                    case 3: g2d.setPaint(new Color(0, 255, 0)); break;
                    case 4: g2d.setPaint(new Color(255, 255, 0)); break;
                    case 5: g2d.setPaint(new Color(255, 127, 0)); break;
                    case 6: g2d.setPaint(new Color(255, 0, 0)); break;
                }
    
                c++;
                if (c > 6) c = 0;
    
                g2d.fill(this.slices[i]);
                g2d.setPaint(new Color(0, 0, 0, 80));
                g2d.draw(this.slices[i]);
    
            }
    

    我想我可以用渐变填充让事情看起来更好。我试过了,但没能把它弄得好看。下面的屏幕截图给出了一个看起来很酷的轮子。

    enter image description here

    我该怎么做才能让车轮更深入一点,基本上让它看起来更酷?

    1 回复  |  直到 6 年前
        1
  •  1
  •   MadProgrammer    6 年前

    这是一个非常基本的例子,使用多个相互重叠的paint effects。。。

    Simple

    如果我有更多的时间玩,我可能会考虑使用更多 RadialGradientPaint 而不是 LinearGradientPaint ,但这可能会给你一个起点

    import java.awt.BasicStroke;
    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.EventQueue;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.LinearGradientPaint;
    import java.awt.RadialGradientPaint;
    import java.awt.RenderingHints;
    import java.awt.geom.Arc2D;
    import java.awt.geom.Path2D;
    import java.awt.geom.Point2D;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    
    public class Test {
    
        public static void main(String[] args) {
            new Test();
        }
    
        public Test() {
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    JFrame frame = new JFrame();
                    frame.add(new TestPane());
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                }
            });
        }
    
        public class TestPane extends JPanel {
    
            private Slice slice = new Slice(100, 200, 60, 40);
    
            public TestPane() {
            }
    
            @Override
            public Dimension getPreferredSize() {
                return new Dimension(200, 400);
            }
    
            @Override
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
                Graphics2D g2d = (Graphics2D) g.create();
    
                g2d.translate((getWidth() / 2.0) - slice.getBounds().width,
                        (getHeight() - slice.getBounds().height) / 2.0);
                RenderingHints hints = new RenderingHints(
                        RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON
                );
                g2d.setRenderingHints(hints);
    
                Color primaryColor = Color.MAGENTA;
                Color alphaColor = new Color(primaryColor.getRed(), primaryColor.getGreen(), primaryColor.getBlue(), 0);
                Color shadowColor = new Color(0, 0, 0, 128);
    
                g2d.setColor(primaryColor);
                g2d.fill(slice);
    
                RadialGradientPaint rgp = new RadialGradientPaint(
                        new Point2D.Double(slice.getBounds2D().getWidth(), slice.getBounds2D().getHeight() / 2d), 
                        (float)slice.getBounds2D().getHeight() / 2.0f, 
                        new float[] {0.6f, 1.0f}, 
                        new Color[] {alphaColor, shadowColor});
                g2d.setPaint(rgp);
                g2d.fill(slice);
    
                Graphics2D gScale = (Graphics2D) g2d.create();
                LinearGradientPaint lgp = new LinearGradientPaint(
                        new Point2D.Double(0, 0), 
                        new Point2D.Double(slice.getBounds2D().getWidth(), 0), 
                        new float[]{0f, 1f}, 
                        new Color[] {shadowColor, alphaColor});
                gScale.setPaint(lgp);
                gScale.fill(slice);
                lgp = new LinearGradientPaint(
                        new Point2D.Double(slice.getBounds2D().getWidth(), 0), 
                        new Point2D.Double(slice.getBounds2D().getWidth() * 2, 0), 
                        new float[]{0f, 1f}, 
                        new Color[] {alphaColor, shadowColor});
                gScale.setPaint(lgp);
                gScale.fill(slice);
                gScale.dispose();
    
    
                g2d.setPaint(primaryColor.brighter());
                g2d.setStroke(new BasicStroke(3, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
                g2d.draw(slice);
                g2d.dispose();
            }
    
        }
    
        public class Slice extends Path2D.Double {
    
            public Slice(double width, double height, double range, double innerHeight) {
                moveTo(0, 0);
                append(new Arc2D.Double(0, 0, width, height,
                        90 - (range / 2.0), range,
                        Arc2D.OPEN), false);
    
                double sliceWidth = width / 2.0;
                double x = (width - sliceWidth) / 2.0;
    
                append(new Arc2D.Double(x, height, sliceWidth, innerHeight,
                        90 + (range / 2.0), -range,
                        Arc2D.OPEN), true);
    
                closePath();
            }
        }
    
    }