【html5手游开发】虚拟摇杆及虚拟按键的开发

40 篇文章 0 订阅
20 篇文章 0 订阅

前言

现在很多手游都有虚拟按钮–尤其是那些需要操作高的。那么我们也要紧跟时代步伐,开发一个虚拟按钮插件。

难点解释

1、首先绝对要先熟悉一下pixi。
2、要计算一下手指触摸拖动摇杆的角度–小学数学要过关,假如是小学连续留级十几年的话,会有点麻烦。
3、pixi有一些小bug,就是touch end会无缘无故由其他物体触发,代码里面已经有解决方案了。想知道原委就看看上一篇文章。

实际运行界面

这里写图片描述

这里写图片描述

核心代码

<%@ page import="java.util.Date" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%

  String  _js_version="7";

%>
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width,initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no"/>

  <meta name="apple-mobile-web-app-capable" content="yes"/>
  <meta name="apple-mobile-web-app-status-bar-style" content="black">
  <meta content="telephone=no,email=no" name="format-detection">
  <meta name="full-screen" content="true"/>
  <%--竖屏--%>
  <%--<meta name="screen-orientation" content="portrait"/>--%>
  <%--横屏--%>
  <meta name="screen-orientation" content="landscape"/>

  <meta name="x5-fullscreen" content="true"/>
  <meta name="360-fullscreen" content="true"/>
  <script type="text/javascript" src="../js/jquery-1.11.0.min.js"></script>
  <script type="text/javascript" src="../js/jquery-migrate-1.2.1.min.js"></script>
  <script src="../js/box2dWeb/Box2dWeb-2.1.a.3.min.js"></script>
  <script src="../js/pixi.min.js"></script>
  <script src="../js/pixi-spine.min.js"></script>




  <style>
    body{
      padding: 0;
      margin: 0;
    }
  </style>

</head>
<body>

<div id="game" style=""></div>
<script>
  var GameOptions={
    width:800 //游戏屏幕的高度。
    ,height:600 //游戏屏幕的宽度。
    ,ground_y:400-65 //地面y坐标
    ,fps:10
    ,actorWidth:57*2*0.8
    ,actorHeight:61*2*0.8

    //--hero的行走向量速度。
    ,hero_run_x_speed:15
    ,hero_run_y_speed:30 //hero跳跃时候向上的速度。

  };
