赞
踩
我把整个文件(这个实践的)放“喵做梦技术讨论群”里了,需者加群自取。
QQ群号:566341887 (大家一起互帮互助,共同进步,交流分享,奔赴未来!)
书接上回, 废话不多说,直接开干!
第一步就迅速点,直接过。
同一级中放代码,存放图片的文件夹P和存放数据的文件夹data。
好,非常快,继续!
也就是最最最基础,简单的,什么导入模块啊,弹出窗口啊之类了。
这里也是非常的简单,速过!
- import pygame
- from random import randint
-
- pygame.init()
- scsize=(1000,600)
-
- screen=pygame.display.set_mode(scsize)
- pygame.display.set_caption("乱来的PVZ")
-
- while True:
- for event in pygame.event.get():
- if event.type==pygame.QUIT:
- pygame.quit()
- pygame.display.flip()
顺手把帧率和字体渲染一类简单的给准备好。
- import pygame
- from random import randint
-
- pygame.init()
- scsize=(1000,600)
-
- #基础
- screen=pygame.display.set_mode(scsize)
- pygame.display.set_caption("乱来的PVZ")
- zf=pygame.time.Clock()
- ts=pygame.font.SysFont("simhei",20)
- tc=ts.render("",True,(0,0,0))
-
- while True:
- for event in pygame.event.get():
- if event.type==pygame.QUIT:
- pygame.quit()
- zf.tick(30)
- pygame.display.flip()
非常的简单喵,下一步。
目前这几步都挺简单的,状态机的话,浅浅分一下:
这么来分,普通模式、娱乐模式、无尽模式、商店、各种各样……太多就先不一一举例了。
无论是什么模式,其实只要会一种了,其他的也就简单了,所以我们先从普通模式开始。
- import pygame
- from random import randint
-
- pygame.init()
- scsize=(1000,600)
-
- #全局变量
- menu=0
- putongmark=1
-
- #基础
- screen=pygame.display.set_mode(scsize)
- pygame.display.set_caption("乱来的PVZ")
- zf=pygame.time.Clock()
- ts=pygame.font.SysFont("simhei",20)
- tc=ts.render("",True,(0,0,0))
-
- while True:
- for event in pygame.event.get():
- if event.type==pygame.QUIT:
- pygame.quit()
- if menu==0:#进入界面
- pass
- elif menu==1:#菜单
- pass
- zf.tick(30)
- pygame.display.flip()
这一步的目标非常明确,是为了让游戏能运行(但是不能打僵尸目前)。
我们要根据窗口的大小,绘制相应的图片。
并且要通过读取鼠标的坐标,以及判断是否按下来确定是否改变menu的值。
这种图片如果要还原的话,大家最好还是去网上搜原图,截下来,然后扣掉边边角角拿来用。
本喵的选择是:自己手搓,这样好玩。
那么开始!
我自己画了一张,非常抽象,无所谓,自己开心就行。
(通过不同状态下的login按键,提示玩家是否触屏到了按键。)
接下来,让我们输入一些简单的代码。(不懂的看以前写的。)
- import pygame
- from random import randint
-
- pygame.init()
- scsize=(1000,600)
-
- #全局变量
- menu=0
- putongmark=1
-
- #基础
- screen=pygame.display.set_mode(scsize)
- pygame.display.set_caption("乱来的PVZ")
- zf=pygame.time.Clock()
- ts=pygame.font.SysFont("simhei",20)
- tc=ts.render("",True,(0,0,0))
-
- #login
- loginback=pygame.image.load("P/login/loginback.png")
- login=pygame.image.load("P/login/loginno.png")
- loginmark=0
- #menu
- menuback=pygame.image.load("P/menu/back.png")
-
- while True:
- for event in pygame.event.get():
- if event.type==pygame.QUIT:
- pygame.quit()
- mox, moy = pygame.mouse.get_pos() #实时读取鼠标x,y
- if menu==0:#进入界面
- screen.blit(loginback,(0,0))
- screen.blit(login,(400,400))
- if loginmark==0:
- login=pygame.image.load("P/login/loginno.png")
- else : login=pygame.image.load("P/login/loginyes.png")
- loginmark=0
- if mox>=400 and mox<=600:
- if moy>=400 and moy<=450:
- loginmark=1
- if loginmark==1 and event.type == pygame.MOUSEBUTTONDOWN:
- menu=1
- elif menu==1:#菜单
- screen.blit(menuback,(0,0))
- zf.tick(30)
- pygame.display.flip()
非常的简单,里面这个对loginmark的判断,就是提示玩家鼠标是否碰到该按键。
我们就先从最简单的开始。
(还要做一个进入到冒险模式的按键)
把这个也缝合进去之后,我们就可以真正开始了。
- import pygame
- from random import randint
-
- pygame.init()
- scsize=(1000,600)
-
- #全局变量
- menu=0
- putongmark=1
-
- #基础
- screen=pygame.display.set_mode(scsize)
- pygame.display.set_caption("乱来的PVZ")
- zf=pygame.time.Clock()
- ts=pygame.font.SysFont("simhei",20)
- tc=ts.render("",True,(0,0,0))
-
- #login
- loginback=pygame.image.load("P/login/loginback.png")
- login=pygame.image.load("P/login/loginno.png")
- loginmark=0
- #menu
- menuback=pygame.image.load("P/menu/back.png")
- mx=pygame.image.load("P/menu/maoxianno.png")
- mxmark=0
-
- while True:
- for event in pygame.event.get():
- if event.type==pygame.QUIT:
- pygame.quit()
- mox, moy = pygame.mouse.get_pos() #实时读取鼠标x,y
- if menu==0:#进入界面
- screen.blit(loginback,(0,0))
- screen.blit(login,(400,400))
- if loginmark==0:
- login=pygame.image.load("P/login/loginno.png")
- else : login=pygame.image.load("P/login/loginyes.png")
- loginmark=0
- if mox>=400 and mox<=600:
- if moy>=400 and moy<=450:
- loginmark=1
- if loginmark==1 and event.type == pygame.MOUSEBUTTONDOWN:
- menu=1
- elif menu==1:#菜单
- screen.blit(menuback,(0,0))
- screen.blit(mx,(700,200))
- if mxmark==0:
- mx=pygame.image.load("P/menu/maoxianno.png")
- else : mx=pygame.image.load("P/menu/maoxianyes.png")
- mxmark=0
- if mox>=700 and mox<=880:
- if moy>=200 and moy<=250:
- mxmark=1
- if mxmark==1 and event.type == pygame.MOUSEBUTTONDOWN:
- menu=2
- elif menu==2:#冒险模式
- pass
- zf.tick(30)
- pygame.display.flip()
在植物大战僵尸中,关卡里面有几个重要的元素:草坪背景、阳光数量显示、卡牌、僵尸。
那么就先随便画点图片(大不了后期做优化)。
但是,不急着画,先理论,后运用。毕竟这个图片大小,是有点影响后面的。
关卡中,我们要先知道,这个窗口的大小为1000×600,我们接下来要对其进行合理地分划。
我数出来,关卡中草坪的区块是9×5个,那么我们可以把每个区块的大小画成100×100。
从上到下,从左到右依次为:
阳光 | 卡片槽 | 铲子 | 菜单 |
小推车 | 草坪 | 僵尸产地 | |
钱 | 关卡名称 | 僵尸进度 |
简单完善一下这个背景。
有点简陋,不过也还好。
当我们选取卡片槽中的一张卡片时,要把它放进各个区块中,就要对鼠标在哪个区块进行判断。
分别用qkx和qky 来表示鼠标所处草坪区块的位置,根据我的这个图片的话,这个草坪的最左上角差不多是(30,90),接下来通过一些列的对鼠标mox和moy的判断,来确定qkx和qky。
点击过卡片后,一株虚拟的植物应该随着鼠标而移动,简而言之就是screen.blit(choice,(mox,moy)),再通过if判断鼠标是否按下,来确定是否种下植物。
而且要注意的是,如果鼠标的mox和moy不在这个草坪的范围内的话,点击鼠标时,就要重新将植物返回到卡片槽中。
这个的话,randint是必不可少的,但是不止这点。
randint可以用来确定僵尸出现在那一排,以及出现什么类型的僵尸。后面这个出现什么类型的僵尸,可以通过当前游戏关卡的进度来确定。
出现之后,通过建立精灵组和精灵,控制每一个僵尸的血量,以及速度。
对于阳光的数量,我们可以通过pygame.font.SysFont("simhei",20)来实现显示数据。
其次,对于白天和屋顶的关卡,阳光会随机自动从天上掉下来,因此可以使用randint来实现。(还要考虑到阳光下落的位置,下落时长,都要考虑)
这个更加简单了,通过图片缩放即可。但是有个注意点,这个进度条是从右到左,于是我们就可以在图片缩放的条件下,把这个进度条往左边挪一点,这么来看的话,就像是进度条往左移动了。
铲子:和植物放置一个原理,只要把放置改为清除即可。
菜单:那就再跳出一块,并且把关卡中僵尸移动速度,植物的子弹发射之类全部改为0,这样就像是被静止了。再在菜单中按选项。
不急哈,慢慢来。
先来张卡片,豌豆射手!(图片均为自己画的,不喜勿喷,谢谢!)
如此,也就将就一下吧。
这个我们先设豌豆射手的生命值为100,经过本喵的检测,豌豆射手大概每1.5s发射一颗豌豆。
为了更加方便,我们将频率改成25帧/s。
zf.tick(25)
每秒运行25次,即运行一遍程序耗时0.04秒,每运行一次,将豌豆射手的cd减1,可设豌豆射手的初始cd约为38。
- #shiwu
- #wandousheshou
- class wandousheshou(pygame.sprite.Sprite):
- def __init__(self):
- super().__init__()
- self.image=pygame.image.load("P/kp/wandousheshou/shiwu.png")
- hp=100
- cd=38
暂且得到这么一个类。为了判断鼠标选择植物后,种下植物的位置,我们需要先制作卡片在卡槽中。
这个卡片,不单单是读取图片,直接绘制在屏幕上。首先要知道整个流程,先是在正式开始前,选择好卡片,后面卡片再根据玩家选择顺序出现在卡槽中。
所以说,我们需要一个列表,用来存储玩家选择卡片的顺序,并且赋予不同卡片不同的编号。
(当前提供9个卡槽)
choice=[0]*10 #1-豌豆射手
'运行
这样一来,许多乱七八糟的问题就解决了,直接用编号来判断所选择的植物,先用编号代替,后期再一次性渲染即可。
那么对于我这个草坪而言,卡槽的最左端的x为104,差不多100,且卡片大小为50×70,则第一张卡片应该位于(100,0),用center的话,应该(125,35)。
先做一个简单的class,如下。
- choice=[0]*10 #1-豌豆射手
- choicemark=1
- choicelocation=1
- #kp
- class kp(pygame.sprite.Sprite):
- def __init__(self):
- super().__init__()
- if choice[choicemark]==1:
- self.image=pygame.image.laod("P/kp/wandousheshou/kpshiwu.png")
- self.rect=self.image.get_rect(center=(75+choicelocation*50,35))
-
- kp_group=pygame.sprite.Group()
chyn=0 #0未选取卡片;1已选取卡片
'运行
先来一个全局变量,确认是否选取了植物。
- elif menu==2:#冒险模式
- screen.blit(gqcp,(0,0))
- for i in range(0,10):
- kp_group.add(kp())
- choicemark=i+1
- kp_group.draw(screen)
- if event.type == pygame.MOUSEBUTTONDOWN:
- if chyn==0:
- chyn=1
- pdx=(mox-100)//50+1
- if pdx==1: choicekp=pygame.image.load("P/kp/wandousheshou/shiwu.png")
- else: chyn=0
- if chyn==1:
- screen.blit(choicekp,(mox,moy))
在冒险模式中,这个for是用来渲染的,使卡槽中出现卡片。
其次,用if判断鼠标是否按下,再根据是否已经选择卡片的不同情况运行不同程序。
这个位置是怎么判断的呢?
喵:减去初始位置的x值100,采用取整的方法,整除50是因为每张卡片的宽为50。
+1是因为,整除不是四舍五入,如果鼠标位置为130时,没有+1的话,运行出来结果是0。
下面的那个if是在鼠标选择卡片后,让植物被鼠标拖动。
接下来是把植物种在草坪上,不但要判断mox,还有moy。上文已知每个草坪的大小为100×100,且草坪左上角为(30,90),那么同理可以判断种植位置。
wandousheshou_group=pygame.sprite.Group()
存放豌豆射手之类植物的组。
- elif chyn==1 and mox>=30 and moy>=90:
- pdx=(mox-30)//100
- pdy=(moy-90)//100
- wandousheshou_group.add(wandousheshou())
- chyn=0
(pdx和pdy都要设置一个全局变量)
相应的,我们要对wandousheshou这个类class进行一些调整和补充。
- class wandousheshou(pygame.sprite.Sprite):
- def __init__(self):
- super().__init__()
- self.image=pygame.image.load("P/kp/wandousheshou/shiwu.png")
- self.rect=self.image.get_rect(center=(30+30+pdx*100,90+35+pdy*100))
- hp=100
- cd=38
这样一来,我们就能很好地实现了这个选择卡片,以及放置相应植物。
写到这里,差不多有模有样的已经有了,那让我们来小小测试一下。
上面的代码比较零散,本喵就在下面展示一下本喵当前写的。
- import pygame
- from random import randint
-
- pygame.init()
- scsize=(1000,600)
-
- #全局变量
- menu=0
- putongmark=1
- pdx,pdy=0,0
-
- #基础
- screen=pygame.display.set_mode(scsize)
- pygame.display.set_caption("乱来的PVZ")
- zf=pygame.time.Clock()
- ts=pygame.font.SysFont("simhei",20)
- tc=ts.render("",True,(0,0,0))
-
- #login
- loginback=pygame.image.load("P/login/loginback.png")
- login=pygame.image.load("P/login/loginno.png")
- loginmark=0
- #menu
- menuback=pygame.image.load("P/menu/back.png")
- mx=pygame.image.load("P/menu/maoxianno.png")
- mxmark=0
- #base
- gqcp=pygame.image.load("P/base/cp.png")
- choice=[1]*11 #1-豌豆射手
- choicemark=1
- choicelocation=1
- chyn=0 #0未选取卡片;1已选取卡片
- choicekp=pygame.image.load("P/kp/wandousheshou/kpshiwu.png")
- #kp
- class kp(pygame.sprite.Sprite):
- def __init__(self):
- super().__init__()
- if choice[choicemark]==1:
- self.image=pygame.image.load("P/kp/wandousheshou/kpshiwu.png")
- self.rect=self.image.get_rect(center=(75+choicelocation*50,35))
-
- #shiwu
- #wandousheshou
- class wandousheshou(pygame.sprite.Sprite):
- def __init__(self):
- super().__init__()
- self.image=pygame.image.load("P/kp/wandousheshou/shiwu.png")
- self.rect=self.image.get_rect(center=(30+30+pdx*100,90+35+pdy*100))
- hp=100
- cd=38
-
- kp_group=pygame.sprite.Group()
- wandousheshou_group=pygame.sprite.Group()
-
- while True:
- for event in pygame.event.get():
- if event.type==pygame.QUIT:
- pygame.quit()
- mox, moy = pygame.mouse.get_pos() #实时读取鼠标x,y
- if menu==0:#进入界面
- screen.blit(loginback,(0,0))
- screen.blit(login,(400,400))
- if loginmark==0:
- login=pygame.image.load("P/login/loginno.png")
- else : login=pygame.image.load("P/login/loginyes.png")
- loginmark=0
- if mox>=400 and mox<=600:
- if moy>=400 and moy<=450:
- loginmark=1
- if loginmark==1 and event.type == pygame.MOUSEBUTTONDOWN:
- menu=1
- elif menu==1:#菜单
- screen.blit(menuback,(0,0))
- screen.blit(mx,(700,200))
- if mxmark==0:
- mx=pygame.image.load("P/menu/maoxianno.png")
- else : mx=pygame.image.load("P/menu/maoxianyes.png")
- mxmark=0
- if mox>=700 and mox<=880:
- if moy>=200 and moy<=250:
- mxmark=1
- if mxmark==1 and event.type == pygame.MOUSEBUTTONDOWN:
- menu=2
- elif menu==2:#冒险模式
- screen.blit(gqcp,(0,0))
- for i in range(0,10):
- kp_group.add(kp())
- choicemark=i+1
- kp_group.draw(screen)
- wandousheshou_group.draw(screen)
- if event.type == pygame.MOUSEBUTTONDOWN:
- if chyn==0:
- chyn=1
- pdx=(mox-100)//50+1
- if pdx==1: choicekp=pygame.image.load("P/kp/wandousheshou/shiwu.png")
- else: chyn=0
- elif chyn==1 and mox>=30 and moy>=90:
- pdx=(mox-30)//100
- pdy=(moy-90)//100
- wandousheshou_group.add(wandousheshou())
- chyn=0
- if chyn==1:
- screen.blit(choicekp,(mox,moy))
- zf.tick(25)
- pygame.display.flip()
再展示一下视频,这个效果。
自制PVZ的小测试
僵尸也是必不可少的一部分,先来一只(风韵犹存的)普通僵尸。
非常的好看,接下来就交给代码了。
先创建一个精灵类。
- #jiangshi
- #putong
- class putong(pygame.sprite.Sprite):
- def __init__()
- super().__init__()
- self.image=pygame.image.load("P/jiangshi/putong.png")
- hp=100
不急好吧,假设血量为100。我试了一下。
数出来普通豌豆射手打普通僵尸,打了5颗后,僵尸掉手臂,10颗后僵尸死亡。7秒左右,普通僵尸就会走完一块草坪。
据此进行编写代码。
先随机生成数字1~5,来确定僵尸生成在哪一路。再多加几张图,让僵尸正常走路,不是死板平移。控制好僵尸的移动速度,以及血量。
我们需要定时来生成新的僵尸,并且随机生成在任意一条路。
- time=0
- shch=0
-
- #jiangshi
- #putong
- class putong(pygame.sprite.Sprite):
- def __init__(self):
- super().__init__()
- self.image=pygame.image.load("P/jiangshi/putong.png")
- self.rect=self.image.get_rect(center=(950,shch*100+30))
- hp=100
-
- putongjiangshi_group=pygame.sprite.Group()
然后再在冒险模式中,对精灵与精灵组进行操作。
- elif menu==2:#冒险模式
- time+=1
- if time>=100:
- time=0
- shch=randint(1,5)
- putongjiangshi_group.add(putong())
- putongjiangshi_group.draw(screen)
非常的简单,无需多言解释吧。
给僵尸多画几张图~
在精灵类里面,加一个update,让它实时更新走路姿势和位置。
- #jiangshi
- #putong
- class putong(pygame.sprite.Sprite):
- def __init__(self):
- super().__init__()
- self.image=pygame.image.load("P/jiangshi/putong/putong.png")
- self.rect=self.image.get_rect(center=(950,shch*100+30))
- self.zishi=1
- self.hp=100
- def update(self):
- if self.zishi==1:
- self.image=pygame.image.load("P/jiangshi/putong/putong.png")
- elif self.zishi==3:
- self.image=pygame.image.load("P/jiangshi/putong/putongd1.png")
- elif self.zishi==5:
- self.image=pygame.image.load("P/jiangshi/putong/putong.png")
- elif self.zishi==7:
- self.image=pygame.image.load("P/jiangshi/putong/putongd2.png")
- elif self.zishi>=9 : self.zishi=0
- self.zishi+=1
- self.rect.x-=0.6
最底下这个self.rect.x-=0.6是算出来的,为了保证约7秒走一格草坪。
我们要知道,不是所有的路线都有僵尸,不是所有的植物发射的都是豌豆。
来一个二维数组,存储草坪上的植物。为了方便,既然草坪是9×5,那么来个10×6的二维数组好了。
zhiwu=[[0]*10]*6
'运行
再来一个精灵类,用来控制豌豆的发射。
我刚刚又去测了一下,豌豆飞过5格草坪的时间约是1秒,再结合运行一次程序是0.04秒,每格草坪为100×100,可以得出每运行一次程序,豌豆在屏幕中x上移动4个像素。
- #wandou
- class wandou(pygame.sprite.Sprtie):
- def __init__(self):
- super().__init__()
- self.image=pyagme.image.load("P/kp/wandousheshou/wandou.png")
- def update(self):
- self.rect.x+=4
非常简单,除此之外我们还需要一个列表来读取每条路线僵尸的个数。
jiance=[0]*6
'运行
在每次生成僵尸的时候顺便把这个jiance[i]+=1,相对应的还要对僵尸之类做一些调整,先不管,后期再优化。
豌豆射手发射豌豆的条件是只要有僵尸即可,与数量无关。
1、那么对jiance这个列表进行遍历,且要遍历检测这一列草坪上的植物。如果没有僵尸就不遍历草坪上植物,这样还能避免没必要的遍历。
- for i in range(1,6):
- if jiance[i]>0 :
- for j in range(1,10):
- if zhiwu[i][j]==1 and cd[i][j]<=0:
- wandoux=j
- wandouy=i
- wandou_group.add(wandou())
- cd[i][j]=38
2、种植植物的时候也要顺带加个改变二维数组里面的编号。
3、检测到有豌豆射手的时候,那就要读取它的位置,这个用全局变量也可以,或是调用的时候直接读取也可以。
- elif chyn==1 and mox>=30 and moy>=90:
- pdx=(mox-30)//100
- pdy=(moy-90)//100
- zhiwu[pdy+1][pdx+1]=1
- wandousheshou_group.add(wandousheshou())
- chyn=0
4、再来一个cd的二维数组,来控制发射间隔。
- cd=[([0]*10) for i in range(6)]
-
- elif menu==2:#冒险模式
- for i in range(1,6):
- for j in range(1,10):
- cd[i][j]-=1
5、删去原豌豆射手精灵类里面的cd。
okok啊!下面就是简简单单的了,加个碰撞,从而修改生命值,先来僵尸的和豌豆的。
在冒险模式中加入以下碰撞检测。
- col = pygame.sprite.groupcollide(wandou_group, putongjiangshi_group, True, False)
- for sprite, list in col.items():
- for s in list:
- s.hp -= 10
确认碰撞之后,就是修改僵尸的ph值了。
- #jiangshi
- #putong
- class putong(pygame.sprite.Sprite):
- def __init__(self):
- super().__init__()
- self.image=pygame.image.load("P/jiangshi/putong/putong.png")
- self.rect=self.image.get_rect(center=(950,shch*100+30))
- self.zishi=1
- self.location=shch
- self.hp=100
- def update(self):
- if self.zishi==1:
- self.image=pygame.image.load("P/jiangshi/putong/putong.png")
- elif self.zishi==3:
- self.image=pygame.image.load("P/jiangshi/putong/putongd1.png")
- elif self.zishi==5:
- self.image=pygame.image.load("P/jiangshi/putong/putong.png")
- elif self.zishi==7:
- self.image=pygame.image.load("P/jiangshi/putong/putongd2.png")
- elif self.zishi>=9 : self.zishi=0
- self.zishi+=1
- self.rect.x-=0.6
- global wf
- global jiance
- if self.rect.x<0:
- wf=0
- if self.hp<=0:
- jiance[self.location]-=1
- self.kill()
哦对了,那个wf是用于失败检测的,也就是游戏失败。
然后最后那个if是没血的时候,把该精灵从精灵组移除,还要改变当前路线上对僵尸数量的检测。
目前写代码写下来呢就是有个问题,僵尸哪怕在植物身后,在僵尸身后的豌豆射手也会发生豌豆,这个就不得不把这个检测升级成二维了。
jiance=[([0]*10) for i in range(6)]
'运行
生成僵尸的时候也要改动。
- if time>=100:
- time=0
- shch=randint(1,5)
- jiance[shch][9]+=1
- putongjiangshi_group.add(putong())
僵尸这个精灵里面每次移动也要对应的检测一下是否发生了变化。
- class putong(pygame.sprite.Sprite):
- def __init__(self):
- super().__init__()
- self.image=pygame.image.load("P/jiangshi/putong/putong.png")
- self.rect=self.image.get_rect(center=(950,shch*100+30))
- self.zishi=1
- self.location=shch
- self.hp=100
- self.pastlo=9
- def update(self):
- if self.zishi==1:
- self.image=pygame.image.load("P/jiangshi/putong/putong.png")
- elif self.zishi==3:
- self.image=pygame.image.load("P/jiangshi/putong/putongd1.png")
- elif self.zishi==5:
- self.image=pygame.image.load("P/jiangshi/putong/putong.png")
- elif self.zishi==7:
- self.image=pygame.image.load("P/jiangshi/putong/putongd2.png")
- elif self.zishi>=9 : self.zishi=0
- self.zishi+=1
- self.rect.x-=0.6
- global wf
- global jiance
- lo=(self.rect.x-30)//100+1
- if self.pastlo-lo>0:
- jiance[self.location][self.pastlo]-=1
- jiance[self.location][lo]+=1
- self.pastlo=lo
- if self.rect.x<0:
- wf=0
- if self.hp<=0:
- jiance[self.location][lo]-=1
- self.kill()
那么改了哪些地方呢:
1、__init__里面多加了一个pastlo,用来保存上一次位置。
2、update中对当前位置和上次位置的比较,从而即使改变jiance里面数量,保存准确性。
当前为止,为了方便测试,阳光一直没加,那么接下来就让我们加入阳光系统。
又要画图哩,来张阳光的图片。
既然一般来说这个阳光的初始值是50,那全局变量一开始赋值50先。
sunsum=50
'运行
还要把这个数字明确实时地显示在游戏界面中。
- tc=ts.render(str(sunsum),True,(0,0,0))
- screen.blit(tc,(35,60))
(这个tc的绘制要绘制在背景图之后,这样不会被背景图覆盖。)
接下来要考虑两个问题,一个是阳光在白天会从天上落下,还有就是植物会产生阳光,综合一下,可以弄一个精灵类。
全局变量先来一对。sunv表示掉阳光速度。
sunx,suny,sunv=0,0,70
'运行
先在while中,根据速率生成阳光,并随机位置。
sun_group=pygame.sprite.Group()
- if sunv<=0:
- sunx=randint(50,850)
- suny=randint(5,50)
- sun_group.add(sun())
- sunv=randint(100,135)
- sunv-=1
注意缩进喵!
一开始呢,我们就来一个简单的精灵。
- #sun
- class sun(pygame.sprite.Sprite):
- def __init__(self):
- super().__init__()
- self.image=pygame.image.load("P/base/sun.png")
- self.rect=self.image.get_rect(center=(sunx+50,suny+50))
- def update(self):
- self.rect.y+=3
- global chyn
- if mox>=self.rect.x and mox<=self.rect.x+100 and moy>=self.rect.y and moy<=self.rect.y+100 and event.type == pygame.MOUSEBUTTONDOWN:
- global sunsum
- sunsum+=25
- self.kill()
- if moy>=650:
- self.kill()
在这个游戏中呢,点阳光拾取另外算。
- if event.type == pygame.MOUSEBUTTONDOWN:
- sun_group.update()
还有种植植物的时候减去相应的阳光数量。植物前再加一个判断,要满足阳光数量。
- if event.type == pygame.MOUSEBUTTONDOWN:
- if chyn==0 and sunsum>=100:
- chyn=1
- pdx=(mox-100)//50+1
- if pdx==1: choicekp=pygame.image.load("P/kp/wandousheshou/shiwu.png")
- else: chyn=0
- elif chyn==1 and mox>=30 and moy>=90:
- pdx=(mox-30)//100
- pdy=(moy-90)//100
- zhiwu[pdy+1][pdx+1]=1
- wandousheshou_group.add(wandousheshou())
- sunsum-=100
- chyn=0
如果要弄那个,阳光数量不足,字体变红闪动的话,只要改变tc颜色即可,就不展示了。
这个僵尸再来两张图片表示体现僵尸在吃,跟豌豆和僵尸碰撞差不多,简简单单。
好吧,其实一点也不简单,琢磨了个把小时……
方便点的,我们只需要在植物的update中加点东西即可。
- def update(self):
- self.hp-=jiance[self.cuny+1][self.cunx+1]*1
- if self.hp<=0:
- zhiwu[self.cuny+1][self.cunx+1]=0
- self.kill()
'运行
每次update的时候都这么运行一下,有僵尸就扣,根据数量来看,因为这个是运行一遍就扣一次,所以说扣少一点。
同样的,当僵尸靠近的时候,僵尸要原地不动且做出吃的动作。
- def update(self):
- if zhiwu[self.location][self.pastlo] > 0:
- self.zishi+=1
- if self.zishi<5:
- self.image=pygame.image.load("P/jiangshi/putong/putongchi1.png")
- if self.zishi>=5:
- self.image=pygame.image.load("P/jiangshi/putong/putongchi2.png")
- if self.zishi>=10 :self.zishi=0
- else :
- if self.zishi==1:
- self.image=pygame.image.load("P/jiangshi/putong/putong.png")
- elif self.zishi==3:
- self.image=pygame.image.load("P/jiangshi/putong/putongd1.png")
- elif self.zishi==5:
- self.image=pygame.image.load("P/jiangshi/putong/putong.png")
- elif self.zishi==7:
- self.image=pygame.image.load("P/jiangshi/putong/putongd2.png")
- elif self.zishi>=9 : self.zishi=0
- self.zishi+=1
- self.rect.x-=0.6
'运行
累死了属于是,这个琢磨了好些天,大家在测试的时候根据实际情况微调即可,其他什么娱乐模式啊什么的就不写了。
喵:其他种类的植物和僵尸以此类推即可!
我把整个文件放“喵做梦技术讨论群”里了,需者加群自取。
这里不太方便展示,就只放一下代码部分吧。(毕竟这个图片,影响对代码某些数字的理解。)
- import pygame
- from random import randint
-
- pygame.init()
- scsize=(1000,600)
-
- def pzh(pr1,pr2,position1,position2):
- return pr1.overlap(pr2,(position2[0]-position1[0],position2[1]-position1[1]))
-
- #全局变量
- menu=0
- putongmark=1
- pdx,pdy=0,0
-
- #基础
- screen=pygame.display.set_mode(scsize)
- pygame.display.set_caption("乱来的PVZ")
- zf=pygame.time.Clock()
- ts=pygame.font.SysFont("simhei",20)
- tc=ts.render("",True,(0,0,0))
- time=0
- shch=0
- zhiwu=[([0]*10) for i in range(6)]
- cd=[([0]*10) for i in range(6)]
- jiance=[([0]*10) for i in range(6)]
- wandoux,wandouy=0,0
- sunx,suny,sunv=0,0,70
-
- #login
- loginback=pygame.image.load("P/login/loginback.png")
- login=pygame.image.load("P/login/loginno.png")
- loginmark=0
- #menu
- menuback=pygame.image.load("P/menu/back.png")
- mx=pygame.image.load("P/menu/maoxianno.png")
- mxmark=0
- #base
- gqcp=pygame.image.load("P/base/cp.png")
- choice=[1]*11 #1-豌豆射手
- choicemark=1
- choicelocation=1
- chyn=0 #0未选取卡片;1已选取卡片
- choicekp=pygame.image.load("P/kp/wandousheshou/kpshiwu.png")
- fail=pygame.image.load("P/base/fail.png")
- wf=1
- sunsum=50
- #kp
- class kp(pygame.sprite.Sprite):
- def __init__(self):
- super().__init__()
- if choice[choicemark]==1:
- self.image=pygame.image.load("P/kp/wandousheshou/kpshiwu.png")
- self.rect=self.image.get_rect(center=(75+choicelocation*50,35))
-
- #shiwu
- #wandousheshou
- class wandousheshou(pygame.sprite.Sprite):
- def __init__(self):
- super().__init__()
- self.image=pygame.image.load("P/kp/wandousheshou/shiwu.png")
- self.rect=self.image.get_rect(center=(30+30+pdx*100,90+35+pdy*100))
- self.cunx=pdx
- self.cuny=pdy
- self.hp=100
- def update(self):
- self.hp-=jiance[self.cuny+1][self.cunx+1]*1
- if self.hp<=0:
- zhiwu[self.cuny+1][self.cunx+1]=0
- self.kill()
-
- #wandou
- class wandou(pygame.sprite.Sprite):
- def __init__(self):
- super().__init__()
- self.image=pygame.image.load("P/kp/wandousheshou/wandou.png")
- self.rect=self.image.get_rect(center=(wandoux*100-20,wandouy*100+10))
- def update(self):
- self.rect.x+=4
-
- #jiangshi
- #putong
- class putong(pygame.sprite.Sprite):
- def __init__(self):
- super().__init__()
- self.image=pygame.image.load("P/jiangshi/putong/putong.png")
- self.rect=self.image.get_rect(center=(950,shch*100+30))
- self.zishi=1
- self.location=shch
- self.hp=100
- self.pastlo=9
- def update(self):
- if zhiwu[self.location][self.pastlo] > 0:
- self.zishi+=1
- if self.zishi<5:
- self.image=pygame.image.load("P/jiangshi/putong/putongchi1.png")
- if self.zishi>=5:
- self.image=pygame.image.load("P/jiangshi/putong/putongchi2.png")
- if self.zishi>=10 :self.zishi=0
- else :
- if self.zishi==1:
- self.image=pygame.image.load("P/jiangshi/putong/putong.png")
- elif self.zishi==3:
- self.image=pygame.image.load("P/jiangshi/putong/putongd1.png")
- elif self.zishi==5:
- self.image=pygame.image.load("P/jiangshi/putong/putong.png")
- elif self.zishi==7:
- self.image=pygame.image.load("P/jiangshi/putong/putongd2.png")
- elif self.zishi>=9 : self.zishi=0
- self.zishi+=1
- self.rect.x-=0.6
- global wf
- global jiance
- lo=(self.rect.x-30)//100+1
- if self.pastlo-lo>0:
- jiance[self.location][self.pastlo]-=1
- jiance[self.location][lo]+=1
- self.pastlo=lo
- if self.rect.x<0:
- wf=0
- if self.hp<=0:
- jiance[self.location][lo]-=1
- self.kill()
-
- #sun
- class sun(pygame.sprite.Sprite):
- def __init__(self):
- super().__init__()
- self.image=pygame.image.load("P/base/sun.png")
- self.rect=self.image.get_rect(center=(sunx+50,suny+50))
- def update(self):
- self.rect.y+=3
- global chyn
- if mox>=self.rect.x and mox<=self.rect.x+100 and moy>=self.rect.y and moy<=self.rect.y+100 and event.type == pygame.MOUSEBUTTONDOWN:
- global sunsum
- sunsum+=25
- self.kill()
- if moy>=650:
- self.kill()
-
- kp_group=pygame.sprite.Group()
- wandousheshou_group=pygame.sprite.Group()
- wandou_group=pygame.sprite.Group()
- putongjiangshi_group=pygame.sprite.Group()
- sun_group=pygame.sprite.Group()
-
- while True:
- for event in pygame.event.get():
- if event.type==pygame.QUIT:
- pygame.quit()
- mox, moy = pygame.mouse.get_pos() #实时读取鼠标x,y
- if menu==0:#进入界面
- screen.blit(loginback,(0,0))
- screen.blit(login,(400,400))
- if loginmark==0:
- login=pygame.image.load("P/login/loginno.png")
- else : login=pygame.image.load("P/login/loginyes.png")
- loginmark=0
- if mox>=400 and mox<=600:
- if moy>=400 and moy<=450:
- loginmark=1
- if loginmark==1 and event.type == pygame.MOUSEBUTTONDOWN:
- menu=1
- elif menu==1:#菜单
- screen.blit(menuback,(0,0))
- screen.blit(mx,(700,200))
- if mxmark==0:
- mx=pygame.image.load("P/menu/maoxianno.png")
- else : mx=pygame.image.load("P/menu/maoxianyes.png")
- mxmark=0
- if mox>=700 and mox<=880:
- if moy>=200 and moy<=250:
- mxmark=1
- if mxmark==1 and event.type == pygame.MOUSEBUTTONDOWN:
- menu=2
- elif menu==2:#冒险模式
- tc=ts.render(str(sunsum),True,(0,0,0))
- time+=1
- if time>=100:
- time=0
- shch=randint(1,5)
- jiance[shch][9]+=1
- putongjiangshi_group.add(putong())
- screen.blit(gqcp,(0,0))
- for i in range(0,10):
- kp_group.add(kp())
- choicemark=i+1
- kp_group.draw(screen)
- wandousheshou_group.draw(screen)
- putongjiangshi_group.draw(screen)
- wandou_group.draw(screen)
- sun_group.draw(screen)
- screen.blit(tc,(35,60))
- putongjiangshi_group.update()
- wandou_group.update()
- wandousheshou_group.update()
- sun_group.update()
- for i in range(1,6):
- for j in range(1,10):
- if zhiwu[i][j]==1 and cd[i][j]<=0:
- youmeiyou=0
- for o in range(j,10):
- if jiance[i][o]>0:
- youmeiyou=1
- break
- if youmeiyou==1:
- wandoux=j
- wandouy=i
- wandou_group.add(wandou())
- cd[i][j]=38
- col = pygame.sprite.groupcollide(wandou_group, putongjiangshi_group, True, False)
- for sprite, list in col.items():
- for s in list:
- s.hp -= 10
- if event.type == pygame.MOUSEBUTTONDOWN:
- if chyn==0 and sunsum>=100:
- chyn=1
- pdx=(mox-100)//50+1
- if pdx==1: choicekp=pygame.image.load("P/kp/wandousheshou/shiwu.png")
- else: chyn=0
- elif chyn==1 and mox>=30 and moy>=90:
- pdx=(mox-30)//100
- pdy=(moy-90)//100
- zhiwu[pdy+1][pdx+1]=1
- wandousheshou_group.add(wandousheshou())
- sunsum-=100
- chyn=0
- if event.type == pygame.MOUSEBUTTONDOWN:
- sun_group.update()
- if chyn==1:
- screen.blit(choicekp,(mox,moy))
- if wf==0:
- screen.blit(fail,(200,100))
- if sunv<=0:
- sunx=randint(50,850)
- suny=randint(5,50)
- sun_group.add(sun())
- sunv=randint(100,135)
- sunv-=1
- for i in range(1,6):
- for j in range(1,10):
- cd[i][j]-=1
- zf.tick(25)
- pygame.display.flip()
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。