PyGame自定义事件 [英] PyGame Custom Event

查看:1118
本文介绍了PyGame自定义事件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想询问pygame中使用自定义事件。


我用pygame进行了一些实验,所以我知道pygame生成的事件是如何工作的。


我的问题是,为什么有人对用户事件感兴趣,它是否有助于简化

组合pygame-events
?和某人如何实现,而且在现实世界的例子中受益于



我在我最近读过的一本书 ..



 #创建事件
CATONKEYBOARD = USEREVENT + 1
my_event = pygame.event.Event(CATONKEYBOARD,message =Bad cat!)
pygame.event.post(my_event)

#处理它
pygame.event.get()中的事件:
如果event.type == CATONKEYBOARD:
print event.message



我尝试过,我发现事件只产生一次(一旦发布) <可以有人向我解释吗?

谢谢..

解决方案

您可以发布自定义事件或者手动使用 pygame.event.post ,如您的示例所示。



此外,您可以使用 pygame.time.set_timer 在特定时间间隔发布自定义事件。以下是另一个问题的一个示例,其中使用自定义事件来移动对象并控制重新加载超时: / p>

  import pygame 

#你将能够每450ms
拍摄RELOAD_SPEED = 450

#对手每1000ms侧向移动,每3500ms下降
MOVE_SIDE = 1000
MOVE_DOWN = 3500

screen = pygame.display.set_mode((300,200))
clock = pygame.time.Clock()

pygame.display.set_caption(Micro Invader)

#创建一堆事件
move_side_event = pygame.USEREVENT + 1
move_down_event = pygame.USEREVENT + 2
reloaded_event = pygame.USEREVENT + 3

move_left,reloaded = True,True

入侵者,颜色,镜头= [],[],[]
范围内的x(15,300,15):
对于y在范围(10,100,15) )
invaders.append(pygame.Rect(x,y,7,7))
colors.append(((x * 0.7)%256,(y * 2.4)%256))

#为运动事件设置定时器
pygame.time.set_timer(move_side_event,MOVE_SIDE)
pygame.time.set_timer(move_down_event,MOVE_DOWN)

player = pygame.Rect(150,180,10,7)

while True:
clock.tick(40)
如果pygame.event.get(pygame.QUIT) :pygame.event.get()中的$ break

如果e.type == move_side_event:入侵者中的入侵者

