[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

[pygame] Re: fundamental (stupid) question about blitting part of a background image



So: blit the background every frame, then the stars atop that. If you really want, you can "kill the stars" by blitting pixels from the background surface, but that's probably slower than blitting the whole thing. Does this help?

Kris


Hi Kris,
thank you for clearing my eyes... i could have seen the solution all the time but i was like blind !
While i was aware that i dont need the kill_stars function any more once the blitting would work, i never come to the idea of just blitting the
whole background every frame (and updating only a rect).


Now it works !

here is the whole listing (you need to make a 'data' subdirectory and put a (ideally white) 'background.jpg' into it.






======================================


#!/usr/bin/env python

"""A simple starfield example. Note you can move the 'center' of
the starfield by leftclicking in the window. This example show
the basics of creating a window, simple pixel plotting, and input
event management"""


import random, math, pygame, os, time from pygame.locals import *

#constants
WINSIZE = [640, 480]
WINCENTER = [320, 240]
NUMSTARS = 200
SCREENRECT  = Rect(0, 0, 640, 480)
GRAD = math.pi/180


##def initialize_stars(): ## "creates a new starfield" ## stars = [] ## for x in range(NUMSTARS/4): ## star = init_star() ## vel, pos = star ## steps = random.randint(0, WINCENTER[0]) ## pos[0] = pos[0] + (vel[0] * steps) ## pos[1] = pos[1] + (vel[1] * steps) ## vel[0] = vel[0] * (steps * .09) ## vel[1] = vel[1] * (steps * .09) ## stars.append(star) ## move_stars(stars, False) ## return stars

def load_image(file, colorkey=None):
"loads an image, prepares it for play, set Backgroundcolor at point 0,0 invisible if no second argument is given at calling "
file = os.path.join('data', file)
try:
surface = pygame.image.load(file)
except pygame.error:
raise SystemExit, 'Could not load image "%s" %s'%(file, pygame.get_error())
if colorkey is None:
colorkey = surface.get_at((0,0))
surface.set_colorkey(colorkey, RLEACCEL)
elif colorkey <> -1:
surface.set_colorkey(colorkey, RLEACCEL)
return surface.convert()





def init_star(direction = 0, arc = 45): "creates new star values" #direction = 0 # 0 = 360 = rechts, 90 = oben #dir = (random.random()*math.pi+0) + (math.pi/180)* direction #180 acr #dir = (random.random()*math.pi/2+45) + (math.pi/180)* direction dir = ((random.random()*GRAD*arc - GRAD*(arc/2) + GRAD * direction)) velmult = random.random()*1.6+.4 vel = [math.sin(dir) * velmult, math.cos(dir) * velmult] age = [0.0] return age, vel, WINCENTER[:]



def draw_stars(surface, stars, color):
        "used to draw (and clear) the stars"
        for age, vel, pos in stars:
            pos = (int(pos[0]), int(pos[1]))
            if age[0] <= 2:
               pygame.draw.circle(surface, color, pos, age[0]/2 ,0)
            else:
               pygame.draw.circle(surface, color, pos, age[0]/2, 1)

##def kill_stars(surface, stars, color):
##        "used to clear the stars with the background color"
##        for age, vel, pos in stars:
##            pos = (int(pos[0]), int(pos[1]))
##            if age[0] <= 2:
##               pygame.draw.circle(surface, color, pos, age[0]/2 ,0)
##            else:
##               pygame.draw.circle(surface, color, pos, age[0]/2, 1)




def move_stars(stars, NoMoreStars):
"animate the star values"
if len(stars) < NUMSTARS and not NoMoreStars:
stars.append(init_star())
MINX = WINCENTER[0]
MAXX = WINCENTER[0]
MINY = WINCENTER[1]
MAXY = WINCENTER[1]
MAXAGE = 0
for age, vel, pos in stars:
age[0] = age[0] + .1
pos[0] = pos[0] + vel[0]
pos[1] = pos[1] + vel[1]
if age[0] > MAXAGE:
MAXAGE = age[0]
if int(pos[0]) < MINX:
MINX = int(pos[0])
if int(pos[0]) > MAXX:
MAXX = int(pos[0])
if int(pos[1]) < MINY:
MINY = int(pos[1])
if int(pos[1]) > MAXY:
MAXY = int(pos[1])
if not 0 <= pos[0] <= WINSIZE[0] or \
not 0 <= pos[1] <= WINSIZE[1] or \
abs(vel[0]) <= 0.1 and abs(vel[1]) <= 0.2:
if NoMoreStars == True:
stars.remove((age, vel,pos))
else:
age[:] , vel[:], pos[:] = init_star()
else:
vel[0] = vel[0] * .99
vel[1] = vel[1] * .99
return MINX - MAXAGE , MINY - MAXAGE , MAXX + MAXAGE , MAXY + MAXAGE




def main():

	"This is the starfield code"
	#create our starfield
	random.seed()
	#stars = initialize_stars()
	stars=[]
        clock = pygame.time.Clock()
	#initialize and prepare screen
	pygame.init()
	screen = pygame.display.set_mode(WINSIZE)
	pygame.display.set_caption('pygame Stars Example')
	white = 255, 240, 200
	black = 20, 20, 40
	#screen.fill(black)
        #print NoMoreStars


MINX = WINCENTER[0] MAXX = WINCENTER[0]+1 MINY = WINCENTER[1] MAXY = WINCENTER[1]+1

#create the background, tile the bgd image
bgdtile = load_image('background.jpg', -1) # -1 avoid conversion to transparent background
background = pygame.Surface(SCREENRECT.size)
for x in range(0, SCREENRECT.width, bgdtile.get_width()):
for y in range(0, SCREENRECT.height, bgdtile.get_height()):
background.blit(bgdtile, (x, y))
screen.blit(background, (0,0))
framecounter = 0
seconds = time.localtime()[5]
#main game loop
done = 0
pygame.display.update()
NoMoreStars = False
while not done:
#kill_stars(screen, stars, white) # delete
#oground = pygame.Surface(Rect(MINX,MINY,MAXX-MINX,MAXY-MINY).size)
#screen.blit(oground, (MINX,MINY))
#screen.blit(oground,(0,0))
screen.blit(background, (0,0))
MINX, MINY, MAXX, MAXY = move_stars(stars, NoMoreStars)
draw_stars(screen, stars, black) # draw new
pygame.display.update(MINX,MINY, MAXX-MINX, MAXY-MINY)
#print MINX, MINY, MAXX, MAXY
#pygame.display.update()
for e in pygame.event.get():
if e.type == QUIT or (e.type == KEYUP and e.key == K_ESCAPE):
done = 1
break
elif e.type == KEYDOWN and e.key == K_SPACE:
NoMoreStars = not NoMoreStars
#print NoMoreStars
elif e.type == MOUSEBUTTONDOWN and e.button == 1:
WINCENTER[:] = list(e.pos)
clock.tick(80)
# fps ?
framecounter += 1
if time.localtime()[5] != seconds:
seconds = time.localtime()[5]
print "FPS:", str(framecounter)
framecounter = 0


# if python says run, then we should run
if __name__ == '__main__':
	main()