当前位置: 首页 > news >正文

Java课设项目

项目简介:射击生存类小游戏

项目采用技术:

游戏引擎: Unity
编程语言: Java
图形处理: NVIDIA PhysX (物理引擎), HDRP (High Definition Render Pipeline)
音效与音乐: FMOD, Wwise
版本控制: Git
功能需求分析:

角色控制:玩家能够使用键盘和鼠标控制角色移动、瞄准和射击。
武器系统:提供多种武器供玩家选择,每种武器有不同的伤害、射速和准确度。
敌人AI:敌人能够智能地追踪玩家,并在必要时进行反击。
生存要素:玩家需要收集资源来维持生命,如食物、水和医疗用品。
游戏难度:随着游戏进程,敌人数量增多、攻击力提升,增加游戏挑战性。
成就与奖励:完成特定任务或击杀特定敌人可以获得奖励或成就。
项目亮点:

真实物理效果:使用NVIDIA PhysX物理引擎,实现逼真的武器后坐力、物体碰撞等效果。
高画质渲染:利用HDRP进行高质量渲染,打造逼真的游戏场景。
丰富多样的武器:从手枪到火箭筒,各种武器供玩家选择。
智能敌人AI:敌人具有复杂的AI逻辑,使游戏更具挑战性。

二、功能架构图

三、个人任务简述

负责输入处理模块,以及图片,动画的视觉制作,路径查找功能的实现,角色远程攻击

1. 完成的任务与功能

简单描述将自己完成的有特色的地方、重难点地方。

序号

完成功能与任务

描述

1

路径查找功能

使用了路径查找算法,实现了角色的合法移动

2

远程攻击

实现了角色的远程攻击方式

本人负责功能

*路径查找功能的实现:

  1. 核心原理:路径查找算法的核心在于寻找从起点到终点的最优路径。这通常涉及对空间或网络的建模,以及搜索算法的运用。
    1. 搜索算法的选择:包括深度优先搜索(DFS)、广度优先搜索(BFS)、Dijkstra算法、A*算法等。这些算法各有特点,适用于不同的场景和需求。由于时间有限,只选择了一种算法进行学习。​​​​​​
