PyGame NotImplementedError - PullRequest
       59

PyGame NotImplementedError

0 голосов
/ 24 декабря 2018

Я создал приложение pygame, использующее PyInstaller, но по какой-то причине, когда я его открываю, оно вызывает NotImplementedError, если обнаруживается, что эта ошибка возникает в функции _has в строке 1663 init .py вpkg-resources но я не уверен почему его так называют.Я попытался отследить его настолько далеко, насколько смогу, и пока не могу найти связь между pkg-ресурсами и pygame.Exe работал с предыдущей версией, которая не включала текст, поэтому я попытался импортировать pygame._view, но это не сработало.Я получаю эту ошибку только с исполняемым файлом, при запуске в Visual Studio или Python IDE он работает отлично.Вот мой код игры:

import pygame as p, random as r, time as t, sys, tkinter as tk

if False:
    import p._view

width, height = 640, 480 #Initial screen width & height
x, y, vel = 0, 0, [1, 1] #Makes coordinates and velocity
showInfo = False #sets bool to show display info
fullscr = False #sets bool to toggle full screen
iter = False #sets iteration bool for fullscreen toggles
catch = False #sets catch bool for fullscreen toggles
showHelp = False #sets the bool to bring up the help menu
showMenuHelp = True #sets the bool to toggle the --Press H for help--
c = 0 #sets counter for corner hits
h = 0 #sets counter for total hits
corners = [(width-29, height-19), (29, 19), (width-29, 19), (29, height-19)] #defiones list of all corner coordinates
helpmsg = ["----Help----", "F3: Show live in-game information", "F11: Fullscreen toggle", "r: set the logo to the center of the screen", "h: Toggle this menu"] #defines list of lines in the help message
DVD = p.image.load('sprites\\w.png') #Loads a sprite
DVDRECT = DVD.get_rect() #Makes object for the sprites to be loaded onto
p.display.set_caption('DVD')#Sets executable capton
screen = p.display.set_mode((width, height), p.RESIZABLE) #Sets screen to resizable mode
fps = 90 #sets FPS
clock = p.time.Clock() #sets FPS clock
p.init() #Initialize Pygame
Font = p.font.Font('freesansbold.ttf', 12) #initializes font
more = Font.render("--Press H for help--", True, (255, 255, 255)) #makes default on boot helper
morerect = more.get_rect() #makes surface for default on boot helper

x, y = r.choice([570, 571, 572]), r.choice([420, 421, 422]) #sets the start location

#Loads in sprites
wht = p.image.load('sprites\\w.png')
blu = p.image.load('sprites\\b.png')
pnk = p.image.load('sprites\\p2.png')
pur = p.image.load('sprites\\p.png')
grn = p.image.load('sprites\\g.png')
org = p.image.load('sprites\\o.png')
ylw = p.image.load('sprites\\y.png')
p.display.set_icon(wht)

def new_color():
    """
    Function for getting random colors
    """
    return r.choice([wht, blu, pnk, pur, grn, org, ylw])

def get_info():
    """
    Function for getting in game live information
    """
    info = p.display.Info() #creates object to get information
    mem = str(info.video_mem) + "mb" #gets vram being used

    #checks for accelerated hardware
    if info.hw:
        accel = "Accerated Hardware: True"
    else:
        accel = "Accerated Hardware: False"

    #checks to see if windowed display modes are availble
    if info.wm:
        disMode = "Window Options: True"
    else:
        disMode = "Window Options: False"


    curPosX, curPosY = DVDRECT.center[0], DVDRECT.center[1] #gets current position of logo
    curW, curH = info.current_w, info.current_h #gets current width and height of window
    fps = round(clock.get_fps())#gets current fps (in interger)

    #checks if there is no vram
    if mem == "0mb":
        mem = "Unknown"

    #gets current color of the DVD logo
    if DVD == wht:
        color = "Color: White"
    if DVD == blu:
        color = "Color: Blue"
    if DVD == pnk:
        color = "Color: Pink"
    if DVD == pur:
        color = "Color: Purple"
    if DVD == grn:
        color = "Color: Green"
    if DVD == org:
        color = "Color: Orange"
    if DVD == ylw:
        color = "Color: Yellow"

    hits = "Total hits: "+str(h) #gets total hits
    corner = "Corner hits: "+str(c) #gets corner hits

    return ["Memory Use: "+str(mem),"DVD X: "+str(curPosX)+" Y: "+str(curPosY), "Screen Width: "+str(curW)+" Height: "+str(curH), "FPS: "+str(fps), hits, corner, accel, disMode, color]

