在水一万 发表于 2015-4-22 08:07:21

第一个python+pygame小游戏

  没有周队那么有情调,自己写故事做rpg,又没什么绘画功底,只能做这样的休闲棋类游戏。本来是用java写的,但里面绘图太麻烦了(或者说我不会多线程),又想起前几天看到的pygame,于是果断python搞起了,从安装pygame,连学代做,到基本功能完成一共也不过两三个小时(小自恋一下~),又花了一个下午时间调整修正,终于可以拿出手了~~
  五子连珠是老妈最喜欢的游戏了,移动棋子使五个棋子在一条线上即可消去;移动后如果没有消去任何棋子,则会随机落下几颗棋子;另外移动时要保证起点和重点之间存在一条没有棋子的路径;如果棋盘满了则游戏结束,否则... 没有否则,没有胜利条件,就刷分数
  自己ps的图片太土了,干脆全用程序绘图,不用任何图片,所以看起来很简陋,使用的颜色是office上的推荐色,还算和谐(Hard难度凑不齐8种颜色,就自己调了两个,看起来好怪),棋子圆形锯齿消不掉,就那样好了,也就这些了......

  
  项目包含两个文件,Row5.py 和 Game.py,Game.py里有两个类,一个是Core内核类,控制游戏棋子信息什么的,一个Draw类,绘制游戏的相关信息,Row5.py是主文件,调用两个类实现游戏,下面代码+注释,中文注释可能会编译出错,看网上的方法改一下编码好了
  
  
  Row5.py


View Code


