Feast 2.0!
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.
 
 
 
 
 

164 строки
5.2 KiB

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