为多个用户同步正在进行的动画 - 游戏开发 [英] Sync ongoing animation for multiple users - Game dev

查看:22
本文介绍了为多个用户同步正在进行的动画 - 游戏开发的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在研究命运之轮,它通过 node.js 和 websockets 同步到每个连接的设备.但是我想切断动画的开始,当用户在滚轮已经旋转的情况下加入时,它只会显示动画的最后几秒而不会改变它的缓动.

I'm currently working on a wheel of fortune, which is synchronized to each connected device via node.js and websockets. However I want to cut off the start of the animation, when a user joins while the wheel is spinning already, so it would only show the last seconds of the animation without changing it's easing.

jquery 动画是由一个简单的步进动画组成的,它围绕着轮子旋转.我已经尝试更改步骤的fx"对象的参数,如 fx.start 或 fx.pos.而 fx.start 只是动画开始时的变量,例如 180 度,而 fx.pos 只是一种输出参数,用于将某些内容更改为动画中的给定时间,例如文本颜色或其他内容.但是 fx.pos 值不能改变,也不能改变动画当前设置的位置.我创建了一个函数来旋转命运之轮两次,然后在给定的角度停止.

The jquery animation is made of a simple step animation, which rotates the wheel around. I already tried to change the parameters of the step's 'fx' object like fx.start or fx.pos. While fx.start only being the variable at which point the animation started, for example 180 degrees and fx.pos is only a sort of output parameter to change something to a given time in the animation, like a text color or something. However the fx.pos value can't be changed nor changes the position the animation is currently set in. I created a function to rotate the wheel of fortune two times and then it stops at a given degree.

我也尝试改变缓动,所以它会是 50% 线性,50% 摆动,但这让动画看起来很垃圾,因为一开始它以恒定速度旋转,突然它旋转得更快而不是更慢.

Also I tried to change the easing, so it would be 50% linear, 50% swing, but this makes the animation look trashy, since at first it's spins at a constant speed and suddenly it spins faster than slower.

function spinRoulette(deg, duration = 10000) {
  deg = Math.round(deg);
  $("img.roulette").animate(
      { now: '+='+(720+deg-getRotation()) }, {
      duration: duration,
      ...
      step: function(now, fx) {
        if(now >= 360)
          now -= 360;
        $(this).css("transform", "rotate("+now+"deg)");
      }
    });
}

如果持续时间少于 10 秒,动画的开始将被切断.所以,如果服务器在大约 5 秒前转动轮子,我的动画的前 5 秒应该被切断.

If the duration would be less then 10 seconds the start of the animation would be cut off. So, if the server spun the wheel about 5 seconds ago the first 5 seconds of my animation should be cut off.

推荐答案

在任何时间点捕捉缓动动画旋转

  • 线性动画 t01,或从 0.N> 到 1.0(如果玩家在 10 秒中的第 6 秒加入,则为 0.6)$({t: t}).animate({t: 1},
  • 轻松!在任何给定的现在"时间点,将当前 0.0-1.0 时间范围(t_now 值)转换为相应的缓动 e_now 值使用自定义缓动函数
  • 将缓动 e_now 结果乘以所需的 end 度数
  • Catch-up an easing animation rotation at any point in time

    • Animate linearly t from 0 to 1, or from 0.N to 1.0 ( 0.6 if a player joined at the 6th second out of 10 max) $({t: t}).animate({t: 1},
    • Ease! At any given "now"-point-in-time, convert the current 0.0-1.0 time range (t_now value) to the respective easing e_now value using a custom easing function
    • Multiply the easing e_now result by the desired end-degrees number
    • 不要使用 "swing" 使用 "linear" 并且让我们控制缓动和时间带有自定义缓动功能(您可以在在线中找到许多缓动片段).假设我们喜欢 easeInOutSine:

      Instead of using "swing" use "linear" and let's take control over the easing and timing with a custom easing function (you can find many easing snippets online). Say we like the easeInOutSine:

      const easeInOutSine = t => -(Math.cos(Math.PI * t) - 1) / 2;
      

      示例

      例如,4 个人,一个人在旋转轮子,其他人在 2、4.5 和 8.7 秒开始旋转后加入节目>:

      const easeInOutSine = t => -(Math.cos(Math.PI * t) - 1) / 2;
      
      function spinRoulette(sel, deg, duration = 10000) {
        const $el = $(sel);
        const maxDuration = 10000;
        const deg_end = 720 + Math.round(deg);  // 2 revolutions + server-generated degrees
        const time = maxDuration - duration;    // Start time in ms
        const t = time / maxDuration;           // Start time to 0.0-1.0 range 
      
        $({t: t}).animate({t: 1}, {             // Custom jQuery anim. from 0.N to 1.0
          duration: duration,
          easing: "linear",                     // We need a linear 0.0 to 1.0
          step: function(t_now) {
            const e_now = easeInOutSine(t_now); // Current easing
            const deg_now = e_now * deg_end;    // Current degrees
            $el.css({transform: `rotate(${ deg_now }deg)`});
          }
        });
      }
      
      // Person 1 spins!
      spinRoulette("#r1", 45);
      // Person 2 joins the room after 2s
      setTimeout(() => spinRoulette('#r2', 45, 10000 - 2000), 2000);
      // Person 3 joins the room after 4.5s
      setTimeout(() => spinRoulette('#r3', 45, 10000 - 4500), 4500);
      // Person 4 joins the room after 8.7s
      setTimeout(() => spinRoulette('#r4', 45, 10000 - 8700), 8700);

      img {height: 120px; display: inline-block;}

      <img id="r1" src="https://i.stack.imgur.com/bScK3.png">
      <img id="r2" src="https://i.stack.imgur.com/bScK3.png">
      <img id="r3" src="https://i.stack.imgur.com/bScK3.png">
      <img id="r4" src="https://i.stack.imgur.com/bScK3.png">
      
      <script src="//code.jquery.com/jquery-3.4.1.min.js"></script>

      在上面的例子中,最后,你可以注意到(除了一些奇怪的视错觉)轮子在任何时间点以正确的旋转状态追赶,速度,并且全部在同时使用相同的缓动,精确预定义的 deg_end 度.

      In the example above, finally, you can notice (besides some weird optical illusion) that the wheels catch-up at any point in time with the correct rotation state, velocity, and all finish at the same time with the same easing, at the exact predefined deg_end degree.

      这篇关于为多个用户同步正在进行的动画 - 游戏开发的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