微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Pygame 问题下落物体不显示

如何解决Pygame 问题下落物体不显示

嘿,谁能告诉我为什么我没有看到物体从顶部掉下来?在这种情况下,“Münzen、Scheine 和 Sack”。我是 pygame 的新手,也许有一个简单的方法。我的游戏应该是这样的:

行走的人应该抓住掉下来的钱并获得积分。

https://gyazo.com/d2ce52cb54e8658e92ae9e5f3d1e7cca

import random
from pygame.sprite import Sprite
pygame.init()

#display
win = pygame.display.set_mode((900,780))
pygame.display.set_caption("The Collector")

#Laufanimation
walkRight = [pygame.image.load('Assets/R1.png'),pygame.image.load('Assets/R2.png'),pygame.image.load('Assets/R3.png'),pygame.image.load('Assets/R4.png'),pygame.image.load('Assets/R5.png'),pygame.image.load('Assets/R6.png'),pygame.image.load('Assets/R7.png'),pygame.image.load('Assets/R8.png'),pygame.image.load('Assets/R9.png')]
walkLeft = [pygame.image.load('Assets/L1.png'),pygame.image.load('Assets/L2.png'),pygame.image.load('Assets/L3.png'),pygame.image.load('Assets/L4.png'),pygame.image.load('Assets/L5.png'),pygame.image.load('Assets/L6.png'),pygame.image.load('Assets/L7.png'),pygame.image.load('Assets/L8.png'),pygame.image.load('Assets/L9.png')]

#Hintergrund
bg = pygame.image.load('City.jpg')
bg = pygame.transform.scale(bg,(900,780))

#Charakter
char = pygame.image.load('Assets/R1.png')

# Geld
Münzen2 = pygame.image.load("Assets/coin.png")
Schein2 = pygame.image.load("Assets/schein.png")
Sack2 = pygame.image.load("Assets/sack.png")

# Geld
Münzen = pygame.image.load("Assets/coin.png")
Schein = pygame.image.load("Assets/schein.png")
Sack = pygame.image.load("Assets/sack.png")

clock = pygame.time.Clock()

class player():
    def __init__(self,x,y,width,height):
        self.x = x
        self.y = y
        self.width = width
        self.height = height
        self.vel = 20
        self.left = False
        self.right = False
        self.walkCount = 0
        self.hitBox = (self.x + 20,self.y,28,60)

    def draw(self,win):
        if self.walkCount + 1 >= 27:
            self.walkCount = 0

        if self.left:
            win.blit(walkLeft[self.walkCount//3],(self.x,self.y))
            self.walkCount += 1
        elif self.right:
            win.blit(walkRight[self.walkCount//3],self.y))
            self.walkCount +=1
        else:
            win.blit(char,self.y))

        self.hitBox = (self.x + 215,self.y + 230,220,70) # NEW
        pygame.draw.rect(win,(255,0),self.hitBox,2)


    
    
class Laser:
    def __init__(self,img):
        self.x = x
        self.y = y
        self.img = img

    def draw(self,window):
        window.blit(self.img,self.y))

    def move(self,vel):
        self.y += vel

    def off_screen(self,height):
        return not(self.y <= height and self.y >= 0)

    def collision(self,obj):
        return collide(self,obj)


def redrawGameWindow():
    win.blit(bg,(0,0))
    collector.draw(win)
    pygame.display.update()

class Ship:
    COOLDOWN = 30

    def __init__(self,health=100):
        self.x = x
        self.y = y
        self.health = health
        self.ship_img = None
        self.laser_img = None
        self.lasers = []
        self.cool_down_counter = 0

    def draw(self,window):
        window.blit(self.ship_img,self.y))
        for laser in self.lasers:
            laser.draw(window)

    def move_lasers(self,vel,obj):
        self.cooldown()
        for laser in self.lasers:
            laser.move(vel)
            if laser.off_screen(HEIGHT):
                self.lasers.remove(laser)
            elif laser.collision(obj):
                obj.health -= 10
                self.lasers.remove(laser)

    def cooldown(self):
        if self.cool_down_counter >= self.COOLDOWN:
            self.cool_down_counter = 0
        elif self.cool_down_counter > 0:
            self.cool_down_counter += 1

    def shoot(self):
        if self.cool_down_counter == 0:
            laser = Laser(self.x,self.laser_img)
            self.lasers.append(laser)
            self.cool_down_counter = 1

    def get_width(self):
        return self.ship_img.get_width()

    def get_height(self):
        return self.ship_img.get_height()        

        

class Enemy(Ship):
    COLOR_MAP = {
                "red": (Münzen,Münzen2),"green": (Schein,Schein2),"blue": (Sack,Sack2)
                }

    def __init__(self,color,health=100):
        super().__init__(x,health)
        self.ship_img,self.laser_img = self.COLOR_MAP[color]
        self.mask = pygame.mask.from_surface(self.ship_img)

    def move(self,vel):
        self.y += vel

    def shoot(self):
        if self.cool_down_counter == 0:
            laser = Laser(self.x-20,self.laser_img)
            self.lasers.append(laser)
            self.cool_down_counter = 1


def collide(obj1,obj2):
    offset_x = obj2.x - obj1.x
    offset_y = obj2.y - obj1.y
    return obj1.mask.overlap(obj2.mask,(offset_x,offset_y)) != None


#mainloop
collector = player(200,410,64,64)

run = True
while run:
    clock.tick(27)

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False

    keys = pygame.key.get_pressed()

    if keys[pygame.K_LEFT] and collector.x > -180 -collector.width -collector.vel:
        collector.x -= collector.vel
        collector.left = True
        collector.right = False
    elif keys[pygame.K_RIGHT] and collector.x < 550 - collector.width - collector.vel:
        collector.x += collector.vel
        collector.right = True
        collector.left = False
    else:
       collector.right = False
       collector.left = False
       collector.walkCount = 0    


    redrawGameWindow()

pygame.quit()````


  [1]: https://i.stack.imgur.com/FYFkB.png

解决方法

您似乎将代码复制/粘贴到了一起,所以让我们放弃它并从头开始吧。在我们继续的过程中,请随时查看 documentation 中的一些内容。

首先,我们需要一个主循环来保持我们的游戏运行。我通常从这样的事情开始:

import pygame

RESOLUTION = 800,600
FPS = 60

def main():
    pygame.init()
    screen = pygame.display.set_mode(RESOLUTION)
    dt,clock = 0,pygame.time.Clock()
    sprites = pygame.sprite.Group()

    while True:
        events = pygame.event.get()
        for e in events:
            if e.type == pygame.QUIT:
                return
        screen.fill('black')
        sprites.update(dt,events)
        sprites.draw(screen)
        pygame.display.flip()
        dt = clock.tick(FPS) / 1000

if __name__ == "__main__":
    main()

这将创建一个窗口并管理我们稍后将创建并添加到 sprites 容器的精灵。目前这里没什么可看的:

enter image description here

现在,我们想要一个可以左右移动的玩家。下面是我将如何做到这一点,利用一些 pygame 功能,如 RectSprite 类。不涉及魔法。 Sprite 基本上只是一个具有 image 属性(您已经猜到这是要使用的图像)和一个 rect 属性的类,其中包含我们要绘制图像的位置。

这是 Player 类:

TILESIZE = 32
PLAYER_SPEED = 600

class Player(pygame.sprite.Sprite):
    def __init__(self,pos,*grps):
        super().__init__(*grps)
        self.image = pygame.Surface((TILESIZE,TILESIZE))
        self.image.fill('dodgerblue')
        self.rect = self.image.get_rect(topleft=pos)
        
    def update(self,dt,events):
        d = 0
        pressed = pygame.key.get_pressed()
        if pressed[pygame.K_a]: d -= 1
        if pressed[pygame.K_d]: d += 1

        self.rect.move_ip(d * dt * PLAYER_SPEED,0)
        display_rect = pygame.display.get_surface().get_rect()
        self.rect.clamp_ip(display_rect)

现在让我们在游戏中添加一个 Player

...
sprites = pygame.sprite.Group()
Player((300,500),sprites)
while True:
...

enter image description here

请注意,您不必手动绘制/blit 任何内容。给我们的类一个 imagerect 属性,子类 Sprite,将实例添加到 Group,并在这个组上调用 draw

现在是掉落的硬币和其他东西。我们应该为他们创建一个类,像这样:

from random import choice
FALLING_SPEED = 400

class FallingStuff(pygame.sprite.Sprite):
    def __init__(self,TILESIZE))
        self.image.fill(choice(['red','yellow','green']))
        self.rect = self.image.get_rect(topleft=pos)
        
    def update(self,events):
        self.rect.move_ip(0,FALLING_SPEED * dt)
        display_rect = pygame.display.get_surface().get_rect()
        if self.rect.top > display_rect.bottom:
            self.kill()

在您的最终游戏中,您可以轻松地将单色 image 替换为您从文件加载的图像。在这里,我只是随机选择红色、黄色或绿色。

