如果你想開始做一些編程與pygame的直接使用精靈,這將是一個好主意,做可用教程的一些初步的研究得到一些基本的瞭解如何使用GUI和能夠處理用戶應用程序事件一般工作。
另一種選擇是從更簡單的事情開始,可以直接看到結果,而不需要編寫必要的(精靈需要組和類)龐大的初步代碼。
除了大量難以理解的Pygame sprites教程外,還有一些提供了很好的代碼示例和相當好的解釋。我建議你仔細看看:
Introduction to sprites --- sprite_collect_blocks.py
,然後再回來這裏與其他問題,如果有的話。
下面我提供了兩段代碼,以便您可以將它們彼此進行比較以查看我之前所講的內容。
兩者的第一部分是您自己的代碼,稍作修改。它在屏幕上創建了三個塊,它實際上與精靈無關(因爲在另一個答案中也是如此),但是顯示瞭如何用矩形填充顯示的Pygame屏幕。仔細閱讀另一個答案,因爲它們提供了你自己的代碼隨附的問題的良好解釋。
import pygame
WHITE = (255,255,255)
BLACK = (0,0,0)
RED = (255,0,0)
BLUE = (0,0,255)
# Set the height and width of the screen:
DISPLAY_width = 640
DISPLAY_height = 480
DISPLAY = pygame.display.set_mode([DISPLAY_width, DISPLAY_height])
DISPLAY.fill(WHITE)
# See here: [(3) stackoverflow.com/.../pygame-drawing-a-rectangle][3]
pygame.draw.rect(DISPLAY,BLACK,(120,40,50,50))
pygame.draw.rect(DISPLAY,RED ,(520,355,50,50))
pygame.draw.rect(DISPLAY,BLUE ,(320,240,50,50))
pygame.display.flip() # without .flip() you get only black screen
pygame.display.init() # IMPORTANT !
clock = pygame.time.Clock()
tick = 0
while tick < 100:
clock.tick(10)
tick += 1
# BETTER do it as follows:
"""
done = False
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
"""
pygame.quit()
import sys
sys.exit()
這裏什麼上面的代碼創建的屏幕截圖:
另一段代碼是實際使用代碼精靈。精靈通常與圖像一起使用。這就需要首先得到scripts目錄中的一些圖片:
這裏進入第二一段代碼(與TRUE精靈),它產生在屏幕上多MOTION(這裏只是一個靜態截圖)。所有的點是在運動以不同的速度填充所述最初黑屏黃色:
strPythonScriptHeader = """
# pygCodeSample_UsageOfGroupsAndSprites.py updated: 2017-04-12 09:17
# Copyright (c) 2005, Claudio at stackoverflow.com created: 2005-01-24 19:43
"""
# #############################################################################
# VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
def pygCodeSample_UsageOfGroupsAndSprites():
strMainInfo = """/*
WATCH OUT using pygame.sprite.Sprite and pygame.sprite.RenderClear classes:
- the order of Sprites in a Group is not necessary the order in which the
Sprites are drawn to the screen.
- the .clear() method of a Group clears the entire image square, not as
expected only the non-transparent part of it.
*/"""
print(strMainInfo)
strSpriteTutorial = """/*
The 'pygame.sprite' library provides classes representing images and
group of images which are to be drawn to the screen during the game.
The concept of a 'Sprite' is to provide a class which objects represent
real-world physical objects which can be viewed on the computer screen.
The Sprite class is not used directly. It is used to derive own classes
of customized Sprites from it:
class CustomizedSpriteDerivedFromSpriteClass(pygame.sprite.Sprite): ...
Within the definition of the CustomizedSpriteDerivedFromSpriteClass
it is necessary to define a member variable
.image (class CustomizedSpriteDerivedFromSpriteClass)
storing an 'Image' object which is to draw to the screen and the
member variable
.rect (class CustomizedSpriteDerivedFromSpriteClass)
storing a 'Rect' object holding the target position of the 'Image'
on the screen.
Usually both variables are set when running the
.__init__() (class CustomizedSpriteDerivedFromSpriteClass)
function which should contain as first command:
pygame.sprite.Sprite.__init__(self)
Further is it necessary to define also an
.update() (class CustomizedSpriteDerivedFromSpriteClass)
function which provides the code of rules telling how the by the Sprite
graphically represented physical objects should change when the .update()
function is executed.
The main purpose of a 'Sprite' is to be added to a container(called Group)
which is an object of the pygame.sprite.RenderClear class:
pGobjGroupOfSprites = pygame.sprite.RenderClear()
ready to hold any number of Sprite objects. A single Sprite is added to it
using
pGobjGroupOfSprites.add(pGobjCustomizedSpriteDerivedFromSpriteClass)
call.
The pGobjGroupOfSprites object of the pygame.sprite.RenderClear class is
equipped with following methods:
pGobjGroupOfSprites.clear(pGobjSCREENsurface, pGobjImage_SCREENsurfaceBackground)
pGobjGroupOfSprites.update()
pGobjGroupOfSprites.draw(pGobjSCREENsurface)
.draw() draws all Sprites to as parameter passed pGobjSCREENsurface
using the .image and .rect properties defined as member variables
within the CustomizedSpriteDerivedFromSpriteClass class.
.clear() draws those parts of the pGobjImage_SCREENsurfaceBackground image
to the pGobjSCREENsurface which are the Rects representing the
positions of the Sprites on the screen using the .rect property of Sprites.
.update() runs the .update() method of each Sprite stored in the GroupOfSprites.
Finally the main game loop looks like:
while True:
evaluateInputEvents()
pGobjGroupOfSprites_Hero.clear(pGobjSCREENsurface, pGobjImage_SCREENsurfaceBackground)
pGobjGroupOfSprites_Hero.update()
pGobjGroupOfSprites_Hero.draw(pGobjSCREENsurface)
pGobjGroupOfSprites_Enemy.clear(pGobjSCREENsurface, pGobjImage_SCREENsurfaceBackground)
pGobjGroupOfSprites_Enemy.update()
pGobjGroupOfSprites_Enemy.draw(pGobjSCREENsurface)
pGobjGroupOfSprites_Widgets.clear(pGobjSCREENsurface, pGobjImage_SCREENsurfaceBackground)
pGobjGroupOfSprites_Widgets.update()
pGobjGroupOfSprites_Widgets.draw(pGobjSCREENsurface)
adjustFrameRateTo(intTargetFrameRate) # time.sleep()/time.clock()
pGdefUpdateScreenWithDataStoredIn_pGobjSCREENsurface # == pygame.display.flip
#:while
How many and which Groups should be used and how to spread all the Sprites
used in the game over the defined Groups is part of the architecture of
the game code which is designed according to the needs of the game and the
individual programming style.
*/"""
print(strSpriteTutorial)
mPGvDctRectOfSCREENsurface = { 'left' : 0, 'right' : 640, 'top' : 0, 'bottom' : 480 }
mPGvIntScreenOriginX = mPGvDctRectOfSCREENsurface['left']
mPGvIntScreenOriginY = mPGvDctRectOfSCREENsurface['top']
mPGvIntScreenWidth = mPGvDctRectOfSCREENsurface['right'] - mPGvDctRectOfSCREENsurface['left']
mPGvIntScreenHeight = mPGvDctRectOfSCREENsurface['bottom'] - mPGvDctRectOfSCREENsurface['top']
mPGvTplScreenSize = (mPGvIntScreenWidth, mPGvIntScreenHeight)
import pygame
pGdefUpdateScreenWithDataStoredIn_pGobjSCREENsurface = pygame.display.flip
class pGobjCustomizedSprite_Dot(pygame.sprite.Sprite):
def __init__(self, strColorOfDot, tplVelocity):
# Intialize the Sprite class:
pygame.sprite.Sprite.__init__(self)
# .image property is used by the pGobjGroup hosting the sprite, so it is
# necessary to set it here in order to make this Sprite useful:
self.image = pygame.image.load(
r'dot-32x32_'+strColorOfDot+'.gif'
) # picture shows a coloured dot and has a transparent background
# .rect property is used by the pGobjGroup hosting the sprite, so it is
# necessary to set it here in order to make this Sprite useful:
self.rect = self.image.get_rect()
self.rect.centerx = 320
self.rect.centery = 240
# definition of other properties not necessary for usage of this class
# as a Sprite, but useful for internal purposes of setting the position
# of the rectangle within the .update() method:
self.x_velocity = tplVelocity[0]
self.y_velocity = tplVelocity[1]
#:def
# .update() method is used by the pGobjGroup hosting the sprite in its
# .update() command, so it is necessary to define it here in order to
# make this Sprite useful:
def update(self):
self.rect.move_ip((self.x_velocity, self.y_velocity))
if(self.rect.left <= 0 or self.rect.right >= mPGvIntScreenWidth):
self.x_velocity = -(self.x_velocity)
#:if
if self.rect.top <= 0 or self.rect.bottom >= mPGvIntScreenHeight:
self.y_velocity = -(self.y_velocity)
#:if
#:def
#:class
pygame.init()
# pGobjSCREENsurface = pygame.display.set_mode(mPGvTplScreenSize, pygame.constants.DOUBLEBUF)
pGobjSCREENsurface = pygame.display.set_mode(mPGvTplScreenSize) # faster than with DOUBLEBUF
pGobjGroupOfSprites_spriteDot = pygame.sprite.RenderClear()
pGobjImage_SCREENsurfaceBackground = pygame.image.load(
r'rect-640x480_yellow.bmp'
) # picture shows yellow background
intLstLength = 0
dctTplVelocity = {}
import random
while(intLstLength < 5):
tplVelocity = (random.randint(1, 5), random.randint(1, 5))
if(tplVelocity in dctTplVelocity): pass
else:
intLstLength+=1
dctTplVelocity[tplVelocity] = intLstLength
#:if/else
#:while
lstTplVelocity = list(dctTplVelocity.keys())
# pGspriteRedDot = pGobjCustomizedSprite_Dot('red' ,lstTplVelocity[0])
# pGspriteWhiteDot = pGobjCustomizedSprite_Dot('purple',lstTplVelocity[1])
# pGspriteGreyDot = pGobjCustomizedSprite_Dot('grey' ,lstTplVelocity[2])
# pGspriteBlueDot = pGobjCustomizedSprite_Dot('blue' ,lstTplVelocity[3])
# pGspriteOrangeDot = pGobjCustomizedSprite_Dot('orange',lstTplVelocity[4])
pGobjGroupOfSprites_spriteDot.add(pGobjCustomizedSprite_Dot('red' ,lstTplVelocity[0]))
pGobjGroupOfSprites_spriteDot.add(pGobjCustomizedSprite_Dot('purple',lstTplVelocity[1]))
pGobjGroupOfSprites_spriteDot.add(pGobjCustomizedSprite_Dot('grey' ,lstTplVelocity[2]))
pGobjGroupOfSprites_spriteDot.add(pGobjCustomizedSprite_Dot('blue' ,lstTplVelocity[3]))
pGobjGroupOfSprites_spriteDot.add(pGobjCustomizedSprite_Dot('orange',lstTplVelocity[4]))
print
print(' target frame rate [frames/second] == 100.0 : ')
intLoopCounter = 0
import time
clock = time.clock
sleep = time.sleep
import sys
fltTime=clock()
fltStartTime = clock()
blnExitMainGameLoop = False
fltFrameRate = 100.0
fltTimeToNextFrame = 1.0/fltFrameRate
import time
while True:
time.sleep(0.03)
# ---
# -----------------------------------------------------
# Processing of user input:
pGlstObjEvent = pygame.event.get()
for pGobjEvent in pGlstObjEvent:
if pGobjEvent.type == pygame.constants.QUIT:
blnExitMainGameLoop = True
#:if
if pGobjEvent.type == pygame.constants.KEYDOWN:
if pGobjEvent.key == pygame.constants.K_ESCAPE:
blnExitMainGameLoop = True
if pGobjEvent.key == pygame.constants.K_s:
time.sleep(21)
blnExitMainGameLoop = False
#:if
#:if
#:for
if(blnExitMainGameLoop):
pygame.display.quit()
break
#:if
# ---
# -----------------------------------------------------
# output of texts with infos to console window:
if(intLoopCounter%100 == 99):
print(' %5.2f '%(fltFrameRate/(clock()-fltTime),),)
fltTime=clock()
#:if
intLoopCounter += 1
# print intLoopCounter,
# ---
# -----------------------------------------------------
# preparing and drawing graphic output to screen:
pGobjGroupOfSprites_spriteDot.update()
pGobjGroupOfSprites_spriteDot.clear(pGobjSCREENsurface, pGobjImage_SCREENsurfaceBackground)
pGobjGroupOfSprites_spriteDot.draw(pGobjSCREENsurface)
# ---
# -----------------------------------------------------
# adjusting frame rate to 100 frames/second:
# fltFrameRate = 100.0
# fltTimeToNextFrame = 1.0/fltFrameRate
fltTargetTime = fltTimeToNextFrame*intLoopCounter
fltTimeDiff = fltTargetTime-(clock()-fltStartTime)
if(fltTimeDiff > 0.8*fltTimeToNextFrame): sleep(0.8*fltTimeToNextFrame)
fltTimeDiff = fltTargetTime-(clock()-fltStartTime)
if(fltTimeDiff > 0.1*fltTimeToNextFrame): sleep(0.1*fltTimeToNextFrame)
fltTimeDiff = fltTargetTime-(clock()-fltStartTime)
while(fltTimeDiff > 0):
fltTimeDiff = (fltTimeToNextFrame*intLoopCounter)-(clock()-fltStartTime)
#:while
# ---
# -----------------------------------------------------
# displaying prepared graphic output:
pGdefUpdateScreenWithDataStoredIn_pGobjSCREENsurface()
#:while
#:def pygCodeSample_UsageOfGroupsAndSprites()
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
if __name__ == '__main__':
print(strPythonScriptHeader)
pygCodeSample_UsageOfGroupsAndSprites()
import sys
if int(sys.version[0]) < 3 : # Python 2 :
raw_input('(exit with ENTER) #> OK? ')
sys.exit()
else: # Python 3 :
input('(exit with ENTER) #> OK? ')
sys.exit()
#:if
pygameConstantsForUsageInKeyEVENTS = ['ACTIVEEVENT', 'ANYFORMAT', 'ASYNCBLIT', 'AUDIO_S16', 'AUDIO_S16LSB', 'AUDIO_S16MSB', 'AUDIO_S16SYS', 'AUDIO_S8', 'AUDIO_U16', 'AUDIO_U16LSB', 'AUDIO_U16MSB', 'AUDIO_U16SYS', 'AUDIO_U8', 'BIG_ENDIAN', 'BLEND_ADD', 'BLEND_MAX', 'BLEND_MIN', 'BLEND_MULT', 'BLEND_PREMULTIPLIED', 'BLEND_RGBA_ADD', 'BLEND_RGBA_MAX', 'BLEND_RGBA_MIN', 'BLEND_RGBA_MULT', 'BLEND_RGBA_SUB', 'BLEND_RGB_ADD', 'BLEND_RGB_MAX', 'BLEND_RGB_MIN', 'BLEND_RGB_MULT', 'BLEND_RGB_SUB', 'BLEND_SUB', 'BUTTON_X1', 'BUTTON_X2', 'DOUBLEBUF', 'FULLSCREEN', 'GL_ACCELERATED_VISUAL', 'GL_ACCUM_ALPHA_SIZE', 'GL_ACCUM_BLUE_SIZE', 'GL_ACCUM_GREEN_SIZE', 'GL_ACCUM_RED_SIZE', 'GL_ALPHA_SIZE', 'GL_BLUE_SIZE', 'GL_BUFFER_SIZE', 'GL_DEPTH_SIZE', 'GL_DOUBLEBUFFER', 'GL_GREEN_SIZE', 'GL_MULTISAMPLEBUFFERS', 'GL_MULTISAMPLESAMPLES', 'GL_RED_SIZE', 'GL_STENCIL_SIZE', 'GL_STEREO', 'GL_SWAP_CONTROL', 'HAT_CENTERED', 'HAT_DOWN', 'HAT_LEFT', 'HAT_LEFTDOWN', 'HAT_LEFTUP', 'HAT_RIGHT', 'HAT_RIGHTDOWN', 'HAT_RIGHTUP', 'HAT_UP', 'HWACCEL', 'HWPALETTE', 'HWSURFACE', 'IYUV_OVERLAY', 'JOYAXISMOTION', 'JOYBALLMOTION', 'JOYBUTTONDOWN', 'JOYBUTTONUP', 'JOYHATMOTION', 'KEYDOWN', 'KEYUP', 'KMOD_ALT', 'KMOD_CAPS', 'KMOD_CTRL', 'KMOD_LALT', 'KMOD_LCTRL', 'KMOD_LMETA', 'KMOD_LSHIFT', 'KMOD_META', 'KMOD_MODE', 'KMOD_NONE', 'KMOD_NUM', 'KMOD_RALT', 'KMOD_RCTRL', 'KMOD_RMETA', 'KMOD_RSHIFT', 'KMOD_SHIFT', 'K_0', 'K_1', 'K_2', 'K_3', 'K_4', 'K_5', 'K_6', 'K_7', 'K_8', 'K_9', 'K_AMPERSAND', 'K_ASTERISK', 'K_AT', 'K_BACKQUOTE', 'K_BACKSLASH', 'K_BACKSPACE', 'K_BREAK', 'K_CAPSLOCK', 'K_CARET', 'K_CLEAR', 'K_COLON', 'K_COMMA', 'K_DELETE', 'K_DOLLAR', 'K_DOWN', 'K_END', 'K_EQUALS', 'K_ESCAPE', 'K_EURO', 'K_EXCLAIM', 'K_F1', 'K_F10', 'K_F11', 'K_F12', 'K_F13', 'K_F14', 'K_F15', 'K_F2', 'K_F3', 'K_F4', 'K_F5', 'K_F6', 'K_F7', 'K_F8', 'K_F9', 'K_FIRST', 'K_GREATER', 'K_HASH', 'K_HELP', 'K_HOME', 'K_INSERT', 'K_KP0', 'K_KP1', 'K_KP2', 'K_KP3', 'K_KP4', 'K_KP5', 'K_KP6', 'K_KP7', 'K_KP8', 'K_KP9', 'K_KP_DIVIDE', 'K_KP_ENTER', 'K_KP_EQUALS', 'K_KP_MINUS', 'K_KP_MULTIPLY', 'K_KP_PERIOD', 'K_KP_PLUS', 'K_LALT', 'K_LAST', 'K_LCTRL', 'K_LEFT', 'K_LEFTBRACKET', 'K_LEFTPAREN', 'K_LESS', 'K_LMETA', 'K_LSHIFT', 'K_LSUPER', 'K_MENU', 'K_MINUS', 'K_MODE', 'K_NUMLOCK', 'K_PAGEDOWN', 'K_PAGEUP', 'K_PAUSE', 'K_PERIOD', 'K_PLUS', 'K_POWER', 'K_PRINT', 'K_QUESTION', 'K_QUOTE', 'K_QUOTEDBL', 'K_RALT', 'K_RCTRL', 'K_RETURN', 'K_RIGHT', 'K_RIGHTBRACKET', 'K_RIGHTPAREN', 'K_RMETA', 'K_RSHIFT', 'K_RSUPER', 'K_SCROLLOCK', 'K_SEMICOLON', 'K_SLASH', 'K_SPACE', 'K_SYSREQ', 'K_TAB', 'K_UNDERSCORE', 'K_UNKNOWN', 'K_UP', 'K_a', 'K_b', 'K_c', 'K_d', 'K_e', 'K_f', 'K_g', 'K_h', 'K_i', 'K_j', 'K_k', 'K_l', 'K_m', 'K_n', 'K_o', 'K_p', 'K_q', 'K_r', 'K_s', 'K_t', 'K_u', 'K_v', 'K_w', 'K_x', 'K_y', 'K_z', 'LIL_ENDIAN', 'MOUSEBUTTONDOWN', 'MOUSEBUTTONUP', 'MOUSEMOTION', 'NOEVENT', 'NOFRAME', 'NUMEVENTS', 'OPENGL', 'OPENGLBLIT', 'PREALLOC', 'QUIT', 'RESIZABLE', 'RLEACCEL', 'RLEACCELOK', 'SCRAP_BMP', 'SCRAP_CLIPBOARD', 'SCRAP_PBM', 'SCRAP_PPM', 'SCRAP_SELECTION', 'SCRAP_TEXT', 'SRCALPHA', 'SRCCOLORKEY', 'SWSURFACE', 'SYSWMEVENT', 'TIMER_RESOLUTION', 'USEREVENT', 'USEREVENT_DROPFILE', 'UYVY_OVERLAY', 'VIDEOEXPOSE', 'VIDEORESIZE', 'YUY2_OVERLAY', 'YV12_OVERLAY', 'YVYU_OVERLAY', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__']
上述代碼配備有大體積的評論。正如我多年前從pygame開始並試圖瞭解精靈時所寫的,目標是寫得清楚明瞭,以便理解。現在你可以判斷自己,我的風格是不言自明的變量命名和提供的解釋和信息,是多麼的成功。
你用白色填充表面,然後設置白色的colorkey。刪除的顏色鍵,它應該工作。關於colorkeys [這裏](http://stackoverflow.com/documentation/pygame/7079/drawing-on-the-screen/23788/transparency#t=201704140013573679697) –
這是比這更錯誤。 – jsbueno