在java游戏中使用斜坡因子

时间:2013-02-05 04:32:19

标签: java swing 2d-games

我正在研究一个小小的射击游戏,我从上面有外星人,而在飞船上有太空飞船,外星人正在太空飞船上射击。但我不能让外星人直接指向船。我尝试使用公式:(x1-x2)/(y1-y2),它只有60%的时间运行良好。其他时间,拍摄距离屏幕边缘很远。我究竟做错了什么?

package battleShip;

import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;
import java.util.ArrayList;
import java.util.Timer;
import java.util.TimerTask;

import javax.swing.JPanel;

import battleShip.ShipRunner.AlienRunner;


public class Alien extends JPanel{

    private int xPosition;
    private int yPosition;
    private final int LEFT_BORDER = -30;
    private final int RIGHT_BORDER = 1100;
    private final int BUTTOM_BORDER = 730;
    private short hitsCounter;
    private boolean isPainted;
    Toolkit toolkit = Toolkit.getDefaultToolkit(); 
    Image myAlien = toolkit.getImage("c:\\Users\\assaf\\workspace\\My First Game\\images\\alien.png"); 
    Image alienHit = toolkit.getImage("c:\\Users\\assaf\\workspace\\My First Game\\images\\alien2.gif");
    long startTime;
    private int x; //used in: checkAlienState()
    private int y; //used in: checkAlienState()
    private boolean approval;
    private boolean readyForAction;
    private boolean switchMovement;
    private byte randomChoice;
    private Ship ship;
    private ArrayList<AlienShot> shots = new ArrayList<AlienShot>();
    private boolean loaded;
    private Timer timer1; 
    public Timer timer2;


    private enum State {MOVING_LEFT,MOVING_RIGHT,MOVING_DOWN,MOVING_DOWN_RIGHT,MOVING_DOWN_LEFT,STAY_IN_PLACE}
    private State currentState;



    public Alien(Ship ship){
        this.hitsCounter = 0;
        this.ship = ship;
        addShots((byte)2);
        timer1 = new Timer();
        timer1.schedule(new ShootTask(),0, 3);
        timer2 = new Timer();
    }

    public void addShots(byte amount){
        for(byte i = 0;i<amount; i++){
            shots.add(new AlienShot(ship,this));
        }
    }

    public void shoot(){
        byte i;
        if(shots.size()>0){
            for( i = 0;i<shots.size();i++){
                if(shots.get(i).getIsPainted()==false){
                    shots.get(i).setShotXposition(getXposition());
                    shots.get(i).setShotYposition(getYposition());
                    shots.get(i).setRamp(calcRamp(getYposition(),ship.getShipYposition(),getXposition(),ship.getShipXposition()));
                    shots.get(i).setIsPainted(true);
                    break;
                }
                else{
                    continue;
                }
            }
            if(i==shots.size()){
                addShots((byte)2);
                shoot();
            }
        }

    }

    public float calcRamp(int y1,int y2,int x1,int x2){
        float ramp;
        if(x1==x2){
            ramp = 0;
        }
        else{
        ramp = (y1-y2)/(x1-x2);
        }
        return ramp;
    }

    public ArrayList<AlienShot>getShotsArray(){
        return this.shots;
    }

    public void setLoaded(boolean load){
        this.loaded = load;
    }

    public boolean getLoaded(){
        return this.loaded;
    }

    public void setRandomChoice(){
        this.randomChoice = (byte)(Math.random()*2);
    }
    public byte getRandomChoice(){
        return this.randomChoice;
    }

    public void setSwitchMovement(boolean switchOrNot){
        this.switchMovement = switchOrNot;
    }

    public boolean getSwitchMovement(){
        return this.switchMovement;
    }

    public void setReadyForAction(boolean ready){
        this.readyForAction=ready;
    }

    public boolean checkReadyForAction(){
        return this.readyForAction;
    }

    public boolean getIsPainted(){
        return this.isPainted;
    }

    public void setIsPainted(boolean painted){
        this.isPainted=painted;
    }

    public void raiseHitsCounter(){
        this.hitsCounter++;
    }

    public short getHitsCounter(){
        return this.hitsCounter;
    }

    public synchronized int getXposition(){
        return this.xPosition;
    }

    public void setXposition(int position){
        this.xPosition = position;
    }

    public synchronized int getYposition(){
        return this.yPosition;
    }

    public synchronized void setYposition(int position){
        this.yPosition = position;
    }

    public void moveLeft(){

            this.xPosition--;


        currentState = State.MOVING_LEFT;
    }

