在尝试了解Pygame中的精灵时,我遇到了一些问题。
首先,我已经为精灵投入了大量的精力,但是我没有让它发挥作用。
在将一个对象绘制到一个精灵上时,我确实完成了互联网上的指南,但是在运行程序时对象没有出现。
任何建议都非常受欢迎!
tick = 0
sprite = pygame.Surface([20, 20])
sprite.fill(white)
sprite.set_colorkey(white)
rect = sprite.get_rect()
rect.x = 400
rect.y = 300
while tick < 100:
screen.fill(black)
pygame.draw.rect(sprite, red, [rect.x, rect.y, 20, 20])
pygame.display.update()
clock.tick(10)
tick += 1
pygame.quit()
quit()
答案 0 :(得分:0)
因此,您的代码存在两个主要问题。
首先,你正在用#34; white&#34;填充你正在调用sprite的表面。然后只需设置&#34; white&#34;通过调用set_colorkey
将其视为该表面的透明色。所以,无论如何都没有任何表现。
其次,您在Surface表面上绘制矩形,而不是在屏幕上绘制。所以,你把它漆成了红色,但是你不会stamp&#34;盖章&#34;它在屏幕上 - 你调用pygame.draw.rect
来绘制你正在调用精灵本身的Surface,而不是在屏幕上。
你的代码根本没有显示你声明一个屏幕 - 我想你是这样做的,但请记住,你总是应该发布一个完整的例子来获得你到达的行为。如果您的代码中存在设置屏幕的错误,我无法了解它。另外,我已将我们的调用更改为draw.rect
来调用screen.blit
:这会在blit方法的曲面所有者上标记当前sprite上的任何图像 - 在这种情况下,屏幕本身:
import pygame
screen = pygame.display.set_mode((800,600))
white = 255, 255, 255
tick = 0
sprite = pygame.Surface([20, 20])
sprite.fill(white)
sprite.set_colorkey(white)
rect = sprite.get_rect()
rect.x = 400
rect.y = 300
while tick < 100:
screen.fill(black)
screen.blit(sprite, (rect.x, rect.y))
pygame.display.update()
clock.tick(10)
tick += 1
pygame.quit()
quit()
有了它你很快就会看到一个白色矩形 - 从它们开始你可以开始改进你的代码以延迟程序结束,或等待用户事件关闭屏幕并让事情滚动。
顺便说一句,在Pygame的谈话中,Surface并不是一个精灵&#34;精灵&#34; - Sprite
是一个特殊类,意在被用作&#34;组&#34;的成员。当您开始组织更完整的游戏或动画序列时,一系列辅助函数将起作用。
答案 1 :(得分:0)
Pygame documents是个好朋友。
1.为什么要填充sprite
白色然后将其颜色键设置为白色?这只会让精灵变得透明。请参阅set_colorkey。
sprite = pygame.Surface([20, 20])
sprite.fill(white)
sprite.set_colorkey(white)
如果您需要红色sprite
,只需创建一个并将其填充为红色。
sprite = pygame.Surface((20, 20))
sprite.fill(red)
2. pygame.draw.rect
做什么只是在Surface
上画一个矩形。因此,如果您想在屏幕上绘制红色矩形,只需
pygame.draw.rect(screen, red, (0, 0, 20, 20))
或者,如果您想在屏幕上显示精灵(通常更有效),请使用blit
screen.blit(sprite, (0, 0))
享受pygame的乐趣:)
答案 2 :(得分:-1)
如果你想直接使用精灵开始使用Pygame进行一些编程,那么对可用教程做一些初步研究是个好主意,以便基本了解使用GUI并能够处理用户事件的应用程序是如何工作的。
另一个选择是从更简单的事情开始,直接看到结果而不需要编写必要的(精灵需要组和类)大量的初步代码。
除了大量难以理解的关于Pygame sprites的教程,还有一些提供了很好的代码示例和很好的解释。我建议你仔细看看:
如果有任何其他问题,请回到这里。
下面我提供了两段代码,以便您可以将它们相互比较,看看我上面谈到的内容。
这两个中的第一部分是您自己的代码,略有修改。它在屏幕上创建了三个块,它实际上与sprite无关(在另一个答案中也是如此),但是展示了如何用矩形填充显示的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()
这里是上面代码创建的屏幕截图:
另一段代码是使用精灵的实际代码。精灵通常与图像一起使用。这使得必须首先在脚本目录中获取一些图像:
这里是第二段代码(带有TRUE sprites),它在屏幕上产生很多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开始编写它并尝试理解精灵一样,目标是将其写得非常清楚,以便易于理解。现在,您可以通过我的自解释变量命名方式以及提供的解释和信息来判断自己的成功程度。