Java游戏。子弹不直接从枪中飞出

时间:2014-04-15 02:46:15

标签: java swing paintcomponent keylistener event-driven

除了直接从大炮直接射击的子弹外,一切都按预期工作。大炮按照预期的方式在屏幕上移动但是一旦子弹被射击,它就不会以枪指向的角度行进。任何想法如何纠正这个,以便它以相同的角度拍摄大炮的设定?

import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.Random;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;

public class Exercise16_25 extends JFrame {

    private Game    board;

    public Exercise16_25(int width, int height) {
        board = new Game(width, height);
        add( board );
        board.setFocusable( true );
    }

    class Game extends JPanel {

        //instance variables
        private int     ballonsHit      = 0;
        private int     ballsShot       = 0;
        private int     xCoordinate     = 0;
        private Point   shootingFrom;
        private boolean shooting        = false;
        Timer           timer;
        private Point   balloonLocation;

        ////////////////////
        //determines how big the gun is vertically
        private int gunSize = 25;

        ////////////////////
        //ensures that a balloon is drawn without appearing cutoff (over the edge)
        private int padding = 25;

        ////////////////////
        //flag to let paintComponent() know to draw the shatter visual
        private boolean isShattered;

        ////////////////////
        //this timer will end the shatter visual
        private Timer stopShatter;

        ///////////////////
        //the current distance of the mini-balloons from the shatter point
        //slowly increases as shatter visual executes
        private int shatterDistance;

        ////////////////////
        //the bulletTilt helps guide the bullet in a diagonal path
        //both are needed as you can change the tilt of the gun
        //while a bullet is flying which require a constant tilt
        private int gunTilt;
        private int bulletTilt;

        ///////////////////////
        //Make the radius one final size, don't use 'balloonRadius*4'
        //Also lets make the balloon a little bigger
        ///////////////////////
        private int     balloonRadius   = 25;
        private int bulletRadius = 5;

        public Game(int width, int height) {

            /////////////////////////
            //You must set the size of this panel so
            //that you can give xCoordinate a value, otherwise
            //getWidth() will equal 0.
            //Since xCoordinate represents the x-coord of the gun,
            //set it to the middle of the board
            this.setSize(width, height);
            xCoordinate     = this.getWidth()/2-1;
            /////////////////////////

            ////////////////////////
            //Don't try this line before the constructor
            //because it depends on the size of the panel
            //which isn't set before setSize is called.
            balloonLocation = setRandomBalloonLocation();

            timer = new Timer( 25, new ActionListener() {

                public void actionPerformed( ActionEvent e ) {
                    repaint();
                }
            } );

            /////////////////////////
            //repaint board every 25 milliseconds
            timer.start();
            /////////////////////////


            ///////////////////////
            //initiate shatter timer. 
            stopShatter = new Timer(2000, new ShatterTerminator());
            ///////////////////////

            addKeyListener( new KeyAdapter() {

                public void keyPressed( KeyEvent e ) {
                    switch ( e.getKeyCode() ) {
                        case KeyEvent.VK_UP:
                            shootBall();
                            bulletTilt = gunTilt;
                            break;
                        case KeyEvent.VK_LEFT:
                            turnLeft();
                            break;
                        case KeyEvent.VK_RIGHT:
                            turnRight();
                            break;
                    }
                }
            } );

        }

        public Point setRandomBalloonLocation() {
            //////////////////////////
            //use java.util.Random to generate random location
            //make x between 1 and the x-coordinate of the right hand edge of the JPanel
            //padding is used so the ball doesn't appear cut off. 
            //make y between 1 and half of the y-coordinate of the lower hand edge of the JPanel
            Random rand = new Random();
            Point location = new Point( rand.nextInt(this.getX()+this.getWidth()-padding)+1, (rand.nextInt(this.getY()+this.getHeight())/2)+1);
            return location;
        }

        public void shootBall() {
            if ( !shooting ) {
                shooting = true;

                shootingFrom = new Point( xCoordinate, getHeight() - gunSize );
                //shootingFrom = new Point( getWidth() / 2 + xCoordinate - bulletRadius / 2, getHeight() - y );
            } else {
                System.out.println( "The ball is already being shot!" );
            }
        }