while True:
    for event in p.event.get():
        #Exits if user closes window
        if event.type == p.QUIT:
            print("exiting")
            p.quit()
            sys.exit()

        if event.type == p.KEYUP:
            #toggles info menu
            if event.key == p.K_F3:
                if showInfo:
                    print("hiding info")
                    showInfo = False
                else:
                    print("showing info")
                    showInfo = True

            #toggles fullscreen
            if event.key == p.K_F11:
                if True != fullscr:
                    fullscr = True
                    iter = False
                    root = tk.Tk()
                    scrw = root.winfo_screenwidth()
                    scrh = root.winfo_screenheight()
                    if width != scrw or scrh != height:
                        screen = p.display.set_mode((scrw, scrh), p.RESIZABLE)
                    else:
                        screen = p.display.set_mode((0, 0), p.FULLSCREEN)
                else:
                    fullscr = False
                    screen = p.display.set_mode((640, 480), p.RESIZABLE)

            #resets the logo to the center of the window
            if event.key == p.K_r:
                info = p.display.Info()
                x, y = round(info.current_w/2), round(info.current_h/2)

            #toggles help menu
            if event.key == p.K_h:
                if showHelp:
                    showHelp = False
                else:
                    showHelp = True
                showMenuHelp = False

            #toggles default on boot helper
            if event.key == p.K_s:
                if showMenuHelp:
                    showMenuHelp = False
                else:
                    showMenuHelp = True

        #checks if the user changed window dimensions and adjust the game surface accordingly
        if event.type == p.VIDEORESIZE:
            scrsize = event.size
            screen = p.display.set_mode(scrsize, p.RESIZABLE)
            width, height = scrsize[0], scrsize[1]
            if DVDRECT.center[0] >= width-29:
                y = DVDRECT.center[1]
                x = width-30
                DVDRECT.center = (x, y)
            if DVDRECT.center[1] >= height-19:
                y = height-20
                DVDRECT.center = (x, y)
            corners = [(width-29, height-19), (29, 19), (width-29, 19), (29, height-19)]

    #Makes new coordinates:
    x += vel[0]
    y += vel[1]

    #checks if logo hits a corner
    if (x, y) in corners:
        print("corner")
        c += 1

    #Checks if logo hits a wall
    if x >= width-29:
        print("right")
        vel[0] = -vel[0] #Makes logo 'bounce' off wall
        DVD = new_color() #Sets a new color to the logo
        p.display.set_icon(DVD) #Sets icon to same color as logo
        h += 1 #Adds one total hit counter

    if x <= 29:
        print("left")
        vel[0] = -vel[0]
        DVD = new_color()
        p.display.set_icon(DVD)
        h += 1

    if y >= height-19:
        print("bottom")
        vel[1] = -vel[1]
        DVD = new_color()
        p.display.set_icon(DVD)
        h += 1

    if y <= 19:
        print("top")
        vel[1] = -vel[1]
        DVD = new_color()
        p.display.set_icon(DVD)
        h += 1

    DVDRECT.center = (x, y) #moves the logo
    screen.fill((0, 0, 0)) #sets background to black
    screen.blit(DVD, DVDRECT) #Updates logo
    Iy = 6 #sets text starting Y coordinate

    #shows live info menu
    if showInfo:
        info = get_info()
        for i in info:
            curIn = Font.render(i, True, (255,255,255))
            curInRect = curIn.get_rect()
            curInRect.center = (round(curInRect.w/2), Iy)
            screen.blit(curIn, curInRect)
            Iy += 12

    #shows help menu
    if showHelp:
        for i in helpmsg:
            help = Font.render(i, True, (255, 255, 255))
            helprect = help.get_rect()
            helprect.center = (round(helprect.w/2), Iy)
            screen.blit(help, helprect)
            Iy += 12
    else:
        #shows default on boot helper
        if showMenuHelp:
            morerect.center = (round(morerect.w/2), Iy)
            screen.blit(more, morerect)

    #sets to fullscreen 1 frame after surface is resized to the display resolution
    if fullscr and iter and catch:
        screen = p.display.set_mode((0, 0), p.FULLSCREEN)
        catch = False

    #sets bools to make the previous IF statment run in the next frame
    if fullscr and iter != True:
        iter = True
        catch = True

    p.display.update() #updates screen
    clock.tick(fps) #updates fps clock

