xLua背包实践

news2024/11/24 10:29:44

准备工作

环境,代码

在C#代码方面我们需要准备单例模式基类,AB包管理器,lua解析器管理器
详情请见AB包管理器 xlua详解

然后是Xlua包和AB包,具体导入方法也在上面的链接中
然后是lua的三个文件
在这里插入图片描述
具体代码:
JsonUtility.lua网上应该能找到
下面是Object.lua
这里实现了一个lua中new和继承的逻辑

--面向对象实现 
--万物之父 所有对象的基类 Object
--封装
Object = {}
--实例化方法
function Object:new()
	local obj = {}
	--给空对象设置元表 以及 __index
	self.__index = self
	setmetatable(obj, self)
	return obj
end
--继承
function Object:subClass(className)
	--根据名字生成一张表 就是一个类
	_G[className] = {}
	local obj = _G[className]
	--设置自己的“父类”
	obj.base = self
	--给子类设置元表 以及 __index
	self.__index = self
	setmetatable(obj, self)
end

然后是SplitTools.lua
这个函数实现了将一个字符串根据指定的分隔符进行分割的逻辑

function string.split(input, delimiter)
    input = tostring(input)
    delimiter = tostring(delimiter)
    if (delimiter=='') then
        return false
    end
    local pos,arr = 0, {}

    local find = function() 
        return string.find(input, delimiter, pos, true) 
    end

    for st,sp in find do
        table.insert(arr, string.sub(input, pos, st - 1))
        pos = sp + 1
    end
    table.insert(arr, string.sub(input, pos))
    return arr
end

然后是Mian.csharp
使用luaMgr来重定向和执行lua脚本的

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Main : MonoBehaviour
{
    void Start()
    {
        LuaMgr.GetInstance().Init();
        LuaMgr.GetInstance().DoLuaFile("Main");
    }

}

接下来是VSCode下载安装
首先我们来到微软官网
微软
在这里插入图片描述
进去下载就行
下好VSCode后我们需要下载插件

  • Chinese
  • C#
  • C# XML Documentation Comments
  • Debugger for Unity
  • Unity Tools
  • UnitySnippets

依次下载安装即可
在这里插入图片描述

我们把Unity中的默认编译器改成VSCode
在这里插入图片描述
这里版本变了。要用的插件其实并不太准,建议大家去查最新版本的方法,这里仅供参考
经过一番折腾可以调试了
在这里插入图片描述
至于lua的调试我们下一个Emmylua,但是需要JDK1.8
然后要配置下环境变量

在这里插入图片描述
然后在VSCode里添加配置,选择通过进程ID附加

资源导入与UI拼接

把准备好的UI资源导入,这里随便使用什么图标都行
接下来我们就开始复习UI相关的知识了
先创建一个UIpanel,把名字改成MainPanel,然后把panel自带的image删了
在这里插入图片描述
修改一下panel的父级canvas
在这里插入图片描述
然后在MainPanel下面新建一个按钮
找到锚点,按住shift和alt点击右下角,这里我说的是中间的3*3格子的右下角
在这里插入图片描述

给这个button添加一个image,再用同样的方法添加一个button
在这里插入图片描述

我们现在要把这个panel做成预制体,用作AB包打包,拖到Asset中就可以了
接下来我们来拼格子面板
再创建一个panel
这里我需要做一点半遮罩的效果,所以把底色改的黑一点
在这里插入图片描述
我们现在要创建一个背景图,新建一个image
我们改一下锚点,还是按住shift和alt,这次不选右下角,选中间第三个(也是那个3*3格子)
在这个panel下新建一个button,作为背景面板的关闭,然后把这个button也是和他的父image一样的锚点设置
在这里插入图片描述

然后我们加一个toggle(单选框),锚点也是中间靠右
我们来看一下这个单选框,选中Back和Check,调整锚点,注意这时要调整为右下角(不是3*3格子。而是整个右下角)
在这里插入图片描述
然后是Label,选中居中
在这里插入图片描述

