[Python] 开发植物大战僵尸游戏
用python开发植物大战僵尸早期的植物大战僵尸是由vc开发的,作者的想法是非常地有特色,所以今天我们来探讨下植物大战僵尸游戏的进入场景怎么开发。我们首需要用到如下几个文件程序文件功能game.py在游戏中就运行的文件initgame.py游戏主菜单选择关卡等loading.py游戏载入等待缓存surface.py游戏入口点击这里首先介绍s......
·
用python开发植物大战僵尸
早期的植物大战僵尸是由vc开发的,作者的想法是非常地有特色,所以今天我们来探讨下植物大战僵尸游戏的进入场景怎么开发。
我们首需要用到如下几个文件
程序文件 | 功能 |
---|---|
game.py | 在游戏中就运行的文件 |
initgame.py | 游戏主菜单选择关卡等 |
loading.py | 游戏载入等待缓存 |
surface.py | 游戏入口点击这里 |
首先介绍surface.py:
# -*- coding:utf-8 -*-
import pygame
from sys import exit
from pygame.locals import *
from random import randint as r_i
pygame.init()
import initgame
import game
import loading
def help_main(screen):
help_bg = pygame.image.load('images/Help.png').convert_alpha()
help_width,help_height = help_bg.get_width(),help_bg.get_height()
help_pos = 450-help_width//2,300-help_height//2
help_run = True
pygame.display.flip()
while help_run:
for event in pygame.event.get():
if event.type == QUIT:
exit()
if event.type == MOUSEBUTTONDOWN:
mosx,mosy = event.pos
if help_pos[0]<mosx<help_pos[0]+help_width and help_pos[1]<mosy<help_pos[1]+help_height:
help_run = False
screen.blit(help_bg,(help_pos))
pygame.display.update()
def calbackmain(screen):
pygame.mixer.music.pause()
initgame.inits(screen)
pygame.mixer.music.play(-1,0,)
pygame.mixer.music.set_volume(0.5)
def StartAdventur_(screen):
beginrun = True
beginbg = pygame.image.load('images/OptionsMenuback32.png').convert_alpha()
optionbtn = pygame.image.load('images/OptionsBackB32.png').convert_alpha()
optionbtn2 = pygame.image.load('images/OptionsBackB321.png').convert_alpha()
fo = pygame.font.Font('font/msyh.ttf',35)
myfont = fo.render("返 回", True, (255, 255, 100))
fo2 = pygame.font.Font('font/msyh.ttf',22)
myfont2 = fo2.render("第一大关 >>", True, (255, 255, 150))
fo3 = pygame.font.Font('font/msyh.ttf',18)
game_list=[ '第一关','第二关','第三关','第四关','第五关',
'第六关','第七关','第八关','第九关','第十关']
pygame.display.flip()
returnbtn = False
Timer_return = 0 #返回的定时器
while beginrun:
for event in pygame.event.get():
if event.type == QUIT:
exit()
if event.type == MOUSEBUTTONDOWN:
mdx,mdy = event.pos
# 270 440 ,360 100
returnbtn = False
if 270<mdx<630 and 440<mdy<540:
returnbtn = True
#--------------------------------------------
#关卡系列 循环检测点击了关卡---------------
# 360+125*list_i , 230+35*list_j---- 54 , 25
#--------------------------------------------
list_index = 0
for list_j in range(5):
for list_i in range(2):
if 360+125*list_i<mdx<414+125*list_i and 230+35*list_j<mdy<255+35*list_j:
print('只能点击第一关')
if list_index == 0:
game.game_one(screen); #进入第一关
beginrun = False #回到游戏退出启动器
list_index+=1
screen.blit(beginbg,(450-beginbg.get_width()/2,300-beginbg.get_height()/2))#背景
screen.blit(myfont2,(390,180))#第一大关
#关卡系列
list_index = 0
for list_j in range(5):
for list_i in range(2):
myfont3 = fo3.render("%s"%(game_list[list_index]), True, (255, 255, 230))#(54,25)
screen.blit(myfont3,(360+125*list_i,230+35*list_j))
list_index+=1
#返回按钮壁纸
screen.blit(optionbtn,(270,440))
screen.blit(myfont,(380,460))#返回字体
if returnbtn:
screen.blit(optionbtn2,(270,441))
screen.blit(myfont,(380,461))
Timer_return+=1
if Timer_return>= 50:
beginrun = False
pygame.display.update()
def eventinit(surf,screen,mosx,mosy):
#-------------------------------------
#--------------主菜单系列-------------
#-------------------------------------
#470,80 331,146开始冒险
if 470<mosx<801 and 80<mosy<203:#h-23
pygame.time.delay(50)
StartAdventur_(screen)
#470,205 313 131玩小游戏
if 470<mosx<783 and 205<mosy<313:#h-23
pygame.time.delay(50)
#470,305 286 122解谜模式
if 470<mosx<756 and 305<mosy<427:#h-23
pygame.time.delay(50)
#-------------------------------------
#--------------小菜单系列-------------
#-------------------------------------
#810,510,65,35退出
if mosx>810 and mosx<875 and mosy>510 and mosy<545:
#pygame.draw.rect(screen, (255,255,0), (810,510,65,35), 1)#退出
pygame.time.delay(50)
calbackmain(screen) #调回主界面
#725,520,65,35帮助
if mosx>725 and mosx<790 and mosy>520 and mosy<555:
pygame.draw.rect(screen, (255,255,0), (725,520,65,35), 1)#帮助
pygame.time.delay(50)
help_main(screen) #调用帮助函数
#647,485,70,40选项
if mosx>647 and mosx<717 and mosy>485 and mosy<525:
#pygame.draw.rect(screen, (255,255,0), (647,485,70,40), 1)#选项
pygame.time.delay(50)
def mouseover(screen,mox,moy):
#470,80 331,146开始冒险
if 470<mox<801 and 80<moy<203:#h-23
return 1
#470,205 313 131玩小游戏
if 470<mox<783 and 205<moy<313:#h-23
return 2
#470,305 286 122解谜模式
if 470<mox<756 and 305<moy<427:#h-23
return 3
return 0
def main():
pygame.mixer.music.load('music/Faster.mp3')
pygame.mixer.music.play(-1,0,)
pygame.mixer.music.set_volume(0.5)
screen = pygame.display.set_mode([900, 600], 0, 32)
caption = pygame.display.set_caption('植物大战僵尸')
screen.fill([255,255,255])
#-------------------
#进入最开始界面-----
initgame.inits(screen)
#-------------------
surf = pygame.image.load('images/Surface.png').convert_alpha()
StartAdventur = pygame.image.load('images/StartAdventur.png').convert_alpha()
StartAdventur2 = pygame.image.load('images/StartAdventur2.png').convert_alpha()
Survival = pygame.image.load('images/Survival.png').convert_alpha()
Survival2 = pygame.image.load('images/Survival2.png').convert_alpha()
Challenges = pygame.image.load('images/Challenges.png').convert_alpha()
Challenges2 = pygame.image.load('images/Challenges2.png').convert_alpha()
pygame.display.flip()
#定义区
capmouseover = 0
#game.game_one(screen)#测试游戏界面 第一关卡
#-------------------------------------------
#s=pygame.mixer.Sound('music/button.wav')
#s.set_volume(0.25)
while True:
for event in pygame.event.get():
if event.type == QUIT:
exit()
if event.type == KEYDOWN:
if event.key == K_ESCAPE:
calbackmain(screen) #调回主界面
if event.key == K_a:
flag = 1
if event.type == MOUSEBUTTONDOWN:
mdx,mdy=event.pos
eventinit(surf,screen,mdx,mdy)#主界面的菜单按钮
if event.type == MOUSEMOTION:
mox,moy = event.pos
capmouseover = 0
capmouseover = mouseover(screen,mox,moy)#鼠标是否经过cap
screen.blit(surf,(0,0))#绘制平面
#开始冒险
screen.blit(StartAdventur,(470,80))
if capmouseover==1:
screen.blit(StartAdventur2,(470,80))
#玩小游戏
screen.blit(Survival,(470,205))
if capmouseover == 2:
screen.blit(Survival2,(470,205))
#解谜模式
screen.blit(Challenges,(470,305))
if capmouseover == 3:
screen.blit(Challenges2,(470,305))
pygame.display.update()
if __name__ == '__main__':
main()
主菜单稍微有点小长,不过代码中标识了注释也不难理解,在文件中我加入了很多图片素材都是原班植物大战僵尸的素材,后面还加了音乐提升游戏的趣味性!
编译后如下:
接着开发initgame.py文件:
# -*- coding:utf-8 -*-
import pygame
from sys import exit
from pygame.locals import *
pygame.init()
def eventinit(mosx,mosy,loadbar_width,loadbar_height):
if mosx>80 and mosx<loadbar_width+80:
if mosy>450 and mosy<loadbar_height+450:
return True
return False
def inits(screen):
bg = pygame.image.load('images/Logo.jpg').convert_alpha()
logoword = pygame.image.load('images/LogoWord.jpg').convert_alpha()
loadbar = pygame.image.load('images/interface/LoadBar.png').convert_alpha()
loadbar_width,loadbar_height = loadbar.get_width(),loadbar.get_height()
loadbar2 = pygame.image.load('images/interface/LoadBar11.png').convert_alpha()
GameRun = 1
Timer = 0
flagblit = False
flagclick = False
pygame.display.flip()
while GameRun:
for event in pygame.event.get():
if event.type == QUIT:
exit()
if event.type == KEYDOWN:
if event.key == K_RETURN:
GameRun = 0 #进入游戏
pygame.time.delay(250)
if event.type == MOUSEMOTION:
mosx,mosy=event.pos
flagblit=eventinit(mosx,mosy,loadbar_width,loadbar_height)
if event.type == MOUSEBUTTONDOWN:
mosx,mosy=event.pos
flagclick=eventinit(mosx,mosy,loadbar_width,loadbar_height)
screen.blit(bg,(0,0)) #logo壁纸
screen.blit(logoword,(320,16))#中文壁纸
#开始按钮系列
if not flagblit:
screen.blit(loadbar,(80,450)) #开始按钮图片1
elif flagblit:
screen.blit(loadbar2,(80,455))#开始按钮图片2
if flagclick: #进入游戏
GameRun = 0
pygame.time.delay(250)
#Timer+=1
pygame.time.delay(10)
pygame.display.update()
然后运行程序得到的结果为:
哈哈,是不是很精彩了,没错这就是程序和图片的魅力!
接着剖析loading.py:
# -*- coding:utf-8 -*-
import pygame,os
from sys import exit
from pygame.locals import *
pygame.init()
def loading(screen,xpos_add_values):
pygame.display.flip()
gamerun = True
FlagMeterEmpty = pygame.image.load('images/interface/FlagMeterEmpty.png').convert_alpha()
FlagMeterFull = pygame.image.load('images/interface/FlagMeterFull.png').convert_alpha()
FlagMeterParts1 = pygame.image.load('images/interface/FlagMeterParts1.png').convert_alpha()
xpos,ypos=450-FlagMeterEmpty.get_width()//2,300-FlagMeterEmpty.get_height()//2
xpos_width = 0
Timer = 0
Timer_loading_font = 0
fo = pygame.font.Font('font/msyh.ttf',25)
fontlist = [
'. ','.. ','...'
]
fl_i = 0
while gamerun:
for event in pygame.event.get():
if event.type == QUIT:
exit()
screen.fill([0,0,0])
#----------
#进度条系列
#----------
#绘制空进度条载入中。。。
screen.blit(FlagMeterEmpty,(xpos,ypos))
pygame.draw.rect(screen, (255,255,100), (xpos+7,ypos+7,xpos_width,7))
screen.blit(FlagMeterParts1,(xpos+7+xpos_width,ypos))
myfont = fo.render("载入中%s"%(fontlist[fl_i]), True, (0, 200, 0))
screen.blit(myfont,(450-myfont.get_width()//2,ypos+100))#载入字体
Timer_loading_font+=1
if Timer_loading_font == 5:
Timer_loading_font=0
fl_i += 1
if fl_i==3:
fl_i = 0
if xpos_width<145:
xpos_width += 5
else:
#绘制满进度
screen.fill([0,0,0])
screen.blit(FlagMeterFull,(xpos,ypos))
#启动定时器
Timer += xpos_add_values
if Timer >= 30:
gamerun = False
pygame.time.delay(xpos_add_values)
pygame.display.update()
上面的loading.py是载入游戏等待时显示的一个动画,可以看做是一个过载动画。
最后插入游戏中设计的场景代码
game.py
# -*- coding:utf-8 -*-
import pygame,os
from sys import exit
from random import randint as r_i
from pygame.locals import *
pygame.init()
import initgame
import loading
def game_one(screen):
pygame.mixer.music.load('music/Look up at the.mp3')
pygame.mixer.music.play(-1,0,)
#--------------
#载入等待区系列
loading.loading(screen,r_i(20, 30)) #第二个是延迟毫秒
#--------------
gamerun = True
background = pygame.image.load('images/interface/background1unsodded.jpg').convert_alpha()
button = pygame.image.load('images/interface/Button.png').convert_alpha()
but_width,but_height = button.get_width(),button.get_height()
fo = pygame.font.Font('font/msyh.ttf',21)
myfont = fo.render("暂 停", True, (0, 230, 0))
myfont2 = fo.render("菜 单", True, (0, 230, 0))
plantshadow = pygame.image.load('images/plantshadow32.png').convert_alpha()
zombies_dir = 'images/Zombies/Zombie/zombies/'
zombies_files = os.listdir(zombies_dir) #僵尸动画列表
zom_len = len(zombies_files) #僵尸帧动画数组数量
zom_Timer = 0 #僵尸动画定时器
zom_index = 0#僵尸帧动画当前位置
Ifshowzom_action = True #是否显示僵尸动画 是否显示
zom_width_add_flag = False#僵尸回拖是否为真
zom_width_add = 0 #僵尸回拖距离
#壁纸拖动变量定义
width_add = 0
maxadd_width = -495
bg_Timer = 1 #壁纸回拖定时器
bg_timerflag = False
beginer = False
#---------------------------------------------
#定义僵尸个数列表 -随机 区域--585,130,200,330
# 坐标位置随机区域585-785 130-460------------
#---------------------------------------------
zom_n = [
[r_i(585,835), r_i(130, 460)] ,
[r_i(585,835), r_i(130, 460)] ,
[r_i(585,835), r_i(130, 460)] ,
[r_i(585,835), r_i(130, 460)] ,
[r_i(585,835), r_i(130, 460)]
]
#僵尸排列问题
zom_n_temp = []
for zoo in zom_n:
zom_n_temp.append(zoo[1])
zom_n_temp=sorted(zom_n_temp)
zom_index_index = 0
for zoo in zom_n:
zom_n[zom_index_index][1] = zom_n_temp[zom_index_index]
zom_index_index += 1
#植物卡片1号豌豆
PeashooterG = pygame.image.load('images/Card/Plants/PeashooterG.png').convert_alpha()
Peashooter = pygame.image.load('images/Card/Plants/Peashooter.png').convert_alpha()
SunBack = pygame.image.load('images/interface/SunBack.png').convert_alpha()
#草皮----
sod1row = pygame.image.load('images/interface/sod1row.png').convert_alpha()
SodRoll = pygame.image.load('images/interface/SodRoll.png').convert_alpha()
SodRoll = pygame.transform.scale(SodRoll,( int(SodRoll.get_width()*0.7) , int(SodRoll.get_height()*0.9) ))
SodRollCap = pygame.image.load('images/interface/SodRollCap.png').convert_alpha()
SodRollCap = pygame.transform.scale(SodRollCap, (int(SodRollCap.get_width()*0.7), int(SodRollCap.get_height()*0.7)))
#草皮宽度变化变量
sod1row_change_value = 0
sod_vas = 25
grass_card_flag = False
#font
fo = pygame.font.Font('font/msyh.ttf',18)
myfon = fo.render('100', True, (0,0,0))
myfon2 = fo.render('17', True, (0,0,0))
pygame.display.flip()
while gamerun:
for event in pygame.event.get():
if event.type == QUIT:
exit()
#区域
screen.fill([0,0,0])
screen.blit(background,(width_add,0))
if width_add>=maxadd_width and beginer == False:
width_add-=5
else:
beginer = True
if beginer:
#壁纸拖回动画定时
if bg_Timer:bg_Timer+=1
if bg_Timer == 200:#到达时间
bg_Timer = 0 #定时器还原不增加了
bg_timerflag = True
zom_width_add_flag = True #僵尸回拖为真
#Ifshowzom_action = False #是否显示僵尸动画
if bg_timerflag:#标志成立 则拖动壁纸
width_add+=5
if width_add > -115:
width_add=-115
bg_timerflag = False#到达指定位置不拖动壁纸了
#暂停开始系列
screen.blit(button,(900-but_width*2,0))
screen.blit(myfont,(900-but_width*2+27,5)) #暂停 开始
#菜单系列
screen.blit(button,(900-but_width*1,0))
screen.blit(myfont2,(900-but_width*1+27,5))#菜单
#开始游戏僵尸动画系列
if width_add>=-115:
if grass_card_flag == False:
#植物卡片绘制 一号豌豆
screen.blit(PeashooterG,(0,0))
else:
screen.blit(Peashooter,(0,0))
screen.blit(SunBack,(120,0))
screen.blit(myfon,(60,37))
#草皮滚动动画
#草皮元素透明慢慢增长
for i in range(sod1row.get_width()):
for j in range(sod1row.get_height()):
temp = sod1row.get_at((i,j))
if i<sod1row_change_value:
if temp[0] or temp[1] or temp[2]:
temp[3] = 255
elif i >=sod1row_change_value:
temp[3] = 0
sod1row.set_at((i,j),temp)
#绘制草皮动画
screen.blit(sod1row,(132,300-sod1row.get_height()/2)) #草皮
if sod1row_change_value<sod1row.get_width():
sod1row_change_value+=sod_vas
screen.blit(SodRoll,(75+sod1row_change_value,270-SodRoll.get_height()/2))#土
screen.blit(SodRollCap,(71+sod1row_change_value,335-SodRollCap.get_height()/2))#卷土
else:
grass_card_flag = True
#僵尸动画系列
if Ifshowzom_action:
zombie_ = pygame.image.load('images/Zombies/Zombie/zombies/%s'%(zombies_files[zom_index]) ).convert_alpha()
#----------------------------------------------------------------------------------
#僵尸产生的区域绘制如下函数--------------------------------------------------------
#pygame.draw.rect(screen, (255,255,255), (585,130,250,330), 1)#僵尸产生位置区域绘制
#----------------------------------------------------------------------------------
#遍历所有僵尸
if zom_width_add_flag: #当壁纸回拖时的变量
zom_width_add+=5
if zom_width_add==500:#当回拖到0点是僵尸动画的位置不移动了
zom_width_add_flag=False#僵尸不会拖了
Ifshowzom_action = False #僵尸不产生动画了
#绘制所有僵尸动画场景
for zom_i in range(len(zom_n)):
screen.blit(zombie_,(zom_n[zom_i][0]+zom_width_add,zom_n[zom_i][1])) #绘制僵尸
screen.blit(plantshadow,(zom_n[zom_i][0]+5+zom_width_add,zom_n[zom_i][1]+102))#w+5,h+102 绘制影子
#僵尸定时器
zom_Timer+=1#定时器加1
if zom_Timer==9: #时间为90毫秒
zom_Timer = 0#
#到达了定时时间,僵尸图片帧下标更改
zom_index+=1
if zom_index==zom_len: #帧下标到达最大值归零
zom_index=0
#区域
pygame.time.delay(10)
pygame.display.update()
敲击回车,运行游戏结果如下图:
我们看到僵尸的位置是随机的,这里我们用到了随机算法,让僵尸固定在一个区域随机生成。
结果是不是很有趣了,真正的完成了一个植物大战僵尸的场景。但是要完全开发一个植物大战僵尸还需要一定的时间呢,作者抽空完成!
更多推荐
已为社区贡献1条内容
所有评论(0)