我正在研究一个小小的射击游戏,我从上面有外星人,而在飞船上有太空飞船,外星人正在太空飞船上射击。但我不能让外星人直接指向船。我尝试使用公式:(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());
}
}
}
答案 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() ));
}