这里有一个选中变色的逻辑,没选中是黄色,选中是绿色
所以back我们选择黄色图,checkmark选择绿色图
我们改一下参数,看起来差不多是这样
在这里插入图片描述
再加两个
在这里插入图片描述

现在我们要把这三个做成互斥的
我们新建一个空对象作为这三个按钮的父对象,依旧是锚点右对齐
在这里插入图片描述
给父对象加个组件
在这里插入图片描述
然后我们把这三个组件的group选择父组件新加的ToggleGroup
在这里插入图片描述
然后就互斥了
之后我们来做格子背景
在这里插入图片描述
然后我们新建一个scroll view锚点右对齐
在这里插入图片描述

我不需要背景图,所以把image移除。只留滑动条
先把滑动方式改成竖直,再把滑动条的联系置空
在这里插入图片描述
然后再把这俩删掉
在这里插入图片描述

最后把这一整个做成预制体
在这里插入图片描述
下面就是整个结构
在这里插入图片描述
然后是格子拼接逻辑
首先新建一个gameobject,宽和高改成170,170,锚点改成3*3中的左上角
在下面添加一个image,也改成170,170,这里的数值你可以随便改,这里image的锚点改成真右下角
在这里插入图片描述
再加个Image作为图标
在这里插入图片描述
这里还要有数量
在这里插入图片描述

Lua基本逻辑准备

别名

我们在lua文件夹下新建一个lua文件,这个文件写的是常用别名
在这里插入图片描述

--1.导入lua准备文件
require(Object)--调用Object.lua 这里面装的是一个面对对象的逻辑
require("SplitTools") --这里面装的是一个根据传入的字符进行字符串分割的函数
Json=require("JsonUtility") --这里面是一个Json解析逻辑

--2.准备Unity别名
GameObject=CS.UnityEngine.GameObject
Resources=CS.UnityEngine.Resources
Transfrom=CS.UnityEngine.Transfrom
RectTransform=CS.UnityEngine.RectTransform
TextAsset=CS.UnityEngine.TextAsset
--2.1图集相关
SpriteAtlas=CS.UnityEngine.U2D.SpriteAtlas

Vector3=CS.UnityEngine.Vector3
Vector2=CS.UnityEngine.Vector2

--2.2UI相关

UI=CS.UnityEngine.UI
Image=UI.Image
Text=UI.Text
Button=UI.Button
Toggle=UI.Toggle
ScrollRect=UI.ScrollRect

--3.自己写的C#脚本相关

AbMgr=CS.AbMgr.GetInstance()--得到AB包管理的单例对象

--4.找到Canvas,方便后期lua脚本操作
Canvas=GameObject.Find("Canvas").transform

然后在Main.lua文件中引用initClass

require(initClass)

数据准备

道具表准备

道具表我们使用excel
先写几个基本属性
在这里插入图片描述
现在icon还没有,我们处理icon
首先做如下的文件结构目录
在这里插入图片描述

在SpriteAltas中新建一个SpriteAltas
在这里插入图片描述
我们在图集下面加图,注意一定要加sprite类型的,如果不是还要转换
在这里插入图片描述
点击pack preview
在这里插入图片描述
把这里取消
可以发现图打的比较整齐了
在这里插入图片描述
我们把它打到UI的AB包里
我们现在就可以在excel表里写信息了,这里格式是图集名+下划线+序号,后续我们根据这个规则进行分割来找图
在这里插入图片描述
然后我们把这个excel转成json
bejson
在这里插入图片描述
在这里插入图片描述
这里把生成的空行删掉,再把倒数第二行多的逗号删掉
在这里插入图片描述
我们在ABRes新建一个Json文件夹,然后一个json文件,把刚才的内容复制粘贴进去
在这里插入图片描述
把json打到jsonAB包里
在这里插入图片描述
然后把我们之前创建的三个预制体面板和图集都打到AB包里
在这里插入图片描述
然后打包
在这里插入图片描述
在这里插入图片描述

Lua读取Json表

