這個丹麥小哥的項目火了!他用Python寫了個游戲機
最近有一個叫PyBoy的開源項目火了,原因是它使用了Python 2.7重新將那些在GameBoy上的上古游戲的整個模擬器實現(xiàn)了出來。
利用現(xiàn)代技術重新實現(xiàn)上古游戲一直是一件相當有意思的事情,大家都知道,Game Boy是任天堂公司在1989年發(fā)售的第一代便攜式游戲機,對于一群80/90后來說,Gameboy是他們童年里不可或缺的一部分,有的人可能忘記了,但是提起《口袋妖怪》,很多人應該就能想起來了。
除此之外,PyBoy支持通過API編寫腳本,還添加了類型定義,使其可以使用Cython編譯軟件,從而獲得與用C和C++編寫的模擬器相媲美的性能。
目前,PyBoy在Github上標星2.6K,累計Fork有 239 個(Github地址:https://github.com/Baekalfen/PyBoy/wiki/Scripts,-AI-and-Bots)
特性
PyBoy 被設計成通過 Python 訪問,因此支持并鼓勵人們做實驗研究,對機器人和AI感興趣的人都可以嘗試一下。創(chuàng)建者正在構建特定于游戲的包裝器,目前,這些包裝器可讓程序員與俄羅斯方塊和超級瑪麗進行交互,而不需要對 Game Boy 有深入的了解。
具體你可以參考該文檔:https://docs.pyboy.dk。
說到這里,不得不提的是,創(chuàng)建這個項目的是一個丹麥小哥,早在2015年,PyBoy就已經(jīng)是一個大學項目,目前,創(chuàng)建者還想學習和嘗試更多奇特的功能,根據(jù)大學項目的研究,他們向模擬器添加了倒回功能,也就是說,你可以在任何游戲中倒回時間。
PyBoy可作為Python中的對象加載。這意味著它可以從另一個腳本初始化,并可以由該腳本控制和探測??匆幌耮amewrapper_tetris.py與游戲互動的原始“機器人”。
所有外部組件都可以在PyBoy文檔中找到,以下是從屏幕讀取數(shù)據(jù)的簡短演示。該代碼也可以在gamewrapper_mario.py以下位置找到:
- import os
- import sys
- from pyboy import PyBoy, WindowEvent
- # Makes us able to import PyBoy from the directory below
- file_path = os.path.dirname(os.path.realpath(__file__))
- sys.path.insert(0, file_path + "/..")
- # Check if the ROM is given through argv
- if len(sys.argv) > 1:
- filename = sys.argv[1]
- else:
- print("Usage: python mario_boiler_plate.py [ROM file]")
- exit(1)
- quiet = "--quiet" in sys.argv
- pyboy = PyBoy(filename, window_type="headless" if quiet else "SDL2", window_scale=3, debug=not quiet, game_wrapper=True)
- pyboy.set_emulation_speed(0)
- assert pyboy.cartridge_title() == "SUPER MARIOLAN"
- mario = pyboy.game_wrapper()
- mario.start_game()
- assert mario.score == 0
- assert mario.lives_left == 2
- assert mario.time_left == 400
- assert mario.world == (1, 1)
- assert mario.fitness == 0 # A built-in fitness score for AI development
- last_fitness = 0
- print(mario)
- pyboy.send_input(WindowEvent.PRESS_ARROW_RIGHT)
- for _ in range(1000):
- assert mario.fitness >= last_fitness
- last_fitness = mario.fitness
- pyboy.tick()
- if mario.lives_left == 1:
- assert last_fitness == 27700
- assert mario.fitness == 17700 # Loosing a live, means 10.000 points in this fitness scoring
- print(mario)
- break
- else:
- print("Mario didn't die?")
- exit(2)
- mario.reset_game()
- assert mario.lives_left == 2
- pyboy.stop()
如果在加載了Super Mario Land ROM的情況下運行上述代碼,則將在下面獲得類似圖片和終端的打印輸出。請注意,Mario的形狀顯示為索引0、1、16和17。
- Super Mario Land: World 1-1
- Coins: 0
- lives_left: 2
- Score: 0
- Time left: 400
- Level progress: 251
- Fitness: 0
- Sprites on screen:
- Sprite [3]: Position: (35, 112), Shape: (8, 8), Tiles: (Tile: 0), On screen: True
- Sprite [4]: Position: (43, 112), Shape: (8, 8), Tiles: (Tile: 1), On screen: True
- Sprite [5]: Position: (35, 120), Shape: (8, 8), Tiles: (Tile: 16), On screen: True
- Sprite [6]: Position: (43, 120), Shape: (8, 8), Tiles: (Tile: 17), On screen: True
- Tiles on screen:
- 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
- ____________________________________________________________________________________
- 0 | 339 339 339 339 339 339 339 339 339 339 339 339 339 339 339 339 339 339 339 339
- 1 | 320 320 320 320 320 320 320 320 320 320 320 320 320 320 320 320 320 320 320 320
- 2 | 300 300 300 300 300 300 300 300 300 300 300 300 321 322 321 322 323 300 300 300
- 3 | 300 300 300 300 300 300 300 300 300 300 300 324 325 326 325 326 327 300 300 300
- 4 | 300 300 300 300 300 300 300 300 300 300 300 300 300 300 300 300 300 300 300 300
- 5 | 300 300 300 300 300 300 300 300 300 300 300 300 300 300 300 300 300 300 300 300
- 6 | 300 300 300 300 300 300 300 300 300 300 300 300 300 300 300 300 300 300 300 300
- 7 | 300 300 300 300 300 300 300 300 310 350 300 300 300 300 300 300 300 300 300 300
- 8 | 300 300 300 300 300 300 300 310 300 300 350 300 300 300 300 300 300 300 300 300
- 9 | 300 300 300 300 300 129 310 300 300 300 300 350 300 300 300 300 300 300 300 300
- 10 | 300 300 300 300 300 310 300 300 300 300 300 300 350 300 300 300 300 300 300 300
- 11 | 300 300 310 350 310 300 300 300 300 306 307 300 300 350 300 300 300 300 300 300
- 12 | 300 368 369 300 0 1 300 306 307 305 300 300 300 300 350 300 300 300 300 300
- 13 | 310 370 371 300 16 17 300 305 300 305 300 300 300 300 300 350 300 300 300 300
- 14 | 352 352 352 352 352 352 352 352 352 352 352 352 352 352 352 352 352 352 352 352
- 15 | 353 353 353 353 353 353 353 353 353 353 353 353 353 353 353 353 353 353 353 353