Libgdx游戏开发系列教程(2)——接水滴游戏实现
目录
游戏玩法
步骤
1.创建项目
2.添加资源文件
3.设置游戏配置
4.加载资源文件
5.播放背景音乐
6.绘制图形
7.雨滴下落实现
8.判断雨滴是否掉落在桶里
9.键盘控制改变桶位置
10.随机雨滴
打包
本文使用Kotlin语言开发
通过本文的学习可以初步了解以下基础知识的使用:
- Basic file access
- Clearing the screen
- Drawing images
- Using a camera
- Basic input processing
- Playing sound effects
游戏玩法
游戏的主要玩法有以下5点:
- 使用桶接水滴
- 桶只能左右移动
- 水滴会从顶部并加速下落
- 玩家可以通过鼠标或键盘来移动桶
- 游戏没有结束一说,可以一直玩
预览动图:
步骤
1.创建项目
由于我是要使用Kotlin开发,所以勾选了Kotlin开发的选项
实际上,创建出来的项目,还是Java文件写的,所以,为了方便,我用了Android Studio把Java文件转为了Kotlin文件
2.添加资源文件
之后,我们需要添加该有的素材文件,总共有四个文件
- drop.wav 水滴掉落在桶里的声音
- rain.mp3 雨声(背景声)
- bucket.png 桶图片
- drop.png 水滴图片
都放在assets资源文件夹中
3.设置游戏配置
找到desktop文件夹目录下的代码文件,进行代码的修改,调整游戏窗口大小为800*480,并开启垂直同步
//设置游戏窗口大小为800*480
config.setWindowedMode(800, 480)
//设置开启垂直同步
config.useVsync(true)
4.加载资源文件
我们进入到core目录下的CatchWater文件,可以看到具体的代码结构
这里可以看到我们的类是继承ApplicationAdapter,从名字上就可以让我们猜测到是使用的设计模式中的适配器模式来兼容不同平台(没深入验证,仅是猜测)
ApplicationAdapter是抽象类方法,提供了几个需要重写的方法,感觉和Android开发中的Activity差不多,应该就是Libgdx游戏的生命周期方法了,这里先不深入扩展了
因为在游戏开始前,我们得先加载上述我们复制到项目的一些图片和音乐的资源文件,所以我们选择在create()方法中进行初始化我们的资源文件
添加以下代码:
lateinit var dropImage: Texture
lateinit var bucketImage: Texture
lateinit var dropSound: Sound
lateinit var rainMusic: Musicoverride fun create() {// load the images for the droplet and the bucket, 64x64 pixels eachdropImage = Texture(Gdx.files.internal("drop.png"))bucketImage = Texture(Gdx.files.internal("bucket.png"))// load the drop sound effect and the rain background "music"dropSound = Gdx.audio.newSound(Gdx.files.internal("drop.wav"))rainMusic = Gdx.audio.newMusic(Gdx.files.internal("rain.mp3"))}
这里需要注意下,我们两张图片(水滴和桶)分辨率都是64*64
我们使用了Gdx.files.internal()方法来获取assets文件夹里的内容,之后游戏如果是运行在Android平台上,这个方法也是通用的
如果是assets文件夹里还有一层文件夹,可以这样写:
Gdx.files.internal("iamge/myimg.png")
稍微讲解下用到的几个类,具体知识得后面再新开文章进行研究
- Texture 这个英文翻译是纹理,但其实可以看做成图片的内存对象,类似Android开发里的Bitmap
- Sound 比较短的那种音效文件
- Music 时长较长的音频文件
5.播放背景音乐
之后我们可以实现播放背景音乐了,这个我们也直接在资源文件加载完毕之后播放吧
//设置循环播放背景音乐
rainMusic.setLooping(true)
rainMusic.play()
这个时候,我们可以进入到desktop里的那个文件,点击箭头运行游戏
游戏界面是黑屏的,但是已经开始播放音乐了,这里就不放图了
6.绘制图形
上述加载资源文件,我们已经得到了两个Texture对象,这个时候我们需要将其画出来,可以通过SpriteBatch这个类来实现
我们直接新建一个全局变量,然后也是在create()方法初始化即可
之后,在render()方法里,将我们的图片绘制出来
override fun render() {//设置屏幕背景色ScreenUtils.clear(0f, 0f, 0.2f, 1f)//绘制图片batch.begin()batch.draw(bucketImage, 400f, 400f)batch.end()
}
效果如下图所示:
这里需要注意一个问题:
在Libgdx中,默认坐标系是以左下角为原点,也就是常规的数学坐标系,当然,也可以通过Camare进行修改,具体如何修改,这里先不研究
上述代码,我们将图片对象的左下角,绘制到屏幕的(400,400)坐标位置上
上面虽然我们成功绘制了一个图片,但是考虑到下述几个问题:
- 雨滴掉落需要改变y坐标,但是y坐标如何存储呢?
- 桶左右移动,需要改变x坐标,x坐标应该如何存储呢?
- 如何确认雨滴和桶的边界关系呢?
考虑到上述的问题,单纯的坐标点记录会使后续的流程代码变得十分的复杂,这个时候我们可以引入一个范围来记录相关的坐标点信息
这里我们可以选用矩形Rectangle来存储我们的图片绘制位置
PS:实际上,不只有Rectangle矩形,还有其他的形状,但具体的使用,还是留在后面教程再进行补充吧
我们通过定义矩形的左上角(x,y)坐标点和宽高,就可以确认一个Rectangle矩形范围了,如下代码所示:
val bucket = Rectangle().apply {//桶放中间x = (800 / 2 - 64 / 2).toFloat()y = 20.toFloat()width = 64.toFloat()height = 64.toFloat()
}
由于此矩形区域是我们用来找回进行边界关系的比对,所以将其宽高都设置为与图片图像的分辨率一样(64*64)
这样一来,我们使用batch.draw()方法绘制的时候,能将图片对象刚好覆盖到矩形范围里
batch.begin()
batch.draw(bucketImage, bucket.x, bucket.y)
batch.end()
7.雨滴下落实现
按照上述的逻辑,我们也创建一个雨滴的矩形范围,并将其绘制出来
雨滴默认在最上面,由于绘制图片的时候以左下角来绘制的,所以,最大y坐标减去64,即是雨滴开始的固定高度
然后雨滴的x坐标是随机的,但是最大范围为800减去宽度64
MathUtils是Libgdx提供的随机数工具类
val rainDrop = Rectangle().apply {//x坐标随机x = MathUtils.random(0, 800 - 64).toFloat()y = (480 - 64).toFloat()width = 64.toFloat()height = 64.toFloat()
}override fun render() {batch.projectionMatrix = camera.combinedbatch.begin()batch.draw(dropImage, rainDrop.x, rainDrop.y)batch.end()
}
效果如下所示:
接下来,我们需要实现雨滴的下落功能,这里,我们可以采用时间作为变量,随着时间的变长来改rainDrop对象的y坐标数值
override fun render() {batch.begin()batch.draw(dropImage, rainDrop.x, rainDrop.y)batch.end()rainDrop.y -= 200 * Gdx.graphics.deltaTime
}
效果如下:
可以看到,下落效果实现了,但是似乎出现了重复的东西,其实就是我们在开始的没清除掉上次绘制的图像,加上清除的代码即可:
override fun render() {//清除并设置屏幕背景色ScreenUtils.clear(0f, 0f, 0.2f, 1f)batch.begin()batch.draw(dropImage, rainDrop.x, rainDrop.y)batch.end()//每帧的时间,高度减少200rainDrop.y -= 200 * Gdx.graphics.deltaTime
}
8.判断雨滴是否掉落在桶里
这里,就是需要判断边界了,上面也说到,使用Rectangle矩形,就是方便我们判断是否水滴和桶接触了
Rectangle对象中,有个overlaps()方法,就是专门来判断两个矩形是否重叠了
//判断两个矩形的接触面积有重叠,即水滴掉落在桶里
if (rainDrop.overlaps(bucket)) {//播放音效dropSound.play()
}
9.键盘控制改变桶位置
上面的功能已经基本完成了,那么还差通过键盘来控制桶的位置就能实现了
我们判断是否按下方向键左或右来改变桶对应矩形的x坐标,这样就能改变桶的绘制位置了
override fun render() {//清除设置屏幕背景色ScreenUtils.clear(0f, 0f, 0.2f, 1f)batch.projectionMatrix = camera.combinedbatch.begin()batch.draw(bucketImage, bucket.x, bucket.y)batch.draw(dropImage, rainDrop.x, rainDrop.y)batch.end()rainDrop.y -= 200 * Gdx.graphics.deltaTime//键盘输入判断if (Gdx.input.isKeyPressed(Input.Keys.LEFT)) bucket.x -= 200 * Gdx.graphics.deltaTimeif (Gdx.input.isKeyPressed(Input.Keys.RIGHT)) bucket.x += 200 * Gdx.graphics.deltaTime//判断两个矩形的接触面积有重叠,即水滴掉落在桶里if (rainDrop.overlaps(bucket)) {//播放音效dropSound.play()//模拟消失(让水滴图片消失在游戏屏幕内)rainDrop.y = -64f}
}
效果如下图:
10.随机雨滴
最后,上述完成的只是一个雨滴,那么,我们需要生成多个雨滴,可以使用一个List来存储雨滴的位置
- 当雨滴掉落在地上,将雨滴从列表中移除;
- 当雨滴被桶接到,雨滴也从列表中移除;
class CatchWater : ApplicationAdapter() {lateinit var dropImage: Texturelateinit var bucketImage: Texturelateinit var dropSound: Soundlateinit var rainMusic: Musiclateinit var camera: OrthographicCameralateinit var batch: SpriteBatch//最后雨滴下落时间var lastDropTime = TimeUtils.millis()val bucket = Rectangle().apply {//桶放中间x = (800 / 2 - 64 / 2).toFloat()y = 20.toFloat()width = 64.toFloat()height = 64.toFloat()}val rainDropList = arrayListOf<Rectangle>()override fun create() {// load the images for the droplet and the bucket, 64x64 pixels eachdropImage = Texture(Gdx.files.internal("drop.png"))bucketImage = Texture(Gdx.files.internal("bucket.png"))// load the drop sound effect and the rain background "music"dropSound = Gdx.audio.newSound(Gdx.files.internal("drop.wav"))rainMusic = Gdx.audio.newMusic(Gdx.files.internal("rain.mp3"))// start the playback of the background music immediatelyrainMusic.setLooping(true)rainMusic.play()// create the camera and the SpriteBatchcamera = OrthographicCamera()camera.setToOrtho(false, 800f, 480f)batch = SpriteBatch()//开始先默认生成一个雨滴generateRainDrop()}private fun generateRainDrop() {val rainDrop = Rectangle().apply {//x坐标随机x = MathUtils.random(0, 800 - 64).toFloat()y = (480 - 64).toFloat()width = 64.toFloat()height = 64.toFloat()}rainDropList.add(rainDrop)}override fun render() {//清除设置屏幕背景色ScreenUtils.clear(0f, 0f, 0.2f, 1f)// tell the camera to update its matrices.camera.update()// tell the SpriteBatch to render in the// coordinate system specified by the camera.batch.projectionMatrix = camera.combinedbatch.begin()batch.draw(bucketImage, bucket.x, bucket.y)//绘制雨滴列表rainDropList.forEach {batch.draw(dropImage, it.x, it.y)}batch.end()// 触摸(手机端的操作和鼠标操作)if (Gdx.input.isTouched) {val touchPos = Vector3()touchPos[Gdx.input.x.toFloat(), Gdx.input.y.toFloat()] = 0fbucket.x = touchPos.x - 64 / 2camera.unproject(touchPos)}//键盘操作if (Gdx.input.isKeyPressed(Input.Keys.LEFT)) bucket.x -= 200 * Gdx.graphics.deltaTimeif (Gdx.input.isKeyPressed(Input.Keys.RIGHT)) bucket.x += 200 * Gdx.graphics.deltaTime//500ms生成一个雨滴if (TimeUtils.millis() - lastDropTime > 500) {generateRainDrop()lastDropTime = TimeUtils.millis()}val iter: MutableIterator<Rectangle> = rainDropList.iterator()while (iter.hasNext()) {val raindrop = iter.next()raindrop.y -= 200 * Gdx.graphics.deltaTime//如果雨滴掉落在地上if (raindrop.y + 64 < 0) iter.remove()//判断两个矩形的接触面积有重叠,即水滴掉落在桶里if (raindrop.overlaps(bucket)) {//播放音效dropSound.play()//将此雨滴移除列表iter.remove()}}}override fun dispose() {//资源释放dropImage.dispose();bucketImage.dispose();dropSound.dispose();rainMusic.dispose();batch.dispose();}
}
上面有个涉及到手机和鼠标的操作,因为和Camera对象一起使用,还没过于研究,之后看看再深入一下吧
打包
关于打包的操作,可以通过Gradle的Task来进行操作
Android Studio4.2之后版本,把task给隐藏掉了,所以需要通过设置开启出来
之后Gradle重构当前项目,右侧的Gradle就会出现Task列表了
打包Android的和Android项目开发打包步骤一样的,这里不再赘述
如果是要打包的jar包,则可以点击右侧的Task任务,如下图所示:
生成的jar文件,在desktop\build\libs目录下
相关文章:
Libgdx游戏开发系列教程(2)——接水滴游戏实现
目录 游戏玩法 步骤 1.创建项目 2.添加资源文件 3.设置游戏配置 4.加载资源文件 5.播放背景音乐 6.绘制图形 7.雨滴下落实现 8.判断雨滴是否掉落在桶里 9.键盘控制改变桶位置 10.随机雨滴 打包 本文使用Kotlin语言开发 通过本文的学习可以初步了解以下基础知识的…...
【2025rust笔记】超详细,小白,rust基本语法
一、常见cargo命令 查看cargo版本 cargo --version创建cargo项目 create new demo_name构建编译项目 cargo build运行项目 cargo run检查项目代码 cargo check (比cargobuild快)发布构建项目 cargo build --release 电子markdown/pdf格式 二、小demo-----猜数游戏 1、print…...
将 SSH 密钥添加到 macOS 的钥匙串中
git提交代码时,如果SSH密码并未免密,每次拉取,上传操作时都需要密码输入, 可将SSH密钥添加到钥匙串中 git config --global credential.helper store报错: WARNING: The -K and -A flags are deprecated and have bee…...
Gpt翻译完整版
上一篇文章收到了很多小伙伴的反馈,总结了一下主要以下几点: 1. 说不知道怎么调api 2. 目前只是把所有的中文变成了英文,如果想要做多语言还需要把这些关键字提炼出来成放到message_zh.properties和message_en.properties文件中,…...
CC++的内存管理
目录 1、C/C内存划分 C语言的动态内存管理 malloc calloc realloc free C的动态内存管理 new和delete operator new函数和operator delete函数 new和delete的原理 new T[N]原理 delete[]的原理 1、C/C内存划分 1、栈:存有非静态局部变量、函数参数、返回…...
HTTP 状态代码 501 502 问题
问题 单个客户端有时会出现 报错 501 或 502 如下: System.Net.Http.HttpRequestException: Response status code does not indicate success: 501 (Not Implemented) 分析 可以排除 服务器无法处理的问题(测试发现 一个客户端报错,不会影响…...
virtio_video virtio_snd
在 Qualcomm 平台的 虚拟机(VM) 环境中,qcom,virtio_snd 是 VirtIO 机制下的 音频 DMA 共享 设备节点,它用于 虚拟机和宿主机(Hypervisor)之间共享音频数据,类似于标准的 VirtIO 声音设备。 1️…...
【大模型安全】大模型安全概述
【大模型安全】大模型安全概述 1.大模型安全目前的关键挑战技术安全合规安全 2.大语言模型的安全隐患与主要风险点3.大语言模型与国家安全风险4.大语言模型的信息安全原则 1.大模型安全目前的关键挑战 技术安全 1、数据的安全与合理利用 大语言模型通常需要处理大量敏感数据…...
基于 vLLM 部署 LSTM 时序预测模型的“下饭”(智能告警预测与根因分析部署)指南
Alright,各位看官老爷们,准备好迎接史上最爆笑、最通俗易懂的 “基于 vLLM 部署 LSTM 时序预测模型的智能告警预测与根因分析部署指南” 吗? 保证让你笑出猪叫,看完直接变身技术大咖!🚀😂 咱们今天的主题,就像是要打造一个“智能运维小管家”! 这个小管家,不仅能提…...
深入理解三色标记、CMS、G1垃圾回收器
三色标记算法 简介 三色标记算法是一种常见的垃圾收集的标记算法,属于根可达算法的一个分支,垃圾收集器CMS,G1在标记垃圾过程中就使用该算法 三色标记法(Tri-color Marking)是垃圾回收中用于并发标记存活对象的核心算…...
【车规芯片】如何引导时钟树生长方向
12nm车规DFTAPR项目中,我们可以看到,绝大部分的sink都受控于xxxx_tessent_occ_clk_cpu_inst/tessent_persistent_cell_clock_out_mux/C10_ctmi_1这个mux,这是我们DFT设计结果: 这里我们重新打开place的数据 Anchor,也就…...
基于Spring Boot的企业车辆管理系统设计与实现(LW+源码+讲解)
专注于大学生项目实战开发,讲解,毕业答疑辅导,欢迎高校老师/同行前辈交流合作✌。 技术范围:SpringBoot、Vue、SSM、HLMT、小程序、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容:…...
Spring Boot 中短时间连续请求时出现Cookie获取异常问题
Spring Boot 中短时间连续请求时出现Cookie获取异常问题 一、问题描述:异步线程操作导致请求复用时 Cookie 解析失败1. 场景背景2. 问题根源 二、问题详细分析1. 场景重现2. 问题分析 三、如何避免影响下一次请求?✅方式 1:在主线程提前复制 …...
轮播图案例
(1)、搭建轮播图的结构 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><title>轮播图结构</title><!-- <script src"../js/tools.js"></script> --…...
通俗版解释:分布式和微服务就像开餐厅
一、分布式系统:把大厨房拆成多个小厨房 想象你开了一家超火爆的餐厅,但原来的厨房太小了: 问题:一个厨师要同时切菜、炒菜、烤面包,手忙脚乱还容易出错。 解决方案: 拆分成多个小厨房(分布式…...
【开源-常用C/C++命令行解析库对比】
以下是几种常用的C/C命令行解析库的对比表格,以及它们的GitHub开源库地址: 库名称语言特点是否支持子命令是否支持配置文件是否支持自动生成帮助信息GitHub地址ClaraC11及以上单一头文件,轻量级,非异常错误处理,自动类…...
JavaEE_多线程(一)
目录 1. 为啥要有线程1.1 线程是什么1.2 进程和线程的区别1.3 Java如何进行多线程编程 2 使用线程2.1 创建线程2.2 Thread类的几个常见方法和属性2.2.1 Thread常见构造方法2.2.2 Thread常见属性2.2.3 常见其他方法 2.3 终止一个线程2.3.1 通过共享的标记位来进行沟通2.3.2 调用…...
table 拖拽移动
表格拖拽 Sortable.js中文网|配置 <!-- 教务处 --><template><div class"but"><el-button click"mergeAndPrintArrays()" type"primary">保存数据</el-button><el-button click"restoration()" t…...
【QGIS二次开发】地图显示与交互-01
1. 系统界面设计 设计的系统界面如下,很好还原了QGIS、ArcGIS等软件的系统界面,充分利用了QT中顶部工具栏、菜单栏、底部状态栏,实现了图层管理器、鹰眼图、工具箱三个工具面板。 菜单栏、工具栏、工具箱集成了系统中实现的全部功能&#x…...
Microsoft.Office.Interop.Excel 的简单操作
Microsoft.Office.Interop.Excel 的简单操作 1、安装 Microsoft.Office.Interop.Excel2、声明引用 Microsoft.Office.Interop.Excel3、简单的新建 EXCEL 操作代码4、将 DataGridView 表数据写到 EXCEL 操作代码5、将 EXCEL 表数据读取到 C# 数据表 DataTable 操作代码 1、安装 …...
Debezium日常分享系列之:Debezium 3.0.8.Final发布
Debezium日常分享系列之:Debezium 3.0.8.Final发布 稀疏向量逻辑类型重命名架构历史配置默认值的更改潜在的 Vitess 数据丢失Oracle 的 Reselect 列后处理器行为更改MariaDB 的 SSL 连接 稀疏向量逻辑类型重命名 PostgreSQL 扩展 vector(也称为 pgvecto…...
论传输层的TCP协议和UDP协议scoket通讯
TCP传输前需要三次握手---断开需要四次挥手 谁先发出请求、谁是客户端(client)另一个就是服务器(server)---简称CS架构 现在更多的是BS架构 什么是BS架构? blower server 浏览器服务器---也就是浏览器代替了客户端…...
《鸢尾花数学大系:从加减乘除到机器学习》开源资源
《鸢尾花数学大系:从加减乘除到机器学习》开源资源 Gitee:https://gitee.com/higkoo/ bilibili:https://space.bilibili.com/513194466 GitHub:https://github.com/Visualize-ML...
DeepSeek 助力 Vue3 开发:打造丝滑的表格(Table)示例2: 分页和排序
前言:哈喽,大家好,今天给大家分享一篇文章!并提供具体代码帮助大家深入理解,彻底掌握!创作不易,如果能帮助到大家或者给大家一些灵感和启发,欢迎收藏+关注哦 💕 目录 DeepSeek 助力 Vue3 开发:打造丝滑的表格(Table)示例2: 分页和排序📚页面效果📚指令输入定义…...
MySQL——DQL、多表设计
目录 一、DQL 1.基本查询 2.条件查询 3.分组查询 4.排序查询 5.分页查询 二、多表设计 1.一对多 2.一对一 3.多对多 一、DQL 1.基本查询 注意: *号代表查询所有字段,在实际开发中尽量少用(不直观、影响效率) 2.条件查询…...
【文献阅读】The Efficiency Spectrum of Large Language Models: An Algorithmic Survey
这篇文章发表于2024年4月 摘要 大语言模型(LLMs)的快速发展推动了多个领域的变革,重塑了通用人工智能的格局。然而,这些模型不断增长的计算和内存需求带来了巨大挑战,阻碍了学术研究和实际应用。为解决这些问题&…...
玩转大模型——Trae AI IDE国内版使用教程
文章目录 Trae AI IDE完备的 IDE 功能强大的 AI 助手 安装 Trae 并完成初始设置管理项目什么是 “工作空间”?创建项目 管理插件安装插件从 Trae 的插件市场安装从 VS Code 的插件市场安装 禁用插件卸载插件插件常见问题暂不支持安装 VS Code 插件市场中某个版本的插…...
【实战 ES】实战 Elasticsearch:快速上手与深度实践-2.3.1 避免频繁更新(Update by Query的代价)
👉 点击关注不迷路 👉 点击关注不迷路 👉 点击关注不迷路 文章大纲 Elasticsearch数据更新与删除深度解析:2.3.1 避免频繁更新(Update by Query的代价)案例背景1. Update by Query的内部机制解析1.1 文档更…...
stable-diffusion-webui 加载模型文件
背景 stable-diffusion-webui 安装完毕后,默认的模型生成的效果图并不理想,可以根据具体需求加载指定的模型文件。国内 modelscope 下载速度较快,以该站为例进行介绍 操作步骤 找到指定的模型文件 在 https://modelscope.cn/models 中查找…...
BKA-CNN基于黑翅鸢算法优化卷积神经网络的数据多特征分类预测Matlab
BKA-CNN基于黑翅鸢算法优化卷积神经网络的数据多特征分类预测Matlab 目录 BKA-CNN基于黑翅鸢算法优化卷积神经网络的数据多特征分类预测Matlab分类效果基本介绍BKA-CNN基于黑翅鸢算法优化卷积神经网络的数据多特征分类预测一、引言1.1、研究背景和意义1.2、研究现状1.3、研究目…...
SparkStreaming之04:调优
SparkStreaming调优 一 、要点 4.1 SparkStreaming运行原理 深入理解 4.2 调优策略 4.2.1 调整BlockReceiver的数量 案例演示: object MultiReceiverNetworkWordCount {def main(args: Array[String]) {val sparkConf new SparkConf().setAppName("Networ…...
maven高级-05.私服
一.私服...
FFmpeg-chapter2-C++中的线程
1 常规的线程 一般常规的线程如下所示 // CMakeProject1.cpp: 定义应用程序的入口点。 //#include "CMakeProject1.h" #include <thread> using namespace std;void threadFunction(int index) {for (int i 0; i < 1000; i){std::cout << "Th…...
【前端】简单原生实例合集html,css,js
长期补充,建议关注收藏点赞。 目录 a标签设置不一样的花样(图片但不用img)侧边固定box分栏input各种类型iframe表单拖拽 a标签设置不一样的花样(图片但不用img) a标签里面不用嵌套img,直接设置为其bg-img即可 <!DOCTYPE html…...
Linux下的shell指令(一)
作业 1> 在终端提示输入一个成绩,通过shell判断该成绩的等级 [90,100] : A [80, 90) : B [70, 80) : C [60, 70) : D [0, 60) : 不及格 #!/bin/bash read -p "请输入学生成绩:" score if [ "$score" -ge 90 ] && [ "$scor…...
AJAX介绍
XMLHttpRequest get请求使用 const xhr new XMLHttpRequest(); xhr.open("GET", "/data/test.json", true); xhr.onreadystatechange function () {if (xhr.readyState 4) {if (xhr.status 200) {alert(xhr.responseText);} else {console.log("…...
Serilog: 强大的 .NET 日志库
Serilog 是一个功能强大的日志记录库,专为 .NET 平台设计。它提供了丰富的 API 和可插拔的输出器及格式化器,使得开发者能够轻松定制和扩展日志记录功能。在本文中,我们将探索 Serilog 的基础知识、API 使用、配置和一些常见的示例。 1. 日志…...
串口通讯基础
第1章 串口的发送和接收过程 1.1 串口接收过程 当上位机给串口发送(0x55)数据时,MCU的RX引脚接受到(0x55)数据,数据(0x55)首先进入移位寄存器。数据全部进入移位寄存器后,一次将(0x55)全部搬运…...
SSL证书和HTTPS:全面解析它们的功能与重要性
每当我们在互联网上输入个人信息、进行在线交易时,背后是否有一个安全的保障?这时,SSL证书和HTTPS便扮演了至关重要的角色。本文将全面分析SSL证书和HTTPS的含义、功能、重要性以及它们在网络安全中的作用。 一、SSL证书的定义与基本概念 S…...
全国青少年航天创新大赛各项目对比分析
全国青少年航天创新大赛各项目对比分析 一、比赛场地对比 项目名称场地尺寸场地特点组别差异筑梦天宫虚拟三维场景动态布局,小学组3停泊处,初高中组6停泊处;涉及传送带、机械臂、传感器等虚拟设备。初中/高中组任务复杂度更高,运…...
低空监视-无人机专用ADS-B应答机
产品简介 ping200XR是经过TSO适航认证的无人机专用ADS-B应答机,用于中大型无人机的低空监视。将经过认证的航空级航电设备引入无人机系统。该应答机支持航管二次雷达A,C/S模式和ADS-B OUT。重量仅52克满足无人机所面临的尺寸、重量、功耗的挑战…...
【linux】文件与目录命令 - sort
文章目录 1. 基本用法2. 常用参数3. 用法举例4. 注意事项 sort 命令用于对文本文件中的行进行排序,支持按字母顺序、数值大小、特定字段等方式进行排序。默认按字母顺序升序排序。 1. 基本用法 语法: sort [选项] 文件 sort [选项] -o 输出文件 文件功能…...
【工具推荐】在线提取PDF、文档、图片、论文中的公式
网址1:https://simpletex.cn/ai/latex_ocr 网址2: https://www.latexlive.com/home 推荐理由:无需下载,在线使用,直接 截图 CTRLV 效果更佳。...
大模型在垂直行业的落地实践:从通用到定制化的技术跃迁
大模型在垂直行业的落地实践:从通用到定制化的技术跃迁 一、通用大模型的局限性:从 “全能” 到 “专精” 的转型挑战 通用大模型,如 GPT 系列,凭借其强大的自然语言处理能力,在文本生成、语义理解、机器翻译等基础任…...
FPGA开发,使用Deepseek V3还是R1(1):应用场景
以下都是Deepseek生成的答案 FPGA开发,使用Deepseek V3还是R1(1):应用场景 FPGA开发,使用Deepseek V3还是R1(2):V3和R1的区别 FPGA开发,使用Deepseek V3还是R1&#x…...
Docker概念与架构
文章目录 概念docker与虚拟机的差异docker的作用docker容器虚拟化 与 传统虚拟机比较 Docker 架构 概念 Docker 是一个开源的应用容器引擎。诞生于 2013 年初,基于 Go 语言实现。Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中…...
算法之数据结构
目录 数据结构 数据结构与算法面试题 数据结构 《倚天村 • 图解数据结构》 | 小傅哥 bugstack 虫洞栈 ♥数据结构基础知识体系详解♥ | Java 全栈知识体系 线性数据结构 | JavaGuide 数据结构与算法面试题 数据结构与算法面试题 | 小林coding...
Mysql学习笔记(六)Django连接MySQL
一、Django中的MySQL驱动程序 Python中常见的MySQL驱动程序: MySQL-python:就是MySQLdb,是对C语言操作MySQL的封装,支持Python2,不支持Python3mysqlclient:MySQL-python的另一个分支,支持Python3pymysql&am…...
手机号码归属地的实现
手机号码归属地查询一般可以通过以下几种方式实现: 1. 使用公开的号码归属地数据库 可以使用国内的手机号码归属地数据库,如: 百度号码归属地开放API阿里云号码归属地API腾讯号码归属地API 你可以在本地存储一个 CSV 或 SQLite 数据库&…...
本地部署 DeepSeek:从 Ollama 配置到 Spring Boot 集成
前言 随着人工智能技术的迅猛发展,越来越多的开发者希望在本地环境中部署和调用 AI 模型,以满足特定的业务需求。本文将详细介绍如何在本地环境中使用 Ollama 配置 DeepSeek 模型,并在 IntelliJ IDEA 中创建一个 Spring Boot 项目来调用该模型…...