我们现在要做的就是把我们上面准备好的json解析一下
新建一个ItemData.lua
我们先通过ABMgr取到我们加载的AB包,然后调用Json库把文本解码到ItemList

local txt=ABMgr:LoadRes("json","ItemData",typeof(TextAsset))
local itemList =Json.decode(txt.text)
print(txt.text)

在这里插入图片描述
我们把itemList打印出来看看

print(itemList[1])

发现是个表
在这里插入图片描述

print(itemList[1].name.."id is"..itemList[1].id)

在这里插入图片描述
这里只是id序号和索引恰巧重合了而已,如果我不想通过索引(因为我并不知道每个索引的id是多少),而是想通过id来查询的话,这个表就不像键值对那样那么好查询,所以我们用个新表实现键值对的逻辑
我来解释一下这段代码,首先我们建一个新表,然后使用pairs遍历这个表,索引使用_表示我不关注索引
ItemData[value.id]=value这里我是使用自定义索引
这行代码执行完毕后可以说数据就与id相关联了,我们可以通过id来取到相应的表

ItemData={}
for _,value in pairs(itemList) do
    ItemData[value.id]=value
end

比如说我可以通过id访问icon

print(ItemData[2].icon)

在这里插入图片描述

然后我们也可以做一个玩家信息
我们之前做的只是一共拥有的物品数量,而现在我需要存储具体的物体

PlayerData.equips={}
PlayerData.items={}
PlayerData.gems={}

function PlayerData:Init()

    table.insert(self.equips,{id=1,num=1})
    table.insert(self.equips,{id=2,num=1})

    table.insert(self.items,{id=3,num=50})
    table.insert(self.items,{id=4,num=20})

    table.insert(self.gems,{id=5,num=99})
    table.insert(self.gems,{id=6,num=88})
end

PlayerData:Init()
print(PlayerData.equips[1].id)

在这里插入图片描述

主面板逻辑

接下来我们要用lua控制MainPanel
在这里插入图片描述
来到vscode新建一个MainPanel.lua
我们来解释一下下面代码,首先我创建个空表,用来模拟Mainpanel对象,这里相当于写了一个,panelObj是主面板的实例化对象,btnRole和btnSkill是两个控件
然后我们写一个初始化方法Init
从我们打包的AB包中取面板,然后放到Canva下面

MainPanel={}

MainPanel.panelObj=nil
MainPanel.btnRole=nil
MainPanel.btnSkill=nil

function MainPanel:Init()
    --1.实例化面板对象
    self.panelObj=ABMgr:LoadRes("ui","MainPanel",typeof(GameObject))

    self.panelObj.transform:SetParent(Canvas,false)--false表明保持原有缩放比例

end

执行后发现成功加载
在这里插入图片描述
然后我们从主界面找到它的子物体button
为其添加一个事件监听

function MainPanel:Init()
    --1.实例化面板对象
    self.panelObj=ABMgr:LoadRes("ui","MainPanel",typeof(GameObject))

    self.panelObj.transform:SetParent(Canvas,false)--false表明保持原有缩放比例

    self.btnRole= self.panelObj.transform:Find("btnRole"):GetComponent(typeof(Button))


    self.btnRole.onClick:AddListener(function()
    self:BtnRoleClick()
    end)

end

function MainPanel:BtnRoleClick()
    print(123123)
end

现在点击图标之后就会打印123了

我们再为其添加一个激活和隐藏的函数
最后完整代码:Main中直接调用showme即可

MainPanel={}

MainPanel.panelObj=nil
MainPanel.btnRole=nil
MainPanel.btnSkill=nil

function MainPanel:Init()

    if self.panelObj==nil then
    --1.实例化面板对象
    self.panelObj=ABMgr:LoadRes("ui","MainPanel",typeof(GameObject))

    self.panelObj.transform:SetParent(Canvas,false)--false表明保持原有缩放比例

    self.btnRole= self.panelObj.transform:Find("btnRole"):GetComponent(typeof(Button))


    self.btnRole.onClick:AddListener(function()
    self:BtnRoleClick()
    end)