1 '''
2 Created on 2011-12-19
3
4 @author: Amb
5 '''
6
7 #Row5.py
8
9 import pygame
10 import Game
11
12 #初始化pygame
13 pygame.init()
14
15 #初始化游戏
16 def initgame(size,coln,fdropn,dropn):
17   global game,draw,menu_pos
18   game = Game.Core(size,coln,fdropn,dropn) #建立内核类
19   draw = Game.Draw(size,dropn) #建立绘图类
20   game.initcore() #初始化内核类
21   menu_pos=draw.initdraw(game) #初始化绘图类
22
23 #点击方格后执行该函数
24 def run(pos):
25   global fclick,over
26   global start_pos,target_pos
27   if pos >= lx or pos >= ly: return #不在棋盘范围内,跳出
28   if fclick: #如果是第一次点击
29         if game.getcolor(pos) != -1: #如果有棋子,则标记第一颗棋子
30             start_pos = pos
31             fclick = False
32             draw.circle(start_pos,game.getcolor(start_pos),1) #高亮该棋子
33   else: #否则第二次点击
34         if game.getcolor(pos) != -1: #如果第二次点击仍然是有棋子的格子
35             if pos == start_pos: #如果和第一次是同一个棋子,则取消选择
36               fclick = True
37               draw.circle(start_pos,game.getcolor(start_pos))
38             else: #否则切换第一颗棋子到当前棋子
39               pre = start_pos
40               draw.circle(pre,game.getcolor(pre),0)
41               start_pos = pos
42               draw.circle(start_pos,game.getcolor(start_pos),1)
43         else: #没棋子
44             target_pos = pos
45             path = game.getpath(start_pos, target_pos) #得到路径
46             if path != []: #路径不为空,可以到达,则沿途绘制棋子移动动画
47               col = game.getcolor(target_pos)
48               draw.path(start_pos,path,col)
49               clock.tick(40)
50             else: return #为空说明不能到达,直接返回
51             fclick = True
52             clear_arr = game.clearmap() #检查棋盘有没有可以消去的棋子
53             if clear_arr == []: #为空,则随机落子
54               fill_arr = game.fillcolors() #形参为空,为tip颜色随机位置,返回位置和颜色
55               for tfill in fill_arr:
56                     draw.circle(tfill,tfill)
57               game.randcolor() #形参为空,得到随机色为tip
58               draw.tip(game.gettip()) #绘制tip
59               clear_arr = game.clearmap() #再进行一次棋盘清除
60               for tpos in clear_arr:
61                     draw.rectangle(tpos)
62             else: #如果有棋子可以消去,则直接消去
63               for tpos in clear_arr:
64                     draw.rectangle(tpos)
65             draw.score(game.getscore()) #绘制分数
66
67 #行列数,颜色种类,起始时落子个数,每次落子个数
68 lx = 10
69 ly = 10
70 coln = 6
71 fdropn = 4
72 dropn = 3
73
74 #初始化游戏为默认值
75 initgame(,coln,fdropn,dropn)
76 #一些标记清空
77 fclick = True
78 over = False
79 pause = False
80 level_pos = []
81
82 #控制刷新频率
83 clock = pygame.time.Clock()
84
85 end = False
86 while end == False:
87   clock.tick(30) #间隔刷新次数,如果配置较低,玩起来比较卡,就设置的高一些
88   for event in pygame.event.get():
89         if event.type == pygame.QUIT: end = True #退出命令
90         if event.type == pygame.MOUSEBUTTONDOWN: #没判断鼠标键,所以中键,右键点击都是有效的
91             point = pygame.mouse.get_pos() #点击位置
92             if pause: #如果是在选择难度状态,那么只判断点击地方是否是按钮
93               if pygame.Rect(level_pos).collidepoint(point): #取消选择
94                     draw.initdraw(game) #重新把之前的状态绘出来
95                     pause = False
96                     continue
97               #下面是三种难度
98               elif pygame.Rect(level_pos).collidepoint(point):
99                     lx = 10
100                     ly = 10
101                     fdropn = 4
102                     coln = 5
103                     dropn = 3
104                     pause = False
105                     over = True
106               elif pygame.Rect(level_pos).collidepoint(point):
107                     lx = 12
108                     ly = 12
109                     fdropn = 4
110                     coln = 6
111                     dropn = 4
112                     pause = False
113                     over = True
114               elif pygame.Rect(level_pos).collidepoint(point):
115                     lx = 16
116                     ly = 16
117                     fdropn = 4
118                     coln = 8
119                     dropn = 4
120                     pause = False
121                     over = True
122               else: continue
123             #如果游戏结束,或者点击了Start,则重新开始游戏
124             if over or pygame.Rect(menu_pos).collidepoint(point):
125               game.updatascore() #关之前把最高分保存了
126               initgame(,coln,fdropn,dropn)
127               over = False
128               fclick = True
129               continue
130             elif pygame.Rect(menu_pos).collidepoint(point): #level,进入level菜单
131               pause = True
132               level_pos=draw.level()
133               game.updatascore()
134             elif pygame.Rect(menu_pos).collidepoint(point): #Exit,退出
135               end = True
136             else: #否则的话就去run一下
137               pos = draw.getpos(point)
138               run(pos)
139   if game.isover(): #游戏结束,退出,并保存最高分
140         over = True
141         draw.over()
142         game.updatascore()
143
144 game.updatascore()
145 #退出pygame
146 pygame.quit()
  
  两个类


View Code


