粉丝1.6万获赞9.3万

如果线上出了 bug 还不能停服,我们的开发环境与测试环境都没有办法重现这个 bug, 这时候我们该怎么排查这个 bug 呢?今天给大家推荐 阿尔萨斯,阿里巴巴开源的加瓦诊断工具,可以方便的定位与诊断线上程序问题。使用步骤,在服务器上通过这个命令下载我们的阿尔萨斯驾包。第二步,加瓦刚炸,阿尔萨斯 bot 点炸启动。第三步,可以反编译我们线上的 class 文件,看一下我们代码是否正确。第四步, 修改我们代码并上传到服务器。第五步,用 re transform class 将我们的修改后的文件加载在我们的 gvm 内存中。第六步,我们测试一下接口,来看一下我们代码演示,这里我已经下载好我们的阿尔萨斯炸包,我就不重复下载了。来看一下我们现在的代码,我这里 打一个炸包,炸包是 user proverter, 一点零版本,然后里面有一个接口是 get user demo, 内蒙,返回的是内蒙,名称是程序员老郭,我们先测试一下,将我们的服务起起来,这个架包我现在放在这一个目录下,起起来之后,我们这下再也不要去管他了,也不要去动他了,模拟线上这个时候永远不停服,我们怎么排查我们那个 bug? 先访问一下现在的接口,返回是程序员老郭, 如果说现在线上你的服务某个接口可能出了问题,这时候你要去排查,你可以给这个方法呢?加日制也可以,如果说你怀疑是哪里的问题,你就修改对应位置的代码, 这里我们简单模拟一下,我把程序员老郭修改为,老郭牛逼,修改完成之后, 帕萨斯的官网是不推荐我们用 m c 命令进行编译的啊。自己在本地编译好之后,将文件上传我们编译一下啊,把这清空 编译好的文件找到你修改的 class, 我们修改的是这个 use demo service employ, 我们把这个类放在和我们的价包同一级的目录下点 class 文件,对吧? 现在相当于是模拟。我们已经把我们的 clus 上传到服务器了,上传到服务器之后怎么去加载呢?来启动一下我们的阿尔萨斯,启动起来, 如果你在 windows 的环境下,你建议你去指定的时候指定一下费用的文件编码啊,让炸,然后阿尔萨斯炸包骑起来啊,骑起来之后你会发现这里有一个加瓦进程输入二回车进去, 进去之后我们现在来看一下还没有加载之前的这个 class 文件对应的源码来,现在还是程序员老郭,对吧?然后我刚在这个目录的 class 进行 g v m 加载 成功,对吧?来再反边一看,一下变了啊,老郭牛逼,现在访问一下,接口 立马变了。在这个过程中我们没有重启服务,他的热更新非常的方便,利于我们线上排查。你可以在你的代码里面加日志,或者你觉得是可能哪行代码出问题,加上去之后立马调试,调试完成之后把代码再又提交打包再替换我们的这扎包 重启复就完成了我们线上 bug 的排查调试以及测试。好,今天的视频我就分享到这里,谢谢大家。 nice。

怎样在不停服前提下热更新某段代码?就是个 screen booty, 用端口 8080, 当前应用下有个获取所有用户的接口,该接口具体的实现逻辑在 service 中可以看到接口会返回三个用户,接下来把应用打包, 等待打包结束后启动该应用,然后访问获取所有用户接口,可以看到该接口返回了三个用户,现在该接口逻辑有个微调, 只想返回前两个用户。如何在不停服不重启该应用的前提下实现该需求呢?下面我来演示下整个过程。 过程中需借助阿尔萨斯来完成。首先修改代码逻辑,让接口只返回前两个用户,然后重新构建该应用,等待应用构建完毕后,在他二弟子目录中找到刚才修改的文件的字节码文件,观察字节码文件, 可看到修改已生效。接着在自愿管理器中打开该文件所在目录,复制该文件全路径,然后打开文本编辑器,对文件路径做简单微调。接着启动阿尔萨斯并监控当前应用。重点来了, 我们在刚才启动好的阿尔萨斯窗口输入 returns born 和刚才获取到的字节马文件全入境命令后,回车可以看到该命令执行成功,该命令含义是动态重新加在某个类,再回到浏览器后重新请求该接口,等接口请求完毕后, 发现用户从三个变成了两个,说明我们修改的那段代码已经被热更新上去了。再拓展一下,如果线上有比较紧急的发,需要热修复,也可以采取这个思路,先反边意类,接着修改反边意后的类,再重新编意, 最后动态重新加载类即可。至此演示结束,你学会了吗?好了,本期视频就到这里,欢迎关注、评论、点赞,我们下期再见!

