Skip to content

Commit

Permalink
Add new animation for card reward
Browse files Browse the repository at this point in the history
  • Loading branch information
oskarrough committed Jan 17, 2024
1 parent 0940484 commit e8eec12
Show file tree
Hide file tree
Showing 7 changed files with 156 additions and 28 deletions.
29 changes: 29 additions & 0 deletions control.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<!DOCTYPE html>
<html class="no-bg" lang="en">
<head>
<meta charset="utf-8" />
<meta name="description" content="A video card game for the web" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, viewport-fit=cover" />
<title>Slay the Web</title>
<meta name="mobile-web-app-capable" content="yes">
<meta name="theme-color" content="#116f54" />
<meta name="msapplication-TileColor" content="#116f54">
<link rel="icon" type="image/png" href="/images/favicons/favicon-512.png" sizes="512x512" />
<link rel="shortcut icon" href="/images/favicons/favicon.ico">
<link rel="apple-touch-icon" href="/images/favicon-512.png" />
</head>
<body>

<h1>Test</h1>

<script async src="/src/ui/pages/main.js" type="module"></script>

<noscript>
<p>
You need JavaScript enabled to play Slay The Web.
See <a href="https://github.com/oskarrough/slaytheweb/">github.com/oskarrough/slaytheweb/</a>.
</p>
</noscript>

</body>
</html>
30 changes: 23 additions & 7 deletions src/ui/animations.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,26 +74,42 @@ gsap.registerEffect({
const tl = gsap.timeline()
return tl
.to(targets, {
duration: 0.6,
y: '-=100',
// x: 0,
duration: 1.5,
y: '-=80',
rotation: 50,
scale: 0.8,
ease: 'power3.out',
onComplete: config.onComplete,
})
.to(targets, {
delay: -0.3,
delay: -1.3,
duration: 0.8,
scale: 0.5,
rotation: 90,
x: window.innerWidth,
rotation: 80,
x: window.innerWidth * 1.2,
y: window.innerHeight,
ease: 'power3.inOut',
onComplete: config.onComplete,
})
},
})

// This throws the card out towards the discard pile in the bottom right corner.
gsap.registerEffect({
name: 'addCardToDeck',
effect: (targets, config) => {
const tl = gsap.timeline()
return tl.to(targets, {
duration: 1,
x: '+=80',
y: '-=80',
rotation: 50,
scale: 0.4,
ease: 'power3.out',
onComplete: config.onComplete,
})
},
})

export default gsap

// So we can use it in the browser.
Expand Down
15 changes: 10 additions & 5 deletions src/ui/components/card-chooser.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,23 @@ import gsap from '../animations.js'

