0

I have KeyEvents for a sprite for moving left, right, up and down. I was just messing around and was thinking ahead for another project in which I want the sprite to jump. It doesn't have to be fully realistic as I am just beginning. What I have is when the space bar is pressed, it will cause the sprite to jump, lets say "dy = -3". So then I have the KeyEvent for keyReleased, it will fall, "dy = -2". This does not work as the sprite just continues to fall...can someone shine some light?

Entire code: package collision;

    import java.awt.Image;
    import java.awt.Rectangle;
    import java.awt.event.KeyEvent;

    import java.util.ArrayList;

    import javax.swing.ImageIcon;

    public class Craft {

    private String craft = "pelican.png";

    private int dx;
    private int dy;
    private int x;
    private int y;
    private int width;
    private int height;
    private boolean visible;
    private Image image;
    private ArrayList missiles;


    public Craft() {
    ImageIcon ii = new ImageIcon(this.getClass().getResource(craft));
    image = ii.getImage();
    width = image.getWidth(null);
    height = image.getHeight(null);
    missiles = new ArrayList();
    visible = true;
    x = 100;
    y = 300;
    }


    public void move() {

    x += dx;
    y += dy;

    if (x < 1) {
        x = 1;
    }

    if (y < 1) {
        y = 1;
    }

    }

    public int getX() {
    return x;
    }

    public int getY() {
    return y;
    }

    public Image getImage() {
    return image;
    }

    public ArrayList getMissiles() {
    return missiles;
    }

    public void setVisible(boolean visible) {
    this.visible = visible;
    }

    public boolean isVisible() {
    return visible;
    }

     public Rectangle getBounds() {
    return new Rectangle(x, y, width, height);
    }

    public void keyPressed(KeyEvent e) {

    int key = e.getKeyCode();

    if (key == KeyEvent.VK_SPACE) {

    }
    if (key == KeyEvent.VK_V){
        dx = 6;
    }

    if (key == KeyEvent.VK_LEFT) {
        dx = -1;
    }

    if (key == KeyEvent.VK_RIGHT) {
        dx = 2;
    }

    if (key == KeyEvent.VK_UP) {
        dy = -1;
    }

    if (key == KeyEvent.VK_DOWN) {
        dy = 1;
    }
    }

    public void fire() {
    missiles.add(new Missile(x + width, y + height/2));
    }

    public void keyReleased(KeyEvent e) {
    int key = e.getKeyCode();

    if (key == KeyEvent.VK_LEFT) {
        dx = 0;
    }
    if (key == KeyEvent.VK_SPACE) {

    }

    if (key == KeyEvent.VK_RIGHT) {
        dx = 0;
    }

    if (key == KeyEvent.VK_UP) {
        dy = 0;
    }

    if (key == KeyEvent.VK_DOWN) {
        dy = 0;
    }
    }
    }

