deux pages (presque)
This commit is contained in:
parent
44c3717796
commit
84aeb36f83
9 changed files with 475 additions and 487 deletions
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -1,281 +1,42 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:osb="http://www.openswatchbook.org/uri/2009/osb"
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="300"
|
||||
height="400"
|
||||
viewBox="0 0 300 400"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.91 r13725"
|
||||
sodipodi:docname="Back.svg"
|
||||
inkscape:export-filename="C:\Users\Fluffy\Documents\Projects\ExtraRiichi\Tiles\Export\Regular\Back.png"
|
||||
inkscape:export-xdpi="180"
|
||||
inkscape:export-ydpi="180">
|
||||
<defs
|
||||
id="defs4">
|
||||
<inkscape:path-effect
|
||||
effect="skeletal"
|
||||
id="path-effect7963"
|
||||
is_visible="true"
|
||||
pattern="m -90.825902,-314.06958 23.03016,41.38503 13.798268,-41.38503 z"
|
||||
copytype="repeated_stretched"
|
||||
prop_scale="1"
|
||||
scale_y_rel="false"
|
||||
spacing="0"
|
||||
normal_offset="0"
|
||||
tang_offset="0"
|
||||
prop_units="false"
|
||||
vertical_pattern="false"
|
||||
fuse_tolerance="0"
|
||||
pattern-nodetypes="cccc" />
|
||||
<inkscape:path-effect
|
||||
effect="skeletal"
|
||||
id="path-effect7830"
|
||||
is_visible="true"
|
||||
pattern="M -12.828427,33.715729 -17,-11 l 9.0000001,0 z"
|
||||
copytype="repeated_stretched"
|
||||
prop_scale="-1"
|
||||
scale_y_rel="false"
|
||||
spacing="5.1"
|
||||
normal_offset="0"
|
||||
tang_offset="0"
|
||||
prop_units="false"
|
||||
vertical_pattern="false"
|
||||
fuse_tolerance="0"
|
||||
pattern-nodetypes="cccc" />
|
||||
<linearGradient
|
||||
id="linearGradient10055"
|
||||
osb:paint="solid">
|
||||
<stop
|
||||
style="stop-color:#000000;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop10057" />
|
||||
</linearGradient>
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Lstart"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Lstart"
|
||||
style="overflow:visible"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
id="path4978"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#ff5c00;stroke-width:1pt;stroke-opacity:1"
|
||||
transform="matrix(0.8,0,0,0.8,10,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath4243">
|
||||
<circle
|
||||
style="opacity:1;fill:#000000;fill-opacity:0.29670332;fill-rule:nonzero;stroke:#000000;stroke-width:19.13299942;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||
id="circle4245"
|
||||
cx="-264.65997"
|
||||
cy="-198.20665"
|
||||
r="293.95438" />
|
||||
<?xml version="1.0"?>
|
||||
<svg width="300" height="400" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg" version="1.1">
|
||||
<defs id="defs4">
|
||||
<clipPath clipPathUnits="userSpaceOnUse" id="clipPath4243">
|
||||
<circle cx="-264.66" cy="-198.21" fill="#000000" fill-opacity="0.3" fill-rule="nonzero" id="circle4245" r="293.95" stroke="#000000" stroke-dashoffset="0" stroke-linejoin="round" stroke-miterlimit="4" stroke-width="19.13"/>
|
||||
</clipPath>
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath7847">
|
||||
<ellipse
|
||||
style="opacity:1;fill:#822600;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:12;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||
id="ellipse7849"
|
||||
cx="394"
|
||||
cy="552.36218"
|
||||
rx="349.49533"
|
||||
ry="216" />
|
||||
<clipPath clipPathUnits="userSpaceOnUse" id="clipPath7847">
|
||||
<ellipse cx="394" cy="552.36" fill="#822600" fill-rule="nonzero" id="ellipse7849" rx="349.5" ry="216" stroke-dashoffset="0" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="4" stroke-width="12"/>
|
||||
</clipPath>
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath4243-1">
|
||||
<circle
|
||||
style="opacity:1;fill:#000000;fill-opacity:0.29670332;fill-rule:nonzero;stroke:#000000;stroke-width:19.13299942;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||
id="circle4245-4"
|
||||
cx="-264.65997"
|
||||
cy="-198.20665"
|
||||
r="293.95438" />
|
||||
<clipPath clipPathUnits="userSpaceOnUse" id="clipPath4243-1">
|
||||
<circle cx="-264.66" cy="-198.21" fill="#000000" fill-opacity="0.3" fill-rule="nonzero" id="circle4245-4" r="293.95" stroke="#000000" stroke-dashoffset="0" stroke-linejoin="round" stroke-miterlimit="4" stroke-width="19.13"/>
|
||||
</clipPath>
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath7876">
|
||||
<circle
|
||||
style="opacity:1;fill:#000000;fill-opacity:0.29670332;fill-rule:nonzero;stroke:#000000;stroke-width:19.13299942;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||
id="circle7878"
|
||||
cx="-264.65997"
|
||||
cy="-198.20665"
|
||||
r="293.95438" />
|
||||
<clipPath clipPathUnits="userSpaceOnUse" id="clipPath7876">
|
||||
<circle cx="-264.66" cy="-198.21" fill="#000000" fill-opacity="0.3" fill-rule="nonzero" id="circle7878" r="293.95" stroke="#000000" stroke-dashoffset="0" stroke-linejoin="round" stroke-miterlimit="4" stroke-width="19.13"/>
|
||||
</clipPath>
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath14693">
|
||||
<rect
|
||||
style="opacity:1;fill:#a53c3c;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:8;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||
id="rect14695"
|
||||
width="131.78395"
|
||||
height="168.82127"
|
||||
x="-332.59583"
|
||||
y="383.49765"
|
||||
rx="1.2551664"
|
||||
ry="3.7514515"
|
||||
transform="matrix(0.99939083,-0.03489951,0.03489951,0.99939083,0,0)" />
|
||||
<clipPath clipPathUnits="userSpaceOnUse" id="clipPath14693">
|
||||
<rect fill="#a53c3c" fill-rule="nonzero" height="168.82" id="rect14695" rx="1.26" ry="3.75" stroke-dashoffset="0" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="4" stroke-width="8" transform="matrix(0.99939083,-0.03489951,0.03489951,0.99939083,0,0)" width="131.78" x="-332.6" y="383.5"/>
|
||||
</clipPath>
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath14952">
|
||||
<ellipse
|
||||
style="opacity:1;fill:#a53c3c;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:7;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||
id="ellipse14954"
|
||||
cx="-271.34384"
|
||||
cy="647.25604"
|
||||
rx="69.057365"
|
||||
ry="116.91089"
|
||||
transform="matrix(0.99939083,-0.03489951,0.03489951,0.99939083,0,0)" />
|
||||
<clipPath clipPathUnits="userSpaceOnUse" id="clipPath14952">
|
||||
<ellipse cx="-271.34" cy="647.26" fill="#a53c3c" fill-rule="nonzero" id="ellipse14954" rx="69.06" ry="116.91" stroke-dashoffset="0" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="4" stroke-width="7" transform="matrix(0.99939083,-0.03489951,0.03489951,0.99939083,0,0)"/>
|
||||
</clipPath>
|
||||
<pattern
|
||||
y="0"
|
||||
x="0"
|
||||
height="6"
|
||||
width="6"
|
||||
patternUnits="userSpaceOnUse"
|
||||
id="EMFhbasepattern" />
|
||||
<filter
|
||||
style="color-interpolation-filters:sRGB;"
|
||||
inkscape:label=""
|
||||
id="filter4198">
|
||||
<feGaussianBlur
|
||||
stdDeviation="2.51 2.51"
|
||||
result="blur"
|
||||
id="feGaussianBlur4200" />
|
||||
<filter color-interpolation-filters="sRGB" id="filter4198">
|
||||
<feGaussianBlur id="feGaussianBlur4200" result="blur" stdDeviation="2.51 2.51"/>
|
||||
</filter>
|
||||
<mask
|
||||
maskUnits="userSpaceOnUse"
|
||||
id="mask4216">
|
||||
<rect
|
||||
ry="40"
|
||||
y="-1325.6035"
|
||||
x="-451.93805"
|
||||
height="400.77808"
|
||||
width="300.05896"
|
||||
id="rect4218"
|
||||
style="opacity:1;fill:#ff3737;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:10;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||
transform="scale(-1,-1)" />
|
||||
<mask id="mask4216" maskUnits="userSpaceOnUse">
|
||||
<rect fill="#ff3737" fill-rule="nonzero" height="400.78" id="rect4218" ry="40" stroke-dashoffset="0" stroke-linejoin="round" stroke-miterlimit="4" stroke-width="10" transform="scale(-1,-1)" width="300.06" x="-451.94" y="-1325.6"/>
|
||||
</mask>
|
||||
<mask
|
||||
maskUnits="userSpaceOnUse"
|
||||
id="mask4222">
|
||||
<rect
|
||||
ry="40"
|
||||
y="652.28351"
|
||||
x="0"
|
||||
height="400.77808"
|
||||
width="300.05896"
|
||||
id="rect4224"
|
||||
style="opacity:1;fill:#ff3737;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:10;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
|
||||
<mask id="mask4222" maskUnits="userSpaceOnUse">
|
||||
<rect fill="#ff3737" fill-rule="nonzero" height="400.78" id="rect4224" ry="40" stroke-dashoffset="0" stroke-linejoin="round" stroke-miterlimit="4" stroke-width="10" width="300.06" x="0" y="652.28"/>
|
||||
</mask>
|
||||
<filter
|
||||
style="color-interpolation-filters:sRGB;"
|
||||
inkscape:label="Blur"
|
||||
id="filter4188">
|
||||
<feGaussianBlur
|
||||
stdDeviation="2.35 2.34"
|
||||
result="blur"
|
||||
id="feGaussianBlur4190" />
|
||||
</filter>
|
||||
<pattern height="6" id="EMFhbasepattern" patternUnits="userSpaceOnUse" width="6" x="0" y="0"/>
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#aeffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="0.35742971"
|
||||
inkscape:cx="-92.256393"
|
||||
inkscape:cy="-195.52606"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="true"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1017"
|
||||
inkscape:window-x="1912"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1"
|
||||
showguides="true"
|
||||
inkscape:guide-bbox="true"
|
||||
units="px">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid4774"
|
||||
visible="true"
|
||||
dotted="false"
|
||||
color="#3f3fff"
|
||||
opacity="0.03921569"
|
||||
empcolor="#3f3fff"
|
||||
empopacity="0.07843137"
|
||||
enabled="false" />
|
||||
<sodipodi:guide
|
||||
position="150,200"
|
||||
orientation="0,1"
|
||||
id="guide8231"
|
||||
inkscape:label=""
|
||||
inkscape:color="rgb(0,0,255)" />
|
||||
<sodipodi:guide
|
||||
position="150,200"
|
||||
orientation="1,0"
|
||||
id="guide8233"
|
||||
inkscape:label=""
|
||||
inkscape:color="rgb(0,0,255)" />
|
||||
</sodipodi:namedview>
|
||||
<metadata
|
||||
id="metadata7">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(0,-652.36216)">
|
||||
<rect
|
||||
style="opacity:1;fill:#ff3737;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:10;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||
id="rect4164"
|
||||
width="300.05896"
|
||||
height="400.77808"
|
||||
x="0"
|
||||
y="652.28351"
|
||||
ry="40" />
|
||||
<path
|
||||
style="fill:#ffffff;fill-opacity:0.78431373;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter4198)"
|
||||
d="M -4.7687833,775.07096 C -9.6501835,741.99485 -16.84552,674.23676 -1.2788716,652.0641 18.998297,625.94378 233.50094,631.63117 263.31435,653.90999 276.21398,662.64856 59.158568,656.47658 35.908342,685.10013 13.199947,712.46776 0.65060847,818.18718 -4.7687833,775.07096 Z"
|
||||
id="path4166"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccc"
|
||||
mask="url(#mask4222)" />
|
||||
<path
|
||||
sodipodi:nodetypes="ccccc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4221"
|
||||
d="m 151.73588,1025.0177 c -3.32683,-9.3138 -10.24843,-68.45389 5.31821,-90.62655 20.27717,-26.12032 219.43558,-16.45796 231.55506,-9.93184 11.07433,5.31702 -178.60366,0.0589 -204.85126,34.86646 -21.59349,30.0006 -26.50086,82.17843 -32.02201,65.69193 z"
|
||||
style="fill:#000000;fill-opacity:0.39215687;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter4198)"
|
||||
transform="matrix(-1,0,0,-1,451.93806,1977.887)"
|
||||
mask="url(#mask4216)" />
|
||||
<metadata id="metadata7">image/svg+xml</metadata>
|
||||
<g class="layer">
|
||||
<title>Layer 1</title>
|
||||
<g id="layer1">
|
||||
<rect fill="#b268e8" fill-rule="nonzero" height="400.78" id="rect4164" ry="40" stroke-dashoffset="0" stroke-linejoin="round" stroke-miterlimit="4" stroke-width="10" width="300.06" y="-0.08"/>
|
||||
<path d="m-4.77,122.71c-4.88,-33.08 -12.08,-100.83 3.49,-123.01c20.28,-26.12 234.78,-20.43 264.59,1.85c12.9,8.74 -204.15,2.57 -227.4,31.19c-22.71,27.37 -35.26,133.09 -40.68,89.97z" fill="#b268e8" fill-opacity="0.78" fill-rule="evenodd" filter="url(#filter4198)" id="path4166" mask="url(#mask4222)" stroke-width="1px"/>
|
||||
<path d="m151.74,1677.38c-3.33,-9.32 -10.25,-68.46 5.31,-90.63c20.28,-26.12 219.44,-16.46 231.56,-9.93c11.07,5.32 -178.6,0.06 -204.85,34.87c-21.6,30 -26.5,82.17 -32.02,65.69z" fill="#b268e8" fill-opacity="0.39" fill-rule="evenodd" filter="url(#filter4198)" id="path4221" mask="url(#mask4216)" stroke-width="1px" transform="matrix(-1, 0, 0, -1, 451.938, 1977.89)"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 9.9 KiB After Width: | Height: | Size: 3.9 KiB |
15
index.html
15
index.html
|
|
@ -72,20 +72,23 @@
|
|||
<div id="canvasContainer"></div>
|
||||
|
||||
<script>
|
||||
const loaderScript = new Set();
|
||||
let currentScript = null;
|
||||
|
||||
function loadScript(scriptName) {
|
||||
if (window.cleanup) {
|
||||
window.cleanup();
|
||||
}
|
||||
|
||||
const container = document.getElementById("canvasContainer");
|
||||
container.innerHTML = `<canvas id="myCanvas" width="1000" height="1000"></canvas>`;
|
||||
|
||||
const timestamp = new Date().getTime();
|
||||
|
||||
const script = document.createElement("script");
|
||||
script.type = "module";
|
||||
script.src = `build/${scriptName}?t=${timestamp}`;
|
||||
currentScript = document.createElement("script");
|
||||
currentScript.type = "module";
|
||||
currentScript.src = `build/${scriptName}?t=${timestamp}`;
|
||||
|
||||
script.onload = () => {};
|
||||
document.body.appendChild(script);
|
||||
document.body.appendChild(currentScript);
|
||||
}
|
||||
|
||||
//script initial
|
||||
|
|
|
|||
86
src/deck.ts
86
src/deck.ts
|
|
@ -1,4 +1,5 @@
|
|||
import { Tile } from "./tile"
|
||||
import { Hand } from "./hand"
|
||||
|
||||
export class Deck {
|
||||
private tiles: Array<Tile>;
|
||||
|
|
@ -15,13 +16,13 @@ export class Deck {
|
|||
size: number,
|
||||
xOffset: number = 0,
|
||||
yOffset: number = 0
|
||||
): undefined {
|
||||
): void {
|
||||
let posX = x;
|
||||
let posY = y;
|
||||
for (let i = 1; i < 6; i++) {
|
||||
if (i < 4) { // ordinaire
|
||||
if (i < 4) { // famille
|
||||
for (let j = 1; j < 10; j++) {
|
||||
const tile = new Tile(i, j, false);
|
||||
const tile = this.find(i, j) as NonNullable<Tile>;
|
||||
tile.drawTile(ctx, posX, posY, size);
|
||||
posX += (75 + xOffset) * size;
|
||||
}
|
||||
|
|
@ -29,7 +30,7 @@ export class Deck {
|
|||
posY += (100 + yOffset) * size;
|
||||
} else if (i === 4) { //vent
|
||||
for (let j = 1; j < 5; j++) {
|
||||
const tile = new Tile(i, j, false);
|
||||
const tile = this.find(i, j) as NonNullable<Tile>;
|
||||
tile.drawTile(ctx, posX, posY, size);
|
||||
posX += (75 + xOffset) * size;
|
||||
}
|
||||
|
|
@ -37,7 +38,7 @@ export class Deck {
|
|||
posY += (100 + yOffset) * size;
|
||||
} else if (i === 5) { //vent
|
||||
for (let j = 1; j < 4; j++) {
|
||||
const tile = new Tile(i, j, false);
|
||||
const tile = this.find(i, j) as NonNullable<Tile>;
|
||||
tile.drawTile(ctx, posX, posY, size);
|
||||
posX += (75 + xOffset) * size;
|
||||
}
|
||||
|
|
@ -45,10 +46,77 @@ export class Deck {
|
|||
}
|
||||
}
|
||||
|
||||
public pop(): Tile {
|
||||
if (this.tiles.length === 0) {
|
||||
}
|
||||
return this.tiles.pop() as NonNullable<Tile>;
|
||||
}
|
||||
|
||||
public find(family: number, value: number): Tile | undefined {
|
||||
let n = undefined;
|
||||
for (let i = 0; i < this.tiles.length; i++) {
|
||||
if (
|
||||
this.tiles[i].getFamily() === family &&
|
||||
this.tiles[i].getValue() === value
|
||||
) {
|
||||
n = i;
|
||||
}
|
||||
}
|
||||
if (n !== undefined) {
|
||||
[this.tiles[n as NonNullable<number>], this.tiles[0]] = [this.tiles[0], this.tiles[n as NonNullable<number>]];
|
||||
return this.tiles.shift();
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
public count(family: number, value: number): number {
|
||||
let n = 0;
|
||||
for (let i = 0; i < this.tiles.length; i++) {
|
||||
if (
|
||||
this.tiles[i].getFamily() === family &&
|
||||
this.tiles[i].getValue() === value
|
||||
) {
|
||||
n++;
|
||||
}
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
public shuffle(): undefined {
|
||||
let newArray: Array<Tile> = [];
|
||||
while (this.tiles.length > 0) {
|
||||
let n = Math.floor(Math.random() * this.tiles.length);
|
||||
[this.tiles[n], this.tiles[0]] = [this.tiles[0], this.tiles[n]];
|
||||
newArray.push(this.tiles.shift() as NonNullable<Tile>);
|
||||
}
|
||||
this.tiles = newArray;
|
||||
}
|
||||
|
||||
public getRandomHand(): Hand {
|
||||
let hand = new Hand();
|
||||
this.shuffle();
|
||||
for (let i = 0; i < 13; i++) {
|
||||
hand.push(this.pop());
|
||||
}
|
||||
return hand;
|
||||
}
|
||||
|
||||
public cleanup(): void {
|
||||
this.tiles.forEach(tile => tile.cleanup());
|
||||
this.tiles = [];
|
||||
}
|
||||
|
||||
public async preload(): Promise<void> {
|
||||
for (let i = 0; i < this.tiles.length; i++) {
|
||||
await this.tiles[i].preloadImg();
|
||||
}
|
||||
}
|
||||
|
||||
private initTiles(allowRed: boolean): undefined {
|
||||
for (let i = 1; i < 6; i++) {
|
||||
if (i < 4) { // ordinaire
|
||||
for (let j = 1; i < 10; i++) {
|
||||
if (i < 4) { // famille
|
||||
for (let j = 1; j < 10; j++) {
|
||||
this.tiles.push(new Tile(i, j, false));
|
||||
this.tiles.push(new Tile(i, j, false));
|
||||
this.tiles.push(new Tile(i, j, false));
|
||||
|
|
@ -58,13 +126,13 @@ export class Deck {
|
|||
this.tiles.push(new Tile(i, j, false));
|
||||
}
|
||||
}
|
||||
} else if (i === 5) { //vent
|
||||
} else if (i === 4) { // vent
|
||||
for (let j = 1; j < 5; j++) {
|
||||
for (let k = 0; k < 4; k++) {
|
||||
this.tiles.push(new Tile(i, j, false));
|
||||
}
|
||||
}
|
||||
} else if (i === 6) { //vent
|
||||
} else if (i === 5) { // dragon
|
||||
for (let j = 1; j < 4; j++) {
|
||||
for (let k = 0; k < 4; k++) {
|
||||
this.tiles.push(new Tile(i, j, false));
|
||||
|
|
|
|||
|
|
@ -1,9 +1,21 @@
|
|||
import { Tile } from "../tile"
|
||||
import { Deck } from "../deck"
|
||||
|
||||
const canvas = document.getElementById("myCanvas") as HTMLCanvasElement;
|
||||
declare global {
|
||||
interface Window {
|
||||
clanup: () => void;
|
||||
}
|
||||
}
|
||||
|
||||
if (canvas) {
|
||||
export {};
|
||||
|
||||
async function preloadDeck(deck: Deck) {
|
||||
await deck.preload();
|
||||
}
|
||||
|
||||
async function display() {
|
||||
const canvas = document.getElementById("myCanvas") as HTMLCanvasElement;
|
||||
|
||||
if (canvas) {
|
||||
const ctx = canvas.getContext("2d");
|
||||
|
||||
if (ctx) {
|
||||
|
|
@ -18,6 +30,7 @@ if (canvas) {
|
|||
let xos = 50;
|
||||
let yos = 100;
|
||||
const deck = new Deck(false);
|
||||
await preloadDeck(deck);
|
||||
deck.displayFamilies(ctx, x, y, size, xos, yos);
|
||||
|
||||
// texte
|
||||
|
|
@ -82,10 +95,17 @@ if (canvas) {
|
|||
y + 4 * (yos + 100) * size + 150 * size
|
||||
);
|
||||
|
||||
window.cleanup = () => {
|
||||
deck.cleanup();
|
||||
}
|
||||
|
||||
} else {
|
||||
console.error("Impossible d'obtenir le contexte du canvas.");
|
||||
}
|
||||
} else {
|
||||
} else {
|
||||
console.error("Canvas introuvable dans le DOM.");
|
||||
}
|
||||
}
|
||||
|
||||
display()
|
||||
|
||||
|
|
|
|||
|
|
@ -1,91 +1,131 @@
|
|||
import { Tile } from "../tile"
|
||||
import { Deck } from "../deck"
|
||||
import { Deck } from "../deck";
|
||||
import { Hand } from "../hand"
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
cleanup: () => void;
|
||||
}
|
||||
}
|
||||
export {}
|
||||
|
||||
const canvas = document.getElementById("myCanvas") as HTMLCanvasElement;
|
||||
|
||||
if (canvas) {
|
||||
const ctx = canvas.getContext("2d");
|
||||
async function preloadDeck(deck: Deck) {
|
||||
await deck.preload();
|
||||
}
|
||||
|
||||
async function display () {
|
||||
if (canvas) {
|
||||
const ctx = canvas.getContext("2d") as NonNullable<CanvasRenderingContext2D>;
|
||||
|
||||
if (ctx) {
|
||||
// tapis
|
||||
ctx.fillStyle = "#007730";
|
||||
ctx.fillRect(50, 50, 1000, 1000);
|
||||
// double buffering
|
||||
const offScreenCanvas = document.createElement('canvas') as HTMLCanvasElement;
|
||||
offScreenCanvas.width = canvas.width;
|
||||
offScreenCanvas.height = canvas.height;
|
||||
const offScreenCtx = offScreenCanvas.getContext('2d') as NonNullable<CanvasRenderingContext2D>;
|
||||
|
||||
//animation parameter
|
||||
let lastTime = 0;
|
||||
const FPS = 30;
|
||||
const interval = 1000 / FPS;
|
||||
|
||||
// tuiles
|
||||
let x = 180;
|
||||
let y = 80;
|
||||
let x = 150;
|
||||
let y = 150;
|
||||
let os = 75;
|
||||
let size = 0.75;
|
||||
let xos = 50;
|
||||
let yos = 100;
|
||||
const deck = new Deck(false);
|
||||
deck.displayFamilies(ctx, x, y, size, xos, yos);
|
||||
await preloadDeck(deck);
|
||||
|
||||
let hands: Array<Hand> = [];
|
||||
for (let i = 0; i < 4; i++) {
|
||||
const hand = deck.getRandomHand();
|
||||
hand.sort();
|
||||
hands.push(hand);
|
||||
}
|
||||
|
||||
// interactive hand
|
||||
const edeck = new Deck(false);
|
||||
await edeck.preload();
|
||||
const ehand = edeck.getRandomHand();
|
||||
ehand.sort();
|
||||
|
||||
let selectedTile: number|undefined = undefined;
|
||||
|
||||
// function to draw
|
||||
const drawCanvas = async () => {
|
||||
// clean screeen
|
||||
offScreenCtx.clearRect(0, 0, canvas.width, canvas.height);
|
||||
|
||||
// tapis
|
||||
offScreenCtx.fillStyle = "#007730";
|
||||
offScreenCtx.fillRect(50, 50, 1000, 1000);
|
||||
|
||||
// texte
|
||||
ctx.fillStyle = "#DFDFFF";
|
||||
ctx.font = "30px serif";
|
||||
offScreenCtx.fillStyle = "#DFDFFF";
|
||||
offScreenCtx.font = "50px serif";
|
||||
offScreenCtx.fillText("Exemples de main:", 65, 100);
|
||||
|
||||
let delta = 50 * size;
|
||||
let eps = 30 * size;
|
||||
ctx.fillText("Caractère:", 55, y + delta + eps);
|
||||
ctx.fillText("Pin:", 55, y + 3 * delta + yos * size + eps);
|
||||
ctx.fillText("Bambou:", 55, y + 5 * delta + 2 * yos * size + eps);
|
||||
ctx.fillText("Vent:", 55, y + 7 * delta + 3 * yos * size + eps);
|
||||
ctx.fillText("Dragon:", 55, y + 9 * delta + 4 * yos * size + eps);
|
||||
|
||||
// familles
|
||||
for (let i = 0; i < 3; i++) {
|
||||
for (let j = 0; j < 9; j++) {
|
||||
ctx.fillText(
|
||||
String(j+1),
|
||||
x + j * (xos + 75) * size + 30 * size,
|
||||
y + i * (yos + 100) * size + 150 * size
|
||||
);
|
||||
}
|
||||
// example hands
|
||||
for (let i = 0; i < hands.length; i++) {
|
||||
hands[i].drawHand(offScreenCtx, x, y + i * size * (100 + os), 5, size);
|
||||
}
|
||||
|
||||
// vent
|
||||
ctx.fillText(
|
||||
"Est",
|
||||
x + 0 * (xos + 75) * size,
|
||||
y + 3 * (yos + 100) * size + 150 * size
|
||||
);
|
||||
ctx.fillText(
|
||||
"Sud",
|
||||
x + 1 * (xos + 75) * size,
|
||||
y + 3 * (yos + 100) * size + 150 * size
|
||||
);
|
||||
ctx.fillText(
|
||||
"Ouest",
|
||||
x + 2 * (xos + 75) * size,
|
||||
y + 3 * (yos + 100) * size + 150 * size
|
||||
);
|
||||
ctx.fillText(
|
||||
"Nord",
|
||||
x + 3 * (xos + 75) * size,
|
||||
y + 3 * (yos + 100) * size + 150 * size
|
||||
// dynamic hand
|
||||
ehand.drawHand(offScreenCtx, x, 800, 5, size, selectedTile);
|
||||
|
||||
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||
ctx.drawImage(offScreenCanvas, 0, 0);
|
||||
}
|
||||
|
||||
const animationLoop = (currentTime: number) => {
|
||||
const deltaTime = currentTime - lastTime;
|
||||
|
||||
if (deltaTime >= interval) {
|
||||
lastTime = currentTime;
|
||||
drawCanvas();
|
||||
}
|
||||
requestAnimationFrame(animationLoop);
|
||||
}
|
||||
|
||||
// mouse event
|
||||
canvas.addEventListener(
|
||||
"mousemove",
|
||||
(event) => {
|
||||
const rect = canvas.getBoundingClientRect();
|
||||
const mouseX = event.clientX - rect.left - x;
|
||||
const mouseY = event.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;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
// dragon
|
||||
ctx.fillText(
|
||||
"Rouge",
|
||||
x + 0 * (xos + 75) * size,
|
||||
y + 4 * (yos + 100) * size + 150 * size
|
||||
);
|
||||
ctx.fillText(
|
||||
"Vert",
|
||||
x + 1 * (xos + 75) * size,
|
||||
y + 4 * (yos + 100) * size + 150 * size
|
||||
);
|
||||
ctx.fillText(
|
||||
"Blanc",
|
||||
x + 2 * (xos + 75) * size,
|
||||
y + 4 * (yos + 100) * size + 150 * size
|
||||
);
|
||||
requestAnimationFrame(animationLoop);
|
||||
|
||||
window.cleanup = () => {
|
||||
deck.cleanup();
|
||||
hands.forEach(hand => hand.cleanup());
|
||||
hands = [];
|
||||
edeck.cleanup();
|
||||
ehand.cleanup();
|
||||
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||
offScreenCtx.clearRect(0, 0, offScreenCanvas.width, offScreenCanvas.height);
|
||||
selectedTile = undefined;
|
||||
}
|
||||
|
||||
} else {
|
||||
console.error("Impossible d'obtenir le contexte du canvas.");
|
||||
}
|
||||
} else {
|
||||
} else {
|
||||
console.error("Canvas introuvable dans le DOM.");
|
||||
}
|
||||
}
|
||||
|
||||
display();
|
||||
|
|
|
|||
68
src/hand.ts
68
src/hand.ts
|
|
@ -1,10 +1,24 @@
|
|||
import { Tile } from "./tile"
|
||||
|
||||
export class hand {
|
||||
export class Hand {
|
||||
private tiles: Array<Tile>;
|
||||
|
||||
public constructor(tiles: Array<Tile> = []) {
|
||||
this.tiles = tiles;
|
||||
public constructor(stiles: string = "") {
|
||||
this.tiles = [];
|
||||
for (let i = 0; 2 * i + 1 < stiles.length; i++) {
|
||||
let ss = stiles.substring(2*i, 2*(i+1));
|
||||
if (ss[0] === "m") {
|
||||
this.tiles.push(new Tile(1, Number(ss[1]), false));
|
||||
} else if (ss[0] === "p") {
|
||||
this.tiles.push(new Tile(2, Number(ss[1]), false));
|
||||
} else if (ss[0] === "s") {
|
||||
this.tiles.push(new Tile(3, Number(ss[1]), false));
|
||||
} else if (ss[0] === "w") {
|
||||
this.tiles.push(new Tile(4, Number(ss[1]), false));
|
||||
} else if (ss[0] === "d") {
|
||||
this.tiles.push(new Tile(5, Number(ss[1]), false));
|
||||
} else {}
|
||||
}
|
||||
}
|
||||
|
||||
public push(tile: Tile): undefined {
|
||||
|
|
@ -14,4 +28,52 @@ export class hand {
|
|||
public pop(): Tile|undefined {
|
||||
return this.tiles.pop();
|
||||
}
|
||||
|
||||
public sort(): 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]];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public drawHand (
|
||||
ctx: CanvasRenderingContext2D,
|
||||
x: number,
|
||||
y: number,
|
||||
offset: number,
|
||||
size: number,
|
||||
focusedTiled: number|undefined = undefined
|
||||
): void {
|
||||
for (var 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
|
||||
);
|
||||
} else {
|
||||
this.tiles[i].drawTile(
|
||||
ctx,
|
||||
x + i * 75 * size + i * offset * size,
|
||||
y,
|
||||
size
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public async preload(): Promise<void> {
|
||||
for (let i = 0; i < this.tiles.length; i++) {
|
||||
await this.tiles[i].preloadImg();
|
||||
}
|
||||
}
|
||||
|
||||
public cleanup(): void {
|
||||
this.tiles.forEach(tile => tile.cleanup());
|
||||
this.tiles = [];
|
||||
}
|
||||
}
|
||||
|
|
|
|||
60
src/tile.ts
60
src/tile.ts
|
|
@ -2,13 +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;
|
||||
|
||||
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.setImgSrc();
|
||||
}
|
||||
|
||||
|
|
@ -29,21 +37,31 @@ export class Tile {
|
|||
x: number,
|
||||
y: number,
|
||||
size: number
|
||||
): undefined {
|
||||
const imgFront = new Image();
|
||||
imgFront.src = "/img/Regular/Front.svg";
|
||||
imgFront.onload = () => {
|
||||
ctx.drawImage(imgFront, x, y, 75 * size, 100 * size);
|
||||
};
|
||||
|
||||
const img = new Image();
|
||||
img.src = this.imgSrc;
|
||||
img.onload = () => {
|
||||
ctx.drawImage(img, x, y, 75 * size, 100 * size);
|
||||
};
|
||||
): void {
|
||||
ctx.drawImage(this.imgFront, x, y, 75 * size, 100 * size);
|
||||
ctx.drawImage(this.img, x, y, 75 * size, 100 * size);
|
||||
}
|
||||
|
||||
private setImgSrc(): undefined {
|
||||
public isLessThan(t: Tile): boolean {
|
||||
if (this.family < t.family) {
|
||||
return true;
|
||||
} else if (this.family === t.family && this.value <= t.value) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public cleanup(): void {
|
||||
this.imgFront.onload = null;
|
||||
this.imgFront.onerror = null;
|
||||
this.imgBack.onload = null;
|
||||
this.imgBack.onerror = null;
|
||||
this.img.onload = null;
|
||||
this.img.onerror = null;
|
||||
}
|
||||
|
||||
private setImgSrc(): void {
|
||||
this.imgSrc = "/img/Regular/"
|
||||
if (this.family <= 3) {
|
||||
this.imgSrc += ["", "Man", "Pin", "Sou"][this.family];
|
||||
|
|
@ -58,4 +76,20 @@ export class Tile {
|
|||
this.imgSrc += ["", "Chun", "Hatsu", "Haku"][this.value] + ".svg";
|
||||
}
|
||||
}
|
||||
|
||||
public async preloadImg(): Promise<void> {
|
||||
await Promise.all([
|
||||
this.loadImg(this.imgFront, "/img/Regular/Front.svg"),
|
||||
this.loadImg(this.imgBack, "/img/Regular/Back.svg"),
|
||||
this.loadImg(this.img, this.imgSrc)
|
||||
]);
|
||||
}
|
||||
|
||||
private loadImg(img: HTMLImageElement, src: string): Promise<void> {
|
||||
return new Promise((resolve, reject) => {
|
||||
img.onload = () => resolve();
|
||||
img.onerror = () => reject();
|
||||
img.src = src;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue