2015/11/9用Python写游戏,pygame入门:按钮和游戏结束

王朝学院·作者佚名  2016-08-27
窄屏简体版  字體: 小  |  中  |  大  |  超大  

昨天没有更新内容,今天相对多写一些。

因为我们已经基本完成游戏框架,但是游戏结束后,并不知道怎样比较好开始。我本来本着懒的原则,想结束后显示一个黑屏,然后你重新点一下鼠标就重新开始。但是那样实在太不像个热爱生活的程序员了,所以我决定用更合适的方法解决这个问题。

为此,我决定实现一个相对比较过得去的按钮。

为了实现按钮,我先创建一个测试程序体。然后在上面先实现一个按钮类的功能。

具体的测试程序,我就不详说了,反正就是你去创建一个这样的小窗口:

然后在上面完成一个按钮的类。

我设想的按钮应该是这样的,当我把鼠标移动上去的时候,它会将白底显示成灰底,移开后,又显示回白底。这其实就是两张图片的切换,所以,第一步要做的是,制作两张图,一张是白底的按钮,一张是灰底的按钮:

好了,接下来开始码这个类的功能了,首先是它的数据对象,必须得有两张图。

然后它还得有个安置它的位置坐标。

所以,它的初始化应该是这样定义的:

def__init__(self, upimage, downimage,position):

self.imageUp=pygame.image.load(upimage).convert_alpha()

self.imageDown=pygame.image.load(downimage).convert_alpha()

self.position= position

然后,它应该有个方法来判断,鼠标是不是在这个按钮的上面:

defisOver(self):

point_x,point_y=pygame.mouse.get_pos()

x, y=self. position

w, h=self.imageUp.get_size()

in_x= x - w/2 < point_x < x + w/2in_y= y - h/2 < point_y < y + h/2returnin_xandin_y

还有一个用于判断显示哪张图的方法:

defrender(self):

w, h=self.imageUp.get_size()

x, y=self.positionifself.isOver():

screen.blit(self.imageDown, (x-w/2,y-h/2))else:

screen.blit(self.imageUp, (x-w/2, y-h/2))

好了,至此我们就做好了一个类。

将它跟我们的测试程序放在一起并且执行它:

#-*- coding: utf-8 -*-importpygamefromsysimportexit

pygame.init()

screen= pygame.display.set_mode((300,200),0,32)

upImageFilename='game_again.png'downImageFilename='game_again_down.png'classButton(object):def__init__(self, upimage, downimage,position):

self.imageUp=pygame.image.load(upimage).convert_alpha()

self.imageDown=pygame.image.load(downimage).convert_alpha()

self.position=positiondefisOver(self):

point_x,point_y=pygame.mouse.get_pos()

x, y=self. position

w, h=self.imageUp.get_size()

in_x= x - w/2 < point_x < x + w/2in_y= y - h/2 < point_y < y + h/2returnin_xandin_ydefrender(self):

w, h=self.imageUp.get_size()

x, y=self.positionifself.isOver():

screen.blit(self.imageDown, (x-w/2,y-h/2))else:

screen.blit(self.imageUp, (x-w/2, y-h/2))

button= Button(upImageFilename,downImageFilename, (150,100))whileTrue:foreventinpygame.event.get():ifevent.type ==pygame.QUIT:

pygame.quit()

exit()

screen.fill((200, 200, 200))

button.render()

pygame.display.update()

就能得到一个显示按钮:

可以实现了我们的功能。

但是,等一下,我们没有写按钮的作用啊,也就是按下去就要执行的作用。

好吧,这件事反而是简单的。我们只需要判断event的时候调用isOver()方法就好了。

接下来我们来完成游戏框架了。

我想要一个开始界面,有开始按钮,游戏过程中,我想让它计分,游戏结束后可以显示最高分和我这次的分数,并且有个结束游戏和重新开始的按钮。

整个功能其实我都已经实现过了。

一步步地构造逻辑我就不多讲了,直接放代码。大家可以自己完成它。

这次代码里,我把自己的飞机也用了类实现,便于以后的拓展,有了计分模块,整个游戏用全屏模式打开。

当然整个代码还是有些乱的,不过由于大多数类和逻辑在之前已经讲过,相信还是易懂的

#-*- coding:utf-8-*-importpygamefromsysimportexitfromrandomimportrandintfrommathimportsqrt

pygame.init()

SCREEN_SIZE= (480,766)

screen= pygame.display.set_mode(SCREEN_SIZE,pygame.FULLSCREEN,32)

pygame.display.set_caption("Plane Fight!")

count_b= 7count_e= 50fps= 100ufo= pygame.image.load('ufo2.png').convert_alpha()

background= pygame.image.load('background.png').convert_alpha()

gameover_image= pygame.image.load('gameover.png').convert_alpha()

