123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347 |
- import { Camera } from "../../libraries/Camera.js";
- import { DomButton } from "../../libraries/components/DomButton.js";
- import { TextPop } from "../../libraries/components/TextPop.js";
- import { Point } from "../../libraries/spatial/Point.js";
- import { Tween, TweenManager, Easing } from "../../libraries/Tween.js";
- import { Theme } from "../../libraries/components/Theme.js"
- import { Picture } from "../../libraries/CanvasArtist.js";
- import { Save } from "../../libraries/Save.js";
- import ShopCard from "../../libraries/ShopCard.js";
- import "../../libraries/RoundRectPolyfill.js"
- export class ShopState {
- constructor(view) {
- this.scaledCanvas = view.scaledCanvas
- this.stateMachine = view.stateMachine
- this.camera = new Camera()
- this.camera.scale = new Point(1, 1)
- this.tweenManager = new TweenManager()
- this.textPops = []
- this.closeShopButton = new DomButton(50, 50, view.element, "close shop", "close-shop")
- this.scrollStart = new Point(0, 0)
- this.scrollEnd = new Point(0, 0)
- this.scrollOffset = new Point(0, 128)
- this.save = new Save()
- this.shopCards = []
- for (let i = 0; i < Math.floor(16 * Math.random()) + 5; i++) {
- this.shopCards.push(new ShopCard())
- }
- this.cardHeight = 100
- }
- init(scaledCanvas) {
- this.canvasBounds = scaledCanvas.bounds
- }
- draw(ctx, scaledCanvas) {
- let fontScale = this.canvasBounds.width / 500
- let headerFontSize = Math.min(Math.floor(48 * fontScale), 48)
- ctx.save()
- this.cardHeight = Math.max(this.canvasBounds.height / 6, 100)
- ctx.translate(0, this.scrollOffset.y + (this.scrollEnd.y - this.scrollStart.y))
- for (let i = 0; i < this.shopCards.length; i++) {
- let card = this.shopCards[i]
- ctx.save()
- ctx.translate(0, this.getListRowOffset(this.cardHeight, i))
- card.draw(ctx, { cardHeight: this.cardHeight, screenWidth: this.canvasBounds.width, fontScale })
- ctx.restore()
- }
- ctx.restore()
- ctx.fillStyle = "gray"
- ctx.beginPath()
- ctx.rect(0, 0, this.canvasBounds.width, 128)
- ctx.fill()
- ctx.fillStyle = Theme.Colors.ivory
- ctx.font = `${headerFontSize}px ${Theme.Fonts.Header}`
- ctx.textAlign = "center"
- ctx.fillText("Bone Market", this.canvasBounds.width / 2, headerFontSize + 24)
- ctx.save()
- ctx.translate(16, 100)
- let inventorySpacing = 0
- if (this.getNumberOfGatheredSkulls() > 8) {
- ctx.save()
- ctx.scale(0.4, 0.4)
- ctx.translate(Theme.Game.TileSize.width / 2, Theme.Game.TileSize.height / 2)
- Picture.Skull(ctx, { width: Theme.Game.TileSize.width, height: Theme.Game.TileSize.height })
- ctx.fillStyle = Theme.Colors.ivory
- ctx.fillText(`x${this.getNumberOfGatheredSkulls()}`, 2 * Theme.Game.TileSize.width - (Theme.Game.TileSize.width / 2), Theme.Game.TileSize.height / 2)
- ctx.restore()
- inventorySpacing += 3
- } else {
- for (let i = 0; i < this.getNumberOfGatheredSkulls(); i++) {
- ctx.save()
- ctx.scale(0.4, 0.4)
- ctx.translate((i * (Theme.Game.TileSize.width + Theme.Game.TileSize.spacing) + (Theme.Game.TileSize.width / 2)), (Theme.Game.TileSize.height / 2))
- Picture.Skull(ctx, { width: Theme.Game.TileSize.width, height: Theme.Game.TileSize.height })
- ctx.restore()
- inventorySpacing++
- }
- }
- if (this.getNumberOfGatheredBones() > 8) {
- ctx.save()
- ctx.scale(0.4, 0.4)
- ctx.translate(((inventorySpacing) * (Theme.Game.TileSize.width + Theme.Game.TileSize.spacing)), 0)
- Picture.Bone(ctx, { width: Theme.Game.TileSize.width, height: Theme.Game.TileSize.height })
- ctx.fillStyle = Theme.Colors.ivory
- ctx.fillText(`x${this.getNumberOfGatheredBones()}`, 2 * Theme.Game.TileSize.width, Theme.Game.TileSize.height)
- ctx.restore()
- } else {
- for (let i = 0; i < this.getNumberOfGatheredBones(); i++) {
- ctx.save()
- ctx.scale(0.4, 0.4)
- ctx.translate(((i + inventorySpacing) * (Theme.Game.TileSize.width + Theme.Game.TileSize.spacing)), 0)
- Picture.Bone(ctx, { width: Theme.Game.TileSize.width, height: Theme.Game.TileSize.height })
- ctx.restore()
- }
- }
- ctx.fillStyle = Theme.Colors.darkgreen
- ctx.textAlign = "right"
- ctx.font = `${Math.min(Math.floor(24 * fontScale), 48)}px ${Theme.Fonts.Header}`
- ctx.fillText(`$${this.getDollars()}`, this.canvasBounds.width - 48,0)
- ctx.restore()
- this.camera.draw(ctx, scaledCanvas, () => {
- ctx.font = `${Math.min(Math.floor(48 * fontScale), 48)}px ${Theme.Fonts.Header}`
- ctx.textAlign = "center"
- let metrics = ctx.measureText(this.completeText)
- ctx.fillStyle = Theme.Colors.umber
- ctx.beginPath()
- ctx.roundRect(this.completePosition.x - metrics.width / 2, this.completePosition.y - Math.min(Math.floor(48 * fontScale), 48), metrics.width, Math.min(Math.floor(64 * fontScale), 64), 8)
- ctx.fill()
- ctx.fillStyle = Theme.Colors.ivory
- ctx.fillText(this.completeText, this.completePosition.x, this.completePosition.y)
- this.textPops.forEach(textpop => {
- textpop.draw(ctx, scaledCanvas)
- })
- })
- this.closeShopButton.setPosition(this.canvasBounds.width * (6 / 8), this.canvasBounds.height * (7 / 8))
- this.closeShopButton.draw(ctx, scaledCanvas)
- }
- getListRowOffset(height, i) {
- return 24 + (i * height + i * 8)
- }
- getNumberOfGatheredBones() {
- return this.save.getKey("bones")
- }
- getNumberOfGatheredSkulls() {
- return this.save.getKey("skulls")
- }
- getDollars() {
- let money = this.save.getKey("money")
- if(money == null) {
- this.save.setKey("money", 0)
- money = 0
- }
- return money
- }
- update(delta) {
- this.camera.update(delta)
- this.closeShopButton.update(delta)
- this.tweenManager.update()
- for (let i = 0; i < this.shopCards.length; i++) {
- let card = this.shopCards[i]
- card.update(delta, this.canvasBounds)
- }
- if (this.shopCards.length == 0 ||
- this.shopCards.filter((card) => card.item == "bones" && card.amount <= this.getNumberOfGatheredBones()).length == 0 &&
- this.shopCards.filter((card) => card.item == "skulls" && card.amount <= this.getNumberOfGatheredSkulls()).length == 0 ) {
- if (this.isComplete) {
- return
- }
- this.isComplete = true
- this.completeText = "Sold Out!"
- this.tweenManager.add(new Tween(this.completePosition, { y: 0 }, 2000, Easing.Elastic.EaseOut, () => {
- this.stateMachine.transitionTo("upgrade")
- }))
- }
- }
- enter() {
- this.registeredEvents = {}
- this.registeredEvents["resize"] = this.onResize.bind(this)
- this.registeredEvents["keydown"] = this.onKeyDown.bind(this)
- this.registeredEvents["keyup"] = this.onKeyUp.bind(this)
- this.registeredEvents["touchstart"] = this.onTouchStart.bind(this)
- this.registeredEvents["touchmove"] = this.onTouchMove.bind(this)
- this.registeredEvents["touchend"] = this.onTouchEnd.bind(this)
- this.registeredEvents["mousedown"] = this.onMouseDown.bind(this)
- this.registeredEvents["mousemove"] = this.onMouseMove.bind(this)
- this.registeredEvents["mouseup"] = this.onMouseUp.bind(this)
- this.registeredEvents["wheel"] = this.onMouseWheel.bind(this)
- for (let index in this.registeredEvents) {
- window.addEventListener(index, this.registeredEvents[index])
- }
- this.closeShopButton.attach()
- this.closeShopButton.onClick(() => {
- this.stateMachine.transitionTo("upgrade")
- })
- this.scrollStart = new Point(0, 0)
- this.scrollEnd = new Point(0, 0)
- this.scrollOffset = new Point(0, 128)
- this.save = new Save()
- this.shopCards = []
- for (let i = 0; i < Math.floor(16 * Math.random()) + 5; i++) {
- this.shopCards.push(new ShopCard())
- }
- this.completePosition = new Point(0, -1000)
- this.completeText = "Sold Out!"
- this.isComplete = false
- }
- leave() {
- for (let index in this.registeredEvents) {
- window.removeEventListener(index, this.registeredEvents[index])
- }
- this.closeShopButton.remove()
- this.textPops = []
- }
- onResize() {
- }
- onKeyDown(event) {
- }
- onKeyUp(event) {
- switch (event.code) {
- case "Enter":
- this.stateMachine.transitionTo("upgrade")
- break
- }
- }
- onTouchStart(event) {
- this.scrollStart = new Point(event.touches[0].clientX, event.touches[0].clientY)
- this.scrollEnd = new Point(event.touches[0].clientX, event.touches[0].clientY)
- this.isScrolling = true
- }
- onTouchMove(event) {
- if (!this.isScrolling) { return }
- this.scrollEnd.x = event.touches[0].clientX
- this.scrollEnd.y = event.touches[0].clientY
- }
- onTouchEnd(event) {
- this.isScrolling = false
- this.scrollOffset.x += this.scrollEnd.x - this.scrollStart.x
- this.scrollOffset.y += this.scrollEnd.y - this.scrollStart.y
- this.scrollOffset.y = this.getScrollLimits()
- this.scrollStart.x = 0
- this.scrollStart.y = 0
- this.scrollEnd.x = 0
- this.scrollEnd.y = 0
- }
- getScrollLimits() {
- return Math.min(Math.max(this.scrollOffset.y, (-(this.cardHeight * (this.shopCards.length + 1)) + this.canvasBounds.height) - 128), 128)
- }
- onMouseDown(event) {
- this.scrollStart = new Point(event.clientX, event.clientY)
- this.scrollEnd = new Point(event.clientX, event.clientY)
- this.isScrolling = true
- }
- onMouseMove(event) {
- document.body.style.cursor = "default"
- for (let i = 0; i < this.shopCards.length; i++) {
- let card = this.shopCards[i]
- let offset = this.scrollOffset.y + this.getListRowOffset(this.cardHeight, i)
- card.mouseMove(event, offset)
- }
- if (!this.isScrolling) { return }
- this.scrollEnd.x = event.clientX
- this.scrollEnd.y = event.clientY
- }
- onMouseUp(event) {
- this.isScrolling = false
- this.scrollOffset.x += this.scrollEnd.x - this.scrollStart.x
- this.scrollOffset.y += this.scrollEnd.y - this.scrollStart.y
- this.scrollOffset.y = this.getScrollLimits()
- this.scrollStart.x = 0
- this.scrollStart.y = 0
- this.scrollEnd.x = 0
- this.scrollEnd.y = 0
- let cardsToRemove = []
- for (let i = 0; i < this.shopCards.length; i++) {
- let card = this.shopCards[i]
- card.onClick((item, rate, amount) => {
- switch (item) {
- case "bones":
- if (this.getNumberOfGatheredBones() < amount) {
- let pop = new TextPop(this.tweenManager, `No Sale`, new Point(0, 0), 0)
- this.textPops.push(pop)
- return
- }
- this.save.incrementKey("bones", -amount)
- break;
- case "skulls":
- if (this.getNumberOfGatheredSkulls() < amount) {
- let pop = new TextPop(this.tweenManager, `No Sale`, new Point(0, 0), 0)
- this.textPops.push(pop)
- return
- }
- this.save.incrementKey("skulls", -amount)
- break;
- }
- this.save.incrementKey("money", rate * amount)
- let pop = new TextPop(this.tweenManager, `$${rate * amount}`, new Point(0, 0), 0)
- this.textPops.push(pop)
- cardsToRemove.push(card)
- if(this.save.getKey("story-stage") == 0) {
- this.save.setKey("story-stage", 1)
- }
- })
- }
- this.shopCards = this.shopCards.filter((card) => !cardsToRemove.includes(card))
- }
- onMouseWheel(event) {
- this.scrollOffset.y += event.wheelDeltaY
- this.scrollOffset.y = this.getScrollLimits()
- }
- }
|