当前位置: 首页 > article >正文

【cocos官方案例改】跳跃牢猫

自制游戏【跳跃牢烟】

案例解析

案例需求,点击鼠标控制白块左右。

资源管理器部分

在body创建一个2d精灵用作玩家。

在地下在创建一个2d精灵用来代表地面。

在body下挂在脚本。

全部脚本如下

(在二次进行复刻时候,发现把代码复制上去无法运行,原来cocos的引入,需要每次在vscode里面挨个打的时候将会自动添加引入,如果直接甩给它,他不会引入任何模块。)

import { _decorator, Component, EventMouse, Input, input, Node } from 'cc';

const { ccclass, property } = _decorator;

 

@ccclass('NewComponent')

export class NewComponent extends Component {

  start() {

    input.on(Input.EventType.MOUSE_DOWN,this.IKUN,this)

  }

  IKUN(event:EventMouse){

    if(event.getButton()==2){

      this.jump(2)

    }

    if(event.getButton()==0){

      this.jump(0)

    }

  }

  jump(kun:number){

    if(kun==2){

      const cur = this.node.position;

      this.node.setPosition(cur.x+40,cur.y,cur.z);

    }

    if(kun==0){

      const cur = this.node.position;

      this.node.setPosition(cur.x-40,cur.y,cur.z);

    }

 

  }

  // protected iikun():void{

  //  input.off(Input.EventType.MOUSE_DOWN,this.IKUN,this);

  // }

  update(deltaTime: number) {

    

  }

}

分段拆解

导入模块

typescript

import { _decorator, Component, EventMouse, Input, input, Node } from 'cc';

const { ccclass, property } = _decorator;

从 'cc' 模块导入了 _decorator、Component、EventMouse、Input、input、Node 等类将 

_decorator 中的 ccclass 和 property 解构出来,用于后续的类装饰。

start 方法

typescript

start() {

    input.on(Input.EventType.MOUSE_DOWN, this.IKUN, this)}

start 方法在组件所在的节点被激活时调用一次。

使用 input.on 方法监听鼠标按下事件 Input.EventType.MOUSE_DOWN,当鼠标按下时,会调用 this.IKUN 方法,并且将当前组件实例 this 作为上下文传递。

IKUN 方法

typescript

IKUN(event: EventMouse) {

    if (event.getButton() == 2) {

        this.jump(2)

    }

    if (event.getButton() == 0) {

        this.jump(0)

    }}

· 当 MOUSE_DOWN 事件发生时,输入系统会调用 IKUN 方法,并将生成的 EventMouse 事件对象作为参数传递给 IKUN 方法,这就是 event 的来源。

· IKUN 方法接收一个 EventMouse 类型的参数。

· 为什么值是eventmouse呢,因为传过来的值是一个鼠标事件(MOUSE_DOWN)嘛

event: EventMouse)也就是说,这个形参的值,是一个EventMouse类型的(鼠标类型)

· 通过 event.getButton() ,意思是获取event里面的getbutton()的值。

· 获取鼠标按下的按钮,2 表示鼠标右键,0 表示鼠标左键。

· 根据按下的按钮不同,调用 this.jump 方法,并传递相应的参数 2 或 0。

jump 方法

typescript

jump(kun: number) {

    if (kun == 2) {

        const cur = this.node.position;

        this.node.setPosition(cur.x + 40, cur.y, cur.z);

    }

    if (kun == 0) {

        const cur = this.node.position;

        this.node.setPosition(cur.x - 40, cur.y, cur.z);

    }}

· jump 方法接收一个 number 类型的参数 kun。

· 如果 kun 为 2,表示鼠标右键按下,将当前节点的 x 坐标增加 40。

· 如果 kun 为 0,表示鼠标左键按下,将当前节点的 x 坐标减少 40。

· 通过 this.node.position 获取当前节点的位置,然后使用 this.node.setPosition 方法设置新的位置。

update 方法

update 方法在每一帧都会被调用,参数 deltaTime 表示从上一帧到当前帧的时间间隔。

· 该方法目前为空,没有实现任何功能。

注释代码

// protected iikun():void{//    input.off(Input.EventType.MOUSE_DOWN,this.IKUN,this);// }

· 这段代码被注释掉了,如果取消注释,iikun 方法会取消监听鼠标按下事件 Input.EventType.MOUSE_DOWN,参数与 input.on 方法相对应,用于移除之前添加的事件监听器

2d视野下的调整

项目设置-》项目数据-》设计宽度(高度)

视野跟随指定物体移动

在层级管理器里面把摄像机(camera)放在指定物体下面

渲染画布外面的部分

Canvas-》属性检查器-》xx.canvas->align canvas wlith screen