end

end

function MainPanel:ShowMe()
    self:Init()
    self.panelObj:SetActive(true)
end

function MainPanel:HideMe()
    self.panelObj:SetActive(false)
end

function MainPanel:BtnRoleClick()
    print(123123)
end

背包面板

新建一个BagPanel.lua
核心逻辑还是按照我们之前想法

BagPanel={}

BagPanel.panelObj=nil
BagPanel.btnClose=nil
BagPanel.togEquip=nil
BagPanel.togGem=nil
BagPanel.svBag=nil
BagPanel.Content=nil

function BagPanel:Init()
    if self.panelObj==nil then
    self.panelObj=ABMgr:LoadRes("ui","BagPanel",typeof(GameObject))
    self.panelObj.transform:SetParent(Canvas,false)
    end
end

function BagPanel:ShowMe()

    self:Init()
    self.panelObj:SetActive(true)
end

function BagPanel:HideMe()

    self.panelObj:SetActive(false)
end

然后在MainPanel中的显示中调用背包格子的显示

function MainPanel:BtnRoleClick()
    BagPanel:ShowMe()
end

就可以显示了
接着我们要实现一个选择单选框切换的逻辑,但是toggle使用的逻辑本质上是Action委托,是只读的,所以要用到我们之前的方法,也就是自己写一个静态类,新建一个列表

using XLua;

public static class CSharpCallLuaList
{
    [CSharpCallLua]
    public static List<Type> csharpCallLuaList=new List<Type>();
}

下面是背包类全部代码

BagPanel={}

BagPanel.panelObj=nil
BagPanel.btnClose=nil
BagPanel.togEquip=nil
BagPanel.togItem=nil
BagPanel.togGem=nil
BagPanel.svBag=nil
BagPanel.Content=nil

function BagPanel:Init()
    if self.panelObj==nil then
    self.panelObj=ABMgr:LoadRes("ui","BagPanel",typeof(GameObject))
    self.panelObj.transform:SetParent(Canvas,false)

    self.btnClose=self.panelObj.transform:Find("btClose"):GetComponent(typeof(Button))
    local group=self.panelObj.transform:Find("Group")
    self.togEquip=group:Find("togEquip"):GetComponent(typeof(Toggle))
    self.togItem=group:Find("togItem"):GetComponent(typeof(Toggle))
    self.togGem=group:Find("togGem"):GetComponent(typeof(Toggle))

    self.svBag=self.panelObj.transform:Find("svBag"):GetComponent(typeof(ScrollRect))
    self.Content=self.svBag.transform:Find("Viewport"):Find("Content")

    self.btnClose.onClick:AddListener(function()
    self:HideMe()
    end)

    self.togEquip.onValueChanged:AddListener(function(value) 
        if value==true then
            self:ChangeType(1)
        end
    end)
    self.togEquip.onValueChanged:AddListener(function(value) 
        if value==true then
            self:ChangeType(2)
        end
    end)
    self.togEquip.onValueChanged:AddListener(function(value) 
        if value==true then
            self:ChangeType(3)
        end
    end)

end
end

function BagPanel:ShowMe()

    self:Init()
    self.panelObj:SetActive(true)
end

function BagPanel:HideMe()

    self.panelObj:SetActive(false)
end

--1.装备 2.道具 3.宝石
function BagPanel:ChangeType(type)
    print("当前类型为"..type)
end

在这里插入图片描述

格子逻辑

格子逻辑有两种实现方法,一种是比较笨的,我们每次点击单选框后生成多个格子对象(不使用面对对象思想)
直接在changeType中实现
我们先创建一个nowItem存相应的单选框存的数据,这个数据来自于PlayerData,是我们自己赋值的,正常情况应该是从服务器或从本地读取的
然后我们遍历nowItem,要做的事情是我们先把需要的素材准备好,然后把图标,文本,生成位置这些对象准备好,最后再赋值

function BagPanel:ChangeType(type)