同样的接口在不同环境效果不同怎么办?在实际工作中,我们有不同的环境,如本地 测试、生产,一个应用会部署在三个环境,各司其职。有时候会出现一个比较奇怪的问题,同样的接口在本地环境和测试环境能正常访问,而在生产环境却不能正常访问,直接四零四。我们来复现下这个问题。 这是一个简单的 screenbook 应用,端口是八零八幺,该应用里有已开发完毕的若干接口。接下来我们把应用或 madam 打包。接着我们在 target 目录中找到打包好的应用,然后在文件夹中找到这个应用。找到后打开 c m d 窗口, 将打包好的应用启动,简单验证一下部署没有问题,至此已经模拟完成将应用部署到生产环境的整 整个过程。接着我们准备启动本地环境,这里将端口改为八零八零,然后启动该应用,用接口 gf tl 验证下发现本地环境正常,然后用同样的接口去访问生产环境,发现直接四零四问题复现了。 为什么会这样呢?我们大胆假设,小心求证。这种问题一般是由于本地和生产环境代码不一致导致的。但是怎样看生产环境正在运行的代码呢?可以用阿尔萨斯提供的 chat 命令。首先我们找到阿尔萨斯, 然后监控运行在八零八幺端口的应用,然后回到代码窗口,找到需要反编译的类,依次点击 office command to compile class chat。 接着将命令粘贴在阿尔萨斯控制台后,回车可以看到这个类已经被反编译了,再把反编译后的代码 与本地环境代码进行比较,确实不一样。那么接下来的事就比较简单了,只需要重新编一下本地代码, 然后把编译好的代码重新发布到生产环境就可以了。发布完成之后,我们重新验证下,发现该接口在生产环境已经正常了。至此,问题解决,你学会了吗?好了,本期视频就到这里,欢迎关注、评论、点赞,我们下期再见!

