Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
203 views
in Technique[技术] by (71.8m points)

java - Gradually speeding a sprite

I'm trying to make the sprite speed-up gradually on button press and not to move constant speed only. Also set a max-speed limit. I hope you understand what i mean.

timer = new Timer(5, this);
timer.start();

public void paint(Graphics g) {
    super.paint(g);
    Graphics2D g2d = (Graphics2D)g;
    g2d.drawImage(image, x, y, this); //x,y = position
    Toolkit.getDefaultToolkit().sync();
    g.dispose();
}

private class TAdapter extends KeyAdapter { 
    public void keyPressed(KeyEvent e) {
        int key = e.getKeyCode();
        if (key == KeyEvent.VK_LEFT) {
            dx = -1;
        }
        if (key == KeyEvent.VK_RIGHT) {
            dx = 1;
        }
        if (key == KeyEvent.VK_UP) {
            dy = -1;
        }
        if (key == KeyEvent.VK_DOWN) {
            dy = 1;
        }
    }
}   
    public void actionPerformed(ActionEvent e) {
        x += dx;   
        y += dy;
        repaint();  
    }
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

There are several things (initially) wrong with your example code...

  1. You are overriding the paint method. It is recommend that you override the paintComponent method instead. If you are overriding the paint method of a top level container, like JFrame, then it is recommended that you don't. Instead, use something like JPanel as the bases for your custom painting...
  2. You are disposing of the Graphics context that is past to you. This is VERY dangerous, as this will prevent anything else from been painted. The Graphics context is a shared resources, everything that needs to be updated during this repaint cycle will using the same Graphics context.
  3. You are using a KeyListener. KeyListener suffers from focus issues. This can easily be remedied through the use of the Key Binding API. Key bindings are also more flexible, as they separate the physical key from the action, allowing you to associate the action with different keys with little effort and/or reuse the underlying action (such as with buttons).

So. For your question. You need to know...

  • The current speed...
  • The minimum allowable speed...
  • The maximum allowable speed...

You will also want to maintain the current position of the object you are altering.

This example doesn't actually move the "player" so much as it moves the background. The background position is altered by the xDelta, which is the speed of change...

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.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
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.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class TestSpeed {

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

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

                JFrame frame = new JFrame("Test");
                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 BufferedImage background;
        // The current position of the background
        private int xPos = 0;
        // The speed/delta that the xPos is changed...
        private int xDelta = 0;

        public TestPane() {
            Timer timer = new Timer(40, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    if (xPos < -(getWidth())) {
                        xPos = 0;
                    }
                    xPos -= xDelta;
                    repaint();
                }
            });
            timer.setRepeats(true);
            timer.setCoalesce(true);
            timer.start();
            InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW);
            im.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0), "slower");
            im.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0), "faster");

            ActionMap am = getActionMap();
            am.put("slower", new AbstractAction() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    setSpeed(-1);
                }
            });
            am.put("faster", new AbstractAction() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    setSpeed(1);
                }
            });
        }

        protected void setSpeed(int delta) {
            xDelta += delta;
            // Check the change in speed to ensure it's within the appropriate range
            if (xDelta < 0) {
                xDelta = 0;
            } else if (xDelta > 9) {
                xDelta = 9;
            }
        }

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

        @Override
        public void invalidate() {
            background = null;
            super.invalidate();
        }

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

            int x = xPos;
            g.setColor(Color.DARK_GRAY);
            while (x < getWidth()) {
                g.drawLine(x, 0, x, getHeight());
                x += 15;
            }

            int width = getWidth();
            int height = getHeight();
            x = (width / 2) - 5;
            int y = (height / 2) - 5;
            g.setColor(Color.RED);
            g.fillOval(x, y, 10, 10);
        }        
    }    
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...