    public void moveRight(){

        this.xPosition++;


        currentState = State.MOVING_RIGHT;
    }

    public void moveDown(){

            this.yPosition++;

        currentState = State.MOVING_DOWN;
    }

    public void stayInPlace(){
        this.xPosition = getXposition();
        this.yPosition = getYposition();

        currentState = State.STAY_IN_PLACE;

    }

    public void moveDownAndLeft(){

        this.xPosition--;
        this.yPosition++;


        currentState = State.MOVING_DOWN_LEFT;
    }

    public void moveDownAndRight(){

        this.xPosition++;
        this.yPosition++;


        currentState = State.MOVING_DOWN_RIGHT;
    }

    public void checkAlienState(){ //this method will run only single time when called (look in the paintAlien() method of this class)
                                   //and will change the startTime variable,so that the burning alien gif will be painted for 2 seconds only.
        if(this.x==this.y){
        this.startTime = System.currentTimeMillis();
            this.x++;
            this.approval = true;

        }
    }


    public void move(){


        if(getXposition()>=RIGHT_BORDER && getHitsCounter()<5){
            setXposition(RIGHT_BORDER);
        }
        if(getXposition()<=LEFT_BORDER && getHitsCounter()<5){
            setXposition(LEFT_BORDER);
        }
        if(getXposition()>=LEFT_BORDER && getXposition()<=RIGHT_BORDER && getSwitchMovement() && getHitsCounter()<5){


                setRandomChoice();
                switch(getRandomChoice()){
                case 0:
                    moveLeft();
                    break;
                case 1:
                    moveRight();
                    break;

                }


        }

        if(getXposition()>=LEFT_BORDER && getXposition()<=RIGHT_BORDER && !getSwitchMovement() && getHitsCounter()<5){
            switch(getRandomChoice()){
            case 0:
                moveLeft();
                break;
            case 1:
                moveRight();
                break;
            }
        }

        if(getHitsCounter()>=5){
            stayInPlace();
        }



    }



    public void paintAlien(Graphics g){

        if(getHitsCounter()<5){
            g.drawImage(myAlien, getXposition(), getYposition(),null);
        }
        if(getHitsCounter()>=5){
            g.drawImage(alienHit, getXposition(), getYposition(),null);
            checkAlienState();

        }

            if(approval){
                if(System.currentTimeMillis()>startTime+2000){

                setIsPainted(false);
            }
        }
    }


    public class ShootTask extends TimerTask{

        @Override
        public void run() {
            if(loaded && getHitsCounter()<5){
                shoot();
                setLoaded(false);
            }

            for(AlienShot shot:shots){
                if(shot.getIsPainted()){
                shot.move();

                }
            }


        }

    }

    public class setLoadedForShooting extends TimerTask{

        @Override
        public void run() {
            setLoaded(true);

        }

    }


}
package battleShip;

import java.awt.Color;
import java.awt.Graphics;

import javax.swing.JPanel;

public class AlienShot extends JPanel {

    private int yPosition;
    private float xPosition;
    private int shipTargetPosition;
    private boolean isPainted;
    private float ramp;
    private Ship ship;
    private Alien alien;




    public AlienShot(Ship ship,Alien alien){
        this.ship = ship;
        this.alien = alien;
    }

    public void setRamp(float ramp){
        this.ramp = ramp;
    }

    public float getRamp(){
        return this.ramp;
    }

    public void setShotXposition(float position){
        this.xPosition = position;
    }



    public float getShotXposition(){
        return this.xPosition;
    }

    public void setShotYposition(int position){
        this.yPosition = position;
    }

    public int getShotYposition(){
        return this.yPosition;
    }

    public void setShipTargetPosition(int position){
        this.shipTargetPosition = position;
    }

    public int getShipTargetPosition(){
        return this.shipTargetPosition;
    }

    public void setIsPainted(boolean painted){
        this.isPainted = painted;
    }

    public boolean getIsPainted(){
        return this.isPainted;
    }


    public void paintAlienShot(Graphics g){
        g.setColor(Color.BLUE);
        g.fillOval((int)getShotXposition()+12,getShotYposition()+20, 8, 8);
    }



    public void move(){

        setShotYposition(getShotYposition()+1);
        //setShotXposition(getShotXposition()+getRamp());


    }

}

package battleShip;

import java.util.ArrayList;

public class AliensStorage {

    public static ArrayList<Alien>alienList1 = new ArrayList<Alien>();
    private Ship ship;


    public AliensStorage(Ship ship){
        this.ship = ship;

    }




    public void fillAlienList1(int number,ArrayList<Alien>list){
        for(int i=0; i<number; i++){
            list.add(new Alien(ship));
        }
    }

