因此,我一直在使用第一个答案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))
该脚本已经有一个冲突方法,我在这里添加了最后三行:
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上时,对话气泡的图像会被渗入屏幕。相反,发生的情况是,当播放器站在SpeechBlock的边缘时,图像会出现一会儿,然后消失,然后再出现一会儿,依此类推...
我做错了什么?我是pygame的新手,所以我真的不太了解blit和显示更新/翻转的工作原理。任何帮助将不胜感激。
最佳答案
您必须了解您的游戏是循环运行的。此循环的每次迭代称为一个框架。在每一帧中,您都需要清理屏幕上的所有内容,处理任何事件,更新游戏世界并再次绘制所有内容。
因此,当您调用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秒。