invader.move_ip(( - 10 if
move_left = not move_left
elif e.type == move_down_event:入侵者中的入侵者

invader.move_ip(0,10)
elif e.type == reloaded_event:
#当重新加载定时器用完时,重置它
reloaded = True
pygame.time.set_timer(reloaded_event,0)

为拍摄照片[:]:
shot.move_ip((0,-4))
如果不是screen.get_rect()。包含(shot):
shotts删除(shot)
else:
hit = False
入侵者的入侵者[:]:
如果invader.colliderect(shot):
hit = True
i =入侵者。 index(invader)
del colors [i]
del invaders [i]
如果命中:
shotts.remove(shot)

ressed = pygame .key.get_pressed()
如果按[pygame.K_LEFT]:player.move_ip(( - 4,0))
如果按[pygame.K_RIGHT]:player.move_ip((4,0) )

如果按[pygame.K_SPACE]:
如果重新加载:
shotts.append(player.copy())
reloaded = False
#当拍摄时,创建一个超时的RELOAD_SPEED
pygame.time.set_timer(reloaded_event,RELOAD_SPEED)

player.c lamp_ip(screen.get_rect())

screen.fill((0,0,0))

为入侵者,(a,b)为zip(入侵者,颜色)
pygame.draw.rect(screen,(150,a,b),invader)

用于拍摄照片:
pygame.draw.rect(screen 255,180,0),shot)

pygame.draw.rect(屏幕,(180,180,180),播放器)
pygame.display.flip()







在适合发布事件的条件下,以便自动生成它?我认为这样会更实用...


实现这样一个功能很容易。只需创建条件和事件列表,并检查主循环中的每个条件:

  conditions = [#闪烁如果播放器在外面屏幕
(lambda:not s_r.contains(player),pygame.event.Event(E_OUTSIDE)),
#如果鼠标如果超过播放器然后增长和收缩播放器
(lambda:player。 collidepoint(pygame.mouse.get_pos()),pygame.event.Event(E_MOUSE))]

while True:
#从条件生成事件
map(pygame.event .post,[e for(c,e)在条件中如果c()])

在pygame.event.get()中的事件:
...

以下是完整示例:



  import pygame 

pygame.init()

screen = pygame.display.set_mode((300,300))
s_r = screen.get_rect()
player = pygame.Rect((100,100,50,50))
tim er = pygame.time.Clock()
flash = 0
grow = True
color = pygame.color.Color('Black')

E_OUTSIDE = pygame .USEREVENT + 1
E_MOUSE = pygame.USEREVENT + 2

条件= [#如果播放器在屏幕外面,$闪烁
(lambda:not s_r.contains(player),pygame。 event.Event(E_OUTSIDE)),
#如果鼠标超过播放器然后增长和收缩播放器
(lambda:player.collidepoint(pygame.mouse.get_pos()),pygame.event.Event(E_MOUSE )]

while True:
#从条件生成事件
map(pygame.event.post,[e for(c,e))条件如果c()] )

pygame.event.get()中的事件:
如果event.type == pygame.QUIT:
raise
elif event.type == E_OUTSIDE而不是flash:
flash = 5
elif event.type == E_MOUSE:
如果成长:
player.inflate_ip(4,4)
grow = player。宽度< 75
else:
player.inflate_ip(-4,-4)
grow = player.width< 50

flash = max(flash - 1,0)
如果flash%2:
color = pygame.color.Color('White')

pressed = pygame.key.get_pressed()
l,r,u,d = map(lambda x:x * 4,[在压缩[k] for k在pygame.K_a,pygame.K_d,pygame.K_w ,pygame.K_s])
player.move_ip(( - l + r,-u + d))

screen.fill(color)
color = pygame.color。 Color('Black')

pygame.draw.rect(screen,pygame.color.Color('Gray'),player)

pygame.display.flip()
timer.tick(25)


I want to ask about the use of custom events in pygame ..
I experimented a little with pygame, so I know how usual pygame-generated events works ..
My Question is, why would anyone be interested in a user event, does it help simplify
combined pygame-events
? And how would someone implement it, and benefit from
it
in a real world example .. ?

I found an example in a book I have been reading lately ..

# creating the event
CATONKEYBOARD = USEREVENT+1
my_event = pygame.event.Event(CATONKEYBOARD, message="Bad cat!")
pygame.event.post(my_event)

# handling it
for event in pygame.event.get():
    if event.type == CATONKEYBOARD:
        print event.message


I tried it, and I found that the event generates only one time (as soon as it gets posted)
Can anybody explain things to me .. ?

Thanks ..

解决方案

You can post custom events either manually with pygame.event.post, as shown in your example.

Also, you can use pygame.time.set_timer to post a custom event at specific time intervalls. Here's a little example I wrote for another question, where custom events are used to move objects and to control a reload timeout:

import pygame

# you'll be able to shoot every 450ms
RELOAD_SPEED = 450

# the foes move every 1000ms sideways and every 3500ms down
MOVE_SIDE = 1000
MOVE_DOWN = 3500

screen = pygame.display.set_mode((300, 200))
clock = pygame.time.Clock()

pygame.display.set_caption("Micro Invader")

# create a bunch of events 
move_side_event = pygame.USEREVENT + 1
move_down_event = pygame.USEREVENT + 2
reloaded_event  = pygame.USEREVENT + 3

move_left, reloaded = True, True

invaders, colors, shots = [], [] ,[]
for x in range(15, 300, 15):
    for y in range(10, 100, 15):
        invaders.append(pygame.Rect(x, y, 7, 7))
        colors.append(((x * 0.7) % 256, (y * 2.4) % 256))

# set timer for the movement events
pygame.time.set_timer(move_side_event, MOVE_SIDE)
pygame.time.set_timer(move_down_event, MOVE_DOWN)

player = pygame.Rect(150, 180, 10, 7)

while True:
    clock.tick(40)
    if pygame.event.get(pygame.QUIT): break
    for e in pygame.event.get():
        if e.type == move_side_event:
            for invader in invaders:
                invader.move_ip((-10 if move_left else 10, 0))
            move_left = not move_left
        elif e.type == move_down_event:
            for invader in invaders:
                invader.move_ip(0, 10)
        elif e.type == reloaded_event:
            # when the reload timer runs out, reset it
            reloaded = True
            pygame.time.set_timer(reloaded_event, 0)

    for shot in shots[:]:
        shot.move_ip((0, -4))
        if not screen.get_rect().contains(shot):
            shots.remove(shot)
        else:
            hit = False
            for invader in invaders[:]:
                if invader.colliderect(shot):
                    hit = True
                    i = invaders.index(invader)
                    del colors[i]
                    del invaders[i]
            if hit:
                shots.remove(shot)

    pressed = pygame.key.get_pressed()
    if pressed[pygame.K_LEFT]: player.move_ip((-4, 0))
    if pressed[pygame.K_RIGHT]: player.move_ip((4, 0))

    if pressed[pygame.K_SPACE]: 
        if reloaded:
            shots.append(player.copy())
            reloaded = False
            # when shooting, create a timeout of RELOAD_SPEED
            pygame.time.set_timer(reloaded_event, RELOAD_SPEED)

    player.clamp_ip(screen.get_rect())

    screen.fill((0, 0, 0))

    for invader, (a, b) in zip(invaders, colors): 
        pygame.draw.rect(screen, (150, a, b), invader)

    for shot in shots: 
        pygame.draw.rect(screen, (255, 180, 0), shot)

    pygame.draw.rect(screen, (180, 180, 180), player)    
    pygame.display.flip()


Can't I just "give in" the suitable conditions for posting the event, so that it can generate it automatically then ? I think that way it'd be more practical ...

Implementing such a function is quite easy. Just create a list of conditions and events and check every condition in your main loop:

conditions = [ # blink if player is outside screen
              (lambda: not s_r.contains(player), pygame.event.Event(E_OUTSIDE)),
               # if mouse if over player then grow and shrink player  
              (lambda: player.collidepoint(pygame.mouse.get_pos()), pygame.event.Event(E_MOUSE))]

while True:
    # generate events from conditions
    map(pygame.event.post, [e for (c, e) in conditions if c()])

    for event in pygame.event.get():
       ...

Here's the full example:

import pygame

pygame.init() 

screen = pygame.display.set_mode((300, 300)) 
s_r = screen.get_rect()
player = pygame.Rect((100, 100, 50, 50))
timer = pygame.time.Clock()
flash = 0
grow = True
color = pygame.color.Color('Black')

E_OUTSIDE = pygame.USEREVENT  + 1
E_MOUSE   = pygame.USEREVENT  + 2

conditions = [ # blink if player is outside screen
              (lambda: not s_r.contains(player), pygame.event.Event(E_OUTSIDE)),
               # if mouse if over player then grow and shrink player  
              (lambda: player.collidepoint(pygame.mouse.get_pos()), pygame.event.Event(E_MOUSE))]

while True:
    # generate events from conditions
    map(pygame.event.post, [e for (c, e) in conditions if c()])

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            raise
        elif event.type == E_OUTSIDE and not flash:
            flash = 5
        elif event.type == E_MOUSE:
            if grow: 
                player.inflate_ip(4, 4)
                grow = player.width < 75
            else: 
                player.inflate_ip(-4, -4)
                grow = player.width < 50

    flash = max(flash - 1, 0)
    if flash % 2:
        color = pygame.color.Color('White')                

    pressed = pygame.key.get_pressed()
    l, r, u, d = map(lambda x: x*4, [pressed[k] for k in pygame.K_a, pygame.K_d, pygame.K_w, pygame.K_s])
    player.move_ip((-l + r, -u + d))

    screen.fill(color)
    color = pygame.color.Color('Black')

    pygame.draw.rect(screen, pygame.color.Color('Grey'), player)

    pygame.display.flip()
    timer.tick(25)

这篇关于PyGame自定义事件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