今天我们给大家带来的是经验分享啊,嗯,我们之前讲过一个阿萨斯啊,阿萨斯的一些基本的一些命令吊用啊, 然后这节课的话我们介绍一下他比较常用的一个工具指令,就是一个吹一次啊,然后这个吹一次呢,可以用来干嘛呢?他就是可以在你没有打印日日的情况下,他能够去把你整个的一个方法的调用链过程给你打印下来啊。 好,具体的话我们等会一起看一下啊。好,然后呢进入之前的课程的话,如果大家不清楚的话,可以看一下咱们这个上面有啊,有这个, 嗯,叫什么?阿萨斯线上代码调试神器啊,然后这一个代码的话就是,嗯,给大家介绍了如果去安装阿萨斯啊,然后还有一个阿萨斯的进门使用啊。好,这几个的话,我们主要的一个目的就是给大 来实战一下吹死的一个指令。好,首先我们需要去写一下这个我们的一些测试代码啊。嗯,我们可以先看一下咱们这个代码啊, 这是一个一个接口的啊,暴露一个接口。然后这里面的一个方法呢,我们看一下啊,首先他接收一个参数啊,是一个 a 参数啊,这都无所谓啊,大家要定一个啊,然后他这里面有一些衣服判断啊, 因为我们平时打那个踹死的话,看那吊运链的话,肯定是看他走了哪一个分支,然后就掉了哪些方法,对吧? 然后锤子,然后我们经常这个锤子会结合这个窝起窝起这个指令去使用的啊,好,然后呢他这里面会去进行一些判断啊,如果他这个是为空的话,我们就会返回处理为空,然后给他返回一个 n p d, 对吧?然后 n p d 一个值,嗯,然后他这里面的话,如果是他为一的话,那么 我就会去处理一个一一套,就好像一个四个塞斯啊,否则也会返回四个塞子啊。啊?这个返回纸咱们不关注,咱们主要去关注他这个方法他走到哪一步了?然后调用到哪些方法,对吧?好, ok, 然后呢我们这里现在需要做的就是把这个进行一个打包放到我们的服务器上面去啊,好,我们来打个包, 然后我们点一下拍个, 哎,咱们的包已经打好了,对吧?打好了,咱们然后来看一下 这里面,然后我们我们到这里面,我们把这个文件给他挪过来。好,咱们打包的包是在这里面,我们给他改一下名字啊, 我们把这个后缀去掉, 给他去掉的吧。然后呢咱们放到我们服务器啊,我这个是本地通过那个 money pass 构建的一个训练机。啊。好,首先呢我们把原有的给他删掉啊,因为我之前这里面已经有了,我们把这些给他删除掉, 我们杠 f。 然后我们把这个阿萨斯呆萌,我们把这个删掉啊 删掉。然后我们现在就是需要的就是把我们的这给他传过来,我们通过这个 sftp 啊给他传过来, 然后来我们怎么弄呢?我们直接给他拖动过来啊,拖过来就行了, 已经过来了,对吧?嗯,阿瑟戴帽,对吧?阿瑟戴帽。然后呢我们现在需要做的就是这个啊,我们首先我们需要把那个阿萨斯给他下下来啊, 下下来如果大家,嗯,不知道怎么去下的话,我们这里也给大家进行演示一下。可以,因为我们后面很多项目啊,他都是放在这个容器里面跑的,他有可能一个容器跑完之后,下次跑的话他二次就不见了,我们需要给他手动去把这些二次的给他,可以把他下下来啊, 我们看一下啊。 ok, 然后我们去去这里面找一下啊, 这里面啊咱们有一个这个指令啊,这个指令是那个阿萨斯给我们提供,官网给我们提供的,就是 curr 去下载这个命令。好, 我们首先我们把我们现有的这个阿萨斯给他清空掉,给大家演示一下啊。好,已经删除了,是不是我们现在这里面是没有阿萨斯这个阿萨斯这个加包的?我们首先来执行一下这个命令啊, 看一下啊,下载是很快的,我们能拿到阿萨斯布特,对不对?然后我们现在怎么去做呢?我们首先去,我们首先去把我们的一个阿萨斯这个戴帽给他起起来啊,我们首先把他起起来,然后我们直接加我干架就行了啊,阿萨斯刚戴帽, 我们等待启动啊,我们等待启动之后,我们来看一下这个能不能正常访问啊?我的服务器的话是幺二九点幺六八点六四点二,我们看下来这个人能正常访问的,对不对?这个能正常访问的, 然后我们再去看一下这个 gps 啊,看看能打印出来,对吧?好,然后我们现在就是去启用我们的一个阿萨斯这个 这个项目啊,阿萨斯布坦,这是我们刚才下载下来的。好,首先我们能够看到他这里面把所有的一个家伙建成给列出来了,可以看到阿萨斯刚呆吗?就是我们刚才启动的那个,然后我们选择建成一,我,然后我建成一的话,我们就开启进去了啊, 好,然后我们可以看到啊,他这里面长这样啊,好,然后我们现在需要做的就是什么?就是需要输入我们今天的一个主题,就是踹死这个指令啊,踹死指令, 然后拆字,纸巾怎么去拿呢?这肯定不是我们不需要我们手中写的呀,对吧?然后我们通过 iad 二给我们装的一个阿萨斯这个插件啊。嗯,听过,我第一节课的话,就是以前讲过的阿萨斯的一个 课程的话的同学们应该知道啊,咱们装过这样的一个插件啊,叫阿萨斯刚 id 二啊,阿萨斯的一个对于 id 二的做的一个插件,然后直接我们去做。怎么做呢?我们直接是踹死啊阿萨斯,然后安装之之后,我们重启一下,会出现一下这个一个菜单栏,然后我们点击我们的踹死啊,点击我们的踹死。 好,然后我们把这个复制过来,就复制复制到这里来,然后回车,回车大家可以看到啊,他这里面已经监听了,已经完成这个监听了,然后我们现在再去请求一下借口,看他会发现什么啊?我看这请求完成了,我,我们可以看到啊, 我们把这个往那边拖一点啊,放大眼看一下啊,咱们看一下这个吊用链啊,首先他会去吊,他吊用了一个胎死方法,是不是进入到这个咱们的一个胎死的一个入口,然后会掉用孩子胎死。 十三行,我们进了十三行啊,进走到十三行到这里来了,然后我们看他继续怎么走,然后又到十四行,十四行是在这里面,说明他这里面是满足条件了,他是没有这个文本的,不对,这个三是为空的,所以进到这里面到十四行,然后我们再看到十四行之后他又去哪?到二十一行去了 二十一行咱们是到这一行代码了,对吧?到这一行他们又进行判通判空,如果孩子他是走位空的话,看他又去哪了,然后就去二十二行了,对吧?二十二行就到这里面了,然后这一步就返回掉了, 直接就返回掉了,对吧?直接返回掉这里面都没走啊,对不对?都没走了啊?然后我们再去看一下啊,这个其实就是已经一个掉链完成了,然后我们现在去切换一下咱们这个参数啊,看一下会有不同的,我把它放成一,他打赢的是 hello 四三四十八,所以他对反馈者是变了, 所以整个钓鱼竿也是一个变更的,他首先进行判断的,太太死的也是同样的去十三行了,我们找到十三行到这个方法了,然后我们再去看一下他到十五行去了。十五行去了十五行是什么原因呢?肯定是这条这个条件他不满足,然后继续到了二次应付里面去,然后继续判断他是唯一, 然后我们到十六行可以看到他这个,因为我们传的就是一才是我一,对吧?所以呢?他进入到了这里面去,然后再看他去哪了,到了二十一行,二十一行就是这个方法,汉德一是吧?汉德一到这里面,呃,也没有去。他对,他到汉德一了,汉德一了。然后我们看一下啊, 十五、十六、二十一、二十二的吧,他其实他也没有去走的吧?十六二十一二十一行,十六行进来了,然后到了二十一行 啊,因为他为什么不走呢?为什么不不往下走呢?因为他们这个的话就直接惹烫了啊,惹烫了啊,他是没有去就没有去出力了啊。 ok, 然后我们再看一下啊,再看一下他走,走到哪了呢?然后到最终他就就二十一,二十二行啊,同样的二十一、二十二行走了,对吧?他如果是还是泰克斯,他是有文本的,所以呢?他是有值的,所以呢他就直接返回了。好,然后我们再去走一个还是泰克斯的,我们去另外一个值啊,看他的 另外一个 a 等于二的吧,他等于二,他走的是个 s 啊,看他整的这个调零调零练什么样的啊?首先他进入太子峰嘛,然后呢,他这里面直接去了一个十三的吧,十三行,然后又去了一个十五行,是吧?看一下他这里面十三行到这里面了,到这里面他是呃不为空,然后又去了十五行, 数行到这里面是长这样的,看他怎么走的,哎,感觉这个是不完整的,我们重新把它。这个是不完整的啊,我们刷新一下, ok, 可以看到咱们他到了十五行之后就直接返回了,呃,直接返回了,我们看一下为什么他是一块四为一,为什么会是一呢? a 点一块二,四为一,为什么到了十五行就直接返回了呢?啊?他到了十五行之后,然后直接应该是直接走了,二四二四就直接返回回去了,他,所以他这里面是个 size 就变成这样了啊, 如果他有的他是直接走的那一步,就直接是一个条件就直接走了,并没有在那个条件里面还有分支,所以呢他就直接给他返回了,所以咱们可以看到这个过程啊,是能够把你整个 教练过程去做的。那么我们什么时候会去使用这个 chess 呢?就是当我们这个没有日日进行的记录啊,然后又不知道他为什么我们传一个纸进来之后, 嗯,我们虽然用握起指令能够看到它传进来什么值,但是我们并不知道它整个的一个调用量的一个过程是什么样的,就是它为什么会进入这个分支?为什么会返回给我们?我们跟我们日期不一样的一个值啊,我们都可以结合踹死指令和握起指令 呃,两个进行结合,然后我们就可以去第八个我们的一些代码了啊,好,今天的分享就到这里,大家也可以结合这个视频,然后还和之前我们录过的一阿嫂子这个视频啊进行一个呃,一起看一下啊。好,今天的分享就到这里,谢谢大家。