plane_image= pygame.image.load('hero.png').convert_alpha()

bullet_image= pygame.image.load('bullet.png').convert_alpha()

enemy_image= pygame.image.load('enemy2.png').convert_alpha()

logo= pygame.image.load('shoot_copyright.png').convert_alpha()

bomb_num= pygame.image.load('bomb_num.png').convert_alpha()

bomb_image= pygame.image.load('bomb.png').convert_alpha()

loading=[]

loading.append(pygame.image.load('game_loading1.png').convert_alpha())

loading.append(pygame.image.load('game_loading2.png').convert_alpha())

loading.append(pygame.image.load('game_loading3.png').convert_alpha())

enemydown=[]

enemydown.append(pygame.image.load('enemy2_down1.png').convert_alpha())

enemydown.append(pygame.image.load('enemy2_down2.png').convert_alpha())

enemydown.append(pygame.image.load('enemy2_down3.png').convert_alpha())

enemydown.append(pygame.image.load('enemy2_down4.png').convert_alpha())

boom=[]

boom.append(pygame.image.load('boom0.png').convert_alpha())

boom.append(pygame.image.load('boom1.png').convert_alpha())

boom.append(pygame.image.load('boom1.png').convert_alpha())

boom.append(pygame.image.load('boom2.png').convert_alpha())

boom.append(pygame.image.load('boom2.png').convert_alpha())

backmusic=pygame.mixer.Sound('game_music.ogg')

buttonmusic= pygame.mixer.Sound('button.ogg')

bulletmusic= pygame.mixer.Sound('bullet.wav')

enemydownmusic= pygame.mixer.Sound('enemy1_down.wav')

gameovermusic= pygame.mixer.Sound('game_over.ogg')

getbombmusic= pygame.mixer.Sound('get_bomb.wav')

usebombmusic= pygame.mixer.Sound('use_bomb.wav')

buttonmusic.set_volume(0.2)

bulletmusic.set_volume(0.04)

gameovermusic.set_volume(0.5)

enemydownmusic.set_volume(0.1)

channel= backmusic.play(-1)

channel.set_volume(0.1,0.1)

channel.pause()

font1= pygame.font.Font(None,64)

font2= pygame.font.Font(None,128)

clock=pygame.time.Clock()defshowLoading(count,pos):

n= count/50x, y=pos

w, h= loading[2].get_size()

x-= w/2y-= h/2ifn <3:

screen.blit(loading[n],(x,y))classButton(object):def__init__(self, upimage, downimage, position):

self.image_up=pygame.image.load(upimage).convert_alpha()

self.image_down=pygame.image.load(downimage).convert_alpha()

self.position=position

self.button_out=Truedefis_over(self):

point_x, point_y=pygame.mouse.get_pos()

x, y=self.position

w, h=self.image_up.get_size()

x-= w/2y-= h/2in_x= x < point_x < x +w

in_y= y < point_y < y +hreturnin_xandin_ydefrender(self, surface):

x, y=self.position

w, h=self.image_up.get_size()

x-= w/2y-= h/2ifself.is_over():

surface.blit(self.image_down, (x, y))ifself.button_out ==True:

buttonmusic.play()

self.button_out=Falseelse:

surface.blit(self.image_up, (x, y))

self.button_out=TrueclassHero(object):defrestart(self):

self.x= 200self.y= 600def__init__(self):

self.restart()

self.image=plane_imagedefmove(self, time_passed_seconds):

mouseX, mouseY=pygame.mouse.get_pos()

self.x= mouseX - self.image.get_width()/2self.y= mouseY - self.image.get_height()/2classBullet(object):def__init__(self):

self.x=0

self.y= -1self.image=bullet_image

self.active=Falsedefmove(self,time_passed_seconds):ifself.active :

self.y-= 700 *time_passed_secondsifself.y <0:

self.active=Falsedefrestart(self,flag):

mouseX, mouseY=pygame.mouse.get_pos()ifflag == 1:

self.x= mouseX - self.image.get_width()/2self.y= mouseY - self.image.get_height()/2ifflag == 2:

self.x= mouseX - self.image.get_width()/2 + 33self.y= mouseY - self.image.get_height()/2self.active=TrueclassEnemy(object):defrestart(self, score):

self.x= randint(-30,440)

self.y= randint(-200,-100)

self.speed= randint(min(200+score/80,400),min(400+score/40,700))

self.active=True

self.count= -1def__init__(self,):

self.restart(0)

self.image=enemy_image

self.active=Falsedefmove(self,time_passed_seconds):ifself.y < SCREEN_SIZE[1]:

self.y+= self.speed *time_passed_secondselse:

self.active=FalsedefshowDown(self):

n= self.count/10screen.blit(enemydown[n],(self.x,self.y))

self.count+= 1ifself.count >= 39:

self.count= -1classBomb(object):def__init__(self):

self.image=bomb_image

(self.x , self.y)= (-100,-100)

self.boom_x, self.boom_y=0,0

self.speed= 800self.active=False

self.is_boom=False

self.boomcount=0defshoot(self):

self.x, self.y=pygame.mouse.get_pos()

self.x-= self.image.get_width()/2self.y-= self.image.get_height()/2self.active=Truedefmove(self,time_passed_seconds):ifself.y > 250:

self.y-= self.speed*time_passed_secondselse:

self.active=False

self.is_boom=True

self.boom_x, self.boom_y=self.x , self.y

usebombmusic.play()defcheckBoom(self,enemy):ifenemy.x - 60 < self.x < enemy.x + enemy.image.get_width()+60\andenemy.y < self.y < enemy.y +enemy.image.get_height():

self.active=False

self.is_boom=True

self.boom_x, self.boom_y=self.x , self.y

usebombmusic.play()defcheckHit(self,enemy):

a= float(self.x - (enemy.x + enemy.image.get_width()/2))

b= float(self.y - (enemy.y + enemy.image.get_height()/2))

l= sqrt(a**2 + b**2)ifl < 250:

enemy.active=False

enemy.count= 1returnTrueelse:returnFalsedefboom(self):

n= self.boomcount/10screen.blit(boom[n],(self.boom_x-boom[n].get_width()/2, self.boom_y-boom[n].get_height()/2))

self.boomcount+= 1ifself.boomcount >= 49:

self.is_boom=False

self.boomcount=0classUfo(object):defrestart(self):

self.x= randint(-30,440)

self.y= -107self.speed= 250def__init__(self):

self.image=ufo

self.restart()

self.active=Falsedefmove(self,time_passed_seconds):ifself.y < SCREEN_SIZE[1]:

self.y+= self.speed *time_passed_secondselse:

self.active=FalsedefcheckGet(self,plane):ifplane.x - 60 < self.x < plane.x + plane.image.get_width()+60\andplane.y -80 < self.y < plane.y +plane.image.get_height():

self.active=False

getbombmusic.play()returnTrueelse:returnFalsedefcheckHit(enemy,bullet):ifenemy.x < bullet.x < enemy.x +enemy.image.get_width() \andenemy.y < bullet.y < enemy.y +enemy.image.get_height():

enemy.active=False

bullet.active=False

enemydownmusic.play()

enemy.count+=1returnTrueelse:returnFalsedefcheckCrash(enemy,plane):ifplane.x + 0.3*plane.image.get_width()< enemy.x + enemy.image.get_width()and\

enemy.x< plane.x + 0.7*plane.image.get_width()and\

plane.y+ 0.3*plane.image.get_height() < enemy.y + enemy.image.get_height()and\

enemy.y< plane.y + 0.7*plane.image.get_height():returnTrueelse:returnFalsedefshowWelcome(gameStart,gameOver):foreventinpygame.event.get():ifevent.typein(pygame.QUIT,pygame.KEYDOWN):

pygame.quit()

exit()ifevent.type ==pygame.MOUSEBUTTONUP:ifgameStart.is_over():returnFalseelifgameOver.is_over():

pygame.quit()

exit()

screen.blit(background, (0,0))

screen.blit(logo, ((SCREEN_SIZE[0]-logo.get_width())/2,100))

gameStart.render(screen)

gameOver.render(screen)returnTruedefrun():

sound=True

gameStart= Button('game_start.png','game_start_down.png',(SCREEN_SIZE[0]/2,SCREEN_SIZE[1]*8/12))

gameOver= Button('game_over.png','game_over_down.png',(SCREEN_SIZE[0]/2,SCREEN_SIZE[1]*11/12))

gameAgain= Button('game_again.png','game_again_down.png',(SCREEN_SIZE[0]/2,SCREEN_SIZE[1]*10/12))

gameContinue= Button('game_continue.png','game_continue_down.png',(SCREEN_SIZE[0]/2,SCREEN_SIZE[1]*9/12))

loadingCount=0whileshowWelcome(gameStart,gameOver):

time_passed= clock.tick(100)

loadingCount= (loadingCount+1) % 200showLoading(loadingCount,(SCREEN_SIZE[0]/2,SCREEN_SIZE[1]*19/24))

pygame.display.update()

pygame.mouse.set_visible(False)

plane=Hero()

bullets1=[]

bullets2=[]foriinrange(count_b):

bullets1.append(Bullet())

bullets2.append(Bullet())

index_b1=0

interval_b1=0#index_b2 = 0#interval_b2 = 0enemies =[]foriinrange(count_e):

enemies.append(Enemy())

index_e=0

interval_e=0

ufo=Ufo()

SCORE= 15000maxScore=0

BOMBnum= 3bomb=Bomb()

gameover=False

gamePause=False

bombflag=True

event=pygame.event.wait()whileTrue:

time_passed=clock.tick(fps)

time_passed_seconds= time_passed / 1000.0foreventinpygame.event.get():ifevent.type ==pygame.KEYDOWN:ifevent.key ==pygame.K_ESCAPE:

pygame.quit()

exit()ifevent.key ==pygame.K_SPACE:

gamePause=TrueifgamePause:

channel.pause()

pygame.mouse.set_visible(True)

screen.blit(background,(0,0))

screen.blit(logo, ((SCREEN_SIZE[0]-logo.get_width())/2,100))

gameOver.render(screen)

gameAgain.render(screen)

gameContinue.render(screen)

bombflag=Trueifevent.type ==pygame.MOUSEBUTTONUP:ifgameOver.is_over():

pygame.quit()

exit()elifgameAgain.is_over():

pygame.mouse.set_visible(False)

gamePause=False

SCORE=0foreinenemies:

e.active=FalseelifgameContinue.is_over():

pygame.mouse.set_visible(False)

gamePause=Falseelifnotgameover:ifrandint(1,1000)==1andufo.active ==False:

ufo.active=True

ufo.restart()

channel.unpause()

screen.blit(background,(0,0))

screen.blit(bomb_num,(SCREEN_SIZE[0]-160,SCREEN_SIZE[1]-65))

text= font1.render("x %d"%BOMBnum,1,(80,80,80))

screen.blit(text,(SCREEN_SIZE[0]-100,SCREEN_SIZE[1]-60))

interval_b1-= 1#interval_b2 -= 1interval_e -= 1ifinterval_b1 <0:

bullets1[index_b1].restart(1)

interval_b1= fps/count_b

index_b1= (index_b1 + 1)%count_b

bulletmusic.play()forbinbullets1:ifb.active:

b.move(time_passed_seconds)

screen.blit(b.image, (b.x,b.y))foreinenemies:ife.active:ifcheckHit(e, b):

SCORE+= 100ifinterval_e <0:

enemies[index_e].restart(SCORE)

interval_e= randint(max(0,30-SCORE/250),max(7,50-SCORE/700))

index_e= (index_e + 1)%count_eifevent.type == pygame.MOUSEBUTTONUPandBOMBnum>0 :ifbombflag == Falseandbomb.active ==False:

bomb.active=True

bomb.shoot()

BOMBnum-= 1bombflag=Trueelse:

bombflag=Falseifbomb.active:foreinenemies:ife.active:

bomb.checkBoom(e)

bomb.move(time_passed_seconds)

screen.blit(bomb.image,(bomb.x,bomb.y))ifbomb.is_boom:

bomb.boom()foreinenemies:ife.active:ifbomb.checkHit(e):

SCORE+= 100foreinenemies:ife.active:ifcheckCrash(e,plane):

gameover=True

e.move(time_passed_seconds)

screen.blit(e.image, (e.x, e.y))ife.count != -1:

e.showDown()ifufo.active:

ufo.move(time_passed_seconds)ifufo.checkGet(plane):

BOMBnum+= 1screen.blit(ufo.image,(ufo.x,ufo.y))

plane.move(time_passed_seconds)

screen.blit(plane.image, (plane.x,plane.y))

text= font1.render("Score: %d"%SCORE,1,(0,0,0))

screen.blit(text,(0,0))else:

bombflag=True

channel.pause()ifsound ==True:

gameovermusic.play()

sound=FalseifSCORE >maxScore:

maxScore=SCORE

Score= font2.render(str(SCORE),1,(50,50,50))

mScore= font1.render(str(maxScore),1,(50,50,50))

screen.blit(gameover_image,(0,0))

screen.blit(mScore,(150,40))

screen.blit(Score,(240-Score.get_width()/2, 375))

gameAgain.render(screen)

gameOver.render(screen)

pygame.mouse.set_visible(True)ifevent.type ==pygame.MOUSEBUTTONUP:ifgameAgain.is_over():

pygame.mouse.set_visible(False)

ufo.active=False

gameover=False

plane.restart()

SCORE=0

sound=True

BOMBnum= 3foreinenemies:

e.active=FalseelifgameOver.is_over():

pygame.quit()

exit()

pygame.display.update()if__name__=='__main__':

run()

pygame的这部分内容到这里也差不多了。这个蹩脚的飞机大战的基本功能也算是勉强实现了。

不过我还会再写一篇添加音乐和击毁动画的部分。

写的东西很基础,适合初学者看,能给大家以帮助的话,那是最好不过了。

但是自己底子太薄,没办法说更多的东西,所以我会学更多的东西,才可能分享更多的东西。

同样,分享的过程也是知识梳理的一个过程。挺棒的。

 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
 
© 2005- 王朝網路 版權所有 導航