【前端】(仅思路)如何在前端实现一个fc手柄,将手机作为游戏手柄设备。

news2024/11/25 18:26:57

文章目录

    • 背景
    • 界面demo
      • 原型图(没错,就是它,童年回忆)
    • 遇到的问题
    • 最终
    • 后端demo(甚至比前端逻辑更简单)

背景

突发奇想,想要在前端实现一个fc游戏手柄,然后控制电脑的nes模拟器玩玩魂斗罗。
思路很简单,前后端使用websocket通信,connected标识socket链接已建立, 为了操作的低延时采用ws通信。

  • 前端: 实现10个按钮:上下左右,选择,开始,AB短按,AB长按。
  • 后端:监听按钮事件,然后调用win32api模拟键盘输入。
  • nes模拟器配置键盘映射。比如上=>w, 下 =>s。
    在这里插入图片描述

界面demo

在这里插入图片描述

原型图(没错,就是它,童年回忆)

在这里插入图片描述

单个按钮事件非常简单,监听touchstart 和touchend就行

        // 获取按钮元素
const leftButton = document.getElementById('left');
const topButton = document.getElementById('top');
const downButton = document.getElementById('down');
const rightButton = document.getElementById('right');

// 添加触摸按下事件监听器
leftButton.addEventListener('touchstart', function() {
    console.log('Left button touched!');
    // 在这里添加按下时的逻辑
    socket.send("a:down"); //
});

topButton.addEventListener('touchstart', function() {
    console.log('Top button touched!');
    // 在这里添加按下时的逻辑
    socket.send("w:down"); //
});

downButton.addEventListener('touchstart', function() {
    console.log('Down button touched!');
    // 在这里添加按下时的逻辑
    socket.send("s:down"); //
});

rightButton.addEventListener('touchstart', function() {
    console.log('Right button touched!');
    // 在这里添加按下时的逻辑
    socket.send("d:down"); //
});

// 添加触摸抬起事件监听器
leftButton.addEventListener('touchend', function() {
    console.log('Left button released!');
    // 在这里添加抬起时的逻辑
    socket.send("a:up"); //
});

topButton.addEventListener('touchend', function() {
    console.log('Top button released!');
    // 在这里添加抬起时的逻辑
    socket.send("w:up"); //
});

downButton.addEventListener('touchend', function() {
    console.log('Down button released!');
    // 在这里添加抬起时的逻辑
    socket.send("s:up"); //
});

rightButton.addEventListener('touchend', function() {
    console.log('Right button released!');
    // 在这里添加抬起时的逻辑
    socket.send("d:up"); //
});

但是组合键位就有问题了, html5触发 右+下 操作时,需要用两个手指点击 right 和 down才行。
PS:玩个魂斗罗还得3指操作, 这不2b的很么。
理想操作是:大拇指按下right 和down的按钮区域,就能触发右+下,尝试让gpt帮我们解决。

遇到的问题

  1. 组合键的问题:right+down, 实体手柄可以实现向右下角瞄准。但是h5中,大拇指按下right和down两个按钮区域时,只会触发一个touch事件。(这玩意儿情况一般人还真不会碰到)

实现大拇指同时按下right和down按钮区域,触发右+下的 解决办法

    // 处理触摸事件, 给方向键4个按钮 touchstart绑定此函数
    function handleTouch(event) {
        event.preventDefault(); // 阻止默认行为,如页面滚动
        const touches = event.touches;
        
        // 获取所有触摸点的位置信息
        const touchPositions = Array.from(touches).map(touch => {
            return {
                x: touch.clientX,
                y: touch.clientY
            };
        });

        // 检查是否同时触摸了 right 和 downsdsdd 按钮
        const touchingRight = touchPositions.some(pos => {
            return isTouchingElement(pos, rightButton);
        });
        const touchingDown = touchPositions.some(pos => {
            return isTouchingElement(pos, downButton);
        });
        // dssdsdsddsdsdsdsdddsdssdsdsdsdsddddssssssssddssssssdssdssd
        if (touchingRight && touchingDown) {
            // 在这里执行同时按下 right 和 down 按钮时的逻辑
            socket.send("s+d:down")
        }else if (touchingRight) {
            socket.send("d:down")
        }else if(touchingDown) {
            socket.send('s:down')
        }
    }

    // 辅助函数:检查触摸点是否在指定元素上
    function isTouchingElement(touchPosition, element) {
        const rect = element.getBoundingClientRect();
        return (
            touchPosition.x >= rect.left &&
            touchPosition.x <= rect.right &&
            touchPosition.y >= rect.top &&
            touchPosition.y <= rect.bottom
        );
    }

最终

可以愉快的拿手机当手柄了, 甚至可以两个页面双人对战。再进一步甚至能远程双人联机。

后端demo(甚至比前端逻辑更简单)

package main

import (
	"fmt"
	"log"
	"net/http"
	"text/template"

	"github.com/go-vgo/robotgo"
	"github.com/gorilla/websocket"
)

var upgrader = websocket.Upgrader{
	ReadBufferSize:  1024,
	WriteBufferSize: 1024,
}

func main() {
	fmt.Println("Starting server on port 18080...")
	http.HandleFunc("/", handler)
	http.HandleFunc("/ws", wsHandler)
	log.Fatal(http.ListenAndServe(":18080", nil))
}

// 页面返回
func handler(w http.ResponseWriter, r *http.Request) {
	tmpl, err := template.ParseFiles("index.html")
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	err = tmpl.Execute(w, nil)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}
}
// wsHandler写的太2b了, 就不放出来了,让gpt给写写吧
func wsHandler(w http.ResponseWriter, r *http.Request) {

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1962617.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

单细胞|MEBOCOST·细胞间代谢通讯

概述 在代谢活跃的细胞中&#xff0c;表达的代谢酶催化代谢反应生成许多代谢物。这些代谢物中的一些可以扩散到细胞外空间并作为信号分子发挥作用。某些细胞外代谢物可以与空间上邻近细胞的感应蛋白结合。我们将分泌代谢物的细胞称为发送细胞&#xff0c;而表达感应蛋白的细胞称…

开放式耳机稳固吗?音质好吗?四款开放式耳机测评

对于体验过不下50款耳机的我来说&#xff0c;在这么多耳机类型里&#xff0c;我推荐入手开放式耳机。 开放式耳机拥有着舒适的体验。有挂耳式的设计&#xff0c;相比入耳式&#xff0c;开放式耳机不会对耳道造成影响。再加上大部分开放式耳机的挂耳式设计都是人体工学设计&…

Astro 实现TodoList网页应用案例

Astro 是一个现代化的静态站点生成器和前端框架&#xff0c;它具有独特的设计理念&#xff1a;岛屿架构。它允许开发人员使用组件化的方式构建内容优先的网站&#xff0c;将各种技术栈&#xff08;如React、Vue、Svelte等&#xff09;的组件无缝集成到同一个项目中。 1、创建项…

STM32高级运动控制系统教程

目录 引言环境准备高级运动控制系统基础代码实现&#xff1a;实现高级运动控制系统 4.1 传感器数据采集模块 4.2 数据处理与运动控制模块 4.3 通信与网络系统实现 4.4 用户界面与数据可视化应用场景&#xff1a;运动控制与优化问题解决方案与优化收尾与总结 1. 引言 高级运动…

【FCA FineDataLink认证指南】解锁高薪职业新机遇,提升职场竞争力

数据集成作为数字化转型的核心组成部分&#xff0c;正在经历前所未有的增长和创新。随着企业对数据驱动决策的需求日益增长&#xff0c;数据集成领域的人才在各行各业中都备受青睐。而且随着大数据、云计算和人工智能技术的不断发展&#xff0c;数据集成领域的职业机会也在不断…

Springcloud物流配送后台-计算机毕业设计源码69809

目 录 摘要 1 绪论 1.1 选题背景与意义 1.2国内外研究现状 1.3论文结构与章节安排 2 物流配送后台系统分析 2.1 可行性分析 2.1.1 技术可行性分析 2.1.2 经济可行性分析 2.1.3 操作可行性分析 2.2 系统流程分析 2.2.1数据增加流程 2.2.2 数据修改流程 2.2.3 数据…

UE4调试手段:主动崩溃与“.pdb”解析“.dmp”文件

主动崩溃 尝试了一些做法&#xff0c;发现 check(false) 对于Development配置而言&#xff0c;是有效果的&#xff0c;代码如下&#xff1a; // Called when the game starts or when spawned void AMyActor::BeginPlay() {Super::BeginPlay();check(false); // 尝试用这个来…

RAG调研

一 &#xff1a; RAG解决的问题 1.1 LLM 的局限 幻觉 知识过期 推理过程不透明&#xff0c;不可追踪 1.2 RAG介绍 检索增强生成&#xff08;RAG&#xff09;是一种使用外部知识库辅助文本生成的技术。它结合了检索与生成&#xff0c;通过访问外部数据库检索得到有关的信息&…

vue的基础知识总结(1)

目录 一.什么是Vue&#xff1f; 二.基于脚手架创建就前端工程&#xff1a; 三.Vue工程结构以及组件&#xff1a; 1.Vue项目结构&#xff1a; 2.Vue组件&#xff1a; 四.Vue基本使用方式&#xff1a; 1.文本插值{{}}&#xff1a; 2.属性绑定v-bind&#xff1a; 3.事件绑…

常用的项目管理软件有哪些?东成电动工具用 PowerProject 打造先进项目管理平台

近日&#xff0c;国内最大的专业电动工具制造企业&#xff1a;江苏东成电动工具有限公司与北京奥博思软件技术有限公司达成合作&#xff0c;借助 PowerProject 项目管理系统&#xff0c;全面提升项目管理效率&#xff0c;满足企业多场景、多角色的全周期项目管理&#xff0c;激…

torch._dynamo 理解(2)——Backend

0 概述 TorchDynamo 是一个 Python 级别的即时 (JIT) 编译器&#xff0c;旨在让未修改的 PyTorch 程序运行得更快。它通过 Python Frame Evaluation Hooks&#xff08;Python 框架评估钩子&#xff09;来实现这一目标&#xff0c;以便在运行时动态地生成和优化代码。这使得 To…

借助Aspose.html控件, 将SVG 转PNG 的 C# 图像处理库

Aspose.HTML for .NET 不仅提供超文本标记语言 ( HTML ) 文件处理&#xff0c;还提供流行图像文件格式之间的转换。您可以利用丰富的渲染和转换功能将SVG文件渲染为PNG、JPG或其他广泛使用的文件格式。但是&#xff0c;我们将使用此C# 图像处理库以编程方式在 C# 中将 SVG 转换…

VBA 颜色

1. ColorIndex 1-1. ColorIndex的值是从1到56。 Option ExplicitConst MAX_COL As Long 8 Const MAX_ROW As Long 2 Const START_ROW As Long 2 Const START_COL As Long 2Sub Color()Dim i As IntegerDim intRow As Long, intCol As LongCells.SelectSelection.ClearCon…

redis Ubuntu安装问题

报错1&#xff1a;Package pkg-config is not available, but is referred to by another package /bin/sh: 1: pkg-config: not found&#xff08;没有安装pkg-config&#xff09; sudo apt-get install pkg-config /bin/sh: 1: cc: not found&#xff08;没有安装gcc环境&am…

年过30年程序员,到底要不要考虑搞点副业

一、前言 作为一名年过三十的程序员&#xff0c;我深刻体会到了职场的残酷和不确定性。在这个技术日新月异的时代&#xff0c;我们不仅要在专业领域深耕细作&#xff0c;更要敏锐地捕捉互联网的风口&#xff0c;以确保自己不被时代淘汰。程序员的黄金年龄似乎被限定在35岁之前…

《Milvus Cloud向量数据库指南》——ChatGLM:从GLM-130B到GLM-4

ChatGLM:从GLM-130B到GLM-4的跨越:智谱AI在通用人工智能领域的深度探索与实践 在人工智能的浩瀚星空中,智谱AI如同一颗璀璨的新星,以其独特的技术视角和坚定的创新步伐,在通用人工智能(AGI)的征途上留下了深刻的足迹。技术生态总监贾伟在近期的一次分享中,不仅为我们描…

蓝牙+LoRa+北斗RTK融合定位系统介绍

蓝牙LoRa北斗RTK定位系统是新锐科创自主研发的融合定位系统&#xff0c;该系统利用融合定位技术将当今主流的室内外定位技术有机融合&#xff0c;从而满足不同场景定位需求。 蓝牙LoRa北斗RTK定位系统是一种室内外高精度人员定位管理系统&#xff0c;具有功耗低、部署简单、实时…

【计算机视觉学习之CV2图像操作实战:车牌识别1】

基于Sobel算子的车牌识别 步骤如下 高斯模糊图片灰度化Sobel算子图像二值化闭操作膨胀腐蚀中值滤波查找轮廓判断车牌区域 import cv2 # 读取图片 rawImage cv2.imread("car1.jpg") # 高斯模糊&#xff0c;将图片平滑化&#xff0c;去掉干扰的噪声 image cv2.Gau…

蓄势赋能 数智化转型掌舵人百望云杨正道荣膺“先锋人物”

2024年&#xff0c;在数据与智能的双涡轮驱动下&#xff0c;我们迎来了一个以智能科技为核心的新质生产力大爆发时代。在数智化浪潮的推动下&#xff0c;全球企业正站在转型升级的十字路口。在这个充满变革的时代&#xff0c;企业转型升级的道路充满挑战&#xff0c;但也孕育着…

【OceanBase DBA早下班系列】—— obdiag 收集的 SQL Monitor Report 如何解读

1. 前言 前几天写了一篇博客&#xff0c;告诉大家在遇到慢SQL或者复杂的并行SQL的时候怎么高效的来收集【SQL Monitor Report】&#xff0c;上一篇博客的链接&#xff1a; OceanBase 社区 &#xff1b;发出去后有不少问我这份报告咋解读。今天再出一篇博客给大家介绍下如何解…