设为首页收藏本站|繁體中文

Project1

 找回密码
 注册会员
搜索
楼主: harinlen
打印 上一主题 下一主题

[版务] 【活动】【VA】RGSS 3 入门教程大家写(更新13/02/15)

  [复制链接]

Lv1.梦旅人

梦石
0
星屑
240
在线时间
9 小时
注册时间
2013-7-18
帖子
4
111
发表于 2013-7-23 21:09:39 | 只看该作者
用了一天看完帖子,总结一句话:又乱又坑!
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
50
在线时间
17 小时
注册时间
2013-7-18
帖子
16
112
发表于 2013-7-28 14:07:57 | 只看该作者
感觉还可以——在每行脚本后都添加上注释这样看起来会简单很多……

{:2_270:}

最后总结一下:
RUBY简单来讲就这些个东西
变量、定量 数组
循环函数
条件函数
定义方法和定义类

像 msgbox  ruturn这些个东西死记下来或者弄一个TXT文档保存下来,用的时候直接翻就行了……

{:2_263:}面对对象的语言不难……
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
49
在线时间
34 小时
注册时间
2013-7-24
帖子
42
113
发表于 2013-9-29 16:08:06 | 只看该作者
加油呢~学习了。
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
300
在线时间
1 小时
注册时间
2013-9-29
帖子
4
114
发表于 2013-9-29 23:38:31 | 只看该作者
怎么得素材????
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
300
在线时间
1 小时
注册时间
2013-9-29
帖子
4
115
发表于 2013-9-29 23:39:26 | 只看该作者
制作不来游戏啊,求素材,怎么可以的素材啊???!!!!

点评

请勿灌水  发表于 2013-9-29 23:59
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
129
在线时间
124 小时
注册时间
2011-9-12
帖子
76
116
发表于 2013-12-10 14:34:21 | 只看该作者
本帖最后由 mxymxy 于 2013-12-10 14:44 编辑

话说,活动还在进行吗?看你们写得有些地方貌似不是很详细,新人来写一个大丈夫?



单纯多态(上)

什么是面向对象?
继承、多态、封装。课本如是言。
但是仔细想想我们发现,只有继承的话几乎什么都干不了,封装的话固然可以是代码更容易看懂,但是函数不能封装么?能,不但能,而且封装的很好。我们只需把类转化成hash表,然后所有实例方法都对表操作,像是WinAPI做的一样。

因此真正重要的只有一个多态而已。所谓多态就是同一个对象拥有多种状态,既是A又是B。一个子类,既是子类的实例,同时又是他的任何一个父类的实例。因此,一切对于父类可行的方法、过程、操作,皆可以自动地对于子类成立,而不需写额外的版本。这极大地简化了我们的代码。(这是课本上的理论,具体之后再谈)

Ruby的多态机制源于Smalltalk。数据是对象,类是对象,凡此一切皆是对象。既然都是对象,那么数据类型就自动的消失了。并不是Smalltalk/Ruby没有整型、字符之类的,而是本来就不需要——他们分别是对应类的实例,在传统意义上都是对象类型。而这个对象类型,是包容万象的。

而Smalltalk/Ruby的一切运算操作,都可以理解为对对象发送消息。像是加a+b或者a.+b,就是给对象a发送符号为:+的消息,带着参数b;(你也可以用send方法实现这一过程)而a收到这个消息之后调用a的+(b)方法处理。不信请看:(这里为了方便讲解采用了smalltalk的代码风格,不是教大家写这种不适合人类阅读的代码)
  1. a = 1
  2. p (a.+2).*3 #=>9
  3. # a接收了:+消息,参数为2,由Fixnum.+(2)把自己变成3
  4. # 然后3再接收:*消息,参数为3,,由Fixnum.*(3)把自己变成9
复制代码
这种上世纪70年代就诞生了的对象、消息思想是出人意料的简单,但是极其强大。我们甚至可以用对象和消息机制实现逻辑演算(控制结构、循环之类的):
  1. class PTrue < Object
  2. end
  3. class PFalse < Object
  4. end

  5. $MTrue = PTrue.new
  6. $MFalse = PFalse.new

  7. class PTrue < Object
  8.   def AND b;        b;                      end
  9.   def OR b;          self;                    end
  10.   def NOT b;        $MFalse;             end
  11.   def IF &b;          b.call;                 end
  12.   def UNLESS &b; nil;                     end
  13.   def EQU b;         b.is_a? PTrue;   end
  14.   def inspect;        "真";                 end
  15. end

  16. class PFalse < Object
  17.   def AND b;            self;            end
  18.   def OR b;              b;               end
  19.   def NOT b;            $MTrue;      end
  20.   def IF &b;              nil;              end
  21.   def UNLESS &b;     b.call;         end
  22.   def EQU b;             b.is_a? PFalse;  end
  23.   def inspect;            "假";           end
  24. end