    public void setAlienList1Position(){
        alienList1.get(0).setXposition(505);
        alienList1.get(0).setYposition(-40);
        alienList1.get(1).setXposition(505);
        alienList1.get(1).setYposition(-120);
        alienList1.get(2).setXposition(505);
        alienList1.get(2).setYposition(-200);
        alienList1.get(3).setXposition(505);
        alienList1.get(3).setYposition(-280);
        alienList1.get(4).setXposition(505);
        alienList1.get(4).setYposition(-360);
        alienList1.get(5).setXposition(505);
        alienList1.get(5).setYposition(-440);
    }

    public void setAliensForAction(ArrayList<Alien> list){
        for(Alien alien:list){
            alien.setIsPainted(true);

        }


    }


    public static boolean checkIfAllAliensAreDead(ArrayList<Alien>list){
        short c = 0;
        for(int i = 0;i<list.size();i++){
            if(list.get(i).getIsPainted()==false){
                c++;
            }
            else{
                continue;
            }
        }
        if(c==list.size()){
            return true;
        }

            return false;

    }


    public static boolean checkIfAllAliensAreReadyForAction(ArrayList<Alien>list){
        int c = 0;
        for(int i = 0; i<list.size();i++){
            if(list.get(i).checkReadyForAction()){
                c++;
            }
            else{
                continue;
            }

        }
        if(c==list.size()){
            return true;
        }
        return false;

    }


}
package battleShip;

import java.util.ArrayList;

import battleShip.ShipRunner.AlienRunner;

public class AlienStartingScenes {

    public void startingSceneAlienList1(){

        for(Alien alien:AliensStorage.alienList1){

            if(alien.getYposition()<100){
                alien.moveDown();
            }
        }

        if(AliensStorage.alienList1.get(0).getYposition()>=100&&AliensStorage.alienList1.get(0).getXposition()>=150){
            AliensStorage.alienList1.get(0).moveLeft();

        }

        else{
            AliensStorage.alienList1.get(0).stayInPlace();

        }

        if(AliensStorage.alienList1.get(1).getYposition()>=100&&AliensStorage.alienList1.get(1).getXposition()>=250){
            AliensStorage.alienList1.get(1).moveLeft();
        }

        else{
            AliensStorage.alienList1.get(1).stayInPlace();

        }

        if(AliensStorage.alienList1.get(2).getYposition()>=100&&AliensStorage.alienList1.get(2).getXposition()>=350){
            AliensStorage.alienList1.get(2).moveLeft();
        }

        else{
            AliensStorage.alienList1.get(2).stayInPlace();

        }

        if(AliensStorage.alienList1.get(3).getYposition()>=100&&AliensStorage.alienList1.get(3).getXposition()<=650){
            AliensStorage.alienList1.get(3).moveRight();
        }

        else{
            AliensStorage.alienList1.get(3).stayInPlace();

        }

        if(AliensStorage.alienList1.get(4).getYposition()>=100&&AliensStorage.alienList1.get(4).getXposition()<=750){
            AliensStorage.alienList1.get(4).moveRight();
        }

        else{
            AliensStorage.alienList1.get(4).stayInPlace();

        }

        if(AliensStorage.alienList1.get(5).getYposition()>=100&&AliensStorage.alienList1.get(5).getXposition()<=850){
            AliensStorage.alienList1.get(5).moveRight();
        }

        else{
            AliensStorage.alienList1.get(5).stayInPlace();



        }
    }


    public void repositionAliensList1(){
        if(AliensStorage.alienList1.get(1).getYposition()>50 && AliensStorage.alienList1.get(4).getYposition()>50){
            AliensStorage.alienList1.get(1).setYposition(AliensStorage.alienList1.get(1).getYposition()-1);
            AliensStorage.alienList1.get(4).setYposition(AliensStorage.alienList1.get(4).getYposition()-1);

        }

    }



}

package battleShip;



import javax.swing.JFrame;


public class MainWindow {

    private JFrame frame;
    private Ship ship;



    public MainWindow(Ship ship){

        this.ship = ship;
        frame = new JFrame();
        frame.setSize(1100,700);
        frame.setLocation(150, 10);
        frame.setResizable(false);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(ship);
        frame.setVisible(true);

    }

package battleShip;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.ArrayList;
import javax.swing.JPanel;


public class Ship extends JPanel implements KeyListener {

    private int xPosition;
    private ArrayList<Shot> shotsSupply = new ArrayList<Shot>();
    private int shotsSupplyIndex;
    private boolean leftKeyPressed;
    private boolean rightKeyPressed;
    private boolean gotHit;
    private ArrayList<Alien> currentAlienList;