local nowItem=nil

 if(type==1)then 
    print("type is"..type)
    nowItem=PlayerData.equips
 elseif(type ==2)then
    print("type is"..type)
    nowItem=PlayerData.items
 else
    print("type is"..type)
    nowItem=PlayerData.gems
 end

 --创建格子

  for i=1,#nowItem do
    local grid={}
    grid.obj=ABMgr:LoadRes("ui","ItemGrid")
    grid.obj.transform:SetParent(self.Content,false)
    grid.obj.transform.localPosition = Vector3((i - 1) % 4 * 175, math.floor((i - 1) / 4) * 175, 0)
    grid.imgIcon=grid.obj.transform:Find("imageIcon"):GetComponent(typeof(Image))
    grid.Text=grid.obj.transform:Find("Text"):GetComponent(typeof(Text))
   
    local data=ItemData[nowItem[i].id]

    local strs=string.split(data.icon,"_")
    local spriteAtlas=ABMgr:LoadRes("ui",strs[1],typeof(SpriteAtlas))
    grid.imgIcon.sprite=spriteAtlas:GetSprite(strs[2])
    print(nowItem[i].num)
    grid.Text.text=nowItem[i].num
    table.insert(self.items,grid)  
 end 

在这里插入图片描述
在这里插入图片描述
但是现在有个问题,我并没有删除不用的itemGrid,这个itemGrid是格子对象
在这里插入图片描述
所以我们在ChangeType进来的时候就把原有的逻辑置空了

function BagPanel:ChangeType(type)

local nowItem=nil
for i=1,#self.items do
    GameObject.Destroy(self.items[i].obj)
end

self.items={}

整体代码

不过现在还有个问题,我重复点同一个单选框时会浪费性能
所以记录一下当前类型,如果是就不改变了

BagPanel.nowType=-1
function BagPanel:ChangeType(type)

    if self.nowType==type then
        return
else
    self.nowType=type
end

最后一个小问题是第一次进入的时候没有刷新
可以直接设置ChangeType(1)

function BagPanel:ShowMe()

    self:Init()
    self.panelObj:SetActive(true)
    if self.nowType==-1 then
        self:ChangeType(1)
        end
end

最终逻辑

BagPanel={}

BagPanel.panelObj=nil
BagPanel.btnClose=nil
BagPanel.togEquip=nil
BagPanel.togItem=nil
BagPanel.togGem=nil
BagPanel.svBag=nil
BagPanel.Content=nil

BagPanel.items={}

BagPanel.nowType=-1

function BagPanel:Init()
    if self.panelObj==nil then
    self.panelObj=ABMgr:LoadRes("ui","BagPanel",typeof(GameObject))
    self.panelObj.transform:SetParent(Canvas,false)

    self.btnClose=self.panelObj.transform:Find("btClose"):GetComponent(typeof(Button))
    local group=self.panelObj.transform:Find("Group")
    self.togEquip=group:Find("togEquip"):GetComponent(typeof(Toggle))
    self.togItem=group:Find("togItem"):GetComponent(typeof(Toggle))
    self.togGem=group:Find("togGem"):GetComponent(typeof(Toggle))

    self.svBag=self.panelObj.transform:Find("svBag"):GetComponent(typeof(ScrollRect))
    self.Content=self.svBag.transform:Find("Viewport"):Find("Content")

    self.btnClose.onClick:AddListener(function()
    self:HideMe()
    end)

    self.togEquip.onValueChanged:AddListener(function(value) 
        if value==true then
            self:ChangeType(1)
        end
    end)
    self.togItem.onValueChanged:AddListener(function(value) 
        if value==true then
            self:ChangeType(2)
        end
    end)
    self.togGem.onValueChanged:AddListener(function(value) 
        if value==true then
            self:ChangeType(3)
        end
    end)

end
end

function BagPanel:ShowMe()

    self:Init()
    self.panelObj:SetActive(true)
    if self.nowType==-1 then
        self:ChangeType(1)
        end
end

