1、创建窗口
package com.txt;
import javax.swing.*;
// 创建游戏窗口
public class GameWin extends JFrame {
//启动的方法
public void launch(){
this.setSize(600,600);
this.setTitle("飞机大战");
//设置窗口位置
this.setLocationRelativeTo(null);
this.setVisible(true);
}
public static void main(String[] args) {
GameWin gameWin=new GameWin();
gameWin.launch();
}
}
2、设置背景图片
将背景图片的文件夹给到项目第二层
创建一个工具类的包 创建工具类 如下
package com.txt.utils;
import java.awt.*;
// 工具类
public class GameUtils {
// 获取背景图片
public static Image bgImg=Toolkit.getDefaultToolkit().getImage("imgs/space.jpg");
}
回到GameWin 重写画笔 paint方法
package com.txt;
import com.txt.utils.GameUtils;
import javax.swing.*;
import java.awt.*;
// 创建游戏窗口
public class GameWin extends JFrame {
//启动的方法
public void launch(){
this.setSize(600,600);
this.setTitle("飞机大战");
//设置窗口位置
this.setLocationRelativeTo(null);
this.setVisible(true);
}
@Override
public void paint(Graphics g) {
g.drawImage(GameUtils.bgImg,0,0,this);
}
public static void main(String[] args) {
GameWin gameWin=new GameWin();
gameWin.launch();
}
}
3、游戏启动页面
先在启动类上面加上 游戏状态的属性
//飞机大战的状态 0 未开始 1 游戏中 2 暂停 3 失败 4成功
public static int state = 0 ;
然后在工具类中加上 爆炸图片和飞机图片
package com.txt.utils;
import java.awt.*;
// 工具类
public class GameUtils {
// 获取背景图片
public static Image bgImg=Toolkit.getDefaultToolkit().getImage("imgs/space.jpg");
// 获取敌方 boss
public static Image bossImg=Toolkit.getDefaultToolkit().getImage("imgs/boss.jpg");
// 获取爆炸特效
public static Image explodeImg=Toolkit.getDefaultToolkit().getImage("imgs/explode/e6.jpg");
}
添加开始的图片和文字 在paint方法中
package com.txt;
import com.txt.utils.GameUtils;
import javax.swing.*;
import java.awt.*;
// 创建游戏窗口
public class GameWin extends JFrame {
//启动的方法
public void launch(){
this.setSize(600,600);
this.setTitle("飞机大战");
//设置窗口位置
this.setLocationRelativeTo(null);
this.setVisible(true);
}
// 增加背景图片的绘制
@Override
public void paint(Graphics g) {
//第一步的笔记 :g.drawImage(GameUtils.bgImg,0,0,this);
// 当游戏状态为 0 时 游戏未开始 添加启动界面 有敌方boss 有爆炸图片 背景图片
if (state==0){
g.drawImage(GameUtils.bgImg,0,0,this);
g.drawImage(GameUtils.bossImg,250,120,null);
g.drawImage(GameUtils.explodeImg,270,350,this);
//添加文字和字体颜色
//设置画笔颜色
g.setColor(Color.ORANGE);
//设置字体的格式 加粗与否 大小
g.setFont(new Font("黑体",Font.BOLD,40));
//写字
g.drawString("点击开始游戏",180 ,300);
}
}
public static void main(String[] args) {
GameWin gameWin=new GameWin();
gameWin.launch();
}
//飞机大战的状态 0 未开始 1 游戏中 2 暂停 3 失败 4成功
public static int state = 0 ;
}
4、启动页面
鼠标点击进入游戏状态 状态码变为1 启动文字消失
在launch方法中添加鼠标点击事件
// 添加鼠标点击事件 点击之后游戏状态改变
this.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
//如果鼠标点击之后 我们更改游戏状态 并使用新的重画方法
if (e.getButton() == 1 && state == 0){
state = 1;
repaint();
}
}
});
在paint方法中添加状态为1(游戏中) 时候的判断代码
//游戏中 状态为1
if (state == 1){
g.drawImage(GameUtils.bgImg,0,0,this);
g.drawImage(GameUtils.bossImg,250,120,null);
g.drawImage(GameUtils.explodeImg,270,350,this);
//添加文字和字体颜色
//设置画笔颜色
g.setColor(Color.ORANGE);
//设置字体的格式 加粗与否 大小
g.setFont(new Font("黑体",Font.BOLD,40));
//写字
g.drawString("开始游戏",220 ,300);
}
5、编写游戏物体的标准类 也就是父类
新建包 新建一个类 有参构造可以多定义几个
package com.txt.obj;
import com.txt.GameWin;
import java.awt.*;
public class GameObj {
// 物体的图片 物体的位置 物体的宽高 物体的运动速度 窗口的引用
Image img;
int x;
int y;
int width;
int height;
double speed;
GameWin frame;
//提供get set方法 有参构造无参构造
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 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 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 void paintSelf(Graphics gImage){
gImage.drawImage(img,x,y,null);
}
// 编写自己矩形的方法 用以碰撞检测
public Rectangle getRec(){
return new Rectangle(x,y,width,height);
}
}
6、背景的移动 一个照片上下滚动
新建实体类 在obj的包下
package com.txt.obj;
import com.txt.GameWin;
import java.awt.*;
public class BgObj extends GameObj{
// alt + ins 选择override 选择需要的构造方法个 paintself方法
public BgObj() {
super();
}
public BgObj(Image img, int x, int y, double speed) {
super(img, x, y, speed);
}
public BgObj(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);
}
}
然后在窗口类中获取背景类的对象
将代码bgobj的画自己的方法放到状态为 1 的if里面
在背景类的方法中让paintself使得自己速度y变化
在窗口启动类的launch方法中加上 死循环 使其一直在 每隔多少毫秒就 做一段重画方法
7、使用双缓存解决屏幕闪烁
启动类添加一个属性
paint方法中添加对象
8、背景图片的循环出现
在paintself中添加
if判断
9、我方战斗机的鼠标控制
创建我方战斗机
package com.txt.obj;
import com.txt.GameWin;
import java.awt.*;
public class PlaneObj extends GameObj{
//重写方法
public PlaneObj() {
super();
}
public PlaneObj(Image img, int x, int y, double speed) {
super(img, x, y, speed);
}
public PlaneObj(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);
}
}
工具类中画出我方战斗机图片
主页面中创建飞机对象属性
状态为1 就是启动游戏时画出 我方敌机
实现鼠标对飞机的控制
在鼠标最长的构造方法中添加鼠标控制事件
10、添加第一颗子d 让子d飞一会
添加子d类ShellObj
重写 画的方法 检测碰撞的方法 构造方法
package com.txt.obj;
import com.txt.GameWin;
import java.awt.*;
public class ShellObj extends GameObj{
public ShellObj() {
super();
}
public ShellObj(Image img, int x, int y, double speed) {
super(img, x, y, speed);
}
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 Image getImg() {
return super.getImg();
}
@Override
public void paintSelf(Graphics gImage) {
super.paintSelf(gImage);
}
@Override
public Rectangle getRec() {
return super.getRec();
}
}
工具类中获取我方子d的图片
public static Image shellImg=Toolkit.getDefaultToolkit().getImage("imgs/shell");
窗口中创建子d的属性
ShellObj shellObj=new ShellObj(GameUtils.shellImg,planeObj.getX()+3,planeObj.getY()-16,14,29,5,this);
在状态等于1 的判断中添加画自己的方法
在子d的paintself方法中实现子d的移动
12、批量添加子d
工具类添加我方子d集合
//所有游戏角色的集合
// 子d集合
public static List shellObjList = new ArrayList<>();
// 所有的父集合
public static List gameObjList =new ArrayList<>();
回到窗口类中创建一个方法 批量创建子d和敌机
public void createObj(){
GameUtils.shellObjList.add(new ShellObj(GameUtils.shellImg,planeObj.getX()+3,planeObj.getY()-16,14,29,5,this));
//将子dlist里面的元素放到 gameobjlist中
GameUtils.gameObjList.add(GameUtils.shellObjList.get(GameUtils.shellObjList.size()-1));
}
在luanch的方法循环里面使用方法 状态为1 时
在paint方法中state判断为1的if中
删除源代码 使用for循环生成子d 飞机 背景 因为list包含着三个对象
//游戏中 状态为1
if (state == 1){
//bgObj.paintSelf(gImage);
//planeObj.paintSelf(gImage);
//shellObj.paintSelf(gImage);
//遍历 gameObjList
for (int i = 0; i < GameUtils.gameObjList.size(); i++) {
GameUtils.gameObjList.get(i).paintSelf(gImage);
}
}
在启动方法中将背景和飞机 添加到gameObjList集合中去
// 第十一步 将背景图片和飞机类加入集合gameobjlist里面
GameUtils.gameObjList.add(bgObj);
GameUtils.gameObjList.add(planeObj);
子d太快 需要控制子d子d速度 需要一个变量记录重绘次数
窗口类定义一个属性 int count =0;用以记录
paint使用一次记录一次
在创建飞机的方法的中只有 count 除以15等于0 才在添加一次对象到集合中
//批量产生敌机 放在while下循环下
public void createObj(){
if (count%15==0){
GameUtils.shellObjList.add(new ShellObj(GameUtils.shellImg,planeObj.getX()+3,planeObj.getY()-16,14,29,5,this));
//将子dlist里面的元素放到 gameobjlist中
GameUtils.gameObjList.add(GameUtils.shellObjList.get(GameUtils.shellObjList.size()-1));
//将之前绘制妃子背景的代码删掉
//将需要绘制的物体添加到objlist中
}
}
12、敌方飞机批量添加
创建敌方飞机类 重写需要的方法
package com.txt.obj;
import com.txt.GameWin;
import java.awt.*;
public class EnemyObj extends GameObj {
public EnemyObj() {
super();
}
public EnemyObj(Image img, int x, int y, double speed) {
super(img, x, y, speed);
}
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 Image getImg() {
return super.getImg();
}
@Override
public void paintSelf(Graphics gImage) {
super.paintSelf(gImage);
}
@Override
public Rectangle getRec() {
return super.getRec();
}
}
工具类中创建敌机集合 敌机图片
public static Image enemyImg=Toolkit.getDefaultToolkit().getImage("imgs/enemy.png");
// 敌机集合
public static List enemyObjList =new ArrayList<>();
回到窗口类
创建对象方法中 创建敌机
public void createObj(){
// 子d生成方法
if (count%15==0){
GameUtils.shellObjList.add(new ShellObj(GameUtils.shellImg,planeObj.getX()+3,planeObj.getY()-16,14,29,5,this));
//将子dlist里面的元素放到 gameobjlist中
GameUtils.gameObjList.add(GameUtils.shellObjList.get(GameUtils.shellObjList.size()-1));
//将之前绘制妃子背景的代码删掉
//将需要绘制的物体添加到objlist中
}
// 敌机生成
if (count%15==0){
GameUtils.enemyObjList.add(new EnemyObj(GameUtils.enemyImg, (int) (Math.random()*12)*15,0,49,36,5,this));
//将子dlist里面的元素放到 gameobjlist中
GameUtils.gameObjList.add(GameUtils.enemyObjList.get(GameUtils.enemyObjList.size()-1));
}
}
没有生成敌机 因为y没改变
重写敌机的paintself方法
13、我方飞机和敌方飞机的检测
图中都为一个矩形 检测矩形的碰撞
在敌机的类中绘画自己的方法中添加遍历 检测每个子d是否跟自己碰撞
14、碰撞后的处理 敌机加子d消失
定义一个removeList 在gameUtils里面
// 将要删除的元素
public static List removeList =new ArrayList<>();
在敌机的paint方法中添加代码 将碰撞了的元素放到窗口外面去
在主窗口的方法中在下次绘制之前在gameObj之前删除
15、我方飞机和敌方飞机的检测
在敌机的绘画自己的帆帆中
检测敌机和子d的for循环下
//敌我方飞机碰撞检测 if (this.getRec().intersects(this.frame.planeObj.getRec())){ GameWin.state = 3; }
主窗口的paint方法中做状态判断
// 游戏结束
if (state==3){
gImage.drawImage(GameUtils.explodeImg,planeObj.getX()-35,planeObj.getY()-50,this);
gImage.setColor(Color.red);
gImage.setFont(new Font("黑体",Font.BOLD,50));
gImage.drawString("游戏结束",220,300);
}
16、敌方boss的移动和添加
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)