提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
前言
提示:这里可以添加本文要记录的大概内容:
我参考过B站尚学堂老师的飞机大战的课程,根据老师的上课,总结一下
提示:以下是本篇文章正文内容,下面案例可供参考
一、基本介绍
要实现飞机大战,需要哪些功能要实现呢?
1.窗口的绘制
2.图片和字体的绘制
3.背景图片的循环移动
4.鼠标控制飞机的移动位置
5.子弹的批量生成
6.敌机在随机位置的批量生成
7.子弹和飞机的碰撞检测
8.爆炸效果动画的实现
9.计分面板的实现
10.游戏的暂停功能
11.游戏的通关设置
12.血条绘制
13.双缓存解决画面闪动
14.集合的使用和优化
二、效果图
三、源码分析
1.首先绘制游戏的主类gamewin
代码如下(示例):
package com.game;
import com.game.obj.*;
import com.game.utils.gameutils;
import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
public class gamewin extends JFrame {
//游戏状态 0未开始 1进行中 2暂停 3游戏通过 4游戏失败
public static int state=0;//游戏的默认状态
//计分数
public static int score=0;
Image offSreenimage=null;
int width=600;
int height=600;
//游戏的重绘次数
int count=1;
//敌机出现的数量
int enemyCount=0;
//背景图图像的移动
Bgobj bgobj=new Bgobj(gameutils.bgimg,0,-400,2);
//我方飞机的对象
public Planeobj planeobj =new Planeobj(gameutils.planeimg,290,550,20,30,0,this);
//boss对象
public Bossobj bossobj =null;
public void launch(){
//设置窗口是否可见
this.setVisible(true);
//设置窗口大小
this.setSize(width,height);
//设置窗口位置
this.setLocationRelativeTo(null);
//设置窗口标题
this.setTitle("飞机大战");
gameutils.gameobjList.add(bgobj);
gameutils.gameobjList.add(planeobj);
//鼠标点击
this.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
//在未开始并且点击鼠标左键,
if(e.getButton()==1&&state==0){
state=1;
repaint();
}
}
});
//游戏的暂停功能
this.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
//按下空格键,空格键的代码为32
if(e.getKeyCode() == 32){
switch (state){
case 1:
state=2;
break;
case 2:
state=1;
break;
default:
}
}
}
});
while(true){
if(state==1){
create();
repaint();
}
try {
Thread.sleep(25);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
@Override
public void paint(Graphics g) {
if(offSreenimage==null){
offSreenimage=createImage(width,height);
}
//获取offScrenimage的画笔对象
Graphics gimage=offSreenimage.getGraphics();
//填充一个宽六百,高六百的区域
gimage.fillRect(0,0,width,height);
//游戏未开始
if(state==0){
gimage.drawImage(gameutils.bgimg,0,0,null);
gimage.drawImage(gameutils.bossimg,200,100,null);
gimage.drawImage(gameutils.explodeimg,270,370,null);
gameutils.drawWord(gimage,"点击开始游戏",Color.yellow,40,180,300);
// gimage.setColor(Color.yellow);
// gimage.setFont(new Font("仿宋",Font.BOLD,40));
// gimage.drawString("点击开始游戏",180,300);
}
//游戏开始
if(state==1){
gameutils.gameobjList.addAll(gameutils.explodeobjList);
for(int i=0;i<gameutils.gameobjList.size();i++){
gameutils.gameobjList.get(i).paintself(gimage);
}
gameutils.gameobjList.removeAll(gameutils.removeobjList);
}
//游戏失败
if(state==3) {
gimage.drawImage(gameutils.explodeimg, planeobj.getX() - 35, planeobj.getY() - 50, null);
gameutils.drawWord(gimage,"GAME OVER",Color.red,40,180,300);
// gimage.setColor(Color.red);
// gimage.setFont(new Font("仿宋", Font.BOLD, 40));
// gimage.drawString("GAME OVER", 180, 300);
}
//游戏通关
if(state==4) {
gimage.drawImage(gameutils.explodeimg, bossobj.getX() + 35, bossobj.getY() + 50, null);
gameutils.drawWord(gimage, " Game Win", Color.red, 40, 180, 300);
}
gameutils.drawWord(gimage,score+"分",Color.green,40,30,100);
//把新图片一次性绘制到主窗口中
g.drawImage(offSreenimage,0,0,null);
count++;
}
//创建方法用来批量生成子弹和敌机
void create(){
//我方子弹 除以10是为了控制子弹的速率
if(count%10==0){
gameutils.shellobjList.add(new Shellobj(gameutils.shellimg,planeobj.getX()+4,planeobj.getY()-16,14,29,5,this));
gameutils.gameobjList.add(gameutils.shellobjList.get(gameutils.shellobjList.size()-1));
}
//敌方战机
if(count%15==0){
gameutils.enemyobjList.add(new Enemyobj(gameutils.enemyimg,(int)(Math.random()*12)*50,0,50,50,5,this));
gameutils.gameobjList.add(gameutils.enemyobjList.get(gameutils.enemyobjList.size()-1));
enemyCount++;
}
//敌方boss子弹
//直到boss出现的时候才会生成子弹
if(count%15==0 && bossobj !=null){
gameutils.bulletobjList.add(new Bulletobj(gameutils.bulletimg,bossobj.getX()+75,bossobj.getY()+80,15,25,5,this));
gameutils.gameobjList.add(gameutils.bulletobjList.get(gameutils.bulletobjList.size()-1));
}
if( enemyCount>30 && bossobj == null ){
bossobj=new Bossobj(gameutils.bossimg,250,20,155,100,5,this);
gameutils.gameobjList.add(bossobj);
}
}
public static void main(String[] args) {
gamewin Gamewin=new gamewin();
Gamewin.launch();
}
}
2.绘制工具类gameutils
一些图片,比如子弹图片、敌方boss背景图片之类的需要绘制在gameutils中:
package com.game.utils;
import com.game.obj.*;
import java.awt.*;
import java.util.ArrayList;
import java.util.List;
public class gameutils {
//背景图片
public static Image bgimg =Toolkit.getDefaultToolkit().getImage("image/背景.jpeg");
//boss图片
public static Image bossimg =Toolkit.getDefaultToolkit().getImage("image/boss.png");
//爆炸图片
public static Image explodeimg =Toolkit.getDefaultToolkit().getImage("image/explode/e11.gif");
//我方飞机图片
public static Image planeimg =Toolkit.getDefaultToolkit().getImage("image/plane.png");
//我方子弹图片
public static Image shellimg =Toolkit.getDefaultToolkit().getImage("image/shell.png");
//敌方boss子弹图片
public static Image bulletimg =Toolkit.getDefaultToolkit().getImage("image/boss子弹.png");
//敌方飞机的图片
public static Image enemyimg =Toolkit.getDefaultToolkit().getImage("image/enemy.png");
//要删除元素的集合
public static List<Gameobj> removeobjList =new ArrayList<>();
//所有物体游戏的集合
public static List<Gameobj> gameobjList =new ArrayList<>();
//我方子弹的集合
public static List<Shellobj> shellobjList =new ArrayList<>();
//敌方飞机的集合
public static List<Enemyobj> enemyobjList =new ArrayList<>();
//敌方boss方子弹的集合
public static List<Bulletobj> bulletobjList =new ArrayList<>();
//爆炸图片的集合
public static List<Explodeobj> explodeobjList =new ArrayList<>();
//绘制字符串的工具类
public static void drawWord(Graphics gImage,String str,Color color,int size,int x,int y){
gImage.setColor(color);
gImage.setFont(new Font("仿宋",Font.BOLD,size));
gImage.drawString(str,x,y);
}
}
3.新建obj文件夹,绘制游戏物体的父类Gameobj
package com.game.obj;
import com.game.gamewin;
import java.awt.*;
//游戏类父类的编写
public class Gameobj {
Image img;
int x;
int y;
int width;
int height;
double speed;//移动速度
gamewin frame;//窗口的引用
public Image getImg() {
return img;
}
public void setImg(Image img) {
this.img = img;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public Gameobj(int x, int y) {
this.x = x;
this.y = y;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public int getWidth() {
return width;
}
public void setWidth(int width) {
this.width = width;
}
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
public double getSpeed() {
return speed;
}
public void setSpeed(double speed) {
this.speed = speed;
}
public gamewin getFrame() {
return frame;
}
public void setFrame(gamewin frame) {
this.frame = frame;
}
//有参构造和无参构造函数
public Gameobj() {
}
public Gameobj(Image img, int x, int y, double speed) {
this.img = img;
this.x = x;
this.y = y;
this.speed = speed;
}
public Gameobj(Image img, int x, int y, int width, int height, double speed, gamewin frame) {
this.img = img;
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.speed = speed;
this.frame = frame;
}
//绘制自身
public void paintself(Graphics gImage){
gImage.drawImage(img,x,y,null);
}
//绘制矩形的方法用来碰撞检测
public Rectangle getrect(){
return new Rectangle(x,y,width,height);
}
}
绘制Bgobj,实现背景的移动和循环出现
package com.game.obj;
import com.game.gamewin;
import java.awt.*;
//游戏类父类的编写
public class Gameobj {
Image img;
int x;
int y;
int width;
int height;
double speed;//移动速度
gamewin frame;//窗口的引用
public Image getImg() {
return img;
}
public void setImg(Image img) {
this.img = img;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public Gameobj(int x, int y) {
this.x = x;
this.y = y;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public int getWidth() {
return width;
}
public void setWidth(int width) {
this.width = width;
}
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
public double getSpeed() {
return speed;
}
public void setSpeed(double speed) {
this.speed = speed;
}
public gamewin getFrame() {
return frame;
}
public void setFrame(gamewin frame) {
this.frame = frame;
}
//有参构造和无参构造函数
public Gameobj() {
}
public Gameobj(Image img, int x, int y, double speed) {
this.img = img;
this.x = x;
this.y = y;
this.speed = speed;
}
public Gameobj(Image img, int x, int y, int width, int height, double speed, gamewin frame) {
this.img = img;
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.speed = speed;
this.frame = frame;
}
//绘制自身
public void paintself(Graphics gImage){
gImage.drawImage(img,x,y,null);
}
//绘制矩形的方法用来碰撞检测
public Rectangle getrect(){
return new Rectangle(x,y,width,height);
}
}
绘制我方战斗机类Planeobj
package com.game.obj;
import com.game.gamewin;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
public class Planeobj extends Gameobj {
@Override
public Image getImg() {
return super.getImg();
}
public Planeobj() {
super();
}
public Planeobj(Image img, int x, int y, int width, int height, double speed, gamewin frame) {
super(img, x, y, width, height, speed, frame);
//飞机随着鼠标的移动而移动
this.frame.addMouseMotionListener(new MouseAdapter() {
@Override
public void mouseMoved(MouseEvent e) {
Planeobj.super.x=e.getX()-11;
Planeobj.super.y=e.getY()-16;
}
});
}
@Override
public void paintself(Graphics gImage) {
super.paintself(gImage);
//y-=speed;
if(this.frame.bossobj !=null && this.getrect().intersects(this.frame.bossobj.getrect())){
gamewin.state=3;
}
}
@Override
public Rectangle getrect() {
return super.getrect();
}
}
绘制战斗机子弹类Shellobj
package com.game.obj;
import com.game.gamewin;
import com.game.utils.gameutils;
import java.awt.*;
public class Shellobj extends Gameobj{
@Override
public Image getImg() {
return super.getImg();
}
public Shellobj() {
super();
}
public Shellobj(Image img, int x, int y, int width, int height, double speed, gamewin frame) {
super(img, x, y, width, height, speed, frame);
}
@Override
public void paintself(Graphics gImage) {
super.paintself(gImage);
y-=speed;
// 我方子弹的越界消失,条件y<0时,,改变后的坐标为-100,100
if(y<0){
this.x=-100;
this.y=100;
gameutils.removeobjList.add(this);
}
}
@Override
public Rectangle getrect() {
return super.getrect();
}
}
绘制敌方战斗机类Enemyobj
package com.game.obj;
import com.game.gamewin;
import com.game.utils.gameutils;
import java.awt.*;
public class Enemyobj extends Gameobj{
public Enemyobj() {
super();
}
public Enemyobj(Image img, int x, int y, int width, int height, double speed, gamewin frame) {
super(img, x, y, width, height, speed, frame);
}
@Override
public void paintself(Graphics gImage) {
super.paintself(gImage);
y+=speed;
//敌我飞机的碰撞检测
if(this.getrect().intersects(this.frame.planeobj.getrect())){
gamewin.state=3;
}
//敌方飞机超出窗口,判断条件y>600,调整坐标为-200,200
if(y>600){
this.x=-200;
this.y=200;
gameutils.removeobjList.add(this);
}
//子弹和敌方飞机碰撞的检测,
for (Shellobj shellobj: gameutils.shellobjList)
{if(this.getrect().intersects(shellobj.getrect())){
//子弹击中敌方飞机爆炸图
Explodeobj explodeobj=new Explodeobj(x,y);
gameutils.explodeobjList.add(explodeobj);
gameutils.removeobjList.add(explodeobj);
// shellobj.setX(-100);
// shellobj.setY(100);
//改变当前敌机的坐标
this.x=-200;
this.y=200;
gameutils.removeobjList.add(shellobj);
gameutils.removeobjList.add(this);
//加分数
gamewin.score++;
}
}
}
@Override
public Rectangle getrect() {
return super.getrect();
}
}
绘制敌方Boss类Bossobj
package com.game.obj;
import com.game.gamewin;
import com.game.utils.gameutils;
import java.awt.*;
public class Bossobj extends Gameobj{
//定义敌方boss的生命值
int life=30;
public Bossobj(Image img, int x, int y, int width, int height, double speed, gamewin frame) {
super(img, x, y, width, height, speed, frame);
}
@Override
public void paintself(Graphics gImage) {
super.paintself(gImage);
//控制敌方boss在整个窗口中
if(x>550 || x<0){
speed=-speed;
}
x+=speed;
for(Shellobj shellobj: gameutils.shellobjList){
//检测子弹和敌方boss碰撞
if(this.getrect().intersects(shellobj.getrect())){
shellobj.setX(-100);
shellobj.setY(100);
gameutils.removeobjList.add(shellobj);
life--;
}
if(life<=0){
gamewin.state=4;//表明游戏通关
}
//血条的白色背景
gImage.setColor(Color.WHITE);
gImage.fillRect(20,40,100,30);
//血条的绘制
gImage.setColor(Color.red);
gImage.fillRect(20,40,life*100/10,30);
//一个整数除以另一个整数,如果结果为小于一,它会算为0
// gImage.fillRect(20,40,life/10 *100,50);
}
}
@Override
public Rectangle getrect() {
return super.getrect();
}
}
绘制敌方boss子弹类Bulletobj
package com.game.obj;
import com.game.gamewin;
import com.game.utils.gameutils;
import java.awt.*;
public class Bulletobj extends Gameobj{
public Bulletobj(Image img, int x, int y, int width, int height, double speed, gamewin frame) {
super(img, x, y, width, height, speed, frame);
}
@Override
public void paintself(Graphics gImage) {
super.paintself(gImage);
y+=speed;
//敌方boss子弹超出窗口,判断为y>600,调整坐标为-300,300
if(y>600){
this.x=-300;
this.y=300;
gameutils.removeobjList.add(this);
}
//敌方boss子弹和我方飞机的碰撞检测
if(this.getrect().intersects(this.frame.planeobj.getrect())){
gamewin.state=3;
}
}
@Override
public Rectangle getrect() {
return super.getrect();
}
}
绘制爆炸类Explodeobj
package com.game.obj;
import java.awt.*;
public class Explodeobj extends Gameobj{
static Image[] pic=new Image[16];
//爆炸图只显示一次
int explodeCount=0;
static {
for (int i=0;i<pic.length;i++){
pic[i]=Toolkit.getDefaultToolkit().getImage("image/explode/e"+(i+1)+".gif");
}
}
public Explodeobj(int x, int y) {
super(x, y);
}
@Override
public void paintself(Graphics gImage) {
if(explodeCount<16){
//绘制数组中的图片
img=pic[explodeCount];
super.paintself(gImage);
explodeCount++;
}
}
}
总结
希望以上内容能够对大家有所帮助,我也是根据B站课程一个个慢慢敲上去的,在过程中可能会有有多细节需要注意,无法达到理想效果,会大大降低大家的自信心,希望大家有任何问题,都可以咨询我噢,虽然我很菜,但我一定尽我所能。加油(⊙o⊙)噢噢!!!
好嘞,资源在这噢
链接: java飞机大战源码
提取码:1234