Игра Маджонг | Mahjong game
Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

481 linhas
16KB

  1. var ресурсы = [
  2. [БАЗА + "модели/фишка/2019-09-08.osgt", "mod"],
  3. [БАЗА + "текстуры/заглушка.png", "tex.stub"],
  4. [БАЗА + "шейдеры/освещение-изображение.vert", "ver"],
  5. [БАЗА + "шейдеры/освещение-изображение.frag", "fra"],
  6. [БАЗА + "раскладки/X_shaped.layout", "lay"],
  7. [БАЗА + "классы/Раскладка/2019-08-16.js", "Layout"],
  8. [БАЗА + "классы/Фишка/2019-09-07.js", "Tile"],
  9. [БАЗА + "темыФишек/заглушка/2019-09-08.js", "theme.stub"],
  10. ];
  11. мж.начали = new Уведомитель();
  12. мж.начать = function()
  13. {
  14. муром.камера.позиция = [0, -70, 0];
  15. муром.камера.вращение = [90, 0, 0];
  16. мж.сцена = муром.узлы.создатьСферу("sce", 0);
  17. мж.сцена.вращение = [60, 0, 0];
  18. var мир = муром.узлы.узел("mir");
  19. мир.добавитьДитя(мж.сцена);
  20. мж.начали.уведомить();
  21. };
  22. мж.задатьНейтральныйМатериал = function()
  23. {
  24. var мат = муром.материалы.создатьМатериал("N");
  25. var изо = муром.ресурсы.ресурс("tex.stub");
  26. мат.задатьТекстуру("image", изо);
  27. var вер = муром.ресурсы.ресурс("ver").содержимое;
  28. var фра = муром.ресурсы.ресурс("fra").содержимое;
  29. мат.задатьШейдеры(вер, фра);
  30. мж.сцена.задатьМатериал(мат);
  31. };
  32. мж.разобратьРаскладку = function()
  33. {
  34. eval(муром.ресурсы.ресурс("Layout").содержимое);
  35. var содержимое = муром.ресурсы.ресурс("lay").содержимое;
  36. мж.раскладка = new Раскладка();
  37. мж.раскладка.разобрать(содержимое);
  38. };
  39. мж.фишки = [];
  40. мж.создатьФишки = function()
  41. {
  42. eval(муром.ресурсы.ресурс("Tile").содержимое);
  43. for (var номер in мж.раскладка.позиции)
  44. {
  45. var ф = new Фишка();
  46. ф.позиция = мж.раскладка.позиции[номер];
  47. мж.фишки.push(ф);
  48. }
  49. };
  50. мж.размерФишки = {
  51. "ширина": 2.0,
  52. "высота": 3.0,
  53. "глубина": 1.0,
  54. };
  55. мж.создатьУзлыФишек = function()
  56. {
  57. const шагФишки = 2.0;
  58. const коэффициенты = {
  59. "x": мж.размерФишки.ширина / шагФишки,
  60. "y": -мж.размерФишки.высота / шагФишки,
  61. "z": мж.размерФишки.глубина,
  62. };
  63. var мод = муром.ресурсы.ресурс("mod");
  64. for (var номер in мж.фишки)
  65. {
  66. var имя = номер.toString();
  67. var узел = муром.узлы.создатьУзел(имя, мод);
  68. мж.сцена.добавитьДитя(узел);
  69. var ф = мж.фишки[номер];
  70. var п = ф.позиция;
  71. узел.позиция = [
  72. п[2] * коэффициенты.x,
  73. п[1] * коэффициенты.y,
  74. п[0] * коэффициенты.z,
  75. ];
  76. ф.узел = узел;
  77. }
  78. };
  79. мж.центрироватьСцену = function()
  80. {
  81. var границы = {
  82. "лево": 1000,
  83. "право": -1000,
  84. "верх": -1000,
  85. "низ": 1000,
  86. };
  87. for (var номер in мж.фишки)
  88. {
  89. const ф = мж.фишки[номер];
  90. const x = ф.узел.позиция[0];
  91. const y = ф.узел.позиция[1];
  92. if (x < границы.лево)
  93. {
  94. границы.лево = x;
  95. }
  96. if (x > границы.право)
  97. {
  98. границы.право = x;
  99. }
  100. if (y < границы.низ)
  101. {
  102. границы.низ = y;
  103. }
  104. if (y > границы.верх)
  105. {
  106. границы.верх = y;
  107. }
  108. }
  109. const ширина = границы.право - границы.лево + мж.размерФишки.ширина;
  110. const высота = границы.верх - границы.низ + мж.размерФишки.высота;
  111. мж.сцена.позиция = [-ширина / 2.0, 0, высота / 2.0];
  112. };
  113. // http://www.rubl.com/rules/mahjong-solitaire-rules.html
  114. мж.задатьФишкамГруппыПоследовательно = function()
  115. {
  116. var группы = [];
  117. // Генерируем группы.
  118. const группВсего = 42;
  119. const группПо4Дубля = 34;
  120. for (var г = 0; г < группВсего; ++г)
  121. {
  122. const четыреДубля = (г < группПо4Дубля);
  123. const колвоДублей = четыреДубля ? 4 : 1;
  124. for (var д = 0; д < колвоДублей; ++д)
  125. {
  126. группы.push(г);
  127. }
  128. }
  129. // Задаём.
  130. for (var номер in мж.фишки)
  131. {
  132. var ф = мж.фишки[номер];
  133. ф.группа = Number(группы[номер]);
  134. }
  135. };
  136. мж.применитьТемуФишек = function()
  137. {
  138. eval(муром.ресурсы.ресурс("theme.stub").contents);
  139. const R = RR();
  140. // Создать текстуры.
  141. var обозначения = [];
  142. var текстуры = [];
  143. for (var номер in R)
  144. {
  145. var обозначение = R[номер][0];
  146. обозначения.push(обозначение);
  147. var имя = "tile.tex/" + обозначение;
  148. var содержимое = R[номер][1];
  149. var текстура = муром.ресурсы.создатьРесурс(имя, содержимое);
  150. текстуры.push(текстура);
  151. }
  152. // Создать материалы.
  153. var нейтраль = [];
  154. var выбор = [];
  155. var вер = муром.ресурсы.ресурс("ver").содержимое;
  156. var фра = муром.ресурсы.ресурс("fra").содержимое;
  157. // Нейтраль.
  158. for (var номер = 0; номер < 42; ++номер)
  159. {
  160. var имя = "tile.mat/" + обозначения[номер];
  161. var изо = текстуры[номер];
  162. var мат = муром.материалы.создатьМатериал(имя);
  163. мат.задатьТекстуру("image", изо);
  164. мат.задатьШейдеры(вер, фра);
  165. нейтраль.push(мат);
  166. }
  167. // Выбор.
  168. for (var номер = 42; номер < 83; ++номер)
  169. {
  170. var имя = "tile.mat/" + обозначения[номер];
  171. var изо = текстуры[номер];
  172. var мат = муром.материалы.создатьМатериал(имя);
  173. мат.задатьТекстуру("image", изо);
  174. мат.задатьШейдеры(вер, фра);
  175. выбор.push(мат);
  176. }
  177. // Применить тему.
  178. for (var номер in мж.фишки)
  179. {
  180. var ф = мж.фишки[номер];
  181. ф.нейтраль = нейтраль[ф.группа];
  182. ф.выбор = выбор[ф.группа];
  183. ф.показатьНейтраль();
  184. }
  185. };
  186. мж.маскаВыбора = 0x2;
  187. мж.сделатьФишкиВыбираемыми = function()
  188. {
  189. for (var номер in мж.фишки)
  190. {
  191. var ф = мж.фишки[номер];
  192. ф.узел.задатьМаску(мж.маскаВыбора);
  193. }
  194. }
  195. мж.индексПозиции = function(п)
  196. {
  197. return п[0] * 1000000 + п[1] * 1000 + п[2];
  198. };
  199. мж.индексПозиций = {};
  200. мж.проиндексироватьПозиции = function()
  201. {
  202. for (var номер in мж.фишки)
  203. {
  204. var ф = мж.фишки[номер];
  205. var и = мж.индексПозиции(ф.позиция);
  206. мж.индексПозиций[и] = true;
  207. }
  208. };
  209. мж.естьСоседи = function(позиция, смещениеПоля, смещениеСтолбца)
  210. {
  211. for (var смещениеРяда = -1; смещениеРяда <= 1; ++смещениеРяда)
  212. {
  213. var сосед = [
  214. Number(позиция[0]) + смещениеПоля,
  215. Number(позиция[1]) + смещениеРяда,
  216. Number(позиция[2]) + смещениеСтолбца,
  217. ];
  218. var и = мж.индексПозиции(сосед);
  219. if (и in мж.индексПозиций)
  220. {
  221. return true;
  222. }
  223. }
  224. // Соседей нет.
  225. return false;
  226. };
  227. мж.можноВыбратьФишку = function(ф)
  228. {
  229. // Проверяем наличие фишек с левой и правой сторон одновременно.
  230. var слева = this.естьСоседи(ф.позиция, 0, -2);
  231. var справа = this.естьСоседи(ф.позиция, 0, 2);
  232. if (слева && справа)
  233. {
  234. return false;
  235. }
  236. // Проверяем наличие фишек непосредственно сверху.
  237. for (var смещение = -1; смещение <= 1; ++смещение)
  238. {
  239. if (this.естьСоседи(ф.позиция, 1, смещение))
  240. {
  241. return false;
  242. }
  243. }
  244. // Фишка не заблокирована.
  245. return true;
  246. };
  247. мж.номерВыбраннойФишки = null;
  248. мж.выбраннаяФишка = null;
  249. мж.выбранаФишка = new Уведомитель();
  250. мж.выбратьФишку = function()
  251. {
  252. // Определить щелчок.
  253. if (муром.мышь.нажатыеКнопки.length == 1)
  254. {
  255. var узел =
  256. муром.камера.узелВПозиции(
  257. муром.мышь.позиция,
  258. мж.маскаВыбора
  259. );
  260. if (узел)
  261. {
  262. var номер = Number(узел.имя);
  263. var ф = мж.фишки[номер];
  264. if (мж.можноВыбратьФишку(ф))
  265. {
  266. мж.номерВыбраннойФишки = номер;
  267. мж.выбраннаяФишка = ф;
  268. мж.выбранаФишка.уведомить();
  269. }
  270. }
  271. }
  272. };
  273. мж.отладитьВыборФишки = function()
  274. {
  275. мж.выбранаФишка.подписать(function(){
  276. console.log(
  277. "Выбор. Номер: '" +
  278. мж.номерВыбраннойФишки +
  279. "' Группа: '" +
  280. мж.выбраннаяФишка.группа +
  281. "'"
  282. );
  283. });
  284. };
  285. мж.показатьВыбраннуюФишку = function()
  286. {
  287. мж.выбраннаяФишка.показатьВыбор();
  288. };
  289. мж.выбранныеФишки = [];
  290. мж.фишкиРазличаются = new Уведомитель();
  291. мж.фишкиСовпадают = new Уведомитель();
  292. мж.фишкиСравнили = new Уведомитель();
  293. мж.сравнитьВыбранныеФишки = function()
  294. {
  295. // Собираем.
  296. мж.выбранныеФишки.push(мж.выбраннаяФишка);
  297. // Удостоверяемся в наличии пары фишек.
  298. if (мж.выбранныеФишки.length != 2)
  299. {
  300. return;
  301. }
  302. var ф1 = мж.выбранныеФишки[0];
  303. var ф2 = мж.выбранныеФишки[1];
  304. // Убираем дубликат при двойном выборе одной фишки.
  305. if (ф1.имя == ф2.имя)
  306. {
  307. мж.выбранныеФишки.shift();
  308. return;
  309. }
  310. // Сравниваем.
  311. if (ф1.группа == ф2.группа)
  312. {
  313. мж.фишкиСовпадают.уведомить();
  314. }
  315. else
  316. {
  317. мж.фишкиРазличаются.уведомить();
  318. }
  319. мж.фишкиСравнили.уведомить();
  320. };
  321. мж.отладитьСравнениеФишек = function()
  322. {
  323. мж.фишкиСовпадают.подписать(function(){
  324. console.log("Фишки совпадают");
  325. });
  326. мж.фишкиРазличаются.подписать(function(){
  327. console.log("Фишки различаются");
  328. });
  329. };
  330. мж.скрытьСовпадающиеФишки = function()
  331. {
  332. мж.выбранныеФишки[0].скрыть();
  333. мж.выбранныеФишки[1].скрыть();
  334. };
  335. мж.убратьСовпадающиеФишки = function()
  336. {
  337. var ф1 = мж.выбранныеФишки[0];
  338. var ф2 = мж.выбранныеФишки[1];
  339. var и1 = мж.индексПозиции(ф1.позиция);
  340. var и2 = мж.индексПозиции(ф2.позиция);
  341. delete мж.индексПозиций[и1];
  342. delete мж.индексПозиций[и2];
  343. };
  344. мж.очиститьОтображениеВыбора = function()
  345. {
  346. мж.выбранныеФишки[0].показатьНейтраль();
  347. мж.выбранныеФишки[1].показатьНейтраль();
  348. };
  349. мж.очиститьВыбор = function()
  350. {
  351. мж.номерВыбраннойФишки = 0;
  352. мж.выбраннаяФишка = null;
  353. мж.выбранныеФишки = [];
  354. };
  355. мж.оставшиесяФишки = [];
  356. мж.задатьОставшиесяФишки = function()
  357. {
  358. мж.оставшиесяФишки = мж.фишки.slice();
  359. };
  360. мж.обновилиОставшиесяФишки = new Уведомитель();
  361. мж.обновитьОставшиесяФишки = function()
  362. {
  363. var и1 = мж.оставшиесяФишки.indexOf(мж.выбранныеФишки[0]);
  364. мж.оставшиесяФишки.splice(и1, 1);
  365. var и2 = мж.оставшиесяФишки.indexOf(мж.выбранныеФишки[1]);
  366. мж.оставшиесяФишки.splice(и2, 1);
  367. мж.обновилиОставшиесяФишки.уведомить();
  368. };
  369. мж.доступныеДляВыбораФишки = function()
  370. {
  371. var фишки = [];
  372. for (var номер in мж.оставшиесяФишки)
  373. {
  374. var ф = мж.оставшиесяФишки[номер];
  375. if (мж.можноВыбратьФишку(ф))
  376. {
  377. фишки.push(ф);
  378. }
  379. }
  380. return фишки;
  381. };
  382. мж.естьХод = function()
  383. {
  384. var фишки = мж.доступныеДляВыбораФишки();
  385. for (var н1 in фишки)
  386. {
  387. for (var н2 in фишки)
  388. {
  389. var ф1 = фишки[н1];
  390. var ф2 = фишки[н2];
  391. if (
  392. (ф1.имя != ф2.имя) &&
  393. (ф1.группа == ф2.группа)
  394. ) {
  395. return true;
  396. }
  397. }
  398. }
  399. return false;
  400. }
  401. мж.победа = new Уведомитель();
  402. мж.поражение = new Уведомитель();
  403. мж.проверитьЗавершение = function()
  404. {
  405. var кончилисьФишки = (мж.оставшиесяФишки.length == 0);
  406. if (кончилисьФишки)
  407. {
  408. мж.победа.уведомить();
  409. return;
  410. }
  411. if (!мж.естьХод())
  412. {
  413. мж.поражение.уведомить();
  414. }
  415. };
  416. мж.отладитьЗавершение = function()
  417. {
  418. мж.победа.подписать(function(){
  419. console.log("Игра завершена. ПОБЕДА!");
  420. });
  421. мж.поражение.подписать(function(){
  422. console.log("Игра завершена. ПОРАЖЕНИЕ :(");
  423. });
  424. };
  425. мж.задатьОтображениеЗавершения = function()
  426. {
  427. мж.победа.подписать(function(){
  428. муром.камера.цветОчистки = [0.2, 0.5, 0.2];
  429. });
  430. мж.поражение.подписать(function(){
  431. муром.камера.цветОчистки = [0.5, 0.2, 0.2];
  432. });
  433. };