线上 cpu 飙到百分之百,老板就在你身后盯着,你还在那敲套,还得用计算器把县城 id 转成十六禁制,等你转完,服务器也挂了, 别再搞那一套,先找 pid, 再找 tid, 再接 stack grab 的 原始人操作了。那是面试被八股文用的,不是给你实战救火用的, 真正实用的只用这一行,神脚本修 b d 加 or sprite, 耗费 cpu 最高的进程对战,甚至具体的代码行号全在屏幕上了,这就是开卷考试 没装脚本,那就用阿尔萨斯输入 sprite 杠 n 三最忙的三个县城瞬间现原形,记住生产环境,没时间给你练习打字。这两个救命神器你用上了吗?

大家好,我是马农 ag, 今天我们来聊第四节字符串拼接使用加号,而非 stream builder 或 stream buffer, 这是代码层面最常见的性能杀手之一,很多同学写起来顺手,却不知道背后藏着巨大的性能陷阱。问题场景,在电商日制报表系统中,字符串拼接是高频操作,批量拼接,订单号日制内容较为常见。 stream 是 不可变对象,每次加号拼接底层都会创建全新 stream 对 象,核心痛点有四个,第一,临时对象激增循环,每次加号影视创建 streambuilder, 在 twstream 产生两个临时对象。 第二, gc 压力暴增,一万次循环产生两万临时对象,快速占满 ed 区,触发 young gc, 高 qps 下近生老年代引发 full gc 接口卡顿超时。第三,性能损耗严重,实测比 streambuilder 差十倍以上。 第四,高病发下内存浪费甚至。嗯,风险根本原因, java 中 stream 不 可变底层叉,二序组 final 修饰,任何修改都产生新对象。 变易器虽将加号转成 streambuilder, 但每次循环都是全新 streambuilder, 在 to stream 完全没有附用。一万次循环等于两万个临时对象,全进一等区, 当 q p s 达到一千,每秒产生数千万临时对象,一顿区秒即填满接口响应从个位数毫秒飙升到几百毫秒。优化前代码在循环内直接用加号拼接,每次执行 result 等于 result, 加逗号加 order id。 日制拼接场景,单次循环四个加号操作产生四个临时 stream builder, 加四个临时 stream, 一万条订单汇总约两万零时对象。实测接口响应二百五十毫秒以上,央 g c 频率极高。 优化方案三个核心技巧,第一,循环外创建 stream builder 并指定出使容量,避免数组扩容。第二,循环内统一调用 append, 仅修改底层字符数组,整个循环零零时对象。 第三,多现成高 qps 场景,用 fredlocal 存储 stream builder, 实力现成,安全又避免重复分配。接口结束必须调用 remove, 防止内存泄露。最后只调用一次 to stream, 优化效果非常显著。临时对象从两万降为一个接口,响应从二百五十毫秒降至八毫秒,降幅超百分之九十六。 qps 从十二提升到一百八十,性能提升约十五倍, gc 压力几乎归零。 核心要点总结,第一,识别 stream 不 可辨,特性是根源所在。第二, streambuilder 循环外创建指定容量循环内 append, 附用最后一次 to stream。 第三,多县城优先 threadlocal 加 streambuilder, 而非 stream buffer。 第四,接口结束必须 remove, 防止 fredlocal 内存泄露。第五, artist 验证三步法, jack 看字解码确认根音 trace 定位瓶颈 monitor 量化效果。记住这条铁律, 能附用的字母串拼接对象绝不在循环内重复创建好了,今天的内容就到这里,我是马农 ag, 我 们下期见!

