|
@@ -0,0 +1,258 @@
|
|
|
+import { Injectable } from '@nestjs/common';
|
|
|
+import { CacheService } from 'src/cache/cache.service';
|
|
|
+
|
|
|
+@Injectable()
|
|
|
+export class JoystickService {
|
|
|
+ constructor(private cacheService: CacheService) {}
|
|
|
+ private Actions = {
|
|
|
+ Clicking: 1,
|
|
|
+ Rotation: 1014,
|
|
|
+ Joystick: 15,
|
|
|
+ };
|
|
|
+ private users = {};
|
|
|
+ private reply =
|
|
|
+ {
|
|
|
+ "traceIds": [],
|
|
|
+ "vehicle": null,
|
|
|
+ "newUserStates": [{
|
|
|
+ "userId": "dcff36ae4fc1d",
|
|
|
+ "playerState": {
|
|
|
+ "roomTypeId": "",
|
|
|
+ "person": 0,
|
|
|
+ "avatarId": "",
|
|
|
+ "skinId": "",
|
|
|
+ "roomId": "",
|
|
|
+ "isHost": false,
|
|
|
+ "isFollowHost": false,
|
|
|
+ "skinDataVersion": "",
|
|
|
+ "avatarComponents": "",
|
|
|
+ "nickName": "",
|
|
|
+ "movingMode": 0,
|
|
|
+ "attitude": "",
|
|
|
+ "areaName": "",
|
|
|
+ "pathName": "",
|
|
|
+ "pathId": "",
|
|
|
+ "avatarSize": 1,
|
|
|
+ "extra": "",
|
|
|
+ "prioritySync": false,
|
|
|
+ "player": {
|
|
|
+ "position": {
|
|
|
+ "x": -421.30057,
|
|
|
+ "y": -1434.4198,
|
|
|
+ "z": -34
|
|
|
+ },
|
|
|
+ "angle": {
|
|
|
+ "pitch": 0,
|
|
|
+ "yaw": 47,
|
|
|
+ "roll": 0
|
|
|
+ }
|
|
|
+ },
|
|
|
+ "camera": {
|
|
|
+ "position": {
|
|
|
+ "x": -436.2,
|
|
|
+ "y": -1408.8,
|
|
|
+ "z": 130.7
|
|
|
+ },
|
|
|
+ "angle": {
|
|
|
+ "pitch": 0,
|
|
|
+ "yaw": 315,
|
|
|
+ "roll": 0
|
|
|
+ }
|
|
|
+ },
|
|
|
+ "cameraCenter": {
|
|
|
+ "x": -400,
|
|
|
+ "y": -1450,
|
|
|
+ "z": 10.610336
|
|
|
+ }
|
|
|
+ },
|
|
|
+ "renderInfo": {
|
|
|
+ "renderType": 0,
|
|
|
+ "videoFrame": null,
|
|
|
+ "cameraStateType": 3,
|
|
|
+ "isMoving": 1,
|
|
|
+ "needIfr": 0,
|
|
|
+ "isVideo": 0,
|
|
|
+ "stillFrame": 0,
|
|
|
+ "isRotating": 0,
|
|
|
+ "isFollowing": 0,
|
|
|
+ "clientPanoTitlesBitmap": [],
|
|
|
+ "clientPanoTreceId": "",
|
|
|
+ "prefetchVideoId": "",
|
|
|
+ "noMedia": false
|
|
|
+ },
|
|
|
+ "event": null,
|
|
|
+ "relation": 1
|
|
|
+ }],
|
|
|
+ "actionResponses": [{
|
|
|
+ "actionType": 15,
|
|
|
+ "pointType": 100,
|
|
|
+ "extra": "",
|
|
|
+ "traceId": "",
|
|
|
+ "packetId": "",
|
|
|
+ "nps": [],
|
|
|
+ "peopleNum": 0,
|
|
|
+ "zoneId": "",
|
|
|
+ "echoMsg": "",
|
|
|
+ "reserveDetail": null,
|
|
|
+ "userWithAvatarList": [],
|
|
|
+ "newUserStates": [],
|
|
|
+ "code": 0,
|
|
|
+ "msg": ""
|
|
|
+ }],
|
|
|
+ "getStateType": 0,
|
|
|
+ "code": 0,
|
|
|
+ "msg": "OK"
|
|
|
+ };
|
|
|
+
|
|
|
+ async joystick(actionRequest) {
|
|
|
+ try {
|
|
|
+ const userId = actionRequest['user_id'];
|
|
|
+ const traceId = actionRequest['trace_id'];
|
|
|
+ const dir_action = actionRequest['dir_action'];
|
|
|
+ const user = this.users[userId];
|
|
|
+
|
|
|
+ //只是移动人物
|
|
|
+ if(dir_action.speed_level<7){
|
|
|
+ user.player.angle.yaw = dir_action.move_angle;
|
|
|
+ this.reply['newUserStates'][0]['userId'] = userId;
|
|
|
+ this.reply['newUserStates'][0].playerState.player.position = user.player.position;
|
|
|
+ this.reply['newUserStates'][0].playerState.player.angle.yaw = dir_action.move_angle;
|
|
|
+
|
|
|
+ this.reply['newUserStates'][0].playerState.camera.position = user.camera.position;
|
|
|
+ this.reply['newUserStates'][0].playerState.camera.angle = user.camera.angle;
|
|
|
+
|
|
|
+ this.reply['newUserStates'][0].playerState.cameraCenter = user.camera.position;
|
|
|
+
|
|
|
+ this.reply['actionResponses'][0].traceId = traceId;
|
|
|
+
|
|
|
+ return this.reply;
|
|
|
+ }
|
|
|
+ //选择过渡
|
|
|
+ else{
|
|
|
+ const breakPointId = user.breakPointId;
|
|
|
+ //先矫正
|
|
|
+ //去redis里找邻居点
|
|
|
+ //key:breakpoints:app_id:10016:break_point_id:1
|
|
|
+ //value:contact,position
|
|
|
+ const contact = [];
|
|
|
+ let chooseBreakPointId = null;
|
|
|
+ let minOffsetAngle = null;
|
|
|
+ let neighPoint = null
|
|
|
+ let angle = 0;
|
|
|
+ for(let i=0;i<contact.length;++i){
|
|
|
+ neighPoint = null //通过contact[i],去redis里找
|
|
|
+ angle = 0; //通过user.player.position;neighPoint.position获得角度
|
|
|
+ if(Math.abs(angle - dir_action.move_angle)<45&&(minOffsetAngle == null||Math.abs(angle - dir_action.move_angle)<minOffsetAngle)){
|
|
|
+ chooseBreakPointId = contact[i];
|
|
|
+ minOffsetAngle = Math.abs(angle - dir_action.move_angle);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if(chooseBreakPointId == null){
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ else{
|
|
|
+ //人物矫正
|
|
|
+ user.player.angle.yaw = angle;
|
|
|
+
|
|
|
+ //相机纠正
|
|
|
+ let replys = [];
|
|
|
+ let traceIds = [];
|
|
|
+ traceIds.push(traceId);
|
|
|
+
|
|
|
+ let checkReplys = [];
|
|
|
+ angle = user.camera.angle.yaw%45; //纠正需要
|
|
|
+ for(let i=0;i<angle;++i){
|
|
|
+ //let reply = rotateService.rotateForAngle(userId,(angle+i)%359);
|
|
|
+ //reply.traceIds = [];
|
|
|
+ //reply.traceIds.push(traceId);
|
|
|
+ //let actionResponse = rotateService.createActionResponse(actionType,trace_id);
|
|
|
+ //reply.actionResponses = [];
|
|
|
+ //reply.actionResponses.push(actionResponse);
|
|
|
+ //checkReplys.push(reply);
|
|
|
+ }
|
|
|
+ replys.push(checkReplys);
|
|
|
+
|
|
|
+ //过渡
|
|
|
+ //读redis里的数据,按照frame_index的大小排序
|
|
|
+ //key:moveframe:app_id+breakPointId+chooseBreakPointId+index
|
|
|
+ //value:frame_index,file_name,camera_position,camera_angle
|
|
|
+ let moveFrames = []; //value赋值
|
|
|
+ //MoveService.createCacheReplys(moveFrames,traceId,userId,user.player.position,neighPoint.position)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ const path = [100,99,97]; //需要计算路径
|
|
|
+ const angle = user.camera.angle.yaw%45; //纠正需要
|
|
|
+ const index = Math.round(user.camera.angle.yaw/45); //过渡需要
|
|
|
+
|
|
|
+ let replys = [];
|
|
|
+ let traceIds = [];
|
|
|
+ traceIds.push(traceId);
|
|
|
+
|
|
|
+ //纠正,旋转传到缓存里
|
|
|
+ let checkReplys = [];
|
|
|
+ for(let i=0;i<angle;++i){
|
|
|
+ //let reply = rotateService.rotateForAngle(userId,(angle+i)%359);
|
|
|
+ //checkReplys.push(reply);
|
|
|
+ }
|
|
|
+ replys.push(checkReplys);
|
|
|
+
|
|
|
+ //过渡传到缓存里
|
|
|
+ this.reply.traceIds = traceIds;
|
|
|
+ this.reply['newUserStates'][0].userId = userId;
|
|
|
+ this.reply['actionResponses'][0].traceId = traceId;
|
|
|
+
|
|
|
+ for(let i=0;i<path.length-1;++i){
|
|
|
+ let pathReplys = [];
|
|
|
+ let start_break_point_id = path[i];
|
|
|
+ let end_break_point_id = path[i+1];
|
|
|
+ //读redis里的数据,按照frame_index的大小排序
|
|
|
+ //key:moveframe:app_id+start_break_point_id+end_break_point_id+index
|
|
|
+ //value:frame_index,file_name,camera_position,camera_angle
|
|
|
+ let moveFrames = []; //value赋值
|
|
|
+
|
|
|
+ //读redis里的数据
|
|
|
+ //key:breakpoints:app_id:10016:break_point_id:112
|
|
|
+ let startBreakPoint,endBreakPoint; //value赋值
|
|
|
+ pathReplys = this.createCacheReplys(moveFrames,traceId,userId,startBreakPoint.position,endBreakPoint.position);
|
|
|
+ replys.push(pathReplys);
|
|
|
+ }
|
|
|
+
|
|
|
+ return replys;
|
|
|
+
|
|
|
+ } catch (error) {
|
|
|
+ console.log('MoveService', error);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ createCacheReplys(moveFrames,traceId,userId,startPosition,endPosition){
|
|
|
+
|
|
|
+ let replys = [];
|
|
|
+ for(let i = 1;i<moveFrames.length;++i){
|
|
|
+ let moveFrame = moveFrames[i];
|
|
|
+
|
|
|
+ let reply = JSON.parse(JSON.stringify(this.reply));
|
|
|
+ reply.traceIds.push(traceId);
|
|
|
+ reply['newUserStates'][0].userId = userId;
|
|
|
+
|
|
|
+ reply['newUserStates'][0].playerState.player.position = {
|
|
|
+ x:(endPosition.x - startPosition.x)/moveFrames.length*i,
|
|
|
+ y:(endPosition.y - startPosition.y)/moveFrames.length*i,
|
|
|
+ z:(endPosition.z - startPosition.z)/moveFrames.length*i
|
|
|
+ }
|
|
|
+ reply['newUserStates'][0].playerState.player.angle = this.users[userId].player.angle;
|
|
|
+
|
|
|
+ reply['newUserStates'][0].playerState.camera.position = moveFrame.camera_position;
|
|
|
+ reply['newUserStates'][0].playerState.camera.angle = moveFrame.camera_angle;
|
|
|
+ reply['newUserStates'][0].playerState.cameraCenter = reply['newUserStates'][0].playerState.player.position;
|
|
|
+
|
|
|
+ reply['actionResponses'][0].traceId = traceId;
|
|
|
+ replys.push(reply);
|
|
|
+ }
|
|
|
+ return replys;
|
|
|
+
|
|
|
+ }
|
|
|
+}
|