VUE+WebPack游戏设计:实现两张扑克牌的逐对厮杀特效

31 篇文章 0 订阅
9 篇文章 1 订阅

本节,我们开始进行两张扑克牌对战时的情景设计,当用户从底部选中一张扑克牌后,系统需要产生一张对手扑克牌,这样两张牌才能相互较量,接下来我们先实现如何引入敌对扑克牌。

在gamescenecomponent.vue中,我们先添加敌对扑克牌的定义,在标签template中,添加如下代码:

<div class="card opponent" :class="{'out' : cardOpponentOut, 'in': !cardOpponentOut}"> 
       <div class="front face"></div>
       <div class="back face">back</div>
</div>

接着在script标签中添加相关变量的定义,以及控制敌对扑克牌的逻辑代码,首先添加几个变量定义:

<script>
  import Constant from './constant'
  export default {
    data () {
      return {
      ....
      selectedCardPower: 0,
      opponentCardPower: 100,
      cardOpponentOut: true
      }
      ....
      methods: {
      ....
      cardAClick () {
        this.cardASelected = true
        this.cardAFlipped = false
        this.cardBOut = true
        this.cardCOut = true

        this.beginBattleAnimation()
      },
      cardBClick () {
        this.cardBSelected = true
        this.cardBFlipped = false
        this.cardAOut = true
        this.cardCOut = true

        this.beginBattleAnimation()
      },
      cardCClick () {
        this.cardCSelected = true
        this.cardCFlipped = false
        this.cardBOut = true
        this.cardAOut = true

        this.beginBattleAnimation()
      },
      randomizerPower () {
        return Math.round(Math.random() * 60) + 40
      },
      beginBattleAnimation () {
        this.cardOpponentOut = false
      }
   }
}
  <script>

selectedCardPower用来表示选中扑克牌的能量值,opponentCardPower用来表示敌对扑克牌的能量值,cardOpponentOut用来控制敌对扑克牌是否在页面上出现,它的值设置成false的话,它就会出现在页面上。

beginBattleAnimation被调用时,他把变量cardOpponentOut设置成false,这样敌对扑克牌就会出现在页面上,当用户选择任意一张扑克牌时,该函数就会调用,也就是说用户选中一张扑克牌后,程序立马将敌对扑克牌显示在页面上,与用户选择的扑克牌并排放在一起,上面代码完成后加载页面,进入游戏场景,点击选择一张扑克牌后,情形如下:
这里写图片描述

右边是用户选中的扑克牌,左边是用户选择后,程序将敌对扑克牌显示到页面上,敌对扑克牌的显示具有动态效果,具体请参看视频。

实现对战特效
当两张对手牌出现在页面中间后,扑克牌间的厮杀就开始了,玩家选择的牌先发送一个冲击波打击对手牌,接着对手牌也发生一个冲击波打击玩家选择的牌。我们先看看这两个冲击波是如何实现的。

首先在html代码部分增加冲击波的定义:

<div class="card opponent" :class="{'out' : cardOpponentOut, 'in': !cardOpponentOut, 'shake' :opponentCardShake}"> 
       <div class="front face"></div>
       <div class="back face">back</div>
</div>

<div class="blaze toward-left" :class="{'attack' : blazeAttackLeft}"></div>
<div class="blaze toward-right"></div>

冲击波本质上是两个静态图片在页面上实现的动态效果:
这里写图片描述

代码中blazeAttackLeft是定义在组件中的变量,如果这个值是true,那么上面的div控件就会具备attack属性,一旦具备这个属性,div控件就可以实现css定义的动画效果。

利用最新的CSS3标准,我们可以实现很多动画特效,在style标签中,我们先添加以下代码:

<style scoped>
@keyframes shake {
    0%   {transform: translate3d(0, 0, 0);}
    20%  {transform: translate3d(-5%, 0, 0);}
    40%  {transform: translate3d(5%, 0, 0);}
    60%  {transform: translate3d(-5%, 0, 0);}
    80%  {transform: translate3d(5%, 0, 0);}
    100% {transofrm: translate3d(0, 0, 0);}
  }
.card.shake{animation: shake 300ms ease-out}
</style>

上面的CSS代码定义了一系列的变换,一系列的变换连接在一起就变成了动画,translate3d(x,y,z)定义了元素沿着x,y,z三个坐标轴上进行变换,在上面的一系列变换中,y,z两个坐标轴全是0,也就是说元素只会沿着x轴变换,translate3d(-5%,0,0)表示元素先向左挪动相应位置,translate3d(5%,0,0)表示元素向右移动相应位置,一系列沿着x轴方向上的作用移动变换会使得css所作用的元素产生一种左右颤抖的效果,具体请参看视频
当我们把变量opponentCardShake设置成true时,shake属性就会添加到’card opponent’这个div上,于是上面定义的shake动画就会作用到敌对扑克牌上。

接着继续添加冲击波的CSS定义,还是在style标签里,添加一下代码:

.blaze {
    position: absolute;
    bottom: 300px;
    width: 50px;
    height: 50px;
    opacity: 0;
    animation-timing-function: ease-out;
    animation-duration: 1000ms;
  }

  .blaze.toward-left {background-image: url(../../static/images/blaze-left.png);}
  .blaze.toward-right {background-image: url(../../static/images/blaze-right.png);}

  @keyframes blaze-toward-left {
  0%, 20% {opacity: 1; transform: translate3d(300px, 0, 0)}
  80% {transform: translate3d(100px, 0, 0);}
  100% {opacity: 0; transform: translate3d(100px, 0, 0);}
  }

  .blaze.toward-left.attack {animation-name: blaze-toward-left;}
  .blaze.toward-right.attack {animation-name: blaze-toward-right;}

我们看看blaze-toward-left所定义的变化,它首先使得图片blaze-left.png出现在x坐标轴300px的地方,接着向左移动一直到100px的地方,然后他的透明度变成0,也就是消失看不到了,这个效果就类似于页面右边的扑克牌放出了一个指向左边的冲击波,冲击波从右向左移动,抵达左边扑克牌的位置后消失,此时左边扑克牌触发shake变化,于是扑克牌产生出一种被击打后左右颤抖的效果。

接下来我们需要使用js实现整个动画流程,这是整个项目的难点所在。我们要实现的效果是,用户从底部选择一张扑克牌后,选中的牌显示在界面的右边,然后敌对扑克牌出现在坐标,一旦敌对扑克牌出现后,右边扑克牌发出一个blaze-left.png表示的冲击波,冲击波打中左边扑克牌后,扑克牌产生一个左右摇摆的颤抖效果。

我们注意到,一个html元素能够产生两种特效,一种叫transform,一种叫animation,后者是由一系列前者组成的。由于我们现在需要做的是一种特效完成后,由程序接着触发另一种特效,这就需要我们的程序知道特效在哪个时刻完成,好在浏览器给我们提供了相应机制,当一个元素完成transform或animation之后,浏览器就可以通知我们的js程序。

当一个元素完成transform变换时,它会发出一个消息叫webkitTransitionEnd,当元素完成animation变换时,它会发出一个消息叫webkitAnimationEnd,我们只要监听这两个消息,然后才行相应动作就好。当前能产生相应变换的只有两个元素,一个是属性为’card opponent’的div,另一个是属性为’blaze toward-left’的div。所以我们的代码要监听这两个元素所发出的相应消息。

我们先在组件中添加相关变量定义:

<script>
  import Constant from './constant'
  export default {
    data () {
      return {
      ....
        opponentCardObject: null,
        blazeTowardLeftObject: null,
        blazeAttackLeft: false,
        opponentCardShake: false,
        transitionState: ''
      }
     ....
  }

其中opponentCardObject将用来获得属性为’card opponent’的div实例,blazeTowardLeftObject将用来获得属性为’blaze toward-left’的div实例。我们在组件的mounted调用中添加如下代码:

mounted () {
      ....

      this.opponentCardObject = document.querySelector('.card.opponent')
      this.blazeTowardLeftObject = document.querySelector('.blaze.toward-left')
    }

当敌对扑克牌要出现在页面左边时,代码需要把变量cardOpponentOut设置成false,然后’in’属性就会添加到属性为’card opponent’的div元素上,我们在看看css定义的in属性:

.card.player.in {
    transform: translate3d(0, 0, 0);
  }

in属性对应的是一个transform变换,也就是说div具备了in属性后,就会执行上面定义的变换,div执行上面的变换后,它就出现在页面上了。前面我们提到过transform变换结束后,元素会发出一个webkitTransitionEnd消息,所以只要我们程序监听到div发出这个消息时,我们就可以判定左边扑克牌出现在页面上了。因此在组件的methods区域添加下面代码:

handleTransitionEnd (htmlObj) {
        var listener = function (e) {
          e.target.removeEventListener('webkitTransitionEnd', listener)
          this.handleTransitionEvent(e)
        }.bind(this)

        htmlObj.addEventListener('webkitTransitionEnd', listener)
      }

只要我们执行handleTransitionEnd(this.opponentCardObject),那么程序就可以监听div发出的webkitTransitionEnd消息,这个消息一旦监控到,里面定义的listener函数会被调用,然后他会调用组件的handleTransitionEvent接口来处理消息。我们以同样的方式来监控元素发出的webkitAnimationEnd消息,在组件中添加如下代码:

handleAnimationEnd (htmlObj) {
        var listener = function (e) {
          e.target.removeEventListener('webkitAnimationEnd', listener)
          this.handleTransitionEvent(e)
        }.bind(this)

        htmlObj.addEventListener('webkitAnimationEnd', listener)
      }

接着修改beginBattaleAnimation代码:

beginBattleAnimation () {
        this.handleTransitionEnd(this.opponentCardObject)
        this.transitionState = Constant.OPPONENT_CARD_TRANSITION_END
        this.cardOpponentOut = false
      }

this.handleTransitionEnd(this.opponentCardObject)作用是监听opponentCardObject对象发出的webkitTransitionEnd消息,然后将变量transitionState设置成Constant.OPPONENT_CARD_TRANSITION_END,然后将cardOpponentOut设置成false,这样opponentCardObject对应的div元素会添加上in属性,于是他就会执行in属性定义的transform变换,一旦变换完成后,组件的handleTransitionEvent接口就会被调用,我们看看该接口的实现,在组件中添加如下代码:

handleTransitionEvent (e) {
        switch (this.transitionState) {
          case Constant.OPPONENT_CARD_TRANSITION_END:
            if (this.cardOpponentOut === false) {
              this.transitionState = Constant.BLAZE_TOWARD_LEFT_ANIMATION_END
              this.blazeAttackLeft = true
              this.handleAnimationEnd(this.blazeTowardLeftObject)
            }
            break
          case Constant.BLAZE_TOWARD_LEFT_ANIMATION_END:
            this.opponentCardShake = true
            break
        }
      }

当handleTransitionEvent被调用,而且transitionState的值是Constant.OPPONENT_CARD_TRANSITION_END,这就表明opponentCardObject对应的div对象刚完成了一个transform变化,如果变量cardOpponentOut的值是false,我们就确定它刚完成了属性in定义的变换,也就是说敌对扑克牌在出现在页面上了。

然后我们把transitionState的值变为Constant.BLAZE_TOWARD_LEFT_ANIMATION_END,然后将blazeAttackLeft属性设置为true,于是attack属性就会添加到属性为’blaze toward-left’所对应的div上,于是该元素就会执行attack所定义的animation变换,this.handleAnimationEnd(this.blazeTowardLeftObject)让我们的代码监听blazeTowardLeftObject元素发出的webkitAnimationEnd消息,一旦这个消息被监控到后,handleTransitionEvent又再次被调用,它执行时发现transitionState的值是Constant.BLAZE_TOWARD_LEFT_ANIMATION_END,此时我们就可以确定blazeTowardLeftObject所对应的div元素,也就是属性为’blaze toward-left’的div元素完成了CSS属性attack所定义的动画特效,也就是说敌对扑克牌被冲击波打到了,因此我们就可以把oppoentCardShake设置成true,一旦设置后,shake属性就会添加到属性为’card opponent’的div元素上,因此该元素就会执行CSS属性shake所定义的动画特效,也就是左右颤抖的效果。

最后我们在Constant组件里添加如下代码:

script>
  import Vue from 'vue'
  export default {
  ...
  OPPONENT_CARD_TRANSITION_END: 'opponent_card_transition_end',
  BLAZE_TOWARD_LEFT_ANIMATION_END: 'blaze_left_animation_end'
}

完成上面代码,然后加载到浏览器后,运行起来可以看到如下效果:
这里写图片描述
一个冲击波从右边发出,打到左边扑克牌后,左边的牌发出一个左右颤抖的动画效果,具体特性和更加详细的讲解演示请参看视频:
VUE+WebPack实现精美Html5游戏设计

主阿,请降临我赏赐的甘露吧:
这里写图片描述

更多技术信息,包括操作系统,编译器,面试算法,机器学习,人工智能,请关照我的公众号:
这里写图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vue + Webpack多页/单页脚手架是一种用于构建Vue.js项目的工具。Vue.js是一个用于构建用户界面的JavaScript框架,而Webpack是一个模块打包工具。 多页/单页脚手架可以根据项目的需求选择构建方式。多页应用指的是每个页面都有自己的HTML文件,而单页应用则是只有一个HTML文件。在多页脚手架中,每个页面都有自己的入口文件和模板文件,Webpack会根据入口文件将各个页面的代码打包成独立的文件。这种方式适用于需要多个独立页面的项目。 而在单页脚手架中,只有一个HTML文件和一个入口文件。所有的页面内容都是通过Vue的路由机制来进行渲染和切换。这种方式适用于更复杂的单页应用,其中页面之间的切换是通过异步加载和前端路由来实现。 使用Vue + Webpack多页/单页脚手架的优点包括: 1. 灵活性:可以根据项目需求选择多页或单页应用方式。 2. 开发效率:脚手架提供了一套默认的配置,可以使开发者更快速地开始项目开发。 3. 模块化:使用Webpack打包模块,使得代码更易于管理和维护。 4. 热更新:脚手架支持热更新,可以在开发过程中实时看到修改的效果。 5. 生态系统:Vue.js和Webpack都有庞大的社区支持,可以方便地找到资料和解决问题。 总结起来,Vue + Webpack多页/单页脚手架是一种方便的工具,可以根据项目需求选择适合的构建方式,并提供了一系列的开发工具和优化配置,使开发更高效、更方便。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值