正如您已经猜到的,我们游戏对象的所有行为都在精灵类的 update 方法中。 FallingStuff 只是向下移动它的 rect 并在它离开屏幕时杀死自己。 'killing' 作为 sprite 只是意味着它将自己从它的所有 Group 容器中移除。使用这些而不是普通列表的另一个原因。

当然,我们要生成多个下落物体。有很多方法可以做到这一点,但让我们使用 pygame 的 time 模块来创建一个事件,因为为什么不:

from random import randint
...
CREATE_STUFF = pygame.USEREVENT + 1
pygame.time.set_timer(CREATE_STUFF,randint(1000,2000),True)
while True:
    events = pygame.event.get()
    for e in events:
        if e.type == pygame.QUIT:
            return
        if e.type == CREATE_STUFF:
            pygame.time.set_timer(CREATE_STUFF,True)
            FallingStuff((randint(50,550),-TILESIZE),sprites)
    screen.fill('black')
    sprites.update(dt,events)
    sprites.draw(screen)
    pygame.display.flip()
    dt = clock.tick(FPS) / 1000

enter image description here

剩下的唯一事情就是检查我们是否能抓住其中一个坠落的物体。

完整代码如下:

import pygame
import pygame.freetype
from random import choice,randint

RESOLUTION = 800,600
FPS = 60
TILESIZE = 32
PLAYER_SPEED = 600
FALLING_SPEED = 400

class Player(pygame.sprite.Sprite):
    def __init__(self,falling_stuff,TILESIZE))
        self.image.fill('dodgerblue')
        self.rect = self.image.get_rect(topleft=pos)
        self.falling_stuff = falling_stuff
        self.score = 0

    def update(self,0)
        display_rect = pygame.display.get_surface().get_rect()
        self.rect.clamp_ip(display_rect)

        for stuff in pygame.sprite.spritecollide(self,self.falling_stuff,True):
            self.score += 1

class FallingStuff(pygame.sprite.Sprite):
    def __init__(self,FALLING_SPEED * dt)
        display_rect = pygame.display.get_surface().get_rect()
        if self.rect.top > display_rect.bottom:
            self.kill()

