程序员的愤怒–用python在《最终幻想10》避雷200次

/ 1评 / 0

在《最终幻想10》中有一个小游戏需要连续躲避闪电200次以上,本来对游戏中的小游戏不怎么上心的,无奈奖品是一个重要的武器升级道具,只能硬着头皮上。但手残加没耐心的我试了几次,最多连续10来次就断了。看了网上说连续200次需要半个小时才能搞定,瞬间不想玩了,但又有点不甘心,有点生气,感觉都是游戏设计的错。

仔细想了一下,避雷的一整套动作都是有特征和固定的,不过是要重复200次而已,这个世界上有什么比程序还擅长做重复的任务呢?说干就干。

首先闪电的特征,全屏变白,马上想到能够取样几个游戏的像素,再用颜色空间的距离来判断出闪电的时间,再接下来按下躲避键就好。

截屏、颜色处理、发送按键,用python。于是周六早上花了几个小时一边找资料,一边测,写了个小脚本,代码有点乱,没去整理,不过效果还行。

打开游戏,进入落雷平原后,切换出来运行脚本,再切换回游戏。如果没问题的话,遇到闪电白屏的时候就会自动闪避。我是在窗口模式运行的,全屏下没试过,请自行测试。

import win32gui as win
from PIL import ImageGrab
import signal
import sys
import colorsys
from math import sin, cos

fps = {}

import win32api, win32con, time

def pressKey(k):
    win32api.keybd_event(k, win32api.MapVirtualKey(k, 0), 0, 0)
    time.sleep(.2)
    win32api.keybd_event(k, win32api.MapVirtualKey(k, 0), win32con.KEYEVENTF_KEYUP, 0)

def signal_handler(sig, frame):
    print(fps)
    sys.exit(0)


def fps_record():
    t = int(time.time())
    if t not in fps:
        fps[t] = 0
    fps[t] += 1


def hsv_distance(hsv1, hsv2):
    h1, s1, v1 = hsv1
    h2, s2, v2 = hsv2
    return ((sin(h1) * s1 * v1 - sin(h2) * s2 * v2) ** 2) + ((cos(h1) * s1 * v1 - cos(h2) * s2 * v2) ** 2) + (
                (v1 - v2) ** 2)


if __name__ == '__main__':
    signal.signal(signal.SIGINT, signal_handler)
    sampleNum = 10
    striking=False
    jump=0
    while True:
        forgroundwindow = win.GetForegroundWindow()
        try:
            bbox = win.GetWindowRect(forgroundwindow)
        except:
            time.sleep(0.5)
            continue

        img= ImageGrab.grab(bbox)
        pixels = img.load()
        height, width = img.size
        height = int(height / 3)
        width = int(width / 3)
        sep = int(width / sampleNum)
        samples = []
        avgDistance = 0
        for i in range(1, sampleNum):
            hsv = colorsys.rgb_to_hsv(*pixels[width + (i - 1) * sep, height])
            samples.append(hsv)
            avgDistance += hsv_distance((0, 0, 255), hsv)

        avgDistance=avgDistance/sampleNum
        if avgDistance<10000 and striking==False:
            striking=True
            time.sleep(0.1)
            jump += 1
            pressKey(0x43)
            print(time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime()), '闪电? +',jump)
            time.sleep(0.2)
        else:
            striking=False

        # fps_record()

下面是运行截图:

闪避200次用了16分钟,比网上说的快。

拿到小游戏奖品后,有一种“老子果然厉害”的感觉,但同时也有一种莫名的空虚。?

  1. 点点点说道:

    很酷
    如果是曾经的我肯定会这么想,我用自己的技术做了一些很酷的事情
    空虚,或许是在想….“不应该只是这样的事情,太小了,明明有这么厉害的技术,有没有什么更酷的事情,做完能让自己不那么空虚”

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注