const Phaser = require('phaser'); const { TEXT } = require('.././constants'); const BOX = ` #ifdef GL_ES precision mediump float; #endif #extension GL_OES_standard_derivatives : enable #ifdef GL_ES precision mediump float; #endif #extension GL_OES_standard_derivatives : enable uniform float time; uniform vec2 resolution; uniform vec2 dimensions; uniform vec2 offset; uniform vec3 colour; uniform sampler2D uMainSampler; varying vec2 outTexCoord; varying vec4 outTint; float sdBox( in vec2 p, in vec2 b ) { vec2 d = abs(p)-b; return length(max(d,vec2(0))) + min(max(d.x,d.y),0.0); } void main() { vec2 p = (gl_FragCoord.xy / resolution.xy); p.x -= offset.x / resolution.x + dimensions.x / (2.0 * resolution.x); p.y -= -1.0 * offset.y / resolution.y + ((resolution.y - dimensions.y) / (2.0 * resolution.y)) + 0.5; vec2 dim = 0.5 * dimensions / resolution.xy; float d = sdBox(p, dim); float tb = abs(sin(time)) + 0.9; vec3 col = tb * colour - sign(d) * vec3(0.1); col *= 0.0 + exp(-100.0 * abs(d)); col += colour * 0.8; vec4 texel = texture2D(uMainSampler, outTexCoord); texel *= vec4(outTint.rgb * outTint.a, outTint.a); gl_FragColor = vec4(col, 1.0); } `; class CustomPipeline extends Phaser.Renderer.WebGL.Pipelines.TextureTintPipeline { constructor(game) { super({ game, renderer: game.renderer, fragShader: BOX }); } } function rgbToHex(rgb) { const getHex = (c) => { const hex = Math.floor(c * 255).toString(16); return hex.length === 1 ? `0${hex}` : hex; }; return `0x${getHex(rgb[0])}${getHex(rgb[1])}${getHex(rgb[2])}`; } class BoxEffect extends Phaser.GameObjects.Graphics { constructor(scene, x, y, width, height, colour, tag) { super(scene); this.tag = tag; this.customPipeline = scene.game.renderer.addPipeline(tag, new CustomPipeline(scene.game)); this.customPipeline.setFloat2('resolution', 1600, 1000); this.customPipeline.setFloat2('offset', x, y); this.customPipeline.setFloat2('dimensions', width, height); this.customPipeline.setFloat3('colour', colour[0], colour[1], colour[2]); this.bgTime = 10.0; const radius = height / 2; this.fillStyle(rgbToHex(colour), 1.0); this.fillRect(x + radius, y, width - radius * 2, height); this.fillCircle(x + radius, y + radius, radius); this.fillCircle(x + width - radius, y + radius, radius); this.on('destroy', () => { scene.game.renderer.removePipeline(tag); }); } activate() { this.setPipeline(this.tag); } deactivate() { this.resetPipeline(); } update() { this.bgTime += 0.05; this.customPipeline.setFloat1('time', this.bgTime); } } class Button extends Phaser.GameObjects.Group { constructor(scene, props) { const { x, y, width, height, colour, glTag, bText, callback, } = props; super(scene, { classType: BoxEffect, runChildUpdate: true }); const leaveGame = scene.add .rectangle(x, y, width, height, 0xaaaaaa, 0xffffff) .setInteractive() .setOrigin(0); const effect = scene.add.existing(new BoxEffect(scene, x, y, width, height, colour, glTag)); this.add(effect); leaveGame .on('pointerdown', callback) .on('pointerover', () => effect.activate()) .on('pointerout', () => effect.deactivate()); this.buttonText = scene.add.text(leaveGame.getCenter().x, leaveGame.getCenter().y, bText, TEXT.HEADER).setOrigin(0.5, 0.5); } } module.exports = Button;