this mindset requires us to think less is more when we think about every feature we do almost every design details should has a arrow function not just for arrow or not just for as addicts for example here is our side view if you look from the sides you will notice our drive hard designed like a floating teardrop here you can see the arrow flow pass over the roof through the underbody of the cockpit, the active underflow at the bottom adjusts, balance of drag and down force in real time during driving now let's follow the camera come to the front from here you can see the air entering from the fronts flowing through the bodies cuts out and air channels and being efficiently expelled from the rear this is the path curved by winged and the rear design is truly one of a kind first the rear of the carpet looks like a boat which flows within the ring and then the ring itself act as a massive outlet now you step back with the light on you immediately see show me hello tail light。

家人们,今天咱们来聊聊阿瑟斯斐的命令,很多人可能对这个命令不太了解,其实他可是查看 jvm 所有现成,现成状态, cp 又高,死锁阻塞现成的力气。 先来说说基础命令,输入 thread 就 能展示所有线程,而且默认是按 cpu 使用率从高到低排序的。这就好比一场比赛,谁的 cpu 使用率高,谁就排在前面。再看看最常用的命令, thread n 三能显示 cpu 占用前三的线程,默认是前一, 这就像在一群跑步的人里找出跑得最快的前三名。 fred 十二能直接打印现成十二的完整调用站,就像追踪一个人的行动轨迹一样。 fred 比超级重要,它能自动找出 block 的 阻设,现成和死锁还能显示谁持有锁,就像侦探找出案件的关键线索。 flag state waiting 和 flag state timed waiting 能查看所有 waiting 和 timed waiting 现成 flag state blocked 能查看所有 blocked。 现成 flag i 五千能采用五秒内的 cpu 占 比,这样更精准,就像用高精度的仪器去测量数据。 flag a 能查看所有现成的简单信息。接着是完整参数一览,这里面包含了各种使用场景, 大家可以根据自己的需求来选择。然后说说 thread 面板字段含义, id 就是 县城, id 是 个数字, name 是 县城名, group 是 县城组, priority 是 优先级, 范围是一到十, state 是 县城状态, cpu 是 县城 cpu 占比, time 是 县城总运行时间, interupt 表示是否为中断, dm 表示是否守护县城。县城状态里 runble 是 运行中, 这是正常状态。 time 的 微停是定时等待,比如 sleep hold 微停是等待,像 lock, park block 的是堵塞,这可是高风险可能存在所竞争 terminator 的是已结束, 怒是新键未启动。最后讲讲实战排查场景,当 cpu 达到百分之一百时,用 flag n 三看看哪几个业务线成占 cpu 最高,然后直接看堆占定位方法,就像找到问题的根源。 应用卡住接口不响应时,用 flat 币看看是否有现成 blocked。 定位死锁或锁竞争接口慢。大量等待时,用 flat state waiting 看看是否大量现成卡在 park wait lock 现成过多导致噩梦时,用 thread w l 看看现成总数是否异常暴涨,退出的话按 q 或 c t r l 加 c 就 行。家人们,你们在实际使用中有没有遇到过用 arthur's thread 命令解决的问题呢?欢迎在评论区分享交流。

