예제 #1
0
class Pipes:
    GAP = 130
    SPEED = 3

    def __init__(self, game):
        self.game = game
        self.pipe_top = Actor('top', anchor=('left', 'bottom'))
        self.pipe_bottom = Actor('bottom', anchor=('left', 'top'))

    def reset(self):
        pipe_gap_y = random.randint(200, self.game.scene.height - 200)
        self.pipe_top.pos = (self.game.scene.width, pipe_gap_y - self.GAP // 2)
        self.pipe_bottom.pos = (self.game.scene.width,
                                pipe_gap_y + self.GAP // 2)

    def checkcollision(self, sprite):
        return sprite.colliderect(self.pipe_top) or sprite.colliderect(
            self.pipe_bottom)

    def draw(self):
        self.pipe_top.draw()
        self.pipe_bottom.draw()

    def update(self, con):
        self.pipe_top.left -= self.SPEED
        self.pipe_bottom.left -= self.SPEED
        if self.pipe_top.right < 0:
            self.reset()
            if not con.dead:
                con.score += 1
예제 #2
0
class Background:
    image = None
    x = None
    y = None
    bg1 = None
    bg2 = None
    scroll_speed = 1

    def __init__(self, x, y, image, x2, y2, image2):
        self.x = x
        self.y = y
        self.image = image
        self.image2 = image2
        self.bg1 = Actor(image)
        self.bg1.x = x
        self.bg1.y = y
        self.bg2 = Actor(image2)
        self.bg2.x = x2
        self.bg2.y = y2

    def draw(self):
        self.bg1.draw()
        self.bg2.draw()

    def update(self):
        if self.bg1.y > 1854:
            self.bg1.y = -2642
        if self.bg2.y > 1854:
            self.bg2.y = -2642
        self.bg1.y += 1
        self.bg2.y += 1
예제 #3
0
파일: uno_pgz.py 프로젝트: yichin-weng/uno
def draw_players_hands():
    for p, player in enumerate(game.game.players):
        color = 'red' if player == game.game.current_player else 'black'
        text = 'P{} {}'.format(p, 'wins' if game.game.winner == player else '')
        screen.draw.text(text, (0, 300 + p * 130), fontsize=100, color=color)
        for c, card in enumerate(player.hand):
            if player == game.player:
                sprite = card.sprite
            else:
                sprite = Actor('back')
            sprite.pos = (130 + c * 80, 330 + p * 130)
            sprite.draw()
    def draw(self):
        """Draw image and additional artifacts.

        This additionally draws a center point, a coordinate tuple, or
        a bounding rectangle, if the respective attributes have
        been set to a color.
        """
        Actor.draw(self)
        if getattr(self, "center_drawing_color", None) is not None:
            _PGZ.screen.draw.filled_circle(self.center, 5,
                                           self.center_drawing_color)
        if getattr(self, "rect_drawing_color", None) is not None:
            _PGZ.screen.draw.rect(self.rect, self.rect_drawing_color)
        if getattr(self, "pos_drawing_color", None) is not None:
            _PGZ.screen.draw.text(("(%d,%d)" % (round(self.x), round(self.y))),
                                  midtop=(self.center),
                                  color=self.pos_drawing_color)
예제 #5
0
class Hero:
    image = None
    x = None
    y = None
    actor = None
    bullets = []

    def __init__(self, x, y, image):
        self.x = x
        self.y = y
        self.image = image
        self.actor = Actor(image)
        self.actor.x = x
        self.actor.y = y

    def draw(self):
        self.actor.draw()
        for bullet in self.bullets:
            bullet.draw()

    def update(self, enemys):
        for bullet in self.bullets:
            bullet.y -= 6
            # 子弹从画面消失 从数组移除
            if bullet.y < 0:
                self.bullets.remove(bullet)
        return self.checkHeroDead(enemys)

    def on_mouse_move(self, pos):
        self.actor.x = pos[0]
        self.actor.y = pos[1]

    def fire(self, key):
        if key == keys.SPACE:
            bullet = Actor('bullet')
            bullet.x = self.actor.x
            bullet.y = self.actor.y - 100
            self.bullets.append(bullet)
            sounds.shoot.play()

    def checkHeroDead(self, enemys):
        for enemy in enemys:
            if enemy.actor.colliderect(self.actor):
                sounds.explode.play()
                self.actor.image = 'boom'
                return True
예제 #6
0
def draw_players_hands() -> None:
    for p, player in enumerate(game.game.players):
        color = '#1a73e8' if player == game.game.current_player else '#454545'
        text = 'Jugador {} {}'.format(
            p + 1, ' - Ganador!' if game.game.winner == player else '')
        screen.draw.text(text, (25, 180 + p * 130),
                         fontname="montserrat-light",
                         fontsize=32,
                         color=color)

        for c, card in enumerate(player.hand):
            if player == game.player:
                sprite = card.sprite
            else:
                sprite = Actor('back')
            sprite.pos = (250 + c * 80, 210 + p * 130)
            sprite.draw()
예제 #7
0
class Base:

    # Represnts the moving floor of the game

    VEL = 3
    WIDTH = 336

    def __init__(self, y):

        self.y = y
        self.x1 = 0
        self.x2 = self.WIDTH

        self.baseimage = Actor('base2', anchor=(0, 0))
        self.baseimage2 = Actor('base2', anchor=(0, 0))

        self.baseimage.pos = (self.x1, self.y)
        self.baseimage2.pos = (self.x2, self.y)

    def update(self):
        # move floor so it looks like its scrolling

        self.x1 -= self.VEL
        self.x2 -= self.VEL
        if self.x1 + self.WIDTH < 0:
            self.x1 = self.x2 + self.WIDTH

        if self.x2 + self.WIDTH < 0:
            self.x2 = self.x1 + self.WIDTH

        self.baseimage.pos = (self.x1, self.y)
        self.baseimage2.pos = (self.x2, self.y)

    def draw(self):
        # Draw the floor. This is two images that move together.
        self.baseimage.draw()
        self.baseimage2.draw()

    def checkcollision(self, sprite):
        return sprite.colliderect(self.baseimage) or sprite.colliderect(
            self.baseimage2)
예제 #8
0
    def draw(self):
        # 绘制病毒图片
        tamp = time.time()

        # 实现非冰冻和冰冻状态下的动画效果。
        if not self.frozen:
            # 非冰冻状态下,每隔0.1秒更换一次image,从而实现动画效果
            temp = int((tamp - self.appear_time) * 10)
            if self.type == 5:
                # 彩蛋关卡图片
                self.image = "pkuer" + str(temp % 2 + 1)
            else:
                self.image = "virus" + str(self.type) + "_" + str(temp % 3 + 1)
        elif self.frozen:
            # 冰冻状态下,image固定为冰冻效果图片
            if self.type == 5:
                self.image = "pkuer0"
            else:
                self.image = "virus" + str(self.type) + "_0"

        Actor.draw(self)  # 绘制病毒
        self.health_bar()  # 绘制血量条
예제 #9
0
 def draw(self):
     Actor.draw(self)
     # 绘制爆炸效果
     if self.type == 3 and self.booming:
         boom1 = Actor("boom", (self.x + 25, self.y - 30))
         boom1.draw()
         boom2 = Actor("boom", (self.x - 25, self.y - 30))
         boom2.draw()
예제 #10
0
class Enemy:
    x = None
    y = None
    actor = None
    image = None
    speed = None
    life = None

    def __init__(self, x, y, image, speed, life):
        self.x = x
        self.y = y
        self.speed = speed
        self.image = image
        self.actor = Actor(image)
        self.actor.x = x
        self.actor.y = y
        self.life = life

    def draw(self):
        self.actor.draw()

    def update(self):
        self.actor.y += self.speed
예제 #11
0
class BaseCell():

    images = ['cell_dead']

    def __init__(self, x, y, cell_width, cell_height, parent):
        self.status = 0
        self._next = 0
        self.x = x
        self.y = y
        self.cell_width = cell_width
        self.cell_height = cell_height
        self.parent = parent

        self._actor = Actor(self.get_image(),
                            self.get_pos(),
                            anchor=('left', 'top'))

    def get_image(self):
        return self.images[self.status]

    def get_pos(self):
        return (
            self.x * self.cell_width,
            self.y * self.cell_height,
        )

    def draw(self):
        self.status = self._next
        self._actor.image = self.get_image()
        self._actor.draw()

    def update(self):
        pass

    def click(self):
        pass
예제 #12
0
 def draw(self):
     if (self.hidden):
         return
     Actor.draw(self)
예제 #13
0
class Game:
    def __init__(self):
        self.begin_time = time.time()
        self.status = "begin"
        self.level = 1
        self.buying = 0
        self.mouse_down_pos = (0, 0)
        self.mouse_move_pos = (0, 0)
        self.lives = 3
        self.money = 500
        self.enemies = []
        self.enemy_count = 0
        self.last_enemy_time = 0
        self.towers = []

        # 音乐
        music.set_volume(0.4)
        music.play("start.wav")

        # 共用界面
        self.back_button = Actor("back_button", (50, 50))
        # 开始界面
        self.begin_button = Actor("begin_button", (500, 425))
        # 帮助界面
        self.help_button = Actor("help_button", (500, 550))
        # 升级界面
        self.egg_button = Actor("egg_button", (100, 400))
        # 游戏中
        self.buy_tower1 = Actor("tower1", (450, 650))
        self.buy_tower2 = Actor("tower2", (625, 650))
        self.buy_tower3 = Actor("tower3", (825, 650))
        self.hint = Actor("tower1", (0, 0))
        self.pause_button = Actor("pause_button", (100, 200))
        self.start_button = Actor("start_button", (100, 300))
        self.next_button = Actor("next_button", (100, 400))
        # 彩蛋
        self.buy_pkuer = Actor("pkuer2", (700, 650))

    def run(self):
        # 开始界面
        if self.status == "begin":
            if self.begin_button.collidepoint(self.mouse_down_pos):
                self.status = "playing"
                sounds.starta.play(loops=0)
                music.set_volume(0.2)
            elif self.help_button.collidepoint(self.mouse_down_pos):
                self.status = "help"
                sounds.starta.play(loops=0)
        # 帮助界面
        elif self.status == "help":
            if self.back_button.collidepoint(self.mouse_down_pos):
                sounds.starta.play(loops=0)
                self.status = "begin"
        # 暂停状态
        elif self.status == "pause":
            if self.start_button.collidepoint(self.mouse_down_pos):
                if self.level <= 3:
                    self.status = "playing"
                elif self.level == 4:
                    self.status = "egg"
        # 游戏中
        elif self.status == "playing":
            self.run_playing()
        # 下一关
        elif self.status == "level up":
            self.run_level_up()
        # 彩蛋
        elif self.status == "egg":
            self.run_egg()
        # 胜利
        elif self.status == "win":
            if self.back_button.collidepoint(self.mouse_down_pos):
                self.restart()
                self.status = "begin"
        # 失败
        elif self.status == "lose":
            if self.back_button.collidepoint(self.mouse_down_pos):
                self.restart()
                self.status = "begin"

    def run_playing(self):
        # 检测游戏结果
        result = self.get_result()
        if result == 1:  # 胜利
            music.stop()
            self.level += 1
            self.status = "level up"
            sounds.levelup.play(loops=0)
        elif result == -1:  # 失败
            self.status = "lose"
            music.set_volume(0.5)
            music.play_once("lose.wav")

        # 返回到开始界面
        if self.back_button.collidepoint(self.mouse_down_pos):
            self.restart()
            self.status = "begin"

        # 暂停游戏
        if self.pause_button.collidepoint(self.mouse_down_pos):
            self.status = "pause"

        # 购买状态
        if self.buying:
            if self.tower_in_range(self.mouse_move_pos):
                self.buy_tower()

        # 按下购买按钮,并更改状态
        if self.buy_tower1.collidepoint(
                self.mouse_down_pos) and self.money - 50 >= 0:
            self.buying = 1
        elif self.buy_tower2.collidepoint(
                self.mouse_down_pos) and self.money - 100 >= 0:
            self.buying = 2
        elif self.buy_tower3.collidepoint(
                self.mouse_down_pos) and self.money - 200 >= 0:
            self.buying = 3

        # 更新
        self.update_actor()

    def run_egg(self):
        # 返回按钮
        if self.back_button.collidepoint(self.mouse_down_pos):
            self.restart()
            self.status = "begin"

        # 暂停游戏
        if self.pause_button.collidepoint(self.mouse_down_pos):
            self.status = "pause"

        # 塔攻击
        for tower in self.towers:
            if tower.type == 1:
                tower.attack(self.enemies)
            elif tower.type == 2:
                tower.frozen(self.enemies)
            elif tower.type == 3:
                tower.boom(self.enemies)

        # 病毒更新
        for enemy in self.enemies:
            enemy.move(self.level)  # 行走
            enemy.hurt(self.towers)  # 受伤
            if enemy.type == 4:  # boss生成病毒
                enemy.boss_born(self.enemies)
            if enemy.health <= 0:  # 检测病毒是否死亡
                self.money += enemy.type * 10
                sounds.coin.play(loops=0)
                self.enemies.remove(enemy)
            if enemy.pos == (925, 325):  # 检测是否胜利
                self.status = "win"
                music.set_volume(0.5)
                music.play_once("youwin.wav")

        # 购买北大学生
        if self.buy_pkuer.collidepoint(self.mouse_down_pos):
            self.enemies.append(Enemy("pkuer", (200, 75), 5))
            self.mouse_down_pos = (0, 0)

    def run_level_up(self):
        # 若处于前三关
        if self.level <= 3:
            self.buying = 0
            self.enemies.clear()
            self.enemy_count = 0
            self.last_enemy_time = 0
            self.towers.clear()
            if self.next_button.collidepoint(self.mouse_down_pos):
                sounds.starta.play(loops=0)
                music.set_volume(0.2)
                music.play("start.wav")
                self.begin_time = time.time()
                self.status = "playing"

        # 若处于彩蛋关卡
        elif self.level == 4:
            self.buying = 0
            self.enemies.clear()
            self.enemy_count = 0
            self.last_enemy_time = 0
            self.towers.clear()
            self.towers.append(Tower("virus4_1", (400, 325), 1))
            self.towers.append(Tower("virus4_0", (500, 200), 2))
            self.towers.append(Tower("virus4_1", (700, 450), 3))
            if self.next_button.collidepoint(self.mouse_down_pos):
                sounds.starta.play(loops=0)
                music.set_volume(0.2)
                music.play("start.wav")
                self.begin_time = time.time()
                self.status = "egg"

    def restart(self):
        sounds.starta.play(loops=0)
        music.set_volume(0.4)
        music.play("start.wav")
        self.level = 1
        self.buying = 0
        self.lives = 3
        self.money = 50
        self.enemies.clear()
        self.enemy_count = 0
        self.last_enemy_time = 0
        self.towers.clear()

    def menu(self):
        # 绘制游戏菜单

        # 开始界面
        if self.status == "begin":
            screen.blit("begin_bg", (0, 0))
            self.begin_button.draw()
            self.help_button.draw()
        # 帮助界面
        elif self.status == "help":
            screen.blit("help_bg", (0, 0))
            self.back_button.draw()
        # 游戏中
        elif self.status == "playing":
            self.draw_playing_menu()
            self.draw_actor()
        # 彩蛋
        elif self.status == "egg":
            screen.blit("playing_bg_thu", (0, 0))
            screen.blit("money", (225, 620))
            screen.draw.text(str(self.money),
                             topright=(350, 640),
                             color=(0, 0, 0),
                             fontsize=50)
            self.back_button.draw()
            self.pause_button.draw()
            self.start_button.draw()
            self.buy_pkuer.draw()
            self.draw_actor()
        # 胜利
        elif self.status == "win":
            screen.blit("win", (200, 0))
        # 升级
        elif self.status == "level up":
            if self.level <= 3:
                screen.blit("level up", (200, 0))
                self.next_button.draw()
            if self.level == 4:
                screen.blit("win_but", (200, 0))
                self.egg_button.draw()
        # 失败
        elif self.status == "lose":
            screen.blit("lose", (200, 0))
            self.back_button.draw()

    def draw_playing_menu(self):
        # 绘制游戏中菜单

        # 背景
        screen.blit("playing_bg_pku", (0, 0))
        # 金币
        screen.blit("money", (225, 620))
        screen.draw.text(str(self.money),
                         topright=(350, 640),
                         color=(0, 0, 0),
                         fontsize=50)
        # 生命
        screen.blit("lives", (50, 90))
        screen.draw.text(str(self.lives),
                         topright=(130, 100),
                         color=(0, 0, 0),
                         fontsize=50)
        # 按钮
        self.back_button.draw()
        self.pause_button.draw()
        self.start_button.draw()
        self.next_button.draw()
        # 塔的价格
        screen.blit("little_money", (500, 650))
        screen.draw.text("50",
                         topright=(575, 650),
                         color=(0, 0, 0),
                         fontsize=30)
        screen.blit("little_money", (675, 650))
        screen.draw.text("100",
                         topright=(750, 650),
                         color=(0, 0, 0),
                         fontsize=30)
        screen.blit("little_money", (875, 650))
        screen.draw.text("200",
                         topright=(950, 650),
                         color=(0, 0, 0),
                         fontsize=30)
        # 塔的购买按钮
        self.buy_tower1.draw()
        self.buy_tower2.draw()
        self.buy_tower3.draw()
        # 游戏进度条
        rect = Rect((25, 475), (150, 10))
        screen.draw.filled_rect(rect, (0, 255, 0))
        rect = Rect((25, 475),
                    (self.enemy_count / (self.level * 10) * 150, 10))
        screen.draw.filled_rect(rect, (255, 0, 0))
        screen.blit("virus2_2",
                    (self.enemy_count / (self.level * 10) * 150, 465))

    def update_actor(self):
        # 更新所有移动图像

        # 购买提示图像坐标
        self.hint.pos = self.mouse_move_pos

        # 添加病毒
        self.add_virus()

        # 病毒更新
        for enemy in self.enemies:
            enemy.move(self.level)  # 行走
            enemy.hurt(self.towers)  # 受伤
            if enemy.type == 4:  # boss生成病毒
                enemy.boss_born(self.enemies)
            if enemy.health <= 0:  # 检测病毒是否死亡
                self.money += enemy.type * 10
                sounds.coin.play(loops=0)
                self.enemies.remove(enemy)
            if int(enemy.x) == 600 and int(enemy.y) == 275:  # 检测病毒是否到达终点
                self.lives -= 1
                self.enemies.remove(enemy)

        # 塔的攻击
        for tower in self.towers:
            if tower.type == 1:
                tower.attack(self.enemies)
            elif tower.type == 2:
                tower.frozen(self.enemies)
            elif tower.type == 3:
                tower.boom(self.enemies)

    def draw_actor(self):
        # 绘制所有移动图像

        # 如果在购买状态,绘制位置提示
        if self.buying:
            if self.tower_in_range(self.mouse_move_pos):
                self.hint.image = "tower" + str(self.buying)
            else:
                self.hint.image = "out_of_range"
            self.hint.draw()

        # 绘制病毒和塔,还有塔发射的子弹
        for enemy in self.enemies:
            enemy.draw()
        for tower in self.towers:
            tower.draw()
            for shoot in tower.shoots:
                shoot.draw()

    def add_virus(self):
        # 增加新病毒
        tamp = time.time()

        # 根据游戏关卡,确定病毒开始位置
        if self.level == 1:
            begin_pos = (1000, 325)
        elif self.level == 2:
            begin_pos = (700, 575)
        elif self.level == 3:
            begin_pos = (200, 75)
        elif self.level == 4:
            begin_pos = (200, 75)

        # 每隔5秒,病毒出场
        enemy_sum = self.level * 10
        if tamp - self.last_enemy_time > 5 and self.enemy_count < enemy_sum:
            if self.enemy_count < enemy_sum / 2:
                # 0 - 1/2 为低级病毒
                self.enemies.append(Enemy("virus1_1", begin_pos, 1))
            elif enemy_sum / 2 <= self.enemy_count < enemy_sum * 3 / 4:
                # 1/2 - 3/4 为中级病毒
                self.enemies.append(Enemy("virus2_1", begin_pos, 2))
            elif enemy_sum * 3 / 4 <= self.enemy_count < enemy_sum - 1:
                # 3/4 - 1 为高级病毒
                self.enemies.append(Enemy("virus3_1", begin_pos, 3))
            elif self.enemy_count == enemy_sum - 1:
                # 最后一个为Boss
                self.enemies.append(Enemy("virus4_1", begin_pos, 4))
            self.enemy_count += 1
            self.last_enemy_time = tamp

    def get_result(self):
        # 获取游戏结果
        tamp = time.time()
        if len(self.enemies) == 0 and self.enemy_count == self.level * 10:
            if self.lives > 0:
                return 1  # 胜利
        if self.lives <= 0:
            return -1  # 失败
        else:
            return 0  # 游戏中

    def buy_tower(self):
        # 购买塔

        # 如果选择的位置不合法,则停止本次购买
        in_range = self.tower_in_range(self.mouse_down_pos)
        if not in_range:
            self.buying = 0

        # 如果选择的位置合法,根据塔的种类放置塔,并播放音效
        if self.buying > 0:
            tower_name = "tower" + str(self.buying)
            sounds.starta.play(loops=0)
            self.towers.append(
                Tower(tower_name, self.mouse_down_pos, self.buying))
            self.money -= self.towers[-1].cost

        # 结束购买状态
        self.buying = 0

    def tower_in_range(self, pos):
        # 判断塔的位置是否合法

        # 塔不能重叠
        for tower in self.towers:
            if tower.collidepoint(pos):
                return False

        # 只有空白区域可以放置塔,道路和建筑物上不能放置
        if 200 < pos[0] < 350 and 0 < pos[1] < 50:
            return True
        elif 200 < pos[0] < 300 and 200 < pos[1] < 300:
            return True
        elif 200 < pos[0] < 300 and 350 < pos[1] < 500:
            return True
        elif 200 < pos[0] < 400 and 550 < pos[1] < 600:
            return True
        elif 350 < pos[0] < 400 and 100 < pos[1] < 450:
            return True
        elif 350 < pos[0] < 400 and 300 < pos[1] < 350:
            return True
        elif 450 < pos[0] < 550 and 150 < pos[1] < 250:
            return True
        elif 525 < pos[0] < 575 and 350 < pos[1] < 375:
            return True
        elif 650 < pos[0] < 750 and 400 < pos[1] < 500:
            return True
        elif 725 < pos[0] < 750 and 250 < pos[1] < 500:
            return True
        elif 725 < pos[0] < 800 and 500 < pos[1] < 600:
            return True
        elif 800 < pos[0] < 900 and 300 < pos[1] < 450:
            return True
        elif 850 < pos[0] < 1000 and 100 < pos[1] < 200:
            return True
        elif 500 < pos[0] < 700 and 0 < pos[1] < 100:
            return True
        elif 600 < pos[0] < 650 and 550 < pos[1] < 600:
            return True
        elif 950 < pos[0] < 1000 and 350 < pos[1] < 500:
            return True
        else:
            return False
예제 #14
0
 def draw(self):
     if (self.status == 'hidden'):
         return
     Actor.draw(self)
예제 #15
0
class Player(Actor):
    def __init__(self, game, number, *args, **kwargs):
        self.number = number
        self.game = game
        image_name = 'players/p{}/p{}_stand'.format(self.number, self.number)
        super().__init__(image_name, *args, **kwargs)
        self.speed = [0, 0]
        self.facing_left = False
        self.last_x = self.last_y = 0
        self.move_distance = 0
        self.carrying = False
        self.putting_down = False
        self.spawn()
        self.highlight = Actor('players/highlight', anchor=(0, 70))
        self.direction = Actor('players/direction_1', anchor=(0, 70))
        
    def __str__(self):
        return "<Player {}, position: {}>".format(self.number, self.pos)
    
    def set_image(self, image_name):
        self.image = 'players/p{}/p{}_{}'.format(self.number, self.number, image_name)
    
    def spawn(self):
        # TODO: find a blank spot on the screen to spawn into? 
        #       Or just have a spawn spot in the top left (clock on?)
        self.pos = 10,10
    
    def draw(self):
        if self.speed == [0,0]:
            self.set_image('stand')
        else:
            step = int( (self.move_distance / 12 ) % 11 + 1 )
            self.set_image('walk{:0>2d}'.format(step))
        super().draw()
        
        if self.carrying:
            self.carrying.draw()
            for part in getattr(self.carrying, '_sub_parts', {}).values():
                part.draw()
        
        #self.game.point(self.pos)
        #self.game.point((self.x, self.y))
    
    def draw_highlight(self):
        my_grid = self.pick_up_space()
        pos = self.game.convert_from_grid(*my_grid)
        machine = self.game.map.get(my_grid, None)
        if self.putting_down and not machine:
            # show a direction arrow
            
            # This fixes an utterly bizarre bug where left and right images
            # are swapped, despite looking fine in the folder.
            direction = self.player_facing()
            if direction == 1: direction = 3
            elif direction == 3: direction = 1
            
            self.direction.image = 'players/direction_{}'.format(direction)
            #print(self.direction.image, self.player_facing(), pos)
            self.direction.pos = pos
            self.direction.draw()
        elif self.carrying or machine:
            self.highlight.pos = pos
            self.highlight.draw()
        
    def update(self, dt):
        #print ("updating player", self.number)
        if not self.putting_down:
            # don't move if we're putting something down.
            self.x += self.speed[0]
            self.y += self.speed[1]
        if self.speed == [0,0] or self.putting_down:
            self.move_distance = 0     # stopped; reset walk distance
        else:
            self.move_distance += abs(self.speed[0]) + abs(self.speed[1])
        
        if not self.putting_down:
            if self.speed[0] < 0:
                self.facing_left = True
            elif self.speed[0] > 0:
                self.facing_left = False
            self.flip = self.facing_left
        
        if self.right > self.game.WIDTH:
            self.right = self.game.WIDTH
        if self.left < 0:
            self.left = 0
        if self.top < 0:
            self.top = 0
        if self.bottom > self.game.HEIGHT:
            self.bottom = self.game.HEIGHT
        
        if self.carrying:
            self.carrying.update(dt)
            self.carrying.y = self.y + 30
            if self.putting_down:
                self.carrying.direction = self.player_facing()
                self.carrying.pos = self.game.convert_from_grid(*self.putting_down)
            else:
                # The anchor on the conveyor is on the left, 
                # so subtract a grid size if we're facing that way
                if self.facing_left:
                    self.carrying.x = self.x - self.game.GRID_SIZE * 1.5
                else:
                    self.carrying.x = self.x + self.game.GRID_SIZE * 0.5
                
    def player_facing(self):
        if (self.last_x, self.last_y) == (0, 0):
            if self.facing_left:
                return 3
            else:
                return 1
        if abs(self.last_x) > abs(self.last_y):
            # pointing mostly left/right
            if self.last_x < 0:
                return 3
            else:
                return 1
        else:
            # pointing mostly up/down
            if self.last_y < 0:
                return 0
            else:
                return 2
        return 1
    
    def pick_up_space(self):
        """Which space are we currently able to pick up?"""
        me = self.game.convert_to_grid(self.x, self.y)
        if self.putting_down:
            # grid is fixed, only direction will change,
            # based on the joystick direction
            return self.putting_down
                    
        # Otherwise, just base it on grid squares to the left or right
        # For some reason, we need to add one to the y value? Not sure where this is coming from...
        if self.facing_left:
            return (me[0] - 1, me[1] + 1)
        else:
            return (me[0] + 1, me[1] + 1)
    
    def pick_up(self):
        if self.carrying:
            # prepare to put down: display a highlight where it'll go,
            # and put it down when the button is released
            self.putting_down = self.pick_up_space()
            return
            
        # try to pick up
        my_grid = self.pick_up_space()
        machine = self.game.map.get(my_grid, None)
        if machine is None:
            # nope, nothing there
            return
        elif (machine.name == 'ore_chute' or
            machine.name == 'loading_dock'):
            pass # no pick up
        elif machine and machine.name == 'training_manual_kiosk':
            print("Training Manual!")
            self.game.show_training_manual = True
        else:
            #print("Picking up", machine)
            machine.carried = True
            self.carrying = machine
            if getattr(machine, 'multimachine', None):
                # need to disable the multimachine
                mm = machine.multimachine
                mm.switch_off()
                self.game.multimachines.remove(mm)
                del mm
            del self.game.map[my_grid]   # dangerous! 
    
    def put_down(self):
        my_grid = self.pick_up_space()
        machine = self.game.map.get(my_grid, None)
        if machine:
            # nope, there's something there
            self.putting_down = False
            pass
        else:
            # Check which direction the player / player's joystick is facing,
            # and make the conveyor face that way.
            my_machine = self.carrying
            self.game.map[my_grid] = my_machine
            my_machine.grid_x = my_grid[0]
            my_machine.grid_y = my_grid[1]
            my_machine.x, my_machine.y = self.game.convert_from_grid(*my_grid)
            my_machine.carried = False
            my_machine.direction = self.player_facing()
            if hasattr(my_machine, 'on_put_down'):
                my_machine.on_put_down()
            #print("Putting down", my_machine, "at", my_grid, "facing", my_machine.direction)
            self.carrying = False
            self.putting_down = False
    
    def do_a_debug(self):
        # debug the conveyors
        my_grid = self.pick_up_space()
        machine = self.game.map.get(my_grid, None)
        if machine:
            print(machine)
        mm = getattr(machine, 'multimachine', None)
        if mm:
            print(mm)
            print("  Production:", mm.input_machines, mm.output_machines)
        print ("Multimachines in game: ", self.game.multimachines)
    
    
    def handle_button_down(self, button):
        #print("Player {} pushed button {}".format(self, button))
        if button == joybutton.ZERO:
            self.pick_up()
            
        if button == joybutton.TWO:
            self.do_a_debug()
            
    def handle_button_up(self, button):
        if button == joybutton.ZERO and self.carrying and self.putting_down:
            self.put_down()
    
    def handle_axis(self, axis, value):
        #print("Player {} moved axis {}: {}".format(self, axis, value))
        if axis == axis.X:
            self.speed[0] = value * 7
            self.last_x = value
        if axis == axis.Y:
            self.speed[1] = value * 7
            self.last_y = value
    
    
    def handle_key_down(self, key):
        if key in (keys.SPACE, keys.RSHIFT):
            # button zero
            self.pick_up()
        
        if key in (keys.RETURN, keys.LALT):
            self.do_a_debug()
        
        if key in (keys.W, keys.UP):
            self.speed[1] = -7
            self.last_y = -7
        
        if key in (keys.S, keys.DOWN):
            self.speed[1] = 7
            self.last_y = 7
            
        if key in (keys.A, keys.LEFT):
            self.speed[0] = -7
            self.last_x = -7
        
        if key in (keys.D, keys.RIGHT):
            self.speed[0] = 7
            self.last_x = 7

    def handle_key_up(self, key):
        if key in (keys.SPACE, keys.RSHIFT) and self.carrying and self.putting_down:
            # button zero
            self.put_down()
        
        if key in (keys.W, keys.UP):
            self.speed[1] = 0
            self.last_y = 0
        
        if key in (keys.S, keys.DOWN):
            self.speed[1] = 0
            self.last_y = 0
            
        if key in (keys.A, keys.LEFT):
            self.speed[0] = 0
            self.last_x = 0
        
        if key in (keys.D, keys.RIGHT):
            self.speed[0] = 0
            self.last_x = 0