小方块缓慢的移动

凭借上述的代码,可以实现小方块的移动,但这样的结果过于僵硬,我们可以通过别的方法来让小方块自然一些。

首先看全部的代码,随后进行分段讲解。

import { _decorator, Component, EventMouse, Input, input, Node } from 'cc';

const { ccclass, property } = _decorator;

@ccclass('NewComponent')

export class NewComponent extends Component {

  private starikun = false;

  private _jumptime = 0.2;

  private _ttime = 0;

  private _ikunsp =0;

  start() {

    input.on(Input.EventType.MOUSE_DOWN,this.IKUN,this)

  }

  IKUN(event:EventMouse){

    if(event.getButton()==2){

      this.jump(2)

    }

    if(event.getButton()==0){

      this.jump(-2)

    }

  }

  jump(kun:number){

    

    this.starikun = true;

    this._ttime = 0;

    this._ikunsp = kun*20/this._jumptime;

  }

  // protected iikun():void{

  //  input.off(Input.EventType.MOUSE_DOWN,this.IKUN,this);

  // }

  update(dt: number) {

   if(this.starikun=true){

    this._ttime+=dt;

    if(this._ttime>this._jumptime){

      this.starikun=false;

    }else{

      const cupikun =this.node.position;

      this.node.setPosition(cupikun.x+this._ikunsp*dt,cupikun.y,cupikun.z);

    }

   } 

  }

}

第一段,基本上没有区别,单纯的增加了几个变量

import { _decorator, Component, EventMouse, Input, input, Node } from 'cc';

const { ccclass, property } = _decorator;

@ccclass('NewComponent')

export class NewComponent extends Component {

   private starikun = false;

  private _jumptime = 0.2;

  private _ttime = 0;

  private _ikunsp =0;

  start() {

    input.on(Input.EventType.MOUSE_DOWN,this.IKUN,this)

  }

  IKUN(event:EventMouse){

    if(event.getButton()==2){

      this.jump(2)

    }

    if(event.getButton()==0){

      this.jump(-2)

    }

  }

starikun 用来判断到时候该不该移动

_jumptime是小方块移动的时候占据多少时间

Titime是当作计时器使用

Ikunsp用来当作速度

第二段

把之前让小方块移动的代码删除了,换做更为复杂的代码,但是这让小方块看起来流畅很多。

这将会使用内置函数update,所以jump函数的作用不再是直接控制移动了。

jump(kun:number){

    

     this.starikun = true;

    this._ttime = 0;

    this._ikunsp = kun*20/this._jumptime;  }

starikun 更改为true,下面有用

_ttime 表示时间为0,初始化时间。

this._ikunsp = kun*20/this._jumptime;  }

是求速度的,因为速度等于路程/时间

最后一段是利用update函数,因为updata函数每一帧都会执行一次,借助特性来使达到想要的缓慢到达目标地点的方块方法。

 update(dt: number) {

   if(this.starikun=true){

    this._ttime+=dt;

    

    if(this._ttime>this._jumptime){

      this.starikun=false;

    }else{

      const cupikun =this.node.position;

      this.node.setPosition(cupikun.x+this._ikunsp*dt,cupikun.y,cupikun.z);

    }

   } 

  }

 update(dt: number) ,把每针的时间定义为dt。

  if(this.starikun=true),starikun变量等于true时候执行。下面全部的函数。

 this._ttime+=dt;使计时器增加,每次增加一帧的时间。

下面进行逻辑判断,如果计时器的时间大于要求的跳跃时间,那么starikun改变,也就进行运动了。

如果没有大于,那么每次都使当前时间乘速度,让小球位移。因为一帧一帧移动,所以看起来会缓和许多,不会过于生硬。

但这时候通过编辑器预览发现小方块的移动并非是完全与速度与时间的乘积相等。

我推测是帧率的时间问题,可能大个几毫秒或者少于几毫秒。

具体的解决措施是将小方块最后移动到该移动的位置。

如何让小方块移动的更加精准

在start函数上方定义两个私有变量。一个是用来保存当前位置,一个是用来保存小方块最终移动位置。

 private _zdp = new Vec3;

 private _zd = new Vec3;

_zdp是最终的位置

_zd用来存储当前位置。

Vec3是一个存储三维数据的一个变量。

New是对象与类的基本知识。

在jump函数的部分让_zd获取当前的位置,让_zdp获取最终位置。

this._zd = this.node.position;

//this.node.getPosition(this._zd);

这两种方法都可以。

一个是把当前的位置赋值给变量。

一个是把node当前的位置通过getposition传递给this.zd。

