🌟 这是星际大战系列的第三篇送福利文章,感谢一路以来支持和关注这个项目的每一位朋友!
💡 文章力求严谨,但难免有疏漏之处,欢迎各位朋友指出,让我们一起在交流中进步。
🎁 项目代码、文档和相关资源都可以免费获取,希望能帮助到更多对游戏开发感兴趣的朋友。
💌 如果您有任何想法、建议或疑问,都欢迎在评论区留言或通过私信与我交流。您的每一个反馈都是项目进步的动力!
文章目录
- 【福利分享】星际大战飞机大战升级版 - 前后端完整版本
- 前言
- 演示视频
- 项目概述
- 技术栈
- 前端技术栈
- 后端技术栈
- 新增功能模块
- 1. 用户系统
- 2. 排行榜系统
- 3. 游戏记录系统
- 4. 管理员功能
- 项目特点
- 前端详细介绍
- 游戏核心功能
- 1. 游戏引擎设计
- 2. 视觉效果系统
- 3. 音频系统
- 用户界面设计
- 1. 响应式布局
- 2. 主题设计
- 3. 交互设计
- 前后端交互
- 1. JWT认证流程
- 2. 游戏数据同步
- 3. 排行榜实现
- 排行榜核心代码实现
- 性能优化
- 1. 渲染优化
- 2. 资源管理
- 3. 代码优化
- 开发亮点
- 1. 模块化架构
- 2. 自定义游戏引擎
- 3. 创新玩法设计
- 后端详细介绍
- 系统架构设计
- 1. 分层架构
- 2. 安全架构
- 3. 缓存架构
- 核心功能实现
- 1. 用户认证与授权
- 2. 游戏记录管理
- 3. 排行榜查询优化
- 性能优化技术
- 1. 数据库优化
- 2. 缓存优化
- 3. API响应优化
- 安全性设计
- 1. 密码安全
- 2. API安全
- 3. 数据安全
- 可扩展性设计
- 1. 模块化设计
- 2. 接口设计
- 3. 配置外部化
- 部署说明
- 源码获取
- 致谢
- 结语
【福利分享】星际大战飞机大战升级版 - 前后端完整版本
繁星点点,太空浩瀚。让我们再次启程,在代码中探索无尽的可能。
前言
大家好,我是程序员果冻~。首先要特别感谢之前纯前端版本的广大读者们的支持和鼓励!你们的点赞、收藏、评论和私信建议给了我极大的动力。应大家的要求,这次我为大家带来了全新升级的前后端完整版本,适合正在学习JAVA的新手朋友学习练习。
源码附文章末尾。
演示视频
前后端进阶版飞机大战
如果上面的视频无法观看,可能是因为还在审核中,可以先看下面的视频。
前后端进阶版飞机大战
项目概述
本次升级版本在保留了原有炫酷游戏玩法的基础上,新增了用户系统、排行榜、游戏记录等功能,让游戏体验更加完整和社交化。项目采用前后端分离架构,是一个非常适合学习全栈开发的示例项目。
技术栈
前端技术栈
- HTML5 + CSS3
- 原生JavaScript (ES6+)
- Canvas游戏渲染
- JWT前端认证
- 响应式设计
后端技术栈
- Spring Boot 2.x
- Spring Security
- JWT认证
- MySQL数据库
- Maven项目管理
新增功能模块
1. 用户系统
- 用户注册登录
- JWT token认证
- 角色权限管理(普通用户/管理员)
- 个人信息管理
2. 排行榜系统
- 多维度排行(得分/击杀/收集/时长)
- 难度分类(简单/普通/困难模式)
- 实时更新
- 分页展示
3. 游戏记录系统
- 详细游戏数据记录
- 个人游戏历史查询
- 数据统计分析
- 游戏进度追踪
4. 管理员功能
- 用户管理
- 数据监控
- 系统维护
项目特点
-
完整的用户体验
- 炫酷的游戏界面
- 流畅的操作体验
- 清晰的游戏反馈
-
安全性保障
- JWT认证
- 密码加密存储
- 权限精细控制
-
数据统计分析
- 个人游戏数据追踪
- 排行榜实时更新
- 游戏记录详细保存
-
优秀的代码结构
- 模块化设计
- 代码注释完善
- 便于学习和二次开发
前端详细介绍
游戏核心功能
1. 游戏引擎设计
本项目使用原生Canvas API构建了一个轻量级的2D游戏引擎,主要包括以下核心组件:
- Game类:游戏主控制器,负责游戏循环、状态管理和场景切换
- Player类:玩家飞船控制,包括移动、射击和碰撞检测
- Enemy类:敌人AI系统,支持多种敌人类型和行为模式
- Bullet类:子弹系统,支持不同弹道和伤害效果
- Item类:道具系统,提供多种游戏增益效果
- Background类:动态星空背景,创造沉浸式太空体验
每个组件都采用面向对象设计,具有高内聚低耦合的特点,便于扩展和维护。
2. 视觉效果系统
- 粒子系统:实现爆炸、引擎尾焰等特效
- 动态光效:飞船引擎光效、武器发射光效
- 视差背景:多层次星空背景,增强深度感
- 屏幕震动:爆炸和碰撞时的震动效果
- 动画过渡:平滑的游戏状态过渡动画
3. 音频系统
- AudioManager类:统一管理游戏音效和背景音乐
- 动态音效:根据游戏状态切换不同背景音乐
- 空间音效:根据事件发生位置调整音量和平衡
- 音频池:优化同时播放多个音效的性能
用户界面设计
1. 响应式布局
- 自适应不同屏幕尺寸,从手机到桌面设备
- 基于CSS Grid和Flexbox的灵活布局
- 媒体查询优化不同设备的游戏体验
2. 主题设计
- 深空科幻主题,暗色调背景配合霓虹色元素
- 半透明玻璃态UI面板,现代感十足
- 动态光效和渐变色,增强视觉冲击力
- 像素风格与现代UI的融合,独特的视觉风格
3. 交互设计
- 流畅的菜单导航系统
- 动态反馈的按钮和控件
- 直观的游戏控制方式
- 清晰的游戏状态指示器
前后端交互
1. JWT认证流程
- 登录/注册请求发送用户凭据
- 服务器验证并返回JWT令牌
- 前端存储令牌并在后续请求中使用
- 令牌过期处理和自动登出机制
2. 游戏数据同步
- 游戏结束时自动保存游戏记录
- 异步提交游戏数据,不阻塞用户体验
- 错误重试机制,确保数据不丢失
- 本地缓存,应对网络不稳定情况
3. 排行榜实现
- 分页加载排行数据,优化性能
- 多维度排序和筛选
- 实时更新机制
- 高亮显示当前用户排名
排行榜核心代码实现
排行榜管理器设计采用了单例模式,集中处理排行榜相关的所有逻辑:
// 排行榜管理器
const LeaderboardManager = {currentPage: 0,pageSize: 10,currentDifficulty: 'EASY', // 默认简单模式currentType: 'score', // 默认得分排行init() {// 初始化排行榜UI和事件监听this.addLeaderboardButton();this.setupEventListeners();// 设置难度选择器const difficultySelect = document.getElementById('difficultySelect');if (difficultySelect) {difficultySelect.innerHTML = `<option value="EASY">简单模式</option><option value="NORMAL">普通模式</option><option value="HELL">困难模式</option>`;difficultySelect.value = this.currentDifficulty;}},fetchLeaderboard() {// 构建API请求URL,包含分页、难度和类型参数const url = `${API_BASE_URL}/api/records/leaderboard?difficulty=${this.currentDifficulty}&type=${this.currentType}&page=${this.currentPage}&size=${this.pageSize}`;// 发送请求获取排行榜数据fetch(url).then(response => response.json()).then(data => {this.renderLeaderboard(data);this.updatePagination(data);}).catch(error => console.error('获取排行榜失败:', error));}
}
排行榜渲染采用了模板化设计,支持不同类型数据的高亮显示:
renderLeaderboard(data) {const tbody = document.getElementById('leaderboardList');tbody.innerHTML = '';if (data.content.length === 0) {tbody.innerHTML = '<tr><td colspan="7" class="no-data">暂无数据</td></tr>';return;}// 根据排行类型决定高亮显示的列const highlightColumn = this.getHighlightColumn();data.content.forEach((record, index) => {const row = document.createElement('tr');// 为前三名添加特殊样式if (index < 3) {row.classList.add(`rank-${index + 1}`);}// 检测是否为当前用户,添加高亮if (record.user.username === currentUser) {row.classList.add('current-user');}// 构建行数据row.innerHTML = `<td>${this.currentPage * this.pageSize + index + 1}</td><td>${record.user.username}</td><td class="${highlightColumn === 'score' ? 'highlight' : ''}">${record.score}</td><td class="${highlightColumn === 'kills' ? 'highlight' : ''}">${record.enemiesKilled}</td><td class="${highlightColumn === 'items' ? 'highlight' : ''}">${record.itemsCollected}</td><td class="${highlightColumn === 'time' ? 'highlight' : ''}">${formatTime(record.playTime)}</td><td>${formatDate(record.createdAt)}</td>`;tbody.appendChild(row);});
}
分页控件实现,支持首页、上一页、下一页、末页导航:
updatePagination(data) {const paginationDiv = document.getElementById('leaderboardPagination');const totalPages = data.totalPages;paginationDiv.innerHTML = `<button class="page-btn" ${this.currentPage === 0 ? 'disabled' : ''} onclick="LeaderboardManager.goToPage(0)">首页</button><button class="page-btn" ${this.currentPage === 0 ? 'disabled' : ''} onclick="LeaderboardManager.goToPage(${this.currentPage - 1})">上一页</button><span class="page-info">第 ${this.currentPage + 1}/${totalPages} 页</span><button class="page-btn" ${this.currentPage >= totalPages - 1 ? 'disabled' : ''} onclick="LeaderboardManager.goToPage(${this.currentPage + 1})">下一页</button><button class="page-btn" ${this.currentPage >= totalPages - 1 ? 'disabled' : ''} onclick="LeaderboardManager.goToPage(${totalPages - 1})">末页</button>`;
}
难度和排行类型切换的实现:
setupEventListeners() {// 难度选择器事件监听const difficultySelect = document.getElementById('difficultySelect');if (difficultySelect) {difficultySelect.addEventListener('change', () => {this.currentDifficulty = difficultySelect.value;this.currentPage = 0; // 切换难度时重置页码this.fetchLeaderboard();});}// 排行类型选择器事件监听const typeSelect = document.getElementById('typeSelect');if (typeSelect) {typeSelect.addEventListener('change', () => {this.currentType = typeSelect.value;this.currentPage = 0; // 切换类型时重置页码this.fetchLeaderboard();});}
}
性能优化
1. 渲染优化
- 使用
requestAnimationFrame
实现平滑动画 - 对象池技术减少垃圾回收
- 图层分离和缓存渲染
- 视口裁剪,只渲染可见区域
2. 资源管理
- 图像精灵表(Sprite Sheet)减少HTTP请求
- 资源预加载和懒加载策略
- 音频和图像压缩优化
- 资源版本控制和缓存策略
3. 代码优化
- 事件委托减少事件监听器数量
- 防抖和节流处理密集型事件
- Web Worker处理复杂计算
- 模块化设计,按需加载
开发亮点
1. 模块化架构
游戏核心逻辑被拆分为多个独立模块:
game.js
: 游戏主循环和状态管理player.js
: 玩家控制和属性enemy.js
: 敌人生成和AIbullet.js
: 子弹系统item.js
: 道具系统background.js
: 背景渲染audioManager.js
: 音频管理main.js
: 应用入口和UI控制
2. 自定义游戏引擎
不依赖第三方游戏引擎,从零构建了轻量级2D游戏引擎,包括:
- 碰撞检测系统
- 粒子系统
- 对象池管理
- 场景管理
- 输入处理系统
3. 创新玩法设计
- 多种武器系统和升级路径
- 动态难度调整
- 多样化的敌人类型和行为模式
- Boss战特殊机制
- 成就系统激励长期游戏
后端详细介绍
系统架构设计
1. 分层架构
后端采用经典的多层架构设计,确保代码的可维护性和可扩展性:
- 控制层(Controller): 处理HTTP请求,参数验证和响应封装
- 服务层(Service): 实现核心业务逻辑,事务管理
- 数据访问层(Repository): 与数据库交互,实现数据持久化
- 实体层(Entity): 映射数据库表结构
- DTO层: 数据传输对象,优化前后端数据交互
- 配置层(Config): 系统配置,如安全、缓存等
2. 安全架构
系统采用Spring Security + JWT的安全架构:
@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class SecurityConfig extends WebSecurityConfigurerAdapter {private final JwtAuthenticationFilter jwtAuthFilter;private final UserDetailsService userDetailsService;private final PasswordEncoder passwordEncoder;@Overrideprotected void configure(HttpSecurity http) throws Exception {http.csrf().disable().authorizeRequests().antMatchers("/api/auth/**").permitAll().antMatchers("/api/admin/**").hasRole("ADMIN").anyRequest().authenticated().and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and().addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class);}@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder);}
}
3. 缓存架构
系统使用Spring Cache实现多级缓存策略,提高查询性能:
不过本文为了能够减少外部服务依赖,并没有引入其他第三方缓存中间件。
直接存在JVM内存中
@Configuration
@EnableCaching
public class CacheConfig {@Beanpublic CacheManager cacheManager() {SimpleCacheManager cacheManager = new SimpleCacheManager();List<Cache> caches = new ArrayList<>();caches.add(new ConcurrentMapCache("leaderboard"));caches.add(new ConcurrentMapCache("userRecords"));cacheManager.setCaches(caches);return cacheManager;}
}
核心功能实现
1. 用户认证与授权
用户认证流程采用JWT令牌机制,确保API安全:
@RestController
@RequestMapping("/api/auth")
@RequiredArgsConstructor
public class AuthController {private final AuthService authService;@PostMapping("/register")public ResponseEntity<AuthResponse> register(@RequestBody RegisterRequest request) {return ResponseEntity.ok(authService.register(request));}@PostMapping("/login")public ResponseEntity<AuthResponse> login(@RequestBody LoginRequest request) {return ResponseEntity.ok(authService.login(request));}
}
JWT过滤器实现:
@Component
@RequiredArgsConstructor
public class JwtAuthenticationFilter extends OncePerRequestFilter {private final JwtService jwtService;private final UserDetailsService userDetailsService;@Overrideprotected void doFilterInternal(HttpServletRequest request,HttpServletResponse response,FilterChain filterChain) throws ServletException, IOException {final String authHeader = request.getHeader("Authorization");if (authHeader == null || !authHeader.startsWith("Bearer ")) {filterChain.doFilter(request, response);return;}final String jwt = authHeader.substring(7);final String username = jwtService.extractUsername(jwt);if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);if (jwtService.isTokenValid(jwt, userDetails)) {UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());authToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));SecurityContextHolder.getContext().setAuthentication(authToken);}}filterChain.doFilter(request, response);}
}
2. 游戏记录管理
游戏记录服务实现了高效的数据存储和查询功能,并集成了缓存优化:
@Service
@RequiredArgsConstructor
public class GameRecordService {private final GameRecordRepository gameRecordRepository;private final UserRepository userRepository;@CacheEvict(value = "leaderboard", allEntries = true)public GameRecord saveRecord(String username, GameRecordRequest request) {User user = userRepository.findByUsername(username).orElseThrow(() -> new UsernameNotFoundException("User not found"));GameRecord record = convertToEntity(request, user);return gameRecordRepository.save(record);}@Cacheable(value = "leaderboard", key = "'leaderboard_' + #difficulty + '_' + #type + '_page_' + #page + '_size_' + #size")public Page<GameRecord> getLeaderboard(String difficulty, String type, int page, int size) {Pageable pageable = PageRequest.of(page, size);switch (type.toLowerCase()) {case "score":return gameRecordRepository.findTopScoresByDifficulty(difficulty, pageable);case "kills":return gameRecordRepository.findTopKillsByDifficulty(difficulty, pageable);case "items":return gameRecordRepository.findTopItemsByDifficulty(difficulty, pageable);case "time":return gameRecordRepository.findTopPlayTimeByDifficulty(difficulty, pageable);case "escapes":return gameRecordRepository.findTopEscapesByDifficulty(difficulty, pageable);default:return gameRecordRepository.findTopScoresByDifficulty(difficulty, pageable);}}
}
3. 排行榜查询优化
排行榜查询使用了高效的SQL查询,通过窗口函数实现复杂的排名逻辑:
@Repository
public interface GameRecordRepository extends JpaRepository<GameRecord, Long> {@Query(nativeQuery = true, value = "WITH RankedScores AS ( " +" SELECT *, " +" ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY score DESC, id DESC) as rn " +" FROM game_records " +" WHERE difficulty = :difficulty " +") " +"SELECT * FROM RankedScores WHERE rn = 1 ORDER BY score DESC")Page<GameRecord> findTopScoresByDifficulty(String difficulty, Pageable pageable);@Query(nativeQuery = true, value = "WITH RankedKills AS ( " +" SELECT *, " +" ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY enemies_killed DESC, score DESC, id DESC) as rn " +" FROM game_records " +" WHERE difficulty = :difficulty " +") " +"SELECT * FROM RankedKills WHERE rn = 1 ORDER BY enemies_killed DESC, score DESC")Page<GameRecord> findTopKillsByDifficulty(String difficulty, Pageable pageable);
}
性能优化技术
1. 数据库优化
- 索引优化: 为频繁查询的字段添加索引
- 分页查询: 避免大数据量全表扫描
- 连接池配置: 优化数据库连接管理
- SQL监控: 使用P6Spy实现SQL性能监控
P6Spy配置示例:
# 指定日志输出模块
modulelist=com.p6spy.engine.logging.P6LogFactory# 自定义日志格式
logMessageFormat=com.p6spy.engine.spy.appender.CustomLineFormat
customLogMessageFormat=执行SQL:%(sqlSingleLine) | 耗时:%(executionTime)ms# 设置P6Spy输出到控制台
appender=com.p6spy.engine.spy.appender.StdoutLogger# 是否开启慢SQL记录
outagedetection=true
# 慢SQL记录标准,单位秒
outagedetectioninterval=2
2. 缓存优化
- 多级缓存: 实现本地缓存和分布式缓存
- 缓存策略: 针对不同数据类型采用不同缓存策略
- 缓存一致性: 通过@CacheEvict确保数据更新时缓存同步
3. API响应优化
- 数据压缩: 启用GZIP压缩减少传输数据量
- DTO优化: 按需返回数据,减少冗余字段
- 异步处理: 非关键操作采用异步处理提高响应速度
安全性设计
1. 密码安全
使用BCrypt加密算法保护用户密码:
@Bean
public PasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();
}
2. API安全
- CORS配置: 限制跨域请求来源
- CSRF防护: 关键操作添加CSRF令牌
- 请求限流: 防止暴力攻击和DoS攻击
3. 数据安全
- 参数验证: 所有输入参数严格验证
- SQL注入防护: 使用参数化查询
- 敏感数据脱敏: 日志和响应中隐藏敏感信息
可扩展性设计
1. 模块化设计
系统按功能划分为多个独立模块,便于扩展:
- 用户认证模块
- 游戏记录模块
- 排行榜模块
- 管理员模块
2. 接口设计
采用RESTful API设计原则,便于集成和扩展:
- 资源明确的URL设计
- 合理使用HTTP方法
- 统一的响应格式
- 版本控制机制
3. 配置外部化
关键配置通过配置文件外部化,便于环境切换:
spring:datasource:url: jdbc:p6spy:mysql://localhost:3306/aircraftwar?useSSL=false&serverTimezone=UTCusername: rootpassword: ******jpa:hibernate:ddl-auto: updatejwt:secret: 5367566B59703373367639792F423F4528482B4D6251655468576D5A71347437expiration: 86400000 # 24小时
部署说明
mysql版本需要8.0以上版本
前端需要安装好nodejs
- 前端部署(端口3000)
# 安装依赖
npm install
# 启动服务
npm start
- 后端部署(端口8880)
# 导入数据库脚本
source init.sql
# 修改数据库配置
vim application.yml
# 启动Spring Boot应用
mvn spring-boot:run
源码获取
https://download.csdn.net/download/Pte_moon/90491980?spm=1001.2014.3001.5503
致谢
再次感谢所有支持和关注本项目的朋友们!你们的支持是我持续更新的动力。也欢迎大家在评论区留言,分享你的想法和建议。让我们一起把这个项目做得更好!
结语
精心打造,只为分享。若这个全栈项目对你有所启发或帮助,请赐予一个赞👍与收藏⭐。每一次支持都是对创作者最好的鼓励,也是促使我不断优化迭代的关键动力。
也欢迎大家关注我,后续会持续分享更多有趣的项目!🌹🌹🌹