export default class CardChooser extends Component {
componentDidMount() {
if (!this.props.animate) return
// Animate all the cards in with a nice animation and staggered delay with gsap
const cards = this.base.querySelectorAll('.CardBox')
gsap.effects.dealCards(cards)
if (this.props.animate) {
// Animate all the cards in with a nice animation and staggered delay with gsap
const cards = this.base.querySelectorAll('.CardBox')
gsap.effects.dealCards(cards)
}
}

clickedCard(card) {
const cardEl = this.base.querySelector(`[data-id="${card.id}"]`)
gsap.effects.playCard(cardEl).then(() => {
setTimeout(() => {
this.props.didSelectCard(card)
}, 300)
gsap.effects.addCardToDeck(cardEl).then(() => {
// this.props.didSelectCard(card)
})
}

render(props) {
return html`
<article class="RewardsBox">
Expand Down
39 changes: 25 additions & 14 deletions src/ui/components/game-screen.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,12 +59,13 @@ export default class App extends Component {
this.game = game

if (debugMode) {
// this.game.enqueue({type: 'removeHealth', amount: 10, target: 'player'})
// this.game.enqueue({type: 'addEnergyToPlayer', amount: 10})
const roomIndex = game.state.dungeon.graph[1].findIndex((r) => r.room)
this.game.enqueue({type: 'move', move: {y: 1, x: roomIndex}})
this.game.enqueue({type: 'iddqd'})
this.game.dequeue()
}

if (urlParams.has('iddqd')) {
this.game.enqueue({type: 'iddqd'})
this.game.dequeue()
}

Expand All @@ -87,29 +88,28 @@ export default class App extends Component {
// Enable a "console" in the browser.
// @ts-ignore
window.stw = {
uiComponent: this,
game: this.game,
update: this.update.bind(this),
// Usage: stw.run('drawCards', {amount: 2})
run: (actionName, props) => {
const action = {type: actionName, ...props}
this.game.enqueue(action)
this.update()
},
saveGame: (state) => saveToUrl(state || this.state),
createCard,
dealCards: this.dealCards.bind(this),
drawCards: (amount) => {
this.game.enqueue({type: 'drawCards', amount})
this.update()
this.dealCards()
// enableDragDrop(this.base, this.playCard)
},
iddqd() {
// console.log(this.game.state)
this.game.enqueue({type: 'iddqd'})
this.update(() => {
// console.log(this.game.state)
})
this.update()
},
help() {
console.log(`Welcome to the Slay The Web Console. Some examples:
stw.game.enqueue({type: 'drawCards', amount: 2})
stw.update()
stw.run('removeHealth', {amount: 2, target: 'player'})
stw.run('drawCards', {amount: 2})
stw.dealCards()`)
},
}
Expand Down Expand Up @@ -144,14 +144,25 @@ stw.dealCards()`)

// Create a clone on top of the card to animate.
const clone = cardElement.cloneNode(true)
clone.style.width = cardElement.offsetWidth + 'px'
clone.style.height = cardElement.offsetHeight + 'px'
clone.style.position = 'absolute'
clone.style.top = cardElement.offsetTop + 'px'
clone.style.left = cardElement.offsetLeft + 'px'
this.base.appendChild(clone)
if (supportsFlip) Flip.fit(clone, cardElement, {absolute: true})

// if (supportsFlip) Flip.fit(clone, cardElement, {absolute: true, duration: 1})

// debugger
// return


// Update state and re-enable dragdrop
this.update(() => {
enableDragDrop(this.base, this.playCard)
sounds.playCard({card, target})


// Animate cloned card away
gsap.effects.playCard(clone).then(() => {
clone.parentNode.removeChild(clone)
Expand Down
4 changes: 2 additions & 2 deletions src/ui/components/victory-room.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export default function VictoryRoom(props) {
const state = props.gameState
return html`
<div class="Container Container--center">
<h1 center>Victory. Onwards!</h1>
<h1 center>Victory!</h1>
<h2 center>${pick(victoryRoomIntroTexts)}</h2>
${!state.didPickCard &&
html`
Expand All @@ -41,7 +41,7 @@ const victoryRoomIntroTexts = [
"Ah, victory! Don't linger too long; those cards won't pick themselves.",
'Where the cards are your oyster',
'Choose a card, any card!',
"Rewards await. But remember, a deck can't thrive on clutter.",
"Rewards await. But remember, a deck can't thrive on clutter. Unless you have corruption. Then it can.",
"Ah, the Victory Room, where today's choices are tomorrow's victories or, you know, defeats.",
"New cards up for grabs. Don't underestimate the power of fresh cardboard.",
]
2 changes: 2 additions & 0 deletions src/ui/pages/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// import '../styles/index.css'
import './slay-the-web.js'
65 changes: 65 additions & 0 deletions src/ui/pages/slay-the-web.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import {html, render, Component} from '../lib.js'
import SplashScreen from '../components/splash-screen.js'
import GameScreen from '../components/game-screen.js'
import WinScreen from '../components/win-screen.js'
import {init as initSounds} from '../sounds.js'

/** @enum {string} */
const GameModes = {
splash: 'splash',
gameplay: 'gameplay',
win: 'win',
}

/**
* Our root component for the game.
* Controls what to render.
*/
export default class SlayTheWeb extends Component {
constructor() {
super()
const urlParams = new URLSearchParams(window.location.search)
const initialGameMode = urlParams.has('debug') ? GameModes.gameplay : GameModes.splash
this.state = {gameMode: initialGameMode}

this.handleWin = this.handleWin.bind(this)
this.handleNewGame = this.handleNewGame.bind(this)
this.handleLoose = this.handleLoose.bind(this)
}

async handleNewGame() {
await initSounds()
this.setState({gameMode: GameModes.gameplay})
// Clear any previous saved game.
window.history.pushState('', document.title, window.location.pathname)
}

handleContinue() {
this.setState({gameMode: GameModes.gameplay})
}

handleWin() {
this.setState({gameMode: GameModes.win})
}

handleLoose() {
this.setState({gameMode: GameModes.splash})
}

render(props, {gameMode}) {
if (gameMode === GameModes.splash)
return html`<${SplashScreen} onNewGame=${this.handleNewGame} onContinue=${this.handleContinue} />`
if (gameMode === GameModes.gameplay)
return html` <${GameScreen} onWin=${this.handleWin} onLoose=${this.handleLoose} /> `
if (gameMode === GameModes.win) return html` <${WinScreen} onNewGame=${this.handleNewGame} /> `
}
}

customElements.define(
'slay-the-web',
class SlayTheWebElement extends HTMLElement {
connectedCallback() {
render(html` <${SlayTheWeb} /> `, this)
}
},
)

0 comments on commit e8eec12

Please sign in to comment.