训练AI玩赛车游戏

目前只操控方向键

算法为每局速度增加奖励增加,每把用时比上把少奖励增加

后续会增加氮气键,漂移键。优化每把操作,如果上次操作导致速度降低,立马反打方向

代码如下:

#利用了openai的gym库

import gym

from gym import spaces

import numpy as np

import pyautogui

import cv2

import time

import pytesseract

class Asphalt9Env(gym.Env):

    def __init__(self):

        super(AsphaltUNITEEnv, self).__init__()

        self.action_space = spaces.Discrete(3)

        self.observation_space = spaces.Box(low=np.array([0]), high=np.array([1]), dtype=np.float32)

        self.game_over_image = cv2.imread('8.png', cv2.IMREAD_GRAYSCALE)

        self.game_start_image = cv2.imread('9.png', cv2.IMREAD_GRAYSCALE)

        self.start_click_image = cv2.imread('10.png', cv2.IMREAD_GRAYSCALE) # 载入 10.png

        self.start_time = None

        self.last_speed = 0

        self.best_time = None

    def reset(self):

        """重置环境,执行初始点击操作并等待游戏开始,返回初始状态"""

        # 在执行初始点击序列前检查截图是否与10.png相符

        if self.is_start_condition_met():

            self.perform_initial_clicks()

        # 等待新一局游戏开始

        self.wait_for_new_game()

        # 初始化状态

        self.start_time = time.time()

        self.state = np.array([1], dtype=np.float32)

        self.last_speed = self.state[0]

        return self.state

    def is_start_condition_met(self):

        """检查截图是否与10.png相符"""

        screenshot = self.capture_screen()

        result = cv2.matchTemplate(screenshot, self.start_click_image, cv2.TM_CCOEFF_NORMED)

        _, max_val, _, _ = cv2.minMaxLoc(result)

        threshold = 0.8

        return max_val >= threshold

    def perform_initial_clicks(self):

        """在初始状态时点击指定的点"""

        click_sequence = [

            (878, 779), # 点击开始第一个点

            (1483, 878), # 点击开始第二个点

            (443, 470), # 点击开始第三个点

            (1583, 889) # 点击开始第四个点

        ]

        wait_times = [2, 2, 2, 2 ] # 每次点击后的等待时间

        for (x, y), wait_time in zip(click_sequence, wait_times):

            pyautogui.click(x, y)

            time.sleep(wait_time)

    def step(self, action):

        """执行一个动作并返回新状态、奖励和是否结束"""

        if action == 0: # 左转

            pyautogui.mouseDown(134, 853) # 按下左键

            time.sleep(0.2) # 长按0.5秒

            pyautogui.mouseUp(134, 853) # 释放左键

        elif action == 1: # 右转

            pyautogui.mouseDown(1793, 898) # 按下右键

            time.sleep(0.2) # 长按2秒

            pyautogui.mouseUp(1793, 898) # 释放右键

        elif action == 2: # 不按键

            pass

        current_speed = self.get_current_speed()

        self.state = np.array([current_speed], dtype=np.float32)

        reward = self.calculate_reward(current_speed)

        done = self.check_done()

        if done:

            # 捕获并保存截图

            screenshot = self.capture_screen(region=(679, 190, 866, 234))

            screenshot_path = 'screenshot.png'

            cv2.imwrite(screenshot_path, screenshot)

            print(f"Screenshot saved to {screenshot_path}")

            time_text = self.extract_time_from_image(screenshot)

            print(f"Detected time text: {time_text}")

            if time_text: # 确保 time_text 不为空

                current_time = self.parse_time_to_seconds(time_text)

                print(f"Parsed current time in seconds: {current_time}") # 打印 current_time

                reward += self.get_time_reward(current_time)

                print(f"Updated reward: {reward}") # 打印更新后的 reward

            self.perform_end_sequence()

        return self.state, reward, done, {}

    def perform_end_sequence(self):

        """在每局结束时执行一系列点击操作"""

        click_sequence = [

            (1513, 917), # 点击结束第一个点

            (1533, 917), # 点击结束第二个点

        ]

        wait_times = [3, 3]

        for (x, y), wait_time in zip(click_sequence, wait_times):

            pyautogui.click(x, y)

            time.sleep(wait_time)

    def wait_for_new_game(self):

        """等待新的一局游戏开始"""

        while True:

            screenshot = self.capture_screen()

            if self.is_game_start(screenshot):

                break

            time.sleep(1)

    def calculate_reward(self, current_speed):

        """计算奖励"""

        reward = current_speed

        return reward

    def get_time_reward(self, current_time):

        """计算时间奖励"""

        if self.best_time is None or current_time < self.best_time:

            self.best_time = current_time

            return 1 # 奖励1

        return 0

    def get_current_speed(self):

        """模拟获取当前速度"""

        x1, y1, x2, y2 = 1533, 94, 1716, 177

        screenshot = self.capture_screen(region=(x1, y1, x2 - x1, y2 - y1))

        speed_text = pytesseract.image_to_string(screenshot, config='--psm 7')

        print(f"Detected speed text: {speed_text}")

        try:

            speed = float(speed_text.strip())

        except ValueError:

            speed = 0.0

        speed = min(max(speed / 300, 0), 1) # 归一化速度

        return speed

    def check_done(self):

        """检查游戏是否结束"""

        screenshot = self.capture_screen()

        return self.is_game_over(screenshot)

    def capture_screen(self, region=None):

        """截取屏幕"""

        screenshot = pyautogui.screenshot(region=region)

 screenshot_np = np.array(screenshot)

        screenshot_gray = cv2.cvtColor(screenshot_np, cv2.COLOR_RGB2GRAY)

        return screenshot_gray

    def is_game_over(self, screenshot):

        """判断截图中是否显示了游戏结束提示"""

        result = cv2.matchTemplate(screenshot, self.game_over_image, cv2.TM_CCOEFF_NORMED)

        _, max_val, _, _ = cv2.minMaxLoc(result)

        threshold = 0.8

        if max_val >= threshold:

            print("find 8.png") # 检测到 8.png 时打印文字

            return True

        return False

    def is_game_start(self, screenshot):

        """判断截图中是否显示了新一局游戏开始提示"""

        result = cv2.matchTemplate(screenshot, self.game_start_image, cv2.TM_CCOEFF_NORMED)

        _, max_val, _, _ = cv2.minMaxLoc(result)

        threshold = 0.8

        if max_val >= threshold:

            print("find 9.png") # 检测到 9.png 时打印文字

            return True

        return False

    def extract_time_from_image(self, image):

        """从图像中提取时间"""

        time_text = pytesseract.image_to_string(image, config='--psm 7 -c tessedit_char_whitelist=:0123456789')

        print(f"Detected time text: {time_text.strip()}")

        return time_text.strip()

    def parse_time_to_seconds(self, time_text):

        """将时间文本解析为秒数"""

        # 去掉非数字和冒号以外的字符

        cleaned_text = ''.join(c for c in time_text if c.isdigit() or c == ':')

        # 去掉开头的0和空格

        cleaned_text = cleaned_text.lstrip('0').strip()

        if not cleaned_text or ':' not in cleaned_text:

            return 0 # 如果时间文本格式不正确,则返回0秒

        # 确保时间文本有正确的格式(如 'MM:SS.mmm')

        try:

            parts = cleaned_text.split(':')

            if len(parts) == 2:

                minutes = int(parts[0]) if parts[0] else 0

                seconds = float(parts[1]) if parts[1] else 0

                return minutes * 60 + seconds

        except ValueError:

            pass

        return 0 # 如果解析失败,则返回0秒

