笔记(9)

编程需要两样东西:思路和工具。Python的特点就是很直白,也很贴近生活,即使没系统学过这种语言,也能从它的逻辑中读懂大概意思。因为这门语言更贴近人的想法,而不仅仅是冰冷的机器语言,所以更容易实现个体的想法。下面是个简单的塔防游戏例子:1、防守方,敌人,子弹,时间条,血条;2、运动轨迹、子弹轨迹;3、逻辑线条、算法计算;4、优化,包括统计结果、背景音乐、图片美观、用户体验。

其中一些代码是固定套路,可以移植,重复使用。如果从本质看塔防游戏(比如“保卫萝卜”)就是个你来我射的拉锯战,就是射击,要实现的包括:位移和碰撞消减,既然是游戏,包括人机互动(按键和鼠标的实现功能,很方便地体现在pygame模块包中)。

例子来源:http://blog.jobbole.com/46308/

感兴趣的最好看原版,略作修改,Python3版本可以实现,效果如下图:

 

  1 # 1 - Import library
  2 import pygame
  3 from pygame.locals import *
  4 import math
  5 import random
  6 
  7 # 2 - Initialize the game
  8 pygame.init()
  9 width, height = 640, 480   # 设置游戏屏幕大小
 10 screen = pygame.display.set_mode((width, height))
 11 keys = [False, False, False, False]  # 方向键和玩家初始位置的设置,当游戏进行时,玩家位置将和兔子重合(控制兔子位置)
 12 playerpos = [100, 100]
 13 acc = [0, 0]
 14 arrows = []
 15 badtimer = 100
 16 badtimer1 = 0
 17 badguys = [[640, 100]]
 18 healthvalue = 194
 19 pygame.mixer.init()
 20 
 21 # 3 - Load image 加载图片和背景音乐
 22 player = pygame.image.load("resources/images/dude.png")
 23 grass = pygame.image.load("resources/images/grass.png")
 24 castle = pygame.image.load("resources/images/castle.png")
 25 arrow = pygame.image.load("resources/images/bullet.png")
 26 badguyimg1 = pygame.image.load("resources/images/badguy.png")
 27 badguyimg = badguyimg1
 28 healthbar = pygame.image.load("resources/images/healthbar.png")
 29 health = pygame.image.load("resources/images/health.png")
 30 gameover = pygame.image.load("resources/images/gameover.png")
 31 youwin = pygame.image.load("resources/images/youwin.png")
 32 # 3.1 - Load audio
 33 hit = pygame.mixer.Sound("resources/audio/explode.wav")
 34 enemy = pygame.mixer.Sound("resources/audio/enemy.wav")
 35 shoot = pygame.mixer.Sound("resources/audio/shoot.wav")
 36 hit.set_volume(0.05)
 37 enemy.set_volume(0.05)
 38 shoot.set_volume(0.05)
 39 pygame.mixer.music.load('resources/audio/moonlight.wav')  # pygame.mixer.music.load 这一行加载游戏的背景音乐然后下一行让背景音乐一直不停的播放
 40 pygame.mixer.music.play(-1, 0.0)
 41 pygame.mixer.music.set_volume(0.25)  # 设置音量
 42 #xx = list(range(width//grass.get_width()+1))
 43 #yy = list(range(height//grass.get_height()+1))
 44 
 45 # 4 - keep looping through
 46 running = 1
 47 exitcode = 0
 48 while running:   # running变量会跟踪游戏是否结束
 49     badtimer -= 1
 50     # 5 - clear the screen before drawing it again
 51     screen.fill(0)
 52     # 6 - draw the player on the screen at X:100, Y:100
 53  #   for x in xx:
 54  #       for y in yy:
 55     for x in range(width//grass.get_width()+1):   # get 图片的宽和高
 56         for y in range(height//grass.get_height()+1):
 57             screen.blit(grass, (x*100, y*100))  # 双层循环嵌套,确保背景图片完全覆盖
 58     screen.blit(castle, (0, 30))   # 该函数表示在屏幕的特定位置安放特定图片
 59     screen.blit(castle, (0, 135))
 60     screen.blit(castle, (0, 240))
 61     screen.blit(castle, (0, 345))
 62     # 6.1 - Set player position and rotation
 63     position = pygame.mouse.get_pos()
 64     angle = math.atan2(position[1]-(playerpos[1]+32), position[0]-(playerpos[0]+26))  # atan2(y,x)[1]是y维;[0]是x维,因为兔子不是一个质点,参考位置不同就有32和26的微调
 65     playerrot = pygame.transform.rotate(player, 360-angle*57.29)  # 设置兔子图形转向,所以下面的playerrot既包含图形又包含转向的性质,同时需要把弧度转为角度
 66     playerpos1 = (playerpos[0]-playerrot.get_rect().width/2, playerpos[1]-playerrot.get_rect().height/2)
 67     screen.blit(playerrot, playerpos1)  # 兔子位置移动包括按键(直上直下)和鼠标操纵(转向)
 68     # 6.2 - Draw arrows  if表达式是检查箭头是否超出了屏幕范围,如果超出,就删除这个箭头。第二个for表达式是循环来把箭头根据相应的旋转画出来。
 69     for bullet in arrows:
 70         index = 0
 71         velx = math.cos(bullet[0])*10
 72         vely = math.sin(bullet[0])*10
 73         bullet[1] += velx
 74         bullet[2] += vely
 75         if bullet[1] < -64 or bullet[1] > 640 or bullet[2] < -64 or bullet[2] > 480:
 76             arrows.pop(index)
 77         index += 1
 78         for projectile in arrows:
 79             arrow1 = pygame.transform.rotate(arrow, 360-projectile[0]*57.29)
 80             screen.blit(arrow1, (projectile[1], projectile[2]))
 81     # 6.3 - Draw badgers
 82     if badtimer == 0:
 83         badguys.append([640, random.randint(50, 430)])
 84         badtimer = 100-(badtimer1*2)
 85         if badtimer1 >= 35:
 86             badtimer1 = 35
 87         else:
 88             badtimer1 += 5
 89     index = 0
 90     for badguy in badguys:
 91         if badguy[0] < -64:
 92             badguys.pop(index)
 93         badguy[0] -= 7
 94         # 6.3.1 - Attack castle  如果獾的x坐标离右边小于64,就删除坏蛋并且减少游戏里的健康值,减少的大小为5至20里的一个随机数。
 95         badrect=pygame.Rect(badguyimg.get_rect())
 96         badrect.top=badguy[1]
 97         badrect.left=badguy[0]
 98         if badrect.left<64:
 99             hit.play()
100             healthvalue -= random.randint(5,20)
101             badguys.pop(index)
102         #6.3.2 - Check for collisions 
103         index1=0
104         for bullet in arrows:
105             bullrect=pygame.Rect(arrow.get_rect())
106             bullrect.left=bullet[1]
107             bullrect.top=bullet[2]
108             if badrect.colliderect(bullrect):  # 查看子弹和敌人是否碰撞
109                 enemy.play()
110                 acc[0]+=1   # 统计精确度,碰撞加一
111                 badguys.pop(index)
112                 arrows.pop(index1)  # 碰撞则消除两者
113             index1+=1
114         # 6.3.3 - Next bad guy
115         index+=1
116     for badguy in badguys:
117         screen.blit(badguyimg, badguy)
118     # 6.4 - Draw clock
119     font = pygame.font.Font(None, 24)
120     survivedtext = font.render(str((90000-pygame.time.get_ticks())//60000)+":"+str((90000-pygame.time.get_ticks())//1000%60).zfill(2), True, (0,0,0))
121     textRect = survivedtext.get_rect()
122     textRect.topright = [635, 5]
123     screen.blit(survivedtext, textRect)
124     # 6.5 - Draw health bar
125     screen.blit(healthbar, (5,5))
126     for health1 in range(healthvalue):
127         screen.blit(health, (health1+8,8))
128     # 7 - update the screen
129     pygame.display.flip()
130     # 8 - loop through the events
131     for event in pygame.event.get():
132         # check if the event is the X button 
133         if event.type == pygame.QUIT:
134             # if it is quit the game
135             pygame.quit()
136             exit(0)
137         if event.type == pygame.KEYDOWN:  # 这是最有趣的地方——人机互动,你检查是否有一个键被按下或放开。然后,检查是哪一个键被按下或放开了,如果被按下或放开的键是你使用的,你就更新记录按键的变量。
138             if event.key==K_w:
139                 keys[0]=True
140             elif event.key==K_a:
141                 keys[1]=True
142             elif event.key==K_s:
143                 keys[2]=True
144             elif event.key==K_d:
145                 keys[3]=True
146         if event.type == pygame.KEYUP:
147             if event.key==pygame.K_w:
148                 keys[0]=False
149             elif event.key==pygame.K_a:
150                 keys[1]=False
151             elif event.key==pygame.K_s:
152                 keys[2]=False
153             elif event.key==pygame.K_d:
154                 keys[3]=False
155         if event.type==pygame.MOUSEBUTTONDOWN:  # 相应的鼠标按键检查,确定是否射击和射击初始位置及箭头(图形)旋转角度
156             shoot.play()
157             position=pygame.mouse.get_pos()
158             acc[1]+=1
159             arrows.append([math.atan2(position[1]-(playerpos1[1]+32),position[0]-(playerpos1[0]+26)),playerpos1[0]+32,playerpos1[1]+32])
160                 
161     # 9 - Move player
162     if keys[0]:   # 0、1、2、3对应W、A、S、D,对应位置以5个单位的移动变化
163         playerpos[1]-=5
164     elif keys[2]:
165         playerpos[1]+=5
166     if keys[1]:
167         playerpos[0]-=5
168     elif keys[3]:
169         playerpos[0]+=5
170 
171     #10 - Win/Lose check   第一个if表达式是检查是否时间到了。第二个是检查城堡是否被摧毁了。第三个计算你的精准度。之后,一个if表达式是检查你是赢了还是输了,然后显示出相应的图片。
172     if pygame.time.get_ticks()>=90000:
173         running=0
174         exitcode=1
175     if healthvalue<=0:
176         running=0
177         exitcode=0
178     if acc[1]!=0:
179         accuracy=acc[0]*1.0/acc[1]*100
180     else:
181         accuracy=0
182 # 11 - Win/lose display        
183 if exitcode==0:
184     pygame.font.init()
185     font = pygame.font.Font(None, 24)
186     text = font.render("Accuracy: "+str(accuracy)+"%", True, (255,0,0))
187     textRect = text.get_rect()
188     textRect.centerx = screen.get_rect().centerx
189     textRect.centery = screen.get_rect().centery+24
190     screen.blit(gameover, (0,0))
191     screen.blit(text, textRect)
192 else:
193     pygame.font.init()
194     font = pygame.font.Font(None, 24)
195     text = font.render("Accuracy: "+str(accuracy)+"%", True, (0,255,0))
196     textRect = text.get_rect()
197     textRect.centerx = screen.get_rect().centerx
198     textRect.centery = screen.get_rect().centery+24
199     screen.blit(youwin, (0,0))
200     screen.blit(text, textRect)
201 while 1:
202     for event in pygame.event.get():
203         if event.type == pygame.QUIT:
204             pygame.quit()
205             exit(0)
206     pygame.display.flip()

 

posted @ 2016-10-18 10:35  CC_python  阅读(363)  评论(0)    收藏  举报