【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

相关文章

Django开发时如何避免频繁发送短信验证码(python图文代码)

《Django开发时如何避免频繁发送短信验证码(python图文代码)》Django开发时,为防止频繁发送验证码,后端需用Redis限制请求频率,结合管道技术提升效率,通过生产者消费者模式解耦业务逻辑... 目录避免频繁发送 验证码1. www.chinasem.cn避免频繁发送 验证码逻辑分析2. 避免频繁

Spring Boot集成/输出/日志级别控制/持久化开发实践

《SpringBoot集成/输出/日志级别控制/持久化开发实践》SpringBoot默认集成Logback,支持灵活日志级别配置(INFO/DEBUG等),输出包含时间戳、级别、类名等信息,并可通过... 目录一、日志概述1.1、Spring Boot日志简介1.2、日志框架与默认配置1.3、日志的核心作用

PyQt5 GUI 开发的基础知识

《PyQt5GUI开发的基础知识》Qt是一个跨平台的C++图形用户界面开发框架,支持GUI和非GUI程序开发,本文介绍了使用PyQt5进行界面开发的基础知识,包括创建简单窗口、常用控件、窗口属性设... 目录简介第一个PyQt程序最常用的三个功能模块控件QPushButton(按钮)控件QLable(纯文本

从入门到精通详解LangChain加载HTML内容的全攻略

《从入门到精通详解LangChain加载HTML内容的全攻略》这篇文章主要为大家详细介绍了如何用LangChain优雅地处理HTML内容,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录引言:当大语言模型遇见html一、HTML加载器为什么需要专门的HTML加载器核心加载器对比表二

基于Python开发一个图像水印批量添加工具

《基于Python开发一个图像水印批量添加工具》在当今数字化内容爆炸式增长的时代,图像版权保护已成为创作者和企业的核心需求,本方案将详细介绍一个基于PythonPIL库的工业级图像水印解决方案,有需要... 目录一、系统架构设计1.1 整体处理流程1.2 类结构设计(扩展版本)二、核心算法深入解析2.1 自

C++链表的虚拟头节点实现细节及注意事项

《C++链表的虚拟头节点实现细节及注意事项》虚拟头节点是链表操作中极为实用的设计技巧,它通过在链表真实头部前添加一个特殊节点,有效简化边界条件处理,:本文主要介绍C++链表的虚拟头节点实现细节及注... 目录C++链表虚拟头节点(Dummy Head)一、虚拟头节点的本质与核心作用1. 定义2. 核心价值二

SpringBoot开发中十大常见陷阱深度解析与避坑指南

《SpringBoot开发中十大常见陷阱深度解析与避坑指南》在SpringBoot的开发过程中,即使是经验丰富的开发者也难免会遇到各种棘手的问题,本文将针对SpringBoot开发中十大常见的“坑... 目录引言一、配置总出错?是不是同时用了.properties和.yml?二、换个位置配置就失效?搞清楚加

前端如何通过nginx访问本地端口

《前端如何通过nginx访问本地端口》:本文主要介绍前端如何通过nginx访问本地端口的问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、nginx安装1、下载(1)下载地址(2)系统选择(3)版本选择2、安装部署(1)解压(2)配置文件修改(3)启动(4)

mysql查询使用_rowid虚拟列的示例

《mysql查询使用_rowid虚拟列的示例》MySQL中,_rowid是InnoDB虚拟列,用于无主键表的行ID查询,若存在主键或唯一列,则指向其,否则使用隐藏ID(不稳定),推荐使用ROW_NUM... 目录1. 基本查询(适用于没有主键的表)2. 检查表是否支持 _rowid3. 注意事项4. 最佳实

HTML中meta标签的常见使用案例(示例详解)

《HTML中meta标签的常见使用案例(示例详解)》HTMLmeta标签用于提供文档元数据,涵盖字符编码、SEO优化、社交媒体集成、移动设备适配、浏览器控制及安全隐私设置,优化页面显示与搜索引擎索引... 目录html中meta标签的常见使用案例一、基础功能二、搜索引擎优化(seo)三、社交媒体集成四、移动