From 86596a14e7ae93dc33efc132ccbe0bff7bc3a1ce Mon Sep 17 00:00:00 2001 From: Didictateur Date: Sun, 9 Mar 2025 00:54:44 +0100 Subject: [PATCH] 3 premiers chapitres --- build/dp1.js | 2 +- build/dp2.js | 2 +- build/dp3.js | 1 + build/dp4.js | 1 + index.html | 47 ++++++++-- src/deck.ts | 8 ++ src/display/dp2.ts | 14 ++- src/display/dp3.ts | 192 ++++++++++++++++++++++++++++++++++++++++ src/display/dp4.ts | 185 ++++++++++++++++++++++++++++++++++++++ src/display/template.ts | 127 ++++++++++++++++++++++++++ src/game.ts | 130 +++++++++++++++++++++++++++ src/group.ts | 21 +++++ src/hand.ts | 135 ++++++++++++++++++++++++---- src/tile.ts | 42 +++++++-- webpack.config.js | 22 ++++- 15 files changed, 892 insertions(+), 37 deletions(-) create mode 100644 build/dp3.js create mode 100644 build/dp4.js create mode 100644 src/display/dp3.ts create mode 100644 src/display/dp4.ts create mode 100644 src/display/template.ts create mode 100644 src/game.ts create mode 100644 src/group.ts diff --git a/build/dp1.js b/build/dp1.js index 9a9e501..3310d07 100644 --- a/build/dp1.js +++ b/build/dp1.js @@ -1 +1 @@ -(()=>{"use strict";var t=function(){function t(t,e,n){this.family=t,this.value=e,this.red=n,this.loadded=!1,this.imgSrc="",this.imgFront=new Image,this.imgBack=new Image,this.img=new Image,this.setImgSrc()}return t.prototype.getFamily=function(){return this.family},t.prototype.getValue=function(){return this.value},t.prototype.isRed=function(){return this.red},t.prototype.drawTile=function(t,e,n,i){t.drawImage(this.imgFront,e,n,75*i,100*i),t.drawImage(this.img,e,n,75*i,100*i)},t.prototype.isLessThan=function(t){return this.family0&&r[r.length-1])||6!==s[0]&&2!==s[0])){o=0;continue}if(3===s[0]&&(!r||s[1]>r[0]&&s[1]0&&r[r.length-1])||6!==s[0]&&2!==s[0])){o=0;continue}if(3===s[0]&&(!r||s[1]>r[0]&&s[1]0;){var n=Math.floor(Math.random()*this.tiles.length);t=[this.tiles[0],this.tiles[n]],this.tiles[n]=t[0],this.tiles[0]=t[1],e.push(this.tiles.shift())}this.tiles=e},n.prototype.getRandomHand=function(){var t=new e;this.shuffle();for(var n=0;n<13;n++)t.push(this.pop());return t},n.prototype.cleanup=function(){this.tiles.forEach((function(t){return t.cleanup()})),this.tiles=[]},n.prototype.preload=function(){return t=this,e=void 0,i=function(){var t;return function(t,e){var n,i,r,o={label:0,sent:function(){if(1&r[0])throw r[1];return r[1]},trys:[],ops:[]},l=Object.create(("function"==typeof Iterator?Iterator:Object).prototype);return l.next=s(0),l.throw=s(1),l.return=s(2),"function"==typeof Symbol&&(l[Symbol.iterator]=function(){return this}),l;function s(s){return function(a){return function(s){if(n)throw new TypeError("Generator is already executing.");for(;l&&(l=0,s[0]&&(o=0)),o;)try{if(n=1,i&&(r=2&s[0]?i.return:s[0]?i.throw||((r=i.return)&&r.call(i),0):i.next)&&!(r=r.call(i,s[1])).done)return r;switch(i=0,r&&(s=[2&s[0],r.value]),s[0]){case 0:case 1:r=s;break;case 4:return o.label++,{value:s[1],done:!1};case 5:o.label++,i=s[1],s=[0];continue;case 7:s=o.ops.pop(),o.trys.pop();continue;default:if(!((r=(r=o.trys).length>0&&r[r.length-1])||6!==s[0]&&2!==s[0])){o=0;continue}if(3===s[0]&&(!r||s[1]>r[0]&&s[1]0&&r[r.length-1])||6!==s[0]&&2!==s[0])){o=0;continue}if(3===s[0]&&(!r||s[1]>r[0]&&s[1]{"use strict";var t=function(){function t(t,e,i){this.family=t,this.value=e,this.red=i,this.imgSrc="",this.imgFront=new Image,this.imgBack=new Image,this.img=new Image,this.tilt=0,this.setImgSrc()}return t.prototype.getFamily=function(){return this.family},t.prototype.getValue=function(){return this.value},t.prototype.isRed=function(){return this.red},t.prototype.setTilt=function(){this.tilt=.05*(1-2*Math.random())},t.prototype.drawTile=function(t,e,i,n,r,o){void 0===r&&(r=!1),void 0===o&&(o=0),t.save(),t.translate(e+75*n/2,i+100*n/2),t.rotate(o+this.tilt),r?t.drawImage(this.imgBack,-75*n/2,-100*n/2,75*n,100*n):(t.drawImage(this.imgFront,-75*n/2,-100*n/2,75*n,100*n),t.drawImage(this.img,-75*n/2,-100*n/2,75*n,100*n)),t.restore()},t.prototype.isLessThan=function(t){return this.family0&&r[r.length-1])||6!==l[0]&&2!==l[0])){o=0;continue}if(3===l[0]&&(!r||l[1]>r[0]&&l[1]0))return[];var i=this.tiles.pop(),n=this.count(i.getFamily(),i.getValue());if(n>=1&&!t){var r=this.find(i.getFamily(),i.getValue()),o=this.toGroup(!0);if(this.tiles.push(r),this.sort(),void 0!==o)return this.tiles.push(i),this.sort(),o.push(new e([i,r])),o}if(n>=2){r=this.find(i.getFamily(),i.getValue());var s=this.find(i.getFamily(),i.getValue());if(o=this.toGroup(t),this.tiles.push(r),this.tiles.push(s),this.sort(),void 0!==o)return o.push(new e([i,r,s])),this.tiles.push(i),this.sort(),o}if(this.count(i.getFamily(),i.getValue()-1)*this.count(i.getFamily(),i.getValue()-2)>0&&(r=this.find(i.getFamily(),i.getValue()-1),s=this.find(i.getFamily(),i.getValue()-2),o=this.toGroup(t),this.tiles.push(r),this.tiles.push(s),this.sort(),void 0!==o))return o.push(new e([s,r,i])),this.tiles.push(i),this.sort(),o;this.tiles.push(i),this.tiles.sort()},i.prototype.drawHand=function(t,e,i,n,r,o,s,l){void 0===o&&(o=void 0),void 0===s&&(s=!1),void 0===l&&(l=0);for(var u=(75+n)*r,a=Math.cos(l)*u,h=Math.sin(l)*u,c=0;c0&&r[r.length-1])||6!==l[0]&&2!==l[0])){o=0;continue}if(3===l[0]&&(!r||l[1]>r[0]&&l[1]0;){var i=Math.floor(Math.random()*this.tiles.length);t=[this.tiles[0],this.tiles[i]],this.tiles[i]=t[0],this.tiles[0]=t[1],e.push(this.tiles.shift())}this.tiles=e},e.prototype.getRandomHand=function(){var t=new i;this.shuffle();for(var e=0;e<13;e++)t.push(this.pop());return t},e.prototype.cleanup=function(){this.tiles.forEach((function(t){return t.cleanup()})),this.tiles=[]},e.prototype.preload=function(){return t=this,e=void 0,n=function(){var t;return function(t,e){var i,n,r,o={label:0,sent:function(){if(1&r[0])throw r[1];return r[1]},trys:[],ops:[]},s=Object.create(("function"==typeof Iterator?Iterator:Object).prototype);return s.next=l(0),s.throw=l(1),s.return=l(2),"function"==typeof Symbol&&(s[Symbol.iterator]=function(){return this}),s;function l(l){return function(u){return function(l){if(i)throw new TypeError("Generator is already executing.");for(;s&&(s=0,l[0]&&(o=0)),o;)try{if(i=1,n&&(r=2&l[0]?n.return:l[0]?n.throw||((r=n.return)&&r.call(n),0):n.next)&&!(r=r.call(n,l[1])).done)return r;switch(n=0,r&&(l=[2&l[0],r.value]),l[0]){case 0:case 1:r=l;break;case 4:return o.label++,{value:l[1],done:!1};case 5:o.label++,n=l[1],l=[0];continue;case 7:l=o.ops.pop(),o.trys.pop();continue;default:if(!((r=(r=o.trys).length>0&&r[r.length-1])||6!==l[0]&&2!==l[0])){o=0;continue}if(3===l[0]&&(!r||l[1]>r[0]&&l[1]0&&r[r.length-1])||6!==l[0]&&2!==l[0])){o=0;continue}if(3===l[0]&&(!r||l[1]>r[0]&&l[1]{"use strict";var t=function(){function t(t,e,n){this.family=t,this.value=e,this.red=n,this.loadded=!1,this.imgSrc="",this.imgFront=new Image,this.imgBack=new Image,this.img=new Image,this.setImgSrc()}return t.prototype.getFamily=function(){return this.family},t.prototype.getValue=function(){return this.value},t.prototype.isRed=function(){return this.red},t.prototype.drawTile=function(t,e,n,i){t.drawImage(this.imgFront,e,n,75*i,100*i),t.drawImage(this.img,e,n,75*i,100*i)},t.prototype.isLessThan=function(t){return this.family0&&r[r.length-1])||6!==a[0]&&2!==a[0])){o=0;continue}if(3===a[0]&&(!r||a[1]>r[0]&&a[1]0&&r[r.length-1])||6!==a[0]&&2!==a[0])){o=0;continue}if(3===a[0]&&(!r||a[1]>r[0]&&a[1]0;){var n=Math.floor(Math.random()*this.tiles.length);t=[this.tiles[0],this.tiles[n]],this.tiles[n]=t[0],this.tiles[0]=t[1],e.push(this.tiles.shift())}this.tiles=e},n.prototype.getRandomHand=function(){var t=new e;this.shuffle();for(var n=0;n<13;n++)t.push(this.pop());return t},n.prototype.cleanup=function(){this.tiles.forEach((function(t){return t.cleanup()})),this.tiles=[]},n.prototype.preload=function(){return t=this,e=void 0,i=function(){var t;return function(t,e){var n,i,r,o={label:0,sent:function(){if(1&r[0])throw r[1];return r[1]},trys:[],ops:[]},s=Object.create(("function"==typeof Iterator?Iterator:Object).prototype);return s.next=a(0),s.throw=a(1),s.return=a(2),"function"==typeof Symbol&&(s[Symbol.iterator]=function(){return this}),s;function a(a){return function(l){return function(a){if(n)throw new TypeError("Generator is already executing.");for(;s&&(s=0,a[0]&&(o=0)),o;)try{if(n=1,i&&(r=2&a[0]?i.return:a[0]?i.throw||((r=i.return)&&r.call(i),0):i.next)&&!(r=r.call(i,a[1])).done)return r;switch(i=0,r&&(a=[2&a[0],r.value]),a[0]){case 0:case 1:r=a;break;case 4:return o.label++,{value:a[1],done:!1};case 5:o.label++,i=a[1],a=[0];continue;case 7:a=o.ops.pop(),o.trys.pop();continue;default:if(!((r=(r=o.trys).length>0&&r[r.length-1])||6!==a[0]&&2!==a[0])){o=0;continue}if(3===a[0]&&(!r||a[1]>r[0]&&a[1]0&&r[r.length-1])||6!==a[0]&&2!==a[0])){o=0;continue}if(3===a[0]&&(!r||a[1]>r[0]&&a[1]=u&&(l=t,x()),requestAnimationFrame(I)},o.addEventListener("mousemove",(function(t){var e=o.getBoundingClientRect(),n=t.clientX-e.left-c,i=t.clientY-e.top,r=Math.floor(n/(80*p));b=n-80*r*p<=75&&r>=0&&r<14&&i>=800&&i<=800+100*p?r:void 0})),requestAnimationFrame(I),window.cleanup=function(){d.cleanup(),y.forEach((function(t){return t.cleanup()})),y=[],m.cleanup(),w.cleanup(),t.clearRect(0,0,o.width,o.height),a.clearRect(0,0,e.width,e.height),b=void 0},[3,4];case 3:console.error("Impossible d'obtenir le contexte du canvas."),k.label=4;case 4:return[3,6];case 5:console.error("Canvas introuvable dans le DOM."),k.label=6;case 6:return[2]}}))}))}()})(); \ No newline at end of file +(()=>{"use strict";var t=function(){function t(t,e,i){this.family=t,this.value=e,this.red=i,this.imgSrc="",this.imgFront=new Image,this.imgBack=new Image,this.img=new Image,this.tilt=0,this.setImgSrc()}return t.prototype.getFamily=function(){return this.family},t.prototype.getValue=function(){return this.value},t.prototype.isRed=function(){return this.red},t.prototype.setTilt=function(){this.tilt=.05*(1-2*Math.random())},t.prototype.drawTile=function(t,e,i,n,r,o){void 0===r&&(r=!1),void 0===o&&(o=0),t.save(),t.translate(e+75*n/2,i+100*n/2),t.rotate(o+this.tilt),r?t.drawImage(this.imgBack,-75*n/2,-100*n/2,75*n,100*n):(t.drawImage(this.imgFront,-75*n/2,-100*n/2,75*n,100*n),t.drawImage(this.img,-75*n/2,-100*n/2,75*n,100*n)),t.restore()},t.prototype.isLessThan=function(t){return this.family0&&r[r.length-1])||6!==l[0]&&2!==l[0])){o=0;continue}if(3===l[0]&&(!r||l[1]>r[0]&&l[1]0))return[];var i=this.tiles.pop(),n=this.count(i.getFamily(),i.getValue());if(n>=1&&!t){var r=this.find(i.getFamily(),i.getValue()),o=this.toGroup(!0);if(this.tiles.push(r),this.sort(),void 0!==o)return this.tiles.push(i),this.sort(),o.push(new e([i,r])),o}if(n>=2){r=this.find(i.getFamily(),i.getValue());var s=this.find(i.getFamily(),i.getValue());if(o=this.toGroup(t),this.tiles.push(r),this.tiles.push(s),this.sort(),void 0!==o)return o.push(new e([i,r,s])),this.tiles.push(i),this.sort(),o}if(this.count(i.getFamily(),i.getValue()-1)*this.count(i.getFamily(),i.getValue()-2)>0&&(r=this.find(i.getFamily(),i.getValue()-1),s=this.find(i.getFamily(),i.getValue()-2),o=this.toGroup(t),this.tiles.push(r),this.tiles.push(s),this.sort(),void 0!==o))return o.push(new e([s,r,i])),this.tiles.push(i),this.sort(),o;this.tiles.push(i),this.tiles.sort()},i.prototype.drawHand=function(t,e,i,n,r,o,s,l){void 0===o&&(o=void 0),void 0===s&&(s=!1),void 0===l&&(l=0);for(var a=(75+n)*r,u=Math.cos(l)*a,h=Math.sin(l)*a,c=0;c0&&r[r.length-1])||6!==l[0]&&2!==l[0])){o=0;continue}if(3===l[0]&&(!r||l[1]>r[0]&&l[1]0;){var i=Math.floor(Math.random()*this.tiles.length);t=[this.tiles[0],this.tiles[i]],this.tiles[i]=t[0],this.tiles[0]=t[1],e.push(this.tiles.shift())}this.tiles=e},e.prototype.getRandomHand=function(){var t=new i;this.shuffle();for(var e=0;e<13;e++)t.push(this.pop());return t},e.prototype.cleanup=function(){this.tiles.forEach((function(t){return t.cleanup()})),this.tiles=[]},e.prototype.preload=function(){return t=this,e=void 0,n=function(){var t;return function(t,e){var i,n,r,o={label:0,sent:function(){if(1&r[0])throw r[1];return r[1]},trys:[],ops:[]},s=Object.create(("function"==typeof Iterator?Iterator:Object).prototype);return s.next=l(0),s.throw=l(1),s.return=l(2),"function"==typeof Symbol&&(s[Symbol.iterator]=function(){return this}),s;function l(l){return function(a){return function(l){if(i)throw new TypeError("Generator is already executing.");for(;s&&(s=0,l[0]&&(o=0)),o;)try{if(i=1,n&&(r=2&l[0]?n.return:l[0]?n.throw||((r=n.return)&&r.call(n),0):n.next)&&!(r=r.call(n,l[1])).done)return r;switch(n=0,r&&(l=[2&l[0],r.value]),l[0]){case 0:case 1:r=l;break;case 4:return o.label++,{value:l[1],done:!1};case 5:o.label++,n=l[1],l=[0];continue;case 7:l=o.ops.pop(),o.trys.pop();continue;default:if(!((r=(r=o.trys).length>0&&r[r.length-1])||6!==l[0]&&2!==l[0])){o=0;continue}if(3===l[0]&&(!r||l[1]>r[0]&&l[1]0&&r[r.length-1])||6!==l[0]&&2!==l[0])){o=0;continue}if(3===l[0]&&(!r||l[1]>r[0]&&l[1]=u&&(a=t,x()),requestAnimationFrame(F)},s.addEventListener("mousemove",(function(t){var e=s.getBoundingClientRect(),i=t.clientX-e.left-h,n=t.clientY-e.top,r=Math.floor(i/(80*p));b=i-80*r*p<=75&&r>=0&&r<14&&n>=800&&n<=800+100*p?r:void 0})),s.addEventListener("mousedown",(function(t){void 0!==b&&(m.push(w.eject(b)),m.shuffle(),w.push(m.pop()),w.sort())})),requestAnimationFrame(F),window.cleanup=function(){d.cleanup(),y.forEach((function(t){return t.cleanup()})),y=[],m.cleanup(),w.cleanup(),t.clearRect(0,0,s.width,s.height),i.clearRect(0,0,e.width,e.height),b=void 0},[3,4];case 3:console.error("Impossible d'obtenir le contexte du canvas."),k.label=4;case 4:return[3,6];case 5:console.error("Canvas introuvable dans le DOM."),k.label=6;case 6:return[2]}}))}))}()})(); \ No newline at end of file diff --git a/build/dp3.js b/build/dp3.js new file mode 100644 index 0000000..7862931 --- /dev/null +++ b/build/dp3.js @@ -0,0 +1 @@ +(()=>{"use strict";var t,e=function(){function t(t,e,i){this.family=t,this.value=e,this.red=i,this.imgSrc="",this.imgFront=new Image,this.imgBack=new Image,this.img=new Image,this.tilt=0,this.setImgSrc()}return t.prototype.getFamily=function(){return this.family},t.prototype.getValue=function(){return this.value},t.prototype.isRed=function(){return this.red},t.prototype.setTilt=function(){this.tilt=.05*(1-2*Math.random())},t.prototype.drawTile=function(t,e,i,n,r,o){void 0===r&&(r=!1),void 0===o&&(o=0),t.save(),t.translate(e+75*n/2,i+100*n/2),t.rotate(o+this.tilt),r?t.drawImage(this.imgBack,-75*n/2,-100*n/2,75*n,100*n):(t.drawImage(this.imgFront,-75*n/2,-100*n/2,75*n,100*n),t.drawImage(this.img,-75*n/2,-100*n/2,75*n,100*n)),t.restore()},t.prototype.isLessThan=function(t){return this.family0&&r[r.length-1])||6!==l[0]&&2!==l[0])){o=0;continue}if(3===l[0]&&(!r||l[1]>r[0]&&l[1]0))return[];var e=this.tiles.pop(),n=this.count(e.getFamily(),e.getValue());if(n>=1&&!t){var r=this.find(e.getFamily(),e.getValue()),o=this.toGroup(!0);if(this.tiles.push(r),this.sort(),void 0!==o)return this.tiles.push(e),this.sort(),o.push(new i([e,r])),o}if(n>=2){r=this.find(e.getFamily(),e.getValue());var s=this.find(e.getFamily(),e.getValue());if(o=this.toGroup(t),this.tiles.push(r),this.tiles.push(s),this.sort(),void 0!==o)return o.push(new i([e,r,s])),this.tiles.push(e),this.sort(),o}if(this.count(e.getFamily(),e.getValue()-1)*this.count(e.getFamily(),e.getValue()-2)>0&&(r=this.find(e.getFamily(),e.getValue()-1),s=this.find(e.getFamily(),e.getValue()-2),o=this.toGroup(t),this.tiles.push(r),this.tiles.push(s),this.sort(),void 0!==o))return o.push(new i([s,r,e])),this.tiles.push(e),this.sort(),o;this.tiles.push(e),this.tiles.sort()},t.prototype.drawHand=function(t,e,i,n,r,o,s,l){void 0===o&&(o=void 0),void 0===s&&(s=!1),void 0===l&&(l=0);for(var a=(75+n)*r,u=Math.cos(l)*a,h=Math.sin(l)*a,c=0;c0&&r[r.length-1])||6!==l[0]&&2!==l[0])){o=0;continue}if(3===l[0]&&(!r||l[1]>r[0]&&l[1]0;){var i=Math.floor(Math.random()*this.tiles.length);t=[this.tiles[0],this.tiles[i]],this.tiles[i]=t[0],this.tiles[0]=t[1],e.push(this.tiles.shift())}this.tiles=e},t.prototype.getRandomHand=function(){var t=new n;this.shuffle();for(var e=0;e<13;e++)t.push(this.pop());return t},t.prototype.cleanup=function(){this.tiles.forEach((function(t){return t.cleanup()})),this.tiles=[]},t.prototype.preload=function(){return t=this,e=void 0,n=function(){var t;return function(t,e){var i,n,r,o={label:0,sent:function(){if(1&r[0])throw r[1];return r[1]},trys:[],ops:[]},s=Object.create(("function"==typeof Iterator?Iterator:Object).prototype);return s.next=l(0),s.throw=l(1),s.return=l(2),"function"==typeof Symbol&&(s[Symbol.iterator]=function(){return this}),s;function l(l){return function(a){return function(l){if(i)throw new TypeError("Generator is already executing.");for(;s&&(s=0,l[0]&&(o=0)),o;)try{if(i=1,n&&(r=2&l[0]?n.return:l[0]?n.throw||((r=n.return)&&r.call(n),0):n.next)&&!(r=r.call(n,l[1])).done)return r;switch(n=0,r&&(l=[2&l[0],r.value]),l[0]){case 0:case 1:r=l;break;case 4:return o.label++,{value:l[1],done:!1};case 5:o.label++,n=l[1],l=[0];continue;case 7:l=o.ops.pop(),o.trys.pop();continue;default:if(!((r=(r=o.trys).length>0&&r[r.length-1])||6!==l[0]&&2!==l[0])){o=0;continue}if(3===l[0]&&(!r||l[1]>r[0]&&l[1]0&&r[r.length-1])||6!==l[0]&&2!==l[0])){o=0;continue}if(3===l[0]&&(!r||l[1]>r[0]&&l[1]=0&&r<14&&n>=800&&n<=875?r:void 0},i=function(t){void 0!==h&&(a[0].push(u[8].eject(h)),a[0].shuffle(),u[8].push(a[0].pop()),u[8].sort())},f.push((function(){p.removeEventListener("mousemove",e),p.removeEventListener("mousedown",i)})),p.addEventListener("mousemove",e),p.addEventListener("mousedown",i),requestAnimationFrame(m),window.cleanup=g,[2]}var e,i}))}))}().catch(console.error)})(); \ No newline at end of file diff --git a/build/dp4.js b/build/dp4.js new file mode 100644 index 0000000..89677a5 --- /dev/null +++ b/build/dp4.js @@ -0,0 +1 @@ +(()=>{"use strict";var t,e,n,i=function(){function t(t,e,n){this.family=t,this.value=e,this.red=n,this.imgSrc="",this.imgFront=new Image,this.imgBack=new Image,this.img=new Image,this.tilt=0,this.setImgSrc()}return t.prototype.getFamily=function(){return this.family},t.prototype.getValue=function(){return this.value},t.prototype.isRed=function(){return this.red},t.prototype.setTilt=function(){this.tilt=.05*(1-2*Math.random())},t.prototype.drawTile=function(t,e,n,i,r,o){void 0===r&&(r=!1),void 0===o&&(o=0),t.save(),t.translate(e+75*i/2,n+100*i/2),t.rotate(o+this.tilt),r?t.drawImage(this.imgBack,-75*i/2,-100*i/2,75*i,100*i):(t.drawImage(this.imgFront,-75*i/2,-100*i/2,75*i,100*i),t.drawImage(this.img,-75*i/2,-100*i/2,75*i,100*i)),t.restore()},t.prototype.isLessThan=function(t){return this.family0&&r[r.length-1])||6!==a[0]&&2!==a[0])){o=0;continue}if(3===a[0]&&(!r||a[1]>r[0]&&a[1]0))return[];var e=this.tiles.pop(),n=this.count(e.getFamily(),e.getValue());if(n>=1&&!t){var i=this.find(e.getFamily(),e.getValue()),o=this.toGroup(!0);if(this.tiles.push(i),this.sort(),void 0!==o)return this.tiles.push(e),this.sort(),o.push(new r([e,i])),o}if(n>=2){i=this.find(e.getFamily(),e.getValue());var s=this.find(e.getFamily(),e.getValue());if(o=this.toGroup(t),this.tiles.push(i),this.tiles.push(s),this.sort(),void 0!==o)return o.push(new r([e,i,s])),this.tiles.push(e),this.sort(),o}if(this.count(e.getFamily(),e.getValue()-1)*this.count(e.getFamily(),e.getValue()-2)>0&&(i=this.find(e.getFamily(),e.getValue()-1),s=this.find(e.getFamily(),e.getValue()-2),o=this.toGroup(t),this.tiles.push(i),this.tiles.push(s),this.sort(),void 0!==o))return o.push(new r([s,i,e])),this.tiles.push(e),this.sort(),o;this.tiles.push(e),this.tiles.sort()},t.prototype.drawHand=function(t,e,n,i,r,o,s,a){void 0===o&&(o=void 0),void 0===s&&(s=!1),void 0===a&&(a=0);for(var l=(75+i)*r,u=Math.cos(a)*l,c=Math.sin(a)*l,h=0;h0&&r[r.length-1])||6!==a[0]&&2!==a[0])){o=0;continue}if(3===a[0]&&(!r||a[1]>r[0]&&a[1]0;){var n=Math.floor(Math.random()*this.tiles.length);t=[this.tiles[0],this.tiles[n]],this.tiles[n]=t[0],this.tiles[0]=t[1],e.push(this.tiles.shift())}this.tiles=e},t.prototype.getRandomHand=function(){var t=new o;this.shuffle();for(var e=0;e<13;e++)t.push(this.pop());return t},t.prototype.cleanup=function(){this.tiles.forEach((function(t){return t.cleanup()})),this.tiles=[]},t.prototype.preload=function(){return t=this,e=void 0,i=function(){var t;return function(t,e){var n,i,r,o={label:0,sent:function(){if(1&r[0])throw r[1];return r[1]},trys:[],ops:[]},s=Object.create(("function"==typeof Iterator?Iterator:Object).prototype);return s.next=a(0),s.throw=a(1),s.return=a(2),"function"==typeof Symbol&&(s[Symbol.iterator]=function(){return this}),s;function a(a){return function(l){return function(a){if(n)throw new TypeError("Generator is already executing.");for(;s&&(s=0,a[0]&&(o=0)),o;)try{if(n=1,i&&(r=2&a[0]?i.return:a[0]?i.throw||((r=i.return)&&r.call(i),0):i.next)&&!(r=r.call(i,a[1])).done)return r;switch(i=0,r&&(a=[2&a[0],r.value]),a[0]){case 0:case 1:r=a;break;case 4:return o.label++,{value:a[1],done:!1};case 5:o.label++,i=a[1],a=[0];continue;case 7:a=o.ops.pop(),o.trys.pop();continue;default:if(!((r=(r=o.trys).length>0&&r[r.length-1])||6!==a[0]&&2!==a[0])){o=0;continue}if(3===a[0]&&(!r||a[1]>r[0]&&a[1]0&&r[r.length-1])||6!==a[0]&&2!==a[0])){o=0;continue}if(3===a[0]&&(!r||a[1]>r[0]&&a[1]0&&r[r.length-1])||6!==a[0]&&2!==a[0])){o=0;continue}if(3===a[0]&&(!r||a[1]>r[0]&&a[1]500&&t.getDeck().length()>0){d=i;var r=Math.floor(Math.random()*t.getHands()[p].length());null==t||t.discard(p,r),p=(p+1)%4,null==t||t.pick(p),null==t||t.getHands()[0].sort()}var o=i-y;o=0&&s=910&&o<=985?s:void 0},r=function(n){0===p&&void 0!==e&&t.getDeck().length()>0&&(null==t||t.discard(0,e),p++,null==t||t.pick(p))},v.push((function(){g.removeEventListener("mousemove",i),g.removeEventListener("mousedown",r)})),g.addEventListener("mousemove",i),g.addEventListener("mousedown",r),requestAnimationFrame(k),window.cleanup=x,[2]}var i,r}))}))}().catch(console.error)})(); \ No newline at end of file diff --git a/index.html b/index.html index 11b073a..6430e74 100644 --- a/index.html +++ b/index.html @@ -8,13 +8,14 @@ font-family: Arial, sans-serif; margin: 0; padding: 0; - background-color: #F0EDFF; + background-color: #007730; } .menu { display: flex; justify-content: center; background-color: #4CAF50; - padding: 10px 0; + padding: 0px 0; + font-size: 26px; } .menu-item { position: relative; @@ -33,15 +34,22 @@ display: none; position: absolute; top: 100%; - left: 0; + left: 50%; + transform: translateX(-40%); background-color: white; - box-shadow: 0px 4px 6px rgba(0, 0, 0, 0.1); + box-shadow: 0px 5px 8px rgba(0, 0, 0, 0.1); + min-width: 200px; + white-space: nowrap; + font-size: 20px; } .dropdown a { color: black; text-decoration: none; - padding: 10px 20px; + padding: 10px 10px; display: block; + white-space: nowrap; + width: 100%; + box-sizing: border-box; } .dropdown a:hover { background-color: #ddd; @@ -53,20 +61,43 @@
diff --git a/src/deck.ts b/src/deck.ts index 632e30a..f3ec44f 100644 --- a/src/deck.ts +++ b/src/deck.ts @@ -46,12 +46,20 @@ export class Deck { } } + public length(): number { + return this.tiles.length; + } + public pop(): Tile { if (this.tiles.length === 0) { } return this.tiles.pop() as NonNullable; } + public push(tile: Tile) { + this.tiles.push(tile); + } + public find(family: number, value: number): Tile | undefined { let n = undefined; for (let i = 0; i < this.tiles.length; i++) { diff --git a/src/display/dp2.ts b/src/display/dp2.ts index b70ae31..a631744 100644 --- a/src/display/dp2.ts +++ b/src/display/dp2.ts @@ -31,7 +31,7 @@ async function display () { const interval = 1000 / FPS; // tuiles - let x = 150; + let x = 100; let y = 150; let os = 75; let size = 0.75; @@ -49,6 +49,7 @@ async function display () { const edeck = new Deck(false); await edeck.preload(); const ehand = edeck.getRandomHand(); + ehand.push(edeck.pop()); ehand.sort(); let selectedTile: number|undefined = undefined; @@ -106,6 +107,17 @@ async function display () { } } ); + canvas.addEventListener( + "mousedown", + (event) => { + if (selectedTile !== undefined) { + edeck.push(ehand.eject(selectedTile)); + edeck.shuffle(); + ehand.push(edeck.pop()); + ehand.sort(); + } + } + ); requestAnimationFrame(animationLoop); diff --git a/src/display/dp3.ts b/src/display/dp3.ts new file mode 100644 index 0000000..053ef9f --- /dev/null +++ b/src/display/dp3.ts @@ -0,0 +1,192 @@ +import { Deck } from "../deck"; +import { Hand } from "../hand"; +import { Group } from "../group" + +// Configuration globale +const CANVAS_ID = "myCanvas"; +const BG_COLOR = "#007730"; +const BG_RECT = { x: 50, y: 50, w: 1000, h: 1000 }; +const FPS = 30; +const FRAME_INTERVAL = 1000 / FPS; + +// variables globales +const DECKS: Array = []; +const HANDS: Array = []; +let selectedTile: number|undefined = undefined; + +// Optimisation des références +let animationFrameId: number; +let lastFrameTime = 0; +const callbacks: Array<() => void> = []; + +// Pré-calcul des dimensions +const canvas = document.getElementById(CANVAS_ID) as HTMLCanvasElement; +const ctx = canvas.getContext("2d") as NonNullable; + +// Cache statique +const staticCanvas = document.createElement('canvas') as HTMLCanvasElement; +const staticCtx = staticCanvas.getContext("2d") as NonNullable; +staticCanvas.width = canvas.width; +staticCanvas.height = canvas.height; + +// Pré-rendu du fond +function prerenderBackground() { + staticCtx.clearRect(0, 0, canvas.width, canvas.height); + staticCtx.fillStyle = BG_COLOR; + staticCtx.fillRect(BG_RECT.x, BG_RECT.y, BG_RECT.w, BG_RECT.h); +}; + +function drawFrame() { + if (!ctx) return; + + // Effacement intelligent (uniquement la zone nécessaire) + prerenderBackground(); + + // Ici viendrait le dessin des éléments dynamiques + // Par exemple: + // drawDeck(); + // drawHands(); + let x = 300; + let y = 150; + let xos = 250; + let yos = 100; + let size = 0.75; + + staticCtx.fillStyle = "#DFDFFF"; + staticCtx.font = "50px serif"; + + staticCtx.fillText("Chii:", 75, y + 100 * size - 5); + HANDS[0].drawHand(staticCtx, x, y, 5, 0.75); // chii + HANDS[1].drawHand(staticCtx, x + (75+xos)*size, y, 5, 0.75); + + staticCtx.fillText("Pon:", 75, y + (100+yos)*size + 100 * size - 5); + HANDS[2].drawHand(staticCtx, x, y + (100+yos)*size, 5, 0.75); // pon + HANDS[3].drawHand(staticCtx, x + (75+xos)*size, y + (100+yos)*size, 5, 0.75); + HANDS[4].drawHand(staticCtx, x + 2*(75+xos)*size, y + 2*(100+yos)*size, 5, 0.75); + + staticCtx.fillText("Invalide:", 75, y + 2*(100+yos)*size + 100 * size - 5); + HANDS[5].drawHand(staticCtx, x, y + 2*(100+yos)*size, 5, 0.75); // wrong + HANDS[6].drawHand(staticCtx, x + (75+xos)*size, y + 2*(100+yos)*size, 5, 0.75); + HANDS[7].drawHand(staticCtx, x + 2*(75+xos)*size, y + 2*(100+yos)*size, 5, 0.75); + + HANDS[8].drawHand(staticCtx, 100, 800, 5, size, selectedTile); + + let groups = HANDS[8].toGroup(); + if (groups !== undefined) { + staticCtx.fillStyle = "#FF0000"; + staticCtx.font = "50px serif"; + staticCtx.fillText("Tous les groupes sont formés !", 100, 750); + } + groups = []; + + // Dessin du cache statique + ctx.clearRect(0, 0, canvas.width, canvas.height); + ctx.drawImage(staticCanvas, 0, 0); +} + +function animationLoop(currentTime: number) { + animationFrameId = requestAnimationFrame(animationLoop); + + const deltaTime = currentTime - lastFrameTime; + if (deltaTime < FRAME_INTERVAL) return; + + lastFrameTime = currentTime - (deltaTime % FRAME_INTERVAL); + drawFrame(); +} + +function initEventListeners() { + const handlers = { + mousemove: (e: MouseEvent) => { + let size = 0.75; + let x = 100; + // Logique de gestion du mouvement de la souris + const rect = canvas.getBoundingClientRect(); + const mouseX = e.clientX - rect.left - x; + const mouseY = e.clientY - rect.top; + + let q = Math.floor(mouseX / (80 * size)); + let r = mouseX - q * 80 * size; + if (r <= 75 && q >= 0 && q < 14 && mouseY >= 800 && mouseY <= 800 + 100*size) { + selectedTile = q; + } else { + selectedTile = undefined; + } + }, + mousedown: (e: MouseEvent) => { + // Logique de gestion du clic de souris + if (selectedTile !== undefined) { + DECKS[0].push(HANDS[8].eject(selectedTile)); + DECKS[0].shuffle(); + HANDS[8].push(DECKS[0].pop()); + HANDS[8].sort(); + } + } + }; + + callbacks.push(() => { + canvas.removeEventListener('mousemove', handlers.mousemove); + canvas.removeEventListener('mousedown', handlers.mousedown); + }); + + canvas.addEventListener('mousemove', handlers.mousemove); + canvas.addEventListener('mousedown', handlers.mousedown); +} + +async function preloadDeck(deck: Deck) { + await deck.preload(); +} +async function preloadHand(hand: Hand) { + await hand.preload(); +} + +export function cleanup() { + cancelAnimationFrame(animationFrameId); + callbacks.forEach(fn => fn()); +} + +export async function initDisplay() { + if (!ctx) { + console.error("Context canvas indisponible"); + return; + } + + // Préchargement des ressources si nécessaire + // const deck = new Deck(); + // await preloadDeck(deck); + DECKS.push( + new Deck(false) + ); + HANDS.push( + new Hand("s1s2s3"), + new Hand("m2m3m4"), + new Hand("p5p5p5"), + new Hand("w2w2w2"), + new Hand("d3d3d3"), + new Hand("s4p5m6"), + new Hand("m9s9p9"), + new Hand("d1d2d3"), + DECKS[0].getRandomHand() + ); + await Promise.all(DECKS.map(d => preloadDeck(d))); + await Promise.all(HANDS.map(h => preloadHand(h))); + + HANDS[8].push(DECKS[0].pop()); + HANDS[8].sort(); + + initEventListeners(); + requestAnimationFrame(animationLoop); + window.cleanup = cleanup; +} + +// Déclaration globale pour TypeScript +declare global { + interface Window { + cleanup: () => void; + } +} + +// Initialisation automatique si le script est chargé directement +if (typeof window !== 'undefined') { + initDisplay().catch(console.error); +} + diff --git a/src/display/dp4.ts b/src/display/dp4.ts new file mode 100644 index 0000000..5910eaf --- /dev/null +++ b/src/display/dp4.ts @@ -0,0 +1,185 @@ +import { Deck } from "../deck"; +import { Hand } from "../hand"; +import { Group } from "../group"; +import { Game } from "../game" + +// Configuration globale +const CANVAS_ID = "myCanvas"; +const BG_COLOR = "#007730"; +const BG_RECT = { x: 50, y: 50, w: 1000, h: 1000 }; +const FPS = 30; +const FRAME_INTERVAL = 1000 / FPS; + +// variables globales +const DECKS: Array = []; +const HANDS: Array = []; +var GAME: Game|undefined; + +// variables for the game +var selectedTile: number|undefined; +var turn: number = 0; +var hasPlayed: boolean = false; +var pCurrentTime = 0; +var pDeltaTime = 500; + +// Optimisation des références +let animationFrameId: number; +let lastFrameTime = 0; +const callbacks: Array<() => void> = []; + +// Pré-calcul des dimensions +const canvas = document.getElementById(CANVAS_ID) as HTMLCanvasElement; +const ctx = canvas.getContext("2d") as NonNullable; + +// Cache statique +const staticCanvas = document.createElement('canvas') as HTMLCanvasElement; +const staticCtx = staticCanvas.getContext("2d") as NonNullable; +staticCanvas.width = canvas.width; +staticCanvas.height = canvas.height; + +// Pré-rendu du fond +function prerenderBackground() { + staticCtx.clearRect(0, 0, canvas.width, canvas.height); + staticCtx.fillStyle = BG_COLOR; + staticCtx.fillRect(BG_RECT.x, BG_RECT.y, BG_RECT.w, BG_RECT.h); +}; + +function drawFrame() { + if (!ctx) return; + + let size = 0.65; + let os = 5; + let w = size * (450 + 5 * os); + let center = 525; + + // Effacement intelligent (uniquement la zone nécessaire) + prerenderBackground(); + + // Ici viendrait le dessin des éléments dynamiques + // Par exemple: + // drawDeck(); + // drawHands(); + // staticCtx.fillStyle = "#005530"; + // staticCtx.fillRect(center - w/2, center - w/2, w, w); + + GAME?.drawGame(staticCtx, size, 0.6, selectedTile); + + // Dessin du cache statique + ctx.clearRect(0, 0, canvas.width, canvas.height); + ctx.drawImage(staticCanvas, 0, 0); +} + +function animationLoop(currentTime: number) { + animationFrameId = requestAnimationFrame(animationLoop); + + // bot playing + if (turn !== 0 && (currentTime - pCurrentTime) > pDeltaTime && (GAME as NonNullable).getDeck().length() > 0) { + pCurrentTime = currentTime; + let n = Math.floor(Math.random() * (GAME as NonNullable).getHands()[turn].length()); + GAME?.discard(turn, n); + turn = (turn + 1) % 4; + GAME?.pick(turn); + GAME?.getHands()[0].sort(); + } + + const deltaTime = currentTime - lastFrameTime; + if (deltaTime < FRAME_INTERVAL) return; + + lastFrameTime = currentTime - (deltaTime % FRAME_INTERVAL); + drawFrame(); +} + +function initEventListeners() { + const handlers = { + mousemove: (e: MouseEvent) => { + // Logique de gestion du mouvement de la souris + let size = 0.75; + let x = 2.5 * 75 * 0.75; + let y = 1000 - 150 * 0.6; + const rect = canvas.getBoundingClientRect(); + const mouseX = e.clientX - rect.left - x; + const mouseY = e.clientY - rect.top; + + let q = Math.floor(mouseX / (80 * size)); + let r = mouseX - q * 80 * size; + if ( + r <= 75 && + q >= 0 && + q < (GAME as NonNullable).getHands()[0].length() && + mouseY >= y && + mouseY <= y + 100 * size + ) { + selectedTile = q; + } else { + selectedTile = undefined; + } + }, + mousedown: (e: MouseEvent) => { + // Logique de gestion du clic de souris + if (turn === 0 && selectedTile !== undefined && (GAME as NonNullable).getDeck().length() > 0) { + GAME?.discard(0, selectedTile); + turn++; + GAME?.pick(turn); + } + } + }; + + callbacks.push(() => { + canvas.removeEventListener('mousemove', handlers.mousemove); + canvas.removeEventListener('mousedown', handlers.mousedown); + }); + + canvas.addEventListener('mousemove', handlers.mousemove); + canvas.addEventListener('mousedown', handlers.mousedown); +} + +async function preloadDeck(deck: Deck) { + await deck.preload(); +} +async function preloadHand(hand: Hand) { + await hand.preload(); +} + +export function cleanup() { + cancelAnimationFrame(animationFrameId); + callbacks.forEach(fn => fn()); +} + +export async function initDisplay() { + if (!ctx) { + console.error("Context canvas indisponible"); + return; + } + + // Préchargement des ressources si nécessaire + // const deck = new Deck(); + // await preloadDeck(deck); + DECKS.push( + ); + HANDS.push( + ); + GAME = new Game(); + await Promise.all(DECKS.map(d => preloadDeck(d))); + await Promise.all(HANDS.map(h => preloadHand(h))); + await GAME?.preload(); + + GAME.pick(0); + GAME.getHands()[0].sort(); + + initEventListeners(); + requestAnimationFrame(animationLoop); + window.cleanup = cleanup; +} + +// Déclaration globale pour TypeScript +declare global { + interface Window { + cleanup: () => void; + } +} + +// Initialisation automatique si le script est chargé directement +if (typeof window !== 'undefined') { + initDisplay().catch(console.error); +} + diff --git a/src/display/template.ts b/src/display/template.ts new file mode 100644 index 0000000..07e752a --- /dev/null +++ b/src/display/template.ts @@ -0,0 +1,127 @@ +import { Deck } from "../deck"; +import { Hand } from "../hand"; +import { Group } from "../group" + +// Configuration globale +const CANVAS_ID = "myCanvas"; +const BG_COLOR = "#007730"; +const BG_RECT = { x: 50, y: 50, w: 1000, h: 1000 }; +const FPS = 30; +const FRAME_INTERVAL = 1000 / FPS; + +// variables globales +const DECKS: Array = []; +const HANDS: Array = []; + +// Optimisation des références +let animationFrameId: number; +let lastFrameTime = 0; +const callbacks: Array<() => void> = []; + +// Pré-calcul des dimensions +const canvas = document.getElementById(CANVAS_ID) as HTMLCanvasElement; +const ctx = canvas.getContext("2d") as NonNullable; + +// Cache statique +const staticCanvas = document.createElement('canvas') as HTMLCanvasElement; +const staticCtx = staticCanvas.getContext("2d") as NonNullable; +staticCanvas.width = canvas.width; +staticCanvas.height = canvas.height; + +// Pré-rendu du fond +function prerenderBackground() { + staticCtx.clearRect(0, 0, canvas.width, canvas.height); + staticCtx.fillStyle = BG_COLOR; + staticCtx.fillRect(BG_RECT.x, BG_RECT.y, BG_RECT.w, BG_RECT.h); +}; + +function drawFrame() { + if (!ctx) return; + + // Effacement intelligent (uniquement la zone nécessaire) + prerenderBackground(); + + // Ici viendrait le dessin des éléments dynamiques + // Par exemple: + // drawDeck(); + // drawHands(); + + // Dessin du cache statique + ctx.clearRect(0, 0, canvas.width, canvas.height); + ctx.drawImage(staticCanvas, 0, 0); +} + +function animationLoop(currentTime: number) { + animationFrameId = requestAnimationFrame(animationLoop); + + const deltaTime = currentTime - lastFrameTime; + if (deltaTime < FRAME_INTERVAL) return; + + lastFrameTime = currentTime - (deltaTime % FRAME_INTERVAL); + drawFrame(); +} + +function initEventListeners() { + const handlers = { + mousemove: (e: MouseEvent) => { + // Logique de gestion du mouvement de la souris + }, + mousedown: (e: MouseEvent) => { + // Logique de gestion du clic de souris + } + }; + + callbacks.push(() => { + canvas.removeEventListener('mousemove', handlers.mousemove); + canvas.removeEventListener('mousedown', handlers.mousedown); + }); + + canvas.addEventListener('mousemove', handlers.mousemove); + canvas.addEventListener('mousedown', handlers.mousedown); +} + +async function preloadDeck(deck: Deck) { + await deck.preload(); +} +async function preloadHand(hand: Hand) { + await hand.preload(); +} + +export function cleanup() { + cancelAnimationFrame(animationFrameId); + callbacks.forEach(fn => fn()); +} + +export async function initDisplay() { + if (!ctx) { + console.error("Context canvas indisponible"); + return; + } + + // Préchargement des ressources si nécessaire + // const deck = new Deck(); + // await preloadDeck(deck); + DECKS.push( + ); + HANDS.push( + ); + await Promise.all(DECKS.map(d => preloadDeck(d))); + await Promise.all(HANDS.map(h => preloadHand(h))); + + initEventListeners(); + requestAnimationFrame(animationLoop); + window.cleanup = cleanup; +} + +// Déclaration globale pour TypeScript +declare global { + interface Window { + cleanup: () => void; + } +} + +// Initialisation automatique si le script est chargé directement +if (typeof window !== 'undefined') { + initDisplay().catch(console.error); +} + diff --git a/src/game.ts b/src/game.ts new file mode 100644 index 0000000..bfdcc5e --- /dev/null +++ b/src/game.ts @@ -0,0 +1,130 @@ +import { Deck } from "./deck"; +import { Hand } from "./hand"; +import { Tile } from "./tile"; + +export class Game { + private deck: Deck; + private hands: Array; + private discards: Array>; + + public constructor(red: boolean = false) { + this.deck = new Deck(red); + this.hands = [ + this.deck.getRandomHand(), + this.deck.getRandomHand(), + this.deck.getRandomHand(), + this.deck.getRandomHand() + ]; + this.discards = [[], [], [], []]; + } + + public getDeck(): Deck { + return this.deck; + } + + public getHands(): Array { + return this.hands; + } + + public drawGame( + ctx: CanvasRenderingContext2D, + discardSize: number, + handSize: number, + selectedTile: number|undefined = undefined + ): void { + const pi = 3.141592; + this.hands[0].drawHand( + ctx, + 2.5 * 75 * 0.75, + 1000 - 150 * handSize, + 5 * handSize, + 0.75, + selectedTile, + false, + 0 + ); + this.hands[1].drawHand( + ctx, + 1000 - 150 * handSize, + 1000 - 75 * 5 * handSize, + 5 * handSize, + handSize, + undefined, + true, + - pi / 2 + ); + this.hands[2].drawHand( + ctx, + 1000 - 75 * 5 * handSize, + 150 * handSize, + 5 * handSize, + handSize, + undefined, + true, + - pi + ); + this.hands[3].drawHand( + ctx, + 150 * handSize, + 75 * 5 * handSize, + 5 * handSize, + handSize, + undefined, + true, + pi / 2 + ); + + for (let i = 0; i < 4; i++) { + this.drawDiscrad(ctx, i, discardSize); + } + } + + public pick(player: number): void { + this.hands[player].push(this.deck.pop()); + } + + public discard(player: number, n: number): void { + let tile = this.hands[player].eject(n); + tile.setTilt(); + this.discards[player].push(tile); + } + + public async preload(): Promise { + await this.deck.preload(); + await Promise.all(this.hands.map(h => h.preload())); + } + + private drawDiscrad( + ctx: CanvasRenderingContext2D, + p: number, + discardSize: number + ): void { + const pi = 3.141592; + + ctx.save(); + ctx.translate(525, 525); + ctx.rotate([0, -pi/2, -pi, pi/2][p]) + + let x = - discardSize * 475 / 2; + let y = discardSize * (475 / 2 + 5); + for (let i = 0; i < this.discards[p].length; i++) { + if (i < 12) { + this.discards[p][i].drawTile( + ctx, + x + (i % 6) * 80 * discardSize, + y + Math.floor(i / 6) * 105 * discardSize, + discardSize + ); + } else { + this.discards[p][i].drawTile( + ctx, + x + (i - 12) * 80 * discardSize, + y + 2 * 105 * discardSize, + discardSize + ); + } + } + + ctx.restore(); + } +} diff --git a/src/group.ts b/src/group.ts new file mode 100644 index 0000000..c646fc1 --- /dev/null +++ b/src/group.ts @@ -0,0 +1,21 @@ +import { Tile } from "./tile" + +export class Group { + private tiles: Array; + + public constructor(tiles: Array = []) { + this.tiles = tiles; + } + + public push(tile: Tile): void { + this.tiles.push(tile); + } + + public pop(): Tile|undefined { + return this.tiles.pop(); + } + + public getTiles(): Array { + return this.tiles; + } +} diff --git a/src/hand.ts b/src/hand.ts index 412f2fa..6d67bba 100644 --- a/src/hand.ts +++ b/src/hand.ts @@ -1,4 +1,5 @@ import { Tile } from "./tile" +import { Group } from "./group" export class Hand { private tiles: Array; @@ -21,6 +22,10 @@ export class Hand { } } + public length(): number { + return this.tiles.length; + } + public push(tile: Tile): undefined { this.tiles.push(tile); } @@ -29,14 +34,103 @@ export class Hand { return this.tiles.pop(); } - public sort(): undefined { + public find(family: number, value: number) :Tile|undefined { + let n = undefined; for (let i = 0; i < this.tiles.length; i++) { - for (let j = 0; j < this.tiles.length-1; j++) { - if (!this.tiles[j].isLessThan(this.tiles[j+1])) { - [this.tiles[j], this.tiles[j+1]] = [this.tiles[j+1], this.tiles[j]]; - } + if (this.tiles[i].getFamily() === family && this.tiles[i].getValue() === value) { + n = i; + break; } } + if (n !== undefined) { + [this.tiles[n], this.tiles[0]] = [this.tiles[0], this.tiles[n]]; + let t = this.tiles.shift(); + this.sort(); + return t; + } else { + return undefined; + } + } + + public eject(idTile: number): Tile { + [this.tiles[0], this.tiles[idTile]] = [this.tiles[idTile], this.tiles[0]]; + let tile = this.tiles.shift(); + this.sort(); + return tile as NonNullable; + } + + public sort(): undefined { + this.tiles.sort((a, b) => a.isLessThan(b) ? -1 : 1); + } + + public count(family: number, value: number): number { + let c = 0; + this.tiles.forEach( + t => { + if (t.getFamily() === family && t.getValue() === value) { + c++; + } + } + ); + return c; + } + + public toGroup(pair: boolean = false): Array|undefined { + if (this.tiles.length > 0) { + let t1 = this.tiles.pop() as NonNullable; + + let c = this.count(t1.getFamily(), t1.getValue()); + if (c >= 1 && !pair) { //can do a pair + let t2 = this.find(t1.getFamily(), t1.getValue()) as NonNullable; + let groups = this.toGroup(true); + this.tiles.push(t2); + this.sort(); + if (groups !== undefined) { + this.tiles.push(t1); + this.sort(); + groups.push(new Group([t1, t2])); + return groups; + } + } + if (c >= 2) { //can do a pon + let t2 = this.find(t1.getFamily(), t1.getValue()) as NonNullable; + let t3 = this.find(t1.getFamily(), t1.getValue()) as NonNullable; + let groups = this.toGroup(pair); + this.tiles.push(t2); + this.tiles.push(t3); + this.sort(); + if (groups !== undefined) { + groups.push(new Group([t1, t2, t3])); + this.tiles.push(t1); + this.sort(); + return groups; + } + } + + let c2 = this.count(t1.getFamily(), t1.getValue()-1); + let c3 = this.count(t1.getFamily(), t1.getValue()-2); + if (c2 * c3 > 0) { //can do a chii + let t2 = this.find(t1.getFamily(), t1.getValue()-1) as NonNullable; + let t3 = this.find(t1.getFamily(), t1.getValue()-2) as NonNullable; + let groups = this.toGroup(pair); + this.tiles.push(t2); + this.tiles.push(t3); + this.sort(); + if (groups !== undefined) { + groups.push(new Group([t3, t2, t1])); + this.tiles.push(t1); + this.sort(); + return groups; + } + } + + this.tiles.push(t1); + this.tiles.sort(); + + } else { + return []; + } + return undefined } public drawHand ( @@ -45,31 +139,38 @@ export class Hand { y: number, offset: number, size: number, - focusedTiled: number|undefined = undefined - ): void { - for (var i = 0; i < this.tiles.length; i++) { + focusedTiled: number|undefined = undefined, + hidden: boolean = false, + rotation: number = 0 + ): void { + let v = (75 + offset) * size; + let vx = Math.cos(rotation) * v; + let vy = Math.sin(rotation) * v; + for (let i = 0; i < this.tiles.length; i++) { if (i === focusedTiled) { this.tiles[i].drawTile( ctx, - x + i * 75 * size + i * offset * size, - y - 25 * size, - size + x + i * vx + 25 * size * Math.sin(rotation), + y + i * vy - 25 * size * Math.cos(rotation), + size, + hidden, + rotation ); } else { this.tiles[i].drawTile( ctx, - x + i * 75 * size + i * offset * size, - y, - size + x + i * vx, + y + i * vy, + size, + hidden, + rotation ); } } } public async preload(): Promise { - for (let i = 0; i < this.tiles.length; i++) { - await this.tiles[i].preloadImg(); - } + await Promise.all(this.tiles.map(t => t.preloadImg())); } public cleanup(): void { diff --git a/src/tile.ts b/src/tile.ts index a68916c..e0e6a2e 100644 --- a/src/tile.ts +++ b/src/tile.ts @@ -2,21 +2,21 @@ export class Tile { private family: number; private value: number; private red: boolean; - private loadded: boolean; private imgSrc: string; private imgFront: HTMLImageElement; private imgBack: HTMLImageElement; private img: HTMLImageElement; + private tilt: number; public constructor(family: number, value: number , red: boolean) { this.family = family; this.value = value; this.red = red; - this.loadded = false; this.imgSrc = ""; this.imgFront = new Image(); this.imgBack = new Image(); this.img = new Image(); + this.tilt = 0; this.setImgSrc(); } @@ -32,14 +32,46 @@ export class Tile { return this.red; } + public setTilt(): void { + this.tilt = (1 - 2 * Math.random()) * 0.05; + } + public drawTile( ctx: CanvasRenderingContext2D, x: number, y: number, - size: number + size: number, + hidden: boolean = false, + rotation: number = 0 ): void { - ctx.drawImage(this.imgFront, x, y, 75 * size, 100 * size); - ctx.drawImage(this.img, x, y, 75 * size, 100 * size); + ctx.save(); + ctx.translate(x + (75 * size) / 2, y + (100 * size) / 2); + ctx.rotate(rotation + this.tilt); + + if (hidden) { + ctx.drawImage( + this.imgBack, + -(75 * size) / 2, + -(100 * size) / 2, + 75 * size, 100 * size + ); + } else { + ctx.drawImage( + this.imgFront, + -(75 * size) / 2, + -(100 * size) / 2, + 75 * size, 100 * size + ); + ctx.drawImage( + this.img, + -(75 * size) / 2, + -(100 * size) / 2, + 75 * size, + 100 * size + ); + } + + ctx.restore(); } public isLessThan(t: Tile): boolean { diff --git a/webpack.config.js b/webpack.config.js index 421abd5..8f456c6 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -1,10 +1,24 @@ const path = require('path'); +const fs = require('fs'); + +// Fonction pour détecter automatiquement les fichiers dp*.ts +function getEntryPoints() { + const displayDir = path.resolve(__dirname, 'src', 'display'); + const files = fs.readdirSync(displayDir); // Lire les fichiers du répertoire + const entryPoints = {}; + + files.forEach((file) => { + if (file.startsWith('dp') && file.endsWith('.ts')) { + const name = path.basename(file, '.ts'); // Nom du fichier sans extension + entryPoints[name] = path.join(displayDir, file); // Chemin complet du fichier + } + }); + + return entryPoints; +} module.exports = { - entry: { - dp1: './src/display/dp1.ts', - dp2: './src/display/dp2.ts' - }, + entry: getEntryPoints(), // Générer automatiquement les points d'entrée output: { filename: '[name].js', path: path.resolve(__dirname, 'build'),