Java游戏开发——飞行射击类游戏

使用到的素材文件夹:

Java游戏开发——飞行射击类游戏_第1张图片Java游戏开发——飞行射击类游戏_第2张图片

素材说明:bg0.jpg是背景图片。bomb_enemy是敌机爆炸时按顺序播放的四帧图片,bullet_0.png是子弹图片,enemy_alive.png是敌机图片,player.png是主角图片;

素材及完整源码链接:https://pan.baidu.com/s/1mwFNPrnNed5jbVZSSrtaUg 提取码: db6h

场景分析:玩家可以通过上下左右控制主角飞机的移动,主角每隔一段时间发射子弹,后台随机位置生成敌机,敌机如果碰到子弹,敌机死亡并播放爆炸效果,同时击中敌机的子弹失效;场景画布滚动播放。

设计子弹Bullet类:

package 雷电飞机射击游戏;

import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.image.ImageObserver;

import javax.swing.JPanel;

public class Bullet {

	static final int BULLET_STEP_X = 3;
	static final int BULLET_STEP_Y = 15;
	static final int BULLET_WIDTH = 30;
	public int m_posX = 0;
	public int m_posY = -20;
	boolean mFacus = true;
	private Image pic[] = null;
	private int mPlayID = 0;
	
	public Bullet(){
		pic = new Image[1];
//		System.out.println(pic.length);
		for(int i=0;i=pic.length)
			mPlayID  = 0;
	}
	
	public void UpdateBullet(){
			m_posY -= BULLET_STEP_Y;
	}
	
}

 

子弹类分析:pic数组用于存放子弹的帧数,由于这里子弹帧数只有一张,所以数组长度设为1;UpdateBullet()用于更新子弹位置;m_posX,m_posY存放子弹坐标;

设计敌机Enemy类:

package 雷电飞机射击游戏;

import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.image.ImageObserver;

import javax.swing.JPanel;

public class Enemy {
	public static final int ENEMY_ALIVE_STATE = 0;
	public static final int ENEMY_DEATH_STATE = 1;
	static final int ENEMY_STEP_Y = 5;
	public int m_posX = 0;
	public int m_posY = 0;
	public int mAnimState = ENEMY_ALIVE_STATE;
	private Image enemyExplorePic[] = new Image[4];
	public int mPlayID = 0;
	
	public Enemy(){
		for(int i=0;i

敌机类分析:m_posX,m_posY存放敌机坐标;enemyExplorePic数组存放敌机爆炸时顺序播放的帧数图片;mAnimState存放敌机状态;UpdateEnemy()控制敌机位置的移动;

设计游戏面板GamePanel类:

package 雷电飞机射击游戏;

import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Iterator;
import java.util.Random;
import java.util.Vector;

import javax.swing.JPanel;


public class GamePanel extends JPanel implements Runnable,KeyListener{

	private int mScreenWidth = 320;//屏宽
	private int mScreenHeight = 480;//屏高
	private static final int STATE_GAME = 0;
	private int mState = STATE_GAME;
	private Image mBitMenuBG0 = null;//背景图1
	private Image mBitMenuBG1 = null;//背景图2
	private int mBitposY0 = 0;//背景1的y轴起点
	private int mBitposY1 = 0;//背景2的y轴起点
	private Sound sound = new Sound();
	private long createEnemyTime = System.currentTimeMillis();//用来监控敌机创建时间
	final static int BULLET_POOL_COUNT = 15;//最多同时存在的子弹数
	final static int PLAN_STEP = 10;//主角移动步长
	final static int PLAN_TIME = 500;//隔500ms发射子弹
	final static int ENEMY_POOL_COUNT = 5;//敌机最多同时存在个数
	final static int ENEMY_POS_OFF = 65;//敌机偏移量
	final static int BULLET_LEFT_OFFSET = 0;//子弹左偏移量
	final static int BULLET_UP_OFFSET = 10;//子弹上偏移量
	
	private Thread mThread = null;//主线程
	private boolean mIsRunning = false;//初始游戏状态未运行
	public int mAirPosX = 0;//主角x位置
	public int mAirPosY = 0;//主角y位置
	Vector mEnemy = new Vector();//存储敌机
	Vector mBullet = new Vector();//存储子弹
	
	public int mSendId = 0;
	public long mSendTime = 0L;
	Image myPlanePic[];
	public int myPlaneID = 0;
	
	public GamePanel(){
		setPreferredSize(new Dimension(mScreenWidth,mScreenHeight));
		setFocusable(true);
		addKeyListener(this);
		sound.loadSound();
		init();
		setGameState(STATE_GAME);
		mIsRunning = true;
		mThread = new Thread(this);
		mThread.start();
		setVisible(true);
	}
	
	public void init(){
		try{
			mBitMenuBG0 = Toolkit.getDefaultToolkit().getImage("D:/Game/bg0.jpg");
			mBitMenuBG1 = Toolkit.getDefaultToolkit().getImage("D:/Game/bg0.jpg");			
		}catch(Exception e){
			e.printStackTrace();
		}
		
		mBitposY0 = 0;
		mBitposY1 = -mScreenHeight;
		mAirPosX = 150;
		mAirPosY = 400;
		myPlanePic = new Image[1];
		for(int i=0;i=mScreenHeight){
				mEnemy.remove(i);								
			}	
		}
		
		long nowTime = System.currentTimeMillis();
		if(mEnemy.size()<5&&nowTime-createEnemyTime>=1000)//至少要间隔1秒才生成飞机
		{
			createEnemyTime = nowTime;
			Enemy tempEnemy = new Enemy();					
			tempEnemy.init(UtilRandom(0,mScreenWidth-30),0);
			mEnemy.add(tempEnemy);
		}
		
		
		if(mSendId=PLAN_TIME){
				Bullet tempBullet = new Bullet();
				tempBullet.init(mAirPosX-BULLET_LEFT_OFFSET, mAirPosY-BULLET_UP_OFFSET);
				mBullet.add(tempBullet);
				mSendTime = now;
				mSendId++;
			}
		}else{
			mSendId= 0;
		}
		
		Collision();
	}
	
	public void Collision(){
		for(int i=0;imEnemy.get(j).m_posX-30&&mBullet.get(i).m_posX=mEnemy.get(j).m_posY&&mBullet.get(i).m_posY<=mEnemy.get(j).m_posY+30){
					mEnemy.get(j).mAnimState = Enemy.ENEMY_DEATH_STATE;
					mBullet.get(i).mFacus = false;//如果子弹撞上敌机,敌机状态修改为死亡,子弹状态修改为失效					
				}
			}
		}
	
	}
	
	//返回的敌机x坐标
	private int UtilRandom(int bottom,int top){
		
		return ((Math.abs(new Random().nextInt()) % (top - bottom)) + bottom);
	}
	
	
	@Override
	public void keyTyped(KeyEvent e) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void keyPressed(KeyEvent e) {
		
		int key = e.getKeyCode();
		//System.out.println(key);
		if(key == KeyEvent.VK_UP){
			mAirPosY -= PLAN_STEP;
		}
		if(key == KeyEvent.VK_DOWN){
			mAirPosY += PLAN_STEP;
		}
		if(key == KeyEvent.VK_LEFT){
			mAirPosX -= PLAN_STEP;
			if(mAirPosX<0){
				mAirPosX = 0;
			}
		}
		
		if(key == KeyEvent.VK_RIGHT){
			mAirPosX += PLAN_STEP;
			if(mAirPosX > mScreenWidth-30){
				mAirPosX = mScreenWidth - 30;
			}
		}
		
//		System.out.println("飞机当前坐标是("+mAirPosX+","+mAirPosY+")");
	}

	@Override
	public void keyReleased(KeyEvent e) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void run() {
		while(mIsRunning){
			draw();
			try{
				Thread.sleep(100);
			}catch(Exception e){
				e.printStackTrace();
			}
		}
	}

}