复制代码
然后:
  1. ($MTrue.AND $MFalse).UNLESS {p "1"}  #=>”1”
  2. ($MFalse.OR $MTrue).IF {p "2"}   #=>”2”
复制代码
(不要觉得荒谬,smalltalk真的是这么实现的,而且做的很好!Ruby你如果外在认为它是这么实现其逻辑的,也根本不会有任何矛盾!)

那么既然是这样,我们想要实现一个普适的功能,就完全不用考虑什么类型、继承。只需要照做就好了、比如说,我们要实现一个函数,能把一个数组中所有的元素相加求和(假设Ruby的数组没那么强大好了):
  1. def PADD l
  2.   ret = l.[] 0
  3.   i = 1
  4.   while i < l.size
  5.     ret = ret.+ (l.[] i)
  6.     i = i.+ 1
  7.   end
  8.   return ret
  9. end

  10. p (PADD [1,2,3,4])  #=>10
  11. p (PADD ["a","b","c","d"])  #=>”abcd”
复制代码
看到了?我们根本不用管数组里存的是什么。假设我们有这样一中数字,它只会和比自己大的数相加,那么
  1. class Fucknum
  2.   def initialize i
  3.     @num = i
  4.   end
  5.   def num
  6.     @num
  7.   end
  8.   def inspect
  9.     @num.to_s
  10.   end
  11.   def + b
  12. return self unless b.is_a? Fucknum
  13.     @num = (b.num.+ @num) if b.num.> @num
  14.     return self
  15.   end
  16. end

  17. a = Fucknum.new(1)
  18. b = Fucknum.new(2)
  19. c = Fucknum.new(3)
  20. d = Fucknum.new(4)
  21. e = Fucknum.new(5)
  22. p (PADD [a,b,c,d,e])  #  =>7
复制代码
我们根本不需要写多余的代码,就能在不知道数组内部核心逻辑的情况下实现“求总和”这一操作。相应的,调用这方法的一方也不需要知道数组内部的实现机理,只需要放心大胆地把数据带进去就可以了!什么虚函数,什么向上映射,统统不用去管他。对父类成立的方法,对子类就一定成立。甚至于说,连继承关系都可以抛开,对能处理某消息的对象成立的方法,对一切能处理同样消息的对象就一定成立。(应该是唯一的特例:用元编程作死者请自重。不过如果你看不懂这句话,那么我想你没事)这就是传说中的鸭子类型匹配(能嘎嘎叫的就能当成鸭子一样处理,不需额外的代码)。这在C++什么的限定类型的语言里根本是不可想象的。纯粹的面向对象“生来就是强大的,其次在逐步增加效率;而不是在保证效率的基础上,把各种各样的杂碎堆上去,好让他强大。”

说了这么半天,到底我们为什么要采用多态和面向对象?仅仅是书上说的省代码?不。更重要的是,符合人类的认知范畴。当我们看到一个椅子,你的第一反应是“这是原子构成的物质”还是“这是椅子”“这是可以坐的东西”?显然是后者。程序员看待数据,本也应该一开始就认识到“这是某类东西”“他可以干什么”,而不是“他的机理是这样的,所以我要这样拿他干什么”。程序不仅仅是一段实现功能的英文,他更是一种逻辑,一种思想,一种描述世界的文字形式。而面向对象和多态给了我们这样的可能,使得我们可以去坐一切可以坐的东西,不管他是桌子、椅子还是床。因此我们的精力就一定程度上放在问题本身,而不是机器实现上了。





简单谈了一下面向对象的强大,以及我们为什么选择他,还有多态在Ruby中极为简单的实现。虽然还是有点不太清楚,但是已经是我的能力极限了……多类继承啥的下次再说吧……

如果有问题请及时提出,大不了扣分,跪求不删……



点评

会有一群菜鸟们连指针都指不清楚怎么回事就很大胆的用上了C++,给世人写出了漏洞百出,庞大而累赘的(模板模板模板模板模板类类模板类模板)  发表于 2014-6-21 22:04
可以形成可怕的迭代,能用的怎么样完全取决于作者的能力。不是C++太累赘,而是Bjarne设计C++的时候只是考虑到给大神们用着方便,没有想到  发表于 2014-6-21 22:02
模板的引入并不是因为效率,因为模板本身就是图灵完备的,可怕的是模板本身可以里面再套模板,而结构体、函数、模板和类之间  发表于 2014-6-21 22:00
我并没觉得C++的模板很累赘,用template实现类似的功能并不需要很多代码,而且绝对会比Ruby、Python这里的实现更加简单易懂。  发表于 2014-6-21 21:58
嗯,C++的模板和auto的确可以实现,但事实上只是一种补救措施而已,所以显得累赘。C++为了效率已经牺牲很多了,所以只能引入一大堆概念来弥补……  发表于 2013-12-15 08:44

评分

参与人数 1星屑 +10 收起 理由
无脑之人 + 10 高端

查看全部评分

回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
117
在线时间
552 小时
注册时间
2012-8-18
帖子
1429
117
发表于 2013-12-10 23:36:25 | 只看该作者
说真的刚开始看的时候还以为各种程序猿卖萌,里面各种问题,虽然后来雪姐姐挑出了很多233,如果可以的话还是建议系统的整理一下,对于初学者来说「只要教程说的都是对的」
--------------------
心情好过来插一脚2333
--------------------
迭代器制作
嘛,学了雪姐姐讲的块和迭代器之后应该会很崇拜这类神奇的事物吧?不过呢,实际上我们也可以运用所学姿势自己创造迭代器哦~
以RGSS内置的类型Table为例,这个高端的多维数组是没有任何用来做迭代器的方法的!也就是说他成了一个我们可以随便黑的小玩具啦2333
假设我们设置了一个三维数组atp=Table.new(5,5,5)「ATP???」我们希望能够这样:
atp.each do |item|
  p item
  # do other things ...
end
通过这种方式把125个值都打印一遍,下面我们开始丢节操,啊不,改Table了
class Table
  def each
    #...
  end
end
我们通过这样的方式给Table追加定义一个each方法,然后这个方法应当怎么写呢?当然是迭代啦!用已有的迭代器来迭代这些值:
class Table
  def each
    0.upto(xsize-1) do |x|
      0.upto(ysize-1) do |y|
        0.upto(zsize-1) do |z|
          #...
        end
      end
    end
  end
end
对upto不熟悉的可以用(0...xsize).each来代替,或者用for x in 0...xsize
如果使用者提供了一个块 我们该怎么调用他呢?
那就是yield
class Table
  def each
    0.upto(xsize-1) do |x|
      0.upto(ysize-1) do |y|
        0.upto(zsize-1) do |z|
          yield self[x,y,z]
        end
      end
    end
    self #根据国际惯例【噗】each的返回值为self,不加的话会返回0...xsize或者0哦
  end
end
在不考虑Table不同维度和each不带块返回Enumer的新特性的情况下【喂喂喂你究竟少加了多少东西!】,一个each迭代器就这么完成了,不过建议不要include Enumerable 可能会出问题的2333 Enumerable里面的其他迭代器就交给读者们自己去实现啦
-----------------
小结:
对于一个数据结构,啊,还是叫「可以用来迭代的类」比较好,如果要构造他的迭代器,我们只需要拥有访问和改变(某些迭代器的要求例如map!)自己的成员的权利,并且有能够找到所有的成员的办法。
-----------------
课后习题(万恶的作业君泥垢了!):
为Table写一个map_with_index_unless_zero!
要求:
1.能够接受{|item,x,y,z|}的一个块
2.遍历所有成员,对非0成员执行块,将块的返回值作为该成员的新值
3.按照国际惯例返回self

点评

是应该系统地整理下了,不过貌似这个贴坑了……  发表于 2013-12-11 11:12
我要填坑!我要背单词!我要学日语!我要每天锻炼!
好吧呵呵= =
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
129
在线时间
124 小时
注册时间
2011-9-12
帖子
76
118
发表于 2013-12-11 19:47:55 | 只看该作者
本帖最后由 mxymxy 于 2013-12-11 19:51 编辑