之后是推测最终位置,把最终地点的坐标传递给_zdp

 this._zdp = new Vec3(this._zd.x+jumpp,this._zd.y,this._zd.z);

其中的jumpp是把固定的距离变成了一个变量,这样想更改距离的时候就不用挨个去更改了,只要直接改一下jumpp的数值就好。

在jump函数第一行定义了一个   const jumpp = kun*20;

其中 this._zdp = new Vec3(this._zd.x+jumpp,this._zd.y,this._zd.z);也可以用vec.add来替换。

Vec3.add(this._zdp,this._zd,new Vec3(jumpp,0,0));

这段代码表示,将第二位与第三位参数相加并传递给第一个参数。

然后就是等函数整体运行之后把位置改变为_zdp位置。

在updata函数里面的 if(this._ttime>this._jumptime)的末尾加上一个

this.node.setPosition(this._zdp);

解决重复按下鼠标导致位置发生偏移的问题。

在jump函数下,第一行增加一句

if(this.starikun)return

意思是starikun为true的话后面代码直接不执行,涉及到if基本知识和return基本知识。

跳跃动画

添加跳跃动画组件

首先选中要添加跳跃动画的组件,在下方动画编辑器里面为其创建,或者在选中组件的时候在右侧添加动画组件(animation)

创建动画剪辑资源

在下方动画编辑器之中创建动画剪辑资源,这时候观测到有两个明显属性。

1节点列表2属性列表

选中某个节点或子节点,对其该节点的某个或多个属性进行修改。

属性列表关键帧

剪辑基础知识,过。

通过简单捅咕即可学会创建一个动画,接下来使代码与动画连接。

不要忘记保存动画,在场景编辑器的那个。

这时候如果选择已经加载好动画的节点,为其animation属性勾选上加载后跳动,那将会在加载此节点的时候执行一次默认动画。

代码部分。

引入动画模块,使其节点可以加载刚才的动画。

@property(Animation)

public bodyiAnim:Animation =null;

@property是一个装饰器(decorator),它主要用于将一个类的成员变量进行属性化处理。

属性化后就可以在节点的部分直接看见。

Animation 在这里是一个类型说明,表明了被装饰的成员变量的类型。

这时候观测该节点的父节点,单击后查看右侧部分,就会神奇的发现多了个节点属性。

注意,在引入Animation容易产生错误,因为有同名的其他,引入cc下的才是正确的。

扩展

在上述学习之中已经了解@property是cocos之中将一个类的成员变量进行属性化处理。尝试自定义一个进行尝试。

代码部分

@property(Number)

   myNumber: number = 42;

返回父节点进行观测,发现新增一个属性,名称为myNumber,数值是42。

在写完代码后,返回cocos属性面板,这时候bodyiAnim=null;,将存在动画的子节点拖入该区域。

当你把节点拖入 bodyiAnim 属性时,实际上是在告诉 Cocos:“我希望 bodyiAnim 变量引用这个节点上的动画组件。

在跳跃时候播放动画

在jump函数里面,也就是准备跳的时候执行动画的播放即可。

代码部分

This.bodyiAnim.play(“动画名”);

这时候运行就可以跳跃了。

接下来目的是创建一个新的动画,让跳一步和两步的动画分开,并在程序中进行判断,如果是一步调用那个动画,两部调用那个动画。

首先是如何创建一个新的动画,在选中节点后,在下方动画编辑器之中进行,动画剪辑-》下标-》新建剪辑动画.

代码部分。

在之前This.bodyiAnim.play(“动画名”);进行修改,使其增加一个判断,如果是左键播放什么动画,右键播放什么动画。

if(kun==2){

        this.bodyani.play("animation");

    }

    if(kun==4){

        this.bodyani.play("animation-001");

    }

这时候发现动画的时间和移动的时间又不一样了,那么可以选择更改动画,让动画时间与移动的时间相等,或者让移动时间等于动画的时间。

这里根据教程使用的是让移动时间等于动画时间。

代码部分

const aniname= kun==2?'animation':'animation-001';

const anistate=this.bodyani.getState(aniname);

this.jumptime=anistate.duration;

const aniname= kun==2?'animation':'animation-001';利用三元表达式,如果kun的值是2,那么返回值animation,否则返回值animation-001。并把值返回给常量aniname。

getState 通常可以被理解为 “获取状态”。翻译一下就是获取bodyani下的aniname的动画的状态。

最后这行代码是把找到的动画状态(anistate)里的 duration 属性的值取出来,存储在 this.jumptime 中。

