震驚,某程序員居然在上班時間搞「恐龍」

這是我參與8月更文挑戰的第11天,活動詳情查看:8月更文挑戰python

相信在座的各位小夥伴對Google Chrome瀏覽器中的一個遊戲彩蛋恐龍小遊戲(Chrome Dino)不陌生吧。在斷開網絡鏈接,咱們訪問網站的時候,就會出現一個小霸王龍,在咱們再按下空格鍵後,便可開始這個遊戲,或者在谷歌瀏覽器的地址欄輸入chrome://dino/, 按下空格鍵,也可這個開始遊戲。chrome

image.png

這是一個簡單的無限跑步遊戲,它會讓你跳過仙人掌,並閃避障礙物,遊戲控制也很簡單,按空格鍵開始遊戲,按空格鍵上箭頭↑跳躍,向下箭頭↓俯身奔跑以躲避鳥類。小程序

有時代碼寫的無聊時,就是玩一下這個遊戲,而後我可能有點手殘,玩不了多少分就game over了,因而就萌生了使用代碼自動玩這個遊戲的想法,說幹就幹,下面我就來使用Python編寫一個能夠自動玩這個恐龍小遊戲的小程序。瀏覽器

思路:

看下面這個截圖,在恐龍向前奔跑的過程當中,咱們能夠獲取恐龍前面一段區間圖像並獲取其中像素點的顏色,若是顏色和背景色不一樣,那麼就必定是障礙物(仙人掌或鳥類),而後按下按鍵作出正確動做便可。提及來很簡單,實現起來卻不是那麼容易。 image.pngmarkdown

實現

獲取指定圖像像素點的顏色

既然是要獲取像素點的顏色,那麼首先要截取圖像,在Python中,咱們可使用下面代碼截取圖像(就是截圖):網絡

import pyautogui as gui

# 截屏
sct_img = gui.screenshot(region=(x, y, width, height))
sct_img.save("name.jpg")
複製代碼

pyautogui是一個GUI自動化工具庫,它有不少能夠控制圖形或者鼠標等等的函數,能夠用程序去代替鼠標鍵盤的一些操做,安裝命令pip install pyautoguiapp

而後咱們可使用下面一段代碼獲取截圖圖片上指定像素點的顏色:函數

def get_pixel(image, x, y):
    """ 獲取圖像中的像素值 :param image:圖片對象 :param x:x座標 :param y:y座標 :return:顏色值 """
    px = image.load()
    return px[x, y]
複製代碼

返回值是一個元組,例如白色就是返回(255,255,255)工具

根據顏色作出按鍵動做

使用程序模擬鍵盤動做,咱們可使用keyboard庫,可使用其提供的函數進行按下按鍵釋放按鍵此類的動做。安裝命令pip install keyboard。 上述咱們說到這個恐龍的小遊戲在操做過程當中只須要上箭頭↑跳躍,下箭頭↓俯身奔跑兩個按鍵 因此咱們可使用如下代碼:post

import keyboard


# 按下「↑」鍵 跳躍
keyboard.press('up')
# 按下「↓」鍵 俯身奔跑
keyboard.press("down")
# 釋放按鍵「↓」
keyboard.release("down") 
複製代碼

獲取障礙物可能出現地方的座標

手動玩了一段時間發現,障礙物可能出現的地方有如下幾點:

image.png

2021-08-10_120515.png

根據截圖軟件得出障礙物可能出現的地方的高度即y座標
注意: 個人是分辨率1920*1080的顯示屏,因此是以此分辨率爲基準截圖並肯定座標

細節調整

我發現,在玩一段時間後,遊戲節奏會加快,出現誤判的概率大大增長,因此我在此加入了模擬加速的邏輯: 判斷兩次跳躍之間的時間間隔,若是間隔和上次不同,那麼就多是節奏加快了,咱們就能夠多恐龍以前的一下區間,就是加大搜索障礙物區間的大小,這樣就至關於提早進行了判斷,就會抵消掉一部分由於遊戲節奏加快帶來的影響。

所有代碼以下:

import pyautogui as gui
import keyboard
import time
import math


def get_pixel(image, x, y):
    """ 獲取圖像中的像素值 :param image:圖片對象 :param x:x座標 :param y:y座標 :return:顏色值 """
    px = image.load()
    return px[x, y]


def start():

    # 截屏圖片尺寸
    x, y, width, height = 0, 102, 1920, 872

    # 用於計算時間
    jumping_time = 0
    last_jumping_time = 0
    current_jumping_time = 0
    last_interval_time = 0

    # 機器人尋找障礙物的區間
    y_search1, y_search2, x_start, x_end = 557, 486, 400, 415
    y_search_for_bird = 460

    time.sleep(3)  # 留3s時間用於程序執行後將界面切換到谷歌瀏覽器
    while True:
        t1 = time.time()
        # 按下q鍵機器人退出
        if keyboard.is_pressed('q'):
            break

        # 截屏
        sct_img = gui.screenshot(region=(x, y, width, height))
        sct_img.save("dd.jpg")

        # 獲取截屏圖片的背景色
        bg_color = get_pixel(sct_img, 100, 100)

        for i in reversed(range(x_start, x_end)):
            # 若是在截屏圖片的背景色中搜索指定區間的像素,若是該像素的顏色和背景色的顏色不一致,就是障礙物
            if get_pixel(sct_img, i, y_search1) != bg_color \
                    or get_pixel(sct_img, i, y_search2) != bg_color:
                # 按下「↑」鍵 跳躍
                keyboard.press('up')
                jumping_time = time.time()
                current_jumping_time = jumping_time
                break
            if get_pixel(sct_img, i, y_search_for_bird) != bg_color:
                keyboard.press("down")
                time.sleep(0.4)
                # 釋放按鍵「↓」
                keyboard.release("down") 
                break

        # 本次跳躍與上次間隔時間
        interval_time = current_jumping_time - last_jumping_time

        # 若是本次間隔時間與上次間隔時間不相同,說明遊戲加速了,也要相應調整搜索區間的寬度,至關於提早搜索
        if last_interval_time != 0 and math.floor(interval_time) != math.floor(last_interval_time):
            x_end += 4
            if x_end >= width:
                x_end = width

        # 記錄上次跳躍時間
        last_jumping_time = jumping_time
        # 記錄上次跳躍與上上次間隔時間
        last_interval_time = interval_time


start()
複製代碼

運行截圖gif以下(無聊的朋友能夠看一下):

dino_bot.gif

通過幾回運行,最高得分是2890分,優化優化,應該還能再多,此次截圖得了886分,可見雖然實現了我想要的功能,可是還有很大的提高空間。
能夠還有其餘沒考慮好的細節,可是......
時間不容許再搞了,這個886的分數是否是就是在暗示我......
別搞了,該上會兒班了 image.png
再搞就要和工做886了,哈哈哈,886~~~

最後,感謝女友在工做和生活中的包容、理解與支持 !

相關文章
相關標籤/搜索