Я также попытался вставить папку pygame с помощью freesansbold.ttf, но это тоже не сработало.Сообщения об ошибках отображаются следующим образом:

Traceback (most recent call last):
    File "DVD.py", line 25, in <module>
    File "site-packages\pygame\pkgdata.py", line 50, in getResource
    File "site-packages\pkg-resources\__init__.py", line 1150, in resource_exists
    File "site-packages\pkg-resources\__init__.py", line 1608, in has_resource
    File "site-packages\pkg-resources\__init__.py", line 1663, in _has
NotImplementedError: Can't perform this operation for unregistered loader type [696] Failed to execute script DVD

Я буду делать все возможное, чтобы выяснить, почему это происходит, и помощь приветствуется.Я также могу поместить файлы на GitHub, если это будет необходимо.

1 Ответ

0 голосов
/ 06 января 2019

Я наконец-то понял это, мне пришлось сохранить файл ttf в том же каталоге, что и код.Это работает для компиляции приложения в папку, но для одного файла вы должны изменить код.

def rp(relative_path):
    """ Get absolute path to resource, works for dev and for PyInstaller """
    try:
        # PyInstaller creates a temp folder and stores path in _MEIPASS
        base_path = sys._MEIPASS
    except Exception:
        base_path = os.path.abspath(".")

    return os.path.join(base_path, relative_path)

после добавления этой функции вы должны вызывать ее с именем и расширением файла, который вы хотите использоватьПример:

rp('freesansbold.ttf')

, чтобы инициализировать шрифт, просто сделайте это:

Font = p.font.Font(rp('freesansbold.ttf'), 12) #initializes font

он работает так же для изображений, которые я тоже использовал, но я взял их вПапка Sprites и упаковка каждой картинки индивидуально с программой.Вот файл спецификации для Pyinstaller:

# -*- mode: python -*-

block_cipher = None


a = Analysis(['DVD.py'],
             pathex=['C:\\Users\\Kaden\\Desktop\\dvd builds'],
             binaries=[],
             datas=[('./w.png', '.'), ('./b.png', '.'), ('./g.png', '.'), ('./o.png', '.'), ('./p.png', '.'), ('./p2.png', '.'), ('./y.png', '.'), ('./freesansbold.ttf', '.')],
             hiddenimports=[],
             hookspath=[],
             runtime_hooks=[],
             excludes=[],
             win_no_prefer_redirects=False,
             win_private_assemblies=False,
             cipher=block_cipher,
             noarchive=False)
pyz = PYZ(a.pure, a.zipped_data,
             cipher=block_cipher)
exe = EXE(pyz,
          a.scripts,
          a.binaries,
          a.zipfiles,
          a.datas,
          [],
          name='DVD',
          debug=False,
          bootloader_ignore_signals=False,
          strip=False,
          upx=True,
          runtime_tmpdir=None,
          console=False , icon='icon.ico')

, затем просто вызовите pyinstaller, как вы обычно это делаете:

pyinstaller DVD.spec
...