雷霆戰機小遊戲java
Shootgame類
package com.hyxy.shoot;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.util.Arrays;
import java.util.Timer;
import java.util.TimerTask;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
/**
* 遊戲面板型別,需要繼承Jpanel
* @author Administrator
*
*/
public class ShootGame extends JPanel{
//定義兩個屬性,分別是遊戲面板的寬高
public static final int WIDTH=400;
public static final int HEIGHT=654;
//面板上需要有一個英雄機屬性
protected Hero hero=new Hero();
protected FlyingObject[] objects={};//所有飛行物
protected Bullet[] bullets={};//所有子彈
protected int score;//面板上的總分
protected int life;//面板上的命數
protected int state;
protected static final int startgame=0;//開始狀態
protected static final int running=1;//執行狀態
protected static final int pausegame=2;//暫停狀態
protected static final int over=3;//結束狀態
//定義所有的圖片屬性
public static BufferedImage hero0;
public static BufferedImage hero1;
public static BufferedImage airplane;
public static BufferedImage bee;
public static BufferedImage bullet;
public static BufferedImage background;
public static BufferedImage start;
public static BufferedImage pause;
public static BufferedImage gameover;
//使用靜態塊給圖片賦值
static{
try {
hero0=ImageIO.read(ShootGame.class.getResource("hero0.png"));
hero1=ImageIO.read(ShootGame.class.getResource("hero1.png"));
airplane=ImageIO.read(ShootGame.class.getResource("airplane.png"));
bee=ImageIO.read(ShootGame.class.getResource("bee.png"));
bullet=ImageIO.read(ShootGame.class.getResource("bullet.png"));
background=ImageIO.read(ShootGame.class.getResource("background.png"));
start=ImageIO.read(ShootGame.class.getResource("start.png"));
pause=ImageIO.read(ShootGame.class.getResource("pause.png"));
gameover=ImageIO.read(ShootGame.class.getResource("gameover.png"));
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 重寫面板繪製功能
*/
public void paint(Graphics g){
//繪製背景圖片
g.drawImage(background, 0, 0, null);
paintHero(g);//繪製英雄機物件
paintBullets(g);//繪製所有的子彈
paintFlyingObject(g);//繪製敵機或蜜蜂
paintScore(g);//繪製分數和生命
paintState(g);//繪製遊戲狀態
}
private void paintState(Graphics g) {
switch(state){
case startgame:
g.drawImage(start, 0, 0, null);
break;
case pausegame:
g.drawImage(pause, 0, 0, null);
break;
case over:
g.drawImage(gameover, 0, 0, null);
break;
}
}
private void paintScore(Graphics g) {
int x=10;
int y=20;
g.setFont(new Font(Font.SANS_SERIF,Font.BOLD,20));
g.setColor(new Color(0xFF0000));
g.drawString("分數:"+score, x, y);
g.drawString("生命:"+hero.getLife(), x, y+20);
}
private void paintFlyingObject(Graphics g) {
for(int i=0;i<objects.length;i++){
FlyingObject obj=objects[i];
g.drawImage(obj.image, obj.x, obj.y, null);
}
}
private void paintBullets(Graphics g) {
for(int i=0;i<bullets.length;i++){
Bullet b=bullets[i];
g.drawImage(b.image, b.x, b.y, null);
}
}
/**繪製英雄機*/
private void paintHero(Graphics g) {
//獲取英雄機圖片
BufferedImage image=hero.image;
g.drawImage(image, hero.x, hero.y, null);
}
Timer timer;//新增定時器屬性
/**
* 程式的所有執行邏輯功能
*/
public void action(){
//新增滑鼠監聽事件
MouseAdapter l=new MouseAdapter(){
//滑鼠的移動事件
public void mouseMoved(MouseEvent e){
if(state==running){
//獲取滑鼠的座標
int x=e.getX();
int y=e.getY();
//英雄機與滑鼠位置關聯
hero.moveTo(x, y);
}
}
/**滑鼠點選即進入runnning狀態*/
@Override
public void mouseClicked(MouseEvent e) {
switch (state) {
case startgame:
state=running;
break;
case over:
state=startgame;
//所有的資料都要重置
hero=new Hero();
score=0;
bullets=new Bullet[0];
objects=new FlyingObject[0];
break;
}
}
/**滑鼠離開即進入pausegame狀態*/
@Override
public void mouseExited(MouseEvent e) {
if(state==running){
state=pausegame;
}
}
/**滑鼠進入即進入running狀態*/
@Override
public void mouseEntered(MouseEvent e) {
if(state==pausegame){
state=running;
}
}
};
//將監聽事件繫結到面板上
this.addMouseListener(l);
//新增監聽事件的滑鼠滑動效果
this.addMouseMotionListener(l);
timer=new Timer();
/**
* 設定定時器任務,
* 第一個為任務內容
* 第二個引數為多少毫秒後開始執行任務,
* 第三個是每隔多少毫秒執行任務
* */
timer.schedule(new TimerTask(){
public void run(){
if(state==running){
enterAction();//飛行物進場
stepAction();//所有飛行物開始走步
shootAction();//射擊行為
boomAction();//碰撞行為
outOfBoundsAction();//處理飛行物越界情況
checkGameOver();//檢查遊戲是否結束
}
//重寫繪製效果
repaint();
}
}, 10, 10);
}
/**處理越界行為,將沒有越界的裝入新的陣列*/
protected void outOfBoundsAction() {
FlyingObject[] objLives={};
for(int i=0;i<objects.length;i++){
FlyingObject obj=objects[i];
if(!obj.outOfBounds()){
objLives=Arrays.copyOf(objLives, objLives.length+1);
objLives[objLives.length-1]=obj;
}
}
objects=objLives;
Bullet[] bsLives={};
for(int i=0;i<bullets.length;i++){
Bullet b=bullets[i];
if(!b.outOfBounds()){
bsLives=Arrays.copyOf(bsLives, bsLives.length+1);
bsLives[bsLives.length-1]=b;
}
}
bullets=bsLives;
}
/**檢查遊戲是否結束*/
protected void checkGameOver() {
if(isGameover()){
state=over;//遊戲結束後,更改狀態
}
}
/**判斷遊戲是否結束
* 條件是,生命值為0
* */
private boolean isGameover() {
int index=-1;
for(int i=0;i<objects.length;i++){
FlyingObject obj=objects[i];
if(hero.hit(obj)){
hero.substractLife();//減一條命
hero.setDoubleFire(0);//重置火力值
//讓飛行物消失
index=i;//記錄敵機下標
if(index!=-1){
objects[index]=objects[objects.length-1];
objects=Arrays.copyOf(objects, objects.length-1);
}
break;
}
}
return hero.getLife()<=0;
}
/**子彈與敵機或蜜蜂進行碰撞*/
protected void boomAction() {
for(int i=0;i<bullets.length;i++){
Bullet b=bullets[i];
//判斷b是否與飛行物相撞
boom(b);
}
}
/**檢視子彈與飛行物相撞的情況*/
private void boom(Bullet b) {
int index=-1;//用於記錄被擊中的飛行的下標
for(int i=0;i<objects.length;i++){
FlyingObject obj=objects[i];
//檢視飛行物是否被飛行物擊中
boolean f=obj.shootBy(b);
if(f){
index=i;
break;
}
}
//需要將被擊中的飛行物刪除
if(index!=-1){
//儲存被擊中的飛行物
FlyingObject obj=objects[index];
//將之從陣列中刪除
objects[index]=objects[objects.length-1];
//縮容一位
objects=Arrays.copyOf(objects, objects.length-1);
//檢視被擊中的是敵機還是蜜蜂
if(obj instanceof Bee){
//是蜜蜂
Bee bee=(Bee)obj;
int awardType=bee.getType();//獲取獎勵型別
switch(awardType){
case Award.DOUBLE_FIRE: //變成雙倍火力
hero.addDoubleFire();
break;
case Award.LIFT: //英雄機生命+1
hero.addLife();
break;
}
}else{
//是敵機
Airplane air=(Airplane)obj;
score+=air.getScore();
}
}
}
/**英雄機發射子彈的功能*/
int shootIndex;//定義變數,計運算元彈發射頻率
protected void shootAction() {
shootIndex++;
/*400毫秒一發射,自定義*/
if(shootIndex%30==0){
Bullet[] bs=hero.shoot();//產生子彈
//將產生的子彈存入遊戲面板的子彈陣列
bullets=Arrays.copyOf(bullets, bullets.length+bs.length);
System.arraycopy(bs, 0, bullets,bullets.length-bs.length, bs.length);
}
}
/**所有飛行物開始走步*/
protected void stepAction() {
//敵機和蜜蜂開始走步
for(int i=0;i<objects.length;i++){
FlyingObject obj=objects[i];
obj.step();
}
for(int i=0;i<bullets.length;i++){
Bullet b=bullets[i];
b.step();
}
hero.step();
}
/**讓所有的飛行物即敵機和蜜蜂進場*/
int objectIndex;//用來控制飛行物入場的頻率
protected void enterAction() {
objectIndex++;
/**飛行物入場:每300毫秒就進入一個*/
if(objectIndex%90==0){
/**
* 隨機產生一個飛行物
*/
FlyingObject obj=randomOne();
objects=Arrays.copyOf(objects, objects.length+1);
objects[objects.length-1]=obj;
}
}
/**隨機一個敵機或者是蜜蜂*/
private FlyingObject randomOne() {
int num=(int)(Math.random()*20);
if(num==19){
Bee b=new Bee();
return b;
}else{
Airplane air=new Airplane();
return air;
}
}
public static void main(String[] args) {
//建立一個視窗
JFrame frame=new JFrame("雷霆戰機");
//設定視窗大小
frame.setSize(WIDTH, HEIGHT);
//建立遊戲面板物件
ShootGame panel=new ShootGame();
//將面板嵌入視窗
frame.add(panel);
//設定關閉即結束
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//設定視窗居中
frame.setLocationRelativeTo(null);
//設定視窗在螢幕最前端
frame.setAlwaysOnTop(true);
//設定視窗可見
frame.setVisible(true);
//執行程式邏輯
panel.action();
}
}
FlyingObject:
package com.hyxy.shoot;
import java.awt.image.BufferedImage;
/**
* 定義抽象型別:飛行物
* 將面板上的所有飛行物的共有特徵及其
* 功能封裝到這個抽象類
* @author Administrator
*
*/
public abstract class FlyingObject {
protected BufferedImage image; //圖片
protected int x;//繪製起始橫座標
protected int y;//繪製起始縱座標
protected int width;//圖片的寬
protected int height;//圖片的高
//共同功能
public abstract void step();//走步行為
public abstract boolean outOfBounds();//越界行為
/**
* 檢視飛行物是否被子彈擊中
* @param b 子彈物件
* @return true:表示被擊中
* false:表示沒被擊中
*/
public boolean shootBy(Bullet b) {
/**計算飛行物中心到子彈中心的距*/
//x軸的中心距離
int x1=this.x+width/2; //飛行物的中心x座標
int y1=this.y+height/2; //飛行物的中心y座標
int x2=b.x+b.width /2;
int y2=b.y+b.height/2;
/**滿足碰撞的條件:
* 1.兩個中心的x軸小於子彈與飛行物一半寬度之和的一半
* 2.兩個中心的y軸小於子彈與飛行物一半高度的之和一半
* */
//x軸兩個中心的距離
double xdis=Math.abs((x1-x2));
double ydis=Math.abs((y1-y2));
//y軸兩個中心的距離
return xdis<(width+b.width)/2&&ydis<(height+b.height)/2;
}
}
Award類
package com.hyxy.shoot;
/**
* 定義獎勵介面
* @author Administrator
*如果從蜜蜂身上獲取0,就表示雙倍火力
*如果從蜜蜂身上獲取0,就表示生命值
*/
public interface Award {
int DOUBLE_FIRE=0;//雙倍火力
int LIFT=1;//生命
/**
*獲取獎勵型別的方法
* @return
*/
public int getType();
}
Enemy類
package com.hyxy.shoot;
/**
* 定義敵人介面:
* 敵人被擊中後,只需要提供分數
* @author Administrator
*
*/
public interface Enemy {
/**提供獲取分數的方法*/
public int getScore();
}
Hero類:
package com.hyxy.shoot;
import java.awt.image.BufferedImage;
/**
* 定義定義英雄機型別繼承FlyingObject
* 英雄機需要新增自己的獨有屬性
* @author Administrator
*
*/
public class Hero extends FlyingObject{
protected BufferedImage[] images;//圖片陣列
protected int double_fire;//火力值
protected int life;//生命值
/**
* 新增構造器,給屬性初始化
*/
public Hero(){
image=ShootGame.hero0;//設定英雄機的初始圖片
x=140;//在面板x軸上的初始位置
y=440;//在面板y軸上的初始位置
width=image.getWidth();
height=image.getHeight();
images=new BufferedImage[]{
ShootGame.hero0,ShootGame.hero1//兩張圖片
};
double_fire=0;//預設單倍火力
life=3;//預設3條命
}
/**
* 英雄機的走步行為即兩張圖片的交換
*設計 每四百毫秒交換一次
* 每十毫秒呼叫一次step()方法
*
* */
protected int index;//用來統計圖片的交換頻率
@Override
public void step() {
index++;
/**
* 每10毫秒 index都會自動加一
* */
image=images[index/10%images.length];
}
/**英雄機設定成永不越界,即返回flase*/
@Override
public boolean outOfBounds() {
// TODO Auto-generated method stub
return false;
}
/**
* 隨著滑鼠移動而移動
* @param x 滑鼠的橫座標
* @param y 滑鼠的縱座標
*/
public void moveTo(int x,int y){
/**通過滑鼠的位置計算英雄機的位置
* 滑鼠位於英雄機的中心位置
* */
this.x=x-width/2;
this.y=y-height/2;
}
/**
* 英雄機的射擊功能
* @return
*/
public Bullet[] shoot(){
if(double_fire==0){
Bullet[] bs=new Bullet[1];
//子彈的橫座標
int x=this.x+width/2;
//子彈的縱座標
int y=this.y-ShootGame.bullet.getHeight();
bs[0]=new Bullet(x,y);
return bs;
}else{
//雙倍火力
Bullet[] bs=new Bullet[2];
int x1=width/4;
int y1=ShootGame.bullet.getHeight();
bs[0]=new Bullet(this.x+x1,this.y-y1);
bs[1]=new Bullet(this.x+x1*3,this.y-y1);
return bs;
}
}
/**設定雙倍火力,讓屬性double_fire大於0就行*/
public void addDoubleFire() {
double_fire+=40;
}
/**設定加命*/
public void addLife() {
life++;
}
/**設定減命*/
public void substractLife() {
life--;
}
/**設定獲取英雄機的總命數*/
public int getLife(){
return life;
}
/**用來設定火力值:英雄機被撞,重置火力值*/
public void setDoubleFire(int fire){
this.double_fire=fire;
}
/**判斷英雄機是否與飛行物碰撞*/
public boolean hit(FlyingObject obj) {
//飛行物的中心座標
int x1=obj.x +obj.width/2;
int y1=obj.y+obj.height/2;
//英雄機的座標
int x2=this.x+this.width/2;
int y2=this.y+this.height/2;
int xdis=Math.abs(x1-x2);
int ydis=Math.abs(y1-y2);
return xdis<(this.width+obj.width)/2
&&
ydis<(this.height+obj.height)/2;
}
}
Bullet類
package com.hyxy.shoot;
/**
* 定義子彈型別:Bullet
*