function BagPanel:HideMe()

    self.panelObj:SetActive(false)
end

--1.装备 2.道具 3.宝石
function BagPanel:ChangeType(type)

    if self.nowType==type then
        return
else
    self.nowType=type
end

local nowItem=nil

for i=1,#self.items do
    GameObject.Destroy(self.items[i].obj)
end

self.items={}

 if(type==1)then 
    print("type is"..type)
    nowItem=PlayerData.equips
 elseif(type ==2)then
    print("type is"..type)
    nowItem=PlayerData.items
 else
    print("type is"..type)
    nowItem=PlayerData.gems
 end

 --创建格子

  for i=1,#nowItem do
    local grid={}
    grid.obj=ABMgr:LoadRes("ui","ItemGrid")
    grid.obj.transform:SetParent(self.Content,false)
    grid.obj.transform.localPosition = Vector3((i - 1) % 4 * 175, math.floor((i - 1) / 4) * 175, 0)
    grid.imgIcon=grid.obj.transform:Find("imageIcon"):GetComponent(typeof(Image))
    grid.Text=grid.obj.transform:Find("Text"):GetComponent(typeof(Text))
   
    local data=ItemData[nowItem[i].id]

    local strs=string.split(data.icon,"_")
    local spriteAtlas=ABMgr:LoadRes("ui",strs[1],typeof(SpriteAtlas))
    grid.imgIcon.sprite=spriteAtlas:GetSprite(strs[2])
    print(nowItem[i].num)
    grid.Text.text=nowItem[i].num
    table.insert(self.items,grid)  
 end 
end

我们回顾一下实现的逻辑,其实格子的逻辑不应该写在背包里的,如果我加什么别的操作,就要一直在背包这里设置格子逻辑,很冗余
所以我们应该把格子写成一个类
所以我们写一个itemGrid.lua

Object:subClass("ItemGrid")

ItemGrid.obj=nil
ItemGrid.imgIcon=nil
ItemGrid.Text=nil

--初始化格子对象
function ItemGrid:Init() 
end

--初始化格子信息
--这里是根据PlayerData传进来的id和num进行操作
function ItemGrid:InitData(data)
end

我们先写Init
首先自己的属性就要用self来调用了,其次father,位置,这里都可以传进去(位置逻辑在外面计算)

function ItemGrid:Init(father,posX,posY) 
    self.obj=ABMgr:LoadRes("ui","ItemGrid")
    self.obj.transform:SetParent(father,false)
    self.obj.transform.localPosition = Vector3(posX,posY,0)
    self.imgIcon=self.obj.transform:Find("imageIcon"):GetComponent(typeof(Image))
    self.Text=self.obj.transform:Find("Text"):GetComponent(typeof(Text))
end

然后是InitData

function ItemGrid:InitData(data)
    local data_keep=ItemData[data.id]

    local strs=string.split(data_keep.icon,"_")
    local spriteAtlas=ABMgr:LoadRes("ui",strs[1],typeof(SpriteAtlas))
    self.imgIcon.sprite=spriteAtlas:GetSprite(strs[2])
    --print(data.num)
    self.Text.text=data.num
end

我们来改背包逻辑

 --创建格子

    for i=1,#nowItem do
    local grid=ItemGrid:new()

    grid:Init(self.Content, (i-1) % 4 * 175, math.floor((i - 1) / 4) * 175)

    grid:InitData(nowItem[i])

    table.insert(self.items,grid)  

itemData逻辑

Object:subClass("ItemGrid")

ItemGrid.obj=nil
ItemGrid.imgIcon=nil
ItemGrid.Text=nil

--初始化格子对象
function ItemGrid:Init(father,posX,posY) 
    self.obj=ABMgr:LoadRes("ui","ItemGrid")
    self.obj.transform:SetParent(father,false)
    self.obj.transform.localPosition = Vector3(posX,posY,0)
    self.imgIcon=self.obj.transform:Find("imageIcon"):GetComponent(typeof(Image))
    self.Text=self.obj.transform:Find("Text"):GetComponent(typeof(Text))
