Feast 2.0!
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

148 lines
4.9 KiB

  1. <template>
  2. <div class="vore-container">
  3. <div class="container-name">{{container.name.capital}}</div>
  4. <div class="container-contents">
  5. <div class="container-prey container-prey-live" v-for="(prey, index) in container.contents" :key="'live-prey-' + index">{{prey.name}}</div>
  6. <div class="container-prey container-prey-dead" v-for="(prey, index) in container.digested" :key="'dead-prey-' + index">{{prey.name}}</div>
  7. </div>
  8. <canvas class="container-waves"></canvas>
  9. </div>
  10. </template>
  11. <script lang="ts">
  12. import { Component, Prop, Vue, Watch, Emit } from 'vue-property-decorator'
  13. import { Creature } from '@/game/creature'
  14. import { POV } from '@/game/language'
  15. import { Stats, Stat } from '@/game/combat'
  16. import { Container, VoreContainer, Vore } from '@/game/vore'
  17. function wiggle (contents: HTMLElement) {
  18. setTimeout(() => wiggle(contents), 3000)
  19. const width = contents.clientWidth
  20. const height = contents.clientHeight
  21. contents.querySelectorAll(".container-prey").forEach(elem => {
  22. const prey = elem as HTMLElement
  23. const preyWidth = prey.clientWidth
  24. const preyHeight = prey.clientHeight
  25. setTimeout(() => {
  26. (prey as HTMLElement).style.left = (Math.floor(Math.random() * (width - preyWidth)) + "px");
  27. (prey as HTMLElement).style.top = (Math.floor(Math.random() * (height - preyHeight)) + "px")
  28. }, Math.random() * 3000)
  29. })
  30. }
  31. // yoinked from https://jsfiddle.net/yckart/0adfw47y/
  32. function draw (delta: number, dt: number, total: number, parent: HTMLElement, canvas: HTMLCanvasElement, container: VoreContainer, smoothedFraction: number, smoothedLiveliness: number) {
  33. const ctx = canvas.getContext('2d') as CanvasRenderingContext2D
  34. canvas.width = parent.clientWidth
  35. canvas.height = parent.clientHeight
  36. ctx.fillStyle = container.fluidColor
  37. const fraction = container.fullness / container.capacity
  38. const livingFraction = container.contents.reduce((total: number, prey: Vore) => total + prey.voreStats.Bulk, 0) / container.capacity
  39. const deadFraction = container.digested.reduce((total: number, prey: Vore) => total + prey.voreStats.Bulk, 0) / container.capacity
  40. const liveliness = livingFraction + deadFraction * 0.5
  41. smoothedFraction = smoothedFraction * 0.995 + fraction * 0.005
  42. smoothedLiveliness = smoothedLiveliness * 0.995 + liveliness * 0.005
  43. total += dt * smoothedLiveliness
  44. requestAnimationFrame((newDelta: number) => draw(newDelta, newDelta - delta, total, parent, canvas, container, smoothedFraction, smoothedLiveliness))
  45. const randomLeft = Math.abs(Math.pow(Math.sin(total / 1000), 2)) * smoothedFraction * 100 + (1 - smoothedFraction) * canvas.height
  46. const randomRight = Math.abs(Math.pow(Math.sin((total / 1000) + 10), 2)) * smoothedFraction * 100 + (1 - smoothedFraction) * canvas.height
  47. const randomLeftConstraint = Math.abs(Math.pow(Math.sin((total / 1000) + 2), 2)) * smoothedFraction * 100 + (1 - smoothedFraction) * canvas.height
  48. const randomRightConstraint = Math.abs(Math.pow(Math.sin((total / 1000) + 1), 2)) * smoothedFraction * 100 + (1 - smoothedFraction) * canvas.height
  49. ctx.beginPath()
  50. ctx.moveTo(0, randomLeft)
  51. ctx.bezierCurveTo(canvas.width / 3, randomLeftConstraint, canvas.width / 3 * 2, randomRightConstraint, canvas.width, randomRight)
  52. ctx.lineTo(canvas.width, canvas.height)
  53. ctx.lineTo(0, canvas.height)
  54. ctx.lineTo(0, randomLeft)
  55. ctx.closePath()
  56. ctx.fill()
  57. }
  58. @Component
  59. export default class ContainerView extends Vue {
  60. @Prop({ required: true })
  61. container!: Container
  62. mounted () {
  63. if ((this.container as VoreContainer).fluidColor !== undefined) {
  64. const canvas = this.$el.querySelector('.container-waves') as HTMLCanvasElement
  65. canvas.width = (this.$el as HTMLElement).clientWidth
  66. canvas.height = (this.$el as HTMLElement).clientHeight
  67. canvas.width = canvas.width + 0
  68. requestAnimationFrame((delta: number) => draw(delta, delta, Math.random() * 1000, this.$el as HTMLElement, canvas, (this.container as VoreContainer), 0, 0))
  69. }
  70. wiggle(this.$el.querySelector(".container-contents") as HTMLElement)
  71. }
  72. }
  73. </script>
  74. <!-- Add "scoped" attribute to limit CSS to this component only -->
  75. <style scoped>
  76. .vore-container {
  77. flex: 1 1;
  78. position: relative;
  79. min-height: 100pt;
  80. display: flex;
  81. flex-direction: column;
  82. }
  83. .container-name {
  84. margin: 8pt;
  85. font-size: 150%;
  86. }
  87. .container-fullness {
  88. margin: 6pt;
  89. font-size: 125%;
  90. }
  91. .container-waves {
  92. position: absolute;
  93. top: 0;
  94. left: 0;
  95. }
  96. .container-contents {
  97. position: relative;
  98. flex: 1;
  99. }
  100. .container-prey {
  101. animation: prey-devour-keyframes 1s;
  102. position: absolute;
  103. transition: 3s all;
  104. top: 25px;
  105. left: 25px;
  106. overflow: hidden;
  107. }
  108. @keyframes prey-devour-keyframes {
  109. from {
  110. opacity: 0;
  111. } to {
  112. opacity: 1;
  113. }
  114. }
  115. .container-prey-live {
  116. color: #eeeeee;
  117. }
  118. .container-prey-dead {
  119. color: #ff8888;
  120. }
  121. </style>