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

2023-12-16 02:59

本文主要是介绍【html5手游开发】虚拟摇杆及虚拟按键的开发,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前言

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

难点解释

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 startthis.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>

资源下载打包

下载

这篇关于【html5手游开发】虚拟摇杆及虚拟按键的开发的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/498856

相关文章

HTML5中的Microdata与历史记录管理详解

《HTML5中的Microdata与历史记录管理详解》Microdata作为HTML5新增的一个特性,它允许开发者在HTML文档中添加更多的语义信息,以便于搜索引擎和浏览器更好地理解页面内容,本文将探... 目录html5中的Mijscrodata与历史记录管理背景简介html5中的Microdata使用M

html5的响应式布局的方法示例详解

《html5的响应式布局的方法示例详解》:本文主要介绍了HTML5中使用媒体查询和Flexbox进行响应式布局的方法,简要介绍了CSSGrid布局的基础知识和如何实现自动换行的网格布局,详细内容请阅读本文,希望能对你有所帮助... 一 使用媒体查询响应式布局        使用的参数@media这是常用的

HTML5表格语法格式详解

《HTML5表格语法格式详解》在HTML语法中,表格主要通过table、tr和td3个标签构成,本文通过实例代码讲解HTML5表格语法格式,感兴趣的朋友一起看看吧... 目录一、表格1.表格语法格式2.表格属性 3.例子二、不规则表格1.跨行2.跨列3.例子一、表格在html语法中,表格主要通过< tab

Vue3组件中getCurrentInstance()获取App实例,但是返回null的解决方案

《Vue3组件中getCurrentInstance()获取App实例,但是返回null的解决方案》:本文主要介绍Vue3组件中getCurrentInstance()获取App实例,但是返回nu... 目录vue3组件中getCurrentInstajavascriptnce()获取App实例,但是返回n

JS+HTML实现在线图片水印添加工具

《JS+HTML实现在线图片水印添加工具》在社交媒体和内容创作日益频繁的今天,如何保护原创内容、展示品牌身份成了一个不得不面对的问题,本文将实现一个完全基于HTML+CSS构建的现代化图片水印在线工具... 目录概述功能亮点使用方法技术解析延伸思考运行效果项目源码下载总结概述在社交媒体和内容创作日益频繁的

前端CSS Grid 布局示例详解

《前端CSSGrid布局示例详解》CSSGrid是一种二维布局系统,可以同时控制行和列,相比Flex(一维布局),更适合用在整体页面布局或复杂模块结构中,:本文主要介绍前端CSSGri... 目录css Grid 布局详解(通俗易懂版)一、概述二、基础概念三、创建 Grid 容器四、定义网格行和列五、设置行

使用Python开发一个带EPUB转换功能的Markdown编辑器

《使用Python开发一个带EPUB转换功能的Markdown编辑器》Markdown因其简单易用和强大的格式支持,成为了写作者、开发者及内容创作者的首选格式,本文将通过Python开发一个Markd... 目录应用概览代码结构与核心组件1. 初始化与布局 (__init__)2. 工具栏 (setup_t

前端下载文件时如何后端返回的文件流一些常见方法

《前端下载文件时如何后端返回的文件流一些常见方法》:本文主要介绍前端下载文件时如何后端返回的文件流一些常见方法,包括使用Blob和URL.createObjectURL创建下载链接,以及处理带有C... 目录1. 使用 Blob 和 URL.createObjectURL 创建下载链接例子:使用 Blob

Vuex Actions多参数传递的解决方案

《VuexActions多参数传递的解决方案》在Vuex中,actions的设计默认只支持单个参数传递,这有时会限制我们的使用场景,下面我将详细介绍几种处理多参数传递的解决方案,从基础到高级,... 目录一、对象封装法(推荐)二、参数解构法三、柯里化函数法四、Payload 工厂函数五、TypeScript

使用Python实现全能手机虚拟键盘的示例代码

《使用Python实现全能手机虚拟键盘的示例代码》在数字化办公时代,你是否遇到过这样的场景:会议室投影电脑突然键盘失灵、躺在沙发上想远程控制书房电脑、或者需要给长辈远程协助操作?今天我要分享的Pyth... 目录一、项目概述:不止于键盘的远程控制方案1.1 创新价值1.2 技术栈全景二、需求实现步骤一、需求