As you may have noticed Im new to Java as well as game programming. All I want is the sprite to go up, then come back down. It will always remain stationary if that helps. The sprite just keeps jumping until he is hit by an on coming obstacle. I know there is code for other movements, but those will be removed once I start on next sprite.

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
DarrenKing
  • 11
  • 1
  • 1
  • 3
  • @ Darren: Consider creating and posting a small program that compiles, runs, and shows your problem for us and contains no code unrelated to your problem, and [sscce](http://sscce.org) as this will give us the best ability to understand your problem and be able to help you. Also, if this were my program and a Swing program, I'd use key bindings not a KeyListener. – Hovercraft Full Of Eels May 11 '13 at 04:56

2 Answers2

4

This is basic concept. Your implementation will change depending on the implementation of your engine.

The basic idea is the player has a vertical delta which is changed over time by gravity. This effects the sprites vertical speed.

This implementation also has a re-bound delta, which allows the sprite to re-bound rather the "stopping" suddenly. The re-bound is effected by a re-bound degradation, which reduces the amount of re-bound on each re-bound.

This simulates a game character, so you'll need to hit Space to start it bouncing...

import java.awt.BorderLayout;
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 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 JumpingSprite {

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

    public JumpingSprite() {
        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 static class TestPane extends JPanel {

        protected static final int SPRITE_HEIGHT = 10;
        protected static final int SPRITE_WIDTH = 10;
        private float vDelta; // The vertical detla...
        private float rbDelta; // Rebound delta...
        private float rbDegDelta; // The amount the rebound is degradation...
        private int yPos; // The vertical position...
        private float gDelta; // Gravity, how much the vDelta will be reduced by over time...
        private Timer engine;
        private boolean bounce = false;

        public TestPane() {

            yPos = getPreferredSize().height - SPRITE_HEIGHT;
            vDelta = 0;
            gDelta = 0.25f;
            // This is how much the re-bound will degrade on each cycle...
            rbDegDelta = 2.5f;

            InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW);
            ActionMap am = getActionMap();
            im.put(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0), "jump");
            am.put("jump", new AbstractAction() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    // Can only bound when we're actually on the ground...
                    // You might want to add fudge factor here so that the 
                    // sprite can be within a given number of pixels in order to
                    // jump again...
                    if (yPos + SPRITE_HEIGHT == getHeight()) {
                        vDelta = -8;
                        rbDelta = vDelta;
                        bounce = true;
                    }
                }
            });

            engine = new Timer(40, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    int height = getHeight();
                    // No point if we've not been sized...
                    if (height > 0) {
                        // Are we bouncing...
                        if (bounce) {
                            // Add the vDelta to the yPos
                            // vDelta may be postive or negative, allowing
                            // for both up and down movement...
                            yPos += vDelta;
                            // Add the gravity to the vDelta, this will slow down
                            // the upward movement and speed up the downward movement...
                            // You may wish to place a max speed to this
                            vDelta += gDelta;
                            // If the sprite is not on the ground...
                            if (yPos + SPRITE_HEIGHT >= height) {
                                // Seat the sprite on the ground
                                yPos = height - SPRITE_HEIGHT;
                                // If the re-bound delta is 0 or more then we've stopped
                                // bouncing...
                                if (rbDelta >= 0) {
                                    // Stop bouncing...
                                    bounce = false;
                                } else {
                                    // Add the re-bound degregation delta to the re-bound delta
                                    rbDelta += rbDegDelta;
                                    // Set the vDelta...
                                    vDelta = rbDelta;
                                }
                            }
                        }
                    }
                    repaint();
                }
            });
            engine.start();
        }

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

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            int width = getWidth() - 1;
            int xPos = (width - SPRITE_WIDTH) / 2;
            g2d.drawOval(xPos, yPos, SPRITE_WIDTH, SPRITE_HEIGHT);
            g2d.dispose();
        }
    }
}
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • Huh? I see a GUI with a circle drawn at the bottom, but is the circle supposed to move? It looks like the timer is set up to produce animation, but for some reason, it is all 'static' here.. – Andrew Thompson Oct 28 '13 at 02:35
  • 1
    @AndrewThompson Hit the space bar ;) – MadProgrammer Oct 28 '13 at 02:39
  • You know, now you mention that, I almost feel like you've told me before (or you used the same technique). For the benefit of the really lazy/stupid(1) amongst us, can you change the title to 'Space to Jump' or something? 1) And no, I am **not** going to narrow down which of those two categories I fit. Left as an exercise for the reader.. ;) – Andrew Thompson Oct 28 '13 at 04:55
  • 1
    @AndrewThompson I generally fit into both (catagories) :P – MadProgrammer Oct 28 '13 at 04:57
  • What you COULD do is put it in a simple 3 lines of code. That would make it a lot easier to read. – bleh Jan 02 '16 at 01:42
  • @bleh But now there isn't any confusion of libraries, imports, proper setups or any other "it doesn't work" comments, as there is a clear and runnable example which demonstrates the solutions and excuse me if I haven't had those f*****g arguments with people in the past – MadProgrammer Jan 02 '16 at 01:56
  • Lol just don't like running it on BlueJ. – bleh Jan 02 '16 at 01:57
  • @bleh BlueJ, the vain of my existance. Run in Netbeans and from the command line, make sure you've configured BlueJ to run Java 7+ – MadProgrammer Jan 02 '16 at 02:00
  • Like, it takes time to put it in a class, compile it, and run it. I'm really just used to BlueJ. – bleh Jan 02 '16 at 02:02
  • @bleh I had to create a new project, copy and paste the code, rename it, compile and ran it. Didn't take more then a minute. If you had like 3 lines of code, you'd need to completely build the rest of the code around it, got and hour or two? – MadProgrammer Jan 02 '16 at 02:05
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/99495/discussion-between-bleh-and-madprogrammer). – bleh Jan 02 '16 at 02:05
0

Well I can think of one way. It involves some complex amounts of math (parabola). So i'm going to provide a very simple answer.

int y = 0;

and in the method that tests for the spacebar...

if (y !< 1){
    if (y < 30){

   y += 1;

   }

   if (y > 30){

    y -= 1;


    }
}

I haven't tested it out yet, but it should work in theory....But it won't animate anything, this code is only going to take the sprites Y value and make it go up. That's just about the easiest jumping method that can exist....