playMode.js 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071
  1. function showComfirm(ok = () => { }, no = () => { }) {
  2. $('.comfirmcon p').html($.i18n("own_zodiac_first"))
  3. $('.comfirmcon .no').html($.i18n("cancel")).click(() => {
  4. no && no()
  5. $('.comfirmcon').fadeOut()
  6. })
  7. $('.comfirmcon .yes').html($.i18n("comfirm")).click(() => {
  8. ok && ok()
  9. $('.comfirmcon').fadeOut()
  10. })
  11. $('.comfirmcon').fadeIn()
  12. }
  13. function showFoucstips(ok = () => { }, no = () => { }) {
  14. $('.foucstips p').html($.i18n("foncus_tips"))
  15. $('.foucstips .yes').html($.i18n("gotit")).click(() => {
  16. ok && ok()
  17. $('.foucstips').fadeOut()
  18. })
  19. $('.foucstips').fadeIn()
  20. }
  21. function PlayMode(EndMode) {
  22. let that = {};
  23. that.zodiacs = [];
  24. let endMode = EndMode;
  25. let zodiac_name = ["Rat", "Ox", "Tiger", "Rabbit", "Dragon", "Snake", "Horse", "Goat", "Monkey", "Rooster", "Dog", "Pig"];
  26. let zodiac_position = [];
  27. let morp_contours;
  28. let live_contours;
  29. let workVideo;
  30. let videofenbianlv = 1080 / 1080;
  31. let first_play = false;
  32. let first_zodiac = 0;
  33. let zodiac_id = -99;
  34. let gameTimer = 20;
  35. let game_play_counter = 0;
  36. let timer = 0;
  37. let playTime = 0;
  38. let score = 0;
  39. let origin_pos = { x: 0, y: -290 };
  40. let beginPlayAnim = 0;
  41. let timerAnim = 0;
  42. let timeAnim = 5;
  43. let beginFirstDone = 0;
  44. let timerFirstDone = 0;
  45. let timeFirstDone = 5;
  46. let foucstipsTimer = null;
  47. // 难度
  48. let threshold = 10e-15;
  49. let threshold_for_first = 10e-15;
  50. let confidence_val = 0;
  51. let isCaribrateCam = 0;
  52. let isPlaySound = false;
  53. let calibProgress = 0.0;
  54. let lastElapsedTimeAtNoneZeroCalibProgress = 0;
  55. let isCalibrateCompleted = false;
  56. var ENUM_STATE = {
  57. IDLE: 0,
  58. PLAY: 1,
  59. MORP: 2,
  60. PLAY_ANIM: 3,
  61. ROTATE: 4,
  62. END: 5,
  63. FIRST_DONE: 6,
  64. };
  65. let spriteWidth = 0;
  66. let spriteHeight = 0;
  67. let spriteScale = 0;
  68. let state = ENUM_STATE.IDLE;
  69. var zodiac_sprite_img = new Array();
  70. var zodiac_sprite_video = new Array();
  71. var zodiac_play_img = new Array();
  72. var zodiac_img = new Array();
  73. var zodiac_black_img = new Array();
  74. var hand_guide_img = new Array();
  75. var zodiac_sound = new Array();
  76. let countTimeGamePlay = 0;
  77. let beginTimerGamePlay = 0;
  78. // responsive stuff
  79. let canvas;
  80. let ctx;
  81. let scale;
  82. let baseWidth = 3840 * 0.5;
  83. let baseHeight = 2160 * 0.5;
  84. let baseRatio = baseWidth / baseHeight;
  85. let wellDoneTextSize = 110 * 0.5;
  86. let wellDoneDescriptionTextSize = 90 * 0.5;
  87. let zodiacNameTextSize = 120 * 0.5;
  88. let timerLineWidth = 45 * 0.5;
  89. let moon_base_rad = 600 * 0.5;
  90. let calibrateMessageSize = 95 * 0.45;
  91. let zodiacPadSize = 120 * 0.5;
  92. let moveGradient_begin = 0;
  93. let moveGradient_timer = 2.0;
  94. let moveGradient_t = 0;
  95. let moveGradient_cicle_begin = 0;
  96. let moveGradient_cicle_timer = 2;
  97. let moveGradient_cicle_t = 0;
  98. let scale_shadow_art = 0.9;
  99. that.loadImageSource = function () {
  100. var queue = new createjs.LoadQueue();
  101. queue.on("fileload", handlePreloading, that);
  102. queue.on("complete", handlePreloadComplete, that);
  103. if (!mobileDevice) {
  104. if (lang === "zh-cn") {
  105. queue.loadManifest(
  106. [
  107. { id: "sprite_src", src: "js/manifest/common/zh-cn/zodiac_sprite.json", type: "manifest" },
  108. { id: "img_color_src", src: "js/manifest/zodiac_color_image.json", type: "manifest" },
  109. { id: "img_black_src", src: "js/manifest/zodiac_black_image.json", type: "manifest" },
  110. { id: "img_play_src", src: "js/manifest/zodiac_play_image.json", type: "manifest" },
  111. { id: "hand_guide_src", src: "js/manifest/hand_guide_image.json", type: "manifest" },
  112. { id: "sound_src", src: "js/manifest/zodiac_sound.json", type: "manifest" },
  113. ],
  114. true
  115. );
  116. spriteWidth = 15300;
  117. spriteHeight = 300;
  118. spriteScale = (moon_base_rad * 2) / spriteHeight;
  119. } else {
  120. queue.loadManifest(
  121. [
  122. { id: "sprite_src", src: "js/manifest/common/en-us/zodiac_sprite.json", type: "manifest" },
  123. { id: "img_color_src", src: "js/manifest/zodiac_color_image.json", type: "manifest" },
  124. { id: "img_black_src", src: "js/manifest/zodiac_black_image.json", type: "manifest" },
  125. { id: "img_play_src", src: "js/manifest/zodiac_play_image.json", type: "manifest" },
  126. { id: "hand_guide_src", src: "js/manifest/hand_guide_image.json", type: "manifest" },
  127. { id: "sound_src", src: "js/manifest/zodiac_sound.json", type: "manifest" },
  128. ],
  129. true
  130. );
  131. spriteWidth = 62500;
  132. spriteHeight = 500;
  133. spriteScale = (moon_base_rad * 2) / spriteHeight;
  134. }
  135. } else {
  136. if (lang === "zh-cn") {
  137. queue.loadManifest(
  138. [
  139. { id: "sprite_src", src: "js/manifest/mobile/zh-cn/zodiac_sprite.json", type: "manifest" },
  140. { id: "img_color_src", src: "js/manifest/zodiac_color_image.json", type: "manifest" },
  141. { id: "img_black_src", src: "js/manifest/zodiac_black_image.json", type: "manifest" },
  142. { id: "img_play_src", src: "js/manifest/zodiac_play_image.json", type: "manifest" },
  143. { id: "hand_guide_src", src: "js/manifest/hand_guide_image.json", type: "manifest" },
  144. { id: "sound_src", src: "js/manifest/zodiac_sound.json", type: "manifest" },
  145. ],
  146. true
  147. );
  148. spriteWidth = 10200;
  149. spriteHeight = 200;
  150. spriteScale = (moon_base_rad * 2) / spriteHeight;
  151. } else {
  152. queue.loadManifest(
  153. [
  154. { id: "sprite_src", src: "js/manifest/mobile/en-us/zodiac_sprite.json", type: "manifest" },
  155. { id: "img_color_src", src: "js/manifest/zodiac_color_image.json", type: "manifest" },
  156. { id: "img_black_src", src: "js/manifest/zodiac_black_image.json", type: "manifest" },
  157. { id: "img_play_src", src: "js/manifest/zodiac_play_image.json", type: "manifest" },
  158. { id: "hand_guide_src", src: "js/manifest/hand_guide_image.json", type: "manifest" },
  159. { id: "sound_src", src: "js/manifest/zodiac_sound.json", type: "manifest" },
  160. ],
  161. true
  162. );
  163. spriteWidth = 25000;
  164. spriteHeight = 200;
  165. spriteScale = (moon_base_rad * 2) / spriteHeight;
  166. }
  167. }
  168. //预加载
  169. function handlePreloading(event) {
  170. $("#fade-wrapper").show();
  171. }
  172. //预加载完成
  173. function handlePreloadComplete(event) {
  174. // 雪碧图
  175. zodiac_sprite_img = that.swapToImageArray(queue.getResult("sprite_src").image, callback);
  176. zodiac_sprite_video = that.swapToVideoArray(queue.getResult("sprite_src").image, callback);
  177. // 生肖图
  178. zodiac_img = that.swapToImageArray(queue.getResult("img_color_src").image, callback);
  179. // 生肖剪影图
  180. zodiac_black_img = that.swapToImageArray(queue.getResult("img_black_src").image, callback);
  181. // 生肖默认图
  182. zodiac_play_img = that.swapToImageArray(queue.getResult("img_play_src").image, callback);
  183. // 手撕图
  184. hand_guide_img = that.swapToStringArray(queue.getResult("hand_guide_src").image);
  185. if (isPlaySound) zodiac_sound = that.swapToAudioArray(queue.getResult("sound_src").sound);
  186. that.preCompute();
  187. mode = ENUM_MODE.SELECT;
  188. let counter = 0;
  189. let img_total = zodiac_sprite_img.length + zodiac_img.length + zodiac_black_img.length + zodiac_play_img.length;
  190. function callback() {
  191. counter++;
  192. if (counter > img_total - 1) {
  193. $("#fade-wrapper").fadeOut();
  194. }
  195. }
  196. }
  197. };
  198. that.swapToImageArray = function (array, callback) {
  199. let target_array = new Array();
  200. let index = 0;
  201. array.forEach((element) => {
  202. target_array[index] = new Image();
  203. target_array[index].onload = callback;
  204. target_array[index].src = element.src;
  205. index++;
  206. });
  207. return target_array;
  208. };
  209. that.swapToVideoArray = function (array, callback) {
  210. let target_array = new Array();
  211. let index = 0;
  212. array.forEach((element) => {
  213. target_array[index] = $('<video src="' + element.videosrc + '" control="false" playsinline="true"></video>');
  214. target_array[index].canplay = callback;
  215. index++;
  216. });
  217. return target_array;
  218. };
  219. that.swapToStringArray = function (array) {
  220. let target_array = new Array();
  221. let index = 0;
  222. array.forEach((element) => {
  223. target_array[index] = element.src;
  224. index++;
  225. });
  226. return target_array;
  227. };
  228. that.swapToAudioArray = function (array) {
  229. let target_array = new Array();
  230. let index = 0;
  231. array.forEach((element) => {
  232. target_array[index] = new Audio(element.src);
  233. index++;
  234. });
  235. return target_array;
  236. };
  237. that.preLoader = function () {
  238. that.loadImageSource();
  239. };
  240. that.preCompute = function () {
  241. canvas = document.getElementById("canvas");
  242. ctx = canvas.getContext("2d");
  243. that.resizeWindow();
  244. degree = -90;
  245. let zodiac_count = 0;
  246. while (zodiac_count < 12) {
  247. // 计算生肖在圆环中的位置
  248. zodiacPosX = parseFloat(Math.cos(degree * (Math.PI / 180.0)));
  249. zodiacPosY = parseFloat(Math.sin(degree * (Math.PI / 180.0)));
  250. zodiac_position.push(moon_rad * filterFloat(zodiacPosX));
  251. zodiac_position.push(moon_rad * filterFloat(zodiacPosY));
  252. let coord = { x: (moon_rad + 70 * scale) * filterFloat(zodiacPosX), y: (moon_rad + 70 * scale) * filterFloat(zodiacPosY) };
  253. // 初始化雪碧图示例
  254. let zodiac_sprite = new sprite({
  255. videofenbianlv: videofenbianlv,
  256. context: ctx,
  257. width: spriteWidth,
  258. height: spriteHeight,
  259. image: zodiac_sprite_img[zodiac_count],
  260. workVideo: zodiac_sprite_video[zodiac_count],
  261. numberOfFrames: spriteWidth / spriteHeight,
  262. ticksPerFrame: 1,
  263. scale: spriteScale,
  264. });
  265. // 初始化生肖实例
  266. that.zodiacs.push(
  267. new zodiac({
  268. canvas: canvas,
  269. ctx: ctx,
  270. id: zodiac_count,
  271. coord: coord,
  272. sprite: zodiac_sprite,
  273. image: zodiac_img[zodiac_count],
  274. image_play: zodiac_play_img[zodiac_count],
  275. image_black: zodiac_black_img[zodiac_count],
  276. name: zodiac_name[zodiac_count],
  277. deg: degree,
  278. scale: scale,
  279. })
  280. );
  281. that.zodiacs[zodiac_count].init();
  282. that.zodiacs[zodiac_count].setup();
  283. degree += 30.0;
  284. zodiac_count++;
  285. }
  286. origin_pos = { x: that.zodiacs[0].coord.x, y: that.zodiacs[0].coord.y };
  287. console.log(that.zodiacs, 'that.zodiacs');
  288. };
  289. that.resizeWindow = function () {
  290. canvas.width = window.innerWidth * devicescreenratio;
  291. canvas.height = window.innerHeight * devicescreenratio;
  292. canvas.style.width = window.innerWidth + "px";
  293. canvas.style.height = window.innerHeight + "px";
  294. ctx.setTransform(devicescreenratio, 0, 0, devicescreenratio, 0, 0);
  295. width = window.innerWidth;
  296. height = window.innerHeight;
  297. c = { x: width / 2.0, y: height / 2.0 };
  298. degree = -90;
  299. scale = width / height > baseRatio ? height / baseHeight : width / baseWidth;
  300. let resizeMoonRad = moon_base_rad * scale;
  301. moon_rad = Math.round(resizeMoonRad);
  302. if (!workVideo) {
  303. workVideo = $('<video src="./video/01Shu.mp4" id="workId" control="true" playsinline="true" width="' + moon_rad + '" height="' + moon_rad + '"></video>');
  304. }
  305. };
  306. that.initZodiac = function (id) {
  307. first_zodiac = id;
  308. zodiac_id = id;
  309. first_play = true;
  310. for (var i = 0; i < that.zodiacs.length; i++) {
  311. that.zodiacs[i].setActivate(false);
  312. }
  313. that.zodiacs[zodiac_id].setActivate(true);
  314. let step_temp = that.zodiacs.length - zodiac_id;
  315. let step_deg = step_temp * 30;
  316. let degree_temp = step_deg - 90;
  317. for (var i = 0; i < that.zodiacs.length; i++) {
  318. zodiacPosX = parseFloat(Math.cos(degree_temp * (Math.PI / 180.0)));
  319. zodiacPosY = parseFloat(Math.sin(degree_temp * (Math.PI / 180.0)));
  320. let coord = { x: (moon_rad + zodiacPadSize * scale) * filterFloat(zodiacPosX), y: (moon_rad + zodiacPadSize * scale) * filterFloat(zodiacPosY) };
  321. that.zodiacs[i].setPosition(coord.x, coord.y);
  322. that.zodiacs[i].deg = degree_temp;
  323. degree_temp += 30;
  324. }
  325. };
  326. that.updateZodiac = function () {
  327. for (var i = 0; i < that.zodiacs.length; i++) {
  328. zodiacPosX = parseFloat(Math.cos(that.zodiacs[i].deg * (Math.PI / 180.0)));
  329. zodiacPosY = parseFloat(Math.sin(that.zodiacs[i].deg * (Math.PI / 180.0)));
  330. let coord = { x: (moon_rad + zodiacPadSize * scale) * filterFloat(zodiacPosX), y: (moon_rad + zodiacPadSize * scale) * filterFloat(zodiacPosY) };
  331. that.zodiacs[i].setPosition(coord.x, coord.y);
  332. that.zodiacs[i].scale = scale;
  333. that.zodiacs[i].sprite.drawWidth = moon_rad * 2;
  334. that.zodiacs[i].sprite.drawHeight = moon_rad * 2;
  335. }
  336. };
  337. that.setup = function () {
  338. state = ENUM_STATE.IDLE;
  339. isCalibrateCompleted = false;
  340. foucstipsTimer = setTimeout(() => {
  341. if (calibProgress<0.4) {
  342. canCalibrate = false
  343. state = -10086; //状态置为10086,不做处理
  344. showFoucstips(()=>{
  345. state = ENUM_STATE.IDLE;
  346. canCalibrate = true
  347. })
  348. }
  349. }, 7*1000);
  350. playTime = getElapsedTimeSeconds();
  351. document.getElementById("sample_container").style.display = "none";
  352. document.getElementById("sample_container").style.height = "0px";
  353. that.resizeWindow();
  354. mode = ENUM_MODE.PLAY;
  355. var loop_duration = 2;
  356. var total_loop = 1;
  357. var FPS = 30;
  358. var width = moon_rad * 2;
  359. var height = moon_rad * 2;
  360. var confident;
  361. var controls = init_preprocessing(
  362. parseInt($(window).width() / 3 - 120),
  363. $("#display_container"),
  364. $("#sample_container"),
  365. function (contour_obj) {
  366. var nps = contour_obj.set_canvas(0, 0, width, height, 256);
  367. // console.log(contour_obj, 'confidentconfident.result');
  368. if (state == ENUM_STATE.PLAY) {
  369. //对比结果
  370. confident = that.compareConfident(contour_obj, zodiac_id);
  371. }
  372. prepare_morph(nps, contour_obj["class"][confident.id], 0, 0, moon_rad * 2, moon_rad * 2, function (morph_object) {
  373. var start_time = Date.now();
  374. var loop_count = 0;
  375. function captureContours() {
  376. let begin = Date.now();
  377. let elapsed = (Date.now() - start_time) / 1000.0;
  378. if (confident.result) {
  379. morp_contours = morph_object((elapsed * 2.0) / loop_duration - 1.0);
  380. that.zodiacs[zodiac_id].setCompleted();
  381. if (state != ENUM_STATE.MORP) {
  382. // console.log('MORPMORPMORP');
  383. action_music.pause()
  384. action_music.src = './audio/success.mp3'
  385. action_music.loop = false
  386. action_music.play()
  387. }
  388. // 当前剪影变换
  389. state = ENUM_STATE.MORP;
  390. }
  391. if (elapsed > loop_duration) {
  392. loop_count = loop_count + 1;
  393. start_time = Date.now();
  394. if (confident.result) {
  395. beginPlayAnim = getElapsedTimeSeconds();
  396. state = ENUM_STATE.PLAY_ANIM;
  397. }
  398. }
  399. if (loop_count < total_loop) {
  400. let delay = 1000 / FPS - (Date.now() - begin);
  401. setTimeout(captureContours, delay);
  402. }
  403. }
  404. if (state === ENUM_STATE.PLAY) {
  405. setTimeout(captureContours, 0);
  406. moveGradient_begin = getElapsedTimeSeconds();
  407. moveGradient_cicle_begin = getElapsedTimeSeconds();
  408. }
  409. });
  410. },
  411. function (contour_obj) {
  412. if (!contour_obj) return;
  413. isCaribrateCam = isCaribrateCam + 1;
  414. if (isCaribrateCam == 1) {
  415. console.log(isCaribrateCam,'isCaribrateCam');
  416. state = ENUM_STATE.PLAY;
  417. playTime = getElapsedTimeSeconds();
  418. }
  419. if (state === ENUM_STATE.PLAY || ENUM_STATE.PLAY_ANIM) {
  420. live_contours = contour_obj.set_canvas(0, 0, moon_rad * 2, moon_rad * 2);
  421. $("#hand_guide_diagram").attr("src", hand_guide_img[zodiac_id]);
  422. $("#calibrate_message").hide();
  423. }
  424. },
  425. function (percent) {
  426. if (isCalibrateCompleted) return;
  427. if (canCalibrate) {
  428. calibProgress = percent;
  429. if (percent > 0.0) {
  430. // lastElapsedTimeAtNoneZeroCalibProgress = getElapsedTimeSeconds();
  431. if (percent >= 1.0) {
  432. $("#calibrate_message").html(""); //Calibration Complete!
  433. isCalibrateCompleted = true;
  434. foucstipsTimer && clearInterval(foucstipsTimer)
  435. foucstipsTimer = null
  436. } else $("#calibrate_message").html($.i18n("calibrating_copy"));
  437. } else {
  438. // let timeBack = 1;
  439. // let calibFailElapsedTime = (getElapsedTimeSeconds() - lastElapsedTimeAtNoneZeroCalibProgress);
  440. // calibProgress = calibFailElapsedTime >= timeBack ? 0.0 : calibProgress*(timeBack-calibFailElapsedTime)/timeBack;
  441. $("#calibrate_message").html($.i18n("keep_clear_copy"));
  442. }
  443. }
  444. }
  445. );
  446. init_shadow();
  447. init_morph();
  448. if (iOS || isSafari) {
  449. setTimeout(function () {
  450. controls.reset_camera();
  451. }, 2000);
  452. }
  453. };
  454. that.compareConfident = function (ml_result, id) {
  455. let raw_score;
  456. let raw_id;
  457. for (var i = 0; i < ml_result["class"].length; i++) {
  458. if (id + 1 == ml_result["class"][i]) {
  459. raw_id = i;
  460. raw_score = ml_result["score"][raw_id];
  461. }
  462. }
  463. confidence_val = raw_score * 100;
  464. console.log(raw_score,threshold_for_first);
  465. if (id == first_zodiac) {
  466. if (raw_score > threshold_for_first) {
  467. score = score + 1;
  468. return { result: true, id: raw_id };
  469. }
  470. }
  471. if (raw_score > threshold) {
  472. score = score + 1;
  473. return { result: true, id: raw_id };
  474. }
  475. // score = score + 2;
  476. return { result: false, id: 0 };
  477. };
  478. let timeBeginRotate = 0;
  479. let timeRotateTimer = 0;
  480. let timeToRotate = 2;
  481. that.update = function () {
  482. that.resizeWindow();
  483. that.gameControl();
  484. that.updateZodiac();
  485. $("#calibrate_message").css({ width: moon_rad * 2, height: moon_rad * 2 });
  486. };
  487. that.gameControl = function () {
  488. countTimeGamePlay = getElapsedTimeSeconds() - beginTimerGamePlay;
  489. // console.log(state, 'mode');
  490. if (state === ENUM_STATE.PLAY) {
  491. if (zodiac_id == first_zodiac) {
  492. gameTimer = 30
  493. // return;
  494. } else {
  495. gameTimer = 20
  496. }
  497. timer = getElapsedTimeSeconds() - playTime;
  498. timer = gameTimer - timer;
  499. if (timer <= 0) {
  500. mode = ENUM_MODE.SUMMARY;
  501. endMode.setResults(first_zodiac, score, countTimeGamePlay, gameTimer == 30);
  502. that.hideUI();
  503. }
  504. } else if (state === ENUM_STATE.PLAY_ANIM) {
  505. if (isPlaySound) zodiac_sound[zodiac_id].play();
  506. timerAnim = getElapsedTimeSeconds() - beginPlayAnim;
  507. that.zodiacs[zodiac_id].onUpdate();
  508. if (that.zodiacs[zodiac_id].isAnimStop()) {
  509. loop_gradient_count = 0;
  510. zodiac_id = zodiac_id + 1;
  511. if (zodiac_id < 0) {
  512. zodiac_id = that.zodiacs.length - 1;
  513. }
  514. if (zodiac_id > that.zodiacs.length - 1) {
  515. zodiac_id = 0;
  516. }
  517. that.zodiacs[zodiac_id].setActivate(true);
  518. that.nextZodiac(zodiac_id);
  519. }
  520. } else if (state === ENUM_STATE.ROTATE) {
  521. that.rotateCW();
  522. } else if (state === ENUM_STATE.FIRST_DONE) {
  523. timerFirstDone = getElapsedTimeSeconds() - beginFirstDone;
  524. // if (timerFirstDone > timeFirstDone) {
  525. // playTime = getElapsedTimeSeconds();
  526. // beginTimerGamePlay = getElapsedTimeSeconds();
  527. // state = ENUM_STATE.PLAY;
  528. // first_play = false;
  529. // }
  530. }
  531. };
  532. that.nextZodiac = function (id) {
  533. game_play_counter = game_play_counter + 1;
  534. zodiac_id = id;
  535. playTime = getElapsedTimeSeconds();
  536. timer = 0;
  537. var check_first_zodiac = function () {
  538. if (first_play) {
  539. state = ENUM_STATE.FIRST_DONE;
  540. beginFirstDone = getElapsedTimeSeconds();
  541. showComfirm(() => {
  542. playTime = getElapsedTimeSeconds();
  543. beginTimerGamePlay = getElapsedTimeSeconds();
  544. state = ENUM_STATE.PLAY;
  545. first_play = false;
  546. }, () => {
  547. mode = ENUM_MODE.SUMMARY;
  548. endMode.setResults(first_zodiac, score, countTimeGamePlay);
  549. that.hideUI();
  550. })
  551. } else {
  552. state = ENUM_STATE.PLAY;
  553. }
  554. };
  555. var check_play_end = function () {
  556. if (game_play_counter > that.zodiacs.length - 1) {
  557. mode = ENUM_MODE.SUMMARY;
  558. endMode.setResults(first_zodiac, score, countTimeGamePlay);
  559. that.hideUI();
  560. }
  561. };
  562. check_first_zodiac();
  563. check_play_end();
  564. that.showHandGuide();
  565. };
  566. that.showHandGuide = function () {
  567. $("#hand_guide_diagram").attr("src", hand_guide_img[zodiac_id]);
  568. };
  569. that.rotateCW = function () {
  570. timeRotateTimer = getElapsedTimeSeconds() - timeBeginRotate;
  571. if (Math.floor(that.zodiacs[zodiac_id].coord.x) >= origin_pos.x && Math.floor(that.zodiacs[zodiac_id].coord.y) >= origin_pos.y) {
  572. setZodiacDeg();
  573. that.zodiacs[zodiac_id].setActivate(false);
  574. playTime = getElapsedTimeSeconds();
  575. timer = 0;
  576. state = ENUM_STATE.PLAY;
  577. } else {
  578. state = ENUM_STATE.ROTATE;
  579. animate(timeRotateTimer);
  580. }
  581. };
  582. that.resetState = function () {
  583. timer = 0;
  584. game_play_counter = 0;
  585. for (var i = 0; i < that.zodiacs.length; i++) {
  586. that.zodiacs[i].setActivate(false);
  587. that.zodiacs[i].setup();
  588. }
  589. that.initZodiac(0);
  590. };
  591. that.draw = function () {
  592. // 绘制光束
  593. that.drawRayShadowBg();
  594. // 绘制标题
  595. // that.drawShadowArtText();
  596. that.drawMoon();
  597. that.drawZodiacs();
  598. that.drawText();
  599. if (state === ENUM_STATE.IDLE) {
  600. that.drawCalibProgress(isCalibrateCompleted ? 1.0 : calibProgress);
  601. }
  602. if (state === ENUM_STATE.PLAY) {
  603. // if (!first_play) {
  604. that.drawTimerProgress(timer);
  605. // }
  606. }
  607. if (state === ENUM_STATE.MORP || state === ENUM_STATE.PLAY_ANIM) {
  608. // 绘画已解锁剪影
  609. that.drawTimerProgressMorpState(-90);
  610. }
  611. };
  612. let loop_gradient_total = 1;
  613. let loop_gradient_count = 0;
  614. that.drawRayShadowBg = function () {
  615. $("#canvasOutput").width(moon_rad * 2);
  616. $("#canvasOutput").height(moon_rad * 2);
  617. $("#hand_guide_diagram").width(moon_rad * 2);
  618. $("#hand_guide_diagram").height(moon_rad * 2);
  619. $("#calibrate_message").width(moon_rad * 2);
  620. $("#calibrate_message").height(moon_rad * 2);
  621. $("#calibrate_message").css({ "font-size": calibrateMessageSize * scale });
  622. $("#display_container ").offset({ top: Math.round(c.y - moon_rad), left: Math.round(width - width / 4 - moon_rad) });
  623. $("#canvasOutput ").offset({ top: Math.round(c.y - moon_rad), left: Math.round(width - width / 4 - moon_rad) });
  624. $("#out_line_diagrame").offset({ top: Math.round(c.y - moon_rad), left: Math.round(width - width / 4 - moon_rad) });
  625. ctx.save();
  626. ctx.drawImage(bg_img, 0, 0, width, height);
  627. ctx.restore();
  628. var on_morph_gradient = function (norm_t) {
  629. ctx.save();
  630. ctx.translate(c.x / 2, c.y);
  631. // ctx.fillStyle = "rgba(196, 195, 181, 0.5)";
  632. let grd = ctx.createLinearGradient(-moon_rad, 0, width - width / 2 + moon_rad * 0.65, 0);
  633. grd.addColorStop(clamp(norm_t - 0.2, 0, 1), "rgba(255, 228, 184, 0.5)");
  634. grd.addColorStop(clamp(norm_t, 0, 1), "rgba(255, 255, 255, 0.1)");
  635. grd.addColorStop(clamp(norm_t + 0.2, 0, 1), "rgba(255, 228, 184, 0.5)");
  636. ctx.fillStyle = grd;
  637. ctx.beginPath();
  638. ctx.arc(0, 0, moon_rad, 0, 2 * Math.PI);
  639. ctx.moveTo(0, -moon_rad);
  640. ctx.lineTo(width - width / 2, -moon_rad * 0.65);
  641. ctx.arc(width - width / 2, 0, moon_rad * 0.65, Math.PI, Math.PI / 2);
  642. ctx.lineTo(0, moon_rad);
  643. ctx.closePath();
  644. ctx.fill();
  645. ctx.restore();
  646. };
  647. var on_idle_gradient = function () {
  648. ctx.save();
  649. ctx.translate(c.x / 2, c.y);
  650. ctx.fillStyle = "rgba(160, 56, 57, 0.1)";
  651. ctx.beginPath();
  652. ctx.arc(0, 0, moon_rad, 0, 2 * Math.PI);
  653. ctx.moveTo(0, -moon_rad);
  654. ctx.lineTo(width - width / 2, -moon_rad * 0.65);
  655. ctx.arc(width - width / 2, 0, moon_rad * 0.65, Math.PI, Math.PI / 2);
  656. ctx.lineTo(0, moon_rad);
  657. ctx.closePath();
  658. ctx.fill();
  659. ctx.restore();
  660. };
  661. on_idle_gradient();
  662. if (state === ENUM_STATE.MORP || state === ENUM_STATE.PLAY_ANIM) {
  663. moveGradient_t = getElapsedTimeSeconds() - moveGradient_begin;
  664. let norm_t = (moveGradient_timer - moveGradient_t) / moveGradient_timer;
  665. on_morph_gradient(norm_t);
  666. if (norm_t < 0) {
  667. if (loop_gradient_count < loop_gradient_total) {
  668. moveGradient_begin = getElapsedTimeSeconds();
  669. loop_gradient_count++;
  670. }
  671. }
  672. }
  673. };
  674. that.drawShadowArtText = function () {
  675. ctx.save();
  676. ctx.translate(width * 0.02, height * 0.02);
  677. ctx.drawImage(shadowArtTextImg, 0, 0, shadowArtTextImg.width * scale * scale_shadow_art, shadowArtTextImg.height * scale * scale_shadow_art);
  678. ctx.restore();
  679. };
  680. that.drawMoon = function () {
  681. ctx.save();
  682. ctx.translate(c.x / 2, c.y);
  683. ctx.beginPath();
  684. ctx.fillStyle = "white";
  685. ctx.arc(0, 0, moon_rad, 0, 2 * Math.PI);
  686. ctx.clip();
  687. ctx.fill();
  688. // 剪影变化
  689. if (state == ENUM_STATE.MORP) {
  690. if (morp_contours) {
  691. ctx.save();
  692. ctx.translate(-moon_rad, -moon_rad);
  693. that.drawContour(morp_contours);
  694. ctx.restore();
  695. }
  696. }
  697. if (state == ENUM_STATE.PLAY) {
  698. if (live_contours) {
  699. ctx.save();
  700. ctx.translate(-moon_rad, -moon_rad);
  701. that.drawContour(live_contours);
  702. ctx.restore();
  703. }
  704. }
  705. // 生肖序列帧
  706. if (state == ENUM_STATE.PLAY_ANIM) {
  707. ctx.save();
  708. ctx.translate(-moon_rad * videofenbianlv, -moon_rad);
  709. that.zodiacs[zodiac_id].onDrawAnim();
  710. ctx.restore();
  711. }
  712. // 第一次完成
  713. if (state == ENUM_STATE.FIRST_DONE) {
  714. // ctx.save();
  715. // ctx.beginPath();
  716. // ctx.fillStyle = "white";
  717. // ctx.arc(0, 0, moon_rad, 0, 2 * Math.PI);
  718. // ctx.fill();
  719. // ctx.closePath();
  720. // ctx.restore();
  721. // let h = wellDoneTextSize * scale;
  722. // let line_h = h;
  723. // let str_array = splitText($.i18n("own_zodiac_completion"), "|");
  724. // if (str_array) {
  725. // let origin_ = -1;
  726. // for (var i = 0; i < str_array.length; i++) {
  727. // if (i == 0) {
  728. // ctx.font = h + "px " + $.i18n("fonts_primary");
  729. // ctx.fillStyle = "rgb(160, 56, 57)";
  730. // ctx.textAlign = "center";
  731. // ctx.fillText(str_array[0], 0, line_h * origin_);
  732. // } else {
  733. // h = wellDoneDescriptionTextSize * scale;
  734. // ctx.font = h + "px " + $.i18n("fonts_primary");
  735. // ctx.fillStyle = "rgb(160, 56, 57)";
  736. // ctx.textAlign = "center";
  737. // ctx.fillText(str_array[i], 0, line_h * origin_);
  738. // }
  739. // origin_ += 1.0;
  740. // }
  741. // }
  742. state = ENUM_STATE.FIRST_DONE;
  743. }
  744. ctx.restore();
  745. var fill_circle_live_feed = function () {
  746. ctx.save();
  747. ctx.translate(c.x + c.x / 2, c.y);
  748. ctx.beginPath();
  749. ctx.fillStyle = "white";
  750. ctx.arc(0, 0, moon_rad, 0, 2 * Math.PI);
  751. ctx.clip();
  752. ctx.fill();
  753. ctx.closePath();
  754. ctx.restore();
  755. };
  756. fill_circle_live_feed();
  757. };
  758. that.drawZodiacs = function () {
  759. ctx.save();
  760. ctx.translate(c.x / 2, c.y);
  761. for (var i = 0; i < that.zodiacs.length; i++) {
  762. that.zodiacs[i].onDraw();
  763. }
  764. ctx.restore();
  765. };
  766. that.drawContour = function (contours) {
  767. ctx.fillStyle = "black";
  768. ctx.beginPath();
  769. ctx.moveTo(contours[0][0], contours[0][1]);
  770. for (var i = 1; i < contours.length; ++i) {
  771. ctx.lineTo(contours[i][0], contours[i][1]);
  772. }
  773. ctx.lineTo(contours[0][0], contours[0][1]);
  774. ctx.closePath();
  775. ctx.fill();
  776. };
  777. that.drawText = function () {
  778. let zodiac = zodiac_text_list[zodiac_id];
  779. ctx.save();
  780. ctx.translate(width - width / 4, c.y - moon_rad - 100 * scale);
  781. ctx.beginPath();
  782. ctx.font = zodiacNameTextSize * scale + "px " + $.i18n("fonts_primary");
  783. ctx.fillStyle = "rgb(160, 56, 57)";
  784. ctx.textAlign = "center";
  785. ctx.fillText(zodiac, 0, 0);
  786. ctx.fill();
  787. ctx.font = "20px " + $.i18n("fonts_primary");
  788. ctx.fillStyle = "rgb(172, 102, 82)";
  789. ctx.fill();
  790. ctx.closePath();
  791. ctx.restore();
  792. };
  793. that.drawCalibProgress = function (t) {
  794. ctx.lineCap = "round";
  795. let deg_ = t * 360;
  796. ctx.save();
  797. ctx.translate(c.x + c.x / 2, c.y);
  798. ctx.beginPath();
  799. // ctx.globalAlpha = 0.1;
  800. ctx.strokeStyle = "rgba(160, 56, 57, 0.1)";
  801. ctx.lineWidth = timerLineWidth * scale;
  802. ctx.arc(0, 0, moon_rad + timerLineWidth * scale * 0.5, (Math.PI / 180) * 270, (Math.PI / 180) * (270 + deg_ + 0.1));
  803. ctx.stroke();
  804. ctx.closePath();
  805. ctx.restore();
  806. };
  807. that.drawTimerProgress = function (t) {
  808. ctx.lineCap = "round";
  809. let rate = t / gameTimer;
  810. let deg_ = rate * 360;
  811. ctx.save();
  812. ctx.translate(c.x + c.x / 2, c.y);
  813. ctx.beginPath();
  814. ctx.strokeStyle = "#A05540";
  815. ctx.lineWidth = timerLineWidth * scale;
  816. ctx.arc(0, 0, moon_rad + timerLineWidth * scale * 0.5, (Math.PI / 180) * 270, (Math.PI / 180) * (270 - deg_));
  817. ctx.stroke();
  818. ctx.closePath();
  819. ctx.restore();
  820. };
  821. that.drawTimerProgressMorpState = function (t) {
  822. ctx.lineCap = "round";
  823. let rate = t / moveGradient_cicle_t;
  824. let deg_ = rate * 360;
  825. ctx.save();
  826. ctx.translate(c.x + c.x / 2, c.y);
  827. ctx.beginPath();
  828. ctx.strokeStyle = "#FFE4B8";
  829. ctx.lineWidth = timerLineWidth * scale;
  830. ctx.arc(0, 0, moon_rad + timerLineWidth * scale * 0.5, (Math.PI / 180) * 270, (Math.PI / 180) * (270 - deg_));
  831. ctx.stroke();
  832. ctx.closePath();
  833. ctx.restore();
  834. };
  835. that.animate = function (t) {
  836. let linearSpeed = 100;
  837. for (var i = 0; i < that.zodiacs.length; i++) {
  838. let newPosX = (moon_rad + 10 + that.zodiacs[i].r) * Math.cos(that.zodiacs[i].deg * (Math.PI / 180.0) + t * linearSpeed * (Math.PI / 180.0));
  839. let newPosY = (moon_rad + 10 + that.zodiacs[i].r) * Math.sin(that.zodiacs[i].deg * (Math.PI / 180.0) + t * linearSpeed * (Math.PI / 180.0));
  840. that.zodiacs[i].setPosition(Math.round(newPosX), Math.round(newPosY));
  841. }
  842. };
  843. that.setZodiacDeg = function () {
  844. that.zodiacs[0].deg += 30;
  845. that.zodiacs[1].deg += 30;
  846. that.zodiacs[2].deg += 30;
  847. that.zodiacs[3].deg += 30;
  848. that.zodiacs[4].deg += 30;
  849. that.zodiacs[5].deg += 30;
  850. that.zodiacs[6].deg += 30;
  851. that.zodiacs[7].deg += 30;
  852. that.zodiacs[8].deg += 30;
  853. that.zodiacs[9].deg += 30;
  854. that.zodiacs[10].deg += 30;
  855. that.zodiacs[11].deg += 30;
  856. };
  857. that.hideUI = function () {
  858. $("#canvasOutput").hide();
  859. $("#hand_guide_diagram").hide();
  860. $("#calibrate_message").hide();
  861. $("#display_container ").hide();
  862. $("#camrea_tips").hide();
  863. $("#out_line_diagrame ").hide();
  864. };
  865. that.showUI = function () {
  866. $("#calibrate_message").show();
  867. $("#canvasOutput").show();
  868. $("#hand_guide_diagram").show();
  869. $("#calibrate_message").show();
  870. $("#display_container ").show();
  871. $("#out_line_diagrame ").show();
  872. $("#calibrate_message").css({ position: "none", bottom: 0, left: 0 });
  873. setTimeout(() => {
  874. $('#camrea_tips').html($.i18n('camrea_tips')).show();
  875. }, 100);
  876. };
  877. return that;
  878. }