fix: clip card images via Canvas 2D in BootScene, no Phaser mask needed
This commit is contained in:
1 parent
4d09102464
commit
da06ecaf2d
2 files changed
+127
-103
No files matched your search
@@ -1,48 +1,124 @@
|
||||
import Phaser from 'phaser'
|
||||
|
||||
// Correspondance id personnage → fichier image
|
||||
const CARD_IMAGES = [
|
||||
{ id: 'queen', file: 'reine.png' },
|
||||
{ id: 'prince', file: 'prince.png' },
|
||||
{ id: 'butcher', file: 'boucher.png' },
|
||||
{ id: 'doctor', file: 'medecin.png' },
|
||||
{ id: 'apothecary', file: 'apoticaire.png'},
|
||||
{ id: 'jester', file: 'fou_du_roi.png'},
|
||||
{ id: 'assassin', file: 'assassin.png' },
|
||||
{ id: 'peasant', file: 'paysan.png' },
|
||||
{ id: 'executioner', file: 'bourreau.png' },
|
||||
{ id: 'knight', file: 'chevalier.png' },
|
||||
{ id: 'merchant', file: 'marchand.png' },
|
||||
{ id: 'bishop', file: 'eveque.png' }
|
||||
{ id: 'queen', file: 'reine.png' },
|
||||
{ id: 'prince', file: 'prince.png' },
|
||||
{ id: 'butcher', file: 'boucher.png' },
|
||||
{ id: 'doctor', file: 'medecin.png' },
|
||||
{ id: 'apothecary', file: 'apoticaire.png' },
|
||||
{ id: 'jester', file: 'fou_du_roi.png' },
|
||||
{ id: 'assassin', file: 'assassin.png' },
|
||||
{ id: 'peasant', file: 'paysan.png' },
|
||||
{ id: 'executioner', file: 'bourreau.png' },
|
||||
{ id: 'knight', file: 'chevalier.png' },
|
||||
{ id: 'merchant', file: 'marchand.png' },
|
||||
{ id: 'bishop', file: 'eveque.png' }
|
||||
]
|
||||
|
||||
const CARD_W = 130
|
||||
const CARD_H = 190
|
||||
const RADIUS = 10
|
||||
|
||||
export class BootScene extends Phaser.Scene {
|
||||
constructor() {
|
||||
super('BootScene')
|
||||
}
|
||||
|
||||
preload() {
|
||||
// Charger les images des 12 personnages
|
||||
CARD_IMAGES.forEach(({ id, file }) => {
|
||||
this.load.image(`card-${id}`, `/cards/${file}`)
|
||||
})
|
||||
|
||||
// Barre de chargement simple
|
||||
// Barre de chargement
|
||||
const { width, height } = this.scale
|
||||
const bar = this.add.graphics()
|
||||
const barBg = this.add.graphics()
|
||||
const barFill = this.add.graphics()
|
||||
|
||||
barBg.fillStyle(0x2a1500)
|
||||
barBg.fillRect(width / 2 - 150, height / 2 - 10, 300, 20)
|
||||
|
||||
this.load.on('progress', (v) => {
|
||||
bar.clear()
|
||||
bar.fillStyle(0x1a0a00)
|
||||
bar.fillRect(width / 2 - 150, height / 2 - 10, 300, 20)
|
||||
bar.fillStyle(0xd4a732)
|
||||
bar.fillRect(width / 2 - 150, height / 2 - 10, 300 * v, 20)
|
||||
barFill.clear()
|
||||
barFill.fillStyle(0xd4a732)
|
||||
barFill.fillRect(width / 2 - 150, height / 2 - 10, 300 * v, 20)
|
||||
})
|
||||
|
||||
this.load.on('complete', () => bar.destroy())
|
||||
this.load.on('complete', () => {
|
||||
barBg.destroy()
|
||||
barFill.destroy()
|
||||
})
|
||||
|
||||
// Charger les images brutes
|
||||
CARD_IMAGES.forEach(({ id, file }) => {
|
||||
this.load.image(`raw-${id}`, `/cards/${file}`)
|
||||
})
|
||||
}
|
||||
|
||||
create() {
|
||||
// Pour chaque personnage, générer une texture clippée via Canvas 2D
|
||||
CARD_IMAGES.forEach(({ id }) => {
|
||||
this._generateClippedTexture(id)
|
||||
})
|
||||
|
||||
this.scene.start('GameScene')
|
||||
}
|
||||
|
||||
/**
|
||||
* Crée une texture `card-{id}` de dimensions CARD_W × CARD_H
|
||||
* avec l'image clippée en rectangle arrondi via Canvas 2D natif.
|
||||
* Pas de masque Phaser, pas de RenderTexture — juste du canvas.
|
||||
*/
|
||||
_generateClippedTexture(id) {
|
||||
const rawKey = `raw-${id}`
|
||||
const outKey = `card-${id}`
|
||||
|
||||
if (!this.textures.exists(rawKey)) return
|
||||
if (this.textures.exists(outKey)) return
|
||||
|
||||
const srcImage = this.textures.get(rawKey).getSourceImage()
|
||||
|
||||
// Créer un canvas offscreen
|
||||
const canvas = document.createElement('canvas')
|
||||
canvas.width = CARD_W
|
||||
canvas.height = CARD_H
|
||||
const ctx = canvas.getContext('2d')
|
||||
|
||||
// Chemin arrondi (clip)
|
||||
ctx.beginPath()
|
||||
ctx.moveTo(RADIUS, 0)
|
||||
ctx.lineTo(CARD_W - RADIUS, 0)
|
||||
ctx.quadraticCurveTo(CARD_W, 0, CARD_W, RADIUS)
|
||||
ctx.lineTo(CARD_W, CARD_H - RADIUS)
|
||||
ctx.quadraticCurveTo(CARD_W, CARD_H, CARD_W - RADIUS, CARD_H)
|
||||
ctx.lineTo(RADIUS, CARD_H)
|
||||
ctx.quadraticCurveTo(0, CARD_H, 0, CARD_H - RADIUS)
|
||||
ctx.lineTo(0, RADIUS)
|
||||
ctx.quadraticCurveTo(0, 0, RADIUS, 0)
|
||||
ctx.closePath()
|
||||
ctx.clip()
|
||||
|
||||
// Dessiner l'image en mode "cover" (ratio conservé, centré)
|
||||
const scaleX = CARD_W / srcImage.width
|
||||
const scaleY = CARD_H / srcImage.height
|
||||
const scale = Math.max(scaleX, scaleY)
|
||||
const dw = srcImage.width * scale
|
||||
const dh = srcImage.height * scale
|
||||
const ox = (CARD_W - dw) / 2
|
||||
const oy = (CARD_H - dh) / 2
|
||||
|
||||
ctx.drawImage(srcImage, ox, oy, dw, dh)
|
||||
|
||||
// Dégradé haut (lisibilité badges)
|
||||
const gTop = ctx.createLinearGradient(0, 0, 0, 45)
|
||||
gTop.addColorStop(0, 'rgba(0,0,0,0.75)')
|
||||
gTop.addColorStop(1, 'rgba(0,0,0,0)')
|
||||
ctx.fillStyle = gTop
|
||||
ctx.fillRect(0, 0, CARD_W, 45)
|
||||
|
||||
// Dégradé bas (lisibilité titre)
|
||||
const gBot = ctx.createLinearGradient(0, CARD_H - 40, 0, CARD_H)
|
||||
gBot.addColorStop(0, 'rgba(0,0,0,0)')
|
||||
gBot.addColorStop(1, 'rgba(0,0,0,0.85)')
|
||||
ctx.fillStyle = gBot
|
||||
ctx.fillRect(0, CARD_H - 40, CARD_W, 40)
|
||||
|
||||
// Enregistrer comme texture Phaser
|
||||
this.textures.addCanvas(outKey, canvas)
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user