经过一番尝试后,我发现这还是有难度的,由于我个人没游戏开发经验,网络编程也刚入门,但是还是可以做下去的。下面是这两周来的开发经验总结。
开发资料:
相关资料挺难找,刚开始没头绪,只有一边写一边找了。暂时找到一篇有参考价值的:http://blog.csdn.net/realman1981/archive/2006/07/18/934011.aspx
开发环境:
开发语言和工具:Python+PyQt+Eric
管理工具:Google Code + SVN
既然是练习Python,还要编写网络和界面程序,当然选择之前熟悉的Eric作为开发调试工具。这次还在Google Code注册了个项目使用SVN来管理进度,项目地址:http://code.google.com/p/python-poker/
开发概要:
介绍:
Python语言开发的网络扑克游戏
功能目标:
*支持客户端和服务端的多人游戏
*支持机器人(Bots)
*支持定义游戏规则,包含子游戏
*支持图形用户界面(计划PyQt)
开发进度:
开发近两周,版本到v0.2(r20),实现基本游戏框架,实现网络通信(待改进),实现简单命令行界面(仅可调试信息),实现一个简单游戏(跟花)的逻辑和AI(待改进),进入图形界面开发。
由于定位为敏捷开发,文档后行。文档方面只有游戏框架UML类图和简要说明,代码注释比较丰富,希望有兴趣的朋友能提出宝贵建议。
本文网址:http://vvonderblog.appspot.com/2010/07/30/python-poker-game-1.html
]]>最终效果图:
所使用开发环境:
开发步骤:
步骤一至四主要为eric的操作,我只贴图,详细可参考之前文章提供的参考资料
一.使用eric新建PyQt4工程gtranslate
二.工程中添加窗体,调用QT Designer设计主界面,保存为main.ui
三.编译窗体文件main.ui为Python代码Ui_main.py
四.工程中根据窗体文件生成代码main.py,代码将根据以上生成的Ui类派生,选择需要的信号槽
五.完善main.py,编写核心代码
主要原理:
参考代码:
# -*- coding: utf-8 -*-
"""
Module implementing Dialog.
"""
import urllib
import urllib2
import sys
import json
from PyQt4 import QtGui, QtCore
from PyQt4.QtGui import QDialog
from PyQt4.QtCore import pyqtSignature, SIGNAL, QThread
from Ui_main import Ui_Dialog
class Dialog(QDialog, Ui_Dialog):
"""
Main window
"""
def __init__(self, parent = None):
"""
Constructor
"""
QDialog.__init__(self, parent)
self.setupUi(self)
lang=sorted(GTranslate.LANG.keys())
self.cbOrigin.addItems(lang)
self.cbOrigin.setCurrentIndex(lang.index('ENGLISH'))
self.cbTarget.addItems(lang)
self.cbTarget.setCurrentIndex(lang.index('CHINESE'))
@pyqtSignature("")
def on_btnTranslate_clicked(self):
"""
Submit to google translate
"""
text=self.tOrigin.toPlainText()
text=unicode(text).encode('utf-8')
key=str(self.cbOrigin.currentText())
langOrigin=GTranslate.LANG[key]
key=str(self.cbTarget.currentText())
langTarget=GTranslate.LANG[key]
self.gt=GTranslate(langOrigin, langTarget, text)
self.connect(self.gt, SIGNAL("finished()"), self.showResult)
self.gt.start()
self.updateUi(False)
@pyqtSignature("")
def on_btnReset_clicked(self):
"""
Reset the UI
"""
self.gt.terminate()
self.updateUi(True)
def showResult(self):
result=self.gt.result
if(result):
self.tTarget.setText(result)
self.updateUi(True)
def updateUi(self, enable):
self.btnTranslate.setEnabled(enable)
self.btnReset.setEnabled(not enable)
class GTranslate(QThread):
def __init__(self, langOrigin='en', langTarget='zh', text=None, parent=None):
QThread.__init__(self, parent)
self.text=text
self.langOrigin=langOrigin
self.langTarget=langTarget
self.result=None
def translate(self):
query = (GTranslate.URL % (urllib.quote(self.text), self.langOrigin, self.langTarget))
req = urllib2.Request(query)
# req.add_header("Referer", "http://www.my-ajax-site.com")
try:
r = urllib2.urlopen(req)
data = r.read()
except:
self.result='Network Connect Error!'
return
obj = json.loads(data)
if obj['responseStatus'] != 200L:
self.result="Error: %s" % obj['responseDetails']
else:
self.result=obj['responseData']['translatedText']
def run(self):
self.translate()
URL = "http://ajax.googleapis.com/ajax/services/language/translate?v=1.0&q=%s&langpair=%s%%7C%s"
LANG={
'AFRIKAANS' : 'af',
'ALBANIAN' : 'sq',
...
'UNKNOWN' : ''
}
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
main = Dialog()
main.show()
sys.exit(app.exec_())
六.测试、打包和发布
这里使用py2exe打包,以便发布在没有安装Python和PyQt的Windows环境下。打包脚本setup.py如下:
#!/usr/bin/env python
#coding=utf-8
from distutils.core import setup
import py2exe
setup(
data_files=[
#vc9 runtime
'msvcr90.dll',
'msvcp90.dll',
'Microsoft.VC90.CRT.manifest',
],
windows=['main.py'],
options={
"py2exe": {
'includes': ['sip'],
"compressed": True,
# 'bundle_files': 2,
}
}
)
注意最好连VS2008相关的库文件一起打包(Python2.6需要msvcr90.dll,PyQt4需要msvcp90.dll),我已将相关的文件放到源码目录,见打包脚本。
工程文件可到我的网盘下载:
本文网址:http://vvonderblog.appspot.com/2009/12/23/pyqt-google-translate-client.html
]]>开始学习了。现在正在研究的主要参考书为《Prentice.Hall.Rapid.GUI.Programming.with.Python.and.Qt》,E文的讲得相当详细,后面有点难度,PDF版和配套源码可以到我的网盘下载。
另外有几篇网上的中文教程推荐:
http://hi.baidu.com/runningon/blog/item/115662279ff36a06918f9d0b.html --eric4结合PyQt教程
http://www.cnitblog.com/addone/archive/2006/04/01/8469.aspx --eric4结合PyQt教程,另一篇
http://code.google.com/p/pyqt-doc-cn/ --PyQt简介教程
http://www.czug.org/python/pyqt4/ --某PyQt教程的翻译
http://www.blogjava.net/glorywine/category/32060.html --一系列PyQt教程
以上教程我已打包整理到网盘。
本文网址:http://vvonderblog.appspot.com/2009/12/22/learning-pyqt-about-resources.html
]]>原理是访客访问/checkimg/获得生成的图形验证码,同时服务器使用session保存验证码值,并在处理提交评论表单时检查。
先测试一下效果,代码以后再整理。
部分代码如下:
safecode.py,gmemsess.py,pngcanvas.py放到app目录
blog.py添加CheckImg类,并在主函数添加路径映射,用于生成验证码图片:
('/checkimg/', CheckImg),from app.safecode import Image
from app.gmemsess import Session
class CheckImg(BaseRequestHandler):
def get(self):
img = Image()
imgdata = img.create()
sess=Session(self,timeout=180)
if not sess.is_new():
sess.invalidate()
sess=Session(self,timeout=180)
sess['code']=img.text
sess.save()
self.response.headers['Content-Type'] = "image/png"
self.response.out.write(imgdata)
Post_comment主要修改如下,验证输入的验证码和session中的是否一致:
sess=Session(self,timeout=180)
if not self.is_login:
if not (self.request.cookies.get('comment_user', '')):
try:
logging.info(checkret)
logging.info(sess['code'])
if sess.is_new() or (int(checkret) != sess['code']):
sess.invalidate()
if useajax:
self.write(simplejson.dumps((False,-102,('Your check code is invalid .'))))
else:
self.error(-102,('Your check code is invalid .'))
return
except:
sess.invalidate()
if useajax:
self.write(simplejson.dumps((False,-102,('Your check code is invalid .'))))
else:
self.error(-102,('Your check code is invalid .'))
return
sess.invalidate()
为了使验证码显示(默认首次访问检查验证码),可以点击这里清除cookie。
本文网址:http://vvonderblog.appspot.com/2009/11/25/add-micolog-image-checkcode.html
]]>其主页:http://webpy.org/,用的人挺多,文档很丰富。
另外最近在免费的神龙主机上弄了个空间来搞了个web.py的简单应用:一个留言版程序guestbook,来演示一下web.py的简洁和强大。
源码如下,演示了web.py的路径映射、数据库访问、模板等功能。
业务逻辑模块view.py:
#!/usr/local/python2/bin/python
#coding:utf-8
import os, sys
#导入webpy包的路径(上上层目录,根据需要调整)
sys.path.append(os.path.abspath('../../'))
#避免URL重定向时出现脚本名
os.environ['REAL_SCRIPT_NAME'] = ""
import web
#URL映射
urls = (
'/clear/?','clear', #清空数据库
'/guestbook/?','guestbook', #留言本
'/.*', 'index', #首页
)
app = web.application(urls, globals())
#模板放到当前路径templates目录
render = web.template.render('templates/')
#连接sqlite数据库,当前目录的guestbook.db
db = web.database(dbn='sqlite', db='guestbook.db')
class clear:
def GET(self):
#db.delete('comment')
db.query('delete from comment')
web.seeother('/guestbook')
class guestbook:
def GET(self):
comments=db.select('comment')
return render.guestbook(comments)
def POST(self):
i=web.input()
if i.author and i.content:
db.insert('comment', author=i.author, content=i.content)
web.seeother('/guestbook')
class index:
def GET(self):
web.seeother('/guestbook')
#fcgi运行时必需,需要flup服务器,本地运行不需要
web.wsgi.runwsgi = lambda func, addr=None: web.wsgi.runfcgi(func, addr)
if __name__ == "__main__":
app.run()
模板文件guestbook.html(放到当前路径的templates目录):
$def with (comments)
<html>
<body>
<form method="post" action="/guestbook">
<p><input type="text" name="author" />author<br />
<input type="text" name="content" />content<br />
<input type="submit" value="Add" /></p>
</form>
<p>Comments:</p>
<ul>
$for comment in comments:
<li>$comment.author: $comment.content</li>
</ul>
</body>
</html>
数据库生成脚本initDB.py(执行生成guestbook.db):
#!/usr/local/python2/bin/python
#coding:utf-8
#import sqlite3
from pysqlite2 import dbapi2 as sqlite3 #神龙主机的sqlite3库
def initDB(con):
cur = con.cursor()
cur.execute("""
create table comment(
author varchar(20),
content varchar(1000)
)""")
con.commit()
if __name__ == '__main__':
initDB(sqlite3.connect("guestbook.db"))
将这些文件上传到神龙主机,当然先要在主机上部署好web.py框架(即上传web文件夹到某目录),并设置好URL重写脚本.htaccess即可访问了,我是放在根目录的webpy目录里。
.htaccess脚本:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ webpy/view.py/$1 [QSA,L]
DirectoryIndex webpy/view.py
演示地址:http://vv0nder.freebsdhost.org/
本文网址:http://vvonderblog.appspot.com/2009/11/10/python-web-framework-webpy.html
]]>中文文档可参考网友的翻译:
译者的那个页面好像就是用Bottle框架的。
另外推荐篇Python Web开发的好文章,进一步理解Python Web框架:网站开发深入浅出Python篇
本文网址:http://vvonderblog.appspot.com/2009/11/10/python-web-framework-bottle.html
]]>首先推荐个很好的Linux学习站点:
鸟哥的Linux私房菜:
主要介绍Linux系统管理方面的知识,很有技术含量,学完几乎成为Linux高手了。
这里还有简体离线版打包下载。
下面介绍几个常去的Linux学习社区:
本文网址:http://vvonderblog.appspot.com/2009/11/1/linux-learning-website.html
]]>现在我博客用的简单脚本(来自互联网,有修改):
<script language="javascript">
<!--
function showPageLink(sUrl,iPage,iCount){
var i;
i=Math.max(1,iPage-1);
if(iPage==1){
document.write("<span style='color:#7D7D7D'>首页</span> ");
document.write("<span style='color:#7D7D7D'>上一页</span> ");
}
else{
document.write("<a href=\"" + sUrl + "1\" title='第 1 页'>首页</a> ");
document.write("<a href=\"" + sUrl + i + "\" title='上一页(第 " + i + " 页)'>上一页</a> ");
}
if(iPage>6) document.write("<span>...</span> ");
for(i=Math.max(1,iPage-5);i<iPage;i++){
document.write("<a href=\""+sUrl + i + "\" title='第 " + i + " 页'><b>" + i + "</b></a> ");
}
document.write("<font color='red'><b>" + iPage + "</b></font> ");
for(i=iPage+1;i<=Math.min(iCount,iPage+5);i++){
document.write("<a href=\""+sUrl + i + "\" title='第 " + i + " 页'><b>" + i + "</b></a> ");
}
i=Math.min(iCount,iPage+1);
if(iCount>iPage+5) document.write("<span>...</span> ");
if(iPage==iCount){
document.write("<span style='color:#7D7D7D'>下一页</span> ");
document.write("<span style='color:#7D7D7D'>尾页</span> ");
}
else{
document.write("<a href=\"" + sUrl + i + "\" title='下一页(第 " + i + " 页)'>下一页</a> ");
document.write("<a href=\"" + sUrl + iCount + "\" title='最后一页(第 " + iCount + " 页)'>尾页</a> ");
}
}
showPageLink("/page/",{{pageindex}},{{pagecount}});//记得按需要修改
//-->
</script>
使用方法:showPageLink("url格式",当前页码,总页码)
基于jQuery的插件:
本文网址:http://vvonderblog.appspot.com/2009/10/23/simple-javascript-page-navigation.html
]]>先研究一下SimpleHTTPServer模块,这个确实够简单:
不用代码的:
终端直接运行命令:python -m SimpleHTTPServer [端口]
两行代码的,保存为Python脚本执行:
import SimpleHTTPServer
SimpleHTTPServer.test()
默认端口为8000,直接访问http://localhost:8000即可,根路径是运行命令或脚本的文件夹。
这个东西有个实用的功能是拿来共享文件
。
以后再来点复杂的...
本文网址:http://vvonderblog.appspot.com/2009/10/22/python-simple-web-server.html
]]>项目地址:http://code.google.com/p/zeroclipboard/
演示地址:http://bowser.macminicolo.net/~jhuckaby/zeroclipboard/
使用简介:
可参考开源的 JavaScript 复制库类 Zero Clipboard
本人在使用过程中发现它的示例在本地无法使用,而在服务器环境下没问题。有Python而一时没法架设服务器的朋友可以这样测试:
这也是快速利用Python架设Http测试服务器的方法。
已经弄到高亮代码页面,欢迎测试。
成功调用的代码(我把它放在Body标签里的最下面成功,要用到jQuery):
<script type="text/javascript" src="/static/ZeroClipboard/ZeroClipboard.js"></script>
<script type="text/javascript">
ZeroClipboard.setMoviePath( '/static/ZeroClipboard/ZeroClipboard.swf' );
function clipInit() {
var clip = new ZeroClipboard.Client();
clip.setHandCursor(true);
clip.addEventListener('mouseOver', function(client){
clip.setText(document.getElementById('code').value);
});
clip.addEventListener('complete', function(client,text){
alert("成功复制代码到剪贴板!");
});
clip.glue('copybtn');
}
//jQuery onLoad
$(document).ready(function() {
clipInit();
});
</script>
其中高亮部分依次是ZeroClipboard脚本地址、ZeroClipboard影片地址、待复制的文本框ID、复制控件ID(被ZeroClipboard覆盖),注意需要Flash支持。
为了兼容ie,使用了jQuery加载初始化代码,如果不想使用jQuery,需要在body标签属性里加入onload='clipInit'。
本文网址:http://vvonderblog.appspot.com/2009/10/21/a-copy-to-clipboard-script.html
]]>