单纯多态(下)

昨天我讲到了单纯的多态,有过C++编程经验的人应该可以感受到Ruby语言本身的强大,根本不需要泛型,不需要虚方法,就实现了C++整了一堆概念都搞不好的问题。
那么,今天来讲一个最有争议的问题:多类继承。



不知大家注意到没,生活中的很多对象都不只有一个属性:椅子既可以坐(”Furniture”类的实例)又可以烧(”Wood”类的实例)。但是Ruby,还有其他大多数的语言,都只支持单类继承。也就是说Chair<Wood或者Chair<Furniture二选一,剩下的即使方法一样,也不能继承!纯生的面向对象——Smalltalk类大部分方法是共同的,所以几乎用不到多重继承。然而C++和Ruby呢?显然,他们需要(考虑istream类、ostream类和iostream类)。

Ruby不支持。也许你会疑惑为什么?不过我得承认在语言本身偏于杂乱(吸收多家语言杂合)的情况下,这样的选择是正确的。比如说,C同时继承A、B,而AB有一个重名的方法(例如initialize),那么运行的时候怎么算?覆盖,还是分立?如果像C++一样选择分立,那么,假设A、B又有一个共同父类D,那A、B中共有的D的部分怎么算?依然分立?那样不仅浪费空间,功能上也是不恰当的。比如说Wood和Furniture都是Good类的实例,Good类有一个Price(价格)的变量,那么当Chair调用Wood的父类的方法修改价格的时候,它从Furniture的父类那里得到的价格应该也应该改变。C++为了解决这个冲突又增加了虚继承等机制,不仅使语言内质变得繁琐杂乱,而且增加了额外的开销,还有可能造成其他冲突(最晚辈派生类的初始化问题等)。因此前辈们提倡在C++系列(不包括Ruby)中使用二次封装或直接继承公共基类而不是多重继承是有道理的

然而,这里是重视语言强度胜过内在实现的Ruby,从理念上,它应该是尽一切可能使程序员把目光放在问题本身而不是实现上。从语言的哲学上,它支持纯粹的面向对象,没有数据类型差异和向上映射,它也不能支持多类继承不是很不好吗?于是它引入了一个新概念——MixIn(以下翻译作“混入继承”)。但是没有引入新的对象,而是把本来只是作为命名空间的模块直接拿来当做混入方法的容器了,这个是安全的。请看下例:
(附注:模块的类别其实是Class类的基类,所以二者表现相似,只是模块不允许实例化而已)
(附注2:昨晚楼上那位大神讲了Table.each真是太好了,因为我正需要这个!)

Ruby中有可比较对象(支持between?和各种比较运算符),有可枚举对象(支持all,any,collect,find等)。我们如果有一个表,它既可比较(字典序),又可枚举,怎么办呢?可以观察到可比较对象和核心是<=>方法(类似于C++中的纯虚方法),其他的如between?等在该方法实现之后其实现都大同小异;而可枚举对象的核心是each方法。于是我们这样:
  1. module PEnumerable
  2.   def all?(&b)  # 不用做命名空间时,方法定义不要加self
  3.     ret = true
  4.     self.each {|v| ret = false unless b.(v) } # 这里使用到了未定义的核心方法each
  5.     return ret
  6.   end
  7. end

  8. module PComparable
  9.   def ==(b)
  10.     return self.<=>(b) == 0
  11.   end
  12.   def >(b)
  13.     return self.<=>(b) > 0
  14.   end
  15.   def <(b)
  16.     return self.<=>(b) < 0
  17.   end
  18. end

  19. class Table
  20.   include PEnumerable,PComparable # 这里混入继承了多个模块,作为多类继承的替代。
  21.   # 为了演示这一实现,楼上不要include的话我就果断无视了啊!
  22.   def each
  23.     0.upto(xsize-1) do |x|
  24.       0.upto(ysize-1) do |y|
  25.         0.upto(zsize-1) do |z|
  26.           yield self[x,y,z]
  27.         end
  28.       end
  29.     end
  30.     self
  31.   end
  32. def <=>(b)
  33.     0.upto([xsize,b.xsize].min-1) do |x|
  34.       0.upto([ysize,b.ysize].min-1) do |y|
  35.         0.upto([zsize,b.zsize].min-1) do |z|
  36.           return  1 if self[x,y,z]>b[x,y,z]
  37.           return -1 if self[x,y,z]<b[x,y,z]
  38.         end
  39.       end
  40.     end
  41.     return 0
  42.   end
  43. end
