【问题标题】:Create a Trailing line of blood behind a player在玩家身后创造一条血迹
【发布时间】:2014-05-20 14:31:20
【问题描述】:

我目前正在开发一个简单的自上而下的射击游戏。该对象是一个在屏幕上滑动的球,我正在尝试制作一种湿拖效果。

我正在使用 Java Swing 和里面的默认 Graphics2d 库。

这就是我所拥有的:

这是我的目标:

我需要知道如何制作一条能够在尾端改变 alpha 的曲线。我在网上搜索过,但我只能找到非动态的解决方案。 (尾巴需要随着玩家在屏幕上移动而更新。)

【问题讨论】:

  • 基本上,记录球移动前的最后位置,将此点放在Points 的List 内。当您更新屏幕时,穿过List 并在每个点之间生成一条线...您甚至可以生成某种多边形或其他Shape 来实现此目的...
  • 嗯,简单但有效...如果您愿意,可以使用代码 sn-p 或其他内容将此作为答案,我会接受。

标签: java swing awt graphics2d java-2d


【解决方案1】:

嗯..也许你需要这样的东西:

public class BallArea extends JComponent {
static final int MAX_SIZE = 63;
static final BasicStroke stroke = new BasicStroke(5);
final Queue<Point> points = new LinkedList();

public BallArea() {
    setSize(400, 400);
    setBackground(Color.BLACK);
    addMouseMotionListener(new MouseAdapter() {
        @Override
        public void mouseMoved(MouseEvent e) {
            if (points.size() >= MAX_SIZE) {
                points.poll();
            }
            points.add(e.getPoint());
            repaint();
        }
    });
}

@Override
public void paintComponent(Graphics g) {
    super.paintComponent(g);
    Graphics2D g2 = (Graphics2D) g;
    g2.setStroke(stroke);
    int i = 1;
    Point prev = null;
    for (Point p : points) {
        if (prev == null) {
            prev = p;
            continue;
        }
        g2.setColor(new Color(255, 0, 0, i*4));
        g.drawLine(prev.x, prev.y, p.x, p.y);
        i++;
        prev = p;
    }
}
}

【讨论】:

  • 1) setSize(400, 400); 布局管理器更倾向于使用首选尺寸而不是尺寸。即使这样,覆盖也比设置好。 2)public void paintComponent(Graphics g) { 应该是public void paintComponent(Graphics g) { super.paintComponent(g);。始终首先调用super 方法。
  • 这只是一个演示样本
  • “演示示例” 演示示例应该使用最佳实践,而不是重复糟糕的建议。 -1
  • paintComponent 应该是 protected,除了继承的类之外,任何人都不应该有任何理由调用它。
【解决方案2】:

一个简单的解决方案可能是将每个点简单地添加到Points 中的List,在玩家移动之前。

然后你只需要迭代这个列表,或者简单地使用Graphics#drawLine 甚至GeneralPath 来呈现“拖动”线,例如...

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.geom.Ellipse2D;
import java.awt.geom.GeneralPath;
import java.util.ArrayList;
import java.util.List;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Drag {

    public static void main(String[] args) {
        new Drag();
    }

    public Drag() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private List<Point> points;
        private Point pos;

        private int diametere = 10;

        public TestPane() {
            points = new ArrayList<>(25);

            InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW);
            im.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0), "left");
            im.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0), "right");
            im.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0), "up");
            im.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0), "down");

            ActionMap am = getActionMap();
            am.put("left", new MoveAction(-5, 0));
            am.put("right", new MoveAction(5, 0));
            am.put("up", new MoveAction(0, -5));
            am.put("down", new MoveAction(0, 5));

            pos = new Point(100 - (diametere / 2), 100 - (diametere / 2));
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            if (points.size() > 1) {
                g2d.setColor(Color.RED);
                GeneralPath path = new GeneralPath();
                boolean started = false;
                System.out.println("----");
                for (Point p : points) {
                    if (started) {
                        System.out.println(p);
                        path.lineTo(p.x, p.y);
                    } else {
                        path.moveTo(p.x, p.y);
                        started = true;
                    }
                }
                g2d.draw(path);
            }
            int radius = (int) (diametere / 2d);
            g2d.setColor(Color.GREEN);
            g2d.draw(new Ellipse2D.Double(pos.x - radius, pos.y - radius, diametere, diametere));
            g2d.dispose();
        }

        protected void moveBy(int xDelta, int yDelta) {

            if (pos.x + xDelta < 0) {

                xDelta = 0;
                pos.x = 0;

            } else if (pos.x + xDelta + diametere > getWidth()) {

                xDelta = 0;
                pos.x = getWidth() - diametere;

            }
            if (pos.y + yDelta < 0) {

                yDelta = 0;
                pos.y = 0;

            } else if (pos.y + yDelta + diametere > getHeight()) {

                yDelta = 0;
                pos.y = getWidth() - diametere;

            }

            points.add(new Point(pos));

            pos.x += xDelta;
            pos.y += yDelta;

            repaint();

        }

        public class MoveAction extends AbstractAction {

            private int xDelta;
            private int yDelta;

            public MoveAction(int xDelta, int yDelta) {
                this.xDelta = xDelta;
                this.yDelta = yDelta;
            }

            @Override
            public void actionPerformed(ActionEvent e) {
                moveBy(xDelta, yDelta);
            }

        }
    }

}

【讨论】:

  • @MattHirdler 这相当简单,但给出了这个想法的要点;)
  • 出于好奇,使用 GeneralPath 有什么好处?我可以不只是制作一个点数组然后使用 drawLine(X1, Y1, X2, Y2); ?
  • 我已经实现的方式,实际上没有,但是你可以做的是而不是使用Points 的List,实际上只是在GeneralPath 中继续使用lineTo每次移动玩家。这将取决于您是否想知道有多少点以及您想要对它们进行多少访问......
猜你喜欢
  • 1970-01-01
  • 2013-12-11
  • 1970-01-01
  • 2019-11-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-14
  • 1970-01-01
相关资源
最近更新 更多