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 面向对象 编程范式 编程是程序员用特定的语法 ...
随机推荐
- 《C专家编程》第一天
1.2 C语言的早期体验 1)C语言的基本数据类型直接与底层硬件相对应.C语言不存在内置的复数类型.C语言一开始不支持浮点类型,直到硬件系统能够直接支持浮点数之后才增加了对它的支持. 2)auto关键 ...
- C# 面向对象 , 抽象基类
抽象基类 关键字, abstract abstract class SSS { public void aaa() { } } 作为抽象基类, 只能在 继承关系 中 担任父类的角色,不能出现在其他地 ...
- spring aop切面配置
<bean id="aopLog" class="sardine.commodity.biz.AopLog"/> <aop:config ...
- 一条insert语句批量插入多条记录
一条insert语句批量插入多条记录 常见的insert语句,向数据库中,一条语句只能插入一条数据: insert into persons (id_p, lastname , firstName, ...
- Linux && vim 批量替换
Linux批量文件的字符串替换 sed -i "s/oldstring/newstring/g" `grep oldstring -rl path` vim多行替换::1,2s/s ...
- Swift - 37 - 值类型和引用类型的简单理解
//: Playground - noun: a place where people can play import UIKit // 值类型:指的是当一个变量赋值给另外一个变量的时候, 是copy ...
- 使用Scanner来解析文件
前面的流是全部流进来再处理,空间换取时间 我们用Scanner来解析文件,先处理再输入数据,时间换取空间 两种方法 Scanner scanner1=new Scanner(file1); for(; ...
- C#冒泡排序--详解
思路:以数组int[]a={55,42,15,3,66,52};为例. 每一轮排序都把最大的数放在最后 所以, 对应循环语句思路 这样就很清晰了. 代码如下: , , , , , , , }; ; i ...
- Oracle数据库之创建表空间与用户
Oracle数据库之创建表空间与用户 一.创建表空间 基本语法表述: CREATE TABLESPACE tablespace_name [DATAFILE datafile_spec1 [,data ...
- 学习笔记 之--AJAX核心对象 XMLHttpRequest
实现AJAX功能,核心就是XMLHttpRequest,而且现在大多数浏览器都支持这个核心组件对象. 实例:实现无刷新登陆验证 1.前台代码 <html xmlns="http://w ...