python 小甲鱼 代码_python(pygame)之:修复小甲鱼第一个游戏的BUG

(PS:几经修改,终于完善.最后附上了此游戏终极完善版,带全屏拖屏,键盘控制,无BUG版)

小甲鱼python第81期讲述pygame事件时,做了一个小游戏,乌龟上下左右移动,按下对应按键可以调整其运动方向.

不过甲鱼哥的代码有一个BUG当时没有发现:当乌龟碰到左边界的瞬间按下⬅时, 有时会出发一个BUG,导致甲鱼以非常高的频率来回撞墙,图像高频率来回翻转,乌龟仿佛变成了一只蝴蝶.... .

用面向对象的思维方法理解下述代码:

1.pygame.event.get()到底是个什么?

2.为什么有的event有key属性,有的有size属性,有的什么都没有???他们不是同一个类的实例吗?

源代码如下(含BUG)

import pygame
import sys

pygame.init()

size=width,height= 600,400
speed=[6,3]
bg=(0,0,0)
screen=pygame.display.set_mode(size) 
#用pygame.display模块里面的set_mode()方法返回一个Surface对象 贴给screen.
#screen是游戏内容的显示区域,Surface是"表现类"对象

pygame.display.set_caption("hello!anny!")
调用pygame.display模块里面的set_caption()方法将游戏框架(非screen)的标题设为"..."
anny=pygame.image.load("sheep.png")
#调用pygame.image.模块里面的load()方法缓存图片,返回一个Surface表现对象给anny

position=anny.get_rect()#获得Surface表现对象的轮廓矩形,每个Surface表现对象都有一个Rect对象

l_head=anny
r_head=anny = pygame.transform.flip(anny, True, False) 
#调用pygame.transform模块里面的flip()方法翻转Surface表现对象并重新贴给anny

while 1:
    for event in pygame.event.get():
    #调用pygame.event模块里面的get()方法,返回Event事件对象列表,列表中每个元素都是Event类型
    #用for遍历此表
        if event.type== pygame.QUIT:#这些大写字母其实是Event的特定type时的属性,类型为INT
    #每个event都有type属性,来确定事件类型,type不同,其他属性也不同,
    #这个地方用面向对象的思维方法该怎么理解?例如type=2时(也就是pygame.QUIT),Event没有key属性,
    #会报AttributeError: 'Event' object has no attribute 'key'.type=4时又有????
    #难道是如果type不对主动抛出异常?
            sys.exit()
        if event.type== pygame.KEYDOWN:
           if event.key == pygame.K_LEFT:
                anny = l_head
                speed=[-6,0]
           if event.key == pygame.K_RIGHT:
                anny = r_head
                speed = [6, 0]
           if event.key == pygame.K_UP:
                speed=[0,-3]
           if event.key == pygame.K_DOWN:
                speed = [0, 3]
    position=position.move(speed)
#position是Surface类的Rect嵌套类(类种类),其中有move方法,移动自己位置.
    if position.left < 0 or position.right > width:
        anny=pygame.transform.flip(anny,True,False)
调用pygame.transform模块里的flip()方法处理图像并返回Surface对象,重新贴上anny
        speed[0]=-speed[0]
    if position.top < -50 or position.bottom > height+20:
        speed[1] = -speed[1]
    screen.fill(bg)  #bg填充 Surface表现对象
    screen.blit(anny,position) 
#blit()是Surface表现对象的一个方法,将anny这个Surface表现对象用一个Rect(position)对象传送到自己上层
    pygame.display.flip()
#这个flip()和pygame.transform模块里的flip()方法完全不是一个方法!!!!!!!
    pygame.time.delay(10)

刚开始没仔细想,感到很困惑.后来仔细分析了一下,其实很简单,当乌龟碰到左边界的瞬间按下⬅,即同时符合以下两个条件:

if event.key == pygame.K_LEFT:
        anny = l_head
        speed=[-6,0]
if position.left < 0 or position.right > width:
        anny=pygame.transform.flip(anny,True,False)
        speed[0]=-speed[0]
  1. 乌龟刚刚碰撞完 speed=6(正常)
  2. 此时按下了K_LEFT,speed=-6(正常)
  3. 乌龟又走向left一个周期(异常)
  4. 此时符合 left<0,故图片反转,speed也翻转(正常))
  5. 但因为之前speed=-6时,多往left走了一个周期,所以还是符合left<0,故有发生了翻转(异常)
  6. 翻转后speed又=-6,又会多走一个周期(异常)
  7. 无限循环4,5,6步(BUG产生!!)

在if position.left < 0 or position.right > width:加一句print(speed[0]),就可以看到它在迷失在6和-6之间了

正确的解决方法是:

1.position=position.move(speed)移动到最后画面刷新之前,将触发条件干掉

2 不用翻转!用绝对速度和绝对图像.理念l_head,r_head差不多.

简单的将position.left < 0 和 position.right > width分开写就可以解决此问题

方法1代码如下:

import pygame
import sys

pygame.init()

size=width,height= 600,400
speed=[2,1]
bg=(0,0,0)
screen=pygame.display.set_mode(size)

pygame.display.set_caption("hello!anny!")
anny=pygame.image.load("sheep.png")
print(type(anny))
position=anny.get_rect()
print(type(position))

