基本功能:
扩展功能:
主要实现的技术:
1.碰撞检测
2.背景滚动
将一张背景图片复制为2张,从上到下连续的拼接在一起连续切换,使其不会出现图片的卡顿和瞬移现象。
3.内存释放
这个程序中有大量的地方需要使用内存,如果不及时删除会出现闪图等情况,容易导致程序崩溃,要及时释放内存资源。
4.定时器
schedule()函数来设置定时器
5.监听器
实现由鼠标控制飞机的移动
6.数据库
将玩家的分数按照降序存入数据库,并在游戏结束时显示
7.多线程
实现背景音效
运用的设计模式:
源码:
World类
package cn.tedu.shoot;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Image;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;//面板
//import cn.music.www.Shootmusic;
import java.util.Arrays;
import java.util.Random;
//定时器
import java.util.Timer;
import java.util.TimerTask;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
public class World extends JPanel{
public static final int WIDTH=800;//窗口的宽
public static final int HEIGHT=1000;//窗口的高
public static final int START=0;
public static final int RUNNING=1;
public static final int PAUSE=2;
private int state=START;//默认为启动状态
public static final int GAME_OVER=3;
private Sky sky= new Sky();
private Hero hero= new Hero();
private FlyingObject[] enemies= {};
private Bullet[] bullets= {};
private BossBullet[] bossbullets= {};
public static int score=1;
public static FlyingObject BossLife;
//生成敌人对象
//控制敌机的生成数量
public FlyingObject nextOne() {
if(score%100==0) {
return new TheBoss();
}else {
Random rand=new Random();
int type=rand.nextInt(20);
if(type<5){
return new Bee();
}else if(type<14) {
return new AIrplane();
}else
return new BigAirplane();
}
}
private FlyingObject TheBoss() {
// TODO Auto-generated method stub
return null;
}
int shootIndex=0;//子弹入场计数器
public void shootAction() {
shootIndex++;//每十毫秒加一
if(shootIndex%30==0) {//每300毫秒走一次
Shootmusic sm = new Shootmusic();
sm.start();
Bullet[] bs=hero.shoot();
bullets=Arrays.copyOf(bullets, bullets.length+bs.length);//扩容(bs有几个元素,就扩大几个元素)、
System.arraycopy(bs, 0, bullets,bullets.length-bs.length , bs.length);
/*
* bs是原始数组
* 0是从原数组bs第一个元素开始
* bullets是目标数组
* bullets.length-bs.lenngth从下标几开始复制
* bs.length是复制几个元素*/
//System.out.println(bs.length);
if(BossLife.life>0)
{
BossBullet[] bbs=BossLife.shoot1();
bossbullets=Arrays.copyOf(bossbullets, bossbullets.length+bbs.length);//扩容(bs有几个元素,就扩大几个元素)、
System.arraycopy(bbs, 0, bossbullets,bossbullets.length-bbs.length , bbs.length);
}
}
}
//子弹和敌机的进场
public void stepAction() {
sky.step();
for(int i=0;i
飞机的基类 FlyingObject
package cn.tedu.shoot;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.util.Random;
public abstract class FlyingObject {
public static final int LIFE=0;
public static final int DEAD=1;
public static final int REMOVE=2;
protected int state=LIFE;
public int life;
protected int width;//宽
protected int height;//高
public float x;//横坐标
public float y;//纵坐标
//提供给敌机,Boss的构造函数
public FlyingObject(int width,int height,int life){
this.width=width;
this.height=height;
Random rand= new Random();
x=rand.nextInt(World.WIDTH-this.width);
this.x=x;
this.y=y;
y=-this.height;
this.life=life;
}
/*提供给英雄机,子弹,天空的构造方法*/
public FlyingObject(int width,int heigth,float x,float y){
this.width=width;
this.height=height;
this.x=x;
this.y=y;
}
/*此处为public访问权限后,其子类也要加public。
派生类的访问权限要大于等于基类 */
public abstract void step() ;
public abstract BufferedImage getImage();
public boolean isLife() {
return state==LIFE;
}
public boolean isDead() {
return state==DEAD;
}
public boolean isRemove() {
return state==REMOVE;
}
public boolean outOfBounds() {
return this.y>=World.HEIGHT;
}
public void paintObject(Graphics g)
{
g.drawImage(this.getImage(),(int)this.x,(int)this.y,null);
}
//碰撞检测。this是敌人,other是子弹或英雄机
public boolean hit(FlyingObject other) {
float x1=this.x-other.width;//x1敌人x-减去子弹的宽
float x2=this.x+this.width;
float y1=this.y-other.height;
float y2=this.y+this.height;
float x=other.x;
float y=other.y;
//x在x1与x2之间并且y在y1与y2之间即为碰撞
return x>=x1&&x<=x2&&y>=y1&&y<=y2;
}
//飞行物被销毁
public void goDead() {
state=DEAD;
}
public BossBullet[] shoot1() {
// TODO Auto-generated method stub
return null;
}
}
图片资源类 Images
package cn.tedu.shoot;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;
/*封装与图片相关的工具*/
public class Images {
public static BufferedImage pause;
public static BufferedImage gameover;
public static BufferedImage start;
public static BufferedImage background;//背景图
public static BufferedImage[] bullet;//子弹图
public static BufferedImage[] heros;//英雄机
public static BufferedImage[] airplanes;//小敌机
public static BufferedImage[] bigairplanes;//大敌机
public static BufferedImage[] bees;//蜜蜂
public static BufferedImage boss;//蜜蜂
public static BufferedImage Bossbullet;//子弹图
static {//初始化静态资源
start=readImage("start.png");
pause=readImage("pause.png");
gameover=readImage("gameover.png");
background=readImage("background11.png");
boss=readImage("boss.png");
Bossbullet=readImage("bullet1.png");
bullet=new BufferedImage[4];
bullet[0]=readImage("z0.png");
bullet[1]=readImage("z1.png");
bullet[2]=readImage("z2.png");
bullet[3]=readImage("z3.png");
heros=new BufferedImage[8];
heros[0]=readImage("hero1.png");
heros[1]=readImage("hero2.png");
heros[2]=readImage("hero3.png");
heros[3]=readImage("hero4.png");
heros[4]=readImage("hero11.png");
heros[5]=readImage("hero22.png");
heros[6]=readImage("hero33.png");
heros[7]=readImage("hero44.png");
airplanes=new BufferedImage[5];
bigairplanes=new BufferedImage[5];
bees=new BufferedImage[5];
airplanes[0]=readImage("敌机1.png");
bigairplanes[0]=readImage("敌机4.png");
bees[0]=readImage("bee0.png");
for(int i=1;i
敌机接口 Enemy
package cn.tedu.shoot;
//得分界口
public interface Enemy {
//得分
public int getScore();
}
奖励接口:
package cn.tedu.shoot;
//奖励接口
public interface Award {
public int DOUBLE_fIRE=0;//默认static final
public int LIFE=1;
public int TIME=2;
//获取奖励类型
public int getAwardType();//默认abstract
}
小敌机Airplane类
package cn.tedu.shoot;
import java.awt.image.BufferedImage;
/*小敌机*/
public class AIrplane extends FlyingObject implements Enemy{
private int speed;//移动速度
public AIrplane(){
super(48,50,1);
speed=2;
}
/*小敌机的移动*/
public void step() {
y+=speed;
}
int index=1;
public BufferedImage getImage() {
if(isLife()) {
return Images.airplanes[0];
}else if(isDead()) {
BufferedImage img= Images.airplanes[index++];
if(index==Images.airplanes.length) {
state=REMOVE;
}
return img;
}
return null;
}
@Override
public int getScore() {
// TODO Auto-generated method stub
return 1;//打掉小敌机,玩家得一分
}
}
奖励敌机 Bee类()
package cn.tedu.shoot;
import java.awt.image.BufferedImage;
import java.util.Random;
public class Bee extends FlyingObject implements Award{
private int xspeed;//x坐标的移动速度
private int yspeed;//y坐标的移动速度
private int awardType;//奖励类型
public Bee(){
super(60,51,0);
xspeed=1;
yspeed=2;
Random rand = new Random();
awardType=rand.nextInt(2);
}
/*小蜜蜂的移动*/
public void step() {
x+=xspeed;
y+=yspeed;
if(x<=0||x>=World.WIDTH-this.width) {
xspeed*=-1;
}
}
int index=1;
public BufferedImage getImage() {
if(isLife()) {
return Images.bees[0];
}else if(isDead()) {
BufferedImage img= Images.bees[index++];
if(index==Images.bees.length) {
state=REMOVE;
}
return img;
}
return null;
}
@Override
public int getAwardType() {
// TODO Auto-generated method stub
return awardType;
}
}
大敌机类 BigAirplane
package cn.tedu.shoot;
import java.awt.image.BufferedImage;
public class BigAirplane extends FlyingObject implements Enemy{
private int speed;
public BigAirplane(){
super(66,99,2);
speed=2;
}
/*大敌机的移动*/
public void step() {
y+=speed;
}
int index=1;
public BufferedImage getImage() {
if(isLife()) {
return Images.bigairplanes[0];
}else if(isDead()) {
BufferedImage img= Images.bigairplanes[index++];
if(index==Images.bigairplanes.length) {
state=REMOVE;
}
return img;
}
return null;
}
@Override
public int getScore() {
// TODO Auto-generated method stub
return 2;
}
}
英雄机类 Hero()
package cn.tedu.shoot;
import java.awt.image.BufferedImage;
public class Hero extends FlyingObject{
public int life;//生命值
private int doubleFire;//火力值
private int speed;
public Hero(){
super(97,139,140,400);
life=3;
doubleFire=0;
}
/*英雄机切换图片*/
/*英雄机随鼠标坐标移动,x和y是鼠标的x坐标和y坐标*/
public void moveTo(int x,int y) {
if(World.score<4) {
this.x=x-78;
this.y=y-78;
}
else if(World.score<14) {
this.x=x-58;
this.y=y-45;
}
else if(World.score<18) {
this.x=x-78;
this.y=y-78;
}
else if(World.score<28) {
this.x=x-48;
this.y=y-45;
}
else if(World.score<32) {
this.x=x-78;
this.y=y-78;
}
else if(World.score<42) {
this.x=x-55;
this.y=y-48;
}
else if(World.score<46) {
this.x=x-78;
this.y=y-78;
}
else{
this.x=x-57;
this.y=y-48;
}
}
public void step() {
System.out.println("Hero");
}
int index=1;
public BufferedImage getImage() {
if(isLife()) {
if(World.score<4)
return Images.heros[4];
else if(World.score<14)
return Images.heros[0];
else if(World.score<18)
return Images.heros[5];
else if(World.score<28)
return Images.heros[1];
else if(World.score<32)
return Images.heros[6];
else if(World.score<42)
return Images.heros[2];
else if(World.score<46)
return Images.heros[7];
else return Images.heros[3];
}
return null;
}
public Bullet[] shoot() {
if(World.score<4){
Bullet[] bs=new Bullet[1];
bs[0]=new Bullet(x+67,y-20);
return bs;
}
else if(World.score<14){
Bullet[] bs=new Bullet[1];
bs[0]=new Bullet(x+50,y-20);
return bs;
}
else if(World.score<18){
Bullet[] bs=new Bullet[2];
bs[0]=new Bullet(x+43,y-20);
bs[1]=new Bullet(x+96,y-20);
return bs;
}
else if(World.score<28){
Bullet[] bs=new Bullet[2];
bs[0]=new Bullet(x+10,y-20);
bs[1]=new Bullet(x+66,y-20);
return bs;
}
else if(World.score<32){
Bullet[] bs=new Bullet[2];
bs[0]=new Bullet(x+50,y-20);
bs[1]=new Bullet(x+83,y-20);
return bs;
}
else if(World.score<42){
Bullet[] bs=new Bullet[2];
bs[0]=new Bullet(x+30,y-40);
bs[1]=new Bullet(x+63,y-40);
return bs;
}
else if(World.score<46){
Bullet[] bs=new Bullet[3];
bs[0]=new Bullet(x+40,y-40);
bs[1]=new Bullet(x+100,y-40);
bs[2]=new Bullet(x+70, y-40);
return bs;
}
else {
Bullet[] bs=new Bullet[3];
bs[0]=new Bullet(x+20,y-40);
bs[1]=new Bullet(x+80,y-40);
bs[2]=new Bullet(x+50,y-50);
return bs;
}
// int xStep=this.width/4;
// int yStep=20;//子弹距离英雄机的长度
// if(doubleFire>0) {
// Bullet[] bs=new Bullet[3];
// bs[0]=new Bullet(x+xStep,y-yStep);
// bs[1]=new Bullet(x+2*xStep,y-yStep);
// bs[2]=new Bullet(x+3*xStep,y-yStep);
// doubleFire-=2;
// return bs;
// }else {//单倍火力
// Bullet[] bs=new Bullet[2];
// bs[0]=new Bullet(x+xStep,this.y-yStep);
// bs[1]=new Bullet(x+3*xStep,this.y-yStep);
// return bs;
// }
}
//英雄机增命
public void addLife() {
life++;
}
public int getLife() {
return life;
}
//增加火力值
public void addDoubleFire() {
doubleFire+=40;//火力值增加40
}
public void clearDoubleFire() {
doubleFire=0;//火力值归零
}
public int getFire() {
return doubleFire;
}
public void subtaractLife() {
life--;
}
}
英雄机发射子弹 Bullets()
package cn.tedu.shoot;
import java.awt.image.BufferedImage;
public class Bullet extends FlyingObject{
public Bullet(float x,float y){
super(8,20,x,y);
}
/*子弹的移动*/
public void step() {
y-=2;
}
public BufferedImage getImage() {
if(isLife()) {
if(World.score<14)
return Images.bullet[0];
else if(World.score<28)
return Images.bullet[1];
else if(World.score<42)
return Images.bullet[2];
else return Images.bullet[3];
}else if(isDead()) {
state=REMOVE;
}
return null;
}
public boolean outOfBounds() {
return this.y
背景天空 Sky()
package cn.tedu.shoot;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
public class Sky extends FlyingObject{
private int speed;
private int y1;//第二张图片的y坐标
public Sky(){
super(World.WIDTH,World.HEIGHT,0,0);
y1=-World.HEIGHT;
speed=1;
}
/*天空的移动*/
public void step() {
y+=speed;
y1+=speed;
if(y>World.HEIGHT) {
y=-World.HEIGHT;
}
if(y1>World.HEIGHT) {
y1=-World.HEIGHT;
}
}
public BufferedImage getImage() {
return Images.background;
}
public void paintObject(Graphics g) {
g.drawImage(this.getImage(),(int)this.x,(int)this.y,null);
g.drawImage(this.getImage(),(int)this.x,(int)this.y1,null);
}
}
Boss类
package cn.tedu.shoot;
import java.awt.image.BufferedImage;
import java.util.Random;
public class TheBoss extends FlyingObject{
private int speed;
public TheBoss(){
super(300,200,40);
x=250;
y=20;
//speed=2;
}
/*大敌机的移动*/
float num=250;
float num1=20;
public void step() {
if(x<450&&num!=450) {
x++;
num++;
}else if(num==450&&x>50) {
x--;
}else num=x;
if(y<100&&num1!=100) {
y++;
num1++;
}else if(num1==100&&y>20) {
y--;
}else num1=y;
}
int index=1;
public BufferedImage getImage() {
if(isLife()) {
return Images.boss;
}else if(isDead()) {
BufferedImage img= Images.bigairplanes[index++];
if(index==Images.bigairplanes.length) {
state=REMOVE;
}
return img;
}
return null;
}
public BossBullet[] shoot1() {
BossBullet[] bs=new BossBullet[4];
bs[0]=new BossBullet(x+50,y+180,x);
bs[1]=new BossBullet(x+116,y+180,x);
bs[2]=new BossBullet(x+172,y+180,x);
bs[3]=new BossBullet(x+250,y+180,x);
return bs;
}
}
Boss子弹的移动 BossBullets()
package cn.tedu.shoot;
import java.awt.image.BufferedImage;
public class BossBullet extends FlyingObject{
public float heroX;
public float bulletX;
public static int n=0;
public BossBullet(float x,float y,float num){
super(8,20,x,y); //
this.heroX=num;
this.bulletX=x;
}
/*子弹的移动*/
public void step() {
if(n<400000) { //n控制子弹的发射形态
if(bulletX==heroX+50) { // hreoX飞机的x坐标,bulletX子弹的x坐标
y+=2;
x+=0.5; //四种子弹的轨迹
}else if(bulletX==heroX+116){
y+=2;
x+=0.5;
}else if(bulletX==heroX+172) {
y+=2;
x-=0.5;
}else {
y+=2;
x-=0.5;
}
n++;
}else if(n<800000) {
y+=3;
n++;
}else if(n<1200000) {
if(bulletX==heroX+50) {
y+=2;
x-=0.5;
}else if(bulletX==heroX+116){
y+=2;
x-=0.5;
}else if(bulletX==heroX+172) {
y+=2;
x+=0.5;
}else {
y+=2;
x+=0.5;
}
n++;
}else n=0;
}
public BufferedImage getImage() {
if(isLife()) {
return Images.Bossbullet;
}else if(isDead()) {
state=REMOVE;
}
return null;
}
public boolean outOfBounds() {
// return this.y>this.height;
return false;
}
}
背景音乐类 Music()
package cn.tedu.shoot;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import javazoom.jl.decoder.JavaLayerException;
import javazoom.jl.player.Player;
public class Music extends Thread {
public void run() {
try {
FileInputStream fil1 =
new FileInputStream("src/music/pirate.mp3");
BufferedInputStream bis1 =
new BufferedInputStream(fil1);
Player p = new Player(bis1);
p.play();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (JavaLayerException e) {
e.printStackTrace();
}
}
}
获得奖励时的背景音效 AwardMusic()
package cn.tedu.shoot;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import javazoom.jl.decoder.JavaLayerException;
import javazoom.jl.player.Player;
public class AwardMusic extends Thread{
public void run() {
try {
FileInputStream fil1 =
new FileInputStream("./src/music/award.mp3");
BufferedInputStream bis1 =
new BufferedInputStream(fil1);
Player p = new Player(bis1);
p.play();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}
爆炸音效 ExplodeMusic()
package cn.tedu.shoot;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import javazoom.jl.decoder.JavaLayerException;
import javazoom.jl.player.Player;
public class ExplodeMusic extends Thread{
public void run() {
try {
FileInputStream fil1 =
new FileInputStream("src/music/explode.mp3");
BufferedInputStream bis1 =
new BufferedInputStream(fil1);
Player p = new Player(bis1);
p.play();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (JavaLayerException e) {
e.printStackTrace();
}
}
}
子弹射击音效 ShootMusic()
package cn.tedu.shoot;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import javazoom.jl.decoder.JavaLayerException;
import javazoom.jl.player.Player;
public class Shootmusic extends Thread{
public void run() {
try {
FileInputStream fil1 =
new FileInputStream("./src/music/bullet.mp3");
BufferedInputStream bis1 =
new BufferedInputStream(fil1);
Player p = new Player(bis1);
p.play();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (JavaLayerException e) {
e.printStackTrace();
}
}
}
数据库 UserDao()
package cn.tedu.shoot;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class UserDao {
//定义数据库驱动
public static String driver="com.mysql.jdbc.Driver";
//定义url
//连接远程mysql 配置的数据源jdbc.url
public static String url="jdbc:mysql://localhost:3306/shoot";
public static String user="root";
static String password="123456";
//定义连接对象
public static Connection con;
//定义传输对象
public static Statement statement;
public static void DBConnection() throws Exception{
//注册数据库
Class.forName(driver);
//获取数据库连接
con=DriverManager.getConnection(url,user,password);
//定义传输器对象
statement=con.createStatement();
}
public static void save(String name,int score) throws Exception{
try {
DBConnection();
String sql="insert into score(username,score) values('"+name+"',"+score+")";
statement.executeUpdate(sql);
} catch(Exception e) {
e.printStackTrace();
}finally {
con.close();
}
}
public static String[] getScoreAndUsername() throws Exception {
ResultSet rs = null;
String result[]=new String[100];
try {
DBConnection();
String sql= "select username,score from score order by score desc";
rs=statement.executeQuery(sql);
for(int i=0;i
本游戏是在老师的指导下完成的,自己和同学进行的增加功能,还存在着很多的问题。
欢迎评论区留言。