Skip to content

Instantly share code, notes, and snippets.

@evgenidb
Created August 19, 2011 20:19
Show Gist options
  • Save evgenidb/1157904 to your computer and use it in GitHub Desktop.
Save evgenidb/1157904 to your computer and use it in GitHub Desktop.
Snake Game - Background Map Test
try:
import pygame
from pygame.locals import *
import sys, os, random
except ImportError as err:
print ('{0} Failed to Load Module: {1}').format(__file__, err)
sys.exit(1)
class Snake(pygame.sprite.Sprite):
pass
class Grass(pygame.sprite.Sprite):
"""A grass sprite. Has a level and position."""
def __init__(self, xy, images, which=None, *, collision=False, randomize=False, randFps=0):
pygame.sprite.Sprite.__init__(self)
self.sprType = 'grass'
# save images and pick one to display
self.images = images
self.imagesLen = len(images)
if which == None:
which = random.randint(1, self.imagesLen)
self.which = which
# set the image and rect so they can be rendered
self.image = self.images[self.which]
self.rect = self.image.get_rect()
# set initial position
self.rect.center = xy
self.xy = xy
# Collision?
self.collision = collision
# be randomized from time to time, randFps - frames between two changes
self.randomized = randomize
self.randFps = randFps if randFps > 0 else 0
if randFps == 0:
self.randomized = False
def changeTile(self, fps, *, which=None):
if fps % self.randFps == 0:
if which is None:
which = random.randint(1, self.imagesLen)
while self.which == which:
which = random.randint(1, self.imagesLen)
self.which = which
self.image = self.images[self.which]
self.rect = self.image.get_rect()
# make sure the tile is in the right coordinates
self.rect.center = self.xy
class Sand(pygame.sprite.Sprite):
"""A sand sprite. Has a level and position."""
def __init__(self, xy, images, which=None, *, collision=False, randomize=False, randFps=0):
pygame.sprite.Sprite.__init__(self)
self.sprType = 'sand'
# save images and pick one to display
self.images = images
self.imagesLen = len(images)
if which == None:
which = random.randint(1, self.imagesLen)
self.which = which
# set the image and rect so they can be rendered
self.image = self.images[self.which]
self.rect = self.image.get_rect()
# set initial position
self.rect.center = xy
self.xy = xy
# Collision?
self.collision = collision
# be randomized from time to time
self.randomized = randomize
self.randFps = randFps if randFps > 0 else 0
if randFps == 0:
self.randomized = False
def changeTile(self, fps, *, which=None):
if fps % self.randFps == 0:
if which is None:
which = random.randint(1, self.imagesLen)
while self.which == which:
which = random.randint(1, self.imagesLen)
self.which = which
self.image = self.images[self.which]
self.rect = self.image.get_rect()
# make sure the tile is in the right coordinates
self.rect.center = self.xy
class Water(pygame.sprite.Sprite):
"""A water sprite. Has a level and position."""
def __init__(self, xy, images, which=None, *, collision=False, randomize=False, randFps=0):
pygame.sprite.Sprite.__init__(self)
self.sprType = 'water'
# save images and pick one to display
self.images = images
self.imagesLen = len(images)
if which == None:
which = random.randint(1, self.imagesLen)
self.which = which
# set the image and rect so they can be rendered
self.image = self.images[self.which]
self.rect = self.image.get_rect()
# set initial position
self.rect.center = xy
self.xy = xy
# Collision?
self.collision = collision
# be randomized from time to time
self.randomized = randomize
self.randFps = randFps if randFps > 0 else 0
if randFps == 0:
self.randomized = False
def changeTile(self, fps, *, which=None):
if fps % self.randFps == 0:
if which is None:
which = random.randint(1, self.imagesLen)
while self.which == which:
which = random.randint(1, self.imagesLen)
self.which = which
self.image = self.images[self.which]
self.rect = self.image.get_rect()
# make sure the tile is in the right coordinates
self.rect.center = self.xy
class BackgroundFactory(object):
"""Using this class to return background tiles with a copy
of the images already loaded. No sense in re-loading
all the images for every new tile every time one is created."""
def __init__(self):
backgrounds = {'grass': 10, 'sand': 10, 'water': 10} # later this data will be taken from a file.
self.backgrounds = backgrounds
BgImgs = {}
for bg in self.backgrounds:
count = self.backgrounds[bg]
images = {}
for tile in range(count+1):
fpath = os.path.join('images', 'tile_background_' + str(bg) + '_' + str(tile) + '.png')
if os.path.isfile(fpath):
images[tile] = pygame.image.load(fpath)
BgImgs[bg] = images
self.BgImages = BgImgs
def getBgTile(self, xy, BgType='grass'):
for bg in self.backgrounds:
if bg != BgType:
continue
else:
count = self.backgrounds[bg]
which = random.randint(1, count)
imgs = self.BgImages[bg]
if bg == 'grass':
return Grass(xy, imgs, which)
if bg == 'sand':
return Sand(xy, imgs, which)
if bg == 'water':
return Water(xy, imgs, which, collision=True, randomize=True, randFps=15)
class Game(object):
def __init__(self, win_size, *, fps=60):
# center the game window
os.environ['SDL_VIDEO_CENTERED'] = '1'
# load and set up pygame
pygame.init()
# create our window
self.window = pygame.display.set_mode(win_size)
self.window_size = win_size
# clock for ticking and FPS
self.clock = pygame.time.Clock()
self.fps = fps
# set the window title
pygame.display.set_caption('Snake Game - Background Map Test')
# tell which events to listen to
pygame.event.set_allowed([QUIT, KEYDOWN])
# default black background
self.background = pygame.Surface(win_size)
self.background.fill((0, 0, 0))
# make the map (background ONLY) - ONLY FOR THE TEST!!!
# a sprite rendering group for our background
self.BgSprites = pygame.sprite.RenderUpdates()
# create our BackgroundFactory object
self.bgfactory = BackgroundFactory()
# generate a random level for the tests
self.randomMap()
def run(self):
print('Starting Event Loop')
# draw the background!
self.BgSprites.clear(self.window, self.background)
dirty = self.BgSprites.draw(self.window)
pygame.display.update(dirty)
# Group the sprites for change
spritesForChange = pygame.sprite.RenderUpdates()
sumS = 0
for toChange in self.BgSprites:
if toChange.randomized:
sumS += 1
spritesForChange.add(toChange)
runCounter = 0
runCounterMax = self.fps * 60 * 10
running = True
while running:
# Count every frame
runCounter += 1
if runCounter > runCounterMax:
runCounter = 1
# tick pygame clock
self.clock.tick(self.fps)
# self.clock.tick()
# handle user input
running = self.handleEvents()
pygame.display.set_caption('Snake Game - Background Map Test ' + str(self.clock.get_fps()))
""" Previous option: without spritesForChange
# render the changing background tiles
self.BgSprites.clear(self.window, self.background)
for change in self.BgSprites:
if change.randomized:
change.changeTile(runCounter)
dirty = self.BgSprites.draw(self.window)
pygame.display.update(dirty)
"""
# render the changing background tiles
spritesForChange.clear(self.window, self.background)
for change in spritesForChange:
if change.randomized:
change.changeTile(runCounter)
dirty = spritesForChange.draw(self.window)
pygame.display.update(dirty)
print('Quit!')
pygame.quit()
def handleEvents(self):
"""Handle events like user input."""
for event in pygame.event.get():
if event.type == QUIT:
return False
# handle user input
elif event.type == KEYDOWN:
if event.key == K_ESCAPE:
return False
return True
def randomMap(self):
tile_size = 25
win_width, win_height = self.window_size
tile_count_x = win_width // tile_size
tile_count_y = win_height // tile_size
for x in range(tile_count_x):
for y in range(tile_count_y):
coor_x = (tile_size // 2) + x * tile_size
coor_y = (tile_size // 2) + y * tile_size
types = ('grass', 'sand', 'water')
bgType = random.choice(types)
self.BgSprites.add(self.bgfactory.getBgTile((coor_x, coor_y), bgType))
if __name__ == '__main__':
game = Game((800, 800))
game.run()
@evgenidb
Copy link
Author

Performance problems. Some optimization would be welcomed as well.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment