python游戏编程——跟13岁儿童学编程
python爬虫基本告一段落,琢磨搞点其他的,正好在网上看到一个帖子,一个外国13岁小朋友用python写的下棋程序,内容详细,也有意思,拿来练手。
13岁啊。。 我这年纪还在敲 dir啥的吧
想到原先玩跑跑卡丁车时看到欧酷有个4岁熊孩子玩的完美漂移录像,深受打击,从此退出车坛。。。
废话不多说,记录一下这几天的游戏编程折腾史
原帖: http://blog.jobbole.com/80379/ 《13岁Python开发者写给青少年的Python入门教程》
游戏规则:6*6的方格棋盘,两个人轮流点击棋盘画横线或竖线,谁成功围成一个格子,这个格子算作此人的积分。
游戏架构:客户端和服务端。
先来看下游戏准备工作,需要用到pygame这个python包。
下载小朋友准备的Resource文件,游戏用到的图片、声音啥的。
一下为BoxGame(客户端)和Server代码,已添加注释。
boxes.py
1 import pygame
2 import math
3 from PodSixNet.Connection import ConnectionListener,connection
4 from time import sleep
5
6 # 客户端游戏类
7 class BoxesGame(ConnectionListener):
8 def initSound(self):
9 pygame.mixer.music.load("music.wav")
10 self.winSound=pygame.mixer.Sound('win.wav')
11 self.loseSound=pygame.mixer.Sound('lose.wav')
12 self.placeSound=pygame.mixer.Sound('place.wav')
13 pygame.mixer.music.play()
14 # 收到来自Server的 action:close指令后调用下面方法
15 def Network_close(self,data):
16 exit()
17 def Network_yourturn(self,data):
18 self.turn=data['torf']
19 def Network_startgame(self,data):
20 self.running=True
21 self.num=data["player"]
22 self.gameid=data["gameid"]
23 def Network_place(self,data):
24 self.placeSound.play()
25 x=data["x"]
26 y=data["y"]
27 hv=data["is_horizontal"]
28 if hv:
29 self.boardh[y][x]=True
30 else:
31 self.boardv[y][x]=True
32 # 设定某个格子为自己的
33 def Network_win(self,data):
34 self.owner[data["x"]][data["y"]]="win"
35 self.boardh[data["y"]][data["x"]]=True
36 self.boardv[data["y"]][data["x"]]=True
37 self.boardh[data["y"]+1][data["x"]]=True
38 self.boardv[data["y"]][data["x"]+1]=True
39 self.winSound.play()
40 self.me+=1
41 def Network_lose(self,data):
42 self.owner[data["x"]][data["y"]]="lose"
43 self.boardh[data["y"]][data["x"]]=True
44 self.boardv[data["y"]][data["x"]]=True
45 self.boardh[data["y"]+1][data["x"]]=True
46 self.boardv[data["y"]][data["x"]+1]=True
47 self.loseSound.play()
48 self.otherplayer+=1
49
50 def __init__(self):
51 self.justplaced=10
52 pygame.init()
53 pygame.font.init()
54 width, height = 389, 489
55 self.me = 0
56 self.otherplayer = 0
57 self.didwin = False
58 self.gameid=None
59 self.num=None
60 self.num=0
61 self.screen = pygame.display.set_mode((width, height))
62 self.owner=[[0 for x in range(6)] for y in range(6)]
63 self.clock = pygame.time.Clock()
64 self.turn = True
65 self.running=False
66 self.boardh = [[False for x in range(6)] for y in range(7)]
67 self.boardv = [[False for x in range(7)] for y in range(6)]
68 print(self.boardh)
69 print(self.boardv)
70 self.initGraphics()
71 self.initSound()
72 self.drawHUD()
73 pygame.display.set_caption("Boxes")
74
75 # address=raw_input("Host:Port(localhost:8080):")
76 # try:
77 # if not address:
78 # host,port="localhost",3721
79 # else:
80 # host,port=address.split(":")
81 # self.Connect((host,port))
82 # except:
83 # print("Error Connecting to Server")
84 # print("Usage: host:port")
85 # print("eg 127.0.0.1;3721")
86 # exit()
87 self.Connect()
88 print("Boxes client started")
89 while not self.running:
90 self.Pump()
91 connection.Pump()
92 self.running=True
93 sleep(0.01)
94 print("not running ,connecting...")
95 if self.num==0:
96 # self.turn=True
97 self.marker=self.greenplayer
98 self.othermarker=self.blueplayer
99 else:
self.turn=False
self.marker=self.blueplayer
self.othermarker=self.greenplayer
def initGraphics(self):
self.normallinev = pygame.image.load("normalline.png")
self.normallineh = pygame.transform.rotate(self.normallinev, -90)
self.bar_donev = pygame.image.load("bar_done.png")
self.bar_doneh = pygame.transform.rotate(self.bar_donev, -90)
self.hoverlinev = pygame.image.load("hoverline.png")
self.hoverlineh = pygame.transform.rotate(self.hoverlinev, -90)
# self.boardh[5][4]=True
# self.boardv[5][5]=True
self.separators = pygame.image.load("separators.png")
self.score_panel = pygame.image.load("score_panel.png")
self.redindicator = pygame.image.load("redindicator.png")
self.greenindicator = pygame.image.load("greenindicator.png")
self.greenplayer = pygame.image.load("greenplayer.png")
self.blueplayer = pygame.image.load("blueplayer.png")
self.winningscreen = pygame.image.load("youwin.png")
self.gameover = pygame.image.load("gameover.png")
def drawBoard(self):
for x in range(6):
for y in range(7):
if not self.boardh[y][x]:
self.screen.blit(self.normallineh, [(x) * 64 + 5, (y) * 64])
else:
self.screen.blit(self.bar_doneh, [(x) * 64 + 5, (y) * 64])
for x in range(7):
for y in range(6):
if not self.boardv[y][x]:
self.screen.blit(self.normallinev, [(x) * 64, (y) * 64 + 5])
else:
self.screen.blit(self.bar_donev, [(x) * 64, (y) * 64 + 5])
def update(self):
# 判断方格是否已经都有归属
if self.me+self.otherplayer==36:
self.didwin=True if self.me>self.otherplayer else False
return 1
self.justplaced-=1
# print('pump connect info')
connection.Pump()
self.Pump()
# print('pump connect info finish')
self.clock.tick(60)
self.screen.fill(0)
self.drawBoard()
self.drawHUD()
self.drawOwnermap()
for event in pygame.event.get():
if event.type == pygame.QUIT:
exit()
mouse = pygame.mouse.get_pos()
xpos = int(math.ceil((mouse[0] - 32) / 64.0))
ypos = int(math.ceil((mouse[1] - 32) / 64.0))
# 判断鼠标位置更接近与那条线
is_horizontal = abs(mouse[1] - ypos * 64) < abs(mouse[0] - xpos * 64)
ypos = ypos - 1 if mouse[1] - ypos * 64 < 0 and not is_horizontal else ypos
xpos = xpos - 1 if mouse[0] - ypos * 64 < 0 and is_horizontal else xpos
board = self.boardh if is_horizontal else self.boardv
isoutofbounds = False
try:
if not board[ypos][xpos]: self.screen.blit(self.hoverlineh if is_horizontal else self.hoverlinev,
[xpos * 64 + 5 if is_horizontal else xpos * 64,
ypos * 64 if is_horizontal else ypos * 64 + 5])
except:
isoutofbounds = True
pass
if not isoutofbounds:
alreadyplaced = board[ypos][xpos]
else:
alreadyplaced = False
# 鼠标点击时,发送place信号给自己划线
if pygame.mouse.get_pressed()[0] and not alreadyplaced and not isoutofbounds and self.turn==True and self.justplaced<=10:
self.justplaced=10
if is_horizontal:
self.boardh[ypos][xpos] = True
self.Send({"action":"place","x":xpos,"y":ypos,"is_horizontal":is_horizontal,"gameid":self.gameid,"num":self.num})
else:
self.boardv[ypos][xpos] = True
self.Send({"action":"place","x":xpos,"y":ypos,"is_horizontal":is_horizontal,"gameid":self.gameid,"num":self.num})
pygame.display.flip()
# 画记分区域
def drawHUD(self):
self.screen.blit(self.score_panel, [0, 389])
myfont = pygame.font.SysFont(None, 32)
label = myfont.render("Your turn", 1, (255, 255, 255))
self.screen.blit(label, (10, 400))
self.screen.blit(self.greenindicator if self.turn else self.redindicator ,(130, 395))
myfont64 = pygame.font.SysFont(None, 64)
myfont20 = pygame.font.SysFont(None, 20)
scoreme = myfont64.render(str(self.me), 1, (255, 255, 255))
scoreother = myfont64.render(str(self.otherplayer), 1, (255, 255, 255))
scoretextme = myfont20.render("You", 1, (255, 255, 255))
scoretextother = myfont20.render("Other Player", 1, (255, 255, 255))
self.screen.blit(scoretextme, (10, 425))
self.screen.blit(scoreme, (10, 435))
self.screen.blit(scoretextother, (280, 425))
self.screen.blit(scoreother, (280, 435))
# 给占领与被占领格子着色
def drawOwnermap(self):
for x in range(6):
for y in range(6):
if self.owner[x][y]!=0:
if self.owner[x][y]=="win":
self.screen.blit(self.marker,(x*64+5,y*64+5))
if self.owner[x][y]=="lose":
self.screen.blit(self.othermarker,(x*64+5,y*64+5))
# 游戏结束后显示gameover或winning的图案
def finished(self):
self.screen.blit(self.gameover if not self.didwin else self.winningscreen,(0,0))
while 1:
for event in pygame.event.get():
if event.type==pygame.QUIT:
exit()
pygame.display.flip()
bg = BoxesGame()
while 1:
if bg.update()==1:
break
bg.finished()
server.py
1 __author__ = 'Administrator'
2 import PodSixNet.Channel
3 import PodSixNet.Server
4 from time import sleep
5
6 # 定义客户端通道,继承PodSixNet.Channel.Channel
7 class ClientChannel(PodSixNet.Channel.Channel):
8 def Network(self,data):
9 print data
10 def Network_place(self,data):
11 hv=data["is_horizontal"]
12 x=data["x"]
13 y=data["y"]
14 # 客户标号
15 num=data["num"]
16 # 本游戏id
17 self.gameid=data["gameid"]
18 self._server.placeLine(hv,x,y,data,self.gameid,num)
19 def Close(self):
20 self._server.close(self.gameid)
21
22 # 定义游戏服务端
23 class BoxesServer (PodSixNet.Server.Server):
24 channelClass = ClientChannel
25 def __init__(self,*args,**kwargs):
26 PodSixNet.Server.Server.__init__(self,*args,**kwargs)
27 self.games=[]
28 self.queue=None
29 self.currentIndex=0
30 def Connected(self,channel,addr):
31 print 'new connection:',channel
32 # 如果队列为空,则新建一局game
33 if self.queue==None:
34 self.currentIndex+=1
35 channel.gameid=self.currentIndex
36 self.queue=Game(channel,self.currentIndex)
37 #如果队列中已有一局game在等待,则将新连进来的channel作为第二名游戏者与等待游戏者配对,加入games[]列表,将queue清空
38 else:
39 channel.gameid=self.currentIndex
40 self.queue.player1=channel
41 self.queue.player0.Send({"action":"startgame","player":0,"gameid":self.queue.gameid})
42 self.queue.player1.Send({"action":"startgame","player":1,"gameid":self.queue.gameid})
43 self.games.append(self.queue)
44 self.queue=None
45 # def placeLine(self,is_h,x,y,data,gameid,num):
46 # if num==self.turn:
47 # self.turn=0 if self.turn else 1
48 # self.player1.Send({"action":"yourturn","torf":True if self.turn==1 else False})
49 # self.player0.Send({"action":"yourturn","torf":True if self.turn==0 else False})
50 # if is_h:
51 # self.boardh[y][x]=True
52 # else:
53 # self.boardv[y][x]=True
54 # self.player0.Send(data)
55 # self.player1.Send(data)
56
57 #通知GameServer哪句游戏要划线,调用游戏placeLine
58 def placeLine(self,is_h,x,y,data,gameid,num):
59 game=[a for a in self.games if gameid==a.gameid]
60 if len(game)==1:
61 game[0].placeLine(is_h,x,y,data,num)
62 # 关闭某局game
63 def close(self,gameid):
64 try:
65 game=[a for a in self.games if a.gameid==gameid][0]
66 game.player0.Send({"action":"close"})
67 game.player1.Send({"action":"close"})
68 except:
69 pass
70 # 判断方格归属
71 def tick(self):
72 index=0
73 # 状态未改变 code 3
74 change=3
75 # 扫描每局游戏
76 for game in self.games:
77 change=3
78 # 扫描2次,因为存在放置一个线条完成两个方格占领的情况
79 for time in range(2):
80 for y in range(6):
81 for x in range(6):
82 # 判断是否是新围成的方格
83 if game.boardh[y][x] and game.boardv[y][x] and game.boardh[y+1][x] and game.boardv[y][x+1] and not game.owner[x][y]:
84 # 是否为己方围成的,围成的一方可以继续走一步
85 # 此处self.games[index]能否替换为game?
86 if self.games[index].turn==0:
87 self.games[index].owner[x][y]=2
88 game.player1.Send({"action":"win","x":x,"y":y})
89 game.player0.Send({"action":"lose","x":x,"y":y})
90 change=1
91 print("player1 win 1 grid")
92 else:
93 self.games[index].owner[x][y]=1
94 game.player0.Send({"action":"win","x":x,"y":y})
95 game.player1.Send({"action":"lose","x":x,"y":y})
96 change=0
97 print("player0 win 1 grid")
98 # 如果状态改变了(即有一方完成了方格占领)则下一步仍由该方走棋;否则正常交替走棋
99 self.games[index].turn=change if change!=3 else self.games[index].turn
game.player1.Send({"action":"yourturn","torf":True if self.games[index].turn==1 else False})
game.player0.Send({"action":"yourturn","torf":True if self.games[index].turn==0 else False})
index+=1
self.Pump()
# 单纯一局游戏的控制类
class Game:
def __init__(self,player0,currentIndex):
self.turn=0
self.owner=[[False for x in range(6)] for y in range(6)]
self.boardh=[[False for x in range(6)] for y in range(7)]
self.boardv=[[False for x in range(7)] for y in range(6)]
self.player0=player0
self.player1=None
self.gameid=currentIndex
# while not self.running:
# self.Pump()
# connection.Pump()
# sleep(0.01)
# if self.num==0:
# self.turn=True
# self.marker=self.greenplayer
# self.othermarker=self.blueplayer
# else:
# self.turn=False
# self.marker=self.blueplayer
# self.othermarker=self.greenplayer
# 划线
def placeLine(self,is_h,x,y,data,num):
if num==self.turn:
self.turn=0 if self.turn else 1
self.player1.Send({"action":"yourturn","torf":True if self.turn==1 else False})
self.player0.Send({"action":"yourturn","torf":True if self.turn==0 else False})
if is_h:
self.boardh[y][x]=True
else:
self.boardv[y][x]=True
self.player0.Send(data)
self.player1.Send(data)
# def Network_palce(self,data):
# x=data["x"]
# y=data["y"]
# hv=data["is_horizontal"]
# if hv:
# self.boardh[y][x]=True
# else:
# self.boardv[y][x]=True
print "Staring server on localhost"
address=raw_input("Host:Port(localhost:8080):")
if not address:
host,port="localhost",31425
print("default host and port")
print(host,":",port)
else:
host,port=address.split(":")
print(host,":",port)
boxesServer=BoxesServer( localaddr=("127.0.0.1", 31425))
# boxesServer=BoxesServer()
while True:
boxesServer.Pump()
boxesServer.tick()
sleep(0.01) 就是这样,休息,休息一下。
python游戏编程——跟13岁儿童学编程的更多相关文章
- Python实用笔记 (13)函数式编程——返回函数
函数作为返回值 我们来实现一个可变参数的求和.通常情况下,求和的函数是这样定义的: def calc_sum(*args): ax = 0 for n in args: ax = ax + n ret ...
- 分享《Python 游戏编程快速上手(第3版)》高清中文版PDF+高清英文版PDF+源代码
通过编写一个个小巧.有趣的游戏来学习Python,通过实例来解释编程的原理的方式.14个游戏程序和示例,介绍了Python基础知识.数据类型.函数.流程控制.程序调试.流程图设计.字符串操作.列表和字 ...
- Python游戏编程入门 中文pdf扫描版|网盘下载内附地址提取码|
Python是一种解释型.面向对象.动态数据类型的程序设计语言,在游戏开发领域,Python也得到越来越广泛的应用,并由此受到重视. 本书教授用Python开发精彩游戏所需的[]为重要的该你那.本书不 ...
- Python游戏编程入门
<Python游戏编程入门>这些文章负责整理在这本书中的知识点.注意事项和课后习题的尝试实现.并且对每一个章节给出的最终实例进行分析和注释. 初识pygame:pie游戏pygame游戏库 ...
- 《Python游戏编程快速上手》——1.3 如何使用本书
本节书摘来自异步社区<Python游戏编程快速上手>一书中的第1章,第1.3节,作者[美] Al Sweigart(斯维加特),李强 译,更多章节内容可以访问云栖社区"异步社区& ...
- 《Python游戏编程快速上手》|百度网盘免费下载|Python基础编程
<Python游戏编程快速上手>|百度网盘免费下载| 提取码:luy6 Python是一种高级程序设计语言,因其简洁.易读及可扩展性日渐成为程序设计领域备受推崇的语言. 本书通过编写一个个 ...
- 【转】以Python为例的Async / Await的编程基础
转, 原文:https://www.cnblogs.com/middleware/p/11996731.html 以Python为例的Async / Await的编程基础 -------------- ...
- Python 第六篇(上):面向对象编程初级篇
面向:过程.函数.对象: 面向过程:根据业务逻辑从上到下写垒代码! 面向过程的编程弊:每次调用的时候都的重写,代码特别长,代码重用性没有,每次增加新功能所有的代码都的修改!那有什么办法解决上面出现的弊 ...
- Python全栈开发-Day6-面向对象编程
本节内容: 面向过程VS面向对象 面向对象编程介绍 类的语法 构造函数.析构函数 私有方法.私有属性 面向对象的特性:封装.继承.多态 1.面向过程 VS 面向对象 编程范式 编程是程序员用特定的语法 ...
随机推荐
- [转] Gradle中的buildScript代码块
PS: 在build script中的task apply plugin: 'spring-boot' 需要 classpath("org.springframework.boot:spri ...
- iTerm2和oh-my-zsh的个性化定制
终于在某东做活动新入手了一台air,看身边小伙伴的mac的终端感觉好炫酷,于是乎准备自己也捯饬捯饬,google了一下,发现了osx平台上的终端神器iTerm2和用来代替bash的oh-my-zsh, ...
- Because the people who are crazy enough to think they can change the world, are the ones who do.
Here's to the crazy ones. The misfits. The rebels. The troublemakers. The round pegs in the square h ...
- spring-qualifier解释
如果一个class有两个对应的beanId,在Autowired的时候,必须指定Qualifier("指定其中一个beanId"). org.springframework.bea ...
- Win7启动修复MBR(Win7+Linux删除Linux后进入grub rescue的情况)
事因:我的笔记本原先同时安装了Win7+Linux,昨天发现硬盘实在不够用(才60G,虽然还有个500G的移动硬盘),就想把里面的Ubuntu格了.都是用虚拟机做测试的多.后来就格了Ubuntu所在的 ...
- ASP.NET执行cmd命令
批处理命令,是执行速度最快效益最高的命令.因为批处理命令,说白了,就是ms-dos环境下的命令,有很多的批处理命令,都是纯DOS下的命令. 然而,批处理命令尽管功能强大,却存在不足之处.批处理命令只能 ...
- Ubuntu最小化桌面快捷键Super+D不生效解决
之前用的Debian,最近研发老大让统一使用Ubuntu来开发,安装了Ubuntu 15.10之后,设置了最小化桌面的快捷键为Super+D(在Systm Settings/系统设置—>Keyb ...
- css background-position:x% y%
规则1: background-position:xpx ypx; 为正值时:背景图片的左上顶点朝右下移动直至距离div的左上顶点为xpx ypx: 规则2: background-position: ...
- switch case加条件语句(非等值) php
<?php $s_level=rand(1,6); echo $s_level.'<br/>'; switch(true){ case $s_level<3 : echo 'l ...
- ecos之widget
weekbuy:widget.php<?php $setting['author']='zhang'; $setting['name']='周末购'; $setting['version']=' ...