def main():
    pygame.init()
    screen = pygame.display.set_mode(RESOLUTION)
    dt,pygame.time.Clock()
    sprites = pygame.sprite.Group()
    falling_stuff = pygame.sprite.Group()
    player = Player((300,sprites)
    font = pygame.freetype.SysFont('Arial',54)

    CREATE_STUFF = pygame.USEREVENT + 1
    pygame.time.set_timer(CREATE_STUFF,True)
    while True:
        events = pygame.event.get()
        for e in events:
            if e.type == pygame.QUIT:
                return
            if e.type == CREATE_STUFF:
                pygame.time.set_timer(CREATE_STUFF,True)
                FallingStuff((randint(50,sprites)
        screen.fill('black')
        font.render_to(screen,(20,20),f'Score: {player.score}','white')
        sprites.update(dt,events)
        sprites.draw(screen)
        pygame.display.flip()
        dt = clock.tick(FPS) / 1000

if __name__ == "__main__":
    main()

enter image description here

动画和命中框也是如此:

import pygame
import pygame.freetype
import os
from random import choice,randint
from itertools import cycle

RESOLUTION = 800,600
FPS = 60
TILESIZE = 32
PLAYER_SPEED = 300
FALLING_SPEED = 400
ANIM_THRESHOLD = 0.05

def load_images(dir):
    path = os.path.dirname(os.path.realpath(__file__))
    path = os.path.join(path,dir)
    for f in os.listdir(path):
        yield pygame.image.load(os.path.join(path,f)).convert_alpha()

class Player(pygame.sprite.Sprite):
    def __init__(self,*grps):
        super().__init__(*grps)
        idle_images = list(load_images('1-Idle'))
        run_images = list(load_images('2-Run'))
        self.images = {
            'IDLE': {
                'RIGHT': cycle(idle_images),'LEFT': cycle(pygame.transform.flip(s,True,False) for s in idle_images)
            },'RUN': {
                'RIGHT': cycle(run_images),False) for s in run_images)
            }
        }
        self.state = 'IDLE'
        self.direction = 'RIGHT'
        self.image = next(self.images['IDLE']['RIGHT'])
        self.animation_counter = 0
        self.rect = self.image.get_rect(topleft=pos)
        self.falling_stuff = falling_stuff
        self.score = 0
        self.hitbox = pygame.Rect(0,30,20)
        self.hitbox.center = self.rect.center
        self.hitbox.move_ip(-10,-10)

    def update_image(self,new_state):
        self.animation_counter += dt
        if self.animation_counter > ANIM_THRESHOLD or self.state != new_state:
            self.image = next(self.images[new_state][self.direction])
            self.animation_counter = 0

    def update(self,0)
        display_rect = pygame.display.get_surface().get_rect()
        self.rect.clamp_ip(display_rect)

        if d == 1:
            new_state = 'RUN'
            self.direction = 'RIGHT'
        if d == -1:
            new_state = 'RUN'
            self.direction = 'LEFT'
        if d == 0:
            new_state = 'IDLE'

        for stuff in self.falling_stuff:
            if self.hitbox.colliderect(stuff.rect):
                stuff.kill()
                self.score += 1

        self.update_image(dt,new_state)
        self.state = new_state
        
        self.hitbox.center = self.rect.center
        self.hitbox.move_ip(10 if self.direction == 'LEFT' else -10,-10)
        pygame.draw.rect(pygame.display.get_surface(),'red',self.hitbox,2)

class FallingStuff(pygame.sprite.Sprite):
    def __init__(self,'white')
        sprites.draw(screen)
        sprites.update(dt,events)
        pygame.display.flip()
        dt = clock.tick(FPS) / 1000

if __name__ == "__main__":
    main()

enter image description here

Sprites by Pixel Frog

,

首先,您应该考虑使用“ae、oe、ue”或仅使用英文翻译而不是“ä、ö、ü”,这可能会导致一些问题。另外,你为什么不包括pygame? 其次,尽量不要对窗口大小使用固定值,如果以后要更改它,则必须更改几个值,并且忘记一个值时很容易遇到问题。我建议您使用宽度和高度变量,您可以稍后更改。

但是对于您的具体问题: 我认为你没有看到任何物体坠落的原因是没有物体。实际运行的代码部分在 while 循环中,只要我没有遗漏任何东西,就不会出现任何关于掉落物体的信息,也不会关于它们掉落的信息(任何类型的加速度或速度)。 此外,我强烈建议(如“oskros”的评论已经说过)在询问之前测试您的代码。这也是编程的一个重要部分,可以像这样完成,例如: 你进入每个函数并在那里写一个“打印”语句,所以你知道这个函数已经运行(通过控制台上的输出)。如果没有运行,请尝试查看它应该运行的点并从该点继续修复。 您基本上可以将这种技术应用于任何调试,stackoverflow 主要用于询问更具体的问题,而不是“为什么这不起作用,您能修复我的代码吗?” (至少对于整个程序而言)

,
import pygame.freetype
from random import choice,randint
pygame.init()

RESOLUTION = 900,780
FPS = 60
TILESIZE = 32
PLAYER_SPEED = 600
FALLING_SPEED = 400

coin = pygame.image.load('coin.png')
coin = pygame.transform.scale(coin,(60,60))

sack = pygame.image.load('sack.png')
sack = pygame.transform.scale(sack,60))

money = pygame.image.load('schein.png')
money = pygame.transform.scale(money,60))

char = pygame.image.load ("L1.png")

walkRight = [pygame.image.load('Assets/R1.png'),pygame.image.load('Assets/R2.png'),pygame.image.load('Assets/R3.png')]


bg = pygame.image.load('City.jpg')
bg = pygame.transform.scale(bg,(900,780))

pygame.mixer.music.load('Music/Titel.mp3')
pygame.mixer.music.play(0)

class Player(pygame.sprite.Sprite):
    def __init__(self,*grps):
        super().__init__(*grps)
        self.image = char
        self.rect = self.image.get_rect(topleft=pos)
        self.falling_stuff = falling_stuff
        self.score = 0

    def update(self,events):
        d = 0
        pressed = pygame.key.get_pressed()
        if pressed[pygame.K_LEFT]: d -= 1
        if pressed[pygame.K_RIGHT]: d += 1

        self.rect.move_ip(d * dt * PLAYER_SPEED,*grps):
        super().__init__(*grps)
        self.image = choice([coin,sack,money])
        self.rect = self.image.get_rect(topleft=pos)
        
    def update(self,pygame.time.Clock()
    sprites = pygame.sprite.Group()
    falling_stuff = pygame.sprite.Group()
    player = Player((400,700),sprites)
    font = pygame.freetype.SysFont('ComicSans',70)

    CREATE_STUFF = pygame.USEREVENT + 1
    pygame.time.set_timer(CREATE_STUFF,sprites)

        screen.blit(bg,(0,0))
        font.render_to(screen,(30,30),events)
        sprites.draw(screen)
        pygame.display.flip()
        dt = clock.tick(FPS) / 1000

    

if __name__ == "__main__":
    main() 

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。