        public void turnLeft() {
            xCoordinate -= 1;
            gunTilt--;
        }

        public void turnRight() {
            xCoordinate += 1;
            gunTilt++;
        }

        ///////////////////////////
        //One of the biggest issues here is your use of constants (hard-coded values).
        //Use all variables, because some variables will be used in several
        //computations, e.g. balloonLocation, ballonRadius.
        ///////////////////////////

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

            ///////////////////////
            //Draw gun
            //'xcoordinate' represents the position of the gun.
            //turnLeft() and turnRight will control it
            g.drawLine( xCoordinate, getHeight()-gunSize, getWidth() / 2, getHeight() );
            ///////////////////////
            //To increase the thickness of the gun draw two more lines beside it
            g.drawLine( xCoordinate-1, getHeight()-gunSize, getWidth() / 2-1, getHeight() );
            g.drawLine( xCoordinate+1, getHeight()-gunSize, getWidth() / 2+1, getHeight() );
            ///////////////////////


            ///////////////////////
            //Display mini-balloons if the balloon was hit, otherwise display balloon
            if(isShattered) {
                g.drawOval( balloonLocation.x+shatterDistance, balloonLocation.y, balloonRadius/2, balloonRadius/2);
                g.drawOval( balloonLocation.x-shatterDistance, balloonLocation.y, balloonRadius/2, balloonRadius/2);
                g.drawOval( balloonLocation.x, balloonLocation.y+shatterDistance, balloonRadius/2, balloonRadius/2);
                g.drawOval( balloonLocation.x, balloonLocation.y-shatterDistance, balloonRadius/2, balloonRadius/2);
                shatterDistance+=5; //move mini-balloons
            }else {
                g.drawOval( balloonLocation.x, balloonLocation.y, balloonRadius, balloonRadius);
            }
            /////////////////////


            //////////////////
            //Draw bullet
            if ( shooting ) {

                g.drawOval( shootingFrom.x, shootingFrom.y, bulletRadius, bulletRadius);

                ////////////////////////////
                //Check if the bullet hit balloon
                //bullet is between the left and right boundaries of balloon
                //and bullet is between the lower and upper boundaries of balloon
                if((shootingFrom.x >= balloonLocation.x && shootingFrom.x <= (balloonLocation.x+(balloonRadius))) 
                && (shootingFrom.y >= balloonLocation.y && shootingFrom.y <= (balloonLocation.y+(balloonRadius)))
                ) {
                    System.out.println("Ballon Hit!");
                    shatterDistance = 0;
                    isShattered = true;
                    stopShatter.start();
                    shooting = false;
                }
                ///////////////////////////

                ///////////////////////////
                //Detect edge collision
                //Hitting the left and right edge aren't even possible, since
                //bullets shoot straight up
                if(shootingFrom.y <= 0 //hits top
                || shootingFrom.x <= 0 //hits left edge
                || shootingFrom.x >= this.getX()+this.getWidth() //hits right edge
                ) 
                { 
                    System.out.println("Hit Boundary!");
                    shooting = false;
                }
                ///////////////////////////


                ////////////////////////////
                //Continue to move bullet straight up
                //To shoot diagonal, you set shootingFrom.x accordingly
                shootingFrom.x += (bulletTilt/3);
                shootingFrom.y -= 5;
                ////////////////////////////

            }
        }

        private class ShatterTerminator implements ActionListener {
            public void actionPerformed( ActionEvent e ) {
                isShattered = false;
                balloonLocation = setRandomBalloonLocation();
                stopShatter.stop();
            }
        }
    }

    public static void main( String[] args ) {

        int width = 200, height = 300;

        Exercise16_25 frame = new Exercise16_25(width, height);

        frame.setSize( 300, 200 );
        frame.setLocationRelativeTo( null );
        frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
        frame.setVisible( true );
    }
}

1 个答案:

答案 0 :(得分:1)

确定子弹移动角度的线是:

shootingFrom.x += (bulletTilt/3);

除以3可能不是正确的计算方法。

您需要在拉动扳机时计算枪的角度,从中提取“子弹水平增量”并在每次刷新时将其添加到shootingFrom.x