package Game;public class PathNode implements Comparable<PathNode>{private Grid stateData;private PathNode parentNode;private int g, h, f, depth; //g 从起点移动到指定方格的移动代价, h 从指定的方格移动到终点的估算成本public PathNode getParentNode() {return parentNode;}public void setParentNode(PathNode parentNode) {this.parentNode = parentNode;}public int getG() {return g;}public void setG(int g) {this.g = g;}public int getH() {return h;}public void setH(int h) {this.h = h;}public int getF() {return f;}public void setF(int f) {this.f = f;}public int getDepth() {return depth;}public void setDepth(int depth) {this.depth = depth;}public Grid getStateData() {return stateData;}public void setStateData(Grid stateData) {this.stateData = stateData;}public PathNode(Grid stateData, PathNode parentNode, int g, int h, int depth) {this.stateData = stateData;this.parentNode = parentNode;this.g = g;this.h = h;this.f = this.g + this.h;this.depth = depth;}@Overridepublic int compareTo(PathNode other){int NodeComp = (this.f - other.getF()) * -1;if (NodeComp == 0){NodeComp = (this.depth - other.getDepth());}return NodeComp;}
}
package Game;import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;public class Pathfinder{private List<PathNode> openNodes;private List<PathNode> closedNodes;private List<PathNode> nodesToGoal;private List<Grid> pathToGoal;private WorldGrids worldGrids;private int depth;private GameObject object;private List<Grid> gridsOfObject;private int centre;public Pathfinder(WorldGrids worldGrids, GameObject object) {this.worldGrids = worldGrids;this.object = object;this.pathToGoal = new ArrayList<>();this.nodesToGoal = new ArrayList<>();this.gridsOfObject = worldGrids.getGrid(object);Grid tmp = this.worldGrids.getGrid(object.getX(), object.getY());for(int i = 0; i < gridsOfObject.size(); i++){if(gridsOfObject.get(i).equals(tmp)){centre = i;break;}}}public List<PathNode> getOpenNodes() {return openNodes;}public void setOpenNodes(List<PathNode> openNodes) {this.openNodes = openNodes;}public List<PathNode> getClosedNodes() {return closedNodes;}public void setClosedNodes(List<PathNode> closedNodes) {this.closedNodes = closedNodes;}public int getDepth() {return depth;}public void setDepth(int depth) {this.depth = depth;}public List<PathNode> getNodesToGoal() {return nodesToGoal;}public void setNodesToGoal(List<PathNode> nodesToGoal) {this.nodesToGoal = nodesToGoal;}public List<Grid> getPathToGoal() {return pathToGoal;}public void setPathToGoal(List<Grid> pathToGoal) {this.pathToGoal = pathToGoal;}public WorldGrids getWorldGrids() {return worldGrids;}public boolean ownGrid(Grid currentGrid, Grid otherGird){int deltaX = currentGrid.getGridX() - getCentreGrid().getGridX();int deltaY = currentGrid.getGridY() - getCentreGrid().getGridY();for(Grid grid : gridsOfObject){Grid tmp = worldGrids.get(grid.getGridX() + deltaX, grid.getGridY() + deltaY);if(tmp.equals(otherGird)){return true;}}return false;}public List<Grid> nextMoves(Grid grid){List<Grid> moves = new ArrayList<>();int[] x = {0, 0, -1, 1, -1, -1, 1, 1};int[] y = {-1, 1, 0, 0, -1, 1, 1, -1};int deltaX = grid.getGridX() - getCentreGrid().getGridX();int deltaY = grid.getGridY() - getCentreGrid().getGridY();for(int i = 0; i < 8; i++){boolean flag = true;for(int j = 0; j < gridsOfObject.size(); j++){int nextX = gridsOfObject.get(j).getGridX() + deltaX + x[i];int nextY = gridsOfObject.get(j).getGridY() + deltaY + y[i];Grid next = worldGrids.get(nextX, nextY);if(!ownGrid(grid, next) && !next.isAccessible()){flag = false;break;}}if(flag){moves.add(worldGrids.get(grid.getGridX() + x[i], grid.getGridY() + y[i]));}}return moves;}public int getHeuristic(Grid currentPos, Grid goalPos){return (Math.abs(goalPos.getGridX() - currentPos.getGridX()) + Math.abs(goalPos.getGridY() - currentPos.getGridY())) * 10;}public int getCost(Grid currentPos, Grid goalPos){if(Math.abs(goalPos.getGridX() - currentPos.getGridX()) != 0 && Math.abs(goalPos.getGridY() - currentPos.getGridY()) != 0){return 14;} else {return 10;}}public int getDistance(int x1, int y1, int x2, int y2){double deltaX = x1 - x2;double deltaY = y1 - y2;return (int)Math.sqrt(Math.pow(deltaX, 2) + Math.pow(deltaY, 2));}public Grid getCentreGrid(){return this.gridsOfObject.get(centre);}public List<Grid> shortestPath(Grid goalPos){if(((Enemy)object).getTarget() == null) return null;worldGrids.updateGrids();Grid startPos = (Grid) getCentreGrid().clone();openNodes = new ArrayList<>();closedNodes = new ArrayList<>();depth = 0;boolean hasGoal = false;openNodes.add(new PathNode(startPos, null, 0, getHeuristic(startPos, goalPos), depth));while(openNodes.size() != 0){closedNodes.add(openNodes.get(openNodes.size() - 1));PathNode currentNode = closedNodes.get(closedNodes.size() - 1);Grid current = currentNode.getStateData();openNodes.remove(openNodes.size() - 1);int distance = getDistance(current.getX(), current.getY(), goalPos.getX(), goalPos.getY());int r = ((Enemy)object).getTarget().getRadius();if (distance < object.getRadius() + r + 10 || currentNode.getDepth() > 25) {hasGoal = true;break;}List<Grid> expanded = nextMoves(current);NodeLoop:for(int i = 0; (i < openNodes.size() || i < closedNodes.size()); i++){int s = expanded.size() - 1;while(s >= 0){if(i < openNodes.size()){Grid OpenstateData = openNodes.get(i).getStateData();if(OpenstateData.equals(expanded.get(s))){if((currentNode.getG() + getCost(current, OpenstateData)) < openNodes.get(i).getG()){openNodes.get(i).setG(currentNode.getG() + getCost(current, OpenstateData));openNodes.get(i).setH(getHeuristic(expanded.get(s), goalPos));openNodes.get(i).setF(openNodes.get(i).getG() + openNodes.get(i).getH());openNodes.get(i).setParentNode(currentNode);}expanded.remove(s);if (expanded.isEmpty()) {break NodeLoop;}s--;continue ;}}if(i < closedNodes.size()){if (closedNodes.get(i).getStateData().equals(expanded.get(s))){expanded.remove(s);if (expanded.isEmpty()){break NodeLoop;}}}s--;}}if (!expanded.isEmpty()) {for (int i = 0; i < expanded.size(); i++) {openNodes.add(new PathNode(expanded.get(i),currentNode,currentNode.getG() + getCost(current, expanded.get(i)),getHeuristic(expanded.get(i), goalPos),currentNode.getDepth() + 1));}}Collections.sort(openNodes);}try {if (hasGoal) {int depth = closedNodes.get(closedNodes.size() - 1).getDepth();PathNode parent = closedNodes.get(closedNodes.size() - 1);for (int s = 0; s <= depth; s++) {nodesToGoal.add(parent);pathToGoal.add(parent.getStateData());parent = nodesToGoal.get(s).getParentNode();}Collections.reverse(pathToGoal);return pathToGoal;}return null;} catch (NullPointerException e){if(pathToGoal != null) return pathToGoal;return null;}}
}

