--- a/angrydd.py +++ b/angrydd.py @@ -23,34 +23,10 @@ __license__ = "GNU GPL v2" __author__ = "Joe Wreschnig " +import pygame import os import sys - -def print_help(): - print("""\ -Usage: %s [ --debug | --help | --version ] -Options: - --help, -h Print this help message and exit. - --version, -v Print version and copyright information and exit. - --debug Start without Psyco support, for profiling and debugging. - --profile Start with profiling (implies --debug). -""" %( - sys.argv[0])) - raise SystemExit - -def print_version(): - print("""\ -Angry Drunken Dwarves %s - a falling block puzzle game -Copyright 2004 %s - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU GPL version 2, as published -by the Free Software Foundation.""" % (__version__, __author__)) - raise SystemExit - -if __name__ == "__main__": - if ("--help" in sys.argv) or ("-h" in sys.argv): print_help() - elif ("--version" in sys.argv) or ("-v" in sys.argv): print_version() +import asyncio angrydd_path = os.path.split(os.path.realpath(__file__))[0] if os.path.exists(os.path.join(angrydd_path, "angrydd.zip")): @@ -66,18 +42,13 @@ # Toggling fullscreen doesn't work on non-X11 platforms as of Pygame 1.7. def toggle_fs(): - flags = 0 - fs = config.getboolean("settings", "fullscreen") ^ True - if "linux" not in sys.platform: - if fs: flags ^= FULLSCREEN - pygame.display.set_mode([800, 600], flags) - else: pygame.display._toggle_fullscreen() - config.set("settings", "fullscreen", str(fs)) + # Full screen is left to the web page, not the game + pass pygame.display._toggle_fullscreen = pygame.display.toggle_fullscreen pygame.display.toggle_fullscreen = toggle_fs -def main(): +async def main(): from characters import Character init() @@ -85,6 +56,10 @@ import menu import howtoplay import unlocker + while True: + await main_menu_loop(Character, menu, howtoplay, unlocker) + +async def main_menu_loop(Character, menu, howtoplay, unlocker): main_menu = [ ("Dwarf versus Dwarf", menu.entry(play_game, False)), ("Arcade Mode", menu.entry(play_arcade_game, False)), @@ -106,52 +81,56 @@ if len(Character.arcade) != 8: main_menu = [main_menu[0]] + main_menu[2:] - menu.Menu(main_menu) - quit() + await menu.Menu().run(main_menu) + # "Quit Game" only saves and starts over: there is nowhere to quit to + save_config() # Start a player vs. player game -def play_game(menu, platform, pos, key): +async def play_game(menu, platform, pos, key): import game, charselect - characters = charselect.init() + characters = await charselect.init() if characters[0] is not None: - game.VersusGame(characters) + await game.VersusGame().start(characters) mixer.music.load(os.path.join("music", "intro.ogg")) mixer.music.play(-1) + save_config() return True # Start a single player game -def play_single_game(menu, platform, pos, key): +async def play_single_game(menu, platform, pos, key): import game - game.SingleGame() + await game.SingleGame().start() mixer.music.load(os.path.join("music", "intro.ogg")) mixer.music.play(-1) + save_config() return True # Start a game versus an AI -def play_ai_game(menu, platform, pos, key): +async def play_ai_game(menu, platform, pos, key): import game, charselect - characters = charselect.init() + characters = await charselect.init() if characters[0] is not None: - game.AIGame(characters) + await game.AIGame().start(characters) mixer.music.load(os.path.join("music", "intro.ogg")) mixer.music.play(-1) + save_config() return True -def play_arcade_game(menu, platform, pos, key): +async def play_arcade_game(menu, platform, pos, key): import game, charselect - characters = charselect.init(numplayers = 1) + characters = await charselect.init(numplayers = 1) if characters[0] is not None: - game.ArcadeGame(characters) + await game.ArcadeGame().start(characters) mixer.music.load(os.path.join("music", "intro.ogg")) mixer.music.play(-1) + save_config() return True # Open the configuration menu -def setup(menu_, platform, pos, key): +async def setup(menu_, platform, pos, key): import menu config_menu = [ (config.get_matches(), menu.entry(config.set_matches)), - (config.get_fullscreen(), menu.entry(config.set_fullscreen)), (config.get_speed(), menu.entry(config.set_speed)), (config.get_rotup(), menu.entry(config.set_rotup)), (config.get_space(), menu.entry(config.set_space)), @@ -166,8 +145,8 @@ config_menu.insert(-1, (config.get_combat(), menu.entry(config.set_combat))) - try: menu.Menu(config_menu) - except menu.MenuExit: pass + await menu.Menu().run(config_menu) + save_config() return True # Set up Pygame, load sounds, etc. @@ -183,8 +162,7 @@ try: pygame.display.set_icon(pygame.image.load("angrydd.png")) except pygame.error: pass pygame.mouse.set_visible(False) - if config.getboolean("settings", "fullscreen"): flags = FULLSCREEN - else: flags = 0 + flags = 0 pygame.display.set_mode([800, 600], flags) import game @@ -211,37 +189,14 @@ mixer.music.load(os.path.join("music", "intro.ogg")) mixer.music.play(-1) -# Shut down Pygame, save configuration data, turn on the Unlocker. -def quit(*args): - pygame.quit() - print("Saving configuration.") +# Save configuration data, turn on the Unlocker. +def save_config(*args): config.unlock("unlocker") if int(config.get("scores-versus-3", "1").split(",")[1]) > 20000: config.unlock("single") - config.write(open(rc_file, "w")) - raise SystemExit + try: + with open(rc_file, "w") as f: config.write(f) + except OSError: + print("Could not save the configuration.") -if __name__ == "__main__": - profile = ("--profile" in sys.argv) - debug = profile or ("--debug" in sys.argv) - double_ai = ("--double-ai" in sys.argv) - - if not debug: - try: - import psyco - psyco.full() - print("Psyco optimizing compiler found. Using psyco.full().") - except ImportError: pass - - if profile: - import profile - profile.run("main()") - elif double_ai: - # Hack to run two AIs versus each other; use --double-ai AI1,Ai2 - # on the command line. Bypasses main(), very buggy, for testing - # use only. - init() - ai1, ai2 = sys.argv[sys.argv.index("--double-ai") + 1].split(",") - game.AIGame([Character.available[0], Character.available[0]], - all_ais = True, ai1 = ai1, ai2 = ai2) - else: main() +asyncio.run(main()) --- a/charselect.py +++ b/charselect.py @@ -17,7 +17,7 @@ # Display the character selection screen; return the two selected # characters (or None, None when escape was pressed). -def init(numplayers = 2): +async def init(numplayers = 2): screen = pygame.display.get_surface() em = EventManager() bg = load.image("select-bg.png") @@ -44,14 +44,14 @@ init_bg = bg.convert() sprites.update(pygame.time.get_ticks()) sprites.draw(init_bg) - wipes.wipe_in(init_bg) + await wipes.wipe_in(init_bg) init_bg = None # Let us GC it pygame.display.update() sprites.clear(screen, bg) while False in [(c.confirmed or i >= numplayers) for i, c in enumerate(portraits)]: - for ev in em.wait(): + for ev in await em.wait(): if ev.type == PLAYER: if ev.key == LEFT: i = (idx[ev.player] - 1) % len(Character.available) --- a/config.py +++ b/config.py @@ -58,8 +58,6 @@ _config.set("scores-versus-%d" % c, str(n), "%s,%d" % (name, score)) - if os.name == "posix": rc_file = os.environ["HOME"] + "/.angryddrc" - else: rc_file = "angryddrc" _config.read([rc_file]) if _config.getboolean("settings", "rotate_on_space") is False: --- a/constants.py +++ b/constants.py @@ -16,7 +16,10 @@ if angrydd_path.lower().endswith(".zip"): angrydd_path = os.path.split(angrydd_path)[0] -if os.name == "posix" and "HOME" in os.environ: +if os.path.isdir("/saves"): + # on the web the page keeps the /saves folder in the browser + rc_file = "/saves/angryddrc" +elif os.name == "posix" and "HOME" in os.environ: rc_file = os.environ["HOME"] + "/.angryddrc" else: rc_file = os.path.join(angrydd_path, "angryddrc") --- a/events.py +++ b/events.py @@ -3,6 +3,7 @@ # Released under the terms of the GNU GPL v2. __revision__ = "$Id: events.py 317 2006-01-12 21:19:27Z piman $" +import asyncio from constants import * from pygame import event, key, joystick, time, display from pygame.event import Event @@ -63,10 +64,10 @@ event.clear() # This isn't a very good "wait" function. - def wait(self): + async def wait(self): while not event.peek([KEYDOWN, JOYBUTTONDOWN, JOYAXISMOTION, JOYBUTTONUP, QUIT]): - time.wait(10) + await asyncio.sleep(0.01) return self.get() # Get all events in the Pygame event queue and translate them @@ -80,9 +81,7 @@ key = self.events[ev.key], player = self.players[ev.key])) except KeyError: - if ev.key == K_F11 or ev.key == K_f: - display.toggle_fullscreen() - elif ev.key == K_p: + if ev.key == K_p: events.append(Event(PAUSE)) elif ev.key == K_ESCAPE: events.append(Event(QUIT)) --- a/game.py +++ b/game.py @@ -996,12 +996,10 @@ self._em = EventManager() self._pickaxe = load.image("pickaxe.png") self._light_axe = self._pickaxe.copy() - alphs = pygame.surfarray.pixels_alpha(self._light_axe) - for row in alphs: - for i in range(len(row)): row[i] = row[i] // 2 - del(alphs) + # (half the opacity, without numpy) + self._light_axe.fill([255, 255, 255, 128], None, pygame.BLEND_RGBA_MULT) - def play(self, matches, wins): + async def play(self, matches, wins): seed = pygame.time.get_ticks() screen = pygame.display.get_surface() @@ -1061,11 +1059,11 @@ for p in self._players: pygame.display.update(p.sprites.draw(screen)) - pygame.time.clock.tick(60) + await pygame.time.clock.tick(60) pygame.key.set_repeat(200, 75) events.DELAY = 200 - def block_out(self): + async def block_out(self): try: pygame.mixer.music.fadeout(1000) except: pass dead_snd = load.sound("death.wav") @@ -1079,11 +1077,11 @@ pygame.display.update(self._screen.blit( self._players[i].dead_image, self._players[i].topleft)) - pygame.time.clock.tick(60) + await pygame.time.clock.tick(60) t = pygame.time.get_ticks() self._screen.set_clip() - def wait_reset(self, text, char): + async def wait_reset(self, text, char): cont = True last = pygame.time.get_ticks() screen = pygame.display.get_surface() @@ -1104,28 +1102,27 @@ r = border.get_rect(center = [400, 100]) pygame.display.update(screen.blit(border, r)) last = t - pygame.time.clock.tick(60) + await pygame.time.clock.tick(60) for p in self._players: p.reset() #pygame.mixer.music.stop() #pygame.mixer.music.set_volume(1.0) class SingleGame(Game): - def __init__(self): - Game.__init__(self) + async def start(self): self._players = [SinglePlayer(0, Character.default)] player = self._players[0] screen = pygame.display.get_surface() bkg = player.char.images["background"] try: pygame.mixer.music.fadeout(2000) except pygame.error: pass - wipes.wipe_in(bkg) + await wipes.wipe_in(bkg) screen.blit(bkg, [0, 0]) pygame.mixer.music.load(os.path.join("music", "single.ogg")) pygame.mixer.music.play(-1) player.dead = True - self.play(0, [0, 0]) - self.block_out() + await self.play(0, [0, 0]) + await self.block_out() text = "Game Over!" text = textfx.TextWavey(50, text, [255, 255, 255], amount = 5) @@ -1135,7 +1132,7 @@ screen.blit(statbox, statbox_r) pygame.display.update() - self.wait_reset(text, player.char) + await self.wait_reset(text, player.char) sec = "scores-single" score = player.score.score @@ -1159,8 +1156,7 @@ r = screen.blit(surf, [80, 440]) screen.blit(textfx.shadow(string, 32), [100, 475]) pygame.display.update(r) - ev = pygame.event.wait() - while ev.type != KEYDOWN: ev = pygame.event.wait() + ev = await util.wait_keydown() if ev.key == K_ESCAPE or ev.key == K_RETURN: break elif ev.key == K_BACKSPACE: string = string[:-1] elif ev.unicode == ",": pass @@ -1172,8 +1168,7 @@ check_unlock(player) class VersusGame(Game): - def __init__(self, chars): - Game.__init__(self) + async def start(self, chars): matches = config.getint("settings", "matches") wins = [0] * len(chars) self._players = [VersusPlayer(i, c) for i,c in enumerate(chars)] @@ -1182,7 +1177,7 @@ for match in range(matches): bkg = random.choice([p.char.images["background"] for p in self._players]) - wipes.wipe_in(bkg) + await wipes.wipe_in(bkg) screen.blit(bkg, [0, 0]) pygame.display.update() f = FightSprite(match, matches) @@ -1194,14 +1189,14 @@ self._sprites.update(pygame.time.get_ticks()) pygame.display.update(self._sprites.draw(screen)) self._sprites.clear(screen, bkg) - pygame.time.clock.tick(60) + await pygame.time.clock.tick(60) pygame.mixer.music.load(os.path.join("music", "versus-1.ogg")) pygame.mixer.music.play(-1) - self.play(matches, wins) + await self.play(matches, wins) if True not in [p.dead for p in self._players]: break else: - self.block_out() + await self.block_out() try: winner = self._players[[p.dead @@ -1213,7 +1208,7 @@ wins[winner._pid] += 1 check_unlock(*self._players) if wins[winner._pid] > matches / 2: - WinScreen(winner, matches) + await WinScreen(winner, matches) break text = "%s wins!" % (winner.char.name.split()[0]) @@ -1224,11 +1219,10 @@ screen.blit(statbox, statbox_r) pygame.display.update() - self.wait_reset(text, winner.char) + await self.wait_reset(text, winner.char) class ArcadeGame(Game): - def __init__(self, chars): - Game.__init__(self) + async def start(self, chars): matches = 3 player = VersusPlayer(0, chars[0]) screen = pygame.display.get_surface() @@ -1242,12 +1236,12 @@ self._players = players = [player, AIPlayer(1, char, ais[i])] lost = False - self._prebattle() + await self._prebattle() for match in range(matches): bkg = random.choice([p.char.images["background"] for p in self._players]) - wipes.wipe_in(bkg) + await wipes.wipe_in(bkg) screen.blit(bkg, [0, 0]) pygame.display.update() f = FightSprite(match, matches) @@ -1259,16 +1253,16 @@ self._sprites.update(pygame.time.get_ticks()) pygame.display.update(self._sprites.draw(screen)) self._sprites.clear(screen, bkg) - pygame.time.clock.tick(60) + await pygame.time.clock.tick(60) pygame.mixer.music.load(os.path.join("music", "versus-1.ogg")) pygame.mixer.music.play(-1) - self.play(matches, wins) + await self.play(matches, wins) if True not in [p.dead for p in self._players]: quit = True break else: - self.block_out() + await self.block_out() try: winner = list(filter(lambda p: not p.dead, self._players))[0] @@ -1283,9 +1277,9 @@ if winner._pid == 0: if i >= 3: config.unlock("cpuversus") if i == 7: winner.score.score += 10000 - WinScreen(winner, "arcade", to_score = (i == 7)) + await WinScreen(winner, "arcade", to_score = (i == 7)) else: - WinScreen(winner, "arcade", scorer = self._players[0]) + await WinScreen(winner, "arcade", scorer = self._players[0]) lost = True break @@ -1297,11 +1291,11 @@ screen.blit(statbox, statbox_r) pygame.display.update() - self.wait_reset(text, winner.char) + await self.wait_reset(text, winner.char) if lost or quit: break - def _prebattle(self): + async def _prebattle(self): screen = pygame.display.get_surface() em = EventManager() chars = [player.char for player in self._players] @@ -1318,7 +1312,7 @@ txt = textfx.shadow("versus", 40) bkg.blit(txt, txt.get_rect(center = [400, 300])) - wipes.wipe_in(bkg) + await wipes.wipe_in(bkg) screen.blit(bkg, [0, 0]) pygame.display.update() cont = True @@ -1328,11 +1322,10 @@ (ev.type == PLAYER and (ev.key in [CONFIRM, ROT_CC, ROT_CW]))): cont = False - pygame.time.clock.tick(60) + await pygame.time.clock.tick(60) class AIGame(Game): - def __init__(self, chars, all_ais = False, ai1 = None, ai2 = None): - Game.__init__(self) + async def start(self, chars, all_ais = False, ai1 = None, ai2 = None): matches = config.getint("settings", "matches") wins = [0] * len(chars) if all_ais: @@ -1346,7 +1339,7 @@ bkg = random.choice([p.char.images["background"] for p in self._players]) screen = pygame.display.get_surface() - wipes.wipe_in(bkg) + await wipes.wipe_in(bkg) screen.blit(bkg, [0, 0]) pygame.display.update() f = FightSprite(match, matches) @@ -1358,14 +1351,14 @@ self._sprites.update(pygame.time.get_ticks()) pygame.display.update(self._sprites.draw(screen)) self._sprites.clear(screen, bkg) - pygame.time.clock.tick(60) + await pygame.time.clock.tick(60) pygame.mixer.music.load(os.path.join("music", "versus-1.ogg")) pygame.mixer.music.play(-1) - self.play(matches, wins) + await self.play(matches, wins) if True not in [p.dead for p in self._players]: break else: - self.block_out() + await self.block_out() winner = self._players[[p.dead for p in self._players].index(False)] @@ -1373,7 +1366,7 @@ wins[winner._pid] += 1 if wins[winner._pid] > matches / 2: - WinScreen(winner, matches, scorer = self._players[0]) + await WinScreen(winner, matches, scorer = self._players[0]) break text = "%s wins!" % (winner.char.name.split()[0]) @@ -1384,15 +1377,15 @@ screen.blit(statbox, statbox_r) pygame.display.update() - self.wait_reset(text, winner.char) + await self.wait_reset(text, winner.char) -def WinScreen(winner, score_sec, to_score = True, scorer = None): +async def WinScreen(winner, score_sec, to_score = True, scorer = None): em = EventManager() if scorer is None: scorer = winner screen = pygame.display.get_surface() print("Player %d wins!" % (winner._pid + 1)) - wipes.wipe_out() - wipes.wipe_in(winner.char.images["background"]) + await wipes.wipe_out() + await wipes.wipe_in(winner.char.images["background"]) font = textfx.WrapFont(30, 400) text = font.render(random.choice(winner.char.quips)) box = winner.char.border([text.get_width() + 20, text.get_height() + 20]) @@ -1410,7 +1403,7 @@ cont = True while cont: - for ev in em.wait(): + for ev in await em.wait(): if (ev.type == QUIT or (ev.type == PLAYER and (ev.key in [CONFIRM, ROT_CC, ROT_CW]))): @@ -1440,8 +1433,7 @@ r = screen.blit(surf, [80, 440]) screen.blit(textfx.shadow(string + "_", 32), [100, 475]) pygame.display.update(r) - ev = pygame.event.wait() - while ev.type != KEYDOWN: ev = pygame.event.wait() + ev = await util.wait_keydown() if ev.key == K_ESCAPE or ev.key == K_RETURN: break elif ev.key == K_BACKSPACE: string = string[:-1] elif ev.unicode == ",": pass --- a/howtoplay.py +++ b/howtoplay.py @@ -19,7 +19,7 @@ # Display the "how to play" screen (with appropriate unlocks enabled). # FIXME: This is pretty messy; the text belongs in a data file rather # than inline. -def init(*args): +async def init(*args): em = EventManager() screen = pygame.display.get_surface() move_snd = load.sound("select-move.wav") @@ -175,7 +175,7 @@ images.append([None, img1, img2]) - wipes.wipe_in(render_help_page(texts[index], images[index])) + await wipes.wipe_in(render_help_page(texts[index], images[index])) cont = True screen.blit(render_help_page(texts[index], images[index]), [0, 0]) @@ -185,7 +185,7 @@ pygame.display.update() while cont: oldindex = index - for ev in em.wait(): + for ev in await em.wait(): if ev.type == QUIT: cont = False elif ev.type == PLAYER: if ev.key == CONFIRM: cont = False --- a/menu.py +++ b/menu.py @@ -3,6 +3,7 @@ # Released under the terms of the GNU GPL v2. __revision__ = "$Id: menu.py 306 2005-10-06 19:46:26Z piman $" +import inspect import pygame from pygame.sprite import Sprite, RenderUpdates @@ -114,7 +115,7 @@ # A menu; a bunch of boxes displayed on carts, with callbacks class Menu(object): - def __init__(self, items): + async def run(self, items): platforms = [Platform([400 + 260 * i, 390], s[0], i) for i, s in enumerate(items)] credits = Credits() @@ -149,6 +150,7 @@ try: r = items[pos][1][ev.key](self, platforms[pos], pos, ev.key) + if inspect.isawaitable(r): r = await r if r: # If the callback returns true, then we # need to redraw the whole screen and @@ -165,7 +167,7 @@ sprites.update(pygame.time.get_ticks()) pygame.display.update(sprites.draw(screen)) sprites.clear(screen, Menu.bg) - pygame.time.clock.tick(60) + await pygame.time.clock.tick(60) # The most common kind of menu entry, a single callback function # that we call when certain keys are pressed. --- a/unlocker.py +++ b/unlocker.py @@ -16,7 +16,7 @@ # Display help text for unlocked features. This includes a lot of # verbatim text we should move to a data file somewhere. -def init(*args): +async def init(*args): em = EventManager() disp = pygame.Surface([800, 600]) @@ -85,11 +85,11 @@ bg.set_alpha(127) disp.blit(bg, [0, 480]) - wipes.wipe_in(disp) + await wipes.wipe_in(disp) pygame.display.update() quit = False while not quit: - for ev in em.wait(): + for ev in await em.wait(): quit = (quit or ev.type == QUIT or (ev.type == PLAYER and --- a/util.py +++ b/util.py @@ -3,6 +3,7 @@ # Released under the terms of the GNU GPL v2. __revision__ = "$Id: util.py 286 2004-09-04 03:51:59Z piman $" +import asyncio import pygame # Implement the singleton pattern. Requires Python 2.3. @@ -32,8 +33,16 @@ self._time = time_func self._last_tick = 0 - def tick(self, fps = 60): + async def tick(self, fps = 60): t = self._time() sleep = (1000 // fps) - (t - self._last_tick) self._last_tick = t - if sleep > 0: pygame.time.wait(sleep) + # (yield to the browser instead of blocking) + await asyncio.sleep(max(sleep, 0) / 1000.0) + +# Wait for a key press, giving the browser time to run in between. +async def wait_keydown(): + while True: + for ev in pygame.event.get(): + if ev.type == pygame.KEYDOWN: return ev + await asyncio.sleep(0.01) --- a/wipes.py +++ b/wipes.py @@ -3,70 +3,76 @@ # Released under the terms of the GNU GPL v2. __revision__ = "$Id: wipes.py 286 2004-09-04 03:51:59Z piman $" +import asyncio import random from pygame import display, draw, time, Rect, Surface from itertools import chain -c = time.Clock() +_n = 0 +async def _tick(): + # one browser frame for every dozen lines drawn + global _n + _n += 1 + if _n % 12 == 0: await asyncio.sleep(0) -def line_out_l2r(): +async def line_out_l2r(): screen = display.get_surface() w, h = screen.get_size() for x in chain(range(0, w, 2), range(w - 1, 0, -2)): display.update(draw.line(screen, [0, 0, 0], [x, 0], [x, h])) - c.tick(700) + await _tick() -def line_out_r2l(): +async def line_out_r2l(): screen = display.get_surface() w, h = screen.get_size() for x in chain(range(w - 1, 0, -2), range(0, w, 2)): display.update(draw.line(screen, [0, 0, 0], [x, 0], [x, h])) - c.tick(700) + await _tick() -def line_out_t2b(): +async def line_out_t2b(): screen = display.get_surface() w, h = screen.get_size() for y in chain(range(0, h, 2), range(h - 1, 0, -2)): display.update(draw.line(screen, [0, 0, 0], [0, y], [w, y])) - c.tick(700) + await _tick() -def line_out_b2t(): +async def line_out_b2t(): screen = display.get_surface() w, h = screen.get_size() for y in chain(range(h - 1, 0, -2), range(0, h, 2)): display.update(draw.line(screen, [0, 0, 0], [0, y], [w, y])) - c.tick(700) + await _tick() -def line_in_l2r(surf): +async def line_in_l2r(surf): screen = display.get_surface() w, h = screen.get_size() for x in chain(range(0, w, 2), range(w - 1, 0, -2)): display.update(screen.blit(surf, [x, 0, 1, h], [x, 0, 1, h])) - c.tick(700) + await _tick() -def line_in_r2l(surf): +async def line_in_r2l(surf): screen = display.get_surface() w, h = screen.get_size() for x in chain(range(w - 1, 0, -2), range(0, w, 2)): display.update(screen.blit(surf, [x, 0, 1, h], [x, 0, 1, h])) - c.tick(700) + await _tick() -def line_in_t2b(surf): +async def line_in_t2b(surf): screen = display.get_surface() w, h = screen.get_size() for y in chain(range(0, h, 2), range(h - 1, 0, -2)): display.update(screen.blit(surf, [0, y, w, 1], [0, y, w, 1])) - c.tick(700) + await _tick() -def line_in_b2t(surf): +async def line_in_b2t(surf): screen = display.get_surface() w, h = screen.get_size() for y in chain(range(h - 1, 0, -2), range(0, h, 2)): display.update(screen.blit(surf, [0, y, w, 1], [0, y, w, 1])) - c.tick(700) + await _tick() OUTS = [line_out_l2r, line_out_r2l, line_out_b2t, line_out_t2b] INS = [line_in_l2r, line_in_r2l, line_in_b2t, line_in_t2b] -def wipe_out(): random.choice(OUTS)() -def wipe_in(s): random.choice(INS)(s) +async def wipe_out(): await random.choice(OUTS)() +async def wipe_in(s): await random.choice(INS)(s)