3 Commits

  1. 302
      李柏霖学习笔记/4.4.md

302
李柏霖学习笔记/4.4.md

@ -0,0 +1,302 @@
练手项目:java地牢
dungeon-boot/
├── src/
│ ├── main/
│ │ ├── java/
│ │ │ └── com/dungeon/
│ │ │ ├── DungeonApplication.java // 项目启动类
│ │ │ ├── common/ // 公共配置与工具
│ │ │ │ ├── config/ // MyBatis-Plus/Redis 配置
│ │ │ │ ├── exception/ // 自定义异常(如:玩家死亡异常)
│ │ │ │ └── result/ // 统一接口返回对象 (Result<T>)
│ │ │ ├── controller/ // API 控制层 (与前端交互)
│ │ │ │ ├── PlayerController.java
│ │ │ │ └── GameController.java
│ │ │ ├── entity/ // 数据库映射实体 (POJO)
│ │ │ │ ├── Player.java
│ │ │ │ ├── Room.java
│ │ │ │ └── Monster.java
│ │ │ ├── mapper/ // MyBatis-Plus Mapper 接口
│ │ │ │ ├── PlayerMapper.java
│ │ │ │ └── RoomMapper.java
│ │ │ └── service/ // 核心业务逻辑层
│ │ │ ├── PlayerService.java // 玩家属性、升级逻辑
│ │ │ ├── MapService.java // 移动、房间探索逻辑
│ │ │ └── BattleService.java // 战斗计算逻辑
│ │ └── resources/
│ │ ├── application.yml // 数据库连接与游戏全局配置
│ └── test/ // 单元测试
└── pom.xml // 项目依赖管理
controller
```java
package com.example.demo01.controller;
import com.example.demo01.common.result.Result;
import com.example.demo01.entity.Player;
import com.example.demo01.entity.Room;
import com.example.demo01.service.BattleService;
import com.example.demo01.service.MapService;
import com.example.demo01.service.PlayerService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api/game")
public class GameController {
@Autowired
private PlayerService playerService;
@Autowired
private MapService mapService;
@Autowired
private BattleService battleService;
@PostMapping("/move")
public Result<Room> move(@RequestBody MoveRequest request) {
// 1. 获取玩家信息
Player player = playerService.getPlayerStatus(request.getPlayerId());
if (player == null) return Result.error("玩家不存在");
// 2. 调用地图服务判断是否可以移动
Room nextRoom = mapService.move(player.getCurrentRoomId(), request.getDirection());
if (nextRoom != null) {
// 3. 移动成功,更新玩家所在的房间ID
playerService.moveToRoom(player.getId(), nextRoom.getId());
// 返回新房间的信息,让前端显示描述文字
return Result.success(nextRoom);
} else {
return Result.error("哎呀!你撞到了墙上,那里没有路。");
}
}
@PostMapping("/attack")
public Result<BattleResult> doAttack(@RequestParam Long playerId, @RequestParam Long monsterId) {
BattleResult result = battleService.attack(playerId, monsterId);
return Result.success(result);
}
}
```
```
@Data
public class MoveRequest {
/**
* 正在操作的玩家 ID
*/
private Long playerId;
/**
* 移动方向:north, south, east, west
*/
private String direction;
}
```
```
@RestController
@RequestMapping("/api/player")
public class PlayerController {
@Autowired
private PlayerService playerService;
// 获取玩家当前面板状态:GET /api/player/status?id=1
@GetMapping("/status")
public Result<Player> getStatus(@RequestParam Long id) {
Player player = playerService.getPlayerStatus(id);
if (player == null) {
return Result.error("未找到该角色");
}
return Result.success(player);
}
}
```
service
```
package com.example.demo01.service.impl;
import com.example.demo01.controller.BattleResult;
import com.example.demo01.entity.Monster;
import com.example.demo01.entity.Player;
import com.example.demo01.mapper.MonsterMapper;
import com.example.demo01.mapper.PlayerMapper;
import com.example.demo01.service.BattleService;
import com.example.demo01.service.PlayerService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class BattleServiceImpl implements BattleService {
@Autowired
private PlayerMapper playerMapper;
@Autowired
private MonsterMapper monsterMapper;
@Autowired
private PlayerService playerService;
@Override
@Transactional
public BattleResult attack(Long playerId, Long monsterId) {
Player player = playerMapper.selectById(playerId);
Monster monster = monsterMapper.selectById(monsterId);
StringBuilder log = new StringBuilder();
// 1. 玩家攻击怪物
// 伤害公式:攻击力 - 防御力(最小为1)
int damageToMonster = Math.max(1, player.getAtk() - monster.getDef());
monster.setHp(Math.max(0, monster.getHp() - damageToMonster));
log.append(String.format("你攻击了 %s,造成了 %d 点伤害。 ", monster.getName(), damageToMonster));
// 2. 检查怪物是否死亡
if (!monster.isAlive()) {
log.append(String.format("%s 倒下了!你获得了 %d 经验。", monster.getName(), monster.getExpReward()));
// 结算奖励
playerService.addRewards(playerId, monster.getExpReward(), monster.getGoldReward());
// 从房间移除怪物(可选逻辑:更新Room表或者标记Monster已死)
monsterMapper.deleteById(monsterId);
return BattleResult.builder()
.log(log.toString()).monsterHp(0).playerHp(player.getHp())
.monsterDead(true).rewardsExp(monster.getExpReward()).build();
}
// 3. 怪物反击(如果还没死)
int damageToPlayer = Math.max(1, monster.getAtk() - 5); // 假设玩家基础防御5
player.setHp(Math.max(0, player.getHp() - damageToPlayer));
playerMapper.updateById(player); // 更新玩家血量
monsterMapper.updateById(monster); // 更新怪物血量
log.append(String.format("%s 发起反击,你受到了 %d 点伤害。", monster.getName(), damageToPlayer));
return BattleResult.builder()
.log(log.toString())
.playerHp(player.getHp())
.monsterHp(monster.getHp())
.playerDead(player.getHp() <= 0)
.build();
}
}
```
```
package com.example.demo01.service.impl;
import com.example.demo01.entity.Room;
import com.example.demo01.mapper.RoomMapper;
import com.example.demo01.service.MapService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class MapServiceImpl implements MapService {
@Autowired
private RoomMapper roomMapper;
@Override
public Room move(Long currentRoomId, String direction) {
// 1. 先找到玩家所在的当前房间
Room currentRoom = roomMapper.selectById(currentRoomId);
if (currentRoom == null) return null;
// 2. 根据方向获取目标房间的 ID
Long nextRoomId = null;
switch (direction.toLowerCase()) {
case "north": nextRoomId = currentRoom.getNorthRoomId(); break;
case "south": nextRoomId = currentRoom.getSouthRoomId(); break;
case "east": nextRoomId = currentRoom.getEastRoomId(); break;
case "west": nextRoomId = currentRoom.getWestRoomId(); break;
}
// 3. 如果 ID 为空,说明那边是墙
if (nextRoomId == null) return null;
// 4. 返回目标房间的完整信息
return roomMapper.selectById(nextRoomId);
}
@Override
public Room getRoomById(Long roomId) {
return roomMapper.selectById(roomId);
}
}
```
```
package com.example.demo01.service.impl;
import com.example.demo01.entity.Player;
import com.example.demo01.mapper.PlayerMapper;
import com.example.demo01.service.PlayerService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class PlayerServiceImpl implements PlayerService {
@Autowired
private PlayerMapper playerMapper;
@Override
public Player getPlayerStatus(Long playerId) {
return playerMapper.selectById(playerId);
}
@Override
@Transactional // 涉及数据库修改,建议开启事务
public boolean moveToRoom(Long playerId, Long newRoomId) {
Player player = playerMapper.selectById(playerId);
if (player == null) return false;
player.setCurrentRoomId(newRoomId);
return playerMapper.updateById(player) > 0;
}
@Override
public void takeDamage(Long playerId, Integer damage) {
Player player = playerMapper.selectById(playerId);
if (player != null) {
// 计算扣血后的 HP,确保不小于 0
int newHp = Math.max(0, player.getHp() - damage);
player.setHp(newHp);
playerMapper.updateById(player);
if (newHp == 0) {
// 这里可以触发死亡逻辑,比如清空存档或传回出生点
System.out.println("玩家 " + player.getName() + " 已阵亡!");
}
}
}
@Override
public void addRewards(Long playerId, Integer exp, Integer gold) {
Player player = playerMapper.selectById(playerId);
if (player != null) {
player.setExp(player.getExp() + exp);
// 简单的升级逻辑:每 100 经验升一级
if (player.getExp() >= player.getLevel() * 100) {
player.setLevel(player.getLevel() + 1);
player.setAtk(player.getAtk() + 5); // 升级加攻击
player.setHp(player.getMaxHp()); // 升级回满血
}
playerMapper.updateById(player);
}
}
}
```
Loading…
Cancel
Save