监听玩家输入。

package Game;public enum Direction {LD, RU, LU, RD, L, R, U, D, STOP;public static double toDegree(Direction dir){switch (dir){case R: return 0;case RU: return 45;case U: return 90;case LU: return 135;case L: return 180;case LD: return 225;case D: return 270;case RD:  return 315;default: return 360;}}public static double getVectorX(Direction dir){switch (dir){case R: return 1;case RU: return Math.cos(Math.toRadians(45));case U: return 0;case LU: return -Math.cos(Math.toRadians(45));case L: return -1;case LD: return -Math.cos(Math.toRadians(45));case D: return 0;case RD:  return Math.cos(Math.toRadians(45));default: return -2;}}public static double getVectorY(Direction dir){switch (dir){case R: return 0;case RU: return Math.cos(Math.toRadians(45));case U: return 1;case LU: return Math.cos(Math.toRadians(45));case L: return 0;case LD: return -Math.cos(Math.toRadians(45));case D: return -1;case RD:  return -Math.cos(Math.toRadians(45));default: return -2;}}
}

​​​​​​​远程攻击的设定:

package Game;import java.awt.*;public class Ball extends Weapon implements Cloneable{private final int attackRange = 40;private boolean ultimateState;private int num;protected int picOffset;private int[] imgOrder = {4,7,5,6,1,2,3,0};public Ball(String name, int radius, int speed, int damage, int coldDownTime, Role role, World world){super(name, radius, speed, damage, coldDownTime, role, 300, 360,true, world);}public void initFireball(Direction dir){if(this.num <= 0) return;this.setDir(dir);double cosA = (Math.cos(Math.toRadians(Direction.toDegree(dir))));double sinA = -(Math.sin(Math.toRadians(Direction.toDegree(dir))));this.x = (int)(this.host.getX() + this.host.getRadius() * cosA);this.y = (int)(this.host.getY() + this.host.getRadius() * sinA);this.xIncrement = (int)(this.speed * cosA);this.yIncrement = (int)(this.speed * sinA);world.addObject((Ball) this.clone());this.num--;}public int getNum() {return num;}public void setNum(int num) {this.num = num;}public void Attack(){}@Overridepublic boolean collisionDetection(GameObject object) {return ((!object.equals(this.host)) && !(object instanceof Weapon) && super.collisionDetection(object));}public void draw(Graphics g){int picY = imgOrder[dir == Direction.STOP ? oldDir.ordinal() : dir.ordinal()];int picX = maintainState(3);this.x += xIncrement;this.y += yIncrement;drawOneImage(g, this.name, getPicOffset(), this.x, this.y, picX, picY);world.collisionDetection(this);}public void setState(){initFireball(this.host.getDir() == Direction.STOP ? host.getOldDir() : host.getDir());super.setState();}public void setUltimateState(){if(getNum() < 8) return;for(Direction dir : Direction.values()){if(dir == Direction.STOP) continue;initFireball(dir);}super.setState();}public int maintainState(int n){this.state++;if(state >= n) {state = 0;}return state;}public void collisionResponse(GameObject object){world.removeObject(this);resetState();object.onAttack(this);}public int getPicOffset(){return picOffset;}@Overridepublic String toString(){String strBuf = name;strBuf += ":";strBuf += String.valueOf(getNum());return strBuf;}
}

