diff --git a/client/assets/styles/game.css b/client/assets/styles/game.css index 0495af41..7e2a31f1 100644 --- a/client/assets/styles/game.css +++ b/client/assets/styles/game.css @@ -194,7 +194,7 @@ } .game-construct.unfocus { - opacity: 0.65; + opacity: 0.35; /* filter: blur(5px); */} diff --git a/client/src/animations.socket.jsx b/client/src/animations.socket.jsx index 5f868869..2108b137 100644 --- a/client/src/animations.socket.jsx +++ b/client/src/animations.socket.jsx @@ -28,20 +28,16 @@ function createSocket(store) { return eachSeries(newRes, (r, cb) => { if (['Disable', 'TargetKo'].includes(r.event[0])) return cb(); // Create sub events for combat animations - const sequence = getCombatSequence(r); - return eachSeries(sequence, (stage, sCb) => { - const { skip } = store.getState(); - if (skip) return sCb('skip'); - const stagedR = Object.create(r); - stagedR.stage = stage; - store.dispatch(actions.setResolution(stagedR)); + store.dispatch(actions.setResolution(r)); + // const sequence = getCombatSequence(r); - return setTimeout(sCb, TIMES[stage]); - }, err => { - if (err) console.error(err); - // Finished this resolution - return cb(); - }); + // sequence.forEach(stage => { + // const stagedR = Object.create(r); + // stagedR.stage = stage; + // store.dispatch(actions.setResolution(stagedR)); + // }); + + setTimeout(cb, 2000); }, err => { if (err) return console.error(err); store.dispatch(actions.setResolution(null)); @@ -49,9 +45,9 @@ function createSocket(store) { store.dispatch(actions.setSkip(false)); // update the game store.dispatch(actions.setGame(currentGame)); - // get the latest state and restart polling return true; }); + } const handlers = { diff --git a/client/src/components/animations.jsx b/client/src/components/animations.jsx index 3d9c7739..bc08bb7b 100644 --- a/client/src/components/animations.jsx +++ b/client/src/components/animations.jsx @@ -1,4 +1,5 @@ const preact = require('preact'); +const anime = require('animejs').default; const AttackCharge = require('./anims/attack.charge'); @@ -27,71 +28,92 @@ const colours = { white: '#FFFFFF', }; +const SOURCE_ANIM_MS = 1000; + +const TARGET_ANIM_DELAY_MS = 500; +const TARGET_ANIM_MS = 1000; function animations(props) { - const { combatTextClass, combatText, stage, player, construct } = props; + const { resolution, stage, player, construct, game, account } = props; + + if (!resolution) return false; + const [type, event] = resolution.event; + if (!event.skill) return false; + if (!resolution.target) return false; + + // source animation + if (resolution.source.id === construct.id) { + const playerTeam = game.players.find(t => t.id === account.id); + const playerTeamIds = playerTeam.constructs.map(c => c.id); + playerTeamIds.sort(); + const otherTeam = game.players.find(t => t.id !== account.id); + const otherTeamIds = otherTeam.constructs.map(c => c.id); + otherTeamIds.sort(); + + const sourceIsPlayer = playerTeamIds.includes(construct.id); + const targetIsPlayer = playerTeamIds.includes(resolution.target.id); + + const sameTeam = (sourceIsPlayer && targetIsPlayer) || (!sourceIsPlayer && !targetIsPlayer); + + const y = sameTeam + ? 0 + : targetIsPlayer + ? 1 + : -1; + + const i = sourceIsPlayer + ? playerTeamIds.findIndex(c => c === construct.id) + : otherTeamIds.findIndex(c => c === construct.id); + + const j = targetIsPlayer + ? playerTeamIds.findIndex(c => c === resolution.target.id) + : otherTeamIds.findIndex(c => c === resolution.target.id); + + const x = j - i; + + anime({ + targets: [document.getElementById(construct.id)], + translateY: y * 200, + translateX: x * 200, + easing: 'easeInOutElastic', + direction: 'alternate', + duration: SOURCE_ANIM_MS, + }); + } + + if (resolution.target.id !== construct.id) return false; + + // target animation const anim = text => { - if (stage === 'START_SKILL') { - const skill = removeTier(text); - switch (skill) { - // Attack Base - case 'Attack': return ; - case 'Strike': return ; - case 'Heal': return ; - case 'Blast': return ; - case 'Chaos': return ; - case 'Slay': return ; - case 'Siphon': return ; - // Stun Base - // Block Base - // Buff Base - // Debuff Base - default: return false; - } - } else if (stage === 'END_SKILL') { - const skill = removeTier(text); - switch (skill) { - case 'Attack': return ; - case 'Amplify': return ; - case 'Banish': return banish(construct.id); - case 'Blast': return ; - case 'Strike': return ; - case 'Chaos': return ; - case 'Slay': return ; - case 'Heal': return ; - case 'Hex': return ; - case 'Siphon': return ; - case 'SiphonTick': return ; - default: return false; - } + console.log(text); + if (!text) return false; + const skill = removeTier(text); + switch (skill) { + case 'Attack': return ; + case 'Amplify': return ; + case 'Banish': return banish(construct.id); + case 'Blast': return ; + case 'Strike': return ; + case 'Chaos': return ; + case 'Slay': return ; + case 'Heal': return ; + case 'Hex': return ; + case 'Siphon': return ; + case 'SiphonTick': return ; + default: return false; } - return false; }; - if (combatText) { - const combatAnim = anim(combatText); - if (combatAnim) { - return ( -
- {combatAnim} -
- ); - } + const combatAnim = anim(event.skill); + console.log(combatAnim); + if (combatAnim) { return ( -
- {combatText} +
+ {combatAnim}
); } - /* - return ( -
- -
- ); - */ - return (
); } diff --git a/client/src/components/anims/amplify.jsx b/client/src/components/anims/amplify.jsx new file mode 100644 index 00000000..174891f4 --- /dev/null +++ b/client/src/components/anims/amplify.jsx @@ -0,0 +1,54 @@ +const preact = require('preact'); +const { Component } = require('preact'); + +const anime = require('animejs').default; + +class Amplify extends Component { + constructor() { + super(); + this.id = Math.random(); + } + + render() { + const path = 'M0,100 C100,100 100,100 200,100'; + + return ( + + + + + + + + ); + } + + componentDidMount() { + const altPath = 'M0,100 C100,400 100,-200 200,100'; + anime({ + targets: '#amplify path', + d: [{ value: altPath }], + stroke: ['#3498db', '#a52a2a'], + duration: 1000, + direction: 'alternate', + easing: 'easeInOutSine', + delay: 500, + }); + + anime({ + targets: ['#ampFilter feTurbulence', '#ampFilter feDisplacementMap'], + baseFrequency: 0.15, + scale: 4, + direction: 'alternate', + easing: 'easeInOutExpo', + delay: 500, + }); + } +} + +module.exports = Amplify; diff --git a/client/src/components/anims/attack.jsx b/client/src/components/anims/attack.jsx index c642f645..140ff5eb 100644 --- a/client/src/components/anims/attack.jsx +++ b/client/src/components/anims/attack.jsx @@ -35,37 +35,35 @@ class Attack extends Component { componentDidMount() { let y = 0; const daggers = document.querySelectorAll('.attack-anim .dagger'); - if (this.props.stage === 'START_SKILL') { - anime.set(daggers, { - y: 250, + anime.set(daggers, { + y: 250, + }); + y = -150; + if (!this.props.team) { + anime.set('.attack-anim', { + rotate: 180, + }); + } else { + anime.set('.attack-anim', { + rotate: 0, }); - y = -150; - if (!this.props.team) { - anime.set('.attack-anim', { - rotate: 180, - }); - } else { - anime.set('.attack-anim', { - rotate: 0, - }); - } } - if (this.props.stage === 'END_SKILL') { - anime.set(daggers, { - y: 400, - }); - y = -150; - if (!this.props.team) { - anime.set('.attack-anim', { - rotate: 0, - }); - } else { - anime.set('.attack-anim', { - rotate: 180, - }); - } - } + // if (this.props.stage === 'END_SKILL') { + // anime.set(daggers, { + // y: 400, + // }); + // y = -150; + // if (!this.props.team) { + // anime.set('.attack-anim', { + // rotate: 0, + // }); + // } else { + // anime.set('.attack-anim', { + // rotate: 180, + // }); + // } + // } anime({ targets: daggers, diff --git a/client/src/components/anims/banish.jsx b/client/src/components/anims/banish.jsx new file mode 100644 index 00000000..53d31eac --- /dev/null +++ b/client/src/components/anims/banish.jsx @@ -0,0 +1,17 @@ +const anime = require('animejs').default; +const { TIMES } = require('../../constants'); + +// shamelessly lifted from teh anime docs +// https://animejs.com/documentation/#svgAttr + +function banish(id) { + anime({ + targets: [document.getElementById(id)], + scaleY: 0, + fill: '#fff', + easing: 'easeInOutElastic', + duration: TIMES.START_SKILL, + }); +} + +module.exports = banish; diff --git a/client/src/components/anims/heal.jsx b/client/src/components/anims/heal.jsx index 63e2b2bb..4f23a22f 100644 --- a/client/src/components/anims/heal.jsx +++ b/client/src/components/anims/heal.jsx @@ -59,19 +59,19 @@ class Heal extends Component { } componentDidMount() { - if (!this.props.team) { - anime.set('.skill-anim', { - rotate: Math.random() * 180 + 90, - }); - } else { - anime.set('.skill-anim', { - rotate: Math.random() * 180 + 270, - }); - } - anime.set('.skill-anim', { - translateY: -200, - translateX: 0, - }); + // if (!this.props.team) { + // anime.set('.skill-anim', { + // rotate: Math.random() * 180 + 90, + // }); + // } else { + // anime.set('.skill-anim', { + // rotate: Math.random() * 180 + 270, + // }); + // } + // anime.set('.skill-anim', { + // translateY: -200, + // translateX: 0, + // }); anime.set('#explosion feDisplacementMap', { scale: 100, }); diff --git a/client/src/components/game.construct.jsx b/client/src/components/game.construct.jsx index 884b7870..adc58d42 100644 --- a/client/src/components/game.construct.jsx +++ b/client/src/components/game.construct.jsx @@ -78,15 +78,16 @@ function GameConstruct(props) { const [combatText, combatClass] = getCombatText(construct, resolution); const combatTextClass = `combat-text ${combatClass}`; + const playerTeam = game.players.find(t => t.id === account.id); + const playerTeamIds = playerTeam.constructs.map(c => c.id); + const stage = resolution ? resolution.stage : false; - const combatInfo = animations({ combatTextClass, combatText, stage, player, construct }); + const combatInfo = animations({ game, account, resolution, stage, player, construct }); const effects = construct.effects.length ? construct.effects.map(c =>
{c.effect} - {c.duration}T
) :
 
; - const playerTeam = game.players.find(t => t.id === account.id); - const playerTeamIds = playerTeam.constructs.map(c => c.id); return (