import { Injectable } from '@nestjs/common'; import { CacheService } from 'src/cache/cache.service'; import { RotateService } from 'src/rotate/rotate.service'; // import { SceneService } from 'src/scene/scene.service'; @Injectable() export class MoveService { constructor( private cacheService: CacheService, private rotateService: RotateService, ) {} private Actions = { Clicking: 1, Rotation: 1014, Joystick: 15, }; public users = this.rotateService.users; private reply = { traceIds: [], vehicle: null, mediaSrc: 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: -700, y: 0, z: 0 }, angle: { pitch: 0, yaw: 0, roll: 0, }, }, camera: { position: { x: -1145, y: 0, z: 160 }, angle: { pitch: 0, yaw: 0, roll: 0, }, }, cameraCenter: { x: -700, y: 0, z: 0 }, }, 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: 1, pointType: 100, extra: '', traceId: '', packetId: '', nps: [], peopleNum: 0, zoneId: '', echoMsg: '', reserveDetail: null, userWithAvatarList: [], newUserStates: [], code: 0, msg: '', }, ], getStateType: 0, code: 0, msg: 'OK', }; init(app_id, userId) { const user = { appId: null, userId: null, breakPointId: null, roomId: null, player: { position: { x: -700, y: 0, z: 0 }, angle: { pitch: 0, yaw: 0, roll: 0, }, }, camera: { position: { x: -1145, y: 0, z: 160 }, angle: { pitch: 0, yaw: 0, roll: 0, }, }, rotateInfo: { frameIndex: 0, horizontal_move: 0, mediaSrc: null, }, moveInfo: {}, // traceIds: [], // actionResponses:[] }; user.appId = app_id; user.userId = userId; user.breakPointId = 100; this.users[userId] = user; } async move(pathArray, actionRequest) { try { const userId = actionRequest['user_id']; const traceId = actionRequest['trace_id']; const actionType = actionRequest['action_type']; const user = this.users[userId]; const appId = user.appId; const path = pathArray || [100, 101, 102]; //需要计算路径 const angle = user.camera.angle.yaw % 44; //纠正需要 console.log('矫正前-相机:' + user.camera.angle.yaw); const replys = {}; const traceIds = []; traceIds.push(traceId); //纠正,旋转传到缓存里 const checkReplys = []; // console.log('矫正: ' + angle + ' 度'); for (let i = 0; i < angle; ++i) { // console.warn('矫正一次:' + i); const reply = await this.rotateService.rotateForAngle(userId, 1); // console.warn( // '矫正:' + reply.newUserStates[0].playerState.camera.angle.yaw, // ); reply.traceIds = []; reply.traceIds.push(traceId); const actionResponse = this.rotateService.createActionResponse( actionType, traceId, ); reply.actionResponses = []; reply.actionResponses.push(actionResponse); checkReplys.push(reply); } replys['P' + user.breakPointId + 'T' + user.breakPointId] = checkReplys; //replys.push(checkReplys); //过渡传到缓存里 this.reply.traceIds = traceIds; this.reply['newUserStates'][0].userId = userId; this.reply['actionResponses'][0].traceId = traceId; console.log('矫正后-相机:' + user.camera.angle.yaw); const index = Math.round(user.camera.angle.yaw / 44); //过渡需要 for (let i = 0; i < path.length - 1; ++i) { let pathReplys = []; const start_break_point_id = path[i]; const end_break_point_id = path[i + 1]; //读redis里的数据,按照frame_index的大小排序 const key = 'moveframe:app_id:' + appId + ':start_break_point_id:' + start_break_point_id + ':end_break_point_id:' + end_break_point_id + ':angle:' + index; const moveFramesRes = await this.cacheService.get(key); if (moveFramesRes == null) { return replys; } const moveFrames = JSON.parse(moveFramesRes); //读redis里的数据 const startBreakPointRes = await this.cacheService.get( 'breakpoints:app_id:' + appId + ':break_point_id:' + start_break_point_id, ); const startBreakPoint = JSON.parse(startBreakPointRes); const endBreakPointRes = await this.cacheService.get( 'breakpoints:app_id:' + appId + ':break_point_id:' + end_break_point_id, ); const endBreakPoint = JSON.parse(endBreakPointRes); pathReplys = this.createCacheReplys( moveFrames, traceId, userId, start_break_point_id, startBreakPoint.position, endBreakPoint.position, ); if (i == path.length - 2) { pathReplys[pathReplys.length - 1][ 'newUserStates' ][0].renderInfo.isMoving = 0; } //replys.push(pathReplys); replys['P' + start_break_point_id + 'T' + end_break_point_id] = pathReplys; } return replys; } catch (error) { console.log('MoveService', error); } } createCacheReplys( moveFrames, traceId, userId, breakPointId, startPosition, endPosition, ) { const replys = []; const angle = -1 * this.getAngle( startPosition, { x: startPosition.x + 1, y: startPosition.y, }, endPosition, ); for (let i = 1; i < moveFrames.length; i += 5) { const moveFrame = moveFrames[i]; const reply = JSON.parse(JSON.stringify(this.reply)); reply.traceIds.push(traceId); reply['newUserStates'][0].userId = userId; reply['newUserStates'][0].playerState.player.position = { x: startPosition.x + ((endPosition.x - startPosition.x) / moveFrames.length) * i, y: startPosition.y + ((endPosition.y - startPosition.y) / moveFrames.length) * i, z: startPosition.z + ((endPosition.z - startPosition.z) / moveFrames.length) * i, }; reply['newUserStates'][0].playerState.player.angle.yaw = 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; reply.mediaSrc = '/' + '0000000001' + '/' + breakPointId + '/' + moveFrame.file_name.substring(0, moveFrame.file_name.indexOf('.')) + '/' + moveFrame.file_name + '?m=' + new Date().getTime(); replys.push(reply); } return replys; } //需要通知user,人物和相机走到哪一个呼吸点位了 updateUser(userId, breakPointId, lastReply) { const user = this.users[userId]; user.breakPointId = breakPointId; // debugger; user.player.position = lastReply['newUserStates'][0].playerState.player.position; user.player.angle = lastReply['newUserStates'][0].playerState.player.angle; user.camera.position = lastReply['newUserStates'][0].playerState.camera.position; user.camera.angle = lastReply['newUserStates'][0].playerState.camera.angle; } async getBreakPoints(actionRequest) { const userId = actionRequest['user_id']; const traceId = actionRequest['trace_id']; const actionType = actionRequest['action_type']; const user = this.users[userId]; const appId = user.appId; const breakPointId = user.breakPointId; const reply = { actionType: actionType, pointType: 100, extra: '', traceId: traceId, packetId: '', nps: [], peopleNum: 0, zoneId: '', echoMsg: '', reserveDetail: null, userWithAvatarList: [], newUserStates: [], code: 0, msg: '', }; //const breakPoints = await this.cacheService.get('breakpoints:app_id:'+appId+':break_point_id:'+breakPointId); //获取redis表全部元素,'breakpoints:app_id:'+appId+':break_point_id:'开头的 const keys = await this.cacheService.keys(`breakpoints:app_id:${appId}*`); for (let i = 0; i < keys.length; ++i) { const breakPointRes = await this.cacheService.get(keys[i]); const breakPoint = JSON.parse(breakPointRes); const position = breakPoint.position; reply['nps'].push({ position: position, breakPointId: breakPoint.breakPointId, }); } return reply; } getAngle(point, point1, point2) { const x1 = point1.x - point.x; const y1 = point1.y - point.y; const x2 = point2.x - point.x; const y2 = point2.y - point.y; const dot = x1 * x2 + y1 * y2; const det = x1 * y2 - y1 * x2; const angle = (Math.atan2(det, dot) / Math.PI) * 180; return (angle + 360) % 360; } async stop(traceId, userId, movePointIds, cameraAngle, playerAngle) { const breakPointId = movePointIds.substring(movePointIds.indexOf('-') + 1); const user = this.users[userId]; user.breakPointId = breakPointId; const appId = user.appId; const breakPointRes = await this.cacheService.get( 'breakpoints:app_id:' + appId + ':break_point_id:' + breakPointId, ); const breakPoint = JSON.parse(breakPointRes); user.player.position = breakPoint.position; user.player.angle = playerAngle; const rotateKey = 'rotateframe:app_id:' + appId + ':frame_index:' + cameraAngle.yaw + ':break_point_id:' + breakPointId; const rotateDataRes = await this.cacheService.get(rotateKey); const rotateData = JSON.parse(rotateDataRes); user.camera.position = rotateData.cameraPosition; user.camera.angle = rotateData.cameraAngle; const reply = JSON.parse(JSON.stringify(this.reply)); reply.traceIds.push(traceId); reply['newUserStates'][0].userId = userId; reply['newUserStates'][0].playerState.player.position = breakPoint.position; reply['newUserStates'][0].playerState.player.angle = playerAngle; reply['newUserStates'][0].playerState.camera.position = rotateData.cameraPosition; reply['newUserStates'][0].playerState.camera.angle = rotateData.cameraAngle; reply['newUserStates'][0].playerState.cameraCenter = breakPoint.position; reply['actionResponses'][0].traceId = traceId; reply.mediaSrc = '/' + '0000000001' + '/' + breakPointId + '/' + rotateData.directory + '/' + rotateData.fileName + '?m=' + new Date().getTime(); reply['newUserStates'][0].renderInfo.isMoving = 0; return reply; } async joystick(actionRequest) { try { const userId = actionRequest['user_id']; const traceId = actionRequest['trace_id']; const dir_action = actionRequest['dir_action']; const actionType = actionRequest['action_type']; const user = this.users[userId]; const appId = user.appId; //只是移动人物 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; //先矫正 const breakPointRes = await this.cacheService.get( 'breakpoints:app_id:' + appId + ':break_point_id:' + breakPointId, ); if (breakPointRes == null) { return null; } const breakPoint = JSON.parse(breakPointRes); const contact = breakPoint.contact; let chooseBreakPointId = null; let minOffsetAngle = null; let neighPoint = null; let angle = 0; for (let i = 0; i < contact.length; ++i) { neighPoint = await this.cacheService.get( 'breakpoints:app_id:' + appId + ':break_point_id:' + contact[i], ); //通过contact[i],去redis里找 //通过user.player.position;neighPoint.position获得角度 neighPoint = JSON.parse(neighPoint); angle = this.getAngle( user.player.position, { x: user.player.position.x + 1, y: user.player.position.y }, 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; //相机纠正 const replys = []; const traceIds = []; traceIds.push(traceId); const checkReplys = []; angle = user.camera.angle.yaw % 44; //纠正需要 for (let i = 0; i < angle; ++i) { const reply = await this.rotateService.rotateForAngle(userId, 1); reply.traceIds = []; reply.traceIds.push(traceId); const actionResponse = this.rotateService.createActionResponse( actionType, traceId, ); reply.actionResponses = []; reply.actionResponses.push(actionResponse); checkReplys.push(reply); } replys.push(checkReplys); //过渡 //读redis里的数据,按照frame_index的大小排序 const key = 'moveframe:app_id:' + appId + ':start_break_point_id:' + breakPointId + ':end_break_point_id:' + chooseBreakPointId + ':angle:' + (user.camera.angle.yaw % 44); const moveFramesRes = await this.cacheService.get(key); if (moveFramesRes == null) { return replys; } const moveFrames = JSON.parse(moveFramesRes); //读redis里的数据 const startBreakPointRes = await this.cacheService.get( 'breakpoints:app_id:' + appId + ':break_point_id:' + breakPointId, ); const startBreakPoint = JSON.parse(startBreakPointRes); const endBreakPointRes = await this.cacheService.get( 'breakpoints:app_id:' + appId + ':break_point_id:' + chooseBreakPointId, ); const endBreakPoint = JSON.parse(endBreakPointRes); const pathReplys = this.createCacheReplys( moveFrames, traceId, userId, breakPointId, startBreakPoint.position, endBreakPoint.position, ); replys.push(pathReplys); return replys; } } } catch (error) { console.log('MoveService', error); } } }