游戏面板类分析:

①mThread线程用于定时生成子弹,如果当前生效的子弹数没有超过15个,每隔500ms生成子弹,子弹位于主角飞机上方一个子弹上偏移量的位置;

②image0和image1是背景图片,初始化背景图片2位于背景图片1上方,随着游戏的进行,背景图片逐渐下移,当背景图片1到屏幕外时,将背景图片1放到背景图片2上方;

③碰撞检测:循环子弹数组和敌机数组,如果当前子弹生效,当前敌机状态存活,子弹的x值>敌机的x值-子弹宽度&&子弹的x值<敌机的x值+敌机宽度&&子弹的y值>=敌机的y值&&子弹的y值<=敌机的y值+敌机高度,那么修改当前敌机的状态为死亡并播放爆炸动画,修改当前子弹状态为失效;

④如果敌机死亡并且爆炸动画播放完毕,或者敌机超出屏幕显示范围,删除敌机;

⑤如果子弹失效或者超过屏幕范围,删除子弹;

⑥敌机后台随机生成,位于屏幕上方,控制至少每隔1秒才能生成新的敌机,并且当前屏幕上的敌机数量最多不能超过五个;

 

最后还剩游戏窗口类和背景音乐类代码:

package 雷电飞机射击游戏;

import java.awt.Container;

import javax.swing.JFrame;

public class planeFrame extends JFrame{

	public planeFrame(){
		setTitle("飞行射击类游戏");
		GamePanel panel = new GamePanel();
		Container contentPane = getContentPane();
		contentPane.add(panel);
		pack();
	}

	
	public static void main(String[] args) {
		planeFrame e1 = new planeFrame();
		e1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		e1.setVisible(true);
	}

}
package 雷电飞机射击游戏;

import javax.sound.midi.*;

import java.io.File;
import java.io.IOException;

public class Sound {

	String path = new String("D:/Music/");
	String file = new String("nor.mid");
	Sequence seq;
	Sequencer midi;
	boolean sign;
	void loadSound(){
		try {
			seq = MidiSystem.getSequence(new File(path+file));
			midi = MidiSystem.getSequencer();
			midi.open();
			midi.setSequence(seq);
			midi.start();
			midi.setLoopCount(Sequencer.LOOP_CONTINUOUSLY);
			
		} catch (InvalidMidiDataException | IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (MidiUnavailableException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		sign = true;
	}
	
	
	public Sound(String file,String path){
		this.file = file;
		this.path = path;
	}
	
	public Sound() {
		// TODO Auto-generated constructor stub
	}


	void mystop(){midi.stop();midi.close();sign=false;}
	boolean isplay(){return sign;}
	void setMusic(String e){file=e;}
	
}

至此,游戏开发已经完毕,运行效果如下:

Java游戏开发——飞行射击类游戏_第3张图片

你可能感兴趣的:(游戏开发,Java小游戏开发合集)