相关文章:

  • Docker Nginx
  • C++访问Private,Protecd的一些方法总结
  • 数据分析的流程是啥样?
  • web前端教程全套:从入门到精通的全方位探索
  • Rust 异步 trait 的实现困难
  • 【linux】认识“文件”的本质,理解“文件系统”的设计逻辑,体会linux优雅的设计理念
  • FreeBSD jail里面pkg 无法update、search和install
  • 零基础到高手蜕变:一步到位Jupyter Notebook安装全攻略
  • Wifi通信协议:WEP,WPA,WPA2,WPA3,WPS
  • C++设计模式——Decorator装饰器模式
  • OpenCV 4.10 发布
  • SpringBoot使用jasypt实现数据库信息的脱敏,以此来保护数据库的用户名username和密码password(容易上手,详细)
  • 经销商的生意好坏很大程度上跟这群人有关
  • 利用Cesium和JS实现地点点聚合功能
  • FastWeb - Lua开源跨平台网站开发服务
  • 收藏网友的 源程序下载网
  • es6要点
  • java取消线程实例
  • Meteor的表单提交:Form
  • nodejs实现webservice问题总结
  • OpenStack安装流程(juno版)- 添加网络服务(neutron)- controller节点
  • Python连接Oracle
  • Terraform入门 - 1. 安装Terraform
  • 对象管理器(defineProperty)学习笔记
  • 面试题:给你个id,去拿到name,多叉树遍历
  • 数据库写操作弃用“SELECT ... FOR UPDATE”解决方案
  • 智能合约Solidity教程-事件和日志(一)
  • postgresql行列转换函数
  • ​html.parser --- 简单的 HTML 和 XHTML 解析器​
  • ​HTTP与HTTPS:网络通信的安全卫士
  • ​创新驱动,边缘计算领袖:亚马逊云科技海外服务器服务再进化
  • # 20155222 2016-2017-2 《Java程序设计》第5周学习总结
  • ######## golang各章节终篇索引 ########
  • #数据结构 笔记一
  • $.ajax中的eval及dataType
  • (1)SpringCloud 整合Python
  • (八)Spring源码解析:Spring MVC
  • (笔记)M1使用hombrew安装qemu
  • (动手学习深度学习)第13章 计算机视觉---微调
  • (附源码)小程序 交通违法举报系统 毕业设计 242045
  • (蓝桥杯每日一题)平方末尾及补充(常用的字符串函数功能)
  • (四)搭建容器云管理平台笔记—安装ETCD(不使用证书)
  • (算法)Travel Information Center
  • (一) springboot详细介绍
  • (一)插入排序
  • (原)Matlab的svmtrain和svmclassify
  • (杂交版)植物大战僵尸
  • (转)Oracle 9i 数据库设计指引全集(1)
  • *** 2003
  • ****** 二 ******、软设笔记【数据结构】-KMP算法、树、二叉树
  • .NET Framework杂记
  • .NET 服务 ServiceController
  • .NET 设计模式—简单工厂(Simple Factory Pattern)
  • .net6 webapi log4net完整配置使用流程
  • .NET版Word处理控件Aspose.words功能演示:在ASP.NET MVC中创建MS Word编辑器