SlideShare a Scribd company logo
页游开发中的 Python 组件与模式
  赖勇浩( http://laiyonghao.com )
          2012-10-21
             上海
去年我来过……
回顾……
• 幻灯:
  http://www.slideshare.net/laiyonghao/py
  thon-webgame-10452102
• 录像(上海 45 分钟版):
  http://e.gensee.com/v_3df867_14
• 录像(广州 91 分钟版):
  http://v.youku.com/v_playlist/f16785412
  o1p4.html

         偏向于“最佳实践”的经验分享
今天不一样……
直奔主题!
class Player(object):
  def signin(self, usr, pwd):
     ...
     self._signin = True
  def do_sth(self):
     if not self._signin:
          self.client.need_signin()
          return
     ...
有什么问题?
def   do_sth_1(...
def   do_sth_2(...
def   do_sth_3(...
def   do_sth_4(...
…
一般这样解决掉……
@ensure_signin
def do_sth(self, *a, **kw):
    …

           Decorator !!!
还有什么问题?
def   do_sth_1(...   if not
def   do_sth_2(...     self._signin: ...
def   do_sth_3(...   if not
                       self._in_battle: ...
def   do_sth_4(...
…                    if not
                       self._is_dead: ...
                     ...
还是这样解决掉?
@ensure_signin
@ensure_in_battle
@ensuer_is_alive
def do_sth(self, *a, **kw):
    …

               ???
好像哪里不对……
• 戴太多“帽子”不好看
• method 的数量没有减少。




       需要一点新思路!
python-state
@stateful                 class Signin(State):
class Player(object):        @behavior
  class                      def move(self,
  NeedSignin(State):      dst): ...
     default = True          @behavior
     @behavior               def atk(self,
     def signin(self,     other): ...
  usr, pwd):                 @behavior
           ...               def …
           switch(self,
  Player.Signin)
python-state
@stateful                 class Signin(State):
class Player(object):        @behavior
  class                      def move(self,
  NeedSignin(State):      dst): ...
     default = True       @behavior
     @behavior               def atk(self,
                          other): ...
     def signin(self,
  usr, pwd):                 @behavior
           ...               def …
           switch(self,
  Player.Signin)
python-state
@stateful                 class Signin(State):
class Player(object):         @behavior
  class                       def move(self,
  NeedSignin(State):      dst): ...
     default = True           @behavior
     @behavior                def atk(self, x):
     def signin(self,     ...
  usr, pwd):                  @behavior
           ...                def …
           switch(self,
  Player.Signin)
python-state
@stateful                 class Signin(State):
class Player(object):        @behavior
  class                      def move(self,
  NeedSignin(State):      dst): ...
     default = True          @behavior
     @behavior               def atk(self,
     def signin(self,     other): ...
  usr, pwd):                 @behavior
           ...               def …
           switch(self,
  Player.Signin)
python-state
@stateful                 class Signin(State):
class Player(object):        @behavior
  class                      def move(self,
  NeedSignin(State):      dst): ...
     default = True          @behavior
     @behavior               def atk(self,
     def signin(self,     other): ...
  usr, pwd):                 @behavior
           ...               def …
           switch(self,
  Player.Signin)
适用场景
• 根据状态授权特定的 RPC API 访问权限
 – 例如未登陆不能调用攻击
• 编写网络协议、文本的 parser
• FSM-based Game AI ?
 – No ! 没有比协程更适合做这件事的机制了。
小结一下……
• 跟 decorator 一样去掉了 if 语句
 – 但是摘掉了许多帽子
 – 而且真正地没有写 if 语句噢!
小结一下……
• 跟 decorator 一样去掉了 if 语句
 – 但是摘掉了许多帽子
 – 而且真正地没有写 if 语句噢!


• 把很多 method 分到多个 State 类中
 – 重用
 – 划分功能
更大的好处是——
• 更容易修正错误……
 – 因为出错信息是 AttributeError !
更容易修正错误……
• 因为出错信息是 AttributeError !




           http://www.slideshare.net/wilhelmshen/py-art
           2010-5-30 shanghai
更容易修正错误……
• 因为出错信息是 AttributeError !
好,继续!

什么引起状态的切换(属性变化)?
有事情发生!

怎么知道有事情发生?
上网、读报、看电视、听收音机……




      大海捞针
好莱坞原则

Don’t call me, I’ll call you.
一个简单的状态切换场景
建个模吧!
建个模吧!
class Lamp(object):
  is_on = False
class
  Swith(object):
  def turn(self):
     ...
建个模吧!
class Lamp(object):     class Line(object):
  is_on = False           ...
class Swith(object):    line = Line()
  def turn(self):       lamp = Lamp(line)
                        swith = Swith(line)
 self.line.lamp.is_on   line.connect(lamp,
 = True                   swith)
                        swith.turn()
                        assert lamp.is_on
好像感觉哪里不对……
• 现实世界中需要真实的 Line ,编程中也
  是吗?
• 如果一个 Switch 对应着很多 Lamp ?
• 循环引用?

   隐形的 Line ?可扩展的 Line ?
python-message
class Switch(object):
  Turn =
  'state.examples.Switch.Trun'
  def turn(self):
     message.pub(Switch.Turn, self)
python-message
@stateful                     class Lamp(object):
class Lamp(object):             def bind(self, s):
  class Off(State):                  self._switch = s
       default = True
       @behavior                message.sub(Switch.Turn,
       def _on_turn(self, s):   self.on_turn)
                                def on_turn(self, s):
              switch(self,
  Lamp.On)                           self._on_turn(s)
  class On(State):
       @behavior
       def _on_turn(self, s):
              switch(self,
  Lamp.Off)
python-message
s = Switch()   <__main__.Lamp object at
l = Lamp()       0x7f6b4dd2f590> begin Off state.
l.bind(s)
s.turn()       <__main__.Lamp object at
                 0x7f6b4dd2f590> end Off state.
s.turn()
               <__main__.Lamp object at
                 0x7f6b4dd2f590> begin On state.

               <__main__.Lamp object at
                 0x7f6b4dd2f590> end On state.
               <__main__.Lamp object at
                 0x7f6b4dd2f590> begin Off state.
解耦
应用场景
• 任务
  – 获得道具时……
  – 怪物死亡时……
• 世界状态
  – 玩家(好友)上下线……
• 网络编程
  – 数据可读……
• ……
更多功能
取消与中止
import message                import message
def hello(name):              def hello(name):
  print 'hello, %s.'%name       print 'hello %s' % name
  message.unsub('greet',        ctx = message.Context()
  hello)                        ctx.discontinued = True
message.sub('greet', hello)     return ctx
message.pub('greet', 'lai')   def hi(name):
message.pub('greet', 'u         print 'u cann't c me.'
  cann't c me.')             message.sub('greet', hello)
                              message.sub('greet', hi)
                              message.pub('greet', 'lai')
进阶
• 改变调用次序
 – 在调用 sub 的时候加上 front = True
 – sub('greet', hello, front = True)
• 订阅过去的消息
 – declare/retract
 – declare(topic, *a, **kw) 用来向“公告栏”发布一
   个消息
 – 把“公告栏”的消息撤消用 retract(topic) 函数
 – get_declarations()/has_declaration(topic)
退化——观察者模式
from message import observable
def greet(people):
        print 'hello, %s.'%people.name
@observable
class Foo(object):
        def __init__(self, name):
                 self.name = name
                 self.sub('greet', greet)
foo = Foo('lai')
foo.pub('greet', foo)
现在
 玩家有了状态
也能知晓世事变幻

那玩家们如何交互?
网络通信


          需要有个 rpc
基于 google protobuf 实现一套就不错
如果有 greenlet 实现同步编程就更好了
abu.rpc
class EchoService(echo.EchoService):
    @abu.rpc.ret
    def Echo(self, controller, request):
        resp = echo.Packet(text = request.text)
        return resp

service = EchoService()
handler = abu.rpc.Handler(abu.rpc.Transport, service)
server = gevent.server.StreamServer(('', 10086), handler)
app = abu.rpc.Application(server)
print 'serving...'
app.run()
abu.rpc
conn =
  gevent.socket.create_connection(('127.0.0.1',
  10086))
channel =
  abu.rpc.Channel(abu.rpc.Transport(conn))
server =
  abu.rpc.Proxy(echo.EchoService_Stub(channel))

req = echo.Packet(text = 'hello'*30)
resp = server.Echo(req)
assert resp.text == req.text
放心,不是 abu.rpc 教程!

 讲 abu.rpc 在真实应用场景中遇
     到的问题及解决方法。
这世界太复杂了……
抽象传输层
@message.observable
class Transport(object):
    TRANSPORT_DATA =
  'abu.rpc.transport.TRANSPORT_DATA‘
 def _recv_func(self):
        while True:
            self.buff =
  self._ll_transport.recv(4096)
            if not self.buff:
                break
            self.pub(self.TRANSPORT_DATA)
很多的传输层
class TgwServerMixin(object):
    def recv(self):
        data = Transport.recv(self)
        if self._handshaked:
            return data
        return self._do_handshake(data)
    def _do_handshake(self, data):
        …

class TgwClientMixin(object): …
很多协议,随意组合。
class TgwServerTransport(TgwServerMixin,
  Transport):
    …
class TgwClientTransport(TgwClientMixin,
  Transport):
    …

class SecTgwServerTransport(SecServerMixin,
  TgwServerTransport):
    …
class SecTgwClientTransport(SecClientMixin,
  TgwClientTransport):
    …
Mixin 威武!

 socketserver.ForkingMixIn
socketserver.ThreadingMixIn
好,大概就是这些了……

         state
  publish-subscribe
       observer
         mixin
使用这些组件……
• http://pypi.python.org/pypi/message
• http://pypi.python.org/pypi/state
• http://pypi.python.org/pypi/abu.rpc
够了吗?
为何不改变语法?
object Earth(Object):
  state default Day(State):
     behavior tick(self):
         if not Sun.visible:
             switch(self, self.Night)
  state Night(State):
     behavior tick(self):
         if Sun.visible:
             switch(self, self.Day)
如果你愿意……

明年我来讲这个。
谢谢大家!

http://laiyonghao.com

More Related Content

What's hot (18)

PDF
OpenEJB - 另一個選擇
Justin Lin
 
PDF
Jscex:案例、经验、阻碍、展望
jeffz
 
PDF
Jscex:案例、阻碍、体会、展望
jeffz
 
PDF
Node way
Ethan Zhang
 
PPTX
180518 ntut js and node
Peter Yi
 
PPT
iPhone,ios,Object-C基础入门
Lucien Li
 
PPT
ios分享
Lucien Li
 
PPTX
C++11综述/新特性描述/Overview of C++11 New Features
Peien Luo
 
PPTX
jQuery源码学习
fangdeng
 
PDF
Ooredis
iammutex
 
PDF
Advanced heap exploitaion
Angel Boy
 
PDF
Node.js开发体验
QLeelulu
 
PDF
用Cython封装c++代码为python模块的一点经验
Leo Zhou
 
PDF
Python learn guide
robin yang
 
PPT
Python 入门
kuco945
 
PPT
JAVA内存泄漏及诊断
ivannotes
 
PDF
Java Thread
艾鍗科技
 
PDF
炎炎夏日學 Android 課程 - Part1: Kotlin 語法介紹
Johnny Sung
 
OpenEJB - 另一個選擇
Justin Lin
 
Jscex:案例、经验、阻碍、展望
jeffz
 
Jscex:案例、阻碍、体会、展望
jeffz
 
Node way
Ethan Zhang
 
180518 ntut js and node
Peter Yi
 
iPhone,ios,Object-C基础入门
Lucien Li
 
ios分享
Lucien Li
 
C++11综述/新特性描述/Overview of C++11 New Features
Peien Luo
 
jQuery源码学习
fangdeng
 
Ooredis
iammutex
 
Advanced heap exploitaion
Angel Boy
 
Node.js开发体验
QLeelulu
 
用Cython封装c++代码为python模块的一点经验
Leo Zhou
 
Python learn guide
robin yang
 
Python 入门
kuco945
 
JAVA内存泄漏及诊断
ivannotes
 
Java Thread
艾鍗科技
 
炎炎夏日學 Android 課程 - Part1: Kotlin 語法介紹
Johnny Sung
 

Similar to 页游开发中的 Python 组件与模式 (20)

KEY
Scala
popeast
 
PDF
Programming python - part 1
Che-Cheng Hsu
 
PPTX
Python入門:5大概念初心者必備 2021/11/18
Derek Lee
 
PDF
lambda/closure – JavaScript、Python、Scala 到 Java SE 7
Justin Lin
 
PDF
《Python 3.5 技術手冊》第六章草稿
Justin Lin
 
PDF
functional-scala
wang hongjiang
 
PPTX
Ecma script edition5-小试
lydiafly
 
PDF
getPDF.aspx
byron zhao
 
PDF
getPDF.aspx
byron zhao
 
PPTX
Javascript share
Xu Mac
 
PDF
Java SE 8 的 Lambda 連鎖效應 - 語法、風格與程式庫
Justin Lin
 
PPTX
Android resource-management
Lucas Xu
 
PPT
Java Script 引擎技术
bigqiang zou
 
PPTX
02.python基础
modou li
 
PPT
基于XMPP的Gtalk机器人
roamin9 Zhou
 
PPTX
CKAN : 資料開放平台技術介紹 (CAKN : Technical Introduction to Open Data Portal)
Jian-Kai Wang
 
PPT
Sun java
softwaredesigner
 
PDF
Learning python in the motion picture industry by will zhou
Will Zhou
 
PPT
JavaScript 脚本控件(二)
RANK LIU
 
PDF
看似比較簡單的推坑教學 C語言從崩潰到崩潰Ex(二)
永立 連
 
Scala
popeast
 
Programming python - part 1
Che-Cheng Hsu
 
Python入門:5大概念初心者必備 2021/11/18
Derek Lee
 
lambda/closure – JavaScript、Python、Scala 到 Java SE 7
Justin Lin
 
《Python 3.5 技術手冊》第六章草稿
Justin Lin
 
functional-scala
wang hongjiang
 
Ecma script edition5-小试
lydiafly
 
getPDF.aspx
byron zhao
 
getPDF.aspx
byron zhao
 
Javascript share
Xu Mac
 
Java SE 8 的 Lambda 連鎖效應 - 語法、風格與程式庫
Justin Lin
 
Android resource-management
Lucas Xu
 
Java Script 引擎技术
bigqiang zou
 
02.python基础
modou li
 
基于XMPP的Gtalk机器人
roamin9 Zhou
 
CKAN : 資料開放平台技術介紹 (CAKN : Technical Introduction to Open Data Portal)
Jian-Kai Wang
 
Learning python in the motion picture industry by will zhou
Will Zhou
 
JavaScript 脚本控件(二)
RANK LIU
 
看似比較簡單的推坑教學 C語言從崩潰到崩潰Ex(二)
永立 連
 
Ad

More from 勇浩 赖 (20)

PPT
一种多屏时代的通用 web 应用架构
勇浩 赖
 
PPT
Tp web
勇浩 赖
 
PPT
2012,我的技术之选
勇浩 赖
 
PDF
Scala
勇浩 赖
 
PPT
珠三角技术沙龙广州场
勇浩 赖
 
PPT
为什么 rust-lang 吸引我?
勇浩 赖
 
PDF
Behavior+tree+ai lite
勇浩 赖
 
PPTX
敏捷网游架构与性能的新玩法
勇浩 赖
 
PPT
先用再学 - 借助 Xna 快速开发游戏原型
勇浩 赖
 
PDF
关于Bitworld的一些话题222
勇浩 赖
 
PPT
Stekin
勇浩 赖
 
PDF
03 -黄朝兴--腾讯游戏
勇浩 赖
 
PPT
abu.rpc intro
勇浩 赖
 
PPTX
06 -甄焱琨--知识转化为资源
勇浩 赖
 
PPT
07 -林伟铃--成长中的36氪
勇浩 赖
 
PDF
01 -阿朱--简单事情夯实做
勇浩 赖
 
PDF
Python 温故
勇浩 赖
 
PPT
如何做好沙龙演讲
勇浩 赖
 
PPT
虚拟世界是怎么炼成的(图片版)
勇浩 赖
 
PPT
Techparty story
勇浩 赖
 
一种多屏时代的通用 web 应用架构
勇浩 赖
 
Tp web
勇浩 赖
 
2012,我的技术之选
勇浩 赖
 
Scala
勇浩 赖
 
珠三角技术沙龙广州场
勇浩 赖
 
为什么 rust-lang 吸引我?
勇浩 赖
 
Behavior+tree+ai lite
勇浩 赖
 
敏捷网游架构与性能的新玩法
勇浩 赖
 
先用再学 - 借助 Xna 快速开发游戏原型
勇浩 赖
 
关于Bitworld的一些话题222
勇浩 赖
 
Stekin
勇浩 赖
 
03 -黄朝兴--腾讯游戏
勇浩 赖
 
abu.rpc intro
勇浩 赖
 
06 -甄焱琨--知识转化为资源
勇浩 赖
 
07 -林伟铃--成长中的36氪
勇浩 赖
 
01 -阿朱--简单事情夯实做
勇浩 赖
 
Python 温故
勇浩 赖
 
如何做好沙龙演讲
勇浩 赖
 
虚拟世界是怎么炼成的(图片版)
勇浩 赖
 
Techparty story
勇浩 赖
 
Ad

页游开发中的 Python 组件与模式