在此时,前面写的if分支if(kun==2){可以删除了,换成this.bodyani.play(aniname);就可以了。

随机生成地图

生成预制体

在层级管理器之中将地面拖入到资源管理器之中,这会生成一个预制体。

创建一个新的脚本和一个新的空节点,将脚本挂在到新的节点上。

在脚本内需要对预制体进行引用,还要创建一个参数用来保存到底生成多少格子,将他们属性化是一个很好的方法。

代码部分

 @property(Prefab)

    public boxprefab:Prefab =null;

    @property

    public roalength =50;

将资源管理器之中准备好的预制体地面放进刚才创建的节点的刚刚代码创建的属性值之上。

然后创建一个枚举类型。用来表示方块应该是那种状态。

代码部分

enum bolkeType{

    BT_none,

BT_white}

enum 是枚举(Enumeration)的缩写,它是一种数据类型,用于定义一组具名的常量。在这个例子中,bolkeType 是枚举的名称。

BT_none 和 BT_white 是 bolkeType 枚举中的成员。

使用 enum 定义枚举时,这些成员会被自动赋值为数字。BT_none 会被赋值为 0,BT_white 会被赋值为 1。

创建一个 _road变量,让其存储刚才定义的枚举类型。

代码部分

 private _road:bolkeType[]=[];

bolkeType[]:这是变量的类型,表明 _road 是一个数组,该数组的元素类型是 之前定义的bolkeType 枚举类型里面的类型。这意味着该数组中的每个元素都应该是 bolkeType 枚举中定义的成员,如 BT_none 或 BT_white。

在start函数里面调用一个自创的函数,具体操作将写在这里。

代码部分

start() {

        this.generate();

    }

    generate(){

        this.node.removeAllChildren();

This._road=[];

this._road.push(bolkeType.BT_white);

}

 this.node.removeAllChildren();销毁该节点下所有子节点。防止被多次调用。This._road同理

push() 是数组的一个内置方法,它的作用是向数组的末尾添加一个元素。

循环生成道路方块。

接下来通过代码来生成地面方块,通过for循环可以简单构成下面代码,这个循环存在于generate之中。

for(let i=1;i<this.roalength;i++){

        }

然后通过生成一个随机的数值,来确定生成哪一个地板块。

for(let i=1;i<this.roalength;i++){

            //Math.round(Math.random());

           this._road.push( Math.random()<0.5?0:1);

        }

Math.random() 是一个 JavaScript 内置的方法,它会生成一个范围在 [0, 1] 之间的随机浮点数,即大于或等于 0 且小于 1 的随机数。

Math.random() < 0.5? 0 : 1:

这是一个三元运算符。它会检查 Math.random() 的结果是否小于 0.5。如果小于 0.5,表达式的值为 0;如果大于或等于 0.5,表达式的值为 1。

Math.round():

这也是 JavaScript 中的一个内置函数,它的作用是将一个数字四舍五入为最接近的整数。对于 Math.round(x),如果 x 的小数部分小于 0.5,则将 x 向下取整;如果 x 的小数部分大于或等于 0.5,则将 x 向上取整。

但要考虑如果连续生成两个块为空,那么将无法进行,所以要进行逻辑判断,如果上一个为空块,则这次必须是白块。

代码部分

for(let i=1;i<this.roalength;i++){

            if(this._road[i-1]==bolkeType.BT_none){

                this._road.push(bolkeType.BT_white);

            }else{

                this._road.push( Math.random()<0.5?0:1);

            }

        }

上述代码是生成了小方块应该出现的类型,但是并没有真正的去生成方块,那么通过应该出现的类型来简单生成方块。

首先通过for循环去遍历,然后通过判断是否应该生成白块来确定方块的生成。

 for( let j=1;j<this.roalength;j++){

            if(this._road[j]==bolkeType.BT_white){

                const box =instantiate(this.boxprefab);

                box.setParent(this.node);

                box.setPosition(j*40,0,0);

            }

        }

if (this._road[j] == bolkeType.BT_white):

this._road[j]:从 this._road 数组中取出索引为 j 的元素。

bolkeType.BT_white:这是之前定义的枚举类型 bolkeType 中的一个枚举成员。

这里的条件判断是为了检查 this._road[j] 是否等于 bolkeType.BT_white,如果相等,则执行 if 语句块内的代码。

this.boxprefab 是一个预制体,类似于一个魔法模具。

instantiate 函数根据 this.boxprefab 创建一个新的对象,这个对象存储在 box 中,如同用模具做出一个新的物品。

setParent(this.node) 就像是给这个 “饼干” 找一个 “盘子”。this.node 就是这个 “盘子”,把 box 放在 this.node 下面,就表示让 box 成为 this.node 的子节点

box.setParent(this.node):将 box 的父节点设置为 this.node。这在游戏开发或节点树结构中很常见,用于组织和管理对象的层次结构。

box.setPosition(j * 40, 0, 0);:

box.setPosition(j * 40, 0, 0):调用 box 的 setPosition 方法,将 box 的位置设置为 (j * 40, 0, 0)。这里的 j * 40 表示 x 轴上的位置,根据 j 的不同会有所变化,而 y 和 z 轴的位置始终为 0。 就是在给这个 “饼干” 找到一个合适的位置。

创建ui

在场景的根节点处,再次创建一个画布节点,用于创建ui等,与之前的游戏画布节点呈现兄弟关系。

在ui画布下面创建一个空节点,在次空节点上创建一个精灵图。

找一个图片当作背景,对其进行拉伸处理,在精灵图属性之中,UItransform里面content sizi属性进行更改。

对精灵图的精灵属性进行修改,让其type属性更改为 SLICED 将鼠标悬停到type属性上的三个点,系统会说明该属性的用处。

创建一个开始按钮,一个积分器的文本label。

渲染问题

当两个摄像机模块存在时候,会导致一个物体被渲染两次,造成非常鬼畜的样子。

选择摄像机,更改其属性,Visibility。这将会告诉摄像机,该摄像机渲染那些类型的层。

选择画布,更改其属性,node属性的layer属性。告诉画布,其下的子节点包括自身是属于什么layer。

将游戏的那区域改为defxxx层,记得勾选连同子节点一起更改。

就是让一个摄像机渲染ui,一个渲染游戏,画布和摄像机为一个组合,这时候总共两个组合,画布下的所有东西定义为一个图层组,另一个也是,让摄像机分别只渲染自己组的画布。

返回之前写地面的脚本。

定义一个枚举类型,已用来保存游戏状态。

代码部分

enum Gamestate{

    GS_ui,

    GS_PLAYER

}

如果是ui状态,那么点击不应该触发小方块跳动,如果是play状态,那么那些ui组件应该隐藏。

设置一个方法,方法内判断当前状态,是Gs-ui还是gs_player

代码部分

start() {

          this.setcurstate(Gamestate.GS_ui);

    }

    setcurstate(vl:Gamestate){

        if(vl===Gamestate.GS_ui){

            this.generate();

        }else if(vl===Gamestate.GS_PLAYER){

        }

    }

这里更改了原先的start()方法,原先的start()方法会直接调用 this.generate();来生成地面。

现在的逻辑是判断是什么状态,再决定生不生成地面。

那么在vl===Gamestate.GS_ui的时候,需要让其禁用掉鼠标的监听。

返回让小方块跳动的代码部分。

取消掉star()开始函数里面的一切。

创建一个公共类型的函数,如果函数内的值为真,注册监听函数,如果为假,取消掉注册函数。

返回地面生成的脚本,添加一个引入。这里将会引入小方块脚本。

然后看之前写的setcurstate函数部分,通过下面的方法来控制另一个脚本的值。

两者有唏嘘差别,具体写时候具体理解。

将层级管理器的小方块节点引入。

之后处理对于ui界面的引用

将层级管理器的ui部分拖拽进去。

更改之前的setcurstate部分,使其让ui部分隐藏

在按钮部分,选择其属性,将cilick events设置为1。

这时候可以设置激活那个节点的哪个属性的那个方法。

让其调用地面脚本的属性。

在小方块的脚本上创建一个公共变量,默认值为0,在每次跳动时候加上跳动的步数,然后创建一个监听,在每次小方块结束移动时候。在使用地面脚本进行监听该事件。

 创建一个公共变量

public fenshu:number=0;

每次跳动时候加上跳动的步数

 this.fenshu+=xx;

然后创建一个监听事件,让地面脚本去监听这个fenshu

 this.node.emit("jumpend",this.fenshu);

这个是放在update函数里面的跳跃结束时候的下面。

if(this.stazz==true){

            if(this.tti>this.time){

                this.stazz=false;

                this.node.setPosition(this.zzwz);

                this.node.emit("jumpend",this.fenshu);

this.node.emit() 是 Cocos Creator 中的一个方法,用于在当前节点上触发一个自定义事件。

事件的名称是 "jumpend",后面跟着的是传递给事件处理程序的参数 this.fenshu。

然后回到地面脚本,在start监听上面的参数。

因为之前引入过小方块脚本,所以直接监听即可。

this.player.node.on("jumpend",this.onjumpend,this);

this.player.node 表示获取 this.player 所引用的节点。

然后,通过调用 on 方法,将一个名为 jumpend 的事件绑定到该节点上。当这个节点上触发 jumpend 事件时,就会调用 this.onjumpend 方法。

创建一个onjumpend方法。

 onjumpend(value:number){

        this.ui_labl.string=value.toString();

}

ui_labl之前没有,是新创建的,创建一个公共变量ui_labl,用于引用ui界面的文本,该文本作为积分器使用。

返回cocos的层级管理器,创建一个label。

然后回到代码部分,把.ui_labl属性化,将label拖入进去。

这样,游戏开始时候进行一个监听,监听的代码又会改变label节点的内容,每次小方块停止移动都会发送一个信号,然后被监听到,然后监听的代码又会改变label节点的内容......

当完成上述代码,游戏只差最后一个是否失败,以及是否通关的判定了,大段代码如下。

这时候发现路并没有回归原点,通过在小方块里面创建一个公用变量,将当前节点的位置更改为0.将之前传参的分数,也设置为0.

 public endfang(){

            this.node.setPosition(0,0,0);

            this.fenshu=0;

        }

然后在地面脚本的判断游戏状态(判断当前是ui还是游戏的那个)里面进行一个调用,让每次生成前先归零参数。

 setcurstate(vl:Gamestate){

        if(vl===Gamestate.GS_ui){

            this.player.endfang();

这时候,每次死亡后发现计数器并不会直接为0,实际上参数已经为0了,但是没有传输过去,所以需要一个手动的更新。

setcurstate(vl:Gamestate){

        if(vl===Gamestate.GS_ui){

            this.player.endfang();

            this.ui_labl.string='0';

相关文章:

【cocos官方案例改】跳跃牢猫

自制游戏【跳跃牢烟】 案例解析 案例需求&#xff0c;点击鼠标控制白块左右。 资源管理器部分 在body创建一个2d精灵用作玩家。 在地下在创建一个2d精灵用来代表地面。 在body下挂在脚本。 全部脚本如下 &#xff08;在二次进行复刻时候&#xff0c;发现把代码复制上去无法…...

docker安装nacos2.2.4详解(含:nacos容器启动参数、环境变量、常见问题整理)

一、镜像下载 1、在线下载 在一台能连外网的linux上执行docker镜像拉取命令 docker pull nacos:2.2.4 2、离线包下载 两种方式&#xff1a; 方式一&#xff1a; -&#xff09;在一台能连外网的linux上安装docker执行第一步的命令下载镜像 -&#xff09;导出 # 导出镜像到…...

使用 postman 测试思源笔记接口

思源笔记 API 权鉴 官方文档-中文&#xff1a;https://github.com/siyuan-note/siyuan/blob/master/API_zh_CN.md 权鉴相关介绍截图&#xff1a; 对应的xxx&#xff0c;在软件中查看 如上图&#xff1a;在每次发送 API 请求时&#xff0c;需要在 Header 中添加 以下键值对&a…...

RK3568使用QT操作LED灯

文章目录 一、QT中操作硬件设备思路Linux 中的设备文件操作硬件设备的思路1. 打开设备文件2. 写入数据到设备3. 从设备读取数据4. 设备控制5. 异常处理在 Qt 中操作设备的典型步骤实际应用中的例子:控制 LED总结二、QT实战操作LED灯设备1. `mainwindow.h` 头文件2. `mainwindo…...

51单片机开发——I2C通信接口

I2C是微电子通信控制领域广泛采用的一种总线标准。 起始和停止信号&#xff1a; void iic_start(void) {IIC_SDA1;//如果把该条语句放在SCL后面&#xff0c;第二次读写会出现问题delay_10us(1);IIC_SCL1;delay_10us(1);IIC_SDA0; //当SCL为高电平时&#xff0c;SDA由高变为低d…...

GitHub Actions定时任务配置完全指南:从Cron语法到实战示例

你好&#xff0c;我是悦创。 博客网站&#xff1a;https://blog.bornforthis.cn/ 本教程将详细讲解如何在GitHub Actions中配置定时任务&#xff08;Scheduled Tasks&#xff09;&#xff0c;帮助你掌握 Cron 表达式的编写规则和实际应用场景。 一、定时任务基础配置 1.1 核…...

【网络】3.HTTP(讲解HTTP协议和写HTTP服务)

目录 1 认识URL1.1 URI的格式 2 HTTP协议2.1 请求报文2.2 响应报文 3 模拟HTTP3.1 Socket.hpp3.2 HttpServer.hpp3.2.1 start()3.2.2 ThreadRun()3.2.3 HandlerHttp&#xff08;&#xff09; 总结 1 认识URL 什么是URI&#xff1f; URI 是 Uniform Resource Identifier的缩写&…...

在K8s中部署动态nfs存储provisioner

背景 之前&#xff0c;我已经在一台worker node上安装了local lvm 的provisioner来模拟需要本地高IOPS的数据库等stafeful应用的实现。 为了后续给虚拟机里的K8s集群安装可用的metrics和logs监控系统&#xff08;metrics和logs的时序数据库需要永久存储&#xff09;&#xff0…...

优雅管理Python2 and python3

python2 和 python3&#xff0c; 由于没有像其他软件的向下兼容&#xff0c;必须同时安装Python2 和Python3 &#xff0c;介绍在linux和windows下优雅管理。 一、linux中安装Python2和Python3 linux 中用conda 创建虚拟环境&#xff0c;来管理不同版版工具 由于主流使用Python3…...

创建与管理MySQL数据库

数据库是现代应用程序的核心部分,无论是Web开发、数据分析还是企业级应用,数据库的创建与管理是基础且关键的技能。本教程旨在帮助自学编程的学习者掌握如何通过SQL命令创建、管理和操作数据库。通过本教程,可以学会如何创建数据库、查看已有数据库、选择数据库以及删除不再…...

基于微信小程序的辅助教学系统的设计与实现

标题:基于微信小程序的辅助教学系统的设计与实现 内容:1.摘要 摘要&#xff1a;随着移动互联网的普及和微信小程序的兴起&#xff0c;基于微信小程序的辅助教学系统成为了教育领域的一个新的研究热点。本文旨在设计和实现一个基于微信小程序的辅助教学系统&#xff0c;以提高教…...

Python从0到100(八十六):神经网络-ShuffleNet通道混合轻量级网络的深入介绍

前言&#xff1a; 零基础学Python&#xff1a;Python从0到100最新最全教程。 想做这件事情很久了&#xff0c;这次我更新了自己所写过的所有博客&#xff0c;汇集成了Python从0到100&#xff0c;共一百节课&#xff0c;帮助大家一个月时间里从零基础到学习Python基础语法、Pyth…...

网络模型简介:OSI七层模型与TCP/IP模型

计算机网络是现代信息社会的基石&#xff0c;而网络通信的基础在于理解网络模型。网络模型是对通信过程的抽象&#xff0c;它帮助我们理解数据从源到目的地的传输过程。常见的网络模型有 OSI 七层模型 和 TCP/IP 模型&#xff0c;这两种模型在理论和实践中都起着重要作用。 一、…...

大模型本地化部署(Ollama + Open-WebUI)

文章目录 环境准备下载Ollama模型下载下载Open-WebUI 本地化部署的Web图形化界面本地模型联网查询安装 Docker安装 SearXNG本地模型联网查询 环境准备 下载Ollama 下载地址&#xff1a;Ollama网址 安装完成后&#xff0c;命令行里执行命令 ollama -v查看是否安装成功。安装成…...

Java 性能优化与新特性

Java学习资料 Java学习资料 Java学习资料 一、引言 Java 作为一门广泛应用于企业级开发、移动应用、大数据等多个领域的编程语言&#xff0c;其性能和特性一直是开发者关注的重点。随着软件系统的规模和复杂度不断增加&#xff0c;对 Java 程序性能的要求也越来越高。同时&a…...

【Linux系统】进程间通信:共享内存

认识共享内存 通过 一些系统调用&#xff0c;在物理内存中开辟一块空间&#xff0c;然后将该空间的起始地址&#xff0c;通过页表映射到两个进程的虚拟地址空间的共享区中&#xff0c;这样不就共享了一块空间吗&#xff01;&#xff01;&#xff01; 这种技术就是共享内存&am…...

渗透测试之WAF组合条件绕过方式手法详解以及SQL注入参数污染绕过

目录 组合绕过waf ​先看一些语句 绕过方式 我给出的注入语句是&#xff1a; 这里要注意的几点是&#xff1a; 组合绕过方式 完整过狗注入语句集合 http请求分块传输方法 其它方式绕过 http参数污染绕过waf 面试题:如何参数污染绕过waf 可以通过http参数污染绕过wa…...

oracl:多表查询>>表连接[内连接,外连接,交叉连接,自连接,自然连接,等值连接和不等值连接]

SQL&#xff08;Structured Query Language&#xff0c;结构化查询语言&#xff09;是一种用于管理和操作关系数据库的标准编程语言。 sql分类: 数据查询语言&#xff08;DQL - Data Query Language&#xff09; 查询的关键词 select 多表查询>>表连接 表连接: 把2个…...

Day31-【AI思考】-关键支点识别与战略聚焦框架

文章目录 关键支点识别与战略聚焦框架**第一步&#xff1a;支点目标四维定位法****第二步&#xff1a;支点验证里程碑设计****第三步&#xff1a;目标网络重构方案****第四步&#xff1a;动态监控仪表盘** 执行工具箱核心心法 关键支点识别与战略聚焦框架 让思想碎片重焕生机的…...

ARIMA详细介绍

ARIMA&#xff08;AutoRegressive Integrated Moving Average&#xff0c;自回归积分滑动平均模型&#xff09;是一种用于时间序列分析和预测的统计模型。它结合了自回归&#xff08;AR&#xff09;、差分&#xff08;I&#xff09;和移动平均&#xff08;MA&#xff09;三种方…...

如何解决Unit sshd.service could not be found

出现 Unit sshd.service could not be found 错误时&#xff0c;通常是因为系统中未安装 OpenSSH 服务、服务名称不匹配或系统未使用 systemd 管理服务。以下是详细的解决方案&#xff1a; 一、确认 SSH 服务是否安装 1. 检查是否已安装 OpenSSH 服务器 不同 Linux 发行版的包…...

飞致云开源社区月度动态报告(2025年1月)

自2023年6月起&#xff0c;中国领先的开源软件公司飞致云以月度为单位发布《飞致云开源社区月度动态报告》&#xff0c;旨在向广大社区用户同步飞致云旗下系列开源软件的发展情况&#xff0c;以及当月主要的产品新版本发布、社区运营成果等相关信息。 飞致云开源运营数据概览&…...

【搜索回溯算法篇】:拓宽算法视野--BFS如何解决拓扑排序问题

✨感谢您阅读本篇文章&#xff0c;文章内容是个人学习笔记的整理&#xff0c;如果哪里有误的话还请您指正噢✨ ✨ 个人主页&#xff1a;余辉zmh–CSDN博客 ✨ 文章所属专栏&#xff1a;搜索回溯算法篇–CSDN博客 文章目录 一.广度优先搜索&#xff08;BFS&#xff09;解决拓扑排…...

WPS怎么使用latex公式?

1、下载并安装mathtype https://blog.csdn.net/weixin_43135178/article/details/125143654?sharetypeblogdetail&sharerId125143654&sharereferPC&sharesourceweixin_43135178&spm1011.2480.3001.8118 2、将mathtype嵌入在WPS MathType面板嵌入器,免费工具…...

简单的爱心跳动表白网页(附源码)

一&#xff1a;准备工作 在开始之前&#xff0c;确保已经具备基础的 HTML、CSS 和 JavaScript 知识。同时&#xff0c;也要准备好一个代码编辑器&#xff0c;比如 VS Code 或 Sublime Text。接下来&#xff0c;我们需要创建三个文件&#xff1a;index.html、styles.css 和 scr…...

【AI】DeepSeek 概念/影响/使用/部署

在大年三十那天&#xff0c;不知道你是否留意到&#xff0c;“deepseek”这个词出现在了各大热搜榜单上。这引起了我的关注&#xff0c;出于学习的兴趣&#xff0c;我深入研究了一番&#xff0c;才有了这篇文章的诞生。 概念 那么&#xff0c;什么是DeepSeek&#xff1f;首先百…...

代理模式 - 代理模式的应用

引言 代理模式&#xff08;Proxy Pattern&#xff09;是一种结构型设计模式&#xff0c;它允许你提供一个代理对象来控制对另一个对象的访问。代理对象通常会在客户端和目标对象之间起到中介的作用&#xff0c;从而可以在不改变目标对象的情况下&#xff0c;增加额外的功能或控…...

DeepSeek超越ChatGPT的能力及部分核心原理

DeepSeek超越ChatGPT的能力及部分核心原理 目录 DeepSeek超越ChatGPT的能力及部分核心原理超越ChatGPT的能力核心原理超越ChatGPT的能力 推理计算能力更强:在复杂的数学计算、法律文件审查等任务中,DeepSeek的推理能力可媲美甚至超越部分国际顶尖AI模型,包括ChatGPT。例如在…...

【4Day创客实践入门教程】Day3 实战演练——桌面迷你番茄钟

Day3 实战演练——桌面迷你番茄钟 目录 Day3 实战演练——桌面迷你番茄钟1. 选择、准备元件、收集资料2. 硬件搭建3.编写代码 Day0 创想启程——课程与项目预览Day1 工具箱构建——开发环境的构建Day2 探秘微控制器——单片机与MicroPython初步Day3 实战演练——桌面迷你番茄钟…...

Git 出现 Please use your personal access token instead of the password 解决方法

目录 前言1. 问题所示2. 原理分析3. 解决方法前言 1. 问题所示 执行Git提交代码的时候,出现如下所示: lixiaosong@IT07 MINGW64 /f/java_project/JavaDemo (master) $ git push -u origin --all libpng warning: iCCP: known incorrect sRGB profile libpng warning...