1 '''
2 Created on 2011-12-19
3
4 @author: Amb
5 '''
6
7 #Game.py
8
9 import pygame
10 import struct
11 import random
12 import os
13 import Queue
14
15 class Core:
16   #根据传入信息,初始化内核类
17   def __init__(self,size,coln,fdropn,dropn):
18         self.lx = size
19         self.ly = size
20         self.coln=coln
21         self.fdropn=fdropn
22         self.dropn=dropn
23         self.map = [[-1 for y in range(self.ly)] for x in range(self.lx)]
24         self.score = 0
25         self.empty = self.lx*self.ly
26         self.tip = []
27         
28         if coln == 5: self.level = 0
29         elif coln == 6: self.level = 1
30         elif coln == 8: self.level = 2
31         
32         self.topscore = self.readdata()
33   
34   #得到某一个位置的颜色信息
35   def getcolor(self,pos):
36         return self.map]]
37   
38   #得到分数,返回[当前分,最高分]
39   def getscore(self):
40         return
41   
42   #返回游戏是否已经结束
43   def isover(self):
44         if self.empty == 0: return True
45         else: return False
46   
47   #返回下一组颜色提示信息,
48   def gettip(self):
49         return self.tip
50   
51   #返回num个随机颜色,如果未传入参数,则随机出tip个数,并赋值给类的tip数组
52   def randcolor(self,num = -1):
53         if num == -1: cnt = self.dropn
54         else: cnt = num
55         col = []
56         for i in range(cnt):
57             col.append(random.randint(0,self.coln-1))
58         if num == -1: self.tip = col
59         return col
60   
61   #填充颜色到一个随机位置,返回位置信息
62   def fill(self,col):
63         if self.empty==0: return [];
64         while True:
65             rx = random.randint(0,self.lx-1)
66             ry = random.randint(0,self.ly-1)
67             if self.map == -1:
68               self.map = col
69               self.empty-=1
70               return
71   
72   #填充一个颜色数组,返回[[位置,颜色]...]信息
73   def fillcolors(self,col=[]):
74         if col == []: col = self.tip
75         fillarray = []
76         for i in col:
77             tpos = self.fill(i)
78             if tpos == []: return fillarray
79             else: fillarray.append()
80         return fillarray
81   
82   #写入文件最高分数,如果没有传参,则初始化文件
83   def writedata(self,score=-1):
84         try:
85             if score == -1:
86               fout = open('game.dat','wb')
87               _bytes = struct.pack('iii',0,0,0)
88               fout.write(_bytes)
89               fout.close()
90             else:
91               fin = open('game.dat','rb')
92               _bytes = fin.read()
93               fin.close()
94               val =
95               val,val,val = struct.unpack('iii',_bytes)
96               #不知道这个地方为什么用元组取出来不能赋值
97               val = score
98               _bytes = struct.pack('iii',val,val,val)
99               fout = open('game.dat','wb')
100               fout.write(_bytes)
101               fout.close()
102         except IOError:
103             print 'IOError'
104            
105   #读取文件信息,如果不存在文件,则建立文件
106   def readdata(self):
107         try:
108             fin = open('game.dat','rb')
109             _bytes = fin.read()
110             fin.close()
111             val=struct.unpack('iii',_bytes)
112             return val
113         except:
114             self.writedata()
115             return 0
116   
117   #更新最高分数
118   def updatascore(self):
119         self.writedata(self.topscore)
120   
121   #初始化内核:包括第一次填充颜色,和随机出下一步tip
122   def initcore(self):
123         self.fillcolors(self.randcolor(self.fdropn))
124         self.randcolor()
125   
126   #得到移动路径,如果不能移动,返回[]
127   def getpath(self,spos,tpos):
128         pre = [[[-1,-1] for y in range(self.ly)] for x in range(self.lx)]
129         _dir = [,,[-1,0],]
130         que = Queue.Queue();
131         que.put(spos)
132         pre]] = [-2,-2];
133         while que.empty() == False:
134             upos = que.get()
135             for i in range(4):
136               vpos = +_dir,upos+_dir]
137               if vpos < 0 or vpos >= self.lx: continue
138               if vpos < 0 or vpos >= self.ly: continue
139               if self.map]] != -1: continue
140               if pre]] != -1: continue
141               pre]] = upos
142               if vpos == tpos:
143                     vx = vpos
144                     vy = vpos
145                     path = []
146                     while pre!=-2:
147                         path.append(pre)
148                         vx=pre]]
149                         vy=pre]]
150                         vpos =
151                     path.reverse()
152                     
153                     self.map]]=self.map]]
154                     self.map]]=-1;
155                     return path
156               que.put(vpos)
157         return []
158   
159   #清空五连棋子,返回要清空的位置元组
160   def clearmap(self):
161         vis = [ for x in range(self.ly)]
162         _dir = [,[-1,0],,,,[-1,-1],,[-1,1]]
163         for i in range(self.lx):
164             for j in range(self.ly):
165               if self.map == -1: continue
166               for k in :
167                     tx = i
168                     ty = j
169                     cnt = 1
170                     while True:
171                         tx += _dir
172                         ty += _dir
173                         if tx < 0 or tx >= self.lx: break
174                         if ty < 0 or ty >= self.ly: break
175                         if self.map != self.map: break
176                         cnt+=1
177                     if cnt >= 5:
178                         while True:
179                           tx -= _dir
180                           ty -= _dir
181                           if tx < 0 or tx >= self.lx: break
182                           if ty < 0 or ty >= self.ly: break
183                           if self.map != self.map: break
184                           vis = True
185         block = []
186         for i in range(self.lx):
187             for j in range(self.ly):
188               if vis:
189                     self.empty+=1
190                     self.score+=1 #算出分数,这个地方有待改进
191                     block.append()
192                     self.map=-1
193         if self.score>self.topscore:
194             self.topscore = self.score
195         return block
196
197
198
199
200
201
202 #graph
203 #各种颜色
204 black = (0,0,0)
205 white = (255,255,255)
206 background = (100,100,100)
207 font_col = (192,80,77)
208
209 color = [[(31,73,125),(192,80,77),(155,187,89),(128,100,162),(75,172,198),(247,150,70),(255,241,59),(232,12,122)],\
210         [(135,176,225),(227,176,175),(217,229,193),(202,190,216),(185,223,233),(252,211,178),(255,248,160),(231,120,169)]]
211
212 xlen=30
213 ylen=30
214 glen=2
215 rlen=12
216
217 class Draw:
218   #初始化绘图,主要是初始pygame和窗口
219   def __init__(self,size,tipn):
220         pygame.init()
221         
222         self.lx=size
223         self.ly=size
224         self.tipn=tipn
225         sizex=(xlen+glen)*self.lx+50
226         sizey=(ylen+glen)*(self.ly+self.tipn)+40
227         self.screen = pygame.display.set_mode()
228         pygame.display.set_caption('Row 5')
229         self.font = pygame.font.Font("PLAYBILL.TTF", 28)
230         icon=pygame.image.load('Row5.png').convert_alpha()
231         pygame.display.set_icon(icon)
232
233   #返回某一个坐标对应的格子位置
234   def getpos(self,pos):
235         px = (pos-glen-20)/(xlen+glen)
236         py = (pos-glen-20)/(ylen+glen)
237         return
238   
239   #画矩形,在棋盘pos(注意是格子id)处绘制一个30*30的白色矩形,主要是起始初始化棋盘和覆盖棋盘用
240   def rectangle(self,pos):
241         px = (xlen+glen)*pos+glen+20
242         py = (ylen+glen)*pos+glen+20
243         pygame.draw.rect(self.screen,white,)
244         pygame.display.update()
245   
246   #画格子,调用rectangle函数,绘制棋盘
247   def grid(self):
248         for i in range(self.lx):
249             for j in range(self.ly):
250               self.rectangle()
251   
252   #绘制棋子,在棋盘pos处
253   def circle(self,pos,col,islight=0):
254         if col == -1: return
255         px = (xlen+glen)*pos+glen+xlen/2+20
256         py = (ylen+glen)*pos+glen+ylen/2+20
257         pygame.draw.circle(self.screen,color,,rlen)
258         pygame.draw.circle(self.screen,black,,rlen,2)
259         pygame.display.update()
260   
261   #路径绘制,沿path一格一格绘制
262   def path(self,spos,path,col):
263         clock = pygame.time.Clock()
264         pre = spos
265         for pos in path:
266             clock.tick(40)
267             self.circle(pos,col)
268             self.rectangle(pre)
269             pre = pos
270   
271   #绘制tip
272   def tip(self,col):
273         for i in range(self.tipn):
274             px = (xlen+glen)*self.lx+glen+(xlen+glen)*i+xlen/2+30
275             py = ylen/2+30
276             pygame.draw.circle(self.screen,color],,rlen)
277             pygame.draw.circle(self.screen,black,,rlen,2)
278             pygame.display.update()
279      
280   #绘制分数,一个最高分,一个当前分
281   def score(self,val):
282         px = (xlen+glen)*(self.lx+self.tipn)-45
283         py = 80
284         score = self.font.render('%8d' %(val),True,font_col,background)
285         self.screen.blit(score,)
286         py = 110
287         score = self.font.render('%8d' %(val),True,color,background)
288         self.screen.blit(score,)
289         pygame.display.update()
290   
291   #绘制菜单,返回菜单位置矩形
292   def menu(self):
293         menu_pos = []
294         
295         px = (xlen+glen)*(self.lx+self.tipn)-60
296         py = (ylen+glen)*(self.ly+self.tipn)-225
297         menu_pos.append()
298         pygame.draw.rect(self.screen,,)
299         py = (ylen+glen)*(self.ly+self.tipn)-190
300         menu_pos.append()
301         pygame.draw.rect(self.screen,,)
302         py = (ylen+glen)*(self.ly+self.tipn)-155
303         menu_pos.append()
304         pygame.draw.rect(self.screen,,)
305         
306         
307         px = (xlen+glen)*(self.lx+self.tipn)-45
308         py = (ylen+glen)*(self.ly+self.tipn)-225
309         button = self.font.render('Start',True,font_col)
310         self.screen.blit(button,)
311         py = (ylen+glen)*(self.ly+self.tipn)-190
312         button = self.font.render('Level',True,font_col)
313         self.screen.blit(button,)
314         py = (ylen+glen)*(self.ly+self.tipn)-155
315         button = self.font.render('Exit',True,font_col)
316         self.screen.blit(button,)
317         pygame.display.update()
318         return menu_pos
319   
320   #绘制level菜单,返回level菜单位置
321   def level(self):
322         menu_pos = []
323         pygame.draw.rect(self.screen,background,self.screen.get_rect())
324         px = self.screen.get_width()/2-40
325         py = self.screen.get_height()/2+60
326         menu_pos.append()
327         pygame.draw.rect(self.screen,,)
328         py = self.screen.get_height()/2-60
329         menu_pos.append()
330         pygame.draw.rect(self.screen,,)
331         py = self.screen.get_height()/2-20
332         menu_pos.append()
333         pygame.draw.rect(self.screen,,)
334         py = self.screen.get_height()/2+20
335         menu_pos.append()
336         pygame.draw.rect(self.screen,,)
337
338         px = self.screen.get_width()/2-30
339         py = self.screen.get_height()/2-60
340         button = self.font.render('Easy',True,font_col)
341         self.screen.blit(button,)
342         py = self.screen.get_height()/2-20
343         button = self.font.render('Normal',True,font_col)
344         self.screen.blit(button,)
345         py = self.screen.get_height()/2+20
346         button = self.font.render('Hard',True,font_col)
347         self.screen.blit(button,)
348         py = self.screen.get_height()/2+60
349         button = self.font.render('Cancel',True,font_col)
350         self.screen.blit(button,)
351         pygame.display.update()
352         return menu_pos
353   
354   #初始绘图,在初始core之后调用这个,返回菜单位置
355   def initdraw(self,core):
356         self.screen.fill(background)
357         self.grid()
358         for i in range(self.lx):
359             for j in range(self.ly):
360               self.circle(,core.getcolor())
361         self.tip(core.gettip())
362         self.score(core.getscore())
363         menu_pos = self.menu()
364         return menu_pos
365   
366   #绘制游戏结束标志
367   def over(self):
368         px = (xlen+glen)*self.lx/2-20
369         py = (ylen+glen)*self.ly/2-20
370         pygame.draw.rect(self.screen,background,)
371         px = (xlen+glen)*self.lx/2-10
372         py = (ylen+glen)*self.ly/2-10
373         over = self.font.render('Game over',True,font_col,background)
374         self.screen.blit(over,)
375         pygame.display.update()
376      
377   
  

  exe和源码下载-12月30更新
  一些学python和pygame的资料
  doc
  http://docs.python.org/
  http://pygame.org/docs/
  
  教程
  http://sebug.net/paper/python/
  http://www.korokithakis.net/tutorials/python/
  http://hyperpolyglot.org/scripting?utm_source 几种脚本对比
  
  http://coolshell.cn/articles/4710.html
  http://eyehere.net/2011/python-pygame-novice-professional-index/ 这个很不错哦
  
页: [1]
查看完整版本: 第一个python+pygame小游戏