JAVA-制作小游戏期末实训
源码
import game.frame.Frame;
public class App {
public static void main(String[] args) {
System.out.println("starting......");
new Frame();
}
}
package game.controller;
import game.model.Enemy;
public class EnemyController implements Runnable{
private Enemy enemy;
public EnemyController(Enemy enemy) {
this.enemy = enemy;
}
@Override
public void run() {
while (true) {
try {
if (enemy.getStatus() == 1 || enemy.getStatus() == -1) {
enemy.setStatus(-2); // 站立状态修改成左跑
}
if (enemy.getX() <= -100) {
enemy.setStatus(2);
}
if (enemy.getX() >= 300) {
enemy.setStatus(-2);
}
Thread.sleep(50);
} catch (InterruptedException e){
e.printStackTrace();
}
}
}
}
package game.frame;
import game.model.BackGround;
import game.model.Enemy;
import game.model.Person;
import javax.swing.JFrame;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferedImage;
import java.util.Date;
import java.util.List;
public class Frame extends JFrame implements Runnable, KeyListener {
private Person person; // 添加人物
private Date startDate = new Date(); // 游戏开始时间
private BackGround nowBackGround; // 当前场景
public Frame() {
setTitle("game"); // 窗体标题
setSize(720, 480); // 窗体大小
// 居中显示
Toolkit toolkit = Toolkit.getDefaultToolkit(); // 获取屏幕工具包
int width = (int)toolkit.getScreenSize().getWidth(); // 获取屏幕宽度
int hight = (int)toolkit.getScreenSize().getHeight(); // 获取屏幕高度
int x = (width - 720) / 2;
int y = (hight - 480) / 2;
this.setLocation(x, y);
// 初始化场景
nowBackGround = new BackGround(1);
setVisible(true); // 设置可见
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 程序随窗体关闭而关闭
// 监听键盘
this.addKeyListener(this);
// 多线程
Thread thread = new Thread(this);
thread.start();
// 创建人物
person = new Person(0, 250, nowBackGround);
}
// 多线程任务
@Override
public void run() {
while (true) {
try {
this.person.applyGravity();
this.repaint(); // 循环重新绘画窗口
Thread.sleep(50); // 线程休息50毫秒
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
@Override
public void paint(Graphics g) {
// 创建图片对象
BufferedImage image = new BufferedImage(720, 480, BufferedImage.TYPE_3BYTE_BGR);
// 获取图像画笔
Graphics graphics = image.getGraphics();
// 图像画笔绘画图像
graphics.drawImage(nowBackGround.getShowImage(), 0, 0, this);
// 添加时间
long dif = new Date().getTime() - startDate.getTime();
// 绘画时间
graphics.drawString("时间 " + (dif/1000/60) + " : " + (dif/1000%60), 600, 60);
// 绘画击杀数
graphics.drawString("击杀数: " + person.getKillNum(), 600, 80);
// 绘画敌人
List<Enemy> allEnemy = nowBackGround.getAllEnemy();
for (Enemy enemy : allEnemy) {
graphics.drawImage(enemy.getShowImage(), enemy.getX(), enemy.getY(), this);
}
// 绘画人物
graphics.drawImage(person.getShowImage(), person.getX(), person.getY(), this);
// 窗体画笔会话图像
g.drawImage(image, 0, 0, this);
// 是否进入下一场景
if (nowBackGround.isPass(person) && nowBackGround.hasNext()) {
nowBackGround = nowBackGround.next();
person.setX(0);
person.setBackGround(nowBackGround); // 重新设置场景
}
}
@Override // 键入某个键时调用
public void keyTyped(KeyEvent e) {
//TODO
}
@Override // 按下某个键时调用
public void keyPressed(KeyEvent e) {
int keyCode = e.getKeyCode();
if (keyCode == 68) { // 按下D时右跑
this.person.rightRun();
}
if (keyCode == 65) { // 按下A时左跑
this.person.leftRun();
}
if (keyCode == 75) { // 按下K时跳跃
this.person.jump();
}
if (keyCode == 74) { // 按下J时攻击
this.person.attack();
}
if (keyCode == 76) { // 按下L时闪现
this.person.flash();
}
// 当按下A或D键且人物处于跳跃状态时,设置方向改变请求为true
if (person.getStatus() == 3 || person.getStatus() == -3) {
if (keyCode == 68) {
person.setJumpDirectionChangeRequested(true);
person.setJumpMoveDirection(1);
} else if (keyCode == 65) {
person.setJumpDirectionChangeRequested(true);
person.setJumpMoveDirection(-1);
}
}
}
@Override // 释放某个键时调用
public void keyReleased(KeyEvent e) {
int keyCode = e.getKeyCode();
if (keyCode == 68) { // 释放D时停止右跑
this.person.stopRightRun();
}
if (keyCode == 65) { // 释放A时停止左跑
this.person.stopLeftRun();
}
}
}
package game.model;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.List;
import game.util.StaticValue;
public class BackGround {
private BufferedImage showImage = null; // 显示的场景图片
private int sort; // 序号
private int nextSort; // 下一个场景序号
private List<Enemy> allEnemy = new ArrayList<>(); // 敌人
public BackGround(int sort) {
this.sort = sort;
create();
}
public void create() { // 根据sort选择场景
if (this.sort == 1) {
this.showImage = StaticValue.bg01;
this.allEnemy.add(new Enemy(400, 110, this));
this.allEnemy.add(new Enemy(200, 110, this));
this.nextSort = 2;
} else if (this.sort == 2) {
this.showImage = StaticValue.bg02;
this.nextSort = 3;
this.allEnemy.add(new Enemy(400, 100, this));
this.allEnemy.add(new Enemy(200, 100, this));
} else if (this.sort == 3) {
this.showImage = StaticValue.bg03;
this.nextSort = 4;
this.allEnemy.add(new Enemy(400, 100, this));
this.allEnemy.add(new Enemy(200, 100, this));
this.allEnemy.add(new Enemy(600, 100, this));
}else if (this.sort == 4) {
this.showImage = StaticValue.bg04;
this.nextSort = 1;
this.allEnemy.add(new Enemy(400, 100, this));
this.allEnemy.add(new Enemy(200, 100, this));
this.allEnemy.add(new Enemy(600, 100, this));
this.allEnemy.add(new Enemy(300, 100, this));
}
}
public boolean hasNext() { // 是否有另一个场景
return nextSort != 0;
}
public BackGround next() { // 创建下一个场景
return new BackGround(nextSort);
}
public boolean isPass(Person person) { // 是否可以通过
if (person.getX() >= 650) {
return true;
}
return false;
}
public BufferedImage getShowImage() {
return showImage;
}
public void setShowImage(BufferedImage showImage) {
this.showImage = showImage;
}
public List<Enemy> getAllEnemy() {
return allEnemy;
}
}
package game.model;
import game.controller.EnemyController;
import game.util.StaticValue;
public class Enemy extends Person{
private Thread controllerThread;
public Enemy(int x, int y, BackGround backGround) {
super(x, y, backGround);
this.status = -1; // 设置状态为左站立
controllerThread = new Thread(new EnemyController(this));
controllerThread.start();
}
// 设置敌人图片
@Override
protected void setImageList() {
leftStandImages = StaticValue.leftEnemyImgs.subList(14, 19);
rightStandImages = StaticValue.rightEnemyImgs.subList(14, 19);
leftRunImages = StaticValue.leftEnemyImgs.subList(0, 6);
rightRunImages = StaticValue.rightEnemyImgs.subList(0, 6);
leftJumpImages = StaticValue.leftEnemyImgs.subList(4, 5);
rightJumpImages = StaticValue.rightEnemyImgs.subList(4, 5);
leftAttackImages = StaticValue.leftEnemyImgs.subList(6, 14);
rightAttackImages = StaticValue.rightEnemyImgs.subList(6, 14);
}
public void dead() { // 死掉
this.backGround.getAllEnemy().remove(this);
Person.killNum++;
}
}
package game.model;
import game.util.StaticValue;
import java.awt.image.BufferedImage;
import java.util.List;
public class Person implements Runnable{
protected int x; // 坐标x
protected int y; // 坐标y
protected BufferedImage showImage; // 人物显示图片
protected Thread t; // 线程
protected double moving = 0; // 移动帧数
protected int status = 1; // 人物状态 默认右站立
protected int jumpForce = 0; // 跳跃力
protected int jumpMoveDirection = 0; // 跳跃移动方向 0垂直 -1向左 1向右
protected BackGround backGround; // 场景
protected static int killNum = 0; // 击杀数
private boolean jumpDirectionChangeRequested = false; // 跳跃时的方向改变请求
protected List<BufferedImage> leftStandImages; // 左站立图集
protected List<BufferedImage> rightStandImages; // 右站立图集
protected List<BufferedImage> leftRunImages; // 左跑图集
protected List<BufferedImage> rightRunImages; // 右跑图集
protected List<BufferedImage> leftJumpImages; // 左跳图集
protected List<BufferedImage> rightJumpImages; // 右跳图集
protected List<BufferedImage> leftAttackImages; // 左攻图集
protected List<BufferedImage> rightAttackImages; // 右攻图集
public Person(int x, int y, BackGround backGround) {
this.x = x;
this.y = y;
this.backGround = backGround;
this.t = new Thread(this);
t.start();
setImageList();
}
protected void setImageList() { // 初始化图集
leftStandImages = StaticValue.leftPersonImgs.subList(0, 4);
rightStandImages = StaticValue.rightPersonImgs.subList(0, 4);
leftRunImages = StaticValue.leftPersonImgs.subList(5, 9);
rightRunImages = StaticValue.rightPersonImgs.subList(5, 9);
leftJumpImages = StaticValue.leftPersonImgs.subList(6, 7);
rightJumpImages = StaticValue.rightPersonImgs.subList(6, 7);
leftAttackImages = StaticValue.leftPersonImgs.subList(9, 12);
rightAttackImages = StaticValue.rightPersonImgs.subList(9, 12);
}
@Override
public void run() {
// 线程更新人物
while (true) {
try {
switch (status) {
case 1: // 向右-站立
if (this.moving > 3) {
this.moving = 0;
}
this.showImage = rightStandImages.get((int)moving);
moving += 0.2;
break;
case 2: // 向右-跑
if (this.moving > 3) {
this.moving = 0;
}
this.showImage = rightRunImages.get((int)moving);
moving += 0.5;
break;
case 3: // 向右-跳跃
this.moving = 0;
this.showImage = rightJumpImages.get((int)moving);
if (jumpDirectionChangeRequested) {
if (jumpMoveDirection == -1) {
status = -3;
}
jumpDirectionChangeRequested = false;
}
if (jumpMoveDirection > 0) {
x += 10;
} else if (jumpMoveDirection < 0) {
x -= 10;
}
y -= jumpForce + 2;
if (y > 250) {
y = 250;
if (jumpMoveDirection > 0) {
this.status = 2;
} else if (jumpMoveDirection < 0) {
this.status = -2;
} else {
this.status = this.status > 0? 1 : -1;
}
}
jumpForce--;
break;
case 4: // 向右-攻击
if (this.moving > 2) {
this.moving = 0;
}
this.showImage = rightAttackImages.get((int)moving);
moving += 0.5;
if (this.moving == 2){
this.status = this.status > 0 ? 1 : -1;
}
break;
case -1: // 向左-站立
if (this.moving > 3) {
this.moving = 0;
}
this.showImage = leftStandImages.get((int)moving);
moving += 0.2;
break;
case -2: // 向左-跑
if (this.moving > 3) {
this.moving = 0;
}
this.showImage = leftRunImages.get((int)moving);
moving += 0.5;
break;
case -3: // 向左-跳跃
this.moving = 0;
this.showImage = leftJumpImages.get((int)moving);
if (jumpDirectionChangeRequested) {
if (jumpMoveDirection == 1) {
status = 3;
}
jumpDirectionChangeRequested = false;
}
if (jumpMoveDirection > 0) {
x += 10;
} else if (jumpMoveDirection < 0) {
x -= 10;
}
y -= jumpForce + 2;
if (y > 250) {
y = 250;
if (jumpMoveDirection > 0) {
this.status = 2;
} else if (jumpMoveDirection < 0) {
this.status = -2;
} else {
this.status = this.status > 0? 1 : -1;
}
}
jumpForce--;
break;
case -4: // 向左-攻击
if (this.moving > 2) {
this.moving = 0;
}
this.showImage = leftAttackImages.get((int)moving);
moving += 0.5;
if (this.moving == 2){
this.status = this.status > 0 ? 1 : -1;
}
default:
break;
}
moveXY(); // 人物移动
// 边界控制
if (x < -100) {
x = -100;
}
if (x > 650) {
x = 650;
}
// 攻击敌人
if (this.backGround != null) {
List<Enemy> allEnemy = this.backGround.getAllEnemy(); // 获取场景中所有的敌人
for (int i = 0; i < allEnemy.size(); i++) {
Enemy enemy = allEnemy.get(i);
if (this.status == 4 && (this.x + 125) > (enemy.getX()) && (this.x + 125) < (enemy.getX() + 250)) {
enemy.dead();
} else if (this.status == -4 && (this.x + 125) < (enemy.getX() + 400) && (this.x + 125) > (enemy.getX() + 256)) {
enemy.dead();
}
}
}
Thread.sleep(50);
}catch (InterruptedException e) {
e.printStackTrace();
}
}
}
private void moveXY() { // 人物移动方法
switch (status) {
case 1: // 向右-站立
break;
case 2: // 向右-跑
x += 10;
break;
case 3: // 向右-跳跃
if (this.jumpMoveDirection > 0) {
x += 10;
}else if (this.jumpMoveDirection < 0) {
x -= 10;
}
y -= jumpForce + 2;
if (y > 250) {
y = 250;
if (this.jumpMoveDirection > 0) {
this.status = 2;
} else if (this.jumpMoveDirection < 0) {
this.status = -2;
}else {
this.status = this.status > 0 ? 1 : -1;
}
}
jumpForce--;
break;
case 4: // 向右-攻击
break;
case -1: // 向左-站立
break;
case -2: // 向左-跑
x -= 10;
break;
case -3: // 向左-跳跃
if (this.jumpMoveDirection > 0) {
x += 10;
}else if (this.jumpMoveDirection < 0) {
x -= 10;
}
y -= jumpForce + 2;
if (y > 250) {
y = 250;
if (this.jumpMoveDirection > 0) {
this.status = 2;
} else if (this.jumpMoveDirection < 0) {
this.status = -2;
}else {
this.status = this.status > 0 ? 1 : -1;
}
}
jumpForce--;
break;
case -4: // 向左-攻击
break;
default:
break;
}
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public void setX(int x) {
this.x = x;
}
public void setY(int y) {
this.y = y;
}
public int getKillNum() {
return killNum;
}
public BufferedImage getShowImage() {
if (showImage == null) { // 当图片显示为空获取图片
showImage = StaticValue.rightPersonImgs.get(0); // 获取第一张
}
return showImage;
}
public void setShowImage(BufferedImage showImage) {
this.showImage = showImage;
}
public void rightRun() { // 右跑
if (this.status == 3 || this.status == -3) { // 浮空状态不允许改变状态
return;
}
this.status = 2;
}
public void leftRun() { // 左跑
if (this.status == 3 || this.status == -3) { // 浮空状态不允许改变状态
return;
}
this.status = -2;
}
public void stopRightRun() { // 停止右跑
if (this.status == 3 || this.status == -3) { // 浮空状态不允许改变状态
this.jumpMoveDirection = 0; // 跳跃结束恢复站立
return;
}
this.status = 1;
}
public void stopLeftRun() { // 停止左跑
if (this.status == 3 || this.status == -3) { // 浮空状态不允许改变状态
this.jumpMoveDirection = 0; // 跳跃结束恢复站立
return;
}
this.status = -1;
}
public void jump() { // 跳跃
if (this.status != 3 && this.status != -3) {
if (this.status == 2 || this.status == -2) {
this.jumpMoveDirection = this.status > 0 ? 1 : -1;
}
this.status = this.status > 0 ? 3 : -3; // 设置状态为跳跃
this.jumpForce = 15; // 设置跳跃力
}
}
public void attack() { // 攻击
if (this.status > 0) {
this.status = 4;
}else {
this.status = -4;
}
}
public int getStatus() {
return status;
}
public void setStatus(int status) {
this.status = status;
}
public BackGround getBackGround() {
return backGround;
}
public void setBackGround(BackGround backGround) {
this.backGround = backGround;
}
public void setJumpDirectionChangeRequested(boolean jumpDirectionChangeRequested) {
this.jumpDirectionChangeRequested = jumpDirectionChangeRequested;
}
public void setJumpMoveDirection(int jumpMoveDirection) {
this.jumpMoveDirection = jumpMoveDirection;
}
private double veloctiyY = 0; // 当前速度
public void applyGravity() { // 跳跃攻击后落地方法
if (this.y < 250) {
double GRAVITY = 0.5;
this.veloctiyY += GRAVITY;
this.y += (int)this.veloctiyY;
if (this.y >= 250) {
this.y = 250;
this.veloctiyY = 0;
}
}
}
public void flash() { // 闪现
if (this.status == 1 || this.status == 2) {
this.x += 100;
}else if (this.status == -1 || this.status == -2) {
this.x -= 100;
}
}
}
package game.util;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;
public class StaticValue {
// 获取项目目录
public static final String ImagePath = System.getProperty("user.dir") + "/res/";
// 背景图片
public static BufferedImage bg01 = null;
public static BufferedImage bg02 = null;
public static BufferedImage bg03 = null;
public static BufferedImage bg04 = null;
// 人物图片集合
public static List<BufferedImage> leftPersonImgs = new ArrayList<>();
public static List<BufferedImage> rightPersonImgs = new ArrayList<>();
// 敌人图片集合
public static List<BufferedImage> leftEnemyImgs = new ArrayList<>();
public static List<BufferedImage> rightEnemyImgs = new ArrayList<>();
static {
try {
// 获取背景图片
bg01 = ImageIO.read(new File(ImagePath + "background/1.png"));
bg02 = ImageIO.read(new File(ImagePath + "background/2.png"));
bg03 = ImageIO.read(new File(ImagePath + "background/3.png"));
bg04 = ImageIO.read(new File(ImagePath + "background/4.png"));
// 获取人物图片
for (int i = 1; i <= 14; i++) {
DecimalFormat decimalFormat = new DecimalFormat("00");
String num = decimalFormat.format(i);
// 添加人物图片到集合中
leftPersonImgs.add(ImageIO.read(new File(ImagePath + "person/left/" + num + ".png")));
rightPersonImgs.add(ImageIO.read(new File(ImagePath + "person/right/" + num + ".png")));
}
// 加载敌人图片
for (int i = 0; i <= 6; i++) {
File rightfile = new File(ImagePath + "enemy/right/517_move_" + i + ".png");
File leftfile = new File(ImagePath + "enemy/left/517_move_" + i + ".png");
leftEnemyImgs.add(ImageIO.read(leftfile));
rightEnemyImgs.add(ImageIO.read(rightfile));
}
for (int i = 0; i <= 7; i++) {
File rightfile = new File(ImagePath + "enemy/right/517_skill_1027_" + i + ".png");
File leftfile = new File(ImagePath + "enemy/left/517_skill_1027_" + i + ".png");
leftEnemyImgs.add(ImageIO.read(leftfile));
rightEnemyImgs.add(ImageIO.read(rightfile));
}
for (int i = 0; i <= 7; i++) {
File rightfile = new File(ImagePath + "enemy/right/517_stand_" + i + ".png");
File leftfile = new File(ImagePath + "enemy/left/517_stand_" + i + ".png");
leftEnemyImgs.add(ImageIO.read(leftfile));
rightEnemyImgs.add(ImageIO.read(rightfile));
}
}catch (IOException e) {
e.printStackTrace();
}
}
}
新增功能
杀敌数量显示
Person添加killNum属性记录杀敌数量
Frame.java
// 绘画时间
graphics.drawString("时间 " + (dif/1000/60) + " : " + (dif/1000%60), 600, 60);
跳跃可攻击
Person.java
public void attack() { // 攻击
if (this.status > 0) {
this.status = 4;
}else {
this.status = -4;
}
}
public void applyGravity() { // 落地方法
if (this.y < 250) {
double GRAVITY = 0.5;
this.veloctiyY += GRAVITY;
this.y += (int)this.veloctiyY;
if (this.y >= 250) {
this.y = 250;
this.veloctiyY = 0;
}
}
}
跳跃可转身
Person.java
private boolean jumpDirectionChangeRequested = false; // 跳跃时的方向改变请求
public void setJumpDirectionChangeRequested(boolean jumpDirectionChangeRequested) {
this.jumpDirectionChangeRequested = jumpDirectionChangeRequested;
}
public void setJumpMoveDirection(int jumpMoveDirection) {
this.jumpMoveDirection = jumpMoveDirection;
}
private void moveXY() { // 人物移动方法
switch (status) {
case 1: // 向右-站立
break;
case 2: // 向右-跑
x += 10;
break;
case 3: // 向右-跳跃
if (this.jumpMoveDirection > 0) {
x += 10;
}else if (this.jumpMoveDirection < 0) {
x -= 10;
}
y -= jumpForce + 2;
if (y > 250) {
y = 250;
if (this.jumpMoveDirection > 0) {
this.status = 2;
} else if (this.jumpMoveDirection < 0) {
this.status = -2;
}else {
this.status = this.status > 0 ? 1 : -1;
}
}
jumpForce--;
break;
case 4: // 向右-攻击
break;
case -1: // 向左-站立
break;
case -2: // 向左-跑
x -= 10;
break;
case -3: // 向左-跳跃
if (this.jumpMoveDirection > 0) {
x += 10;
}else if (this.jumpMoveDirection < 0) {
x -= 10;
}
y -= jumpForce + 2;
if (y > 250) {
y = 250;
if (this.jumpMoveDirection > 0) {
this.status = 2;
} else if (this.jumpMoveDirection < 0) {
this.status = -2;
}else {
this.status = this.status > 0 ? 1 : -1;
}
}
jumpForce--;
break;
case -4: // 向左-攻击
break;
default:
break;
}
}
Frame.java
@Override // 按下某个键时调用
public void keyPressed(KeyEvent e) {
int keyCode = e.getKeyCode();
if (keyCode == 68) { // 按下D时右跑
this.person.rightRun();
}
if (keyCode == 65) { // 按下A时左跑
this.person.leftRun();
}
if (keyCode == 75) { // 按下K时跳跃
this.person.jump();
}
if (keyCode == 74) { // 按下J时攻击
this.person.attack();
}
if (keyCode == 76) { // 按下L时闪现
this.person.flash();
}
// 当按下A或D键且人物处于跳跃状态时,设置方向改变请求为true
if (person.getStatus() == 3 || person.getStatus() == -3) {
if (keyCode == 68) {
person.setJumpDirectionChangeRequested(true);
person.setJumpMoveDirection(1);
} else if (keyCode == 65) {
person.setJumpDirectionChangeRequested(true);
person.setJumpMoveDirection(-1);
}
}
}
闪现
Person.java
public void flash() { // 闪现
if (this.status == 1 || this.status == 2) {
this.x += 100;
}else if (this.status == -1 || this.status == -2) {
this.x -= 100;
}
}