2015/11/9用Python写游戏,pygame入门(8):按钮和游戏结束
昨天没有更新内容,今天相对多写一些。
因为我们已经基本完成游戏框架,但是游戏结束后,并不知道怎样比较好开始。我本来本着懒的原则,想结束后显示一个黑屏,然后你重新点一下鼠标就重新开始。但是那样实在太不像个热爱生活的程序员了,所以我决定用更合适的方法解决这个问题。
为此,我决定实现一个相对比较过得去的按钮。
为了实现按钮,我先创建一个测试程序体。然后在上面先实现一个按钮类的功能。
具体的测试程序,我就不详说了,反正就是你去创建一个这样的小窗口:
然后在上面完成一个按钮的类。
我设想的按钮应该是这样的,当我把鼠标移动上去的时候,它会将白底显示成灰底,移开后,又显示回白底。这其实就是两张图片的切换,所以,第一步要做的是,制作两张图,一张是白底的按钮,一张是灰底的按钮:
好了,接下来开始码这个类的功能了,首先是它的数据对象,必须得有两张图。
然后它还得有个安置它的位置坐标。
所以,它的初始化应该是这样定义的:
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
然后,它应该有个方法来判断,鼠标是不是在这个按钮的上面:
def isOver(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/2
in_y = y - h/2 < point_y < y + h/2
return in_x and in_y
还有一个用于判断显示哪张图的方法:
def render(self):
w, h = self.imageUp.get_size()
x, y = self.position if self.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 -*-
import pygame
from sys import exit pygame.init()
screen = pygame.display.set_mode((300,200),0,32)
upImageFilename = 'game_again.png'
downImageFilename = 'game_again_down.png' class Button(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 = position def isOver(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/2
in_y = y - h/2 < point_y < y + h/2
return in_x and in_y def render(self):
w, h = self.imageUp.get_size()
x, y = self.position if self.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)) while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
screen.fill((200, 200, 200))
button.render()
pygame.display.update()
就能得到一个显示按钮:
可以实现了我们的功能。
但是,等一下,我们没有写按钮的作用啊,也就是按下去就要执行的作用。
好吧,这件事反而是简单的。我们只需要判断event的时候调用isOver()方法就好了。
接下来我们来完成游戏框架了。
我想要一个开始界面,有开始按钮,游戏过程中,我想让它计分,游戏结束后可以显示最高分和我这次的分数,并且有个结束游戏和重新开始的按钮。
整个功能其实我都已经实现过了。
一步步地构造逻辑我就不多讲了,直接放代码。大家可以自己完成它。
这次代码里,我把自己的飞机也用了类实现,便于以后的拓展,有了计分模块,整个游戏用全屏模式打开。
当然整个代码还是有些乱的,不过由于大多数类和逻辑在之前已经讲过,相信还是易懂的
#-*- coding:utf-8-*-
import pygame
from sys import exit
from random import randint
from math import sqrt
pygame.init()
SCREEN_SIZE = (480,766)
screen = pygame.display.set_mode(SCREEN_SIZE,pygame.FULLSCREEN,32)
pygame.display.set_caption(" Plane Fight!") count_b = 7
count_e = 50
fps = 100 ufo = 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() def showLoading(count,pos):
n = count/50
x, y = pos
w, h = loading[2].get_size()
x -= w/2
y -= h/2
if n <3:
screen.blit(loading[n],(x,y)) class Button(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 = True def is_over(self):
point_x, point_y = pygame.mouse.get_pos()
x, y = self.position
w, h = self.image_up.get_size()
x -= w/2
y -= h/2 in_x = x < point_x < x + w
in_y = y < point_y < y + h
return in_x and in_y def render(self, surface):
x, y = self.position
w, h = self.image_up.get_size()
x -= w/2
y -= h/2
if self.is_over():
surface.blit(self.image_down, (x, y))
if self.button_out == True:
buttonmusic.play()
self.button_out = False
else:
surface.blit(self.image_up, (x, y))
self.button_out = True class Hero(object):
def restart(self):
self.x = 200
self.y = 600
def __init__(self):
self.restart()
self.image = plane_image
def move(self, time_passed_seconds):
mouseX, mouseY = pygame.mouse.get_pos()
self.x = mouseX - self.image.get_width()/2
self.y = mouseY - self.image.get_height()/2 class Bullet(object):
def __init__(self):
self.x = 0
self.y = -1
self.image = bullet_image
self.active = False
def move(self,time_passed_seconds):
if self.active :
self.y -= 700 * time_passed_seconds
if self.y < 0:
self.active = False def restart(self,flag):
mouseX, mouseY = pygame.mouse.get_pos()
if flag == 1:
self.x = mouseX - self.image.get_width()/2
self.y = mouseY - self.image.get_height()/2
if flag == 2:
self.x = mouseX - self.image.get_width()/2 + 33
self.y = mouseY - self.image.get_height()/2
self.active = True
class Enemy(object):
def restart(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 = -1
def __init__(self,):
self.restart(0)
self.image = enemy_image
self.active = False def move(self,time_passed_seconds):
if self.y < SCREEN_SIZE[1]:
self.y += self.speed * time_passed_seconds
else:
self.active = False
def showDown(self):
n = self.count/10
screen.blit(enemydown[n],(self.x,self.y))
self.count += 1
if self.count >= 39:
self.count = -1 class Bomb(object):
def __init__(self):
self.image = bomb_image
(self.x , self.y) = (-100,-100)
self.boom_x, self.boom_y = 0,0
self.speed = 800
self.active = False
self.is_boom = False
self.boomcount = 0
def shoot(self):
self.x, self.y = pygame.mouse.get_pos()
self.x -= self.image.get_width()/2
self.y -= self.image.get_height()/2
self.active = True
def move(self,time_passed_seconds):
if self.y > 250:
self.y -= self.speed*time_passed_seconds
else:
self.active = False
self.is_boom = True
self.boom_x, self.boom_y = self.x , self.y
usebombmusic.play()
def checkBoom(self,enemy):
if enemy.x - 60 < self.x < enemy.x + enemy.image.get_width()+60\
and enemy.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()
def checkHit(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)
if l < 250:
enemy.active = False
enemy.count = 1
return True
else:
return False
def boom(self):
n = self.boomcount/10
screen.blit(boom[n],(self.boom_x-boom[n].get_width()/2, self.boom_y-boom[n].get_height()/2))
self.boomcount += 1
if self.boomcount >= 49:
self.is_boom = False
self.boomcount = 0 class Ufo(object):
def restart(self):
self.x = randint(-30,440)
self.y = -107
self.speed = 250
def __init__(self):
self.image = ufo
self.restart()
self.active = False
def move(self,time_passed_seconds):
if self.y < SCREEN_SIZE[1]:
self.y += self.speed * time_passed_seconds
else:
self.active = False
def checkGet(self,plane):
if plane.x - 60 < self.x < plane.x + plane.image.get_width()+60\
and plane.y -80 < self.y < plane.y + plane.image.get_height():
self.active = False
getbombmusic.play()
return True
else:
return False def checkHit(enemy,bullet):
if enemy.x < bullet.x < enemy.x + enemy.image.get_width() \
and enemy.y < bullet.y < enemy.y + enemy.image.get_height():
enemy.active = False
bullet.active = False
enemydownmusic.play()
enemy.count+=1
return True
else:
return False def checkCrash(enemy,plane):
if plane.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():
return True
else:
return False def showWelcome(gameStart,gameOver):
for event in pygame.event.get():
if event.type in (pygame.QUIT,pygame.KEYDOWN):
pygame.quit()
exit()
if event.type == pygame.MOUSEBUTTONUP:
if gameStart.is_over():
return False
elif gameOver.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)
return True def run():
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 = 0
while showWelcome(gameStart,gameOver):
time_passed = clock.tick(100)
loadingCount = (loadingCount+1) % 200
showLoading(loadingCount,(SCREEN_SIZE[0]/2,SCREEN_SIZE[1]*19/24))
pygame.display.update() pygame.mouse.set_visible(False)
plane = Hero()
bullets1 = []
bullets2 = []
for i in range(count_b):
bullets1.append(Bullet())
bullets2.append(Bullet())
index_b1 = 0
interval_b1 = 0
#index_b2 = 0
#interval_b2 = 0
enemies = []
for i in range(count_e):
enemies.append(Enemy())
index_e = 0
interval_e = 0
ufo = Ufo() SCORE = 15000
maxScore = 0
BOMBnum = 3
bomb = Bomb()
gameover = False
gamePause = False
bombflag = True
event = pygame.event.wait()
while True:
time_passed = clock.tick(fps)
time_passed_seconds = time_passed / 1000.0
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
pygame.quit()
exit()
if event.key == pygame.K_SPACE:
gamePause = True if gamePause:
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 = True
if event.type == pygame.MOUSEBUTTONUP:
if gameOver.is_over():
pygame.quit()
exit()
elif gameAgain.is_over():
pygame.mouse.set_visible(False)
gamePause = False
SCORE = 0
for e in enemies:
e.active = False
elif gameContinue.is_over():
pygame.mouse.set_visible(False)
gamePause = False
elif not gameover:
if randint(1,1000)==1 and ufo.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 -= 1
interval_e -= 1
if interval_b1 < 0:
bullets1[index_b1].restart(1)
interval_b1 = fps/count_b
index_b1 = (index_b1 + 1)% count_b
bulletmusic.play() for b in bullets1:
if b.active:
b.move(time_passed_seconds)
screen.blit(b.image, (b.x,b.y))
for e in enemies:
if e.active:
if checkHit(e, b):
SCORE += 100 if interval_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_e
if event.type == pygame.MOUSEBUTTONUP and BOMBnum>0 :
if bombflag == False and bomb.active == False:
bomb.active = True
bomb.shoot()
BOMBnum -= 1
bombflag = True
else:
bombflag = False if bomb.active:
for e in enemies:
if e.active:
bomb.checkBoom(e)
bomb.move(time_passed_seconds)
screen.blit(bomb.image,(bomb.x,bomb.y))
if bomb.is_boom:
bomb.boom()
for e in enemies:
if e.active:
if bomb.checkHit(e):
SCORE += 100
for e in enemies:
if e.active:
if checkCrash(e,plane):
gameover = True
e.move(time_passed_seconds)
screen.blit(e.image, (e.x, e.y))
if e.count != -1:
e.showDown()
if ufo.active:
ufo.move(time_passed_seconds)
if ufo.checkGet(plane):
BOMBnum += 1
screen.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()
if sound == True:
gameovermusic.play()
sound = False
if SCORE > 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)
if event.type == pygame.MOUSEBUTTONUP:
if gameAgain.is_over():
pygame.mouse.set_visible(False)
ufo.active = False
gameover = False
plane.restart()
SCORE = 0
sound = True
BOMBnum = 3
for e in enemies:
e.active = False
elif gameOver.is_over():
pygame.quit()
exit() pygame.display.update() if __name__ == '__main__':
run()
pygame的这部分内容到这里也差不多了。这个蹩脚的飞机大战的基本功能也算是勉强实现了。
不过我还会再写一篇添加音乐和击毁动画的部分。
写的东西很基础,适合初学者看,能给大家以帮助的话,那是最好不过了。
但是自己底子太薄,没办法说更多的东西,所以我会学更多的东西,才可能分享更多的东西。
同样,分享的过程也是知识梳理的一个过程。挺棒的。
2015/11/9用Python写游戏,pygame入门(8):按钮和游戏结束的更多相关文章
- 2015/11/6用Python写游戏,pygame入门(6):控制大量的对象
昨天我们已经实现了这个游戏的三个基本类. 但是现在它还是没办法做成一个适合玩的游戏,毕竟只有一架敌机的游戏是很乏味的.所以,我们需要好多子弹,也需要好多敌机. 所以,我们要创建list,这个list存 ...
- 2015/11/1用Python写游戏,pygame入门(1):pygame的安装
这两天学习数据结构和算法,有时感觉并不如直接做项目来的有趣.刚刚学完python的基本使用,现在刚好趁热打铁做个小项目. 由于本人一直很想制作一款游戏,就想使用Python制作一个基础的游戏.搜了一下 ...
- 2015/11/5用Python写游戏,pygame入门(5):面向对象的游戏设计
昨天的内容里有了运动的子弹,虽然我们只添加了一个子弹,但你可以看到我们需要记录子弹的x,y坐标,每次要更新它的坐标.如果我们想要有多颗子弹,就需要存储多个坐标.那时候处理起来就不显得那么简单,也许我们 ...
- 2015/11/4用Python写游戏,pygame入门(4):获取鼠标的位置及运动
按昨天的说法,今天将开始做一个简单的游戏了. 目标是拷贝微信的飞机大战,当然拷贝完以后大家就具备自己添加不同内容的能力了. 首先是要拿到一些图片素材,熟悉使用图像处理软件和绘画的人可以自己制作,并没有 ...
- 2015/11/3用Python写游戏,pygame入门(3):字体模块、事件显示和错误处理
游戏里面一般是肯定会出现文字显示的,即使是俄罗斯方块也应该显示分数.那么我们应该怎样来显示文字呢,今天一起学习一下pygame的font模块. 使用字体模块 pygame可以直接调用系统字体,也可以调 ...
- 2015/11/7用Python写游戏,pygame入门(7):碰撞检测
我们已经完成了飞机大战的大部分东西,但是游戏还是没有办法正式开玩,因为子弹并不能打掉飞机.只有完成了这一个工作,游戏才算基本成型. 今天的内容就非常简单了,就是做到这个碰撞检测,以及控制好子弹和飞机的 ...
- 2015/11/2用Python写游戏,pygame入门(2):游戏中的事件和显示
pygame是一个比较大的库,以我这点弱小的实力是没办法详解的.所以我只讲我懂得那些部分,其他部分由大家慢慢查找了解. ------------------------------- 我用pygame ...
- 用Python写个开心消消乐小游戏
本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,如有问题请及时联系我们以作处理 提到开心消消乐这款小游戏,相信大家都不陌生,其曾在 2015 年获得过玩家最喜爱的移动单机游戏奖,受 ...
- 游戏编程入门之Bomb Catcher游戏
首先是代码: MyDirectX.h: #pragma once //header file #define WIN32_EXTRA_LEAN #define DIRECTINPUT_VERSION ...
随机推荐
- python中列表、元组、字典内部功能介绍
一.列表(list) 常用功能的介绍:
- Highcharts使用简例 + 异步动态读取数据
第一部分:在head之间加载两个JS库. <script src="html/js/jquery.js"></script> <script src= ...
- Linux 学习001
遇到的问题一: xxx is not in the sudoers file.This incident will be reported.的解决方法 1.切换到root用户下,怎么切换就不用说了吧, ...
- 讲讲js中的逻辑与(&&)以及逻辑或(||)
前几天看到一个函数,百思不得其解,今天早上醒来看了本js的书,正好讲到操作符的用法,给大家分享下js中的&&,||,和我们用的其他的编程语言还是有点区别的. 直接上那个函数的代码: f ...
- Linux系统管理命令之用户组管理
涉及的配置文件 /etc/group /etc/gshadow /etc/gshadow- 可用于还原 不同系统的备份文件名称不同:name-或name.old 命令: 添加用户组groupadd 组 ...
- android 关于appcompat v7出错问题与解决
1.appcompat_v7:应用兼容包,V7说的是版本7,即android2.1,这个兼容包支持2.1版本以上系统2.最近谷歌官方将兼容jar包与某些资源文件单独拿出来建立了一个android工程, ...
- Android 解读.apk解压后文件详细说明
转自:http://xdang.org/post-602.html 以下原文: 反编译 — 在apk文件中能得到什么 最近在做android客户端与服务器安全通信,有一种常见的不安全因素:很多软件常常 ...
- 嵌入式Linux开发板
嵌入式Linux开发板开发介绍: iTOP-4412嵌入式Linux开发板搭载三星Exynos四核处理器,配备1GB内存,4GB固态硬盘EMMC存储,独家配备三星S5M8767电源管理,配备Andro ...
- Github 扩展推荐
前言 github是个知识的宝库,分享一下自己浏览github使用的浏览器扩展. octotree 功能简介:以文件组织的结构方式查看仓库,再也不用一级一级地翻目录啦.下载单个文件 源码:https: ...
- DBCP连接池配置参数说明
<!-- 数据源1 --> <bean id="dataSource" class="org.apache.commons.dbcp.BasicData ...