This is the 11th day of my participation in the August More text Challenge. For details, see: August More Text Challenge

I believe you are familiar with Chrome Dino, a small game in Google Chrome. When we disconnect from the Internet and visit the website, a small TYrannosaurus rex will appear. We can start the game by pressing the space bar again, or by typing Chrome ://dino/ in the address bar of Google’s Browser and pressing the space bar.

This is a simple infinite running game, it will let you jump over cactus, and dodge obstacles, the game control is very simple, press the space bar to start the game, press the space bar or up arrow ↑ jump, down arrow ↓ run down to avoid birds.

Sometimes when I get bored with writing code, I just play this game, and then I may have a bit of hand injury, and I can’t play the game over many points, so I have the idea to use the code to automatically play this game, just do it, now I will use Python to write a small program that can automatically play this dinosaur game.

Ideas:

If you look at the screenshot below, as the dinosaur is running forward, we can take the image of the front segment of the dinosaur and capture itThe color of the pixelIf the colors andThe background colorIf not, it must be an obstacle (cactus or bird), and then press the button to make the correct action. Simple as it sounds, it’s not so easy to implement.

implementation

Gets the color of the specified image pixel

Since we want to get the color of the pixels, we first need to capture the image. In Python, we can use the following code to capture the image (which is a screenshot) :

import pyautogui as gui

# screenshots
sct_img = gui.screenshot(region=(x, y, width, height))
sct_img.save("name.jpg")
Copy the code

Pyautogui is a GUI automation tool library, it has a lot of functions can control graphics or mouse and so on, you can use the program to replace some mouse and keyboard operations, install command PIP install PyAutogui.

Then we can use the following code to get the color of the specified pixel on the screenshot:

def get_pixel(image, x, y) :
    """ """ """ """ """ """ """ """ """ """ "
    px = image.load()
    return px[x, y]
Copy the code

The return value is a tuple, for example white is returned (255,255,255).

Make button action according to the color

To use programs to simulate keyboard actions, we can use the Keyboard library, which provides functions to press a key or release a key. Install the PIP install keyboard command. As we mentioned above, this dinosaur game only requires two buttons to jump up arrow ↑ and down arrow down run, so we can use the following code:

import keyboard


Press ↑ to jump
keyboard.press('up')
Press the ↓ key and run
keyboard.press("down")
# Release key "↓"
keyboard.release("down") 
Copy the code

Gets the coordinates of where the obstacle is likely to appear

After playing manually for a period of time, I found that there are the following places where obstacles may appear:

According to the screenshot software, the height (y coordinate) of the place where the obstacle may appear can be obtained. Note: I have a 1920*1080 screen, so I’m taking screenshots at that resolution and determining the coordinates

Details to adjust

I found that after playing for a while, the pace of the game would speed up and the probability of misjudgment would increase greatly, so I added the logic of simulation acceleration here: To judge the time interval between two jump, if the interval and is not the same as last time, speed up the pace of it may be, we can more dinosaurs before the interval, is increasing the size of the search interval obstruction, such as the judgment in advance, will offset part because of the effects of speed up the pace of the game.

The complete code is as follows:

import pyautogui as gui
import keyboard
import time
import math


def get_pixel(image, x, y) :
    """ """ """ """ """ """ """ """ """ """ "
    px = image.load()
    return px[x, y]


def start() :

    # Screenshot image size
    x, y, width, height = 0.102.1920.872

    # is used to calculate time
    jumping_time = 0
    last_jumping_time = 0
    current_jumping_time = 0
    last_interval_time = 0

    # Where the robot looks for obstacles
    y_search1, y_search2, x_start, x_end = 557.486.400.415
    y_search_for_bird = 460

    time.sleep(3)  # Allow 3s to switch the interface to Chrome after the program is executed
    while True:
        t1 = time.time()
        Press the Q key to exit the robot
        if keyboard.is_pressed('q') :break

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

        Get the background color of the screenshot image
        bg_color = get_pixel(sct_img, 100.100)

        for i in reversed(range(x_start, x_end)):
            # If you search for pixels in the background color of the screenshot, if the color of the pixel is different from the color of the background color, it is an obstacle
            ifget_pixel(sct_img, i, y_search1) ! = bg_color \orget_pixel(sct_img, i, y_search2) ! = bg_color:Press ↑ to jump
                keyboard.press('up')
                jumping_time = time.time()
                current_jumping_time = jumping_time
                break
            ifget_pixel(sct_img, i, y_search_for_bird) ! = bg_color: keyboard.press("down")
                time.sleep(0.4)
                # Release key "↓"
                keyboard.release("down") 
                break

        # Time between this jump and the last
        interval_time = current_jumping_time - last_jumping_time

        If this interval is different from the last interval, the game is speeding up and the width of the search interval should be adjusted accordingly, which is equivalent to searching ahead of time
        iflast_interval_time ! =0 andmath.floor(interval_time) ! = math.floor(last_interval_time): x_end +=4
            if x_end >= width:
                x_end = width

        Record the last jump time
        last_jumping_time = jumping_time
        Record the time between the last jump and the last jump
        last_interval_time = interval_time


start()
Copy the code

Run the screenshot GIF below (if you’re bored) :

After several runs, the highest score is 2890 points. After optimization, it should be more. This time, the screenshot got 886 points, which shows that although THE function I want has been realized, there is still a lot of room for improvement.

There may be other details that haven’t been considered, but……

Time does not allow to do again, the score of this 886 is to imply me……

Stop it. It’s time to get back to work

It’s going to be work 886, hahaha, 886

Finally, I would like to thank my girlfriend for her tolerance, understanding and support in work and life.