鱼C论坛

 找回密码
 立即注册
查看: 2151|回复: 2

自己改编了课上的playaball游戏,但有几个问题怎么也解决不了,请大神指点!

[复制链接]
发表于 2019-10-10 09:17:50 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

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()
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2019-10-10 12:24:36 | 显示全部楼层
哪位大神方便加个微信啥的指导一下?我已经解决了小部分问题~
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-10-10 21:08:08 | 显示全部楼层
问题已经基本弄得差不多了,不过最后一个我发现,不论用小甲鱼推荐的哪种碰撞检测,都会出现两个球黏在一起的情况,这种情况有没有办法完全解决呢?
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2026-1-19 20:56

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表