原谅帽大作战
制作人:崔帅宽
时间:2020.11.10
一、如何创建原谅帽大作战的窗体:
(1)先创建一个原谅帽的类包,然后创建:游戏客户端GameClinet类。
/*
游戏客户端
*/
public class GameClinet extends Frame {
// 常量 定义背景图片的路径
public static final String BG_PATH = "Javaylm/images/bg.png";
//定义一个图片的静态变量
private static Image image;
//静态块,所有资源(图片、音频,视频)只需要加载一次
static{
image = CommonUtils.getImage(BG_PATH);
}
/**
* 游戏入口
* @param args
*/
public static void main(String[] args) {
GameClinet gameClinet = new GameClinet();
// 开始游戏
gameClinet.start();
}
/*
* 开始游戏
* */
public void start(){
System.out.println("游戏马上开始,请玩家做好准备");
//TODO 游戏业务
// 设置标题
this.setTitle("原谅帽大战");
//设置窗体的大小以及位置
this.setBounds(0,0,1100,700);
// 让窗体显示出来
this.setVisible(true);
System.out.println("Game Over!!!");
}
/*
* 画画,重写父类的paint方法
* Graphics 画笔类
* @param g 画笔
* */
@Override
public void paint(Graphics g) {
// 画背景图
g.drawImage(image,0,0,1100,700,this);
(2)其次在原谅帽的类包下,在创建一个Util包,在Util类包下创建:常用工具类CommonUtils类。
package ylm.Util;
import javax.swing.*;
import java.awt.*;
/*
* 常用工具类
* */
public class CommonUtils {
/**
* 读取图片资源, 转变为Java对象 Image
* @param imgPath 图片路径
* @return Image对象
*/
public static Image getImage(String imgPath) {
ImageIcon imageIcon = new ImageIcon(imgPath);
return imageIcon.getImage();
}
}
(3)在原谅帽的类包下,在创建一个thread包,在thread类包下创建:常用工具类RepaintThread类。
/*
定义一个重新绘制画面的线程 相当于 在招一个工人去车间工作
*/
public class RepaintThread implements Runnable{
// 游戏窗体
private GameClinet gameClinet;
// 通过构造器赋值
public RepaintThread(GameClinet gameClinet) {
this.gameClinet = gameClinet;
}
@Override
public void run() {
while (true){
// 每50毫秒 执行一次
try {
Thread.sleep(40);
// 重新绘制图像
gameClinet.repaint();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
二、如何将图片加载到窗体里:
第一步:发现类(对象)
在做游戏的同时,先找到它有那些对象:
1、人物-小丑(友方、敌方):Buffon
2、发射物-帽子: Missile
3、墙体 Wall
4、爆炸物 Explode
第二步:发现属性
小丑:宽、高,位置(x、y),移动速度
帽子:宽、高,位置(x、y),移动速度
墙体:宽、高,位置(x、y)
爆炸物:宽、高,位置(x、y)
第三步:发现方法
小丑:移动 move
'Left向左': x = x - this.speed;
'Right向右': x = x + this.speed;
'Down向下': y = y + this.speed;
'Up向上': y = y - this.speed;
'UR东北方向':x = x + this.speed;
y = y - this.speed;
'DR东南方向':x = x + this.speed;
y = y + this.speed;
'LD西南方向':X = x — this.speed;
y = y + this.speed;
'LU西北方向':x = x - this.speed;
y = y - this.speed;
攻击(发子弹)
人物撞边界
子弹:移动 move
子弹撞墙
子弹撞边界
墙体:
爆炸物:爆炸物消失
(1)人物–小丑:
创建一个实体类包:entity,包里放入实体类小丑类:Buffon。
小丑有自己的图片属性:宽、高,位置(x、y),移动速度等。
import ylm.Util.CommonUtils;
import java.awt.*;
/*
* 人物--小丑类
* */
public class Buffoon {
// 人物图片属性
public static Image buffoonImage = CommonUtils.getImage("Javaylm/images/body/s-left.png");
//人物--横坐标
private int x;
//人物--纵坐标
private int y;
// 图片--宽度
private int width;
// 图片--高度
private int height;
// 人物--速度
private int speed;
}
(2)发射物-帽子:
在实体类包entity:放入发射物-帽子类:Missile
package ylm.entity;
import ylm.Util.CommonUtils;
import java.awt.*;
/*
* 发射物--帽子
*/
public class Missile {
// 发射物图片属性
public static Image missileImage = CommonUtils.getImage("Javaylm/images/missile.png");
// 发射物--横坐标
private int x;
// 发射物--纵坐标
private int y;
// 图片--宽度
private int width;
// 图片--高度
private int height;
// 发射物--速度
private int speed;
}
(3)墙体:
在实体类包entity:放入墙体类:Wall
墙体有自己的图片属性:宽、高,位置(x、y)等。
package ylm.entity;
import ylm.Util.CommonUtils;
import java.awt.*;
/*
* 墙体
* */
public class Wall {
// 墙体图片属性
// 横向墙体
public static Image wallImage = CommonUtils.getImage("Javaylm/images/wall-h.png");
// 竖向墙体
public static Image wallImage1 = CommonUtils.getImage("Javaylm/images/wall-v.png");
// 墙体横坐标
private int x;
// 墙体纵坐标
private int y;
// 图片宽度
private int width;
// 图片高度
private int height;
}
(4)爆炸物:
在实体类包entity:放入爆炸物类:Explode
爆炸物同样也有自己的图片属性:宽、高,位置(x、y)等。
package ylm.entity;
import ylm.Util.CommonUtils;
import java.awt.*;
/*
* 爆炸物
* */
public class Explode {
// 爆炸物图片属性
public static Image explodeImage = CommonUtils.getImage("Javaylm/images/explode.png");
// 爆炸物横坐标
private int x;
// 爆炸物纵坐标
private int y;
// 爆炸物宽度
private int width;
// 爆炸物高度
private int height;
}
创建无参、带参构造、get、set方法操作:
// 无参构造
public Buffoon(){}
// 带参构造
public Buffoon(int x,int y,GameClinet gameClinet){
this.x = x;
this.y = y;
this.width = 50;
this.height = 50;
this.speed = 5;
this.gameClinet = gameClinet;
}
// 生成get set方法
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 int getSpeed() {
return speed;
}
public void setSpeed(int speed) {
this.speed = speed;
}
人物移动:move
/*
* 人物移动
*/
public void move(String dir){
// 向上 北
if ("UP".equals(dir)){
this.y = this.y - this.speed;
}
// 向右 东
if ("RIGHT".equals(dir)){
this.x = this.x + this.speed;
}
// 向下 南
if ("DOWN".equals(dir)){
this.y = this.y + this.speed;
}
// 向左 西
if ("LEFT".equals(dir)){
this.x = this.x - this.speed;
}
// 东南方向
if ("DR".equals(dir)){
this.x += this.speed;
this.y += this.speed;
}
// 东北方向
if ("UR".equals(dir)){
this.x += this.speed;
this.y -= this.speed;
}
// 西南方向
if ("LD".equals(dir)){
this.x -= this.speed;
this.y += this.speed;
}
// 西北方向
if ("UL".equals(dir)){
this.x -= this.speed;
this.y -= this.speed;
}
三、将实体类里的人物依次调用到游戏客户端类中:GameClinet
/*
游戏客户端
*/
public class GameClinet extends Frame {
// 常量 定义背景图片的路径
public static final String BG_PATH = "Javaylm/images/bg.png";
//定义一个图片的静态变量
private static Image image;
// 创建人物--小丑
private Buffoon buffoonImage = new Buffoon();
// 创建发射物--帽子
private Missile missileImage = new Missile();
// 创建墙体
private Wall wallImage = new Wall();
private Wall wallImage1 = new Wall();
// 创建爆炸物
private Explode explodeImage = new Explode();
四、再游戏客户端:GameClinet画所有人物
/*
* 画画,重写父类的paint方法
* Graphics 画笔类
* @param g 画笔
* */
*
@Override
public void paint(Graphics g) {
// 画背景图
g.drawImage(image,0,0,1100,700,this);
// 画人物--小丑
g.drawImage(Buffoon.buffoonImage,350,300,50,50,this);
g.drawImage(Buffoon.buffoonImage,600,350,50,50,this);
g.drawImage(Buffoon.buffoonImage,700,150,50,50,this);
g.drawImage(Buffoon.buffoonImage,500,100,50,50,this);
g.drawImage(Buffoon.buffoonImage,450,200,50,50,this);
//画发射物--帽子
g.drawImage(Missile.missileImage,200,200,35,25,this);
g.drawImage(Missile.missileImage,250,350,35,25,this);
g.drawImage(Missile.missileImage,500,280,35,25,this);
g.drawImage(Missile.missileImage,800,260,35,25,this);
g.drawImage(Missile.missileImage,700,450,35,25,this);
g.drawImage(Missile.missileImage,600,200,35,25,this);
//画墙体
// 横向墙体
g.drawImage(Wall.wallImage,400,150,130,20,this);
g.drawImage(Wall.wallImage,400,250,130,20,this);
g.drawImage(Wall.wallImage,600,100,130,20,this);
g.drawImage(Wall.wallImage,600,400,130,20,this);
g.drawImage(Wall.wallImage,400,350,130,20,this);
// 竖向墙体
g.drawImage(Wall.wallImage1,300,300,20,130,this);
g.drawImage(Wall.wallImage1,800,300,20,130,this);
g.drawImage(Wall.wallImage1,300,100,20,130,this);
g.drawImage(Wall.wallImage1,800,100,20,130,this);
g.drawImage(Wall.wallImage1,650,200,20,130,this);
// 画爆炸物
g.drawImage(Explode.explodeImage,850,350,50,50,this);
}
}
关闭游戏、退出游戏
// 关闭游戏,退出游戏
this.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.out.println("Game Over!!!");
// 退出游戏
System.exit(0);
}
});
五:在游戏客户端:GameClinet增添键盘事件(按下触发、松开触发)
// 监听键盘事件
this.addKeyListener(new KeyAdapter() {
// 键盘按下触发
@Override
public void keyPressed(KeyEvent e) {
// 获取被按下的键对应的数值 如:a:67,b:68
int keyCode = e.getKeyCode();
switch (keyCode){
case KeyEvent.VK_UP:
System.out.println("向上走!!!");
// 按向上箭头,给人物的方向设置为上
buffoons.setDir("UP");
break;
case KeyEvent.VK_DOWN:
System.out.println("向下走!!!");
// 按向下箭头,给人物的方向设置为上
buffoons.setDir("DOWN");
break;
case KeyEvent.VK_LEFT:
System.out.println("向左走!!!");
// 按向左箭头,给人物的方向设置为上
buffoons.setDir("LEFT");
break;
case KeyEvent.VK_RIGHT:
System.out.println("向右走!!!");
// 按向右箭头,给人物的方向设置为上
buffoons.setDir("RIGHT");
break;
}
// 人物移动
buffoons.move(buffoons.getDir());
}
// 键盘松开触发
@Override
public void keyReleased(KeyEvent e) {
buffoons.setDir("STOP");
}
});
// 开启重新绘制线程
RepaintThread repaintThread = new RepaintThread(this);
// 创建车间工人
Thread thread = new Thread(repaintThread);
// 工人听后调度
thread.start();
效果图如下: