|
|
@@ -0,0 +1,480 @@ |
|
|
|
var ресурсы = [ |
|
|
|
[БАЗА + "модели/фишка/2019-09-08.osgt", "mod"], |
|
|
|
[БАЗА + "текстуры/заглушка.png", "tex.stub"], |
|
|
|
[БАЗА + "шейдеры/освещение-изображение.vert", "ver"], |
|
|
|
[БАЗА + "шейдеры/освещение-изображение.frag", "fra"], |
|
|
|
[БАЗА + "раскладки/X_shaped.layout", "lay"], |
|
|
|
|
|
|
|
[БАЗА + "классы/Раскладка/2019-08-16.js", "Layout"], |
|
|
|
[БАЗА + "классы/Фишка/2019-09-07.js", "Tile"], |
|
|
|
[БАЗА + "темыФишек/заглушка/2019-09-08.js", "theme.stub"], |
|
|
|
]; |
|
|
|
|
|
|
|
мж.начали = new Уведомитель(); |
|
|
|
мж.начать = function() |
|
|
|
{ |
|
|
|
муром.камера.позиция = [0, -70, 0]; |
|
|
|
муром.камера.вращение = [90, 0, 0]; |
|
|
|
мж.сцена = муром.узлы.создатьСферу("sce", 0); |
|
|
|
мж.сцена.вращение = [60, 0, 0]; |
|
|
|
var мир = муром.узлы.узел("mir"); |
|
|
|
мир.добавитьДитя(мж.сцена); |
|
|
|
|
|
|
|
мж.начали.уведомить(); |
|
|
|
}; |
|
|
|
|
|
|
|
мж.задатьНейтральныйМатериал = function() |
|
|
|
{ |
|
|
|
var мат = муром.материалы.создатьМатериал("N"); |
|
|
|
var изо = муром.ресурсы.ресурс("tex.stub"); |
|
|
|
мат.задатьТекстуру("image", изо); |
|
|
|
var вер = муром.ресурсы.ресурс("ver").содержимое; |
|
|
|
var фра = муром.ресурсы.ресурс("fra").содержимое; |
|
|
|
мат.задатьШейдеры(вер, фра); |
|
|
|
мж.сцена.задатьМатериал(мат); |
|
|
|
}; |
|
|
|
|
|
|
|
мж.разобратьРаскладку = function() |
|
|
|
{ |
|
|
|
eval(муром.ресурсы.ресурс("Layout").содержимое); |
|
|
|
|
|
|
|
var содержимое = муром.ресурсы.ресурс("lay").содержимое; |
|
|
|
мж.раскладка = new Раскладка(); |
|
|
|
мж.раскладка.разобрать(содержимое); |
|
|
|
}; |
|
|
|
|
|
|
|
мж.фишки = []; |
|
|
|
мж.создатьФишки = function() |
|
|
|
{ |
|
|
|
eval(муром.ресурсы.ресурс("Tile").содержимое); |
|
|
|
|
|
|
|
for (var номер in мж.раскладка.позиции) |
|
|
|
{ |
|
|
|
var ф = new Фишка(); |
|
|
|
ф.позиция = мж.раскладка.позиции[номер]; |
|
|
|
мж.фишки.push(ф); |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
мж.размерФишки = { |
|
|
|
"ширина": 2.0, |
|
|
|
"высота": 3.0, |
|
|
|
"глубина": 1.0, |
|
|
|
}; |
|
|
|
мж.создатьУзлыФишек = function() |
|
|
|
{ |
|
|
|
const шагФишки = 2.0; |
|
|
|
const коэффициенты = { |
|
|
|
"x": мж.размерФишки.ширина / шагФишки, |
|
|
|
"y": -мж.размерФишки.высота / шагФишки, |
|
|
|
"z": мж.размерФишки.глубина, |
|
|
|
}; |
|
|
|
var мод = муром.ресурсы.ресурс("mod"); |
|
|
|
|
|
|
|
for (var номер in мж.фишки) |
|
|
|
{ |
|
|
|
var имя = номер.toString(); |
|
|
|
var узел = муром.узлы.создатьУзел(имя, мод); |
|
|
|
мж.сцена.добавитьДитя(узел); |
|
|
|
|
|
|
|
var ф = мж.фишки[номер]; |
|
|
|
var п = ф.позиция; |
|
|
|
узел.позиция = [ |
|
|
|
п[2] * коэффициенты.x, |
|
|
|
п[1] * коэффициенты.y, |
|
|
|
п[0] * коэффициенты.z, |
|
|
|
]; |
|
|
|
ф.узел = узел; |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
мж.центрироватьСцену = function() |
|
|
|
{ |
|
|
|
var границы = { |
|
|
|
"лево": 1000, |
|
|
|
"право": -1000, |
|
|
|
"верх": -1000, |
|
|
|
"низ": 1000, |
|
|
|
}; |
|
|
|
for (var номер in мж.фишки) |
|
|
|
{ |
|
|
|
const ф = мж.фишки[номер]; |
|
|
|
const x = ф.узел.позиция[0]; |
|
|
|
const y = ф.узел.позиция[1]; |
|
|
|
if (x < границы.лево) |
|
|
|
{ |
|
|
|
границы.лево = x; |
|
|
|
} |
|
|
|
if (x > границы.право) |
|
|
|
{ |
|
|
|
границы.право = x; |
|
|
|
} |
|
|
|
if (y < границы.низ) |
|
|
|
{ |
|
|
|
границы.низ = y; |
|
|
|
} |
|
|
|
if (y > границы.верх) |
|
|
|
{ |
|
|
|
границы.верх = y; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
const ширина = границы.право - границы.лево + мж.размерФишки.ширина; |
|
|
|
const высота = границы.верх - границы.низ + мж.размерФишки.высота; |
|
|
|
мж.сцена.позиция = [-ширина / 2.0, 0, высота / 2.0]; |
|
|
|
}; |
|
|
|
|
|
|
|
// http://www.rubl.com/rules/mahjong-solitaire-rules.html |
|
|
|
мж.задатьФишкамГруппыПоследовательно = function() |
|
|
|
{ |
|
|
|
var группы = []; |
|
|
|
// Генерируем группы. |
|
|
|
const группВсего = 42; |
|
|
|
const группПо4Дубля = 34; |
|
|
|
for (var г = 0; г < группВсего; ++г) |
|
|
|
{ |
|
|
|
const четыреДубля = (г < группПо4Дубля); |
|
|
|
const колвоДублей = четыреДубля ? 4 : 1; |
|
|
|
for (var д = 0; д < колвоДублей; ++д) |
|
|
|
{ |
|
|
|
группы.push(г); |
|
|
|
} |
|
|
|
} |
|
|
|
// Задаём. |
|
|
|
for (var номер in мж.фишки) |
|
|
|
{ |
|
|
|
var ф = мж.фишки[номер]; |
|
|
|
ф.группа = Number(группы[номер]); |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
мж.применитьТемуФишек = function() |
|
|
|
{ |
|
|
|
eval(муром.ресурсы.ресурс("theme.stub").contents); |
|
|
|
const R = RR(); |
|
|
|
|
|
|
|
// Создать текстуры. |
|
|
|
var обозначения = []; |
|
|
|
var текстуры = []; |
|
|
|
for (var номер in R) |
|
|
|
{ |
|
|
|
var обозначение = R[номер][0]; |
|
|
|
обозначения.push(обозначение); |
|
|
|
var имя = "tile.tex/" + обозначение; |
|
|
|
var содержимое = R[номер][1]; |
|
|
|
var текстура = муром.ресурсы.создатьРесурс(имя, содержимое); |
|
|
|
текстуры.push(текстура); |
|
|
|
} |
|
|
|
|
|
|
|
// Создать материалы. |
|
|
|
var нейтраль = []; |
|
|
|
var выбор = []; |
|
|
|
var вер = муром.ресурсы.ресурс("ver").содержимое; |
|
|
|
var фра = муром.ресурсы.ресурс("fra").содержимое; |
|
|
|
// Нейтраль. |
|
|
|
for (var номер = 0; номер < 42; ++номер) |
|
|
|
{ |
|
|
|
var имя = "tile.mat/" + обозначения[номер]; |
|
|
|
var изо = текстуры[номер]; |
|
|
|
var мат = муром.материалы.создатьМатериал(имя); |
|
|
|
мат.задатьТекстуру("image", изо); |
|
|
|
мат.задатьШейдеры(вер, фра); |
|
|
|
нейтраль.push(мат); |
|
|
|
} |
|
|
|
// Выбор. |
|
|
|
for (var номер = 42; номер < 83; ++номер) |
|
|
|
{ |
|
|
|
var имя = "tile.mat/" + обозначения[номер]; |
|
|
|
var изо = текстуры[номер]; |
|
|
|
var мат = муром.материалы.создатьМатериал(имя); |
|
|
|
мат.задатьТекстуру("image", изо); |
|
|
|
мат.задатьШейдеры(вер, фра); |
|
|
|
выбор.push(мат); |
|
|
|
} |
|
|
|
|
|
|
|
// Применить тему. |
|
|
|
for (var номер in мж.фишки) |
|
|
|
{ |
|
|
|
var ф = мж.фишки[номер]; |
|
|
|
ф.нейтраль = нейтраль[ф.группа]; |
|
|
|
ф.выбор = выбор[ф.группа]; |
|
|
|
|
|
|
|
ф.показатьНейтраль(); |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
мж.маскаВыбора = 0x2; |
|
|
|
мж.сделатьФишкиВыбираемыми = function() |
|
|
|
{ |
|
|
|
for (var номер in мж.фишки) |
|
|
|
{ |
|
|
|
var ф = мж.фишки[номер]; |
|
|
|
ф.узел.задатьМаску(мж.маскаВыбора); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
мж.индексПозиции = function(п) |
|
|
|
{ |
|
|
|
return п[0] * 1000000 + п[1] * 1000 + п[2]; |
|
|
|
}; |
|
|
|
|
|
|
|
мж.индексПозиций = {}; |
|
|
|
мж.проиндексироватьПозиции = function() |
|
|
|
{ |
|
|
|
for (var номер in мж.фишки) |
|
|
|
{ |
|
|
|
var ф = мж.фишки[номер]; |
|
|
|
var и = мж.индексПозиции(ф.позиция); |
|
|
|
мж.индексПозиций[и] = true; |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
мж.естьСоседи = function(позиция, смещениеПоля, смещениеСтолбца) |
|
|
|
{ |
|
|
|
for (var смещениеРяда = -1; смещениеРяда <= 1; ++смещениеРяда) |
|
|
|
{ |
|
|
|
var сосед = [ |
|
|
|
Number(позиция[0]) + смещениеПоля, |
|
|
|
Number(позиция[1]) + смещениеРяда, |
|
|
|
Number(позиция[2]) + смещениеСтолбца, |
|
|
|
]; |
|
|
|
var и = мж.индексПозиции(сосед); |
|
|
|
if (и in мж.индексПозиций) |
|
|
|
{ |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// Соседей нет. |
|
|
|
return false; |
|
|
|
}; |
|
|
|
|
|
|
|
мж.можноВыбратьФишку = function(ф) |
|
|
|
{ |
|
|
|
// Проверяем наличие фишек с левой и правой сторон одновременно. |
|
|
|
var слева = this.естьСоседи(ф.позиция, 0, -2); |
|
|
|
var справа = this.естьСоседи(ф.позиция, 0, 2); |
|
|
|
if (слева && справа) |
|
|
|
{ |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
// Проверяем наличие фишек непосредственно сверху. |
|
|
|
for (var смещение = -1; смещение <= 1; ++смещение) |
|
|
|
{ |
|
|
|
if (this.естьСоседи(ф.позиция, 1, смещение)) |
|
|
|
{ |
|
|
|
return false; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// Фишка не заблокирована. |
|
|
|
return true; |
|
|
|
}; |
|
|
|
|
|
|
|
мж.номерВыбраннойФишки = null; |
|
|
|
мж.выбраннаяФишка = null; |
|
|
|
мж.выбранаФишка = new Уведомитель(); |
|
|
|
мж.выбратьФишку = function() |
|
|
|
{ |
|
|
|
// Определить щелчок. |
|
|
|
if (муром.мышь.нажатыеКнопки.length == 1) |
|
|
|
{ |
|
|
|
var узел = |
|
|
|
муром.камера.узелВПозиции( |
|
|
|
муром.мышь.позиция, |
|
|
|
мж.маскаВыбора |
|
|
|
); |
|
|
|
if (узел) |
|
|
|
{ |
|
|
|
var номер = Number(узел.имя); |
|
|
|
var ф = мж.фишки[номер]; |
|
|
|
if (мж.можноВыбратьФишку(ф)) |
|
|
|
{ |
|
|
|
мж.номерВыбраннойФишки = номер; |
|
|
|
мж.выбраннаяФишка = ф; |
|
|
|
мж.выбранаФишка.уведомить(); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
мж.отладитьВыборФишки = function() |
|
|
|
{ |
|
|
|
мж.выбранаФишка.подписать(function(){ |
|
|
|
console.log( |
|
|
|
"Выбор. Номер: '" + |
|
|
|
мж.номерВыбраннойФишки + |
|
|
|
"' Группа: '" + |
|
|
|
мж.выбраннаяФишка.группа + |
|
|
|
"'" |
|
|
|
); |
|
|
|
}); |
|
|
|
}; |
|
|
|
|
|
|
|
мж.показатьВыбраннуюФишку = function() |
|
|
|
{ |
|
|
|
мж.выбраннаяФишка.показатьВыбор(); |
|
|
|
}; |
|
|
|
|
|
|
|
мж.выбранныеФишки = []; |
|
|
|
мж.фишкиРазличаются = new Уведомитель(); |
|
|
|
мж.фишкиСовпадают = new Уведомитель(); |
|
|
|
мж.фишкиСравнили = new Уведомитель(); |
|
|
|
мж.сравнитьВыбранныеФишки = function() |
|
|
|
{ |
|
|
|
// Собираем. |
|
|
|
мж.выбранныеФишки.push(мж.выбраннаяФишка); |
|
|
|
// Удостоверяемся в наличии пары фишек. |
|
|
|
if (мж.выбранныеФишки.length != 2) |
|
|
|
{ |
|
|
|
return; |
|
|
|
} |
|
|
|
var ф1 = мж.выбранныеФишки[0]; |
|
|
|
var ф2 = мж.выбранныеФишки[1]; |
|
|
|
// Убираем дубликат при двойном выборе одной фишки. |
|
|
|
if (ф1.имя == ф2.имя) |
|
|
|
{ |
|
|
|
мж.выбранныеФишки.shift(); |
|
|
|
return; |
|
|
|
} |
|
|
|
// Сравниваем. |
|
|
|
if (ф1.группа == ф2.группа) |
|
|
|
{ |
|
|
|
мж.фишкиСовпадают.уведомить(); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
мж.фишкиРазличаются.уведомить(); |
|
|
|
} |
|
|
|
мж.фишкиСравнили.уведомить(); |
|
|
|
}; |
|
|
|
|
|
|
|
мж.отладитьСравнениеФишек = function() |
|
|
|
{ |
|
|
|
мж.фишкиСовпадают.подписать(function(){ |
|
|
|
console.log("Фишки совпадают"); |
|
|
|
}); |
|
|
|
мж.фишкиРазличаются.подписать(function(){ |
|
|
|
console.log("Фишки различаются"); |
|
|
|
}); |
|
|
|
}; |
|
|
|
|
|
|
|
мж.скрытьСовпадающиеФишки = function() |
|
|
|
{ |
|
|
|
мж.выбранныеФишки[0].скрыть(); |
|
|
|
мж.выбранныеФишки[1].скрыть(); |
|
|
|
}; |
|
|
|
|
|
|
|
мж.убратьСовпадающиеФишки = function() |
|
|
|
{ |
|
|
|
var ф1 = мж.выбранныеФишки[0]; |
|
|
|
var ф2 = мж.выбранныеФишки[1]; |
|
|
|
var и1 = мж.индексПозиции(ф1.позиция); |
|
|
|
var и2 = мж.индексПозиции(ф2.позиция); |
|
|
|
delete мж.индексПозиций[и1]; |
|
|
|
delete мж.индексПозиций[и2]; |
|
|
|
}; |
|
|
|
|
|
|
|
мж.очиститьОтображениеВыбора = function() |
|
|
|
{ |
|
|
|
мж.выбранныеФишки[0].показатьНейтраль(); |
|
|
|
мж.выбранныеФишки[1].показатьНейтраль(); |
|
|
|
}; |
|
|
|
|
|
|
|
мж.очиститьВыбор = function() |
|
|
|
{ |
|
|
|
мж.номерВыбраннойФишки = 0; |
|
|
|
мж.выбраннаяФишка = null; |
|
|
|
мж.выбранныеФишки = []; |
|
|
|
}; |
|
|
|
|
|
|
|
мж.оставшиесяФишки = []; |
|
|
|
мж.задатьОставшиесяФишки = function() |
|
|
|
{ |
|
|
|
мж.оставшиесяФишки = мж.фишки.slice(); |
|
|
|
}; |
|
|
|
|
|
|
|
мж.обновилиОставшиесяФишки = new Уведомитель(); |
|
|
|
мж.обновитьОставшиесяФишки = function() |
|
|
|
{ |
|
|
|
var и1 = мж.оставшиесяФишки.indexOf(мж.выбранныеФишки[0]); |
|
|
|
мж.оставшиесяФишки.splice(и1, 1); |
|
|
|
var и2 = мж.оставшиесяФишки.indexOf(мж.выбранныеФишки[1]); |
|
|
|
мж.оставшиесяФишки.splice(и2, 1); |
|
|
|
|
|
|
|
мж.обновилиОставшиесяФишки.уведомить(); |
|
|
|
}; |
|
|
|
|
|
|
|
мж.доступныеДляВыбораФишки = function() |
|
|
|
{ |
|
|
|
var фишки = []; |
|
|
|
for (var номер in мж.оставшиесяФишки) |
|
|
|
{ |
|
|
|
var ф = мж.оставшиесяФишки[номер]; |
|
|
|
if (мж.можноВыбратьФишку(ф)) |
|
|
|
{ |
|
|
|
фишки.push(ф); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
return фишки; |
|
|
|
}; |
|
|
|
|
|
|
|
мж.естьХод = function() |
|
|
|
{ |
|
|
|
var фишки = мж.доступныеДляВыбораФишки(); |
|
|
|
for (var н1 in фишки) |
|
|
|
{ |
|
|
|
for (var н2 in фишки) |
|
|
|
{ |
|
|
|
var ф1 = фишки[н1]; |
|
|
|
var ф2 = фишки[н2]; |
|
|
|
if ( |
|
|
|
(ф1.имя != ф2.имя) && |
|
|
|
(ф1.группа == ф2.группа) |
|
|
|
) { |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
мж.победа = new Уведомитель(); |
|
|
|
мж.поражение = new Уведомитель(); |
|
|
|
мж.проверитьЗавершение = function() |
|
|
|
{ |
|
|
|
var кончилисьФишки = (мж.оставшиесяФишки.length == 0); |
|
|
|
if (кончилисьФишки) |
|
|
|
{ |
|
|
|
мж.победа.уведомить(); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
if (!мж.естьХод()) |
|
|
|
{ |
|
|
|
мж.поражение.уведомить(); |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
мж.отладитьЗавершение = function() |
|
|
|
{ |
|
|
|
мж.победа.подписать(function(){ |
|
|
|
console.log("Игра завершена. ПОБЕДА!"); |
|
|
|
}); |
|
|
|
мж.поражение.подписать(function(){ |
|
|
|
console.log("Игра завершена. ПОРАЖЕНИЕ :("); |
|
|
|
}); |
|
|
|
}; |
|
|
|
|
|
|
|
мж.задатьОтображениеЗавершения = function() |
|
|
|
{ |
|
|
|
мж.победа.подписать(function(){ |
|
|
|
муром.камера.цветОчистки = [0.2, 0.5, 0.2]; |
|
|
|
}); |
|
|
|
мж.поражение.подписать(function(){ |
|
|
|
муром.камера.цветОчистки = [0.5, 0.2, 0.2]; |
|
|
|
}); |
|
|
|
}; |