|
|
马上注册,结交更多好友,享用更多功能^_^
您需要 登录 才可以下载或查看,没有账号?立即注册
x
改编思路:
1、添加ball_ctr_flg标签,检查此标签确保每一时刻只有一个小球接受控制
2、改编小球碰撞后运动规则:小球碰撞后将两个小球的速度交换,而不是原路返回。因为要交换速度,所以需要获得两个碰撞球的速度,故碰撞检测使用的是小甲鱼给出的第一种方法。
3、在定义球类时,我把速度属性直接定义到球里
目前发现存在的问题:
1、游戏结束后,只有loser_sound,而laugh_sound并不执行
2、每次游戏控制2个球入洞后,再也无法通过鼠标移动来控制球,不知道哪里的问题
3、在碰撞过程中,自认为理论上不应该存在两个小球堆一起抖啊抖分不开的情况,但实际还是有
4、开始在写控制球的移动按键部分时,直接用each.speed[0] += 1等方式,但报错了,提示':tuple' does object not support item assignment,看这意思是把each.speed看成元组了,但我明明用的列表形式啊,不懂~
以上问题有点多,如有大神肯费心知道一二,不胜感激!
下面是我的代码:
import pygame
import math
import random
from pygame.locals import *
import traceback
import sys
class Ball(pygame.sprite.Sprite):
def __init__(self,image_gray,image_green,bg_size,target):
pygame.sprite.Sprite.__init__(self)
self.image_gray = pygame.image.load(image_gray).convert_alpha() #加载灰球图片
#self.image_gray = pygame.image.load(image_gray).convert_alpha()
self.image_green = pygame.image.load(image_green).convert_alpha()#加载绿球图片
self.direct = [random.choice([-1, 1]), random.choice([-1, 1])]#随机选择小球初始移动方向
self.speed_abs = [random.randint(2,6),random.randint(2,6)]
self.width, self.height = bg_size[0], bg_size[1]
self.position = [random.randint(0, self.width-100), random.randint(0, self.height-100)]#随机生成小球位置
self.control = False #控制标识
self.collide = False #碰撞标识
self.collide_check = False #碰撞检测标识
self.speed = [self.direct[0]*self.speed_abs[0],self.direct[1]*self.speed_abs[1]]
self.target = target#用来设置捕获设定的参数
self.rect = self.image_gray.get_rect()#获取球的矩形区域大小
self.rect.left=self.position[0]
self.rect.right=self.position[1]
self.radius = self.rect.width/2#获取球半径
def move(self):
self.rect.left += self.speed[0]
self.rect.top += self.speed[1]
#self.rect = self.rect.move(self.speed)
#边界穿越检测设定
if self.rect.right <= 0:
self.rect.left = self.width
elif self.rect.left >= self.width:
self.rect.right = 0
elif self.rect.top >= self.height:
self.rect.bottom = 0
elif self.rect.bottom <= 0:
self.rect.top = self.height
def check(self,motion):
if self.target < motion < self.target +10:
return True
else:
return False
class Glass(pygame.sprite.Sprite):
def __init__(self,glass_image,mouse_image,bg_size):
#初始化动画精灵
pygame.sprite.Sprite.__init__(self)
self.glass_image = pygame.image.load(glass_image).convert_alpha()
self.glass_rect = self.glass_image.get_rect()
self.glass_rect.left,self.glass_rect.top = \
(bg_size[0]-self.glass_rect.width)//2,\
(bg_size[1]-self.glass_rect.height)
self.mouse_image = pygame.image.load(mouse_image).convert_alpha()
self.mouse_rect = self.mouse_image.get_rect()
self.mouse_rect.left,self.mouse_rect.top = \
self.glass_rect.left,self.glass_rect.top
pygame.mouse.set_visible(False)
def main():
#初始化pygame
pygame.init()
pygame.mixer.init()#添加声音和背景音乐,其实可以不加,添加是保险起见
image_gray = 'gray_ball.png'
image_green = 'green_ball.png'
glass_image = 'glass.png'
mouse_image = 'hand.png'
bg_image = 'background.png'
running = True
#添加魔性的背景音乐
pygame.mixer.music.load('bg_music.ogg')
pygame.mixer.music.play()
#添加音效
loser_sound = pygame.mixer.Sound('loser.wav')
laugh_sound = pygame.mixer.Sound('laugh.wav')
laugh_sound.play()
winner_sound = pygame.mixer.Sound('winner.wav')
hole_sound = pygame.mixer.Sound('hole.wav')
#音乐播放完时游戏结束
GAMEOVER = USEREVENT #用户自定义事件?
pygame.mixer.music.set_endevent(GAMEOVER)
#根据背景图片指定游戏界面尺寸
bg_size = width,height = 1024,681
screen = pygame.display.set_mode(bg_size)
pygame.display.set_caption('play a ball!_CC')
background = pygame.image.load(bg_image).convert_alpha()
#5个坑的范围,因为100%命中太难,所以只要在范围内即可
#每个元素:(x1,x2,y1,y2)
hole = [(115,121,197,203),(223,229,388,394),\
(501,507,318,324),(696,702,190,196),\
(904,910,417,423)]
#存放要打印的消息
msgs=[]
#用来存放小球对象的列表
balls = []
group = pygame.sprite.Group()
for i in range(8):
ball = Ball(image_gray,image_green,bg_size,10*(i+2))
#检测新诞生的小球是否会卡住其它小球
while pygame.sprite.spritecollide(ball,group,False,pygame.sprite.collide_circle):
ball.rect.left,ball.rect.top = random.randint(0,width-100),random.randint(0,height-100)
balls.append(ball)
group.add(ball)
glass = Glass(glass_image,mouse_image,bg_size)
#motion 记录鼠标在玻璃面板产生的事件数量
motion = 0
#1秒检查1次鼠标摩擦产生的事件数量
MYTIMER = USEREVENT + 1
pygame.time.set_timer(MYTIMER,1000)#怎么理解?
#设置持续按下键盘的重复响应
pygame.key.set_repeat(100,100)
clock = pygame.time.Clock()
ball_ctr_flg = False#用来标识当前是否有受控制的小球
while running:
for event in pygame.event.get():#退出按键
if event.type == QUIT:
pygame.quit()
sys.exit()
elif event.type == GAMEOVER:#游戏失败
loser_sound.play()
pygame.time.delay(2000)
laugh_sound.play()
running = False
#1秒检查1次鼠标摩擦产生的事件数量
elif event.type == MYTIMER:
if not ball_ctr_flg:
if motion:
for each in group:
if each.check(motion):
each.control = True
ball_ctr_flg = True#其它小球不再检测是否可以被控制的状态
# each.speed = [0,0]
motion = 0
elif event.type == MOUSEMOTION:
motion += 1
#当存在小球的control 属性为True时
#被控制的小球可以用w/s/a/d控制移动小球
elif event.type == KEYDOWN:
for each in group:
if each.control:
if event.key == K_w:
if each.direct[1] == 1:
each.speed_abs[1] -= 1
if each.speed_abs[1] < 0:
each.speed_abs[1] = 0
each.direct[1] = -1
else:
each.speed_abs[1] += 1
#each.rect.top -= 3
each.speed = [each.direct[0]*each.speed_abs[0],each.direct[1]*each.speed_abs[1]]
elif event.key == K_s:
if each.direct[1] == -1:
each.speed_abs[1] -= 1
if each.speed_abs[1] < 0:
each.speed_abs[1] = 0
each.direct[1] = 1
else:
each.speed_abs[1] += 1
#each.rect.top += 3
each.speed = [each.direct[0]*each.speed_abs[0],each.direct[1]*each.speed_abs[1]]
elif event.key == K_a:
if each.direct[0] == 1:
each.speed_abs[0] -= 1
if each.speed_abs[0] < 0:
each.speed_abs[0] = 0
each.direct[0] = -1
else:
each.speed_abs[0] += 1
#each.rect.left -= 3
each.speed = [each.direct[0]*each.speed_abs[0],each.direct[1]*each.speed_abs[1]]
elif event.key == K_d:
if each.direct[0] == -1:
each.speed_abs[0] -= 1
if each.speed_abs[0] < 0:
each.speed_abs[0] = 0
each.direct[0] = 1
else:
each.speed_abs[0] += 1
#each.rect.left += 3
each.speed = [each.direct[0]*each.speed_abs[0],each.direct[1]*each.speed_abs[1]]
if event.key == K_SPACE:
#判断小球是否在坑内
for i in hole:
if i[0] <= each.rect.left <= i[1] and\
i[2] <= each.rect.top <= i[3]:
#播放音乐
hole_sound.play()
each.speed = [0,0]
group.remove(each)#把小球从列表中移除
temp = balls.pop(balls.index(each))
balls.insert(0,temp)
hole.remove(i)#把坑移除
ball_ctr_flg = False
if not hole or not group:
pygame.mixer.music.stop()
winner_sound.play()
pygame.time.delay(3000)
#打印“然并卵”
msg = pygame.image.load('win.png').convert_alpha()
msg_pos = (width - msg.get_width()) // 2,\
(height - msg.get_height())//2
msgs.append((msg,msg_pos))
laugh_sound.play()
pygame.time.delay(3000)
screen.blit(background,(0,0))
screen.blit(glass.glass_image,glass.glass_rect)
#限制鼠标只能在玻璃内摩擦摩擦
glass.mouse_rect.left,glass.mouse_rect.top = pygame.mouse.get_pos()
if glass.mouse_rect.left < glass.glass_rect.left:
glass.mouse_rect.left = glass.glass_rect.left
if glass.mouse_rect.left > glass.glass_rect.right - glass.mouse_rect.width:
glass.mouse_rect.left = glass.glass_rect.right - glass.mouse_rect.width
if glass.mouse_rect.top < glass.glass_rect.top:
glass.mouse_rect.top = glass.glass_rect.top
if glass.mouse_rect.top > glass.glass_rect.bottom - glass.mouse_rect.height:
glass.mouse_rect.top = glass.glass_rect.bottom - glass.mouse_rect.height
screen.blit(glass.mouse_image,glass.mouse_rect)
for each in balls:
each.move()
if each.control:
screen.blit(each.image_green,[each.rect.left,each.rect.top])
else:
screen.blit(each.image_gray,[each.rect.left,each.rect.top])
# if each.collide:
# screen.blit(each.image_gray,each.rect)
#碰撞检测
for each in group:
#先从组中移出当前球
group.remove(each)
#判断当前球与其它球是否相撞
for other in group:
if not other.collide_check:#用来标记是否进行过碰撞检测,只对未进行过的进行检测
distance = math.sqrt(\
math.pow((each.rect.center[0]-other.rect.center[0]),2)+\
math.pow((each.rect.center[1]-other.rect.center[1]),2)
)
if distance <= (each.rect.width + other.rect.width)/2:
#发生碰撞
each.collide = True
other.collide = True
if each.control:
each.control = not each.control
ball_ctr_flg = False
elif other.control:
other.control = not other.control
ball_ctr_flg = False
#重新计算小球碰撞后的速度
if each.direct[0] == other.direct[0] and each.direct[1] == other.direct[1]:
each.speed_abs[0],other.speed_abs[0] = other.speed_abs[0],each.speed_abs[0]
each.speed_abs[1],other.speed_abs[1] = other.speed_abs[1],each.speed_abs[1]
elif each.direct[0]==other.direct[0] and each.direct[1] != other.direct[1]:
each.speed_abs[0],other.speed_abs[0] = other.speed_abs[0],each.speed_abs[0]
each.speed_abs[1],other.speed_abs[1] = other.speed_abs[1],each.speed_abs[1]
#each.direct[1] = -each.direct[1]
#other.direct[1] = -other.direct[1]
each.direct[1],other.direct[1] = other.direct[1],each.direct[1]
elif each.direct[1]==other.direct[1] and each.direct[0] != other.direct[0]:
each.speed_abs[0],other.speed_abs[0] = other.speed_abs[0],each.speed_abs[0]
each.speed_abs[1],other.speed_abs[1] = other.speed_abs[1],each.speed_abs[1]
#each.direct[0] = -each.direct[0]
#other.direct[0] = -other.direct[0]
each.direct[0],other.direct[0] = other.direct[0],each.direct[0]
elif each.direct[0]!=other.direct[0] and each.direct[1] != other.direct[1]:
each.speed_abs[0],other.speed_abs[0] = other.speed_abs[0],each.speed_abs[0]
each.speed_abs[1],other.speed_abs[1] = other.speed_abs[1],each.speed_abs[1]
#each.direct[0]=-each.direct[0]
#each.direct[1]=-each.direct[1]
#other.direct[0]=-other.direct[0]
#other.direct[1]=-other.direct[1]
each.direct[0],other.direct[0] = other.direct[0],each.direct[0]
each.direct[1],other.direct[1] = other.direct[1],each.direct[1]
each.speed = [each.direct[0]*each.speed_abs[0],each.direct[1]*each.speed_abs[1]]
other.speed = [other.direct[0]*other.speed_abs[0],other.direct[1]*other.speed_abs[1]]
each.collide_check = True
#将当前球添加回组中
group.add(each)
for each in group:
each.collide_check = False#将小球的碰撞检测标识重置,为下一次检测做准备
for msg in msgs:
screen.blit(msg[0],msg[1])
pygame.display.flip()
clock.tick(30)
if __name__ == '__main__':
#这样做的好处时双击打开时如果出现异常可以报告异常,而不是一闪而过!
try:
main()
except SystemExit:
pass
except:
traceback.print_exc()
pygame.quit()
input() |
|