rajout des textes explicatifs
This commit is contained in:
parent
d686d6559a
commit
ac2825a7cb
15 changed files with 432 additions and 55 deletions
3
Makefile
3
Makefile
|
|
@ -1,6 +1,3 @@
|
||||||
DISPLAY = $(wildcard src/display/*.ts)
|
|
||||||
OUTFILES = $(patsubst src/display/%.ts,build/%.js,$(DISPLAY))
|
|
||||||
|
|
||||||
all:
|
all:
|
||||||
npx webpack --mode development
|
npx webpack --mode development
|
||||||
|
|
||||||
|
|
|
||||||
29
index.html
29
index.html
|
|
@ -57,6 +57,10 @@
|
||||||
.menu-item:hover .dropdown {
|
.menu-item:hover .dropdown {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
.container {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-betwenne;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
@ -108,10 +112,30 @@
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<div id="canvasContainer"></div>
|
<div class="container">
|
||||||
|
<div id="canvasContainer"></div>
|
||||||
|
<div id="anotherCanvasContainer"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
let currentScript = null;
|
let currentScript = null;
|
||||||
|
|
||||||
|
function loadText(scriptName) {
|
||||||
|
if (window.cleanup) {
|
||||||
|
window.cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
const container = document.getElementById("anotherCanvasContainer");
|
||||||
|
container.innerHTML = `<canvas id="myTextCanvas" width="1000" height="1000"></canvas>`;
|
||||||
|
|
||||||
|
const timestamp = new Date().getTime();
|
||||||
|
|
||||||
|
currentScript = document.createElement("script");
|
||||||
|
currentScript.type = "module";
|
||||||
|
currentScript.src = `build/${scriptName}?t=${timestamp}`;
|
||||||
|
|
||||||
|
document.body.appendChild(currentScript);
|
||||||
|
}
|
||||||
|
|
||||||
function loadScript(scriptName) {
|
function loadScript(scriptName) {
|
||||||
if (window.cleanup) {
|
if (window.cleanup) {
|
||||||
|
|
@ -128,6 +152,9 @@
|
||||||
currentScript.src = `build/${scriptName}?t=${timestamp}`;
|
currentScript.src = `build/${scriptName}?t=${timestamp}`;
|
||||||
|
|
||||||
document.body.appendChild(currentScript);
|
document.body.appendChild(currentScript);
|
||||||
|
|
||||||
|
const number = scriptName.substring(2, scriptName.length - 3);
|
||||||
|
loadText("txt" + number + ".js");
|
||||||
}
|
}
|
||||||
|
|
||||||
//script initial
|
//script initial
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
import { Tile } from "./tile"
|
||||||
|
|
||||||
type button_t = (
|
type button_t = (
|
||||||
arg0: CanvasRenderingContext2D,
|
arg0: CanvasRenderingContext2D,
|
||||||
arg1: number,
|
arg1: number,
|
||||||
|
|
@ -37,7 +39,6 @@ export function clickAction(
|
||||||
) {
|
) {
|
||||||
return buttons.filter(c => c[0])[q][1] as number;
|
return buttons.filter(c => c[0])[q][1] as number;
|
||||||
}
|
}
|
||||||
console.log(q, r, "\n");
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -72,6 +73,66 @@ export function drawButtons(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function clickChii(
|
||||||
|
x: number,
|
||||||
|
y: number,
|
||||||
|
chiis: Array<Array<Tile>>
|
||||||
|
): number {
|
||||||
|
let xmin = 960 - (chiis.length + 1) * 120;
|
||||||
|
let inside = 838 < y && y < 888;
|
||||||
|
let q = Math.floor((x - xmin) / 120);
|
||||||
|
let r = (x - xmin) - 120 * q;
|
||||||
|
if (
|
||||||
|
q >= 0 &&
|
||||||
|
q < (chiis.length + 1) &&
|
||||||
|
r > 10 &&
|
||||||
|
inside
|
||||||
|
) {
|
||||||
|
return q === chiis.length ? 0 : q + 1;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function drawChiis(
|
||||||
|
ctx: CanvasRenderingContext2D,
|
||||||
|
chiis: Array<Array<Tile>>
|
||||||
|
): void {
|
||||||
|
const r = 8;
|
||||||
|
const w = 110;
|
||||||
|
const h = 50;
|
||||||
|
button(ctx, 850, 835, r, w, h, "#FF9030");
|
||||||
|
ctx.fillStyle = "black";
|
||||||
|
ctx.font = "30px garamond";
|
||||||
|
ctx.fillText("Retour", 850 + w * 0.1, 835 + h/2 * 1.3);
|
||||||
|
|
||||||
|
let dx = 1;
|
||||||
|
console.log("length: ", chiis.length, "\n");
|
||||||
|
for (let i = 0; i < chiis.length; i++) {
|
||||||
|
console.log("trying to draw\n");
|
||||||
|
drawOneChii(
|
||||||
|
ctx,
|
||||||
|
850 - dx * 120,
|
||||||
|
835,
|
||||||
|
chiis[i]
|
||||||
|
);
|
||||||
|
dx++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function drawOneChii(
|
||||||
|
ctx: CanvasRenderingContext2D,
|
||||||
|
x: number,
|
||||||
|
y: number,
|
||||||
|
tiles: Array<Tile>
|
||||||
|
): void {
|
||||||
|
const r = 8;
|
||||||
|
const w = 110;
|
||||||
|
const h = 50;
|
||||||
|
button(ctx, x, y, r, w, h, "#FFCC33");
|
||||||
|
ctx.fillStyle = "black";
|
||||||
|
ctx.font = "30px garamond";
|
||||||
|
}
|
||||||
|
|
||||||
function button(
|
function button(
|
||||||
ctx: CanvasRenderingContext2D,
|
ctx: CanvasRenderingContext2D,
|
||||||
x: number,
|
x: number,
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ async function display() {
|
||||||
let x = 180;
|
let x = 180;
|
||||||
let y = 80;
|
let y = 80;
|
||||||
let size = 0.75;
|
let size = 0.75;
|
||||||
let xos = 50;
|
let xos = 40;
|
||||||
let yos = 100;
|
let yos = 100;
|
||||||
const deck = new Deck(false);
|
const deck = new Deck(false);
|
||||||
await preloadDeck(deck);
|
await preloadDeck(deck);
|
||||||
|
|
|
||||||
165
src/game.ts
165
src/game.ts
|
|
@ -2,7 +2,7 @@ import { Deck } from "./deck";
|
||||||
import { Hand } from "./hand";
|
import { Hand } from "./hand";
|
||||||
import { Tile } from "./tile";
|
import { Tile } from "./tile";
|
||||||
import { Group } from "./group";
|
import { Group } from "./group";
|
||||||
import { drawButtons, clickAction } from "./button";
|
import { drawButtons, clickAction, drawChiis, clickChii } from "./button";
|
||||||
import { drawState } from "./state";
|
import { drawState } from "./state";
|
||||||
|
|
||||||
export type mousePos = { x: number, y: number};
|
export type mousePos = { x: number, y: number};
|
||||||
|
|
@ -23,6 +23,7 @@ export class Game {
|
||||||
private hasPicked: boolean = false;
|
private hasPicked: boolean = false;
|
||||||
private hasPlayed: boolean = false;
|
private hasPlayed: boolean = false;
|
||||||
private lastPlayed: number = Date.now();
|
private lastPlayed: number = Date.now();
|
||||||
|
private chooseChii: boolean = false;
|
||||||
private end: boolean = false;
|
private end: boolean = false;
|
||||||
|
|
||||||
// display parameter
|
// display parameter
|
||||||
|
|
@ -100,38 +101,59 @@ export class Game {
|
||||||
mp: mousePos,
|
mp: mousePos,
|
||||||
): void {
|
): void {
|
||||||
const rect = this.cv.getBoundingClientRect();
|
const rect = this.cv.getBoundingClientRect();
|
||||||
let action = clickAction(
|
|
||||||
mp.x - rect.left,
|
|
||||||
mp.y - rect.top,
|
|
||||||
this.canDoAChii().length > 0,
|
|
||||||
this.canDoAPon(),
|
|
||||||
false && this.level > 1,
|
|
||||||
false && this.level > 0,
|
|
||||||
false && this.level > 0
|
|
||||||
);
|
|
||||||
|
|
||||||
if (this.canCall && action !== -1) { // can call
|
|
||||||
if (action === 0) { // pass
|
|
||||||
this.canCall = false;
|
|
||||||
if (this.turn === 3) {
|
|
||||||
this.turn = 0;
|
|
||||||
this.pick(0);
|
|
||||||
} else {
|
|
||||||
this.turn++;
|
|
||||||
}
|
|
||||||
this.hasPicked = true;
|
|
||||||
this.hasPlayed = false;
|
|
||||||
} else if (action == 2) { // pon
|
|
||||||
this.pon(this.turn);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else { // nothing unusual
|
if (this.chooseChii) { // is choosing
|
||||||
if (this.turn === 0 && this.selectedTile !== undefined) {
|
let allChii = this.getChii(0);
|
||||||
this.discard(0, this.selectedTile as NonNullable<number>);
|
let c = clickChii(
|
||||||
this.checkPon();
|
mp.x - rect.x,
|
||||||
console.log("turn", this.turn, "\n");
|
mp.y - rect.y,
|
||||||
this.turn = (this.turn + 1) % 4;
|
allChii
|
||||||
console.log("new turn", this.turn, "\n");
|
);
|
||||||
|
console.log("chii action:", c, "\n");
|
||||||
|
|
||||||
|
if (c === 0) {
|
||||||
|
this.chooseChii = false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let action = clickAction(
|
||||||
|
mp.x - rect.left,
|
||||||
|
mp.y - rect.top,
|
||||||
|
this.canDoAChii().length > 0,
|
||||||
|
this.canDoAPon(),
|
||||||
|
false && this.level > 1,
|
||||||
|
false && this.level > 0,
|
||||||
|
false && this.level > 0
|
||||||
|
);
|
||||||
|
|
||||||
|
if (this.canCall && action !== -1) { // can call
|
||||||
|
if (action === 0) { // pass
|
||||||
|
this.canCall = false;
|
||||||
|
if (this.turn === 3) {
|
||||||
|
this.turn = 0;
|
||||||
|
this.pick(0);
|
||||||
|
} else {
|
||||||
|
this.turn++;
|
||||||
|
}
|
||||||
|
this.hasPicked = true;
|
||||||
|
this.hasPlayed = false;
|
||||||
|
} else if (action === 1) { // chii
|
||||||
|
let chiis = this.canDoAChii();
|
||||||
|
if (chiis.length === 0) { // only one possible
|
||||||
|
this.chii(chiis[0], 0); // TODO not 0
|
||||||
|
} else {
|
||||||
|
this.chooseChii = true;
|
||||||
|
this.drawGame();
|
||||||
|
}
|
||||||
|
} else if (action == 2) { // pon
|
||||||
|
this.pon(this.turn);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else { // nothing unusual
|
||||||
|
if (this.turn === 0 && this.selectedTile !== undefined) {
|
||||||
|
this.discard(0, this.selectedTile as NonNullable<number>);
|
||||||
|
this.checkPon();
|
||||||
|
this.turn = (this.turn + 1) % 4;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -166,7 +188,6 @@ export class Game {
|
||||||
if (
|
if (
|
||||||
this.turn !== 0
|
this.turn !== 0
|
||||||
) { // bot playing
|
) { // bot playing
|
||||||
console.log(this.turn, '\n');
|
|
||||||
if (!this.hasPicked) { // begin of his turn
|
if (!this.hasPicked) { // begin of his turn
|
||||||
this.lastPlayed = Date.now();
|
this.lastPlayed = Date.now();
|
||||||
this.pick(this.turn);
|
this.pick(this.turn);
|
||||||
|
|
@ -214,16 +235,16 @@ export class Game {
|
||||||
this.lastPlayed = Date.now();
|
this.lastPlayed = Date.now();
|
||||||
}
|
}
|
||||||
|
|
||||||
private canDoAChii(): Array<number> {
|
private canDoAChii(p: number = 0): Array<number> {
|
||||||
let chii = [] as Array<number>;
|
let chii = [] as Array<number>;
|
||||||
if (
|
if (
|
||||||
this.lastDiscard !== undefined &&
|
this.lastDiscard !== undefined &&
|
||||||
this.lastDiscard === 3 &&
|
(this.lastDiscard + 1) % 4 === p &&
|
||||||
this.turn === 3 &&
|
(this.turn + 1) % 4 === p &&
|
||||||
this.discards[this.lastDiscard][this.discards[this.lastDiscard].length-1].getFamily() < 4
|
this.discards[this.lastDiscard][this.discards[this.lastDiscard].length-1].getFamily() < 4
|
||||||
) {
|
) {
|
||||||
let t = this.discards[this.lastDiscard][this.discards[this.lastDiscard].length-1];
|
let t = this.discards[this.lastDiscard][this.discards[this.lastDiscard].length-1];
|
||||||
let h = this.hands[0];
|
let h = this.hands[p];
|
||||||
if (
|
if (
|
||||||
h.count(t.getFamily(), t.getValue()-2) > 0 &&
|
h.count(t.getFamily(), t.getValue()-2) > 0 &&
|
||||||
h.count(t.getFamily(), t.getValue()-1) > 0
|
h.count(t.getFamily(), t.getValue()-1) > 0
|
||||||
|
|
@ -244,14 +265,57 @@ export class Game {
|
||||||
return chii;
|
return chii;
|
||||||
}
|
}
|
||||||
|
|
||||||
private chii(minValue: number): void {
|
private chii(minValue: number, p: number): void {
|
||||||
console.log("Chii !\n");
|
let t = this.discards[p === 0 ? 3 : p - 1].pop() as NonNullable<Tile>;
|
||||||
|
this.lastDiscard = undefined;
|
||||||
|
let tn = 0;
|
||||||
|
let v = minValue;
|
||||||
|
let tt: Array<Tile> = [];
|
||||||
|
while (tn < 2) {
|
||||||
|
if (v === t.getValue()) {
|
||||||
|
v++;
|
||||||
|
} else {
|
||||||
|
tt[tn] = this.hands[p].find(t.getFamily(), v) as NonNullable<Tile>;
|
||||||
|
tn++;
|
||||||
|
v++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
[t, tt[0], tt[1]].forEach(t => t.setTilt());
|
||||||
|
this.groups[p].push(new Group([t, tt[0], tt[1]], p === 0 ? 3 : p - 1, p));
|
||||||
|
|
||||||
|
this.turn = p;
|
||||||
|
this.hasPicked = true;
|
||||||
|
this.hasPlayed = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private getChii(p: number): Array<Array<Tile>> {
|
||||||
|
let chiis = [] as Array<Array<Tile>>;
|
||||||
|
let numChii = this.canDoAChii();
|
||||||
|
|
||||||
|
let d = this.discards[p === 0 ? 3 : p - 1];
|
||||||
|
let t = d[d.length - 1]
|
||||||
|
|
||||||
|
for (let i = 0; i < numChii.length; i++) {
|
||||||
|
let v = numChii[i];
|
||||||
|
let chii = [];
|
||||||
|
for (let dv = 0; dv < 3; dv++) {
|
||||||
|
if (v + dv === t.getValue()) {
|
||||||
|
chii.push(t);
|
||||||
|
} else {
|
||||||
|
let tt = this.hands[p].find(t.getFamily(), v + dv) as NonNullable<Tile>;
|
||||||
|
chii.push(tt);
|
||||||
|
this.hands[p].push(tt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
chiis.push(chii);
|
||||||
|
}
|
||||||
|
|
||||||
|
return chiis;
|
||||||
}
|
}
|
||||||
|
|
||||||
private checkPon(): void {
|
private checkPon(): void {
|
||||||
for (var p = 1; p < 4; p++) {
|
for (var p = 1; p < 4; p++) {
|
||||||
if (this.canDoAPon(p)) {
|
if (this.canDoAPon(p)) {
|
||||||
console.log(p, '\n');
|
|
||||||
this.pon(this.lastDiscard as NonNullable<number>, p);
|
this.pon(this.lastDiscard as NonNullable<number>, p);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -272,7 +336,6 @@ export class Game {
|
||||||
}
|
}
|
||||||
|
|
||||||
private pon(p: number, thief: number = 0): void {
|
private pon(p: number, thief: number = 0): void {
|
||||||
console.log(thief, "stole", p, '\n');
|
|
||||||
let t = this.discards[p].pop() as NonNullable<Tile>;
|
let t = this.discards[p].pop() as NonNullable<Tile>;
|
||||||
this.lastDiscard = undefined;
|
this.lastDiscard = undefined;
|
||||||
let t2 = this.hands[thief].find(t.getFamily(), t.getValue()) as NonNullable<Tile>;
|
let t2 = this.hands[thief].find(t.getFamily(), t.getValue()) as NonNullable<Tile>;
|
||||||
|
|
@ -308,14 +371,18 @@ export class Game {
|
||||||
}
|
}
|
||||||
|
|
||||||
// called
|
// called
|
||||||
drawButtons(
|
if (this.chooseChii) {
|
||||||
this.staticCtx,
|
drawChiis(this.staticCtx, this.getChii(0));
|
||||||
this.canDoAChii().length > 0,
|
} else {
|
||||||
this.canDoAPon(),
|
drawButtons(
|
||||||
false && this.level > 1,
|
this.staticCtx,
|
||||||
false && this.level > 0,
|
this.canDoAChii().length > 0,
|
||||||
false && this.level > 0
|
this.canDoAPon(),
|
||||||
);
|
false && this.level > 1,
|
||||||
|
false && this.level > 0,
|
||||||
|
false && this.level > 0
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private drawHands() {
|
private drawHands() {
|
||||||
|
|
|
||||||
57
src/text/parse.ts
Normal file
57
src/text/parse.ts
Normal file
|
|
@ -0,0 +1,57 @@
|
||||||
|
export async function drawText(
|
||||||
|
filePath: string,
|
||||||
|
ctx: CanvasRenderingContext2D,
|
||||||
|
): Promise<void> {
|
||||||
|
console.log(filePath, "\n");
|
||||||
|
const fileContent = await fetch(filePath)
|
||||||
|
.then(response => response.text());
|
||||||
|
const size = 30;
|
||||||
|
const dl = 5;
|
||||||
|
const ll = 50;
|
||||||
|
const xx = 10;
|
||||||
|
const defaultColor = "#ffffff";
|
||||||
|
ctx.fillStyle = defaultColor;
|
||||||
|
ctx.font = size + "px Garamond";
|
||||||
|
|
||||||
|
let readingColor = false;
|
||||||
|
let color = "";
|
||||||
|
let gras = "";
|
||||||
|
let italic = "";
|
||||||
|
|
||||||
|
let line = 1;
|
||||||
|
let x = 0;
|
||||||
|
for (var c of fileContent) {
|
||||||
|
if (c === '*') {
|
||||||
|
if (gras === "") {
|
||||||
|
gras = "bold ";
|
||||||
|
} else {
|
||||||
|
gras = "";
|
||||||
|
}
|
||||||
|
ctx.font = italic + gras + size + "px Garamond";
|
||||||
|
} else if (c === '~') {
|
||||||
|
if (italic === "") {
|
||||||
|
italic = "italic ";
|
||||||
|
} else {
|
||||||
|
italic = "";
|
||||||
|
}
|
||||||
|
ctx.font = italic + gras + size + "px Garamond";
|
||||||
|
} else if (c === '#') {
|
||||||
|
color = "#";
|
||||||
|
readingColor = true;
|
||||||
|
} else if (c === '{') {
|
||||||
|
readingColor = false;
|
||||||
|
ctx.fillStyle = color;
|
||||||
|
} else if (c === '}') {
|
||||||
|
color = "";
|
||||||
|
ctx.fillStyle = defaultColor;
|
||||||
|
} else if (readingColor) {
|
||||||
|
color += c;
|
||||||
|
} else if (c === '\n') {
|
||||||
|
line++;
|
||||||
|
x = 0;
|
||||||
|
} else {
|
||||||
|
ctx.fillText(c, xx + x, ll + line * (size + dl));
|
||||||
|
x += ctx.measureText(c).width;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
18
src/text/txt1.ts
Normal file
18
src/text/txt1.ts
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
import { drawText } from "./parse"
|
||||||
|
|
||||||
|
const CANVAS_ID = "myTextCanvas";
|
||||||
|
const BG_RECT = { x: 0, y: 0, w: 800, h: 1050, color: "#007733" };
|
||||||
|
|
||||||
|
const canvas = document.getElementById(CANVAS_ID) as HTMLCanvasElement;
|
||||||
|
const ctx = canvas.getContext("2d") as NonNullable<CanvasRenderingContext2D>;
|
||||||
|
canvas.width = BG_RECT.w;
|
||||||
|
canvas.height = BG_RECT.h;
|
||||||
|
|
||||||
|
const path = "../src/text/";
|
||||||
|
|
||||||
|
ctx.fillStyle = BG_RECT.color;
|
||||||
|
ctx.fillRect(BG_RECT.x, BG_RECT.y, BG_RECT.w, BG_RECT.h);
|
||||||
|
|
||||||
|
drawText(path + "txt1.txt", ctx).catch(error => console.error(error));
|
||||||
|
|
||||||
|
export {};
|
||||||
16
src/text/txt1.txt
Normal file
16
src/text/txt1.txt
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
Le *Riichi Mahjong* est un jeu qui se joue avec des *tuiles*.
|
||||||
|
Elles sont similaires aux cartes d'un jeu de Tarot dans la mesure
|
||||||
|
où elles se divisent en deux catégories:
|
||||||
|
|
||||||
|
- Les #ff00ff{familles}
|
||||||
|
Nous pouvons retrouver dans ce jeu *3* familles distinctes:
|
||||||
|
- Les *Man*, appelées les #ff00ff{Caractères}
|
||||||
|
- Les *Pin*, appelées les #ff00ff{Ronds}
|
||||||
|
- Les *Sou*, appelées les #ff00ff{Bambous}
|
||||||
|
Comme dans un jeu de cartes, ils sont tous numérotées
|
||||||
|
de *1* jusqu'à *9*.
|
||||||
|
|
||||||
|
- Les #ff00ff{honneurs}
|
||||||
|
Ils sont séparés selon *2* catégories:
|
||||||
|
- Les *Dragons*: #ff0000{Rouge}, #ffffff{Blanc} et #00ff00{Vert}
|
||||||
|
- Les *Vents*: #0000e0{Est}, #0000e0{Sud}, #0000e0{Ouest} et #0000e0{Nord}
|
||||||
18
src/text/txt2.ts
Normal file
18
src/text/txt2.ts
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
import { drawText } from "./parse"
|
||||||
|
|
||||||
|
const CANVAS_ID = "myTextCanvas";
|
||||||
|
const BG_RECT = { x: 0, y: 0, w: 800, h: 1050, color: "#007733" };
|
||||||
|
|
||||||
|
const canvas = document.getElementById(CANVAS_ID) as HTMLCanvasElement;
|
||||||
|
const ctx = canvas.getContext("2d") as NonNullable<CanvasRenderingContext2D>;
|
||||||
|
canvas.width = BG_RECT.w;
|
||||||
|
canvas.height = BG_RECT.h;
|
||||||
|
|
||||||
|
const path = "../src/text/";
|
||||||
|
|
||||||
|
ctx.fillStyle = BG_RECT.color;
|
||||||
|
ctx.fillRect(BG_RECT.x, BG_RECT.y, BG_RECT.w, BG_RECT.h);
|
||||||
|
|
||||||
|
drawText(path + "txt2.txt", ctx).catch(error => console.error(error));
|
||||||
|
|
||||||
|
export {};
|
||||||
23
src/text/txt2.txt
Normal file
23
src/text/txt2.txt
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
Durant une partie, un joueur possède dans sa main un total
|
||||||
|
de *13 tuiles*.
|
||||||
|
|
||||||
|
Lors de son tour, un joueur commence par *récupérer* une
|
||||||
|
tuile supplémentaire, avant d'en *défausser* une (il peut
|
||||||
|
s'agir de la même).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
~Une main interactive est mise à disposition pour s'entrainer
|
||||||
|
à cette mécanique~
|
||||||
18
src/text/txt3.ts
Normal file
18
src/text/txt3.ts
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
import { drawText } from "./parse"
|
||||||
|
|
||||||
|
const CANVAS_ID = "myTextCanvas";
|
||||||
|
const BG_RECT = { x: 0, y: 0, w: 800, h: 1050, color: "#007733" };
|
||||||
|
|
||||||
|
const canvas = document.getElementById(CANVAS_ID) as HTMLCanvasElement;
|
||||||
|
const ctx = canvas.getContext("2d") as NonNullable<CanvasRenderingContext2D>;
|
||||||
|
canvas.width = BG_RECT.w;
|
||||||
|
canvas.height = BG_RECT.h;
|
||||||
|
|
||||||
|
const path = "../src/text/";
|
||||||
|
|
||||||
|
ctx.fillStyle = BG_RECT.color;
|
||||||
|
ctx.fillRect(BG_RECT.x, BG_RECT.y, BG_RECT.w, BG_RECT.h);
|
||||||
|
|
||||||
|
drawText(path + "txt3.txt", ctx).catch(error => console.error(error));
|
||||||
|
|
||||||
|
export {};
|
||||||
24
src/text/txt3.txt
Normal file
24
src/text/txt3.txt
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
Dans le but de gagner, un joueur doit réussir à créer une
|
||||||
|
main avec une forme particulière. en effet, elle doit être
|
||||||
|
constituée de:
|
||||||
|
|
||||||
|
- *4 groupes distincts* constituées de *3 tuiles*
|
||||||
|
- *1 paire*
|
||||||
|
|
||||||
|
~Ci-contre des exemples de groupes valides et non valides~
|
||||||
|
|
||||||
|
Nous y distinguons:
|
||||||
|
- Les #ff00ff{Chii}, correspondant aux *Suites*
|
||||||
|
- Les #ff00ff{Pon}, correspondant aux *Brelans*
|
||||||
|
|
||||||
|
Ainsi, pour gagner, un joueur doit posseder *3 x 4 + 2* tuiles,
|
||||||
|
soit *14* tuiles au total.
|
||||||
|
De ce fait, il n'est possible de gagner uniquement lorsqu'une
|
||||||
|
tuile est récupérée
|
||||||
|
|
||||||
|
Lorsque tous ces groupes sont présents, nous dirons que la
|
||||||
|
main est #ff00ff{Valide}
|
||||||
|
|
||||||
|
~De même, il est possible de s'entraîner cette fois à piocher
|
||||||
|
et défausser des tuiles jusqu'à l'obtention d'une main valide
|
||||||
|
PS: un message le fera savoir à ce moment là~
|
||||||
18
src/text/txt4.ts
Normal file
18
src/text/txt4.ts
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
import { drawText } from "./parse"
|
||||||
|
|
||||||
|
const CANVAS_ID = "myTextCanvas";
|
||||||
|
const BG_RECT = { x: 0, y: 0, w: 800, h: 1050, color: "#007733" };
|
||||||
|
|
||||||
|
const canvas = document.getElementById(CANVAS_ID) as HTMLCanvasElement;
|
||||||
|
const ctx = canvas.getContext("2d") as NonNullable<CanvasRenderingContext2D>;
|
||||||
|
canvas.width = BG_RECT.w;
|
||||||
|
canvas.height = BG_RECT.h;
|
||||||
|
|
||||||
|
const path = "../src/text/";
|
||||||
|
|
||||||
|
ctx.fillStyle = BG_RECT.color;
|
||||||
|
ctx.fillRect(BG_RECT.x, BG_RECT.y, BG_RECT.w, BG_RECT.h);
|
||||||
|
|
||||||
|
drawText(path + "txt4.txt", ctx).catch(error => console.error(error));
|
||||||
|
|
||||||
|
export {};
|
||||||
25
src/text/txt4.txt
Normal file
25
src/text/txt4.txt
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
Voici votre *première partie* !
|
||||||
|
Il est temps de mettre en oeuvre tout ce que vous avez appris.
|
||||||
|
|
||||||
|
Il est cependant important de noter dorénavant une mécanique
|
||||||
|
essentielle pour l'obtention de nouvelles tuiles:
|
||||||
|
|
||||||
|
- Lorsqu'une personne défausse une tuile permettant à un joueur
|
||||||
|
de compléter un *brelan*, il peut l'annoncer avec #ff00ff{Pon !} et la
|
||||||
|
récupérer pour lui
|
||||||
|
- Lorsque le joueur *précédent* défausse une tuile permettant au
|
||||||
|
joueur de compléter une *suite*, il peut l'annoncer avec #ff00ff{Chii !} et
|
||||||
|
de la même manière la récupérer pour lui
|
||||||
|
|
||||||
|
#ff0000{Attention !}
|
||||||
|
Cette action est appelée un #ff00ff{appel}. Ce dernier est *définitif* et est
|
||||||
|
*visible par tout le monde*
|
||||||
|
|
||||||
|
PS: si un joueur veut faire un *Chii* en même temps qu'un autre
|
||||||
|
veut faire un *Pon*, alors le *Pon* a *toujours* la priorité
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
~Il est maintenant tant de choisir une tuile à défausser !~
|
||||||
|
|
@ -4,7 +4,9 @@ const fs = require('fs');
|
||||||
// Fonction pour détecter automatiquement les fichiers dp*.ts
|
// Fonction pour détecter automatiquement les fichiers dp*.ts
|
||||||
function getEntryPoints() {
|
function getEntryPoints() {
|
||||||
const displayDir = path.resolve(__dirname, 'src', 'display');
|
const displayDir = path.resolve(__dirname, 'src', 'display');
|
||||||
|
const textDir = path.resolve(__dirname, 'src', 'text');
|
||||||
const files = fs.readdirSync(displayDir); // Lire les fichiers du répertoire
|
const files = fs.readdirSync(displayDir); // Lire les fichiers du répertoire
|
||||||
|
const texts = fs.readdirSync(textDir);
|
||||||
const entryPoints = {};
|
const entryPoints = {};
|
||||||
|
|
||||||
files.forEach((file) => {
|
files.forEach((file) => {
|
||||||
|
|
@ -13,6 +15,12 @@ function getEntryPoints() {
|
||||||
entryPoints[name] = path.join(displayDir, file); // Chemin complet du fichier
|
entryPoints[name] = path.join(displayDir, file); // Chemin complet du fichier
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
texts.forEach((file) => {
|
||||||
|
if (file.startsWith('txt') && file.endsWith('.ts')) {
|
||||||
|
const name = path.basename(file, '.ts');
|
||||||
|
entryPoints[name] = path.join(textDir, file);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
return entryPoints;
|
return entryPoints;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue