OpenHarmony南向开发实例:【游戏手柄】

 介绍

基于TS扩展的声明式开发范式编程语言,以及OpenHarmony的分布式能力实现的一个手柄游戏。

完成本篇Codelab需要两台开发板,一台开发板作为游戏端,一台开发板作为手柄端,实现如下功能:

  • 游戏端呈现飞机移动、发射子弹等效果。
  • 游戏端分布式拉起手柄端FA。
  • 手柄端与游戏端建立连接,发送指令给游戏端,比如移动飞机,发射子弹和释放技能等。

最终效果图如下:

搭建OpenHarmony环境

完成本篇Codelab我们首先要完成开发环境的搭建,本示例以RK3568开发板为例,参照以下步骤进行:

  1. [获取OpenHarmony系统版本]:标准系统解决方案(二进制)。

    以3.1版本为例:

  2. 搭建烧录环境。

    1. [完成DevEco Device Tool的安装]
    2. [完成RK3568开发板的烧录]
    3. 鸿蒙开发指导:qr23.cn/AKFP8k参考前往复制转到。
  3. 搭建开发环境。

    1. 开始前请参考[工具准备],完成DevEco Studio的安装和开发环境配置。
    2. 开发环境配置完成后,请参考[使用工程向导]创建工程(模板选择“Empty Ability”),选择JS或者eTS语言开发。
    3. 工程创建完成后,选择使用[真机进行调测]。 2.鸿蒙next文档籽料+mau123789直接去v拿取

搜狗高速浏览器截图20240326151547.png

分布式组网

本章节以系统自带的音乐播放器为例(具体以实际的应用为准),介绍如何完成两台设备的分布式组网。

  1. 硬件准备:准备两台烧录相同的版本系统的RK3568开发板A、B。

  2. 开发板A、B连接同一个WiFi网络。

    打开设置-->WLAN-->点击右侧WiFi开关-->点击目标WiFi并输入密码。

  3. 将设备A,B设置为互相信任的设备。

    • 找到系统应用“音乐”。

    • 设备A打开音乐,点击左下角流转按钮,弹出列表框,在列表中会展示远端设备的id。

    • 选择远端设备B的id,另一台开发板(设备B)会弹出验证的选项框。

    • 设备B点击允许,设备B将会弹出随机PIN码,将设备B的PIN码输入到设备A的PIN码填入框中。

    配网完毕。

代码结构解读

  • [HandleEtsOpenHarmony]
  • [GameEtsOpenHarmony]

本篇Codelab只对核心代码进行讲解,对于完整代码,我们会在参考章节中提供下载方式,首先介绍一下整个工程的代码结构:

└── HandleGameApplication│── GameEtsOpenHarmony│  └── HandleEtsOpenHarmony

其中HandleEtsOpenHarmony为手柄端工程代码,GameEtsOpenHarmony为游戏端工程代码。

HandleEtsOpenHarmony

  • MainAbility:存放应用主页面。

    • pages/index.ets:应用主页面。
    • common/images:存放图片资源的目录。
  • ServiceAbility:存放ServiceAbility相关文件。

    • service.ts:service服务,用于跨设备连接后通讯。

GameEtsOpenHarmony

  • MainAbility:存放应用主页面。

    • pages/index.ets:应用主页面。
    • common/images:存放图片资源。
  • model:存放获取组网内的设备列表相关文件。

    • RemoteDeviceModel.ets:获取组网内的设备列表。
    • GameElement.ets:游戏端界面元素的实体类,用于封装子弹、飞机等元素的属性。
  • ServiceAbility:存放ServiceAbility相关文件。

    • service.ts:service服务,用于跨设备连接后通讯。

实现手柄端功能

  1. 实现布局和样式。

    手柄端有两个功能:向游戏端发送指令和实时获取游戏端得分数据。界面上有三个功能组件:蓝色图形组件用于控制游戏端飞机移动方向,黄色图形组件用于发射子弹,绿色图形组件用于释放技能,效果图如下:

    主要代码如下:

    @Entry
    @Component
    struct Index {
    ...build() {Stack() {...Text('score:' + this.score)...Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Start, justifyContent: FlexAlign.SpaceBetween }) {Stack() {Image('/common/images/bigcircle.png').width(300).height(300)Image('/common/images/smallcircle.png').width(140).height(140).position({ x: this.smallPosX, y: this.smallPosY }) // 30+75-35}...Row() {Image('/common/images/a.png').width(160).height(160).margin({ right: 20, bottom: 80 })Image('/common/images/b.png').width(200).height(200)}.alignItems(VerticalAlign.Bottom)...}}
    }

  2. 实现摇杆功能。

    给摇杆(蓝色小圆图形)添加TouchEvent,动态改变摇杆position属性使摇杆跟随手指移动,主要代码如下:

    onTouchEvent(event: TouchEvent) {switch (event.type) {case TouchType.Down:this.startX = event.touches[0].screenX;this.startY = event.touches[0].screenY;break;case TouchType.Move:this.curX = event.touches[0].screenX;this.curY = event.touches[0].screenY;this.getSmallCurrentPos(this.curX - this.smallR - 60, this.curY - this.smallR - 60)angle = Math.round(this.calculateAngle());break;default:break;}
    }
    

  3. 计算摇杆偏移角度。

    主要代码如下:

    calculateAngle() {var angle = 0var degree = Math.atan(this.getDisAbsY() / this.getDisAbsX()) * 180 / Math.PIvar quadrant = this.quadrant();switch (quadrant) {case this.QUADRANT_1:// 向右上移动angle = degree;break;case this.QUADRANT_2:// 向左上移动angle = 180 - degree;break;case this.QUADRANT_3:// 向左下移动angle = -180 + degree;break;case this.QUADRANT_4:// 向右下移动angle = -degree;break;default:angle = 0;break;}return angle;
    }

  4. 连接游戏端Service。

    当手柄端被游戏端拉起时,获取游戏端传递的数据:游戏端deviceId和分数score。然后通过deviceId连接游戏端Service,主要代码如下:

    aboutToAppear() {// 当被拉起时,通过want传递的参数同步对端界面UIawait featureAbility.getWant((error, want) => {// 远端被拉起后,连接游戏端的serviceif (want.parameters.deviceId) {let remoteDeviceId = want.parameters.deviceIdconnectRemoteService(remoteDeviceId)}});
    }async function connectRemoteService(deviceId) {
    ...await featureAbility.connectAbility({'deviceId': deviceId,'bundleName': "com.huawei.cookbook",'abilityName': "com.huawei.cookbook.ServiceAbility",},{onConnect: onConnectCallback,onDisconnect: onDisconnectCallback,onFailed: onFailedCallback,},);
    }

  5. 通过RPC发送数据到游戏端。

    连接游戏端Service之后,摇杆角度angle和操作类型actionType(1为发射子弹,2为释放技能)发送给游戏端,主要代码如下:

    async function sendMessageToRemoteService() {
    ...let option = new rpc.MessageOption();let data = new rpc.MessageParcel();let reply = new rpc.MessageParcel();data.writeInt(actionType);data.writeInt(angle);await mRemote.sendRequest(1, data, reply, option);
    }

实现游戏端功能

  1. 实现布局和样式。

    游戏界面主要由玩家飞机、敌机、子弹和道具(降落伞)等组成,由于敌机和子弹都是多个的,所以使用ForEach来实现,主要代码如下:

    @Entry
    @Component
    struct Index {build() {Stack() {... ForEach(this.bullets, item => {Image(item.imgSrc).width(item.imgWidth).height(item.imgHeight).position({ x: item.positionX, y: item.positionY })}, item => item.timestamp.toString())ForEach(this.enemyPlanes, item => {Image(item.imgSrc).width(item.imgWidth).height(item.imgHeight).position({ x: item.positionX, y: item.positionY })}, item => item.timestamp.toString())Image('/common/images/planeOne.png').width(this.planeSize).height(this.planeSize).position({ x: this.planePosX, y: this.planePosY }).onTouch((event: TouchEvent) => {this.onTouchEvent(event)})Image('/common/images/props.png').width(this.propsSize).height(this.propsSize).position({ x: this.propsPosX, y: this.propsPosY })...}.height('100%').width('100%')}
    }

  2. 实现游戏端元素动画效果。

    飞机、子弹和道具等元素的移动是通过动态改变Image的position属性来实现的。使用定时器setInterval每隔16ms重新设置界面元素position属性的值,主要实现代码如下:

     startGame() {var that = thissetInterval(function () {   // 每60*16ms创建一个敌机if (that.num % 60 == 0) {that.createEnemyPlane()}// 移动子弹var bulletsTemp: GameElement[] = []for (var i = 0; i < that.bullets.length; i++) {var bullet = that.bullets[i]bullet.positionY -= 8// 当子弹移除屏幕外的时候,释放掉if (bullet.positionY > 0) {bulletsTemp.push(bullet)}}that.bullets = bulletsTemp// 移动飞机var enemyPlanesTemp: GameElement[] = []for (var j = 0; j < that.enemyPlanes.length; j++) {var enemyPlane = that.enemyPlanes[j]enemyPlane.positionY += 6// 当飞机移除屏幕外的时候,释放掉if (enemyPlane.positionY < that.screenHeight) {enemyPlanesTemp.push(enemyPlane)}}that.enemyPlanes = enemyPlanesTemp// 每隔 500*16ms显示降落伞if (that.num % 500 == 0) {that.getPropsFlag = truethat.propsPosY = -that.propsSizethat.propsPosX = Math.round((Math.random() * (that.screenWidth - that.propsSize)))}// 刷新道具位置if (that.propsPosY < that.screenHeight) {that.propsPosY += 6}that.checkCollision()}, 16);}

  3. 判断元素是否发生碰撞。

    在setInterval中改变元素位置的时候同时检测元素之间是否发生碰撞,子弹和敌机发生碰撞则分数值改变(摧毁小飞机加50分,摧毁大飞机加100分),玩家飞机和道具发生碰撞则道具加1,主要实现代码如下:

    checkCollision() {...for (var i = 0; i < this.enemyPlanes.length; i++) {var enemy = this.enemyPlanes[i];for (var j = 0; j < this.bullets.length; j++) {var bullet = this.bullets[j];var inside = this.isInside(bullet, enemy);// 发生碰撞if (inside) {enemy.imgSrc = '/common/images/boom.png'if (enemy.flag == 1) {this.score += 50sendMessageToRemoteService(that.score)} else if (enemy.flag == 2) {this.score += 100sendMessageToRemoteService(that.score)}// 清除子弹this.enemyPlanes.splice(i, 1);i--;enemy.flag = 3// 清除被子弹打中敌机that.bullets.splice(j, 1);j--;}}}// 飞机和降落伞是否发生碰撞var isGetProps = this.isInside(myPlane, props);if (isGetProps && this.getPropsFlag) {this.getPropsFlag = falsethis.bombNum++this.propsPosY = 2000}}

  4. 获取设备列表。

    点击界面右上角的“电脑”图标,调用registerDeviceListCallback()发现设备列表,并弹出设备列表选择框DeviceListDialog ,选择设备后拉起远端FA。DeviceListDialog 主要代码如下:

    @CustomDialog
    export struct DeviceListDialog {controller: CustomDialogControllerbuild() {Column() {Text("选择设备").fontWeight(FontWeight.Bold).fontSize(20).margin({ top: 20, bottom: 10 })List() {ForEach(deviceList, item => {ListItem() {Stack() {Text(item).fontSize(12).margin({ top: 10 })}.onClick(() => {startRemoteAbility(item)this.controller.close();}).padding({ left: 30, right: 30 })}}, item => item.toString())}.height("30%").align(Alignment.TopStart)
    ...}}
    }

  5. 拉起手柄端FA。

    点击设备列表获取远程设备id后,拉起手柄端FA,代码如下:

    function startRemoteAbility(deviceId) {var params = {deviceId: localDeviceId}var wantValue = {bundleName: 'com.huawei.cookbook',abilityName: 'com.huawei.cookbook.MainAbility',deviceId: deviceId,parameters: params};featureAbility.startAbility({want: wantValue}).then((data) => {console.info('[game] featureAbility.startAbility finished, localDeviceId=' + localDeviceId + '----deviceId:' + deviceId);// 拉起远端后,连接远端serviceconnectRemoteService(deviceId)});
    }

  6. 连接手柄端Service。

    拉起手柄端FA后,连接手柄端Service,代码如下:

    async function connectRemoteService(deviceId) {// 连接成功的回调async function onConnectCallback(element, remote) {mRemote = remote;}
    ...if (remoteDeviceModel.deviceList.length === 0) {return;}await featureAbility.connectAbility({'deviceId': deviceId,'bundleName': "com.huawei.cookbook",'abilityName': "com.huawei.cookbook.ServiceAbility",},{onConnect: onConnectCallback,onDisconnect: onDisconnectCallback,onFailed: onFailedCallback,},);
    }

  7. 通过RPC发送数据到手柄端。

    通过RPC将游戏分数发送给手柄端,主要代码如下:

    async function sendMessageToRemoteService(score) {console.log('[game]connectRemoteService sendMessageToRemoteService:')if (mRemote == null) {return;}let option = new rpc.MessageOption();let data = new rpc.MessageParcel();let reply = new rpc.MessageParcel();data.writeInt(score);await mRemote.sendRequest(1, data, reply, option);
    }
    

  8. Service发布公共事件。

    通过Service接收手柄端数据,然后使用CommonEvent模块将数据发送给FA,主要代码如下:

    class GameServiceAbilityStub extends rpc.RemoteObject {
    ...onRemoteRequest(code, data, reply, option) {console.log('[game]Service onRemoteRequest');var publishCallBack;if (code === 1) {// 读取手柄端发送的数据let actionType = data.readInt();let angle = data.readInt();reply.writeInt(100);var params = {actionType: actionType,angle: angle,}var options = {code: 1,data: 'init data',isOrdered: true,bundleName: 'com.huawei.cookbook',parameters: params}publishCallBack = function () {}// 发布公共事件commonEvent.publish("publish_action", options, publishCallBack);} return true;}
    }

  9. FA订阅公共事件。

    订阅公共事件,接收从Service发送的公共事件数据,actionType 为操作类型(1表示发送子弹指令,2表示释放技能指令),angle 为飞机移动的角度。接收到数据后执行手柄端发送的指令:移动玩家飞机、发射子弹和释放技能摧毁所有敌机,主要代码如下:

    subscribeEvent() {
    ...// 订阅公共事件回调function SubscribeCallBack(err, data) {let msgData = data.data;let code = data.code;
    ...// 处理接收到的数据datathat.actionType = data.parameters.actionType;that.angle = data.parameters.angle;if (that.actionType == 1) {that.createBullet()}if (that.actionType == 2) {if (that.bombNum > 0) {that.bombNum--that.destroyAllEnemy()}}if (that.angle != 0) {that.movePlaneByHandle()}}//创建订阅者回调function CreateSubscriberCallBack(err, data) {subscriber = data;//订阅公共事件commonEvent.subscribe(subscriber, SubscribeCallBack);}//创建订阅者commonEvent.createSubscriber(subscribeInfo, CreateSubscriberCallBack);
    }

鸿蒙开发岗位需要掌握那些核心要领?

目前还有很多小伙伴不知道要学习哪些鸿蒙技术?不知道重点掌握哪些?为了避免学习时频繁踩坑,最终浪费大量时间的。

自己学习时必须要有一份实用的鸿蒙(Harmony NEXT)资料非常有必要。 这里我推荐,根据鸿蒙开发官网梳理与华为内部人员的分享总结出的开发文档。内容包含了:【ArkTS、ArkUI、Stage模型、多端部署、分布式应用开发、音频、视频、WebGL、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、Harmony南向开发、鸿蒙项目实战】等技术知识点。

废话就不多说了,接下来好好看下这份资料。

如果你是一名Android、Java、前端等等开发人员,想要转入鸿蒙方向发展。可以直接领取这份资料辅助你的学习。鸿蒙OpenHarmony知识←前往。下面是鸿蒙开发的学习路线图。

针对鸿蒙成长路线打造的鸿蒙学习文档。鸿蒙(OpenHarmony )学习手册(共计1236页)与鸿蒙(OpenHarmony )开发入门教学视频,帮助大家在技术的道路上更进一步。

其中内容包含:

《鸿蒙开发基础》鸿蒙OpenHarmony知识←前往

  1. ArkTS语言
  2. 安装DevEco Studio
  3. 运用你的第一个ArkTS应用
  4. ArkUI声明式UI开发
  5. .……

《鸿蒙开发进阶》鸿蒙OpenHarmony知识←前往

  1. Stage模型入门
  2. 网络管理
  3. 数据管理
  4. 电话服务
  5. 分布式应用开发
  6. 通知与窗口管理
  7. 多媒体技术
  8. 安全技能
  9. 任务管理
  10. WebGL
  11. 国际化开发
  12. 应用测试
  13. DFX面向未来设计
  14. 鸿蒙系统移植和裁剪定制
  15. ……

《鸿蒙开发实战》鸿蒙OpenHarmony知识←前往

  1. ArkTS实践
  2. UIAbility应用
  3. 网络案例
  4. ……

最后

鸿蒙是完全具备无与伦比的机遇和潜力的;预计到年底将有 5,000 款的应用完成原生鸿蒙开发,这么多的应用需要开发,也就意味着需要有更多的鸿蒙人才。鸿蒙开发工程师也将会迎来爆发式的增长,学习鸿蒙势在必行!

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python生成二维码

要在Python中生成二维码&#xff0c;可以使用第三方库qrcode。首先&#xff0c;确保已经安装了qrcode库&#xff1a; pip install qrcode然后&#xff0c;使用以下代码生成二维码&#xff1a; import qrcodedata "https://mp.csdn.net/mp_blog/creation/editor?spm100…

项目7-音乐播放器2(上传音乐+查询音乐+拦截器)

0.加入拦截器 之后就不用对用户是否登录进行判断了 0.1 定义拦截器 0.2 注册拦截器 生效 1.上传音乐的接口设计 请求&#xff1a; { post, /music/upload {singer&#xff0c;MultipartFile file}&#xff0c; } 响应&#xff1a; { "status": 0, "message&…

Promise简单概述

一. Promise是什么&#xff1f; 理解 1.抽象表达&#xff1a; Promise是一门新的技术(ES6规范) Promise是JS中进行异步编程的新解决方案(旧方案是单纯使用回调函数) 异步编程&#xff1a;包括fs文件操作&#xff0c;数据库操作(Mysql)&#xff0c;AJAX&#xff0c;定时器 2.具…

RK3568笔记二十二:基于TACO的垃圾检测和识别

若该文为原创文章&#xff0c;转载请注明原文出处。 基于TACO数据集&#xff0c;使用YOLOv8分割模型进行垃圾检测和识别&#xff0c;并在ATK-RK3568上部署运行。 一、环境 1、测试训练环境&#xff1a;AutoDL. 2、平台&#xff1a;rk3568 3、开发板: ATK-RK3568正点原子板子…

大创项目推荐 深度学习YOLOv5车辆颜色识别检测 - python opencv

文章目录 1 前言2 实现效果3 CNN卷积神经网络4 Yolov56 数据集处理及模型训练5 最后 1 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; **基于深度学习YOLOv5车辆颜色识别检测 ** 该项目较为新颖&#xff0c;适合作为竞赛课题方向&#xff0…

前端开发框架BootStrap

版权声明 本文原创作者&#xff1a;谷哥的小弟作者博客地址&#xff1a;http://blog.csdn.net/lfdfhl BootStrap概述 Bootstrap是一个开源的前端框架&#xff0c;它由Twitter的设计师和开发者创建并维护。Bootstrap提供了许多现成的Web组件&#xff0c;可帮助开发者快速设计和…

36、二叉树-二叉树的中序遍历

思路&#xff1a; 二叉树的遍历可以有 前序&#xff0c;中序&#xff0c;后序&#xff0c;层序遍历。 前序&#xff1a;头左右中序&#xff1a;左头右后序&#xff1a;左右头层序:从左往右依次遍历 实现方式&#xff1a; 递归通过栈结构便于回溯 代码如下&#xff1a; c…

软件开发安全设计方案

2.1.应用系统架构安全设计要求 2.2.应用系统软件功能安全设计要求 2.3.应用系统存储安全设计要求 2.4.应用系统通讯安全设计要求 2.5.应用系统数据库安全设计要求 2.6.应用系统数据安全设计要求 软件开发全资料获取&#xff1a;软件开发全套资料_软件开发资料-CSDN博客https://…

【C++学习】C++IO流

这里写目录标题 &#x1f680;C语言的输入与输出&#x1f680;什么是流&#x1f680;CIO流&#x1f680;C标准IO流&#x1f680;C文件IO流 &#x1f680;C语言的输入与输出 C语言中我们用到的最频繁的输入输出方式就是scanf ()与printf()。 scanf(): 从标准输入设备(键盘)读取…

Go Plugin:动态模块的加载与问题解析_go语言加载动态库的工具(1)

先自我介绍一下&#xff0c;小编浙江大学毕业&#xff0c;去过华为、字节跳动等大厂&#xff0c;目前阿里P7 深知大多数程序员&#xff0c;想要提升技能&#xff0c;往往是自己摸索成长&#xff0c;但自己不成体系的自学效果低效又漫长&#xff0c;而且极易碰到天花板技术停滞…

flutter书架形式格口的动态创建(行、列数,是否全选的配置)

根据传入的行列数创建不同格口数量的书架 左图&#xff1a;5行3列、右图&#xff1a;3行3列 代码 import package:jade/bean/experienceStation/ExpCellSpecsBean.dart; import package:jade/configs/PathConfig.dart; import package:jade/utils/DialogUtils.dart; import p…

springboot整合dubbo实现RPC服务远程调用

一、dubbo简介 1.什么是dubbo Apache Dubbo是一款微服务开发框架&#xff0c;他提供了RPC通信与微服务治理两大关键能力。有着远程发现与通信的能力&#xff0c;可以实现服务注册、负载均衡、流量调度等服务治理诉求。 2.dubbo基本工作原理 Contaniner:容器Provider&#xf…

Linux内核之WRITE_ONCE用法实例(四十八)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a;多媒…

分析ARP解析过程

1、实验环境 主机A和主机B连接到交换机&#xff0c;并与一台路由器互连&#xff0c;如图7.17所示&#xff0c;路由器充当网关。 图7.17 实验案例一示意图 2、需求描述 查看 ARP 相关信息,熟悉在PC 和 Cisco 设备上的常用命令,设置主机A和主机B为同一个网段网关设置为路由接…

【Conda基础命令】使用conda创建、查看、删除虚拟环境及可能的报错处理

文章目录 前言&#xff08;1&#xff09; 在默认路径下创建一个新的虚拟环境&#xff08;2&#xff09; 查看已有的虚拟环境&#xff08;3&#xff09; 删除已有的虚拟环境&#xff08;谨慎操作&#xff09;&#xff08;4&#xff09;激活虚拟环境&#xff08;5&#xff09;退出…

OpenCV轻松入门(八)——图片卷积

对图像和滤波矩阵进行逐个元素相乘再求和的操作就相当于将一个二维的函数移动到另一个二维函数的所有位置&#xff0c;这个操作就叫卷积。 卷积需要4个嵌套循环&#xff0c;所以它并不快&#xff0c;除非我们使用很小的卷积核。这里一般使用3x3或者5x5 图像滤波 图像滤波是尽…

P9241 [蓝桥杯 2023 省 B] 飞机降落

原题链接&#xff1a;[蓝桥杯 2023 省 B] 飞机降落 - 洛谷 目录 1. 题目描述 2. 思路分析 3. 代码实现 1. 题目描述 2. 思路分析 dfs全排列的变形题。 因为最后问飞机是否降落&#xff0c;并且一架飞机降落完毕时另一架飞机才能降落。所以我们设置dfs的两个变量cnt为安全…

通过adb 命令打印安装在第三方模拟器上的log

1&#xff0c;环境&#xff1a;Windows 11 &#xff0c;第三方模拟器 网易的MuMu 步骤&#xff1a; 1&#xff0c;打开cmd&#xff0c;输入 adb connect 172.0.0.1:7555 2&#xff0c;在cmd&#xff0c;再次输入adb logcat 回车

案例分析-redis

案例需求&#xff1a;在7002这个slave节点执行手动故障转移&#xff0c;重新夺回master地位 步骤如下&#xff1a; 1&#xff09;利用redis-cli连接7002这个节点 2&#xff09;执行cluster failover命令 如图&#xff1a; 效果&#xff1a; 4.5.RedisTemplate访问分片集群 …

一个文生视频MoneyPrinterTurbo项目解析

最近抖音剪映发布了图文生成视频功能,同时百家号也有这个功能,这个可以看做是一个开源的实现,一起看看它的原理吧~ 一句话提示词 大模型生成文案 百家号生成视频效果 MoneyPrinterTurbo生成视频效果 天空为什么是蓝色的? 天空之所以呈现蓝色,是因为大气中的分子和小粒子会…