一天一个拍子干货分享,今天教大家用拍子代码制作小恐龙游戏。 ok, 各位小伙伴,那么今天呢,给大家分享一个用拍子写的小游戏啊,我们首先来看一下效果,呃,打开这个拍项目工具啊,进到这个界面,然后我们点击运行。 好,那么接下来就会打开一个这样的窗体啊,好,我们点击任意按键可以进到游戏,对吧?然后呢就可以开始进行一个游玩。好,那么这边应该是结束了啊, 好,这大概的话呢,是有几种障碍物啊,有这个需要跳跃躲避的啊,当然也有需要这个下蹲躲避的,那么障碍物的出现呢,是随机的啊,你看这里全部都是这个跳跃的啊,然后这个飞鸟的话呢,就要下蹲对吧?好, 那么这个游戏本身代码并不复杂啊,呃,总共来总共来说呢,也就是两三百行的样子啊,除了这个代码之外呢,其他的都是一些资源文件啊,包括在这个地方有这个飞鸟的对吧?啊,有这个小恐龙刺身的啊,包括一些其他的资源啊, 好,那么具体是怎么实现的呢?我们一起来看一下。首先我们用到了三个库啊,第一个库的话呢,是这个拍 game 啊,就是专门用于这个游戏制作的一个库啊,就是拍省中比较常用的一个游戏库。 第二个是这个 os 啊,呃,用于这个文件已经目录管理的啊,就主要用于目录管理啊,啊,你像我们去读取这样的资源文件对吧?啊,他都要去找某个目录,那么就用了这个 os 啊 啊,不,然后再就是那个 random, 你 像我们刚刚那个障碍物的生成是随机的嘛?那么既然是随机的啊,我们就可以用到这个 random 来生成一个随机数。 好,呃,那么基于这几个库呢,我们就可以进行一个实现了。呃,我们在这里呢,就对这个拍片母做了一个粗俗化, 然后呢我们去设置一些场量啊,那么这个场量就包括了,比如说这个屏幕的高度是六百,宽度是一千一,对吧?然后把整个屏幕呢去居中摆放啊,所以呢,我们运行之后就是这个界面啊,就是宽度是一千一,高度是六百的一个界面。 好,那么除了这个之外呢,我们所有的这个图片资源啊,都是从这个 assess 这个里面去拿到的啊。啊,那么比如说啊,这个小恐龙在跑的时候用这个 running 啊,在跳的时候用这个 jumping, 对 吧?在低头的时候用这个 ducking 啊, 所以呢,他们都是对应到的一些个资源文件啊,那么相应的这个资源文件的图片啊,给大家稍微看一下啊,比如说跑步的第一个图,这个对吧?第二个图是这个啊,这个两帧图呢,可以组合起来变成这个奔跑的动作, 对吧?呃,再比如说呢,这个低头也有两张图啊,来描述低头奔跑。好,所以这个 就是我们说的这个敞亮设置啊,设置了一些游戏的图像资源。敞亮。好,然后呢我们去定了一个小恐龙 啊,小恐龙自身的一个坐标,先给它固定好,对吧?呃,然后呢这个跳跃的一个高度啊,给它定一下,然后再往下走啊,你像这边呢,就它所对应的几张图,比如说低头的时候,对吧?比如说这个 奔跑的时候啊,用这个 running 就 我们干练和这个长亮啊。再就是跳跃的时候让它的状态呢,默认是一个奔跑状态,对吧?所以它是一个曲啊。 当然呢,我们可以通过呃去使用不同的按键啊,来使它进行不同的状态,比如说按上那个上键的话,就变成跳跃状态,对吧?那这个东西呢?在哪里设置啊?注意在这里设置,看到没有啊?就如果说你当前是一个低头状态,那我就执行低头方法,如果你是一个什么呢? 奔跑状态,那我就奔跑,对吧?跳跃就跳跃啊,那么根据用户不同的输入呢,我们就可以去更新这一个小小孔的状态,对吧?啊?其实很简单的一件事啊,那就比如说你当前按的是这个 up 就是 上键啊,我们就把它的这个状态改成一个 jump, 一个跳跃,对吧?啊?如果你按的是这一个 向下的键啊,那就变成这个低头状态啊,变成一个低头状态,好,就大概是这么回事啊,好,然后呢往下走啊,他的每一个动作在这里都有描述,对吧?啊?第一件事就是换图片 啊,你蹲下的话肯定有蹲下图片,对吧?奔跑的话有奔跑图片啊,这地方就是他的每一个动作的一个处理啊,集中在这三个方法里面,呃,然后呢会制小恐龙的方法用这个叫啊,然后除了定义小恐龙之外呢,还有这个云,对吧? 包括什么呢?这个障碍物啊,障碍物的话呢,他肯定和这个小恐龙的碰撞有相应的逻辑关系啊,那就如果碰到了之后呢就要结束游戏,对吧?好, 然后再就是这个仙人掌和这个大仙人掌以及这个鸟啊,因为他们三个都是属于这个障碍物的啊,所以呢,我们在写代码的时候让他们就继承了这个障碍物啊。好,所以呢,他们这三都是被小朋小恐龙碰到之后就游戏结束了啊。 好,然后再就是游戏组函数啊。啊,那就包括去呃,定一些个,就是创建一些个窗体啊,对吧?定一些计时器啊。好, 然后呢去进行一个得分计算呀,对吧?进行这个背景的滚动啊,就是这样的一个操作啊。 ok, 那 么这一来的话呢,我们整个的这个游戏功能就实现了啊。好,那么这个分享到这里就结束。