    private enum Movement {MOVE_RIGHT,MOVE_LEFT,STAY_PUT}
    private Movement currentMovement;


    Toolkit toolkit = Toolkit.getDefaultToolkit(); 
    Image myShip = toolkit.getImage("c:\\Users\\assaf\\workspace\\My First Game\\images\\ship.png"); 


    public Ship(){


        this.xPosition = 500;
        this.shotsSupplyIndex = 0;
        fillShotsSupply(300);
        currentMovement = Movement.STAY_PUT;
        addKeyListener(this);
        setFocusable(true);
        setFocusTraversalKeysEnabled(false);

    }

    public ArrayList<Alien>getCurrentAlienList(){
        return this.currentAlienList;
    }

    public void setCurrentAlienList(ArrayList<Alien>list){
        this.currentAlienList = list;
    }



    public void fillShotsSupply(int shotsAmount){
        for(int i = 0; i<shotsAmount; i++){
            shotsSupply.add(new Shot(this));
        }
    }

    public ArrayList<Shot> getShotSupply(){
        return this.shotsSupply;
    }

    public synchronized int getShipXposition(){
        return this.xPosition;
    }

    public synchronized int getShipYposition(){
        return 610;
    }

    public void setShipXposition(int position){
        this.xPosition = position;
    }

    public void move(Movement movement){
        switch(movement){
        case MOVE_RIGHT:
            this.xPosition++;
            break;

        case MOVE_LEFT:
            this.xPosition--;
            break;

        case STAY_PUT:
            this.xPosition = getShipXposition();
            break;
        }


    }

    public void moveShip(){

            if(getShipXposition()<0){
                setShipXposition(0);
            }

            if(getShipXposition()>1050){
                setShipXposition(1050);
            }

            if(leftKeyPressed == false && rightKeyPressed == false){
                currentMovement = Movement.STAY_PUT;
            }
            move(currentMovement);


    }


    //this is the main painting method

    public void paintComponent(Graphics g){
        super.paintComponent(g);
        this.setBackground(Color.BLACK);

        //painting the ship
        g.drawImage(myShip,this.xPosition,610,null);


        //painting the shots
        for(Shot shot:getShotSupply()){
            if(shot.getShootable()){
                shot.paintShot(g);
            }
        }


        //painting the aliens
        for(Alien alien:getCurrentAlienList()){
            if(alien.getIsPainted()){
                alien.paintAlien(g);
            }
        }
        //painting the alien shots
        for(Alien alien:getCurrentAlienList()){
            for(AlienShot shot:alien.getShotsArray()){
                if(shot.getIsPainted()){
                    shot.paintAlienShot(g);
                }
            }
        }


    }


    @Override
    public void keyTyped(KeyEvent e) {


    }

    @Override
    public void keyPressed(KeyEvent e) {

        int c = e.getKeyCode();
        if(c==KeyEvent.VK_LEFT){
            currentMovement = Movement.MOVE_LEFT;
            leftKeyPressed = true;

        }

        if(c==KeyEvent.VK_RIGHT){
            currentMovement = Movement.MOVE_RIGHT;
            rightKeyPressed = true;

        }

        if(c==KeyEvent.VK_CONTROL){
            if(shotsSupplyIndex<shotsSupply.size()){
                shotsSupply.get(shotsSupplyIndex).setXposition(getShipXposition());
                shotsSupply.get(shotsSupplyIndex).setShootable(true);
                shotsSupply.get(shotsSupplyIndex).timer.schedule(shotsSupply.get(shotsSupplyIndex).
                new ShootingTask(),0,2);
                shotsSupplyIndex++;
            }
        }
    }

    @Override
    public void keyReleased(KeyEvent e) {

        int c = e.getKeyCode();
        if(c==KeyEvent.VK_LEFT){
            leftKeyPressed = false;
        }

        if(c==KeyEvent.VK_RIGHT){
            rightKeyPressed = false;
        }

    }






}

package battleShip;

import java.util.ArrayList;





public class ShipRunner extends Thread {

    private Ship ship;


    public ShipRunner(Ship ship){
        this.ship = ship;

    }

    @Override
    public void run() {
        super.run();

            while(1<2){
                ship.moveShip();
                try{
                ShipRunner.sleep(2);
                }
                catch(Exception e){}
                ship.repaint();
            }




        }

    public class AlienRunner extends Thread{

        AlienStartingScenes scenes;

        public AlienRunner(AlienStartingScenes scenes){
            this.scenes = scenes;
        }



