用三角函数实现朝向玩家方向移动,注释翻译:风火轮少儿编程作者:李兴球

"""
用三角函数实现朝向玩家方向移动,注释翻译:风火轮少儿编程作者:李兴球
来自arcade官方网站。本程序实现金币角色自动朝向玩家移动。
"""

import random
import arcade
import math
import os

# --- Constants ---
SPRITE_SCALING_PLAYER = 0.5
SPRITE_SCALING_COIN = 0.2
COIN_COUNT = 50
COIN_SPEED = 0.5

SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
SCREEN_TITLE = "用三角函数实现朝向玩家方向移动_注释翻译 :李兴球"

SPRITE_SPEED = 0.5

class Coin(arcade.Sprite):
    """
    Coin类是角色类的子弹,只是给它增加了一个方法而已
    """

    def follow_sprite(self, player_sprite):
        """
        向着玩家角色的方向移动
        """

        self.center_x += self.change_x  # 在水平方向上移动change_x
        self.center_y += self.change_y  # 在垂直方向上移动change_y

        # 设置一定的机率重新调整方向向量,好像金币好聪明的样子
        if random.randrange(100) == 0:
            start_x = self.center_x  # 起点,就是自己的坐标
            start_y = self.center_y

            # 终点就是玩家的坐标
            dest_x = player_sprite.center_x
            dest_y = player_sprite.center_y

            # 用反正切函数计算朝向角度
            x_diff = dest_x - start_x  # 是当于向量的x值
            y_diff = dest_y - start_y  # 相当于向量的y值
            angle = math.atan2(y_diff, x_diff)

            # 算出方向向量值
            self.change_x = math.cos(angle) * COIN_SPEED
            self.change_y = math.sin(angle) * COIN_SPEED

class MyGame(arcade.Window):
    """ Our custom Window Class"""

    def __init__(self):
        """ Initializer """
        # 调用父类的实始化方法
        super().__init__(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_TITLE)

        # 设置工作目录 
        file_path = os.path.dirname(os.path.abspath(__file__))
        os.chdir(file_path)

        # 定义角色列表
        self.player_list = None
        self.coin_list = None

        # 定义玩家的相关变量
        self.player_sprite = None
        self.score = 0

        # 隐藏鼠标
        self.set_mouse_visible(False)

        arcade.set_background_color(arcade.color.AMAZON)

    def setup(self):
        """ 设置游戏,实例化变量的值 """

        # 实例化角色列表
        self.player_list = arcade.SpriteList()
        self.coin_list = arcade.SpriteList()

        # 得分初始值为0
        self.score = 0

        # 实例化玩家
        self.player_sprite = arcade.Sprite("images/character.png", SPRITE_SCALING_PLAYER)
        self.player_sprite.center_x = 50
        self.player_sprite.center_y = 50
        self.player_list.append(self.player_sprite)

        # 创建一些金币
        for i in range(COIN_COUNT):

            # 实例化金币
            coin = Coin("images/coin_01.png", SPRITE_SCALING_COIN)

            # 放到随机坐标位置
            coin.center_x = random.randrange(SCREEN_WIDTH)
            coin.center_y = random.randrange(SCREEN_HEIGHT)

            # 增加到金币列表
            self.coin_list.append(coin)

    def on_draw(self):
        """ 重画所有对象"""
        arcade.start_render()
        self.coin_list.draw()
        self.player_list.draw()

        # 显示文本
        output = f"Score: {self.score}"
        arcade.draw_text(output, 10, 20, arcade.color.WHITE, 14)

    def on_mouse_motion(self, x, y, dx, dy):
        """ 鼠标移动事件 """

        #  用鼠标操作玩家
        self.player_sprite.center_x = x
        self.player_sprite.center_y = y

    def update(self, delta_time):
        """ 移动与游戏逻辑 """

        for coin in self.coin_list: # 让每个金币朝向玩家移动
            coin.follow_sprite(self.player_sprite)

        # 金币和玩家的碰撞检测
        hit_list = arcade.check_for_collision_with_list(self.player_sprite, self.coin_list)

        # 碰到的金币删除并且加分
        for coin in hit_list:
            coin.kill()
            self.score += 1


def main():
    """ Main method """
    window = MyGame()
    window.setup()
    arcade.run()

if __name__ == "__main__":
    main()