</script>
<script>
  //--虚拟手柄控件。
  function GameJoyPad(parent_container,_opts){
    var me=this;
    this.settings={
      joy_pad_background:"assets/joystick/Backgrounds/Back_08.png"//摇杆的背景。
      ,joy_pad_joystick:"assets/joystick/Joystick/Joystick_08.png" //摇杆正体。
      ,joy_pad_x:100 //摇杆的坐标
      ,joy_pad_y:220 //摇杆的y坐标
      //--注意,所有缩放的尺寸都是按照unitiy3d获得的这些摇杆素材来设置的,假如替换了texture,请重新设置缩放尺寸。
      ,joy_pad_background_scale:{
        x:0.4
        ,y:0.4
      }//摇杆背景需要缩放的比例,默认是x和y上面都是1
      ,joy_pad_joystick_scale:{
        x:0.4
        ,y:0.4
      }//摇杆主体需要缩放的比例,默认x、y都是1
      ,buttons:[
        {
          button_name:"shoot"
          ,normal_texture:"assets/joystick/Buttons/Button_08_Normal_Shoot.png"
          ,pressed_texture:"assets/joystick/Buttons/Button_08_Pressed_Shoot.png"
          ,x:300
          ,y:250
          ,scale:{x:0.4,y:0.4}
        }
        ,{
          button_name:"gun"
          ,normal_texture:"assets/joystick/Buttons/Button_08_Normal_Shoot_B.png"
          ,pressed_texture:"assets/joystick/Buttons/Button_08_Pressed_Shoot_B.png"
          ,x:400
          ,y:250
          ,scale:{x:0.4,y:0.4}
        }
        , {
          button_name:"blank"
          ,normal_texture:"assets/joystick/Buttons/Button_08_Normal_Virgin.png"
          ,pressed_texture:"assets/joystick/Buttons/Button_08_Pressed_Virgin.png"
          ,x:500
          ,y:250
          ,scale:{x:0.4,y:0.4}
        }
      ] //虚拟手柄的其他按钮。


      //--摇杆摇动角度变换时候的回调函数。
      ,onJoyStickMove:function(now_stick_angle){

      }
      //--点击了控制按钮的回调事件。
      ,onButtonClick:function(event,button_name){

      }



    };
    $.extend(this.settings,_opts);
    //--基本赋值。
    this.parent_container=parent_container;
    this.joy_pad_container={};
    this.joy_pad_background={};
    this.joy_pad_joystick={};
    this.joy_pad_radius=0;//这是背景大圈子的半径。
    this.joy_pad_stickRadius=0;//这是摇杆小圈子的半径。
    //--生成一个随机的joy container id。
    this.joy_pad_container_id=new Date().getTime()+"_"+parseInt(Math.random()*1000);

    //--好了,加载相关资源
    me.__loadResources(function(){
      me.__init_stick();
    });
    //--新建按钮。
    for(var i=0;i< me.settings.buttons.length;i++){
      var buttonItemInfo=me.settings.buttons[i];
      me.__createButton(buttonItemInfo);
    }
  }
  GameJoyPad.prototype.__loadResources=function(callback){
    var me=this;
    PIXI.loader.add('joy_pad_background',me.settings.joy_pad_background);
    PIXI.loader.add('joy_pad_joystick',me.settings.joy_pad_joystick);
    PIXI.loader.once('complete',function(){
      if(callback){
        callback();
      }
    });
    PIXI.loader.load();
  }
  //--初始化摇杆。
  GameJoyPad.prototype.__init_stick=function(){
    var child=this;
    var texture_bg=PIXI.Texture.fromImage(this.settings.joy_pad_background);
    var texture_joystick=PIXI.Texture.fromImage(this.settings.joy_pad_joystick);

    this.joy_pad_container=new PIXI.Container();
    this.joy_pad_background=new PIXI.Sprite(texture_bg);
    this.joy_pad_joystick=new PIXI.Sprite(texture_joystick);
    this.joy_pad_background.scale=this.settings.joy_pad_background_scale;
    this.joy_pad_joystick.scale=this.settings.joy_pad_joystick_scale;
    this.joy_pad_background.anchor={x:0.5,y:0.5};
    this.joy_pad_joystick.anchor={x:0.5,y:0.5};
    this.joy_pad_container.anchor={x:0.5,y:0.5};
    this.joy_pad_container.addChild(this.joy_pad_background);
    this.joy_pad_container.addChild(this.joy_pad_joystick);
    this.joy_pad_radius=this.joy_pad_container.width/2;
    this.joy_pad_stickRadius=this.joy_pad_joystick.width/2;
    window.joy_container=this.joy_pad_container;
    this.joy_pad_container.position={
      x:this.settings.joy_pad_x
      ,y:this.settings.joy_pad_y
    };
    this.parent_container.addChild(this.joy_pad_container);
    this.joy_pad_container.random_id=this.joy_pad_container_id;
    this.__init_stick_events();
  }
  GameJoyPad.prototype.__init_stick_events=function(){
    var me=this;
    this.joy_pad_container.interactive=true;
    var _on_drag=false;
    var _event_data={};
    var _touch_event_id=0;
    /******pixi bug1:当两个手指其中一个,譬如摇杆,另一个手指点击按钮,摇杆会接收到touch end事件。醉了。******/
    function onDragStart(event){
      //--注意,pc端的identifier是undefined。
      _event_data = event.data;
      var startPosition = _event_data.getLocalPosition(this.parent);
      _touch_event_id=event.data.identifier;
      _on_drag=true;
    }
    function onDragEnd(event){
      if(_on_drag==false){
        return;
      }
      if(_touch_event_id!=event.data.identifier){
        return;
      }
      _on_drag=false;
      window.end_event=event;
      me.joy_pad_joystick.position={
        x:0
        ,y:0
      };
    }
    function onDragMove(event){

      if(_touch_event_id!=event.data.identifier){
        return;
      }
      if(_on_drag==false){
        return;
      }
      var newPosition = _event_data.getLocalPosition(this.parent);
      var _side_length_y=newPosition.y-me.settings.joy_pad_y;
      var _side_length_x=newPosition.x-me.settings.joy_pad_x;

      var _center_point={
        x:0
        ,y:0
      };//--中心点。

      var _stick_angle=0; //当前摇杆的角度


      if(_side_length_x==0&&_side_length_y==0){
        return;
      }
      //--好了,现在判断执行计算的半径。
      var _cal_radius=0;

      if(_side_length_x*_side_length_x+_side_length_y*_side_length_y>=me.joy_pad_radius*me.joy_pad_radius){
        _cal_radius=me.joy_pad_radius;
        //--假如大于的话,那么就按照圆弧计算坐标。

      }
      else{
        _cal_radius=me.joy_pad_radius-me.joy_pad_stickRadius;
      }


      if(_side_length_x==0){
        if(_side_length_y>0){
          _center_point={
            x:0
            ,y:_side_length_y>me.joy_pad_radius?me.joy_pad_radius:_side_length_y
          };
          _stick_angle=270;//180度。
        }
        else{
          _center_point={
            x:0
            ,y:-(Math.abs(_side_length_y)>me.joy_pad_radius?me.joy_pad_radius:Math.abs(_side_length_y))
          };
          _stick_angle=90;//901度
        }

        me.joy_pad_joystick.position=_center_point;
        me.settings.onJoyStickMove(_stick_angle);
        return;
      }
      else if(_side_length_y==0){
        if(_side_length_x>0){
          _center_point={
            x:(Math.abs(_side_length_x)>me.joy_pad_radius?me.joy_pad_radius:Math.abs(_side_length_x))
            ,y:0
          };
          _stick_angle=0;//0度
        }
        else{
          _center_point={
            x:-(Math.abs(_side_length_x)>me.joy_pad_radius?me.joy_pad_radius:Math.abs(_side_length_x))
            ,y:0
          };
          _stick_angle=180;//180度
        }
        me.joy_pad_joystick.position=_center_point;
        me.settings.onJoyStickMove(_stick_angle);
        return;
      }
      var _tan_val=Math.abs(_side_length_y/_side_length_x);
      var _radian=Math.atan(_tan_val);
      var _angle=_radian*180/Math.PI;
      _stick_angle=_angle;

      //--好了,计算现在摇杆的中心点主坐标了。
      var _center_x= 0;
      var _center_y=0;
      if(_side_length_x*_side_length_x+_side_length_y*_side_length_y>=me.joy_pad_radius*me.joy_pad_radius){
        _center_x= me.joy_pad_radius*Math.cos(_radian);
        _center_y=me.joy_pad_radius*Math.sin(_radian);

      }
      else{
        _center_x= Math.abs(_side_length_x)>me.joy_pad_radius?me.joy_pad_radius:Math.abs(_side_length_x);
        _center_y=Math.abs(_side_length_y)>me.joy_pad_radius?me.joy_pad_radius:Math.abs(_side_length_y);
      }

      if(_side_length_y<0){
        _center_y=-Math.abs(_center_y);
      }
      if(_side_length_x<0){
        _center_x=-Math.abs(_center_x);
      }
      if(_side_length_x>0&&_side_length_y<0){
        //--锐角。
      }
      else if(_side_length_x<0&&_side_length_y<0){
        //--好了,钝角。
        _stick_angle=180-_stick_angle;
      }
      else if(_side_length_x<0&&_side_length_y>0){
        _stick_angle=_stick_angle+180;
      }
      else if(_side_length_x>0&&_side_length_y>0){
        _stick_angle=360-_stick_angle;
      }
      _center_point={
        x:_center_x
        ,y:_center_y
      };
      me.joy_pad_joystick.position=_center_point;
      me.settings.onJoyStickMove(_stick_angle);
    };

      // events for drag start
            this.joy_pad_container.on('mousedown', onDragStart)
            .on('touchstart', onDragStart)
      // events for drag end
            .on('mouseup', onDragEnd)
            .on('mouseupoutside', onDragEnd)
            .on('touchend', onDragEnd)
            .on('touchendoutside', onDragEnd)
      // events for drag move
            .on('mousemove', onDragMove)
            .on('touchmove', onDragMove);


  }
  GameJoyPad.prototype.__createButton=function(buttonItemInfo){
    var me=this;
    var textureButton = PIXI.Texture.fromImage(buttonItemInfo.normal_texture);
    var textureButtonDown = PIXI.Texture.fromImage(buttonItemInfo.pressed_texture);
    var textureButtonOver = PIXI.Texture.fromImage(buttonItemInfo.normal_texture);
    var button = new PIXI.Sprite(textureButton);
    button.buttonMode = true;
    button.anchor.set(0.5);
    button.position.x = buttonItemInfo.x;
    button.position.y = buttonItemInfo.y;

    button.interactive = true;
    if(buttonItemInfo.scale){
      button.scale=buttonItemInfo.scale;
    }

    var _event_data_identifier=0;
    function onButtonDown(event)
    {
      this.isdown = true;
      this.texture = textureButtonDown;
      this.alpha = 1;
      _event_data_identifier=event.data.identifier;

    }

    function onButtonUp(event)
    {
      if(_event_data_identifier!=event.data.identifier){
        return;
      }
      this.isdown = false;

      if (this.isOver)
      {
        this.texture = textureButtonOver;
      }
      else
      {
        this.texture = textureButton;
      }
    }

    function onButtonOver()
    {
      this.isOver = true;

      if (this.isdown)
      {
        return;
      }

      this.texture = textureButtonOver;
    }

    function onButtonOut()
    {
      this.isOver = false;

      if (this.isdown)
      {
        return;
      }

      this.texture = textureButton;
    }


    button.on('mousedown', onButtonDown)
          .on('touchstart', onButtonDown)

      // set the mouseup and touchend callback...
            .on('mouseup', onButtonUp)
            .on('touchend', onButtonUp)
            .on('mouseupoutside', onButtonUp)
            .on('touchendoutside', onButtonUp)

      // set the mouseover callback...
            .on('mouseover', onButtonOver)

      // set the mouseout callback...
            .on('mouseout', onButtonOut);


    // you can also listen to click and tap events :
    //.on('click', noop)

    var noop = function (_event) {
      me.settings.onButtonClick(_event,buttonItemInfo.button_name);
    };
    button.tap = noop;
    button.click = noop;
    this.parent_container.addChild(button);

    return button;
  }
