我正在开发一款2D java自顶向下飞机游戏。这是一个高中的课程,但我毕业前没有完成它。无论如何,我仍然是Java的初学者,所以我不知道如何扫描我的代码以查看它被挂起的地方。我能够评论出代码并发现我可怕的FPS的原因是我必须绘制的大量图像(飞机,导弹,爆炸和背景)。背景由两个图像组成,这些图像从上到下滚动,然后传送回顶部,让玩家感觉他们正在移动。删除它们会将我的FPS从14跳到45-50左右。我的FPS计算器非常糟糕,只计算当前程序实例的平均FPS。 (我无法弄清楚如何仅计算当前的FPS,抱歉)。
我见过很多人询问如何优化移动背景,但我没有看到任何移动背景的东西。
放一个背景而不是另一个只能将我的FPS提高到20,这是不错的但是我想多一点因为我需要添加更多功能,这可能会减慢它的速度,更不用说看到景观和然后是一个灰色的盒子然后更多的景观。
我相信我正在和Swing一起工作,但你可能想检查一下,正如我所说,我仍然是一个初学者。
修改的 此外,游戏在旧计算机上以更好的FPS运行(即2008年及更早版本) 结束编辑
继承我的主要课程我发表了一个大评论,上面写着“看这里!!!!”关于背景材料的地方。大多数东西都在现场声明和油漆的顶部附近。在ActionPerformed的底部最后几行代码中有实际的运动内容:
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.*;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
public class runTime extends JPanel implements ActionListener, KeyListener {
static String pPlane;
long start = System.currentTimeMillis();
public static void main(String[] args0) {
planeSelect ps = new planeSelect();
while(true){
if(ps.getPlane()=="f15.png"||ps.getPlane()=="f35.png"||ps.getPlane()=="a10.png"){
pPlane=ps.getPlane();
break;
}
}
ps.pullThePlug();
runTime rt=new runTime(Toolkit.getDefaultToolkit().getScreenSize());
}
entity e = new entity(); //creates an entity so all other subclasses can initialize
Timer t = new Timer(5, this); // refresh screen
int count = 0; //used for deceleration
int aam = 0; //number of active AAMs or Missiles
final static int ammo = 10; //number of max active missiles
missile[] fox3 = new missile[ammo]; // missile array
BufferedImage[] msl = new BufferedImage[ammo]; //Image array
final static int maxBaddies = 8; //Maximum number of badguys
badGuy[] baddies = new badGuy[maxBaddies]; //Badguy array
BufferedImage[] planes = new BufferedImage[maxBaddies]; //Image array for Baddies
int plane = 0; //number of flying planes
badGuyMissile[] bmsl = new badGuyMissile[maxBaddies]; //Array of badGuyMissiles
BufferedImage[] bmslImg = new BufferedImage[maxBaddies]; //Array of badGuyMissile images
int[] bgMslUse = new int[maxBaddies]; //used badGuyMissiles
final static int speed = 6; //plane speed and basis for other objects
static int playerSpeed = speed; //player speed (can be increased with afterburner)
final static int decel = 1; //deceleration delay
playerPlane f15; //Playerplane Object
int altCount2=-1; //Annother count storage variable for slowing fuel use to less than instantaneous
final static int fuel = 100; //Fuel count for Afterburner
int remainingFuel = fuel; //Fuel displayed in HUD for Afterburner
boolean[] checkFire=new boolean[maxBaddies]; //prevents badguys from firing more than one missile
Image[] ammoCount = new Image[ammo]; //Images for the Ammo count in the HUD (FIRED)
Image[] ammoCount2 = new Image[ammo]; //Images for the Ammo count in the HUD (LIVE)
int w=0;
int h=0;
int array = (maxBaddies*2)+ammo+1;
//storage in order
//first maxBaddies is badguy planes
//second maxBaddies is badguy missiles
//ammo is player missiles
//last is player plane
int velX=0; //X coordinate modifier for player plane
int velY=0; //Y coordinate modifier for player plane
int score=0; //Player Score
boolean pause = false; //boolean for pausing the game
public runTime(Dimension screenSize) {
w=(int)(screenSize.getWidth()/2);
h=(int)(screenSize.getHeight()/2);
f15=new playerPlane(w,h,pPlane);
JFrame window = new JFrame("AIR ASSAULT");
window.setBounds(0,0,getWidth(), getHeight());
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container c = window.getContentPane();
c.add(this);
t.start();
window.setVisible(true);
System.out.println("start");
for(int i=0;i<maxBaddies;i++){
checkFire[i]=false;
}
for(int i=0;i<ammo;i++){
ammoCount[i]=(new ImageIcon("ammo.png")).getImage();
ammoCount2[i]=(new ImageIcon("AAM.png")).getImage();
}
try {
player = ImageIO.read(new File(pPlane));
} catch (IOException e1) {
e1.printStackTrace();
}
}
Image img = (new ImageIcon("tbg.gif")).getImage(); //Background image 1
Image img2 = (new ImageIcon("tbg.gif")).getImage(); //Background image 2
int[] test = new int[10];
//LOOK HERE!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
int bgy=0; //Background X coordinate
int bgx=0; //Background Y coordinate
long fps; //FPS counter
static BufferedImage player; //Player Image Variable
Image[] boom = new Image[array]; //explosion gifs, 1 for each plane
int[] boomLocX = new int[array]; //X coordinates for explosion
int[] boomLocY = new int[array]; //Y coordinates for explosion
int[] altCount = new int[array]; //count storage for explosion gif expiration
//storage in order
//first maxBaddies is badguy planes
//second maxBaddies is badguy missiles
//ammo is player missiles
//last is player plane
//FROM SCREEN *****
public int getWidth(){
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
double width = screenSize.getWidth();
if(width>1024){
width=1024;
}
return (int)width;
}
public int getHeight(){
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
double height = screenSize.getHeight();
if(height>1024){
height=1024;
}
return (int)height;
}
//RUNTIME RESUME *****
//PAINT COMPONENT *****
public void paintComponent(Graphics g){
//init *****
addKeyListener(this);
setFocusable(true);
setFocusTraversalKeysEnabled(false);
super.paintComponent(g);
//BACKGROUND ***** LOOK HERE!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
g.drawImage(img, bgx, bgy, null);
g.drawImage(img2, bgx, bgy-1024, null);
//HUD MISSILES *****
for(int i=0;i<aam;i++){
g.drawImage(ammoCount[i],((ammo-i)*15)-5,getHeight()-120,null);
}
for(int i=0;i<ammo-aam; i++){
g.drawImage(ammoCount2[i],10+i*15,getHeight()-120,null);
}
//INITIALIZE TEXT APPERANCE *****
//int screenRes = Toolkit.getDefaultToolkit().getScreenResolution();
//int fontSize = (int)Math.round(12.0 * screenRes / 72.0);
Font font = new Font("Arial", Font.BOLD, 15);
g.setFont(font);
//HUD FPS ******
g.drawString("FPS: "+fps, 20, 20);
//HUD SCORE *****
g.drawString("KILL COUNT: "+score, 20, getHeight()-140);
//HUD FUEL
g.drawString("FUEL:", 20, getHeight()-155);
//SET COLOR TO RED
if(remainingFuel>=fuel/2+fuel/6){
g.setColor(Color.GREEN);
}else if(remainingFuel>=fuel/3){
g.setColor(Color.ORANGE);
}else{
g.setColor(Color.RED);
}
g.fillRect(70, getHeight()-166, remainingFuel*2, 10);
g.setColor(Color.BLACK);
g.drawRect(70, getHeight()-166, fuel*2, 10);
//MISSILES *****
for(int i=0;i<aam;i++){ //For Each Missile
if(i<ammo&&(fox3[i]!=null&&msl[i]!=null)){ //if missile exists
if(fox3[i].findY()>getHeight()){ //if not on screen
//destroy
fox3[i]=null;
msl[i]=null;
}else if(fox3[i]!=null&&fox3[i]!=null){
g.drawImage(msl[i], fox3[i].findX(), fox3[i].findY(), null);
fox3[i].aamMove(speed);
}
}
}
//PLAYER PLANE *****
g.drawImage(player,f15.findX(),f15.findY(),null);
//BAD GUYS *****
for(int i=0;i<maxBaddies;i++){ //for all badguys
if(baddies[i]!=null){ //checks weather baddies exists
g.drawImage(planes[i], baddies[i].findX(), baddies[i].findY(), null);
baddies[i].move(speed);
}else{
// THESE LINES ARE FOR BADGUY MISSILES (SEE BELOW) (resets the missiles for next plane)
bgMslUse[i]=0;
checkFire[i]=false;
}
}
//BadGuy Missile draw*****
for(int i=0;i<maxBaddies;i++){ //counts bad guys
if(planes[i]!=null&&baddies[i]!=null&&checkFire[i]==false&&baddies[i].findY()>50&&f15.findY()-baddies[i].findY()>0&&f15.findX()-baddies[i].findY()<750&&bmslImg[i]==null&&Math.abs(baddies[i].findX()-f15.findX())<=90&&bgMslUse[i]==0){
//checks whether
//the plane and baddies exists
//plane has fired
//plane is off screen
//plane is in front of target
//plane is not too far from the target
//the missile has not been created
//the plane is close enough on the X axis
//the plane has not already fired a missile
bmsl[i]=new badGuyMissile(baddies[i].findX(),baddies[i].findY()); //intializes missile object
try { //initializes image
bmslImg[i] = ImageIO.read(new File("badAAM.png"));
} catch (IOException e1) {
e1.printStackTrace();
}
checkFire[i]=true; //prevents an infinite number of missiles
bgMslUse[i]++;
}else if(i<maxBaddies&&bmslImg[i]!=null&&bmsl[i]!=null&&checkFire[i]==true){//draws any previously created missiles
g.drawImage(bmslImg[i],bmsl[i].findX(),bmsl[i].findY(),null);
bmsl[i].aamMove(speed); //missile mover
}
if(checkFire[i]==false){ //resets all missile variables
bmsl[i]=null;
bmslImg[i]=null;
checkFire[i]=false;
}
}
//collision implementation and explosion paint *****
for(int i=0;i<array;i++){
if(altCount[i]!=-1&&count-altCount[i]<=17&&boomLocX[i]!=-1&&boomLocY[i]!=-1){
g.drawImage(boom[i],boomLocX[i],boomLocY[i],null);
}else{
altCount[i]=-1;
}
if(altCount[i]==17){
altCount[i]=-1;
}
}
}
// BEGIN COLCHECK *****
//**
public void colCheck(){
for(int i=0;i<plane;i++){ //counts existing bad planes
for(int j=0;j<aam;j++){ //counts player missiles
if(i<maxBaddies&&j<aam&&baddies[i]!=null&&fox3[j]!=null){ //double check existance
Rectangle r1 = baddies[i].getBounds(); //creates rectangles around both objects
Rectangle r2 = fox3[j].getBounds(); //THIS IS A COLLISION FOR BADGUYS AND PLAYER MISSILES
if(r1.intersects(r2)){ //checks for overlap on rectangles
boomLocX[i]=(baddies[i].findX()+fox3[j].findX())/2; //Stores X coordinates for explosion (see archive order on declaration of int array)
boomLocY[i]=(baddies[i].findY()+fox3[j].findY())/2; //Stores Y coordinates for explosion
altCount[i]=count; //Initializes altCount, the timer for the explosions existance
boom[i] = (new ImageIcon("splosion.gif")).getImage(); //Initializes the explosion gif
baddies[i]=null; //Nullifies object(s)
fox3[j]=null;
score++; //only for this collision increments score
}
}
for(int k=0; k<maxBaddies;k++){ //counts badguys who fire missiles
if(bgMslUse[k]!=0&&bmsl[k]!=null){ //checks to see if there is a badguy missile
if(fox3[j]!=null){
Rectangle r1 = fox3[j].getBounds();
Rectangle r2 = bmsl[k].getBounds(); //THIS IS A COLLISION FOR BADGUY MISSILES AND PLAYER MISSILES
if(r1.intersects(r2)){
boomLocX[maxBaddies+k]=bmsl[k].findX()-50;
boomLocY[maxBaddies+k]=fox3[j].findY()-50;
altCount[maxBaddies+k]=count;
boom[maxBaddies+k] = (new ImageIcon("splosion.gif")).getImage();
fox3[j]=null;
bmsl[k]=null;
}
}
if(f15!=null&&bmsl[k]!=null){
Rectangle r1 = bmsl[k].getBounds();
Rectangle r2 = f15.getBounds(); //THIS IS A COLLISION FOR BADGUY MISSILES AND THE PLAYER
if(r1.intersects(r2)){
boomLocX[maxBaddies*2+ammo]=(bmsl[k].findX()+f15.findX())/2;
boomLocY[maxBaddies*2+ammo]=(bmsl[k].findY()+f15.findY())/2;
altCount[maxBaddies*2+ammo]=count;
boom[maxBaddies*2+ammo] = (new ImageIcon("splosion.gif")).getImage();
bmsl[k]=null;
bmslImg[k]=null;
System.out.println("DEAD");
}
}
}
}
}
for(int j=0;j<maxBaddies;j++){
if(i<maxBaddies&&i!=j&&baddies[i]!=null&&baddies[j]!=null){
Rectangle r1 = baddies[i].getBounds();
Rectangle r2 = baddies[j].getBounds();//THIS IS A COLLISON FOR MULTIPLE BAD GUYS
if(r1.intersects(r2)){
baddies[i]=null;
}
}
}
if(i<maxBaddies&&baddies[i]!=null&&f15!=null){
Rectangle r1 = baddies[i].getBounds();
Rectangle r2 = f15.getBounds(); //THIS IS A COLLISION FOR BADGUYS AND PLAYERS
if(r1.intersects(r2)){
boomLocX[i]=(baddies[i].findX()+f15.findX())/2;
boomLocY[i]=(baddies[i].findY()+f15.findY())/2;
altCount[i]=count;
boom[i] = (new ImageIcon("splosion.gif")).getImage();
baddies[i]=null;
System.out.println("DEAD");
}
}
}
}
//END COL CHECK *****
//*/
/**
//FINE COL CHECK *****
//this tests individual pixels for transparency
public boolean withinBounds(BufferedImage a, BufferedImage b) {
int z = 225;
for(int i = a.getWidth(null);i>=0;i--){ //for a.width
for(int j = a.getHeight(null);j>=0;j--){ //for a.height
if(a.getRGB(j,i)<z){
for(int k = b.getWidth(null);k>=0;k--){ //for b.width
for(int l = b.getHeight(null);l>=0;l--){ //for b.height
if(b.getRGB(l,k)<z){
if(i==k&&j==l){ //coordinates are the same
System.out.println("TRUE");
return true; //collision
}
}
}
}
}
}
}
return false; //no collision
}
//rgb = getPixelData(img, i, j);
// */
public int inboundsX(){
if(f15.findX()<0){
return 1;
}
if(f15.findX()>getWidth()-f15.getWidth()){
return -1;
}
return 0;
}
public int inboundsY(){
if(f15.findY()<0){
return 1;
}
if(f15.findY()>(getHeight()-f15.getHeight())-45){
return -1;
}
return 0;
}
public void afterburners(){
if(altCount2!=count){
altCount2=count;
if(remainingFuel>0){
playerSpeed=speed*2;
remainingFuel--;
}else{
playerSpeed=speed;
}
}else{
playerSpeed=speed;
}
}
public void refuel(){
if(remainingFuel<fuel){
playerSpeed=speed;
remainingFuel++;
}
}
boolean fire = true; //allows for the firing of a missile to prevent all from being fired at one time
boolean mg = false; //allowss for multiple bullets to be fired in one keypress
//LISTENER STUFF BELOW HERE *****
boolean[] acceleration={false,false,false,false}; //allows for independent deceleration in any direction
public void keyPressed(KeyEvent e) {
int c = e.getKeyCode();
if(pause==false){
//MOVEMENT
if (c == KeyEvent.VK_A){
acceleration[0]=true;
velX=-playerSpeed;
}
if (c == KeyEvent.VK_D){
acceleration[1]=true;
velX=playerSpeed;
}
if (c == KeyEvent.VK_S){
acceleration[2]=true;
velY=speed;
}
if (c == KeyEvent.VK_W){
acceleration[3]=true;
velY=-playerSpeed;
}
//MISSILE FIRE
if (c == KeyEvent.VK_SPACE&&aam<ammo&&fire==true){
fire=false;
fox3[aam] = new missile(f15.findX(),f15.findY());
try {
msl[aam] = ImageIO.read(new File("AAM.png"));
} catch (IOException e1) {
e1.printStackTrace();
}
aam++;
}
//MISSILE RELOAD
if(c == KeyEvent.VK_R){
for(int i = 0; i<aam; i++){
fox3[i]=null;
}
aam=0;
}
//AFTERBURNERS
if(c == KeyEvent.VK_SHIFT){
mg=true;
}
}
//PAUSE
if(c == KeyEvent.VK_P){
if(pause==true){
pause=false;
}
}
if(c == KeyEvent.VK_O){
if(pause==false){
pause=true;
}
}
}
public void keyReleased(KeyEvent e) {
if(pause==false){
int c = e.getKeyCode();
if(c == KeyEvent.VK_A&&inboundsX()!=1){ //left
acceleration[0]=false;
}
if(c == KeyEvent.VK_D&&inboundsX()!=-1){ //right
acceleration[1]=false;
}
if(c == KeyEvent.VK_S&&inboundsY()!=-1){ //down
acceleration[2]=false;
}
if(c == KeyEvent.VK_W&&inboundsY()!=1){ //up
acceleration[3]=false;
}
if(c == KeyEvent.VK_SPACE&&fire==false){
fire=true;
}
if(c == KeyEvent.VK_SHIFT){
mg=false;
}
}
}
public void keyTyped(KeyEvent arg0) {
}
public void actionPerformed(ActionEvent arg0) {
if(pause==false){
if(mg==true){
afterburners();
}else{
refuel();
}
count++; //increments count the game regulator most intervals come from count
if(f15!=null){
if(inboundsY()==0&&inboundsX()==0){ //checks weather the new location will be on screen
f15.setLoc(velX,velY); //refreshes F15 location
}else if(count>5){ //if any position not on screen set location to be on screen
if(inboundsX()==-1){ //right
velX-=playerSpeed;
}else if(inboundsX()==1){ //left
velX+=playerSpeed;
}
if(inboundsY()==-1){ //bottom
velY-=playerSpeed;
}else if(inboundsY()==1){ //top
velY+=playerSpeed;
}
f15.setLoc(velX,velY); //refreshes F15 Location
}
}
if(plane<maxBaddies){ //if max planes has not been reached
for(int i=0; i<maxBaddies;i++){ //for all badguys
if(baddies[i]==null){ //badguy does not yet exist
baddies[i] = new badGuy((int)(Math.random()*w)%1024,h-600-(int)(Math.random()*500));
//creates them in random X Y positions above the screen to space them out
try {
planes[i] = ImageIO.read(new File("Su-27.png"));
} catch (IOException e1) {
e1.printStackTrace();
}
plane++;
}
}
}
for(int i=0;i<plane;i++){ //nullifies bad planes so they can respawn
//works for off screen and for collisions
if(i<maxBaddies&&((baddies[i]!=null&&baddies[i].findY()>1200)||baddies[i]==null||planes[i]==null)){
baddies[i]=null;
planes[i]=null;
plane--;
}
}
for(int i = 0; i<aam; i++){ //For each missile
if(fox3[i]==null||msl[i]==null){ //if partially null make entirely null
fox3[i]=null;
msl[i]=null;
}
}
//DECELERATION
if(count%decel==0&&acceleration[0]==false&&(velX!=0||velY!=0)){
if(velX<0)
velX++;
}
if(count%decel==0&&acceleration[1]==false&&(velX!=0||velY!=0)){
if(velX>0)
velX--;
}
if(count%decel==0&&acceleration[2]==false&&(velX!=0||velY!=0)){
if(velY>0)
velY--;
}
if(count%decel==0&&acceleration[3]==false&&(velX!=0||velY!=0)){
if(velY<0)
velY++;
}
//BACKGROUND MOVEMENT !!!!!!!!!!!!!!!!!!LOOK HERE!!!!!!!!!!!!!!!!
if(bgy>1024){ //if background image is greater than 1024 its entirely off the screen and is moved down
bgy-=1024;
}else{ //otherwise it is incrimented
bgy+=speed+3;
}
//COLISIONS
colCheck(); //checks collisions for badguys and missiles
//REPAINT
Toolkit.getDefaultToolkit().sync();
repaint(); //repaints the screen by calling the repaint method
//FPS CALCULATE *****
long deltaTime = System.currentTimeMillis();
fps=1000/((deltaTime-start)/count);
}
}
}
对于大量代码表示歉心,感谢您的帮助。如果我需要发布不同的代码或者我可以删除一些代码,请告诉我。