end


--初始化格子信息
--这里是根据PlayerData传进来的id和num进行操作
function ItemGrid:InitData(data)
    local data_keep=ItemData[data.id]

    local strs=string.split(data_keep.icon,"_")
    local spriteAtlas=ABMgr:LoadRes("ui",strs[1],typeof(SpriteAtlas))
    self.imgIcon.sprite=spriteAtlas:GetSprite(strs[2])
    --print(data.num)
    self.Text.text=data.num
end

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

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

相关文章

必应bing广告可以在国内推广投放了吗?

搜索引擎营销&#xff08;SEM&#xff09;是企业不可或缺的市场拓展手段之一&#xff0c;微软的必应Bing搜索引擎&#xff0c;作为全球第二大搜索引擎&#xff0c;其在中国市场的布局正逐渐显露其独特的价值与潜力。随着必应Bing广告正式对中国市场开放&#xff0c;它不仅为国内…

活动回顾 | 春起潮涌——硬件驱动的量化交易与AI

4月20日&#xff0c;华锐技术ACLUB联合AMD在上海举办了“春起潮涌——硬件驱动的量化交易与AI”沙龙活动&#xff0c;会议围绕FPGA硬件加速、CPU&网卡调优、AI技术应用等展开&#xff0c;近50位量化IT与分享嘉宾一起探讨硬件技术在量化交易和AI领域的应用和创新。 FPGA在交…

SmartEDA助力教学创新:探索未来教育的无限可能

在数字化、智能化的浪潮中&#xff0c;教育领域正经历着前所未有的变革。SmartEDA&#xff0c;作为一款强大的数据分析工具&#xff0c;不仅能够助力科研工作者探索数据的奥秘&#xff0c;还能为教育工作者提供全新的教学手段和思路。本文将探讨如何使用SmartEDA进行教学&#…

Vue3框架

Vue3框架 一.使用create-vue搭建Vue3项目二.组合式API - setup选项1.setup选项的写法和执行时机2.setup中写代码的特点3. script setup 语法糖 三.组合式API - reactive和ref函数1. reactive2. ref3. reactive 对比 ref 四.组合式API - computed五.组合式API - watch1. 侦听单个…

【OC和红移的双面材质】

OC和红移的双面材质 2021-12-23 18:36 rs oc 评论(0)

【酱浦菌-模拟仿真】python模拟仿真PN结伏安特性

PN结的伏安特性 PN结的伏安特性描述了PN结在外部电压作用下的电流-电压行为。这种特性通常包括正向偏置和反向偏置两种情况。 正向偏置 当外部电压的正极接到PN结的P型材料&#xff0c;负极接到N型材料时&#xff0c;称为正向偏置。在这种情况下&#xff0c;外加的正向电压会…

nmap扫描工控设备的脚本支持

参考资料 转自&#xff08;http://www.360doc.com/content/15/1201/11/26186435_517125254.shtml&#xff09; 介绍 NMAP是一款强大的网络扫描工具&#xff0c;除了普通的TCP/IP网络扫描之外&#xff0c;NMAP的扩展脚本功能为我们提供了更为广阔的应用范围。 针对脚本学习可…

构建下一代去中心化应用:基于BASE链的DApp开发

在区块链技术的快速发展中&#xff0c;去中心化应用&#xff08;Decentralized Applications&#xff0c;DApps&#xff09;已经成为了一个热门话题。这些应用通过区块链技术&#xff0c;实现了去中心化、透明、安全和不可篡改的特性&#xff0c;为用户提供了全新的体验和解决方…

js使用echarts图表的柱状图的使用

效果图&#xff1a; 代码&#xff1a; <!DOCTYPE html> <html> <head><title>Bar Chart with Custom Label</title><script src"https://cdn.jsdelivr.net/npm/echarts5.2.2/dist/echarts.min.js"></script> </head&…

Linux编辑器调试器 gcc/g++ gdb 编译过程及使用讲解

