diff --git a/package.json b/package.json index 8d0db7dc..bb127743 100644 --- a/package.json +++ b/package.json @@ -48,5 +48,5 @@ "preview:https": "serve dist", "reinstall": "rm -rf node_modules; yarn; vue-tsc --noEmit" }, - "version": "5.0.0-alpha.263" + "version": "5.0.0-alpha.264" } diff --git a/src/components/units/AppGameVariants.vue b/src/components/units/AppGameVariants.vue index b2a22df8..5994d7b7 100644 --- a/src/components/units/AppGameVariants.vue +++ b/src/components/units/AppGameVariants.vue @@ -59,7 +59,7 @@ return logo[appLogoFilePath].default; }; const customBoardRoute = () => { - let boardStr = window.prompt('Enter a valid board string:'); + let boardStr = window.prompt('Enter a valid variant:'); if (boardStr !== null) { router.push({ name: 'game', params: { type: gameType.value, gameId: gameId.value, variantId: boardStr } }) } diff --git a/src/components/units/GameBody/AppGameBodyHeaderOptions.vue b/src/components/units/GameBody/AppGameBodyHeaderOptions.vue index d4514535..832490aa 100644 --- a/src/components/units/GameBody/AppGameBodyHeaderOptions.vue +++ b/src/components/units/GameBody/AppGameBodyHeaderOptions.vue @@ -115,7 +115,7 @@ aria-label="toggle" type="checkbox" v-model="options.showNextMoves" /> - +
store.getters.game(gameType, gameId)); const gameVariant = computed(() => store.getters.variant(gameType, gameId, variantId)); diff --git a/src/components/units/GameBody/CharacterAutoGUI.vue b/src/components/units/GameBody/CharacterAutoGUI.vue index 9fb74379..60b91caa 100644 --- a/src/components/units/GameBody/CharacterAutoGUI.vue +++ b/src/components/units/GameBody/CharacterAutoGUI.vue @@ -287,14 +287,15 @@ // Highlight move cells on hover g:hover > &.move { + cursor: pointer; fill: var(--neutralColor); } } .app-game-board-default-token { - alignment-baseline: middle; text-anchor: middle; - cursor: default; + alignment-baseline: middle; + cursor: pointer; [data-turn="A"] &.move { fill: var(--turn1Color); @@ -361,6 +362,7 @@ } &:hover { + cursor: pointer; animation-name: pulsing-arrow; animation-duration: 0.3s; animation-iteration-count: infinite; diff --git a/src/components/units/GameBody/CustomGUISim.vue b/src/components/units/GameBody/CustomGUISim.vue index a15cbb68..d5e92362 100644 --- a/src/components/units/GameBody/CustomGUISim.vue +++ b/src/components/units/GameBody/CustomGUISim.vue @@ -115,6 +115,7 @@ } &:hover { + cursor: pointer; animation-name: pulsing-line; animation-duration: 0.3s; animation-iteration-count: infinite; diff --git a/src/components/units/GameBody/ImageAutoGUI.vue b/src/components/units/GameBody/ImageAutoGUI.vue index 106eeacf..8918401b 100644 --- a/src/components/units/GameBody/ImageAutoGUI.vue +++ b/src/components/units/GameBody/ImageAutoGUI.vue @@ -182,7 +182,7 @@ const move = { str: nextMoveData.move, hint: nextMoveData.moveValue, - hintOpacity: nextMoveData.moveValueOpacity, + hintOpacity: !options.value.showNextMoves ? 0.001 : nextMoveData.moveValueOpacity, nextPosition: nextMoveData.position }; @@ -330,6 +330,7 @@ } &:hover { + cursor: pointer; animation-name: pulsing-token; animation-duration: 0.3s; animation-iteration-count: infinite; @@ -375,6 +376,7 @@ } &:hover { + cursor: pointer; animation-name: pulsing-arrow; animation-duration: 0.3s; animation-iteration-count: infinite; @@ -398,6 +400,7 @@ } &:hover { + cursor: pointer; animation-name: pulsing-line; animation-duration: 0.3s; animation-iteration-count: infinite; diff --git a/src/models/images/svg/0to10by1or2/grid.svg b/src/models/images/svg/0to10by1or2/grid.svg new file mode 100644 index 00000000..e7a6ecc5 --- /dev/null +++ b/src/models/images/svg/0to10by1or2/grid.svg @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + + + + \ No newline at end of file diff --git a/src/models/images/svg/0to10by1or2/x.svg b/src/models/images/svg/0to10by1or2/x.svg new file mode 100644 index 00000000..12ca9701 --- /dev/null +++ b/src/models/images/svg/0to10by1or2/x.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/models/images/svg/connect4/a.svg b/src/models/images/svg/connect4/a.svg deleted file mode 100644 index 50d21b54..00000000 --- a/src/models/images/svg/connect4/a.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/src/models/images/svg/lightsout/0.svg b/src/models/images/svg/lightsout/0.svg new file mode 100644 index 00000000..1089d13b --- /dev/null +++ b/src/models/images/svg/lightsout/0.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/models/images/svg/lightsout/1.svg b/src/models/images/svg/lightsout/1.svg new file mode 100644 index 00000000..36b57e74 --- /dev/null +++ b/src/models/images/svg/lightsout/1.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/models/images/svg/lightsout/background.svg b/src/models/images/svg/lightsout/background.svg new file mode 100644 index 00000000..70fed712 --- /dev/null +++ b/src/models/images/svg/lightsout/background.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/models/images/svg/lightsout/t.svg b/src/models/images/svg/lightsout/t.svg new file mode 100644 index 00000000..a4174a2b --- /dev/null +++ b/src/models/images/svg/lightsout/t.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/models/images/thumbnail/0to10by1or2-regular.png b/src/models/images/thumbnail/0to10by1or2-regular.png new file mode 100644 index 00000000..a9a4eb9b Binary files /dev/null and b/src/models/images/thumbnail/0to10by1or2-regular.png differ diff --git a/src/scripts/gamesmanUni/moveAnimation.ts b/src/scripts/gamesmanUni/moveAnimation.ts index a8f76c02..ab736e23 100644 --- a/src/scripts/gamesmanUni/moveAnimation.ts +++ b/src/scripts/gamesmanUni/moveAnimation.ts @@ -90,10 +90,17 @@ const animateQuarto = (volume: number, currPosition: string, nextPosition: strin } const animateImageAutoGUI = (volume: number, currPosition: string, nextPosition: string, moveObj: Types.Move): number => { - const currBoard = currPosition.split("_")[4]; - const nextBoard = nextPosition.split("_")[4]; - if (currBoard.length != nextBoard.length) return 0; - + var currBoard = currPosition.split("_")[4]; + var nextBoard = nextPosition.split("_")[4]; + + // Append dashes to make currBoard and nextBoard have same length, if one of them is shorter + var lengthDiff = currBoard.length - nextBoard.length; + if (lengthDiff > 0) { + nextBoard = nextBoard.concat('-'.repeat(lengthDiff)) + } else if (lengthDiff < 0) { + currBoard = currBoard.concat('-'.repeat(-lengthDiff)); + } + const store = useStore(); const imageAutoGUIData = store.getters.imageAutoGUIData(store.getters.currentGameType, store.getters.currentGameId, store.getters.currentVariantId); const currentTheme = store.getters.currentGameTheme; @@ -111,139 +118,22 @@ const animateImageAutoGUI = (volume: number, currPosition: string, nextPosition: const animationWindow = theTheme.defaultAnimationWindow || [0, currBoard.length]; var diffIdxs = []; - var i, j; + var i; var svg = document.getElementById('image-autogui'); //Get svg element var g = document.createElementNS("http://www.w3.org/2000/svg", 'g'); g.setAttribute("id", "animationForeground"); svg!.appendChild(g); - if (animationType === "simpleSlidePlaceRemove") { - var fromIdx = null; - var toIdx = null; - var appearDisappearIdx = null; - var appearing = null; + if (animationType === "entityFade") { + var entitiesAppear = false; for (i = animationWindow[0]; i < animationWindow[1]; i++) { if (currBoard[i] != nextBoard[i]) { - diffIdxs.push(i); - } - } - if (diffIdxs.length == 1) { - i = diffIdxs[0]; - if (nextBoard[i] == '-') { // Removal (fade-out) - appearing = false; - } else if (currBoard[i] == '-') { // Placement (fade-in) - appearing = true; - toIdx = i; - } else { - return 0; - } - appearDisappearIdx = i; - } else if (diffIdxs.length == 2) { - i = diffIdxs[0]; - j = diffIdxs[1]; - if (currBoard[j] == nextBoard[i] && currBoard[j] != '-') { - i = j; - j = diffIdxs[0]; - } - if (currBoard[i] == nextBoard[j]) { - if (currBoard[j] != '-' && nextBoard[i] != '-') { - return 0; - } else if (currBoard[j] != '-') { // Capture - appearDisappearIdx = j; - appearing = false; - } else if (nextBoard[i] != '-') { // Uncapture - appearDisappearIdx = i; - appearing = true; - } - fromIdx = i; - toIdx = j; - } else { - return 0; - } - } else if (diffIdxs.length == 3) { - for (const idx1 of diffIdxs) { - for (const idx2 of diffIdxs) { - if (currBoard[idx1] == nextBoard[idx2] && currBoard[idx1] != '-') { - fromIdx = idx1; - toIdx = idx2; - } - } - } - if (fromIdx == null) { - return 0; - } - for (const idx of diffIdxs) { - if (fromIdx != idx && toIdx != idx) { - appearDisappearIdx = idx; - } - } - if (currBoard[appearDisappearIdx!] == '-') { - appearing = true; - } else if (nextBoard[appearDisappearIdx!] == '-') { - appearing = false; - } else { - return 0; - } - } else { - return 0; - } - - // If `appearing` is null, don't play an appearing or disappearing animation - if (appearing === false) { // Play disappearing animation - // Opacity set to 0.001 and not 0 so that the element remains loaded - gsap.fromTo("#entity" + appearDisappearIdx, {autoAlpha: 1}, {duration: 0.5, autoAlpha: 0.001}); - } else if (appearing === true && appearDisappearIdx != null) { // Play appearing animation - var appearingChar = nextBoard[appearDisappearIdx]; - var newElement = document.createElementNS("http://www.w3.org/2000/svg", 'image'); - newElement.setAttribute("class", "appearingEntity"); - newElement.setAttribute("x", (centers[appearDisappearIdx][0] - 0.5 * entities[appearingChar].scale * widthFactor).toString()); - newElement.setAttribute("y", (centers[appearDisappearIdx][1] - 0.5 * entities[appearingChar].scale * widthFactor).toString()); - newElement.setAttribute("width", (entities[appearingChar].scale * widthFactor).toString()); - newElement.setAttribute("height", (entities[appearingChar].scale * widthFactor).toString()); - newElement.setAttribute("href", getImageSource(entities[appearingChar].image)); - newElement.setAttribute("opacity", "0.001"); - g.appendChild(newElement); - gsap.fromTo(".appearingEntity", {opacity: 0.001}, {duration: 0.5, opacity: 1}); - } - - if (fromIdx != null && toIdx != null) { // Play sliding animation - const toCoords = centers[toIdx]; - const fromCoords = centers[fromIdx]; - gsap.fromTo("#entity" + fromIdx, {autoAlpha: 1}, {duration: 0.001, autoAlpha: 0.001}); - - var movingChar = currBoard[fromIdx]; - var newElement = document.createElementNS("http://www.w3.org/2000/svg", 'image'); - newElement.setAttribute("class", "movingEntity"); - newElement.setAttribute("x", (centers[fromIdx][0] - 0.5 * entities[movingChar].scale * widthFactor).toString()); - newElement.setAttribute("y", (centers[fromIdx][1] - 0.5 * entities[movingChar].scale * widthFactor).toString()); - newElement.setAttribute("width", (entities[movingChar].scale * widthFactor).toString()); - newElement.setAttribute("height", (entities[movingChar].scale * widthFactor).toString()); - newElement.setAttribute("href", getImageSource(entities[movingChar].image)); - g.appendChild(newElement); - gsap.to(".movingEntity", {duration: 0.5, x: toCoords[0] - fromCoords[0], y: toCoords[1] - fromCoords[1]}); - } - if (foregroundImagePath !== "") { // Redraw foreground image in front of any newly introduced entities - var newElement = document.createElementNS("http://www.w3.org/2000/svg", 'image'); - newElement.setAttribute("width", scaledWidth.toString()); - newElement.setAttribute("height", scaledHeight.toString()); - newElement.setAttribute("href", getImageSource(foregroundImagePath)); - g.appendChild(newElement); - } - let matches; - if (matches = moveObj.move.match(/^([AML])_([a-zA-Z0-9-]+)_([a-zA-Z0-9-]+)_([a-zA-Z0-9-]+)*/)) { - if (Object.keys(sounds).includes(matches[4])) { - playAudio(sounds[matches[4]], volume); - } - } - return 500; - } else if (animationType === "naiveInterpolate") { - for (i = animationWindow[0]; i < animationWindow[1]; i++) { - if (currBoard[i] != nextBoard[i]) { - if (currBoard[i] != '-') { // Entity originally at i shall fade out + if (currBoard[i] != '-') { // Entity originally at center i shall fade out gsap.fromTo("#entity" + i, {autoAlpha: 1}, {duration: 0.5, autoAlpha: 0.001}); } - if (nextBoard[i] != '-') { // Entity that will be at i shall fade in + if (nextBoard[i] != '-') { // Entity that will be at center i shall fade in + entitiesAppear = true; var appearingChar = nextBoard[i]; var newElement = document.createElementNS("http://www.w3.org/2000/svg", 'image'); newElement.setAttribute("class", "appearingEntity"); @@ -264,7 +154,9 @@ const animateImageAutoGUI = (volume: number, currPosition: string, nextPosition: newElement.setAttribute("href", getImageSource(foregroundImagePath)); g.appendChild(newElement); } - gsap.fromTo(".appearingEntity", {opacity: 0.001}, {duration: 0.5, opacity: 1}); + if (entitiesAppear) { + gsap.fromTo(".appearingEntity", {opacity: 0.001}, {duration: 0.5, opacity: 1}); + } let matches; if (matches = moveObj.move.match(/^([AML])_([a-zA-Z0-9-]+)_([a-zA-Z0-9-]+)_([a-zA-Z0-9-]+)*/)) { if (Object.keys(sounds).includes(matches[4])) { @@ -272,7 +164,7 @@ const animateImageAutoGUI = (volume: number, currPosition: string, nextPosition: } } return 500; - } else if (animationType === "multipleSlides") { + } else if (animationType === "simpleSlides") { for (i = animationWindow[0]; i < animationWindow[1]; i++) { if (currBoard[i] != nextBoard[i]) { diffIdxs.push(i); @@ -280,63 +172,56 @@ const animateImageAutoGUI = (volume: number, currPosition: string, nextPosition: } var slides = []; - var slideIdxs = []; - for (const idx1 of diffIdxs) { - if (currBoard[idx1] != '-') { - for (const idx2 of diffIdxs) { - if (currBoard[idx1] == nextBoard[idx2]) { - slides.push([idx1, idx2]); - slideIdxs.push(idx1); - slideIdxs.push(idx2); + var fadeOutIdxs = diffIdxs.filter((idx) => currBoard[idx] != '-'); + var fadeInIdxs = diffIdxs.filter((idx) => nextBoard[idx] != '-'); + for (const idxFrom of diffIdxs) { + if (currBoard[idxFrom] != '-') { + for (const idxTo of diffIdxs) { + if (currBoard[idxFrom] == nextBoard[idxTo]) { + slides.push([idxFrom, idxTo]); + i = fadeOutIdxs.indexOf(idxFrom); + if (i !== -1) fadeOutIdxs.splice(i, 1); + i = fadeInIdxs.indexOf(idxTo); + if (i !== -1) fadeInIdxs.splice(i, 1); break; } } } } - var interpolateIdxs = []; - for (const idx1 of diffIdxs) { - if (!slideIdxs.includes(idx1)) { - interpolateIdxs.push(idx1); - } + for (i of fadeOutIdxs) { + gsap.fromTo("#entity" + i, {autoAlpha: 1}, {duration: 0.5, autoAlpha: 0.001}); } - - // Interpolate animation - for (const i of interpolateIdxs) { - if (currBoard[i] != '-') { // Entity originally at i shall fade out - gsap.fromTo("#entity" + i, {autoAlpha: 1}, {duration: 0.5, autoAlpha: 0.001}); - } - if (nextBoard[i] != '-') { // Entity that will be at i shall fade in - var appearingChar = nextBoard[i]; - var newElement = document.createElementNS("http://www.w3.org/2000/svg", 'image'); - newElement.setAttribute("class", "appearingEntity"); - newElement.setAttribute("x", (centers[i][0] - 0.5 * entities[appearingChar].scale * widthFactor).toString()); - newElement.setAttribute("y", (centers[i][1] - 0.5 * entities[appearingChar].scale * widthFactor).toString()); - newElement.setAttribute("width", (entities[appearingChar].scale * widthFactor).toString()); - newElement.setAttribute("height", (entities[appearingChar].scale * widthFactor).toString()); - newElement.setAttribute("href", getImageSource(entities[appearingChar].image)); - newElement.setAttribute("opacity", "0.001"); - g.appendChild(newElement); - } + for (i of fadeInIdxs) { + var appearingChar = nextBoard[i]; + var newElement = document.createElementNS("http://www.w3.org/2000/svg", 'image'); + newElement.setAttribute("class", "appearingEntity"); + newElement.setAttribute("x", (centers[i][0] - 0.5 * entities[appearingChar].scale * widthFactor).toString()); + newElement.setAttribute("y", (centers[i][1] - 0.5 * entities[appearingChar].scale * widthFactor).toString()); + newElement.setAttribute("width", (entities[appearingChar].scale * widthFactor).toString()); + newElement.setAttribute("height", (entities[appearingChar].scale * widthFactor).toString()); + newElement.setAttribute("href", getImageSource(entities[appearingChar].image)); + newElement.setAttribute("opacity", "0.001"); + g.appendChild(newElement); } for (const slide of slides) { // Play sliding animations - fromIdx = slide[0]; - toIdx = slide[1]; - const toCoords = centers[toIdx]; - const fromCoords = centers[fromIdx]; - gsap.fromTo("#entity" + fromIdx, {autoAlpha: 1}, {duration: 0.001, autoAlpha: 0.001}); + const idxFrom = slide[0]; + const idxTo = slide[1]; + const toCoords = centers[idxTo]; + const fromCoords = centers[idxFrom]; + gsap.fromTo("#entity" + idxFrom, {autoAlpha: 1}, {duration: 0.001, autoAlpha: 0.001}); - var movingChar = currBoard[fromIdx]; + var movingChar = currBoard[idxFrom]; var newElement = document.createElementNS("http://www.w3.org/2000/svg", 'image'); - newElement.setAttribute("id", "movingEntity" + fromIdx); - newElement.setAttribute("x", (centers[fromIdx][0] - 0.5 * entities[movingChar].scale * widthFactor).toString()); - newElement.setAttribute("y", (centers[fromIdx][1] - 0.5 * entities[movingChar].scale * widthFactor).toString()); + newElement.setAttribute("id", "movingEntity" + idxFrom); + newElement.setAttribute("x", (fromCoords[0] - 0.5 * entities[movingChar].scale * widthFactor).toString()); + newElement.setAttribute("y", (fromCoords[1] - 0.5 * entities[movingChar].scale * widthFactor).toString()); newElement.setAttribute("width", (entities[movingChar].scale * widthFactor).toString()); newElement.setAttribute("height", (entities[movingChar].scale * widthFactor).toString()); newElement.setAttribute("href", getImageSource(entities[movingChar].image)); g.appendChild(newElement); - gsap.to("#movingEntity" + fromIdx, {duration: 0.5, x: toCoords[0] - fromCoords[0], y: toCoords[1] - fromCoords[1]}); + gsap.to("#movingEntity" + idxFrom, {duration: 0.5, x: toCoords[0] - fromCoords[0], y: toCoords[1] - fromCoords[1]}); } if (foregroundImagePath !== "") { // Redraw foreground image in front of any newly introduced entities @@ -346,7 +231,9 @@ const animateImageAutoGUI = (volume: number, currPosition: string, nextPosition: newElement.setAttribute("href", getImageSource(foregroundImagePath)); g.appendChild(newElement); } - gsap.fromTo(".appearingEntity", {opacity: 0.001}, {duration: 0.5, opacity: 1}); + if (fadeInIdxs.length > 0) { + gsap.fromTo(".appearingEntity", {opacity: 0.001}, {duration: 0.5, opacity: 1}); + } let matches; if (matches = moveObj.move.match(/^([AML])_([a-zA-Z0-9-]+)_([a-zA-Z0-9-]+)_([a-zA-Z0-9-]+)*/)) { if (Object.keys(sounds).includes(matches[4])) {