- 博客(143)
- 收藏
- 关注
原创 【DIY】手把手教你爆改一台手机制作掌上游戏机
开头声明:此篇文章为本人原创,首发于酷安,转载请标明出处这个游戏机的创意并非本人原创,创意来自B站UP主极客湾,在B站搜索“自制掌机”就可以看见相关视频。这是一篇混合了教程+制作历程的图文,我把所有制作过程(包括内核编译的详细步骤)详细列出,各位可以参考着制作。好了,不说废话,先看东西介绍一下东西:废旧二手小米5splus+原生安卓9+自编译内核+二手ps4手柄+散热硅胶垫+石墨散热贴+半导体制冷片+散热风扇=超奇葩游戏机1.这玩意能玩什么?它能玩手机游戏(废话),支持所有psp游戏,
2020-07-25 01:18:22 28949 5
原创 《游戏编程模式》学习笔记(十四)事件队列 Event Queue
事件队列在队列中按先入先出的顺序存储一系列通知或请求。发送通知时,将请求放入队列并返回。处理请求的系统之后稍晚从队列中获取请求并处理。这解耦了发送者和接收者,既静态又及时。
2023-10-11 21:21:31 603
原创 《游戏编程模式》学习笔记(十三)组件模式 Component
单一实体跨越了多个领域。为了保持领域之间相互分离,将每部分代码放入各自的组件类中。实体被简化为组件的容器。组件模式没什么好说的,就是放弃传统的继承思路,用组合代替继承来达到对各个领域的解耦。不是让两个类继承同一类来分享代码,而是让它们拥有同一个类的实例。举例public:Bjorn(){}private:int x_, y_;在Bjorn的update方法中,我们作如下更新// 根据用户输入修改英雄的速度break;break;// 根据速度修改位置。
2023-10-09 19:09:11 305
原创 《游戏编程模式》学习笔记(十二)类型对象 Type Object
那么问题来了,每次你要创造一个新的种类的敌人,即使这些敌人仅仅是名字不一样,其属性和行为都差不多,你都得写代码。实例相关的数据被存储在有类型对象的实例中,被同种类分享的数据或者行为存储在类型对象中。这让我们在一组相同的对象间分享行为和数据,就像子类让我们做的那样,但没有固定的硬编码子类集合。Breed类本质上定义了一个怪物的类型,这就是为啥这个模式叫做类型对象。最容易想到的就是,哦,我先写一个Monster抽象基类,里边定义了基本的属性和抽象方法,然后让子类继承这个基类,来制造特定的敌人。
2023-10-08 21:32:56 898
原创 《游戏编程模式》学习笔记(十一)字节码 Bytecode
这一节的内容是介绍一些游戏虚拟机的概念以及实现,非常复杂,以我现在的功力还无法做到概括总结,故先放着。感兴趣的同学请移步原文进行阅读。
2023-09-10 14:18:04 153
原创 《游戏编程模式》学习笔记(十二)子类沙箱 Subclass Sandbox
基类定义抽象的沙箱方法和几个提供的操作。将操作标为protected,表明它们只为子类所使用。每个推导出的沙箱子类用提供的操作实现了沙箱函数。
2023-09-10 14:14:28 301
原创 《游戏编程模式》学习笔记(十)更新方法 Sequencing Patterns
游戏世界管理对象集合。每个对象实现一个更新方法模拟对象在一帧内的行为。每一帧,游戏循环更新集合中的每一个对象。这个模式的定义十分直观,简单地说,就是我们的游戏世界有一个大循环Update(),而我们在游戏对象中封装一个update()小方法来存储个体的更新逻辑,同时因为封装在了小方法里,我们可以自由地添加一些类变量来帮助我们存储状态。
2023-09-10 11:35:35 243
原创 《游戏编程模式》学习笔记(九)游戏循环 Sequencing Patterns
所以有时候会出现渲染在两次更新之间的情况,而这个时候,渲染的往往是前一次更新的时候的情况,这会造成困扰,例如玩家看见子弹在左边,下一次渲染的时候应该在中间但还是显示在左边。在代码中可以看到,这个循环会计算上一次循环到现在间隔的时间,如果间隔时间过长,就会进入里边的小循环,多次调用update方法以追上现实时间。每一次循环,它都会无阻塞地处理玩家的输入,更新游戏的状态,渲染游戏。用真实的时间做循环,每次循环会计算上一次循环到这一次循环所用的时间间隔,然后在update的时候传入这个时间间隔。
2023-08-29 11:16:37 552
原创 《游戏编程模式》学习笔记(八)双缓冲模式 Sequencing Patterns
双缓冲模式定义缓冲类封装了缓冲:一段可改变的状态。这个缓冲被增量地修改,但我们想要外部的代码将修改视为单一的原子操作。为了实现这点,类保存了两个缓冲的实例:下一缓冲和当前缓冲。当信息从缓冲区中读取,它总是读取当前的缓冲区。当信息需要写到缓存,它总是在下一缓冲区上操作。当改变完成后,一个交换操作会立刻将当前缓冲区和下一缓冲区交换, 这样新缓冲区就是公共可见的了。旧的缓冲区成为下一个重用的缓冲区。
2023-08-24 18:38:22 292
原创 《游戏编程模式》学习笔记(六)单例模式 Singleton Pattern
保证一个类只有一个实例,并且提供了访问该实例的全局访问点。定义这种东西一般都是不说人话的,要想要理解这句话的意思,我们得把它揉开了才能搞明白。我们先看前半句 “保证一个类只有一个实例”,单例一般使用类来实现,也就是说,这个单例类,其有且只能有一个实例化的对象instance,一旦出现多个,就不是单例模式。后半句“并且提供了访问该实例的全局访问点”,这句话的意思是,这个实例化的对象是全局可见的,任何系统,任何类都可以访问这个实例化的单例对象。
2023-08-16 20:48:25 1161
原创 《游戏编程模式》学习笔记(四) 观察者模式 Observer Pattern
观察者模式定义了对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。这是定义,看不懂就看不懂吧,我接下来举个例子慢慢说。
2023-08-15 18:30:28 937
原创 《游戏编程模式》学习笔记(三)享元模式 Flyweight Pattern
为了减少需要推送到GPU的数据量,我们想把共享的数据——TreeModel——只发送一次。然后,我们分别发送每个树独特的数据——位置,颜色,大小。第一部分是一块需要渲染多次的共同数据——在例子中是树的网格和纹理。我们只需要一个TreeModel实例化的对象就好了,剩下的树只需要保存一个TreeModel的指针,就可以很快的找到这个对象。这就是享元模式,实际上我认为享元模式没有什么好说的东西,所以这里的大部分内容我都是直接照搬原著的。在系统设计中,对象实例进行分类后,发现真正有区别的分类很少的时候。
2023-08-04 14:36:33 640
原创 《游戏设计模式》学习笔记(二)命令模式 Command Pattern
采用命令模式后,我们将jump,fire这些方法做成一个抽象类command的子类,这样每个命令就有了面向对象的形式的封装(将命令变为数据对象,让这个对象和其他对象一样可以被存储和传递)2.对于不同的游戏角色,我们因为会往里边传入不同actor的引用,最后调用的是actor中内置的方法(如jump方法),这就实现了不同的角色拥有不同的按键行为。1.对于不同的按键,由于其类型都是command*,我们只需要让这个指针指向不同的子类命令对象,就可以实现按键配置功能了。这个时候我们就需要考虑使用命令模式了。
2023-08-04 14:34:39 2008
原创 《游戏编程模式》学习笔记(一) 架构,性能和游戏
开新坑,准备把《游戏编程模式》这本书啃完。这是一本讲设计模式的书,针对游戏开发而作,写得很好。以下是读书笔记,文末有原文链接。
2023-08-04 14:31:37 471
原创 Leetcode 148 给链表排序
链表排序这名字就很好记,面试的时候随手就能想到出这一题,然后看你吭哧吭哧写半天,对于他们来说,即不用废自己脑子,又可以折磨你,的确是一种精神上的享受。
2023-03-12 13:58:10 179 1
原创 LeetCode 152 乘积最大子数组,一个奇特的动态规划问题
对于每个dp[i]来说,每次可以做选择,要么选择与dp[i-1]结合,乘积为dp[i-1]*nums[i], 要么就不选择于之前结合,自己另起炉灶,直接等于nums[i]。实际上,这个问题中,我给出的dp定义并不满足动态规划的最优子结构性质,具体来说,[-2,3,-4]中,实际上答案应该是整个数组的相乘才是最大的乘机。我们这里令 Fmax[i]表示到下标为i的元素为止的乘积的极大值,Fmin[i]表示到下标为i的元素为止的乘积的极小值。在这个用例中, 我的算法给出的是3,而真正的答案是24。
2023-03-12 13:35:21 200
原创 从数据流中快速查找中位数
C++中的priority_queue默认是以大根堆存储的,也就是说,堆顶是堆中最大的元素。如果要定义小根堆,那么就得自己写一个仿函数。这题的思路就是维护两个堆,一个大根堆一个小根堆,将数据加入到这两个堆中,这样从两个堆的堆顶就可以获取整个数据的中位数。...
2022-07-28 14:27:11 266
原创 【左神算法笔记】Class2,3 各种排序算法总结
快排3.0随机选择的一个数,与最尾巴数字交换,并以这个新的尾巴数字为基准做划分,这样就无法人为构建最差情况,这样时间复杂度就是O(nlogn)归并排序需要借助额外数组完成merge的过程所以空间复杂度为O(n),归并排序的时间复杂度是根据master公式计算的,为O(nlogn)归并排序的时间复杂度是基于master公式算出来的,空间复杂度为O(n),因为merge的时候需要借助额外数组完成。桶排序和之前说的排序不同,其是不是基于比较排序,时间复杂度是O(n),不受O(nlogn)下限的影响。.......
2022-07-27 02:24:37 495
原创 【左神算法笔记】Class1:异或交换,时间复杂度计算
因为a^b的后的结果中的那一位为1,这就说明这个位可以将这组数字分为两组,一组里包含a,一组里包含b,那么用eor’与这两组中任意一组相与,一定能得到a或b中的一个。思路首先还是设置变量eor,和之前一样连续数字相与,假设目标数字叫a和b,那么eor最后一定是eor=a^b。下一步,找到eor二进制数字中为1的位,以这个位为基准,再创建一个变量eor’,令eor’=eor’思路设一个变量,例如inteor,将eor连续与每一个数字相异或,也就是eor=eor^a这样。a=a^b即a=甲^乙。........
2022-07-26 13:25:24 236
原创 为什么函数模板声明和定义必须写在一起?
在解释这个问题之前,我们要先回顾一下一个C++程序编译链接的过程。1.编译链接的过程我们编程的时候习惯将函数的声明文件写在.h文件中,然后将函数的定义写在.cpp文件中,在需要调用别的文件中的某个函数的时候就会将该函数所在的头文件include到调用处的文件头部。在C++程序预编译过程中,所有头文件都会展开,在之后的过程中所有的头文件都会消失,只剩下头部被展开了#include的源文件被转为.obj文件。因为展开了头文件的缘故,这些.cpp文件中会有许多的函数声明。而这些函数声明的真正定义往往就集中在某一
2022-07-10 14:06:24 1832 1
原创 【网络是怎样连接的】第六章 请求到达服务器以及响应给客户端(完结)
1.服务器架构当网络包到达Web服务器后,服务器就会接收这个包并进行处理。服务器有很多种类,其硬件和操作系统与客户端相比是不一样的。但是网络相关的部分,如网卡,协议栈,Socket库什么的和客户端却别无二致。无论硬件还是OS如何变化,TCP和IP的功能都是一样的。(当然Socket库的用法以及服务器程序的结构还是不同的)服务器的程序结构如图,我们可以把程序分为两个模块,等待连接模块a以及负责与客户端通信的模块b。当服务器启动的时候就会运行等待连接模块a,这个模块负责创建套接字,然后进入等待连接的暂停状态。
2022-07-02 08:47:35 563
原创 【网络是怎样连接的】第五章 探索服务器
1.Web服务器部署的位置Web服务器可以部署在公司里,也可以直接放在网络运营商管理的数据中心里,或者直接租用运营商提供的服务器。放在公司里,服务器可以从互联网直接访问。这种情况下,网络包通过最近的POP中的路由器、接入网以及服务器端路由器之后,就直接到达了服务器。以前这样的服务器部署方式很常见,但现在已经不是主流方式了。这里有几个原因。第一个原因是IP 地址不足。这样的方式需要为公司网络中的所有设备,包括服务器和客户端计算机,都分配各自的公有地址。然而现在公有地址已经不够用了,因此采用这种方式已经不现实
2022-07-02 08:43:30 218
原创 【网络是怎么连接的】第四章 探索接入网和网络运营商
1. 互联网和家庭局域网的区别与联系互联网虽然是一个遍布世界的巨大的系统,但基本工作方式和我们的家庭局域网没什么区别,都是通过路由器进行包的转发。我们可以把互联网想象成家庭局域网的放大版。但是互联网相比之下还是有一点点区别的,数据包传输距离的不同和路由的维护方式, 就是互联网与家庭、 公司网络之间最主要的两个不同点。我们上一章讲过,网络包经过交换机和路由器一步一步地接近互联网,最终会经过互联网接入路由器进入互联网。 互联网接入路由器和以太网路由器基本相同,简单来说,就是根据IP头部钟大哥接收方IP地址在路由
2022-07-02 08:40:23 1313
原创 【网络是怎么连接的】第三章 探索集线器,交换机和路由器
计算机发出的网络包都会通过集线器,路由器等设备转发,最终到达目的地。这些设备在转发包的时候只会查看包头部的控制信息,然后就会将包送到下一个目的地。本章我们将探索一个网络包经历集线器,交换机以及路由器最终进入互联网的过程。1. 双绞线究竟是干什么用的在这之前,我们先看看常说的网线究竟是什么。上一章说到,我们的网络包通过层层包装,最后由网卡的PHY模块将包转换成电信号,这些信号就会通过RJ-45接口进入双绞线。RJ-45接口就是这个东西但是信号到达集线器的时候会和出发时不一样,主要原因是能量衰减和噪声的
2022-06-29 06:01:57 439
原创 【网络是怎么连接的】第二章(下):一个网络包的接收
之前讨论了一个网络包的发送,现在我们来看看一个计算机或服务器收到一个网络包后会怎么做。在一台半双工模式的以太网中,一个设备发送的包会被连接在集线器上的所有设备接收,所以接收操作会接收到很多可能不是发给自己的包。首先PHY(MAU)模块先将信号转为通用格式然后发给MAC模块,MAC模块通过读取报头的同步时钟和起始帧分界符,将分节符后边的东西都转化为数字信息,再检查尾巴的FCS看看这个包有没有出错,出错的话就直接丢弃。如果FCS校验没错,MAC模块就要查询MAC头部中接收方的MAC地址与自己网卡的MAC地址是否
2022-06-25 12:07:11 388
原创 【网络是怎么连接的】第二章(中):一个网络包的发出
1. 关于网络包的基本知识一个网络包是由头部和数据两部分组成的。头部里放着目的地址等控制信息,数据则就是我们要传送的东西。如图所示控制信息(头部)用来在传输过程中告诉转发设备们,我要去往哪里。这就类似于快递包裹上的快递单一样。2. 网络包传输的过程对于一个TCP/IP协议产生的网络包,结构也是如此,具体长这样其中TCP头部我们在上一节讲过了,是由协议栈中的TCP模块加上去的。图中的IP头部和MAC头部则是由TCP下层的IP协议模块加上去的。IP协议在在添加头部的过程中,会将要访问的服务器的IP地址写入I
2022-06-25 12:03:17 687
原创 【网络是怎么连接的】第二章(上): 建立连接,传输数据,断开连接
1. 协议栈以下是操作系统中的网络控制软件,也就是我们说的协议栈的内部示意图。这张图只是显示总体规则,并不涉及细节,仅供参考。我们从上往下看,最上层的网络应用程序就是我们日常使用的比如浏览器,电子邮件等程序。这些应用程序会将收发数据的操作交给下层处理。应用程序下层就是socket库,这是一种链接库。在linux下,socket库有动态库也有静态库。库中包含之前提到过的解析器(用于向DNS服务器发出查询)。然后就到操作系统内部了,这里也是协议栈的位置。其中TCP协议程序部分和UDP协议程序部分都依赖于下
2022-06-25 11:58:51 618
原创 【网络是怎么连接的】第一章:浏览器生成消息
1.输入网址后发生了什么在最开始,我们如果要访问一个网页,就需要在浏览器的输入框内输入网址。例如www.baidu.com之类的东西。但是实际上你按下回车后,我们输入的地方的内容就变了,它会变成https://www.baidu.com/ 这样的东西。这个东西实际上叫做URL。我们可以发现URL是在我们输入的网址前边添加了”http”,”ftp:”,”file:“这样的东西。实际上URL开头的这些文字都表示了浏览器应该使用的访问方法。访问web服务器就应该用HTTP协议,访问FTP服务器就应该使用FTP协议
2022-06-20 05:17:10 191
转载 C语言字符串的长度与大小
在C语言中没有string类型的数据,要想表示字符串一般有两种形式:1.字符数组字符数组表示字符串可以有两种方式:此种方法声明的字符串本质上是字符数组,在赋值前数组大小还没有确定。在赋值后编译器会自动在“aaaaa”后加上’\0‘以表示字符串的结尾,此时str1中存储的数是“aaaaa\0”,数组的大小为6。此种方法声明的字符串本质上是字符数组,在声明部分已经定义了数组的大小为5,在赋值“bbbb”后str2已没有空间来存储‘\0‘,str2存储的数据是“bbbbb”,数组的大小为5;此种方法声明的字
2022-06-11 13:44:20 3941 1
原创 预编译,编译,汇编,链接,静态库,动态库都是什么
预编译:预编译又称为预处理,是做一些代码文本的替换工作将头文件展开,取消注释,替换所有宏定义的符号编译:将文件进行词法分析,语法分析,语义分析,符号汇总后,将代码翻译为汇编语言(汇编语言就是MOV,ADD之类的东西)汇编:将文件转换为二进制文件即目标文件,每一个源文件对应一个目标文件,在windows中目标文件的后缀为.obj链接:其实就是一个“打包”的过程,它将所有二进制形式的目标文件和系统组件组合成一个可执行文件。完成链接的过程也需要一个特殊的软件,叫做链接器。在完成汇编后,各个目标文件还没有
2022-06-02 13:07:27 531
原创 【哈工大李治军操作系统听课笔记】L25 内存换出
1.页面换出实际上上一节所说的页面换入过程实际上还缺少一个环节。因为物理内存是有限的,且相比于虚拟内存而言要小得多,我们不可能一直能换入页面,找到空闲的,没有映射过的虚拟页。所以更符合实际的做法是,如果找到了空闲的虚拟页框就直接建立映射,否则就需要从已有的映射中找到一页物理页,将其换出,腾出空闲页框供操作系统换入新的物理页。2.基本页面换出算法先进先出FIFO先进先出的FIFO是最容易想到的,每次淘汰最先放入的那个物理页。但这当然不可能是足够高效的算法。最优置换算法OPT开天眼预知未来
2022-05-27 10:35:58 168
原创 【哈工大李治军操作系统听课笔记】内存换入-请求调页
1.内存换出的含义虚拟内存就是操作系统给进程提供的一个规整的,总长度为4GB(32位)的地址空间,这个进程可以随意访问这个空间的任何一个地址。但是由于实际的物理内存可能比4GB小,所以实际上这4GB的虚拟内存可能无法全部映射到物理内存上。这就需要内存换入和换出来解决这个问题。正因为这样的换入和换出,操作系统用一个小的物理内存来制造出一个大而规整的虚拟内存供进程使用。2.内存换入的详细过程何时进行内存换入?回忆段页式管理机制就会发现,在进程PC指针读到一个逻辑地址的时候,操作系统就会查段表算出虚拟
2022-05-27 10:33:47 135
原创 【哈工大李治军操作系统听课笔记】L23 段页结合的实际内存管理
1.实际上的内存管理机制前边讲了两种内存管理的机制,分别是分段和分页。从用户的角度,我们希望将程序分成若干段存入内存中,因为我们通常喜欢用“代码段的第50条指令”“数据段数组的第500个单元”等描述查找内容。但是从物理内存的角度来看,分页才是真正的好选择。因为分页可以避免分段产生的内存碎片问题,能提高物理内存的空间利用率。在实际的内存管理中,分段机制和分页机制其实是同时存在的,段面向用户,页面向硬件。那么如何做到这一点呢?查看图中的那个双向箭头,我们可以设计一种中间结构。一个程序用分段机制分成多个段
2022-05-26 07:20:52 304
原创 【哈工大李治军操作系统听课笔记】L22多级页表和快表:
1.分页机制存在的问题实际上分页机制存在问题,所以需要多级页表和快表辅助解决这个问题。分页机制主要的问题就是页表太大了….由于要提高内存空间的利用率,分出来的实际物理页应该是很小的(4K),但是页小了相应的页表就会变大。我们需要解决这个问题。2.方案一,去掉没有记录地址的页号。按照分页机制,一个程序的段会被分成好多个页。这个页的页号是由这个段的最大逻辑寻址空间决定的。32位系统中,一个程序段的逻辑地址是32位的,所以最大逻辑地址是2的32次方。每个页内存的大小为4K(2的12次方),因此32位逻
2022-05-25 23:33:36 425
原创 【哈工大李治军操作系统听课笔记】L21 内存分区与分页
1.内存分区遗留问题:上次的课内容中,没有讲如何在内存中找到一个空闲区域,将程序载入进去为了在内存中找到一个空闲的区域。自然想到需要维护一个数据结构,用于保存空闲的内存位置和长度。这就是空闲分区表。表的样子如图:同时我们还需要在这个表中找到一个可以被分配出去的空闲分区,这就需要用一个算法来提供帮助。由于这项工作的核心是分割内存区域,所以该算法被称作内存分区算法。又由于请求的内存大小是不固定的,所以该算法也被称为可变分区算法。分区算法大致有三种:首先适配,最佳适配以及最差适配。首先适配:最先找到空
2022-05-24 13:09:59 189
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人