deux pages (presque)

This commit is contained in:
Didictateur 2025-03-07 17:50:37 +01:00
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

View file

@ -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

View file

@ -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

View file

@ -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));

View file

@ -1,6 +1,18 @@
import { Tile } from "../tile"
import { Deck } from "../deck"
declare global {
interface Window {
clanup: () => void;
}
}
export {};
async function preloadDeck(deck: Deck) {
await deck.preload();
}
async function display() {
const canvas = document.getElementById("myCanvas") as HTMLCanvasElement;
if (canvas) {
@ -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 {
console.error("Canvas introuvable dans le DOM.");
}
}
display()

View file

@ -1,86 +1,124 @@
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;
async function preloadDeck(deck: Deck) {
await deck.preload();
}
async function display () {
if (canvas) {
const ctx = canvas.getContext("2d");
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.");
@ -88,4 +126,6 @@ if (canvas) {
} else {
console.error("Canvas introuvable dans le DOM.");
}
}
display();

View file

@ -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 = [];
}
}

View file

@ -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;
});
}
}