精华内容
下载资源
问答
  • 自己用的MOD合集.深海潜航.扩大背包等实用.
  • HoneySelect Mod集合

    2019-02-16 23:33:31
    HoneySelect的人物模型一般都放在游戏根目录下的UserData\chara\female下,都是png格式,我这个解压后是一个完整的female文件夹,建议你直接把内容拷贝进去,不要直接覆盖,当然也可以直接覆盖,我觉得我的角色模型...
  • kmod-oracleasm-2.0.8-13.el6_8.x86_64.rpm oracleasmlib-2.0.4-1.el6.x86_64.rpm oracleasm-support-2.1.8-1.el6.x86_64.rpm
  • 火炬之光2 MOD制作工具合集 包括PAK文件解压,压缩 DAT文件批量修改 PAK文件修改日期 360会误报,请放心,绝对无毒!
  • 工学+ Mindustry的Java mod设计增加了更多工厂和更多资源,使行业变得更加有趣。... 这个mod还将成为许多其他mod的基础,所有这些mod都源于此mod中添加的基本功能。 这个mod的目的是改变香草的进展
  • de4dot-mod-reactor 4.9 神器 De4dot是一款免费、开源的脱壳/反混淆工具,用户可以用它来脱Dotfuscator、MaxToCode处理过的程序,不过需要在命令行下进行操作,有从事软件开发和逆向编程的人员不要错过。
  • 贱金属Modmod向Minecraft添加了历史上常用的金属,特别是银,铜,锡,铅,锌,水银和镍。 您还将在此mod中找到许多金属合金和一个新工具:Crack Hammer。 虚幻金属已添加到“地狱与末日”:冷铁,秘银,精金和...
  • MOD法在双轴织构Ni_W合金基片上制备La_2Zr_2O_7缓冲层,黄博,郭培,MOD(金属有机化合物沉积)法是最具产业前景的第二代超导带材制备技术之一。La_2Zr_2O_7(LZO)缓冲层以其优良的化学稳定性和热稳定性�
  • 最强cleo补丁合集+完美通关存档,另附游戏死机关闭器(注:本资源收录于其他作者)
  • 这是由Spektre菜单的一个非官方的叉与被并非官方叉。 此菜单用于测试/个人娱乐。 我不容忍在Prismatic Trials等竞争性模式下使用此菜单,也不会容忍此菜单以任何方式损害其他玩家体验的情况。 谢谢你。 刚刚发布...
  • gtasa 特效合集

    2014-04-07 15:22:40
    覆盖到gtasa更目录里的models文件夹里
  • 进入游戏后 ,首先吧modmanager 这个mod 激活,激活之后才会是如图的样子,原版的mod 管理功能比较少 重启之后,点击图中 中间栏 最下方的导入,可以从剪贴板导入,导入的文本信息比较多 传到wp里了 解压密码 是 qq...

    游戏推荐 Rimworld 边缘世界

    首先关于购买

    网上学习版很好找,不再多言。
    steam正版的话,可以去外面 到阿根廷 区 加上特惠 42 拿下(+皇权)
    嫌麻烦 某宝 也有,50基本可以拿下。

    进入正题 mod合集分享

    mod合集地址 记得点赞加收藏哦
    mod manager
    进入游戏后 ,首先吧modmanager 这个mod 激活,激活之后才会是如图的样子,原版的mod 管理功能比较少
    重启之后,点击图中 中间栏 最下方的导入,可以从剪贴板导入,导入的文本信息比较多 传到wp里了 解压密码 是 qq923132714 。

    自用 1.1 中文 超精简

    快试试吧,包括了更多的科技 更好看的ui 更智能的小人 更多的武器 等等。

    展开全文
  • 数据结构(C++)有关练习题

    热门讨论 2008-01-02 11:27:18
    内容及步骤: 编写一个类Complex,定义复数的加法、减法、乘法和除法运算,要求在编写该类时重载这些运算操作符,重载I/O操作符,以便输入和输出复数; 实验报告要求: 按要求写出完整的实验代码; ...
  • 一个专注于添加酷(而不是op)新事物的mod! 炮塔: 空中电弧:仅针对空中敌人的电弧。 范·特雷特海姆(Van Turretheim):可以用不同类型的弹药射击的炮塔。 嫉妒:幽灵的更好版本。 射击归巢回合。 Gattling:...
  • Hash表 Hash算法 的介绍与思考

    千次阅读 2017-06-08 14:41:05
    Hash表 Hash表也称散列表,也有直接译作哈希表,Hash表是一种特殊的数据结构,它同数组、链表以及二叉...以下的函数生成一个长度为0x500(10进制数:1280)的cryptTable[0x500] ...

    Hash表

    Hash表也称散列表,也有直接译作哈希表,Hash表是一种特殊的数据结构,它同数组、链表以及二叉排序树等相比较有很明显的区别,它能够快速定位到想要查找的记录,而不是与表中存在的记录的关键字进行比较来进行查找。这个源于Hash表设计的特殊性,它采用了函数映射的思想将记录的存储位置与记录的关键字关联起来,从而能够很快速地进行查找。

       数组的特点是:寻址容易,插入和删除困难,链表的特点是:寻址困难,插入和删除容易,hash表则是融合了两者的优势之处。

    Hash表采用一个映射函数 f : key —> address 将关键字映射到该记录在表中的存储位置,从而在想要查找该记录时,可以直接根据关键字和映射关系计算出该记录在表中的存储位置,通常情况下,这种映射关系称作为Hash函数,而通过Hash函数和关键字计算出来的存储位置(注意这里的存储位置只是表中的存储位置,并不是实际的物理地址)称作为Hash地址。

    -----------------------

    映射函数又叫Hash函数,是hash表查找效率的关键:

    -------------

    hash表的大小设计:

    -------------

    hash地址冲突的解决:


    *********

    一个好的应用实例(引用原文http://blog.jobbole.com/49229/)

    -------------------------------------

    说明:本文分为三部分内容,第一部分为一道百度面试题Top K算法的详解;第二部分为关于Hash表算法的详细阐述;第三部分为打造一个最快的Hash表算法。

    第一部分:Top K 算法详解

    问题描述

    百度面试题:

    搜索引擎会通过日志文件把用户每次检索使用的所有检索串都记录下来,每个查询串的长度为1-255字节。
    假设目前有一千万个记录(这些查询串的重复度比较高,虽然总数是1千万,但如果除去重复后,不超过3百万个。一个查询串的重复度越高,说明查询它的用户越多,也就是越热门。),请你统计最热门的10个查询串,要求使用的内存不能超过1G。

    必备知识:

    什么是哈希表?文章第二、三部分,会针对Hash表详细阐述

    问题解析:

    要统计最热门查询,首先就是要统计每个Query出现的次数,然后根据统计结果,找出Top 10。所以我们可以基于这个思路分两步来设计该算法。

    即,此问题的解决分为以下俩个步骤

    第一步:Query统计
    Query统计有以下俩个方法,可供选择:
    1、直接排序法
    首先我们最先想到的的算法就是排序了,首先对这个日志里面的所有Query都进行排序,然后再遍历排好序的Query,统计每个Query出现的次数了。

    但是题目中有明确要求,那就是内存不能超过1G,一千万条记录,每条记录是255Byte,很显然要占据2.375G内存,这个条件就不满足要求了。

    让我们回忆一下数据结构课程上的内容,当数据量比较大而且内存无法装下的时候,我们可以采用外排序的方法来进行排序,这里我们可以采用归并排序,因为归并排序有一个比较好的时间复杂度O(NlgN)。

    排完序之后我们再对已经有序的Query文件进行遍历,统计每个Query出现的次数,再次写入文件中。

    综合分析一下,排序的时间复杂度是O(NlgN),而遍历的时间复杂度是O(N),因此该算法的总体时间复杂度就是O(N+NlgN)=O(NlgN)。

    2、Hash Table法
    在第1个方法中,我们采用了排序的办法来统计每个Query出现的次数,时间复杂度是NlgN,那么能不能有更好的方法来存储,而时间复杂度更低呢?

    题目中说明了,虽然有一千万个Query,但是由于重复度比较高,因此事实上只有300万的Query,每个Query255Byte,因此我们可以考虑把他们都放进内存中去,而现在只是需要一个合适的数据结构,在这里,Hash Table绝对是我们优先的选择,因为Hash Table的查询速度非常的快,几乎是O(1)的时间复杂度。

    那么,我们的算法就有了:维护一个Key为Query字串,Value为该Query出现次数的HashTable,每次读取一个Query,如果该字串不在Table中,那么加入该字串,并且将Value值设为1;如果该字串在Table中,那么将该字串的计数加一即可。最终我们在O(N)的时间复杂度内完成了对该海量数据的处理。

    本方法相比算法1:在时间复杂度上提高了一个数量级,为O(N),但不仅仅是时间复杂度上的优化,该方法只需要IO数据文件一次,而算法1的IO次数较多的,因此该算法2比算法1在工程上有更好的可操作性。
    第二步:找出Top 10
    算法一:普通排序
    我想对于排序算法大家都已经不陌生了,这里不在赘述,我们要注意的是排序算法的时间复杂度是NlgN,在本题目中,三百万条记录,用1G内存是可以存下的。

    算法二:部分排序
    题目要求是求出Top 10,因此我们没有必要对所有的Query都进行排序,我们只需要维护一个10个大小的数组,初始化放入10个Query,按照每个Query的统计次数由大到小排序,然后遍历这300万条记录,每读一条记录就和数组最后一个Query对比,如果小于这个Query,那么继续遍历,否则,将数组中最后一条数据淘汰,加入当前的Query。最后当所有的数据都遍历完毕之后,那么这个数组中的10个Query便是我们要找的Top10了。

    不难分析出,这样,算法的最坏时间复杂度是N*K, 其中K是指top多少。

    算法三:堆
    在算法二中,我们已经将时间复杂度由NlogN优化到NK,不得不说这是一个比较大的改进了,可是有没有更好的办法呢?

    分析一下,在算法二中,每次比较完成之后,需要的操作复杂度都是K,因为要把元素插入到一个线性表之中,而且采用的是顺序比较。这里我们注意一下,该数组是有序的,一次我们每次查找的时候可以采用二分的方法查找,这样操作的复杂度就降到了logK,可是,随之而来的问题就是数据移动,因为移动数据次数增多了。不过,这个算法还是比算法二有了改进。

    基于以上的分析,我们想想,有没有一种既能快速查找,又能快速移动元素的数据结构呢?回答是肯定的,那就是堆。
    借助堆结构,我们可以在log量级的时间内查找和调整/移动。因此到这里,我们的算法可以改进为这样,维护一个K(该题目中是10)大小的小根堆,然后遍历300万的Query,分别和根元素进行对比

    思想与上述算法二一致,只是算法在算法三,我们采用了最小堆这种数据结构代替数组,把查找目标元素的时间复杂度有O(K)降到了O(logK)。
    那么这样,采用堆数据结构,算法三,最终的时间复杂度就降到了N‘logK,和算法二相比,又有了比较大的改进。

    总结:
    至此,算法就完全结束了,经过上述第一步、先用Hash表统计每个Query出现的次数,O(N);然后第二步、采用堆数据结构找出Top 10,N*O(logK)。所以,我们最终的时间复杂度是:O(N) + N’*O(logK)。(N为1000万,N’为300万)。第一部分,以上。

     

    第二部分、Hash表 算法的详细解析

    什么是Hash
     Hash,一般翻译做“散列”,也有直接音译为“哈希”的,就是把任意长度的输入(又叫做预映射, pre-image),通过散列算法,变换成固定长度的输出,该输出就是散列值。这种转换是一种压缩映射,也就是,散列值的空间通常远小于输入的空间,不同的输入可能会散列成相同的输出,而不可能从散列值来唯一的确定输入值。简单的说就是一种将任意长度的消息压缩到某一固定长度的消息摘要的函数。

    HASH主要用于信息安全领域中加密算法,它把一些不同长度的信息转化成杂乱的128位的编码,这些编码值叫做HASH值. 也可以说,hash就是找到一种数据内容和数据存放地址之间的映射关系。

    数组的特点是:寻址容易,插入和删除困难;而链表的特点是:寻址困难,插入和删除容易。那么我们能不能综合两者的特性,做出一种寻址容易,插入删除也容易的数据结构?答案是肯定的,这就是我们要提起的哈希表,哈希表有多种不同的实现方法,我接下来解释的是最常用的一种方法——拉链法,我们可以理解为“链表的数组”,如图:

    ctdwcdjxhxbsf01
    左边很明显是个数组,数组的每个成员包括一个指针,指向一个链表的头,当然这个链表可能为空,也可能元素很多。我们根据元素的一些特征把元素分配到不同的链表中去,也是根据这些特征,找到正确的链表,再从链表中找出这个元素。

    元素特征转变为数组下标的方法就是散列法。散列法当然不止一种,下面列出三种比较常用的:

    1,除法散列法
    最直观的一种,上图使用的就是这种散列法,公式:
    index = value % 16
    学过汇编的都知道,求模数其实是通过一个除法运算得到的,所以叫“除法散列法”。

    2,平方散列法
    求index是非常频繁的操作,而乘法的运算要比除法来得省时(对现在的CPU来说,估计我们感觉不出来),所以我们考虑把除法换成乘法和一个位移操作。公式:
    index = (value * value) >> 28   右移,除以2^28。记法:左移变大,是乘。右移变小,是除。
    如果数值分配比较均匀的话这种方法能得到不错的结果,但我上面画的那个图的各个元素的值算出来的index都是0——非常失败。也许你还有个问题,value如果很大,value * value不会溢出吗?答案是会的,但我们这个乘法不关心溢出,因为我们根本不是为了获取相乘结果,而是为了获取index。

    3,斐波那契(Fibonacci)散列法

    平方散列法的缺点是显而易见的,所以我们能不能找出一个理想的乘数,而不是拿value本身当作乘数呢?答案是肯定的。

    1,对于16位整数而言,这个乘数是40503
    2,对于32位整数而言,这个乘数是2654435769
    3,对于64位整数而言,这个乘数是11400714819323198485

    这几个“理想乘数”是如何得出来的呢?这跟一个法则有关,叫黄金分割法则,而描述黄金分割法则的最经典表达式无疑就是著名的斐波那契数列,即如此形式的序列:0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144,233, 377, 610, 987, 1597, 2584, 4181, 6765, 10946,…。另外,斐波那契数列的值和太阳系八大行星的轨道半径的比例出奇吻合。

    对我们常见的32位整数而言,公式:
    index = (value * 2654435769) >> 28

    如果用这种斐波那契散列法的话,那上面的图就变成这样了:

    ctdwcdjxhxbsf02
    很明显,用斐波那契散列法调整之后要比原来的取摸散列法好很多。

    适用范围
    快速查找,删除的基本数据结构,通常需要总数据量可以放入内存。

    基本原理及要点
    hash函数选择,针对字符串,整数,排列,具体相应的hash方法。
    碰撞处理,一种是open hashing,也称为拉链法;另一种就是closed hashing,也称开地址法,opened addressing。

    扩展
    d-left hashing中的d是多个的意思,我们先简化这个问题,看一看2-left hashing。2-left hashing指的是将一个哈希表分成长度相等的两半,分别叫做T1和T2,给T1和T2分别配备一个哈希函数,h1和h2。在存储一个新的key时,同 时用两个哈希函数进行计算,得出两个地址h1[key]和h2[key]。这时需要检查T1中的h1[key]位置和T2中的h2[key]位置,哪一个 位置已经存储的(有碰撞的)key比较多,然后将新key存储在负载少的位置。如果两边一样多,比如两个位置都为空或者都存储了一个key,就把新key 存储在左边的T1子表中,2-left也由此而来。在查找一个key时,必须进行两次hash,同时查找两个位置。

    问题实例(海量数据处理)
    我们知道hash 表在海量数据处理中有着广泛的应用,下面,请看另一道百度面试题:
    题目:海量日志数据,提取出某日访问百度次数最多的那个IP。
    方案:IP的数目还是有限的,最多2^32个,所以可以考虑使用hash将ip直接存入内存,然后进行统计。

     

    第三部分、最快的Hash表算法

    接下来,咱们来具体分析一下,一个最快的Hash表算法。
    我们由一个简单的问题逐步入手:有一个庞大的字符串数组,然后给你一个单独的字符串,让你从这个数组中查找是否有这个字符串并找到它,你会怎么做?有一个方法最简单,老老实实从头查到尾,一个一个比较,直到找到为止,我想只要学过程序设计的人都能把这样一个程序作出来,但要是有程序员把这样的程序交给用户,我只能用无语来评价,或许它真的能工作,但…也只能如此了。

    最合适的算法自然是使用HashTable(哈希表),先介绍介绍其中的基本知识,所谓Hash,一般是一个整数,通过某种算法,可以把一个字符串”压缩” 成一个整数。当然,无论如何,一个32位整数是无法对应回一个字符串的,但在程序中,两个字符串计算出的Hash值相等的可能非常小,下面看看在MPQ中的Hash算法:

    函数一、以下的函数生成一个长度为0x500(合10进制数:1280)的cryptTable[0x500]

    函数二、以下函数计算lpszFileName 字符串的hash值,其中dwHashType 为hash的类型,在下面的函数三、GetHashTablePos函数中调用此函数二,其可以取的值为0、1、2;该函数返回lpszFileName 字符串的hash值:

    Blizzard的这个算法是非常高效的,被称为”One-Way Hash”( A one-way hash is a an algorithm that is constructed in such a way that deriving the original string (set of strings, actually) is virtually impossible)。举个例子,字符串”unitneutralacritter.grp”通过这个算法得到的结果是0xA26067F3。

    是不是把第一个算法改进一下,改成逐个比较字符串的Hash值就可以了呢,答案是,远远不够,要想得到最快的算法,就不能进行逐个的比较,通常是构造一个哈希表(Hash Table)来解决问题,哈希表是一个大数组,这个数组的容量根据程序的要求来定义,例如1024,每一个Hash值通过取模运算 (mod) 对应到数组中的一个位置,这样,只要比较这个字符串的哈希值对应的位置有没有被占用,就可以得到最后的结果了,想想这是什么速度?是的,是最快的O(1),现在仔细看看这个算法吧:

    一种可能的结构体定义?

    函数三、下述函数为在Hash表中查找是否存在目标字符串,有则返回要查找字符串的Hash值,无则,return -1.

    看到此,我想大家都在想一个很严重的问题:“如果两个字符串在哈希表中对应的位置相同怎么办?”,毕竟一个数组容量是有限的,这种可能性很大。解决该问题的方法很多,我首先想到的就是用“链表”,感谢大学里学的数据结构教会了这个百试百灵的法宝,我遇到的很多算法都可以转化成链表来解决,只要在哈希表的每个入口挂一个链表,保存所有对应的字符串就OK了。事情到此似乎有了完美的结局,如果是把问题独自交给我解决,此时我可能就要开始定义数据结构然后写代码了。

    然而Blizzard的程序员使用的方法则是更精妙的方法。基本原理就是:他们在哈希表中不是用一个哈希值而是用三个哈希值来校验字符串。

    MPQ使用文件名哈希表来跟踪内部的所有文件。但是这个表的格式与正常的哈希表有一些不同。首先,它没有使用哈希作为下标,把实际的文件名存储在表中用于验证,实际上它根本就没有存储文件名。而是使用了3种不同的哈希:一个用于哈希表的下标,两个用于验证。这两个验证哈希替代了实际文件名。
    当然了,这样仍然会出现2个不同的文件名哈希到3个同样的哈希。但是这种情况发生的概率平均是:1:18889465931478580854784,这个概率对于任何人来说应该都是足够小的。现在再回到数据结构上,Blizzard使用的哈希表没有使用链表,而采用”顺延”的方式来解决问题,看看这个算法:

    函数四、lpszString 为要在hash表中查找的字符串;lpTable 为存储字符串hash值的hash表;nTableSize 为hash表的长度:

    上述程序解释:

    1.计算出字符串的三个哈希值(一个用来确定位置,另外两个用来校验)
    2. 查看哈希表中的这个位置
    3. 哈希表中这个位置为空吗?如果为空,则肯定该字符串不存在,返回-1。
    4. 如果存在,则检查其他两个哈希值是否也匹配,如果匹配,则表示找到了该字符串,返回其Hash值。
    5. 移到下一个位置,如果已经移到了表的末尾,则反绕到表的开始位置起继续查询
    6. 看看是不是又回到了原来的位置,如果是,则返回没找到
    7. 回到3

    ok,这就是本文中所说的最快的Hash表算法。

    ——————————————–
    补充1、一个简单的hash函数:

    补充2、一个完整测试程序:
    哈希表的数组是定长的,如果太大,则浪费,如果太小,体现不出效率。合适的数组大小是哈希表的性能的关键。哈希表的尺寸最好是一个质数。当然,根据不同的数据量,会有不同的哈希表的大小。对于数据量时多时少的应用,最好的设计是使用动态可变尺寸的哈希表,那么如果你发现哈希表尺寸太小了,比如其中的元素是哈希表尺寸的2倍时,我们就需要扩大哈希表尺寸,一般是扩大一倍。

    下面是哈希表尺寸大小的可能取值:

    17,            37,          79,        163,          331,
    673,           1361,        2729,       5471,         10949,
    21911,          43853,      87719,      175447,      350899,
    701819,         1403641,    2807303,     5614657,     11229331,
    22458671,       44917381,    89834777,    179669557,   359339171,
    718678369,      1437356741,  2147483647

    以下为该程序的完整源码,已在linux下测试通过:

    ------------------------

    至于上文中作者提到的动态可变化的hash表,我这里考虑了一种思路:

    1)一个假设hash表记录结构 

    static uint32_t  TotalHashTableLength = 0;  // 记录hash表的逻辑总长度

    typedef struct _HashTableUnit

    {

         uint32_t  CheckValue0;   //  校验hash值0

         uint32_t  CheckValue1;   //  校验hash值1(两个同时满足才认为是相同的字段)

    }HashTableUnit;


    typedef struct  _HashTableDict

    {

    HashTableUnit * ThisHashTable ;    //开辟连续内存(HashTableUnit * )alloc(sizeof(HashTableUnit)*length)

            uint32_t    HashTableBeginIndex;  // 本次开辟的hash表做整个hash表字典中的所占区段的开始索引

            uint32_t    HashTableLength;    //  本次开辟的hash表做整个hash表字典中的所占区段的长度

      _HashTableDict *prev;    // 指向上一hash表

      _HashTableDict *next;    //  指向下一个hash表

    }HashTableDict;


    2)访问 


    假设初始化时候设置了HashTableUnit   HashTable_0[163];

    HashTableDict_head->HashTableUnit HashTable_0;

    HashTableDict_head->HashTableBeginIndex = 0;

    HashTableLength->HashTableLength = 163;

    HashTableDict_head->next = NULL;

    HashTableDict_head->prev = NULL;


    TotalHashTableLength += 163;

    当发现hash表不够时,自动按照一定的规则添加HashTableUnit   HashTable_1[1361];

    HashTableDict_head->next->HashTableUnit  = HashTable_1;

    HashTableDict_head->next->HashTableBeginIndex = HashTableDict_head->next->prev->HashTableLength;

    HashTableDict_head->next->HashTableLength  = 1361;

    HashTableDict_head->next->next = NULL;

    HashTableDict_head->next->prev = HashTableDict_head;


    TotalHashTableLength += 1361;


    访问的时候的原则:

    a 计算key值 

    b 从hash字典中找此key值所属的子hash表

    c index = key-子hash表的beginIndex 所得即为在此子hash表中顺序位置

    d 通过index可以直接访问对应逻辑hash表位置


    *********



    参考引用:

    http://www.cnblogs.com/dolphin0520/archive/2012/09/28/2700000.html





    Hash算法

    虽然命名上与hash表有部分交集,但是两者侧重点不同。hash算法的应用或者存在领域更主要的是在密码学。



    参考引用:

    http://www.cnblogs.com/hzorac/p/5399042.html  哈希算法集锦

    http://www.cnblogs.com/loujiayu/p/3451668.html  暴雪哈希算法

    http://www.cnblogs.com/bonelee/p/6409733.html  布谷鸟哈希算法

    展开全文
  • Mod for Euro Truck Simulator 2 ドライバーをアイドルにします 标准ドライバー(341人まで)は性别を维持し,これまでのゲームデータでも性転换が発生しません ド张追加ドライバーについては性别を留意しません 不...
  • 这个mod增加了一些东西来增强香草的体验。 如果您对新事物有任何建议,请随时给我发消息。 仍在开发中 仅V6.0,较旧版本没有向后兼容性 这不是因为我很懒,而是因为V6的重大更改。 内容: ium和调压合金输送机,钛...
  • 线段树入门&lazy思想

    千次阅读 多人点赞 2014-11-21 20:42:47
    线段树

    线段树将区间分成若干个子区间,子区间又继续分,直到区间为一个点(区间左值等于右值)

    对于父区间[a,b],其子区间为[a,(a+b)/2][(a+b)/2+1,b] 

    用于求区间的值,如区间最值、区间的和等。

    代码实现中,约定结点下标从1开始,所以某结点下标为x,那么左儿子下标为2x,右儿子下标为2x+1,父结点下标为x/2。



    常用符号
    符号等价意义
    rt<<1rt*2左子树的编号
    rt<<1|1
    rt*2+1右子树的编号
     (l+r)>>1
    (l+r)/2区间长度的一半


    常用宏定义

    #define Mid ((l+r)>>1)      	//注意括号
    #define lson rt<<1,l,Mid	//左结点
    #define rson rt<<1|1,Mid+1,r	//右结点


    建树

    建树丛根结点开始,递归建立左右子树,直到叶子结点,然后反向赋值,父结点的值 = F(左结点的值,右结点的值),这个F是依据题意变的,如果是区间最大则为max()

    void build(int rt,int l,int r)      //建编号为rt的区间为[l,r]的树,主函数传进来的固定是(1,1,n)
    {
        if(l==r){            //叶子结点赋初值,注意下标,Max的是编号,val原数组的是l,看图可以理解
            Max[rt] = val[l];
        }else{                      //建左右子树
            build(lson);
            build(rson);
            Max[rt] = max( Max[rt<<1], Max[rt<<1|1]);   //父结点Max值为Max(左子结点,右子结点)
        }
    }


    查询

    查询为区间查询(只是查询某个点的话不需要线段树),即在区间里查询某个特性值,每次查询都是从跟结点开始往下,根据查询区间和当前区间的区间位置判断是要去左右子区间查询,还是直接返回。如果被查询区间是查询区间的子区间则直接返回子区间的值,如在[1,6]里查询[1,12]就返回[1,6]的值,不再往下查询。
    void query(int rt,int l,int r,int L,int R)  //在[l,r]里查询[L,R]的值,[L,R]一直不变,[l,r]变
    {
        if(L <= l && r <= R){   
            ans1 = max(ans1,Max[rt]);
            ans2 = min(ans2,Min[rt]);
        }else{
            if( L <= Mid) //查询区间在当前区间的左半区间有内容,如在[1,6]里查询[2,3]
                query(lson,L,R);    
            if( R > Mid)  //同理去右子区间,注意不能有else,因为有横跨左右的情况,如[1,6]里查询[2,5]
                query(rson,L,R);
        }
    }


    更新

    更新分为单点更新和区间更新,区间更新等会在下面讲述,而单点更新跟普通区间查询差不多

    void update(int rt,int l,int r,int pos,int num)
    {
        if(l == r && r == pos){     //到对应的叶结点
            Max[rt] = num;
        }else{
            if( pos <= Mid)
                update(lson,pos,num);
            if( pos > Mid)          //或者直接else,点不可能同时在两个区间里
                update(rson,pos,num);
            Max[rt] = max( Max[rt<<1], Max[rt<<1|1]);
        }
    }

    数组大小要为原数据范围的4倍,证明点这里

    题目

    POJ 3264 Balanced Lineup 求区间的最大值-最小值

    #include <cstdio>
    #include <cmath>
    #include <iostream>
    using namespace std;
    #define FOR( i , a , b ) for ( int i = a ; i <= b ; ++ i )
    #define RE freopen("1.in","r",stdin);
    #define bug(x) cout<<#x<<":"<<(x)<<endl;
    
    #define Mid ((l+r)>>1)      //括号!
    #define lson rt<<1,l,Mid
    #define rson rt<<1|1,Mid+1,r
    
    const int maxn= 50005;
    const int inf=0x3f3f3f3f;
    int Max[maxn<<2],Min[maxn<<2];
    int ans1,ans2;
    
    void build(int rt,int l,int r)
    {
        if(l==r){
            scanf("%d",&Max[rt]);
            Min[rt] = Max[rt];
        }else{
            build(lson);
            build(rson);
            Max[rt] = max( Max[rt<<1], Max[rt<<1|1]);
            Min[rt] = min( Min[rt<<1], Min[rt<<1|1]);
        }
    }
    
    void query(int rt,int l,int r,int L,int R)
    {
        if(L <= l && r <= R){
            ans1 = max(ans1,Max[rt]);
            ans2 = min(ans2,Min[rt]);
        }else{
            if( L <= Mid)
                query(lson,L,R);
            if( R > Mid)
                query(rson,L,R);
        }
    }
    
    int main()
    {
        int n,m,L,R;
        while(scanf("%d%d",&n,&m)!=EOF){
            build(1,1,n);
            while(m--){
                ans1 = -inf,ans2 = inf;
                scanf("%d%d",&L,&R);
                query(1,1,n,L,R);
                printf("%d\n", ans1-ans2);
            }
        }
        return 0;
    }
    


    HDU 1754  I Hate It单点更新,区间查询最大

    #include <cstdio>
    #include <cmath>
    #include <iostream>
    using namespace std;
    #define FOR( i , a , b ) for ( int i = a ; i <= b ; ++ i )
    #define RE freopen("1.in","r",stdin);
    #define bug(x) cout<<#x<<":"<<(x)<<endl;
    
    #define Mid ((l+r)>>1)     
    #define lson rt<<1,l,Mid
    #define rson rt<<1|1,Mid+1,r
    
    const int maxn= 200000+5;
    const int inf=0x3f3f3f3f;
    int Max[maxn<<2];
    int ans1,ans2;
    
    void build(int rt,int l,int r)
    {
        if(l==r){
            scanf("%d",&Max[rt]);
        }else{
            build(lson);
            build(rson);
            Max[rt] = max( Max[rt<<1], Max[rt<<1|1]);
        }
    }
    void update(int rt,int l,int r,int pos,int num)
    {
        if(l == r && r == pos){
            Max[rt] = num;
        }else{
            if( pos <= Mid)
                update(lson,pos,num);
            if( pos > Mid)
                update(rson,pos,num);
            Max[rt] = max( Max[rt<<1], Max[rt<<1|1]);
        }
    }
    int query(int rt,int l,int r,int L,int R)
    {
        if(L <= l && r <= R){
            return Max[rt];
        }else{
            int tmp = -1;
            if( L <= Mid)
                tmp = max(tmp,query(lson,L,R));
            if( R > Mid)
                tmp = max(tmp,query(rson,L,R));
            return tmp;
        }
    }
    
    int main()
    {
    //    RE
        int n,m,L,R;
        char op;
        while(scanf("%d%d",&n,&m)!=EOF){
            build(1,1,n);
            getchar();
            while(m--){
                scanf("%c%d%d%*c",&op,&L,&R);
                if(op=='Q')
                    printf("%d\n",query(1,1,n,L,R));
                else
                    update(1,1,n,L,R);
            }
        }
        return 0;
    }
    


    HDU 1166 敌兵布阵

    单点更新,查询区间和【此题树状数组解法转见

    #include <cstdio>
    #include <cmath>
    #include <iostream>
    using namespace std;
    #define FOR( i , a , b ) for ( int i = a ; i <= b ; ++ i )
    #define RE freopen("1.in","r",stdin);
    #define bug(x) cout<<#x<<":"<<(x)<<endl;
    
    #define Mid ((l+r)>>1)
    #define lson rt<<1,l,Mid
    #define rson rt<<1|1,Mid+1,r
    
    const int maxn= 50000+5;
    const int inf=0x3f3f3f3f;
    int sum[maxn<<2];
    int ans1,ans2;
    
    void build(int rt,int l,int r)
    {
        if(l==r){
            scanf("%d",&sum[rt]);
        }else{
            build(lson);
            build(rson);
            sum[rt] = sum[rt<<1] + sum[rt<<1|1];
        }
    }
    void update(int rt,int l,int r,int pos,int num)
    {
        if(l == r && r == pos){     
            sum[rt] += num;
        }else{
            if( pos <= Mid)
                update(lson,pos,num);
            else        
                update(rson,pos,num);
            sum[rt] = sum[rt<<1] + sum[rt<<1|1];
        }
    }
    
    int query(int rt,int l,int r,int L,int R)
    {
        if(L <= l && r <= R){
            return sum[rt];
        }else{
            int tmp = 0;
            if( L <= Mid)
                tmp += query(lson,L,R);
            if( R > Mid)
                tmp += query(rson,L,R);
            return tmp;
        }
    }
    
    int main()
    {
    //    RE
        int n,m,L,R,t;
        char op[10];
        scanf("%d",&t);
        for(int cas=1;cas<=t;cas++){
            scanf("%d",&n);
            build(1,1,n);
            printf("Case %d:\n",cas);
            while(scanf("%s",op),op[0]!='E'){
                scanf("%d%d",&L,&R);
                if(op[0]=='Q')
                    printf("%d\n", query(1,1,n,L,R));
                else if(op[0]=='A')
                    update(1,1,n,L,R);
                else
                    update(1,1,n,L,-R);
            }
        }
        return 0;
    }
    




    Lazy


    区间成段更新

    Lazy:正常来说,区间改值,当更改某个区间的值的时候,子区间也该跟着更改,这样容易TLE。

    Lazy思想就是更新到某个区间的时候,就先给这个区间打上标记,标记内容是需要更新的值,并把子区间的值改为子区间对应的值,清除该区间的lazy标记;然后return,不去更新子区间。当下一次更新或查询等需要访问该区间的子区间的时候再把该区间的lazy和其他信息送回子区间。


    举个简单粗暴的例子:

    对应下面的那个图,假如目的是求和,现在要给[1,6] 的值都加2,那么我们从[1,12]->[1,6],然后[1,6]的sum值加上区间长度[ (6-1+1)*2 ],再把[1,6]的add[i]设置为2,就不再往下更新了【这里极大提高效率】。下一次更新/查询[1,6]的子区间时,我们将[1,6]原存的add值下传给[1,6]的两个直接子区间,再往下更新。假设在这种情况下,我们再更新[1,6]加3,则[1,6]的add值为2+3=5,然后我们查询[1,3],则从上往下经过[1,6]时把[1,6]的add值给了子区间[1,3]和[4,6],同时把sum[子区间]跟着子区间长度和add[父结点]改动,清除add[父节点]。【如果是查询间接子区间,则连续传递add值,也就是连续pushDown】


    详细例子:假设update()是区间改值,query()是求和,所有叶子区间的和都为1,则[7,8]和[7,9]在build()的时候就附上了值(图中绿色字体)。假设此时我们更新[7,9]的值,改为2,则线段树从[1,12]->[7,12]->[7,9],然后把[7,9]打上值为2的标记,求和(求和直接用区间长度*此时更新的值)然后不去更新[7,8]和[9,9]了,他们值仍然是2和1,lazy值为0。


    然后我们查询[7,8],当遍历经过[7,9]时

     if(add[i])
            pushDown(i);

    成立,把[7,9]的lazy标记2传给子区间[7,8]和[9,9],分别求这2个子区间的和,把[7,9]的lazy标记去掉,然后继续遍历,到[7,8]的时候直接返回答案。



    HDU 1698 Just a Hook 区间改值,求和

    #include <cstdio>
    #include <cmath>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    #define ll long long
    #define FOR( i , a , b ) for ( int i = a ; i <= b ; ++ i )
    #define RE freopen("1.in","r",stdin);
    #define WE freopen("1.out","w",stdout);
    #define MOD 10009
    #define bug(x) cout<<#x<<":"<<(x)<<endl;
    
    #define Mid ((l+r)>>1)
    #define lson rt<<1,l,Mid
    #define rson rt<<1|1,Mid+1,r
    const int maxn = 100010;
    int sum[maxn<<2],add[maxn<<2];
    
    void build(int rt,int l,int r)
    {
        add[rt] = 0;
        if(l == r){
            sum[rt] = 1;
        }else{
            build(lson);
            build(rson);
            sum[rt]=sum[rt<<1]+sum[rt<<1|1];
        }
    }
    
    void pushDown(int rt,int len)
    {
        add[rt<<1] = add[rt<<1|1] = add[rt];
        sum[rt<<1] = (len-(len>>1))*add[rt];
        sum[rt<<1|1] = (len>>1)*add[rt];
        add[rt] = 0;
    }
    
    void update(int rt,int l,int r,int L,int R,int z)
    {
        if(L <= l && r <= R){
            add[rt] = z;
            sum[rt] = (r-l+1)*z;
        }else{
            if(add[rt])
                pushDown(rt,r-l+1);
            if(L <= Mid)
                update(lson,L,R,z);
            if(R > Mid)
                update(rson,L,R,z);
            sum[rt] = sum[rt<<1] + sum[rt<<1|1];
        }
    }
    
    int main()
    {
    //    RE;
        int t,n,q,x,y,z;
        int cnt=1;
        scanf("%d",&t);
        while(t--){
            scanf("%d%d",&n,&q);
            build(1,1,n);
            while(q--){
                scanf("%d%d%d",&x,&y,&z);
                update(1,1,n,x,y,z);
            }
            printf("Case %d: The total value of the hook is %d.\n", cnt++,sum[1]);
        }
        return 0;
    }
    

    相关链接:线段树题目合集                  二维线段树                       线段树模板


    展开全文
  • 用游戏编辑器制作MOD脱颖而出

    千次阅读 2018-11-08 01:05:26
    用游戏编辑器制作MOD脱颖而出

    分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow

    也欢迎大家转载本篇文章。分享知识,造福人民,实现我们中华民族伟大复兴!

                    【导读】

    立志成为游戏策划的你,和千千万万的游戏玩家的不同之处在哪? 是你玩过很多的游戏?别人也玩过 是你游戏打得比别人好?也许电子竞技更适合你 是你对游戏的理解比别人深,知道如何设计出更好玩的游戏?嗯,是的,可是怎么证明呢? Action speaks louder than words! 最好的证明就是拿出你自己制作的游戏MOD,这胜过一万字的文字简历。可做mod难吗?不难,需要的只是你的一刻红心(立志成为游戏设计师的决心),两手准备(选对工具,找对方法),假以时日,你就能做出自己的第一个mod!

    本文将向大家介绍并推荐几款市面上主流的游戏编辑器,并结合一些作者的关卡制作经验,帮助新手在制作mod的过程中少走弯路。

    本文分为三部分:
    一、什么是MOD与编辑器;
    二、常用编辑器简介;
    三、制作MOD步骤。

    一、什么是MOD与编辑器

    什么是MOD?

    MOD,全称为modification,直译为“修改,改进”,但对于游戏来说,MOD指的是玩家使用独立游戏引擎或已发售游戏中自带的编辑器,利用游戏引擎或编辑器自带的,或自己制作并导入到游戏引擎或编辑器中的游戏资源,做出新的游戏地图,甚至新的游戏模式。早期的MOD可以追溯到FC时代的坦克大战,摩托飞车等,功能非常简单,只能利用游戏提供的资源,而且缺少了MOD的另外一大特征——分享性,所以也只局限于玩家的自娱自乐。MOD真正开始兴起是在PC游戏上,比如大家最熟悉的CS就是玩家利用《半条命》所带的编辑器做的,现在提到MOD也一般是指PC游戏,虽然现在的次时代主机也有一些MOD,并且可以利用网络分享,比如PS3的《小小大星球》,但受限于工具使用的不便性和局限性,也难成为主流。而就游戏类型来说,虽然基本各种类型的游戏都可以制作出MOD,但最成熟和最流行的是FPS和RTS,其余的像RAC和RPG虽然也有不少,但仍显小众向。

    什么是编辑器?——制作MOD的工具

    就像上面提到的,MOD是在独立游戏引擎或编辑器中制作的,那么我们先来对他们有点了解。

    游戏编辑器的定义和概念

    游戏地图编辑器,顾名思义,就是用来编辑游戏地图的工具,如果你玩过魔兽争霸或是帝国时代2,英雄无敌的话,应该会知道这几款游戏都附有地图编辑工具,可提供给玩家自行编辑地图关卡,地图编辑器就具有类似的功能。

    1.游戏引擎和游戏编辑器的区别

    虽然这两个词常常被混用,但它们是不一样的,游戏编辑器只是游戏引擎中用于整合资源的可视化工具,两者是从属关系。编辑器能制作什么类型的游戏,能实现什么功能,能在哪些平台上运行等等都是游戏引擎所决定的。举个最直观的例子,利用《战争机器》PC版附带的unreal编辑器,你只能制作出在PC上运行的类似《战争机器》的游戏,而不可能做出360版的《生化奇兵》(Bioshock)或《暗影帝国》(Shadow Complex),虽然他们都是通过unreal3引擎开发的。而虽然像魔兽3的编辑器能制作出塔防,Dota等跟原游戏有很大区别的新模式,而且能导入新的模型,但这些都是停留在脚本修改级别的,而不是真正的代码级别,所以只是算魔兽3的编辑器功能更开放而已。

    所以两者的大致区别是:

    1) 游戏附带的都只能叫编辑器,不能修改游戏底层代码,不能创建完全脱离原游戏的内容,使用某游戏编辑器制作出的MOD只能在该游戏中运行;
    2) 游戏引擎一般需要购买以获得授权,可以修改游戏代码,从而开发出各种类型的游戏,运行游戏不需要安装该引擎。

    2.工具的选择

    游戏引擎和游戏编辑器都可以实现制作MOD的功能,那么如何选择呢?

    除了是“成功游戏”的编辑器外,一个好的编辑器在我看来还应该有以下特点:

    1) 流行广,这意味着你更容易获得这个编辑器,接触到更多“同道中人”,而做出的MOD也有让更多玩家玩到的空间
    2) 技术新,对于想通过制作MOD,进而有机会进入游戏行业的同学们来说,在一步步制作MOD的过程中,更宝贵的收获是对当今游戏的制作方法有所了解,所以请尽量避免使用年代过于久远的编辑器,以免学到的是火星技术
    3) 教程多,大部分的MOD制作者都是靠自学掌握编辑器的使用,所以有丰富教程资源的编辑器能让制作者更容易上手,遇到问题也能马上找到解决方法;当然,以上几点是在广义的层面来定义一个我认为“好”的编辑器,但对于个体来说,最重要的是你自己的兴趣和动机,假如你是一个星际的死忠,梦想是加入暴雪或制作出超越Lost Temple那样的经典地图,那么星际的编辑器一定是你的最先考虑对象;假如你的梦想加入Epic,那么不管什么游戏类型,Unreal的重要性对你也就不言而喻。

    二、常用编辑器简介

    基于以上几点,我不会向大家介绍太多编辑器,除了求精不求多的原则外,很多编辑器我本人也没有用过,不会做无责任推荐

    UDK

    UDK是Epic于2009年11月正式对外发布的免费开发套件(下载地址:http://www.udk.com/download UDK;UDK开发案例:http://www.lhgamer.com/forum-47-1.html),拥有Unreal Engine3的绝大部分功能,可以制作出次时代品质的MOD。

    与其他编辑器最大的不同之处在于UDK是代码开放,所以它相当于是个引擎,而不只是编辑器,只要你有时间和精力,完全可以用其开发出全新的游戏,初期公布的几个游戏也都提供源代码学习。

    Unreal是笔者用过的最方便的编辑器,如果只是利用UDK提供的资源,那么利用它搭建关卡就像搭积木一样简单,相信只要通过一天的学习,你就能搭出自己的第一个关卡,当然这只是说工具易用性方面,如何搭建结构合理而充满乐趣的关卡是件非常不容易的事。本文最后会分享一些笔者的关卡制作经验给大家,希望能有所帮助。

    UDK中搭建关卡
    在UDK中搭建关卡

    另外,对于大部分没学过程序的同学们来说,也许比较怕听到“脚本”二字,可脚本对于实现关卡内互动元素又是必不可少的(比如开关门,触发机关等)。早期的脚本都是“脚本语言”,而UDK的脚本很简单,因为它是“可视化脚本”,在脚本编辑器Kismet中提供了很多功能模块的接口,你只需要想清楚逻辑,找到自己想要的接口,并通过一条条的线把这些接口连起来就可以了。

    可视化脚本编辑器Kisme
    可视化脚本编辑器Kismet

    教程方面网上非常多,想要深入学习的话,我推荐3D Buzz制作的视频教程,这是和Epic官方合作的,对UDK的几大功能都有非常详细的讲解。下载地址为:http://udn.epicgames.com/Three/VideoTutorials.html。听力不好的同学可以下载英文字幕:http://udn.epicgames.com/Three/rsrc/Three/VideoTutorials/3DBuzz_EN_SRT.zip。如果追求最短的时间了解最多的话,EA洛杉矶的美术师Waylon Brinck制作的视频教程很不错,在电驴上搜“[UDK-顶级虚幻引擎教材].gnomonunreal-CGFRIEND.iso”就能找到

    用UDK除了能制作出精美的MOD外,另外很重要的一点是UE3是游戏业内使用最广的商业引擎,不光国外,现在很多国内公司都购买了UE3,所以UDK是相当值得花功夫学习的,不夸张的说,学会UDK就相当于半只脚迈进了游戏公司。

    Bounty Arms
    Bounty Arms

    Dungeon Defense
    Dungeon Defense

    注:以上游戏虽都是利用UDK开发的,但美术物件和游戏逻辑都是新增的,而UDK初始所带的资源来自于《虚幻竞技场3》,利用它们只能做出《虚幻竞技场3》的新图。

    CryEngine2

    CryEngine

    CryEngine是德国Crytek公司开发的一款商业引擎,最初是为Nvidia的显卡演示而制作的,因为反响热烈转而全面开发,并希望能像Unreal一样打入商业引擎授权市场。该引擎所开发的游戏Crysis系列,因其“照片级”的画面一度被称为“最强的引擎”。目前该引擎发展到CryEngine3,但对应游戏Crysis2还未发售,所以我们还是只讨论CryEngine2(以下简称CE2)

    CE2并没有像UDK那样提供代码开放的版本,要获得CE2的编辑器Sandbox2,可以在:http://wiki.crymod.com/index.php/Mod_SDK_Information下载官方认可的MODSDK,或者是使用通过已发售的Crysis系列游戏中自带的编辑器Sandbox。

    相比Unreal,CE2出彩的地方是其对自然环境的模拟,地形(Terrain)编辑器异常强大,能够轻松制作出非常逼真的地形,另外它的道路制作工具(RoadTool),天气如云,雾等模拟也很强大。此外CE2的光照系统也很不错,当初演示时就是以其逼真的即时光影吸引了大家的眼球,对阳光的模拟(LightShaft),时间流逝的模拟(TimeOfDay)都很逼真。所以如果你想制作的关卡使用到大量户外地形,那么CryEngine2是非常好的选择。


    道路制作工具

    脚本编辑方面,CE倡导的理念是WYSIWYP(What You See Is What You Play,所见即所玩),大部分互动物体(SmartObject)都是在3D视窗内直接编辑的,也有类似Unreal的Kismet那样直观的编辑器(Flow Graph)


    编辑SmartObject

    教程方面的话CE2并没有UDK那么多,特别是像UDK那样成熟的视频教程,主要教程来自网上,中文的话可以去http://oldbbs.ali213.net/viewthread.php?tid=1723210,英文好的推荐去http://www.crymod.com,这里聚集着很多CE的MOD爱好者,资源很多,也可以利用论坛相互学习。

    虽然CE系列引擎并没有像Unreal那样广泛应用,但它本身无疑是非常优秀的,学习的过程就是一个接触世界一流引擎工作方式的过程,另外Crytek也抓紧了CE的推广工作,近年的CGDC(中国游戏开发者展)也常看到CE的身影,他们也将中国市场看得很重,说不定哪天国内也会有公司购买,先学习CE的同学说不定能成为国内第一批使用CE的开发者的。

    ScumEdit

    对于暴雪和《星际争霸2》,我想已不用介绍。因为当年《魔兽争霸3》的编辑器(WorldEditor,下简称WE)受到广大MOD爱好者的狂热支持,制作出了类似Dota,3C,各种塔防等经典游戏模式,成为了魔兽3的宝贵附加资源,延长了该游戏的可玩性。所以,在SC2中推出编辑器也是顺理成章的事。(SC2的编辑器目前还没有正式名,官方目前称Scumedit,以下简称SE)。由于SC2有中文版,所以SE也对应的是中文版的,下载地址网上很多,自己可百度之。

    SE可以说是WE的全面升级强化版,是一款深入贯彻MOD精神的编辑器,功能的开放程度很高,除了做出WE所能做的任何模式外,在自定义camera,UI,操作和大量的脚本功能下,SE还可以制作出横版动作游戏和2D射击游戏等。功能强大得让人开玩笑说SC2其实是SE的一个MOD。


    利用SE制作的横版动作游戏

    如果你用过WE,对SE应该上手很快,连界面都很相似。SE包含了很多的子编辑器,包括地形编辑器(Terrain),数据编辑器(Data),触发器(Trigger)等。地形编辑器的上手度也很简单直观,只需简单的教学就可搭出关卡来。


    SE的地型编辑器界面

    当然,就像WE一样,SE的核心也是触发器和数据编辑器,但两者都比WE强大很多。触发器是负责游戏逻辑的,数据编辑器是创建和修改各种参数的,这是SE中最难掌握的,用好这两个东西也是菜鸟和高手的区别,可以先了解基本功能,然后打开别人做好的图来慢慢学习。


    触发器中设置复杂的游戏逻辑面


    数据编辑器中几乎可以修改任何参数

    脚本方面,据说是基于C语言的,这个我还没研究过。教程方面的话,由于SE刚公布不久,现在大家都是初级研究阶段,所以各种论坛的研究帖都很多,网站我推荐http://forums.sc2mapster.com/, 国内的话没有找到很好的,不过http://bbs.sc2.com.cn/thread-16755390-1-1.html有不错的教学贴

    其它编辑器

    以上介绍的都是3D的编辑器,其实也有很多不错的2D编辑器,MM们估计会比较喜欢2D的,而且用一下2D编辑器也能补充一下自己对2D游戏制作的知识,下面就简单介绍两款比较流行的

    RPG Maker XP

    RPG MakerXP是日本的Enterbrain发行的2D RPG制作工具RPG Maker的最新版,支持 640×480像素分辨率,32色真彩色图像,功能比较齐全,使用比较简单,可以导入自定义的图片,动画和BGM,脚本使用Ruby语言编写,可以制作出非常有趣的游戏内容。网上有非常多的对应资源可以下载。 编辑器下载地址:http://bbs.66rpg.com/RMXP.exe  推荐教程:推荐网站http://bbs.66rpg.com/,里面有很多教程


    RPG Maker XP界面

    Action Game Maker

    同样是EB社的作品,在RPGMaker大获成功后推出的ActionGameMaker更加强大,它不仅支持制作的游戏类型扩大到ACT,ARPG和STG三大类,而且支持包含Window平台和XNA,所以可以制作出在360Arcade平台上运行的游戏。

    在使用上和RPGMaker比较相似,都是面向所有人的,所以界面相当的简单直观,不需任何编程知识都可以制作出有趣的游戏。而且内建的范例游戏Simple系列也可以帮助你最快的制作出自己第一款的游戏。 编辑器下载地址:http://bbs.66rpg.com/AGM.exe  推荐教程:同样推荐网站http://bbs.66rpg.com/


    AGM中制作ARPG的界面


    AGM中制作ACT的界面

    三、制作MOD步骤

    ◆ 可为与不可为
    首先你得清楚你选的编辑器能做什么,而在你有限的时间和能力下又能掌握多少,然后再开始构思你的MOD的复杂度和规模。当然你也可以和几个人一起合作制作一个MOD,这样不仅大大增加了效率,还能培养团队合作意识,对将来的工作也很有帮助。

    ◆ 学习MOD的方法
    除了教程外,学习MOD最好的方法就是打开别人做好的图,点开各种编辑器看别人怎么用的,然后试着自己改改看产生的效果;如果可以复制的话,复制一些已设置好的复杂功能,然后再自己修改也是一个很方便的方法(比如WE中的塔防敌人波数配置,自己配的话非常麻烦,但在别人的基础上改的话就很简单了)

    ◆ 以策划的思维与流程来进行
    对于策划来说,制作MOD主要体现的是你的创意能否实现,你的关卡是否好玩,而不是你的MOD好不好看—那是美术的事。所以,制作策划的MOD就应该是以策划的思维和步骤来做,下面8条是我以自己的经验所列出的关卡制作大致步骤,希望能给准备开始动手的同学做点参考:1. 研究同类游戏 2. 搜集参考资料,获得灵感 3. 绘制2D关卡图 4. 搭建最简单的可玩关卡 5. 反复测试和修改 6. 美化关卡 7. 获取别人的反馈 8. 根据反馈优化关卡

    1. 研究同类游戏 当你脑中对即将制作的MOD有了大概轮廓,比如游戏类型,镜头表现,操作方式,核心玩法,地图尺寸等,是不是马上就可以开始动工了呢?别急,先看看市面上有没有和你的游戏相似的,看看哪些成功了,哪些失败了,然后总结哪些是可以借鉴的,哪些是应该避免的。

    2. 搜集参考资料,获得灵感灵感不光是靠想的,很多时候是需要激发的。当我们开始构思自己的关卡时,可以充分利用各种各样的资料获取灵感,游戏当然是非常重要的一项参考,但千万别局限于游戏,我们还可以从电影,动漫,图片,建筑,地图,甚至机械构造,解剖学等中受到启发,如果某一刻突然获得什么灵感了,记得要把它记下来,以免睡一觉又忘了。

    3. 绘制2D关卡图 当你对关卡有想法的时候,别急着就开始用编辑器做,先动手把它画下来,因为2D的总比3D的快,先在2D上验证你的关卡结构,流程,节奏,尺寸等合不合适,以免在3D中做到一半发现不对时又重新返工。绘图的工具我建议以最快和最简单的纸和笔开始,注意标明图示和比例,在不需解释的前提下让别人也看得懂的2D关卡图才是合格的。如果想作为简历发送,可以利用Visio,Photoshop或Google Sketchup等重新绘制一下。

    4. 搭建最简单的可玩关卡(沙盒关卡) 2D的关卡图验证完毕后,接下来就可以用编辑器搭建你的关卡了,这个阶段的目的是在可玩的游戏环境下验证你的关卡是否达到你画2D图时的构思,比如关卡的尺寸是不是合适,大体结构是不是合理,流程是不是紧凑等。“最简单”的目的是为了省时间和方便修改,利用编辑器提供的最基本的模型,贴图和物件就行了。

    5. 反复测试和修改 在编辑器里搭建完关卡的雏形后,就自己试着玩玩,把自己不满意的都记下来,然后一条条的修改,改完后再继续测试,然后再修改,直到自己满意为止才开始下一步。

    6. 美化关卡 如果你觉得自己的关卡尺寸,结构和流程都差不多了,玩起来也基本实现自己的初步构想了,那么就可以美化关卡了:利用编辑器提供的各种模型,贴图,特效,动画等使你的关卡漂亮起来。如果你有美术的合作同学,而且编辑器可以导入美术资源的话,你们还可以制作出全新的美术风格来。

    7. 获取别人反馈 获取别人反馈是使自己关卡不断提升品质的最好方法。一个关卡自己玩久了难免会失去判断力,自己在怎么测也不可能发现所有问题,而别人可能一下就能指出你从没想到过的不足之处,所以获得别人反馈是非常重要的。你可以邀请自己的朋友来玩,先静静的观察他们玩的过程,记录下他们对关卡感到迷惑或经常会死的地方,然后再询问他们对你的关卡的意见。另外关卡也可以发布到网上,让更多的人玩到,获得更多的反馈。

    8. 根据反馈优化关卡 收集到玩家们的反馈后,你可能会发现玩家的反馈有时候是非常主观的,所以不可以全听,但如果大部分玩家都反映出某一个问题,那么就是共性的不足,值得引起你的重视并该思考如何可以改进了。改进之后有时间和条件的话,再重复第7步和第8步,理论上这是一个无止境的循环,就看自己什么时候觉得满意了。

    ◆ 记录并展示你的关卡

    如果你想把你的关卡作为简历投递的话,你要知道收到简历的人会真正去玩你的关卡的几率是相当低的,一是因为不一定能运行(没有对应的编辑器或游戏),二是也没有时间。所以最好的办法就是视频录制,并将录制的视频发到网上,然后在简历中附上该视频的链接。在录制视频时要展示你关卡的亮点,最好有配音讲解,时间最好不超过3分钟。对方如果感兴趣的话再想办法能让他玩到你的游戏。

    另外,简历中最好能附上你所制作的2D关卡图,并附上关卡的说明,有时这比视频还有效。

    【版权声明】本文由GA游戏策划新手营独家约稿 未经许可不得转载

    作者简介:

    snowinter 自我简介:毕业于某师范大学生物学专业,04年末以好奇的心态在育碧(Ubisoft)做了三个月的tester,预谋转职Level Designer失败后回去了老家,沦落为一名人民教师,“误人子弟”长达近两年,因对转职事件一直耿耿于怀,07年毅然辞职杀回上海滩,在GA策划班学习后有幸进入了维塔士(Virtuos),成为了一名“业内人士”,现就职于英佩(Epic Games China),担任某未公开项目的关卡设计师参与过的项目平台有NDS, PSP, Wii, PC,类型包含FPS,ACT,RAC等联系方式:snowinter82@hotmail.com

               

    给我老师的人工智能教程打call!http://blog.csdn.net/jiangjunshow

    这里写图片描述
    展开全文
  • 前体(金属有机分解(MOD))油墨用于将2D和3D打印的导电结构直接制造到基材上。 通过配制包含多种金属的纳米合金结构,存在改变化学和物理性质的机会。 在本文中,通过混合铜和镍前驱体墨水在真空中烧结来制造铜-...
  • 《星露谷物语》mod安装超详细教程

    千次阅读 2021-06-01 17:44:29
    《星露谷物语》mod安装超详细教程 《星露谷物语》是一个基于C#的极高开放性的游戏。目前国内玩家接触途径主要为腾讯代理的WeGame和Steam。两者安装mod的操作大同小异,我会在文章中写出。 <iframe ...
  • 一般MOD制作的工具集合 解压即用 有 MIX提取器 MIX写入器 VXL单位制造器 PAL编辑器 CSF语言编辑器 地图编辑器 SHP建筑编辑器 兵种属性修改器(改RULESMD.INI) 电影文件制作器 HAV编辑器 AI编辑器 教程及常用INI文件...
  • 增加了98个新方块,5个物品,2种液体和31个单位,计划增加更多。 该mod尚未完成,我们已经意识到了拼写问题。 学分 Oreo的想法和JSON CoinCaribou2070 / Chickenloser编写的Sprites和JSON 达芬特制造的精灵 ...
  • 使用说明: ...2、安装“Social-Club-Setup”(这个文件在游戏目录里面) 3、点击“GTAVLauncher”进入游戏修改器使用说明:进游戏按F4打开修改器菜单小键盘2846上下左右小键盘5确定 小键盘0返回(添加载具在修改器内...
  • Cake 的(又名 pspchucky)表达式 2 合集 这是我在过去 4 年学习编程时编写的每一个 Wiremod Expression 2。 没有评判 :victory_hand: 其中许多要么未完成,要么已损坏,要么只是一次性使用。
  • MOD法制备SrTiO3薄膜研究,陈文祥,丁灵效,本文采用金属有机物沉积(MOD)方法在双轴织构的Ni-5at%W合金基带上制备YBCO超导带材的SrTiO3(STO)缓冲层。研究了退火温度以及单层薄膜厚�
  • alloys-mastering-mod-源码

    2021-04-02 22:06:10
    合金掌握 “合金精通”是将Minecraft中的矿石和合金添加到我的世界的mod
  • MOD3干扰导致掉线.docx

    2021-09-17 11:09:49
    专注于分享4/5G网优资料:包括网络优化基础原理资料、各厂家常用网管指导、接入、切换、掉线、高丢包、干扰分析、速率、容量负载均衡、覆盖单验簇优化、各类网优常用工具合集
  • 微信小程序小技巧系列《一》幻灯片,tab导航切换: http://www.wxapp-union.com/portal.php?mod=view&aid=70 微信小程序小技巧系列《二》show内容展示,上传文件编码问题 : ...
  • hs赠送人物.zip

    2019-06-20 20:57:32
    HoneySelect的人物模型一般都放在游戏根目录下的UserData\chara\female下,都是png格式,我这个解压后是一个完整的female文件夹,建议你直接把内容拷贝进去,不要直接覆盖,当然也可以直接覆盖,我觉得我的角色模型...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 12,777
精华内容 5,110
关键字:

并合mod