l_head=anny
r_head=anny = pygame.transform.flip(anny, True, False)

while 1:
    for event in pygame.event.get():
        if event.type== pygame.QUIT:
            sys.exit()
        print(str(event))
        try:
            print(event.type,event.pos,event.rel,event.buttons)
        except:
            pass
        if event.type== pygame.KEYDOWN:
           if event.key == pygame.K_LEFT:
                anny = l_head
                speed=[-6,0]
           if event.key == pygame.K_RIGHT:
                anny = r_head
                speed = [6, 0]
           if event.key == pygame.K_UP:
                speed=[0,-3]
           if event.key == pygame.K_DOWN:
                speed = [0, 3]

    if position.left < 0 or position.right > width:
        anny=pygame.transform.flip(anny,True,False)
        speed[0]=-speed[0]
    if position.top < -50 or position.bottom > height+20:
        speed[1] = -speed[1]
    position = position.move(speed)
    screen.fill(bg)
    screen.blit(anny,position)
    pygame.display.flip()
    pygame.time.delay(10)

方法2代码如下:

import pygame
import sys

pygame.init()

size=width,height= 600,400
speed=[2,1]
bg=(0,0,0)
screen=pygame.display.set_mode(size)

pygame.display.set_caption("hello!anny!")
anny=pygame.image.load("sheep.png")
print(type(anny))
position=anny.get_rect()
print(type(position))

l_head=anny
r_head=anny = pygame.transform.flip(anny, True, False)

while 1:
    for event in pygame.event.get():
        if event.type== pygame.QUIT:
            sys.exit()
        print(str(event))
        try:
            print(event.type,event.pos,event.rel,event.buttons)
        except:
            pass
        if event.type== pygame.KEYDOWN:
           if event.key == pygame.K_LEFT:
                anny = l_head
                speed=[-6,0]
           if event.key == pygame.K_RIGHT:
                anny = r_head
                speed = [6, 0]
           if event.key == pygame.K_UP:
                speed=[0,-3]
           if event.key == pygame.K_DOWN:
                speed = [0, 3]
    position=position.move(speed)
    if position.left < 0:
        anny=r_head
        speed[0]=abs(speed[0])
    elif position.right > width:
        anny = l_head
        speed[0] = -abs(speed[0])
    if position.top < -50 or position.bottom > height+20:
        speed[1] = -speed[1]
    screen.fill(bg)
    screen.blit(anny,position)
    pygame.display.flip()
    pygame.time.delay(10)

此外:还写了一个投机的方法,也能解决此BUG:

if position.left<100:
    speed[0]=6
if position.right>300:
    speed[0]=-6
#代替  speed[0]=-speed[0](只是人为的区分了一下左右而已,个人还是会选择上面的方法.)

c03577812ece1b4bbe94feeaef0e1503.png

最后一跃:

import pygame
import sys
from pygame.locals import *

pygame.init()

size=width,height= 600,400
speed=[2,1]
bg=(0,0,0)
fullscreen=False

screen=pygame.display.set_mode(size,RESIZABLE)

pygame.display.set_caption("hello!anny!")
anny=pygame.image.load("sheep.png")

position=anny.get_rect()
l_head=anny
r_head=anny = pygame.transform.flip(anny, True, False)

while 1:

    for event in pygame.event.get():
        if event.type== pygame.QUIT:
            sys.exit()

        if event.type== pygame.KEYDOWN:
            if event.key == pygame.K_LEFT:
                anny = l_head
                speed=[-6,0]
            if event.key == pygame.K_RIGHT:
                anny = r_head
                speed = [6, 0]
            if event.key == pygame.K_UP:
                speed=[0,-3]
            if event.key == pygame.K_DOWN:
                speed = [0, 3]
            # 全屏
            if event.key == pygame.K_F11:
                fullscreen=not(fullscreen)
                if fullscreen:
                    screen = pygame.display.set_mode(pygame.display.list_modes()[0],FULLSCREEN|HWSURFACE)
                    width=pygame.display.list_modes()[0][0]
                    height=pygame.display.list_modes()[0][1]
                else:
                    screen = pygame.display.set_mode(size,RESIZABLE)
        #拖屏
        if event.type == VIDEORESIZE:
            if fullscreen:
                pass
            else:
                try:
                    if event.size[0]>400 and event.size[1]>300:
                        size = event.size
                        screen = pygame.display.set_mode(size, RESIZABLE)
                        width = event.size[0]
                        height = event.size[1]
                        if position.right > width:
                            position.right = width
                        if position.bottom > height:
                            position.bottom = height + 20
                    else:
                        size=width,height= 600,400
                        screen = pygame.display.set_mode(size, RESIZABLE)
                        if position.right > width:
                            position.right = width
                        if position.bottom > height:
                            position.bottom = height + 20
                except AttributeError:
                    pass
    if position.left < 0 or position.right > width:
        anny=pygame.transform.flip(anny,True,False)
        speed[0]=-speed[0]
    if position.top < -40 or position.bottom > height+20:
        speed[1] = -speed[1]
    position = position.move(speed)
    screen.fill(bg)
    screen.blit(anny,position)
    pygame.display.flip()
    pygame.time.delay(10)
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值