复制代码
然后试一下:
  1. tb = Table.new(2,2,2)
  2. tb[0,0,0]=0
  3. tb[0,0,1]=1
  4. tb[0,1,0]=2
  5. tb[0,1,1]=3
  6. tb[1,0,0]=4
  7. tb[1,0,1]=5
  8. tb[1,1,0]=6
  9. tb[1,1,1]=7
  10. tb.each {|v| p v}   # 输出0-7
  11. p tb.all? {|v| v > 0}  # =>false
  12. p tb.all? {|v| v < 8}  # =>true
复制代码
再试下比较:
  1. t2 = Table.new(1,1,1)
  2. t2[0,0,0]=1
  3. p tb < t2 # => true
复制代码
实际上Ruby1.9实现了很完备的Comparable模块和Enumerable模块,我们可以直接用。而RGSS3的其他模块大多是用来当命名空间的,即使混入继承了也没加入啥新方法,所以就不用。而Math这个模块特殊,它的每一个方法都同时定义了self.sin(x)和sin(x)两个实现相同的版本,所以既可以混入继承又可以当命名空间调用。只是注意当你混入继承某个模块的时候一定先把这个模块的核心方法实现了,否则会爆出“未定义的方法”错误。

最后,我们如何给模块的方法改名?直接alias是不行的。国外的某大神教我们这样做:
  1. module DataManager
  2.   
  3.   # 设置别名,很奇葩的方法→_→
  4.   class <<self
  5.     alias :load_database_HZ2 :load_database
  6.     alias :setup_new_game_HZ2 :setup_new_game
  7.   end
  8.   
  9.   #--------------------------------------------------------------------------
  10.   # ● 读取数据库
  11.   #--------------------------------------------------------------------------
  12.   def self.load_database
  13.     load_database_HZ2
  14.     # 做某事
  15.   end
  16.   
  17.   #--------------------------------------------------------------------------
  18.   # ● 设置新游戏
  19.   #--------------------------------------------------------------------------
  20.   def self.setup_new_game
  21.     setup_new_game_HZ2
  22.     # 做某事
  23.   end
  24.   
  25. end
复制代码


不知道多久之后的下一章我打算讲lambda演算。老实说,整个66RPG上讲块、方法、lambda表达式三者讲得清楚的帖子我就见过一个,还只是说了下区别,没有讲其中的逻辑……

点评

至于lambda演算本来只是一种奇异的数理逻辑形式,后来在LISP语言里变成一种编程思考方式。而Ruby语言的发明者本来是LISP大神,所以就部分借鉴了。  发表于 2013-12-12 16:30
@无脑之人 :嗯,each我想已经符合要求了,块内用return的话三重循环应该会一步跳出。  发表于 2013-12-12 16:29
其实不让include的原因是这个each提供的参数可能不符合Enumerable的要求XD……另外lambda什么的也许对于其他语言会更明显一点?【好吧我承认我不懂lambda  发表于 2013-12-12 12:23
本帳號已經作廢。新ID是「湖中神劍」。
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
1675
在线时间
15 小时
注册时间
2013-12-9
帖子
1
119
发表于 2013-12-13 16:48:42 | 只看该作者
不知该说些什么。。。。。。就是谢谢
回复 支持 反对

使用道具 举报

Lv3.寻梦者

梦石
0
星屑
1268
在线时间
409 小时
注册时间
2012-8-7
帖子
1536
120
 楼主| 发表于 2013-12-14 13:28:40 | 只看该作者
好久没回来了,现在再看面向过程的自己写的东西真是很多都没理解啊……

点评

C++的这种方式很喜欢,不失C的简介,也可以OO,当然如果是个写GTK的Geek说C++累赘我也没啥意见了……  发表于 2014-6-22 16:27
同意呢,C++的GP的确很强大,一点也不比OOP差呢  发表于 2014-6-22 15:28
……不至于吧……  发表于 2013-12-15 08:44


回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册会员

本版积分规则

拿上你的纸笔,建造一个属于你的梦想世界,加入吧。
 注册会员
找回密码

站长信箱:[email protected]|手机版|小黑屋|无图版|Project1游戏制作

GMT+8, 2024-12-22 15:01

Powered by Discuz! X3.1

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表