gpt4 book ai didi

python - 在 pygame 中,当我与某物碰撞并让它停留时,我如何 blit 图像?

转载 作者:太空宇宙 更新时间:2023-11-04 01:51:12 24 4
gpt4 key购买 nike

所以我一直在使用第一个答案 here 中略微修改过的 python 脚本版本我在此处添加了一个名为“SpeechBlock”的类:

    level = [
"PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP",
"P P",
"P P",
"P P",
"P P",
"P P",
"P P",
"P P",
"PPPPPPPPSPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP",]
# build the level
for row in level:
for col in row:
if col == "P":
p = Platform(x, y)
platforms.append(p)
entities.add(p)
if col == "E":
e = ExitBlock(x, y)
platforms.append(e)
entities.add(e)
if col == "S":
s = SpeechBlock(x, y)
platforms.append(s)
entities.add(s

并使其成为一个类:

class SpeechBlock(Platform):
def __init__(self, x, y):
Platform.__init__(self, x, y)
self.image.fill(Color("#0033FF"))
self.x=x
self.y=y

def speak(self):
self.events = [
"test",
]
for row in self.events:
image=pygame.image.load(row+".png")
screen.blit(image, (self.x,self.y))

脚本已经有一个碰撞方法,我在这里添加了最后 3 行:

ef collide(self, xvel, yvel, platforms):
for p in platforms:
if pygame.sprite.collide_rect(self, p):
if isinstance(p, ExitBlock):
pygame.event.post(pygame.event.Event(QUIT))
if xvel > 0:
self.rect.right = p.rect.left
print("collide right")
if xvel < 0:
self.rect.left = p.rect.right
print ("collide left")
if yvel > 0:
self.rect.bottom = p.rect.top
self.onGround = True
self.yvel = 0
if yvel < 0:
self.rect.top = p.rect.bottom
if isinstance(p, SpeechBlock):
SpeechBlock.speak(self)
pygame.display.update()

我想要并且仍然想要实现的是,当玩家站在 SpeechBlock 上方时,一个对话气泡的图像会被 blit 到屏幕上。取而代之的是,当玩家站在 SpeechBlock 的边缘时,图像会出现一小会儿,然后消失,然后再次出现,等等......我做错了什么?我对 pygame 很陌生,所以我不太了解 blitting 和显示更新/翻转的工作原理。任何帮助将不胜感激。

最佳答案

您必须了解您的游戏是循环运行的。此循环的每次迭代称为一个帧。在每一帧中,您都可以清除屏幕上的所有内容、处理任何事件、更新您的游戏世界并重新绘制所有内容。

因此,当您调用 SpeechBlock.speak(self)pygame.display.update() 时,您绘制图像(来自 speak方法)到屏幕,但它们将在下一帧中被删除。

你不应该每帧多次调用 pygame.display.update()。你应该做的是引入一些新的状态来改变 SpeechBlock 在你触摸它时的行为方式。

tl;dr 下面的示例:

import pygame
from pygame import *
import sys

SCREEN_SIZE = pygame.Rect((0, 0, 800, 640))
TILE_SIZE = 32
GRAVITY = pygame.Vector2((0, 0.3))

class CameraAwareLayeredUpdates(pygame.sprite.LayeredUpdates):
def __init__(self, target, world_size):
super().__init__()
self.target = target
self.cam = pygame.Vector2(0, 0)
self.world_size = world_size
if self.target:
self.add(target)

def update(self, *args):
super().update(*args)
if self.target:
x = -self.target.rect.center[0] + SCREEN_SIZE.width/2
y = -self.target.rect.center[1] + SCREEN_SIZE.height/2
self.cam += (pygame.Vector2((x, y)) - self.cam) * 0.05
self.cam.x = max(-(self.world_size.width-SCREEN_SIZE.width), min(0, self.cam.x))
self.cam.y = max(-(self.world_size.height-SCREEN_SIZE.height), min(0, self.cam.y))

def draw(self, surface):
spritedict = self.spritedict
surface_blit = surface.blit
dirty = self.lostsprites
self.lostsprites = []
dirty_append = dirty.append
init_rect = self._init_rect
for spr in self.sprites():
rec = spritedict[spr]
newrect = surface_blit(spr.image, spr.rect.move(self.cam))
if rec is init_rect:
dirty_append(newrect)
else:
if newrect.colliderect(rec):
dirty_append(newrect.union(rec))
else:
dirty_append(newrect)
dirty_append(rec)
spritedict[spr] = newrect
return dirty

def main():
pygame.init()
screen = pygame.display.set_mode(SCREEN_SIZE.size)
pygame.display.set_caption("Use arrows to move!")
timer = pygame.time.Clock()

level = [
"PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP",
"P P",
"P P",
"P P",
"P PPPPPPPPPPP P",
"P P",
"P P",
"P P",
"P PPPPPPPP P",
"P P",
"P PPPPPPP P",
"P PPPPPP P",
"P P",
"P PPPPPPP P",
"P P",
"P PPPPPP P",
"P P",
"P PPPPPPPPPPP P",
"P P",
"P PPPPPPPPPPP P",
"P P",
"P P",
"P P",
"P P",
"PPPPPPPPPSPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP",]


platforms = pygame.sprite.Group()
player = Player(platforms, (TILE_SIZE, TILE_SIZE))
level_width = len(level[0])*TILE_SIZE
level_height = len(level)*TILE_SIZE
entities = CameraAwareLayeredUpdates(player, pygame.Rect(0, 0, level_width, level_height))

# build the level
x = y = 0
for row in level:
for col in row:
if col == "P":
Platform((x, y), entities, platforms)
if col == "S":
SpeechBlock((x, y), entities, platforms)
x += TILE_SIZE
y += TILE_SIZE
x = 0

dt = 0

while 1:
events = pygame.event.get()
for e in events:
if e.type == QUIT:
return
if e.type == KEYDOWN and e.key == K_ESCAPE:
return

entities.update(dt, events)
screen.fill((0, 0, 0))
entities.draw(screen)
pygame.display.update()
dt = timer.tick(60)

class Entity(pygame.sprite.Sprite):
def __init__(self, color, pos, *groups):
super().__init__(*groups)
self.image = Surface((TILE_SIZE, TILE_SIZE))
self.image.fill(color)
self.rect = self.image.get_rect(topleft=pos)

def update(self, dt, events):
pass

class Player(Entity):
def __init__(self, platforms, pos, *groups):
super().__init__(Color("#0000FF"), pos)
self.vel = pygame.Vector2((0, 0))
self.onGround = False
self.platforms = platforms
self.speed = 8
self.jump_strength = 10

def update(self, dt, events):
pressed = pygame.key.get_pressed()
up = pressed[K_UP]
left = pressed[K_LEFT]
right = pressed[K_RIGHT]
running = pressed[K_SPACE]

if up:
# only jump if on the ground
if self.onGround: self.vel.y = -self.jump_strength
if left:
self.vel.x = -self.speed
if right:
self.vel.x = self.speed
if running:
self.vel.x *= 1.5
if not self.onGround:
# only accelerate with gravity if in the air
self.vel += GRAVITY
# max falling speed
if self.vel.y > 100: self.vel.y = 100

if not(left or right):
self.vel.x = 0
# increment in x direction
self.rect.left += self.vel.x * dt/10.
# do x-axis collisions
self.collide(self.vel.x, 0, self.platforms)
# increment in y direction
self.rect.top += self.vel.y * dt/10.
# assuming we're in the air
self.onGround = False;
# do y-axis collisions
self.collide(0, self.vel.y, self.platforms)

def collide(self, xvel, yvel, platforms):
for p in platforms:
if pygame.sprite.collide_rect(self, p):
if isinstance(p, SpeechBlock):
p.trigger()
if xvel > 0:
self.rect.right = p.rect.left
if xvel < 0:
self.rect.left = p.rect.right
if yvel > 0:
self.rect.bottom = p.rect.top
self.onGround = True
self.yvel = 0
if yvel < 0:
self.rect.top = p.rect.bottom

class Platform(Entity):
def __init__(self, pos, *groups):
super().__init__(Color("#DDDDDD"), pos, *groups)

class TextBlock(pygame.sprite.Sprite):
def __init__(self, pos, text, *groups):
super().__init__(*groups)
self.image = Surface((200, 100))
self.rect = self.image.get_rect(center=pos)
self.image.fill(Color("white"))
# todo: don't load font everytime
self.image.blit(pygame.font.SysFont(None, 32).render(text, True, Color("Black")), (10, 10))

class SpeechBlock(Entity):
def __init__(self, pos, *groups):
super().__init__(Color("orange"), pos, *groups)
self.cooldown = 0
self.text = None

def trigger(self):
# do nothing if already triggered
if self.cooldown: return

self.cooldown = 2000
# first group is the entity group
self.text = TextBlock(self.rect.move(0, -150).center, 'Ouch!', self.groups()[0])

def update(self, dt, events):

if self.cooldown:
self.cooldown -= dt
if self.cooldown <= 0:
self.text.kill()
self.text = None
self.cooldown = 0

if __name__ == "__main__":
main()

在这里您可以看到我们创建了一个新的 Entity,当玩家进入 SpeechBlock 时它会显示文本。两秒后,SpeechBlock 调用 kill 将其从游戏中移除。

我还稍微更新了代码以使用增量时间,这样我们就可以轻松检查是否已经过了 2 秒。

enter image description here

关于python - 在 pygame 中,当我与某物碰撞并让它停留时,我如何 blit 图像?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57983559/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com