</script>

<script>
  var game_renderer = PIXI.autoDetectRenderer(GameOptions.width, GameOptions.height,{backgroundColor : 0x1099bb});
  var game_stage = new PIXI.Container(0x66FF99);
  $("#game").append(game_renderer.view);
  var _joy_pad=new GameJoyPad(game_stage,{
          //--摇杆摇动角度变换时候的回调函数。
          onJoyStickMove:function(now_stick_angle){
            _showMsg("摇杆角度为:"+now_stick_angle);
          }
  //--点击了控制按钮的回调事件。
        ,onButtonClick:function(event,button_name){
            _showMsg("点击的按钮名称是:"+button_name);
        }
  });
  var style = {
    font : 'bold italic 20px Arial',
    fill : '#F7EDCA',
    stroke : '#4a1850',
//    strokeThickness : 5,
//    dropShadow : true,
//    dropShadowColor : '#000000',
//    dropShadowAngle : Math.PI / 6,
//    dropShadowDistance : 6,
    wordWrap : true,
    wordWrapWidth : 300
  };

  var richText = new PIXI.Text('Rich text with a lot of options and across multiple lines',style);
  richText.x = 0;
  richText.y = 0;

  game_stage.addChild(richText);
  function game_animate(){

    requestAnimationFrame(game_animate);
    game_renderer.render(game_stage);
  }
  requestAnimationFrame(game_animate);

</script>
<script>
  function _debug(msg){
    var _str=richText.text;
    richText.text=_str+"\n"+msg;
  }
  function _showMsg(msg){
    richText.text=msg;
  }
</script>

</body>
</html>

资源下载打包

下载

  • 1
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值