这恋爱呀 我有两不谈 第一异性不谈 因为我们性别不一样 我知道的她不知道相处起来太累 第二同性不谈 因为我们性别一样 我知道的他也知道相处起来太无聊了 –❀–❀–❀–❀–❀–❀–❀–❀–❀–❀–❀–❀–❀–❀–❀–❀–❀–❀–❀-正文开始-❀–❀–❀–❀–❀–❀–…

stm32f103c8t6学习笔记(学习B站up江科大自化协)-UNIX时间戳、BKPRTC

UNIX时间戳 UNIX时间戳最早是在UNIX系统使用的&#xff0c;所以叫做UNIX时间戳&#xff0c;之后很多由UNIX演变而来的系统也继承了UNIX时间戳的规定&#xff0c;目前linux&#xff0c;windows&#xff0c;安卓这些操作系统的底层计时系统都是用UNIX时间戳 时间戳这个计时系统和…

numpy+matplotlib绘制玫瑰线图案

【第10次课]实验十一数据可视化及应用】 声明&#xff1a;著作权归作者所有。商业转载请联系作者获得授权&#xff0c;非商业转载请注明出处。 1.简答题 本实验绘制简单图形&#xff0c;要导入numpy库函数和matplotlib.pyplot子库函数: import matplotlib.pyplot as plt impor…

iOS 17上如何恢复数据?iOS 17 数据恢复软件

“您好&#xff0c;我正在为我的 iPhone 寻找一款iOS 17 数据恢复软件。升级到 iOS 17 后&#xff0c;我丢失了 iPhone 上的所有照片、联系人和消息。有什么建议吗&#xff1f;” ——丹尼 iOS 17数据恢复软件下载 升级到iOS 17后如何恢复丢失的数据&#xff1f;由于在 iPhone…

【保姆级讲解如何安装与配置Xcode】

&#x1f308;个人主页: 程序员不想敲代码啊 &#x1f3c6;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f44d;点赞⭐评论⭐收藏 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共…

国内各种免费AI聊天机器人(ChatGPT)推荐(上)

作者主页&#xff1a;点击&#xff01; 国内免费AI推荐专栏&#xff1a;点击&#xff01; 创作时间&#xff1a;2024年4月27日11点25分 欢迎来到AI聊天机器人推荐系列的第一篇文章&#xff01; 在这个系列中&#xff0c;我将引领您探索国内各种AI聊天机器人的精彩世界。 从…

Linux内核之临时映射内核内存:kmap_atomic用法实例(六十二)

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

解决Android Studio安卓开发写入文件问题

有很多小伙伴想把文件写进安卓系统储存失败&#xff0c;类似下面的代码 val file File("account.txt")val writer BufferedWriter(FileWriter(file))writer.use {it.write(username "," password)} 用java方式写入读出文件但是显示成功但是找不到文件…

react-lib 读取本地模板创建PDF

读取本地文件和读取远程的一样&#xff0c;都使用fetch去获取 async function modifyPdf() {let url ./template.pdflet existingPdfBytes await fetch(url).then(res > res.arrayBuffer()) // 这里也有问题要转一下const d new Uint8Array(existingPdfBytes)const pdfDo…

鸿蒙开发面试真题——面向对象

鸿蒙开发面向对象的面试题是近年来在软件开发领域中备受关注的话题。作为一种新兴的操作系统&#xff0c;鸿蒙系统的开发者需要具备扎实的面向对象编程知识和丰富的开发经验。在面试中&#xff0c;面试官常常会通过一系列的问题来考察面试者对于鸿蒙开发面向对象的理解和应用能…

第1章 手写WebServer

1.1 Web原理 1.1.1 Web概述 Web是指互联网上的万维网&#xff08;World Wide Web&#xff09;&#xff0c;是一个由超文本、超链接和多媒体内容组成的信息空间。Web的基础技术是HTTP协议、URL、HTML、CSS和JavaScript等。Web被广泛应用于信息检索、在线购物、社交媒体、在线游…