        @Override
        public void run() {
            super.run();
            try{
                AlienRunner.sleep(3000);
            }
            catch(Exception e){}


            long startTime = System.currentTimeMillis();
            while(System.currentTimeMillis()<startTime+3000){
                scenes.startingSceneAlienList1();
                try{
                    AlienRunner.sleep(3);
                }
                catch(Exception e){}
            }

            startTime = System.currentTimeMillis();
            while(System.currentTimeMillis()<startTime+2500){
                scenes.repositionAliensList1();
                try{
                    AlienRunner.sleep(13);
                }
                catch(Exception e){}
            }
            for(Alien alien:AliensStorage.alienList1){
                alien.setReadyForAction(true);
                alien.timer2.schedule(alien.new setLoadedForShooting(),0,(long)(Math.random()*2000+1000));

            }
            while(!AliensStorage.checkIfAllAliensAreDead(AliensStorage.alienList1)){
                for(Alien alien:AliensStorage.alienList1){
                    alien.setSwitchMovement(true);
                }
                startTime = System.currentTimeMillis();
                while(System.currentTimeMillis()<startTime+(int)(Math.random()*1000+6000)){
                    for(Alien alien:AliensStorage.alienList1){
                        alien.move();
                        alien.setSwitchMovement(false);
                    }
                    try{
                        AlienRunner.sleep(6);
                    }
                    catch(Exception e){}
                }
            }

        }
    }










    public static void main(String[]args){

        System.setProperty("sun.java2d.opengl", "True");
        Ship gameShip = new Ship();
        AliensStorage storage = new AliensStorage(gameShip);
        storage.fillAlienList1(6,AliensStorage.alienList1);
        storage.setAliensForAction(AliensStorage.alienList1);
        storage.setAlienList1Position();
        gameShip.setCurrentAlienList(AliensStorage.alienList1);
        AlienStartingScenes scenes = new AlienStartingScenes();
        MainWindow window = new MainWindow(gameShip);
        ShipRunner shipRunner = new ShipRunner(gameShip);
        ShipRunner.AlienRunner alienRunner = shipRunner.new AlienRunner(scenes);
        shipRunner.start();
        alienRunner.start();

    }


}

package battleShip;

import java.awt.Color;
import java.awt.Graphics;
import java.util.ArrayList;
import java.util.Timer;
import java.util.TimerTask;
import javax.swing.JPanel;


public class Shot extends JPanel{


    private int yPosition;
    private int xPosition;
    private boolean shootable;
    private boolean scanning;
    private Ship ship;
    Timer timer = new Timer();


    public Shot(Ship ship){

        this.ship = ship;
        this.yPosition = 610;

    }

    public void setXposition(int position){
        this.xPosition = position;
    }

    public int getXposition(){
        return this.xPosition;
    }


    public boolean getShootable(){
        return this.shootable;
    }

    public void setShootable(boolean shootable){
        this.shootable = shootable;

    }


    public void move(){

        this.yPosition--;

    }

    public int getShotYposition(){
        return this.yPosition;
    }


    public void paintShot(Graphics g){


        g.setColor(Color.ORANGE);
        g.drawLine(xPosition+23,yPosition,xPosition+23,yPosition-15);

    }

    public void checkIfHitAlien(ArrayList<Alien> list){

            for(Alien alien:list){
                if(getShotYposition()==alien.getYposition()+20&&getXposition()>=alien.getXposition()-20&&getXposition()<=alien.getXposition()+8){
                    alien.raiseHitsCounter();
                    setShootable(false);
                    this.timer.cancel();
                }
            }
    }


    public class ShootingTask extends TimerTask{

        @Override
        public void run() {
            move();
            checkIfHitAlien(ship.getCurrentAlienList());

        }

    }

}

1 个答案:

答案 0 :(得分:1)

您已将x,y位置变量声明为int,而斜坡因子为float 当外星人通过1像素垂直前进时,渐变因子通常会结束< 0.5,因此移动看起来就像是这样:

public void move(){
    setShotYposition(getShotYposition()+1);
    setShotXposition((int)( (int)getShotXposition()+ (float)getRamp() ));
}

getRamp() < 0.5时整个shotXposition四舍五入到原来的状态,就好像没有斜坡一样。

要解决此问题,只需将x,y viariables转换为float,只有在绘制内容时才将它们转换为int。此外,public synchronized int getShipXposition()等对应的getter也应返回float

当然move()应保留:

public void move(){
    setShotYposition(getShotYposition()+1);
    setShotXposition(getShotXposition()+getRamp() ));
}