if __name__ == "__main__":

    env = Asphalt9Env()

    

    while True:

        state = env.reset() # 重置环境并开始新的一局

        done = False

        

        while not done:

            action = env.action_space.sample()

            state, reward, done, _ = env.step(action)

            print(f"Action: {action}, State: {state}, Reward: {reward}, Done: {done}")

            time.sleep(1)

        print("Game over. Resetting environment...")

强化学习训练AI游戏是通过使用Q-learning算法和DQN算法来训练AI游戏中进行决策和行动。在Q-learning算法中,AI通过与环境的交互来学习最优的行动策略,以达到游戏的目标。例如,在走迷宫游戏中,AI通过训练学习到在迷宫中找到通关路径的最佳策略\[1\]。 而在DQN算法中,AI通过深度强化学习来训练,以在游戏中与机器进行弹球对战。通过训练AI的胜率得到了显著提高,从最开始几乎全输到几乎全胜\[3\]。 在训练过程中,经验池起到了重要的作用。经验池的功能是解决相关性及非静态分布问题,通过将每个时间戳Agent与环境交互得到的转移样本储存到回放记忆单元中,然后随机抽取一些样本进行训练,以减少经验浪费并减轻经验关联性对网络训练的影响\[5\]。 总的来说,强化学习训练AI游戏是通过使用Q-learning算法和DQN算法,结合经验池的方法,让AI能够学习并改进在游戏中的决策和行动,从而提高AI游戏中的表现和胜率。 #### 引用[.reference_title] - *1* *2* *3* *4* *5* [基于强化学习与深度强化学习的游戏AI训练](https://blog.csdn.net/pigpigpig64/article/details/118976302)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值