GameSceneLocal.ts 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  1. import { _decorator, Component, Node } from "cc";
  2. import { GameCamera } from "./GameCamera";
  3. import { Material } from "cc";
  4. import { GameEvent, GameMgr } from "../../module_basic/scripts/GameMgr";
  5. import { UITransform } from "cc";
  6. import { size } from "cc";
  7. import { Sprite } from "cc";
  8. import { Vec2 } from "cc";
  9. import { renderer } from "cc";
  10. import {
  11. IFood,
  12. IGameData,
  13. IGamePlayer,
  14. } from "../../module_basic/shared/protocols/public/game/GameTypeDef";
  15. import { instantiate } from "cc";
  16. import { GameResMgr } from "./GameResMgr";
  17. import { Cell } from "./Cell";
  18. import { UserMgr } from "../../module_basic/scripts/UserMgr";
  19. import { PlayerMovement2D } from "./PlayerMovement2D";
  20. import { PlayerController } from "./PlayerController";
  21. import { UIGameJoystick } from "../ui_game_joystick/UIGameJoystick";
  22. import { UIGameHUD } from "../ui_game_hud/UIGameHUD";
  23. import { UIGameRank } from "../ui_game_rank/UIGameRank";
  24. import { RoomMgr } from "../../module_basic/scripts/RoomMgr";
  25. import { IRoomData, IUserData } from "../../module_basic/shared/types/RoomData";
  26. import { UserInfo } from "../../module_basic/shared/types/UserInfo";
  27. import { color } from "cc";
  28. import { GameLocalData } from "./GameLocalData";
  29. import { director } from "cc";
  30. import { SceneUtil } from "../../core_tgx/base/SceneUtils";
  31. import { ModuleDef } from "../../scripts/ModuleDef";
  32. import { SceneDef } from "../../scripts/SceneDef";
  33. import { GameSceneUtil } from "../../module_basic/scripts/GameSceneUtil";
  34. import { UIGameResult } from "../../module_ball/ui_game/UIGameResult";
  35. const { ccclass, property } = _decorator;
  36. @ccclass("GameLocalScene")
  37. export class GameLocalScene extends Component {
  38. @property(Node) mapRoot: Node;
  39. @property(Node) background: Node;
  40. @property(Node) objectsRoot: Node;
  41. @property(GameCamera) gameCamera: GameCamera;
  42. @property(Material) mapMaterial: Material;
  43. public static MAP_WIDTH = 10000;
  44. public static MAP_HEIGHT = 10000;
  45. // private _cellMap: { [key: number]: Cell } = {};
  46. private _foodMap: { [key: number]: Node } = {};
  47. private _foodInfoMap: { [key: number]: IFood } = {};
  48. private _foodPool: Node[] = [];
  49. private _backgroundPass: renderer.Pass;
  50. private _handleEdgeFactor: number;
  51. private _selfPlayers: Cell[] = [];
  52. start() {
  53. let localUser: UserInfo = {
  54. uid: "local-me-uid-xxx-001",
  55. };
  56. UserMgr.inst.setUserInfo(localUser);
  57. let roomData: IRoomData = GameLocalData.ins.createLocalRoomData(
  58. localUser.uid
  59. );
  60. RoomMgr.inst.onNet_RoomDataSyncPush({
  61. data: roomData,
  62. });
  63. tgx.UIMgr.inst.showUI(UIGameJoystick);
  64. tgx.UIMgr.inst.showUI(UIGameHUD);
  65. // tgx.UIMgr.inst.showUI(UIGameRank);
  66. let selfPlayerInfo = GameLocalData.ins.mockIGamePlayer();
  67. let gameData = GameLocalData.ins.createLocalGameData(selfPlayerInfo);
  68. GameMgr.inst.localMode(gameData);
  69. GameMgr.inst.onNet_PlayerComesPush({
  70. player: selfPlayerInfo,
  71. });
  72. this.initBackground();
  73. this.createCell(selfPlayerInfo);
  74. let self = this;
  75. let intIn = setInterval(() => {
  76. if (
  77. !GameMgr.inst.gameData ||
  78. GameMgr.inst.gameData.gameState == "gameover"
  79. ) {
  80. clearInterval(intIn);
  81. return;
  82. }
  83. self.createFoods();
  84. }, 1000);
  85. director.on(GameEvent.GAME_EXIT, this.onGameExit, this);
  86. director.on(GameEvent.LOCAL_PLAYER_SPAWN, this.onLocalPlayerSpawn, this);
  87. }
  88. private _lastSpawnTime = 0;
  89. private onLocalPlayerSpawn() {
  90. if (Date.now() - this._lastSpawnTime < 500) {
  91. return;
  92. }
  93. this._lastSpawnTime = Date.now();
  94. let waitCreateData = [];
  95. for (let i = 0; i < this._selfPlayers.length; i++) {
  96. console.log(">>>> i", i, this._selfPlayers.length);
  97. let oneSelfCell = this._selfPlayers[i];
  98. if (oneSelfCell.player.radius > 50) {
  99. oneSelfCell.player.radius = Math.floor(oneSelfCell.player.radius / 2);
  100. oneSelfCell.setRadius(oneSelfCell.player.radius);
  101. let newInfo = JSON.parse(JSON.stringify(oneSelfCell.player));
  102. newInfo.state = "moving";
  103. let moveDistance = oneSelfCell.player.radius * 3;
  104. let move2D = oneSelfCell.getComponent(PlayerMovement2D);
  105. let moveDir = move2D.moveDir;
  106. let newPos = new Vec2(
  107. oneSelfCell.node.getWorldPosition().x + moveDistance * moveDir.x,
  108. oneSelfCell.node.getWorldPosition().y + moveDistance * moveDir.y
  109. );
  110. newInfo.transform[0] = newPos.x;
  111. newInfo.transform[1] = newPos.y;
  112. newInfo.transform[3] = move2D.rotDegree;
  113. waitCreateData.push(newInfo);
  114. }
  115. }
  116. for (let i = 0; i < waitCreateData.length; i++) {
  117. this.createCell(waitCreateData[i]);
  118. }
  119. }
  120. onGameExit() {
  121. tgx.UIMgr.inst.closeAll();
  122. GameMgr.inst.localGameOver();
  123. UIGameResult.show();
  124. }
  125. protected onDestroy(): void {
  126. director.off(GameEvent.GAME_EXIT, this.onGameExit, this);
  127. }
  128. initBackground() {
  129. const extBorder = 4000;
  130. let gameData = GameMgr.inst.gameData;
  131. const realWidth = gameData.mapWidth + extBorder;
  132. const realHeight = gameData.mapHeight + extBorder;
  133. this.background.getComponent(UITransform).contentSize = size(
  134. realWidth,
  135. realHeight
  136. );
  137. //@en initialize the material parameters of the background.
  138. //@zh 初始化地图背景材质
  139. const halfWidth = gameData.mapWidth / 2;
  140. const halfHeight = gameData.mapHeight / 2;
  141. let spriteFrame = this.background.getComponent(Sprite).spriteFrame;
  142. let uvScale = new Vec2();
  143. let scaler = 0.6;
  144. //@en use uv scale to adapt the map size
  145. //@zh 使用uv缩放来适配地图大小
  146. uvScale.x = (realWidth / spriteFrame.width) * scaler;
  147. uvScale.y = (realHeight / spriteFrame.height) * scaler;
  148. this.mapMaterial.setProperty("uvScale", uvScale);
  149. this.mapMaterial.setProperty(
  150. "halfMapSize",
  151. new Vec2(halfWidth, halfHeight)
  152. );
  153. //this.mapMaterial.setProperty('edgeColor', new Vec4(1.0,0.0,0.0,1.0));
  154. //this.mapMaterial.setProperty('fadeOutRange', 1000.0);
  155. //@en save the material parameter handle for efficient setting of material parameters in update
  156. //@zh 保存材质参数相关句柄,方便在update中高效率地设置材质参数
  157. this._backgroundPass = this.mapMaterial.passes[0];
  158. this._handleEdgeFactor = this._backgroundPass.getHandle("edgeFactor");
  159. }
  160. tmpColor = color();
  161. createFoods() {
  162. let createCount = 1000 - Object.keys(this._foodMap).length;
  163. if (createCount <= 0) {
  164. return;
  165. }
  166. if (createCount > 100) {
  167. createCount = 100;
  168. }
  169. for (let i = 0; i < createCount; i++) {
  170. this.createFood(GameLocalData.ins.newFoodData());
  171. }
  172. }
  173. protected update(dt: number): void {
  174. let value = Math.sin(Date.now() / 50 / Math.PI);
  175. value = value * 0.5 + 0.5;
  176. this._backgroundPass.setUniform(this._handleEdgeFactor, value);
  177. this.checkFoodAndEat();
  178. this.mergeLogic();
  179. }
  180. mergeLogic() {
  181. let mergeInfo = this.checkCanMerge();
  182. if (mergeInfo) {
  183. let left = mergeInfo.left;
  184. let right = mergeInfo.right;
  185. left.setRadius(left.player.radius + right.player.radius);
  186. let index = this._selfPlayers.indexOf(right);
  187. if (this.gameCamera.target === right) {
  188. this.gameCamera.target = left;
  189. }
  190. right.node.destroy();
  191. this._selfPlayers.splice(index, 1);
  192. }
  193. }
  194. checkCanMerge(): {
  195. left: Cell;
  196. right: Cell;
  197. } {
  198. let m1 = null;
  199. let m2 = null;
  200. for (let i = 0; i < this._selfPlayers.length; i++) {
  201. let left = this._selfPlayers[i];
  202. for (let j = i + 1; j < this._selfPlayers.length; j++) {
  203. let right = this._selfPlayers[j];
  204. if (left === right) {
  205. continue;
  206. }
  207. let distance = Vec2.distance(
  208. left.node.getWorldPosition(),
  209. right.node.getWorldPosition()
  210. );
  211. let ddd = left.player.radius + right.player.radius;
  212. if (distance < ddd) {
  213. m1 = left;
  214. m2 = right;
  215. if (m1.player.radius > m2.player.radius) {
  216. m1 = right;
  217. m2 = left;
  218. }
  219. return {
  220. left: m1,
  221. right: m2,
  222. };
  223. }
  224. }
  225. }
  226. }
  227. async createCell(player: IGamePlayer) {
  228. let newCell = instantiate(GameResMgr.inst.cellPrefab);
  229. this.objectsRoot.addChild(newCell);
  230. newCell.setWorldPosition(
  231. player.transform[0],
  232. player.transform[1],
  233. player.transform[2]
  234. );
  235. let cellComp = newCell.getComponent(Cell);
  236. cellComp.setPlayer(player);
  237. // this._cellMap[player.playerId] = cellComp;
  238. if (player.uid == UserMgr.inst.uid) {
  239. this._selfPlayers.push(cellComp);
  240. let mv2d = newCell.addComponent(PlayerMovement2D);
  241. mv2d.needRotation = false;
  242. mv2d.moveSpeed = player.speed;
  243. mv2d.setPrecision(10);
  244. if (this._selfPlayers.length == 1) {
  245. this.gameCamera.target = cellComp;
  246. }
  247. newCell.addComponent(PlayerController);
  248. if (player.state == "moving") {
  249. mv2d.onMovement(player.transform[3], 1.0);
  250. }
  251. }
  252. }
  253. async createFood(fd: IFood) {
  254. // console.log("createFood", fd);
  255. let newFood = this._foodPool.pop();
  256. if (!newFood) {
  257. newFood = new Node();
  258. newFood.addComponent(Sprite);
  259. }
  260. this._foodInfoMap[fd.id] = fd;
  261. this.mapRoot.addChild(newFood);
  262. newFood.name = "food_" + fd.id;
  263. this._foodMap[fd.id] = newFood;
  264. let foodSprites = GameResMgr.inst.foodSprites;
  265. let sprf = foodSprites[fd.type % foodSprites.length];
  266. let spr = newFood.getComponent(Sprite);
  267. spr.spriteFrame = sprf;
  268. this.tmpColor.fromHEX(fd.color.toString(16));
  269. spr.color = this.tmpColor;
  270. let scale = (fd.radius * 2) / sprf.rect.width;
  271. newFood.setScale(scale, scale, 1.0);
  272. newFood.setRotationFromEuler(0, 0, Math.random() * 360);
  273. newFood.setWorldPosition(fd.x, fd.y, 0);
  274. }
  275. checkFoodAndEat() {
  276. if (this._selfPlayers.length == 0) {
  277. return;
  278. }
  279. for (let foodId in this._foodMap) {
  280. let foodNode = this._foodMap[foodId];
  281. let foodPos = foodNode.getWorldPosition();
  282. for (let i = 0; i < this._selfPlayers.length; i++) {
  283. let oneSelfCell = this._selfPlayers[i];
  284. let playerPos = oneSelfCell.node.getWorldPosition();
  285. let distance = Vec2.distance(foodPos, playerPos);
  286. let ddd = oneSelfCell.player.radius / 1.5;
  287. let foodInfo = this._foodInfoMap[foodId];
  288. if (foodInfo && distance < ddd) {
  289. delete this._foodMap[foodId];
  290. delete this._foodInfoMap[foodId];
  291. foodNode.removeFromParent();
  292. this._foodPool.push(foodNode);
  293. let oneAdd = foodInfo.radius / 10;
  294. oneSelfCell.setRadius(oneSelfCell.player.radius + oneAdd);
  295. }
  296. }
  297. }
  298. }
  299. }