Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

state code from class plus pause menu

  • Loading branch information...
commit 1e9c16670a08b07af56e37963d66f0a3d4ee806e 1 parent 11a4ad8
@alecgoebel alecgoebel authored
View
53 samplecode/menus_and_states/anim.py
@@ -0,0 +1,53 @@
+class AnimationFrames(object):
+ def __init__(self, frames, loops=-1):
+ self._times = []
+ self._data = []
+ total = 0
+ for t, data in frames:
+ total += t
+ self._times.append(total)
+ self._data.append(data)
+
+ self.end = total
+ self.loops = loops
+
+
+ def get(self, time):
+ # if looping forever or within the number of loops, wrap time
+ if self.loops == -1 or time < self.loops * self.end:
+ time %= self.end
+
+ # return last frame if we've gone too far
+ if time > self.end:
+ return self._data[-1]
+
+ # otherwise loop until we get the right frame
+ idx = 0
+ while self._times[idx] < time:
+ idx += 1
+
+ return self._data[idx]
+
+
+
+
+class Animation(object):
+ def __init__(self, spritesheet, frames):
+ if not isinstance(frames, AnimationFrames):
+ frames = AnimationFrames(frames)
+
+ self.spritesheet = spritesheet
+ self.frames = frames
+ self.time = 0
+ self.update(0)
+
+ def get_frame_data(self, time):
+ return self.frames.get(time)
+
+ def get_current_frame(self):
+ return self.spritesheet.get(self.x, self.y)
+
+ def update(self, dt):
+ self.time += dt
+ self.x, self.y = self.get_frame_data(self.time)
+
View
48 samplecode/menus_and_states/app.py
@@ -0,0 +1,48 @@
+import inspect
+
+import pygame
+from pygame.locals import *
+
+class ApplicationState(object):
+ def __init__(self, app):
+ self.app = app
+ self.setup()
+
+ def setup(self): pass
+ def resume(self): pass
+ def handle_event(self, event): pass
+ def update(self): pass
+ def draw(self, screen): pass
+
+
+class Application(object):
+ def __init__(self, state):
+ self.screen = pygame.display.get_surface()
+ pygame.display.set_caption("Super Coin Get")
+
+ self.set_state(state)
+
+ def quit(self):
+ self.done = True
+
+ def set_state(self, state):
+ if inspect.isclass(state):
+ state = state(self)
+
+ state.resume()
+ self.state = state
+
+ def run(self):
+ self.done = False
+ while not self.done:
+ # input
+ for event in pygame.event.get():
+ if event.type == QUIT:
+ self.quit()
+ else:
+ self.state.handle_event(event)
+
+ self.state.update()
+ self.state.draw(self.screen)
+ pygame.display.flip()
+
View
67 samplecode/menus_and_states/coin.py
@@ -0,0 +1,67 @@
+from random import randrange
+
+from pygame import Surface
+from pygame.sprite import Sprite, Group
+
+from anim import Animation
+from spritesheet import SpriteSheet
+
+
+
+class CoinAnimation(Animation):
+ def __init__(self, duration):
+ spritesheet = SpriteSheet("coin", (8, 1))
+
+ frames = [ (duration, (0, 0)),
+ (duration, (1, 0)),
+ (duration, (2, 0)),
+ (duration, (3, 0)),
+ (duration, (4, 0)),
+ (duration, (5, 0)),
+ (duration, (6, 0)),
+ (duration, (7, 0)) ]
+
+ Animation.__init__(self, spritesheet, frames)
+
+
+## Coin
+class Coin(Sprite):
+ def __init__(self, loc):
+ Sprite.__init__(self)
+
+ self.anim = CoinAnimation(240)
+ self.image = self.anim.get_current_frame()
+ self.rect = self.image.get_rect()
+ self.rect.center = loc
+
+
+ def update(self, dt):
+ self.anim.update(dt)
+ self.image = self.anim.get_current_frame()
+
+class CoinGroup(Group):
+ spawn_rate = 1000 # ms
+
+ def __init__(self, bounds):
+ Group.__init__(self)
+
+ self.bounds = bounds
+ self.spawn_timer = 0
+
+ def spawn(self):
+ x = randrange(self.bounds.x, self.bounds.x + self.bounds.width)
+ y = randrange(self.bounds.y, self.bounds.y + self.bounds.height)
+
+ coin = Coin((x,y))
+ coin.rect.clamp_ip(self.bounds)
+ self.add(coin)
+
+ def update(self, dt):
+ Group.update(self, dt)
+
+ # update the spawner
+ self.spawn_timer += dt
+ if self.spawn_timer >= self.spawn_rate:
+ self.spawn()
+ self.spawn_timer = 0
+
View
BIN  samplecode/menus_and_states/data/images/coin.bmp
Binary file not shown
View
BIN  samplecode/menus_and_states/data/images/grass.bmp
Binary file not shown
View
BIN  samplecode/menus_and_states/data/images/mario.bmp
Binary file not shown
View
BIN  samplecode/menus_and_states/data/music/maintheme.ogg
Binary file not shown
View
BIN  samplecode/menus_and_states/data/sfx/coin.ogg
Binary file not shown
View
97 samplecode/menus_and_states/game.py
@@ -0,0 +1,97 @@
+"""
+game.py
+
+"""
+
+import pygame
+from pygame.locals import *
+from pygame.sprite import spritecollide, GroupSingle
+
+from app import ApplicationState
+from level import Level
+
+
+class MainMenu(ApplicationState):
+ fg_color = 255,255,255
+ bg_color = 0,0,0
+ flash_rate = 500
+
+ def setup(self):
+ font = pygame.font.Font(None, 60)
+
+ font.set_bold(True)
+ self.title = font.render("Super Coin Get", True, self.fg_color, self.bg_color)
+
+ font.set_bold(False)
+ font.set_italic(True)
+ self.inst = font.render("Press <SPACE> to Start", True, self.fg_color, self.bg_color)
+
+ def resume(self):
+ self.clock = pygame.time.Clock()
+ self.time = 0
+
+ def handle_event(self, event):
+ if event.type == KEYDOWN and (event.key == K_q or event.key == K_ESCAPE):
+ self.app.quit()
+ elif event.type == KEYDOWN and event.key == K_SPACE:
+ self.app.set_state(Game)
+
+ def update(self):
+ self.time += self.clock.tick()
+ self.time %= 2 * self.flash_rate
+ self.draw_inst = self.time < self.flash_rate
+
+
+ def draw(self, screen):
+ bounds = screen.get_rect()
+
+ screen.fill(self.bg_color)
+
+ rect = self.title.get_rect()
+ rect.center = bounds.centerx, bounds.centery - bounds.height / 4
+ screen.blit(self.title, rect)
+
+ if self.draw_inst:
+ rect = self.inst.get_rect()
+ rect.center = bounds.centerx, bounds.centery + bounds.height / 4
+ screen.blit(self.inst, rect)
+
+
+class PauseMenu(ApplicationState):
+ def resume(self):
+ self.game = self.app.state
+
+ screen = pygame.display.get_surface()
+ frame = screen.convert_alpha()
+ frame.fill((0,0,0,128))
+ screen.blit(frame, (0,0))
+
+
+ def handle_event(self, event):
+ if event.type == KEYDOWN and event.key == K_q:
+ self.app.set_state(MainMenu)
+ elif event.type == KEYDOWN and (event.key == K_SPACE or event.key == K_ESCAPE):
+ self.app.set_state(self.game)
+
+
+class Game(ApplicationState):
+ fps = 60
+
+ def setup(self):
+ self.level = Level(self.app.screen.get_size())
+ self.level.restart()
+
+ def resume(self):
+ self.clock = pygame.time.Clock()
+ pygame.mixer.music.unpause()
+
+ def handle_event(self, event):
+ if event.type == KEYDOWN and event.key == K_ESCAPE:
+ self.app.set_state(PauseMenu)
+
+ def update(self):
+ dt = self.clock.tick(self.fps)
+ self.level.update(dt)
+
+ def draw(self, screen):
+ self.level.draw(screen)
View
62 samplecode/menus_and_states/level.py
@@ -0,0 +1,62 @@
+"""
+level.py
+
+"""
+
+import os
+
+import pygame
+from pygame import Rect, Surface
+from pygame.sprite import Group, spritecollide
+
+from resource import load_image, play_song, load_sfx
+
+from player import Player
+from coin import CoinGroup
+
+class Level(object):
+ initial_coins = 20
+ song = "maintheme"
+
+ def __init__(self, size):
+ self.bounds = Rect((0,0), size)
+ self.bg_tile = load_image("grass")
+ self.coin_sfx = load_sfx("coin")
+
+ def draw_background(self, surf):
+ tw, th = self.bg_tile.get_size()
+ sw, sh = surf.get_size()
+
+ for y in range(0, sh, th):
+ for x in range(0, sw, tw):
+ surf.blit(self.bg_tile, (x,y))
+
+ def restart(self):
+ self.player = Player()
+ self.player.rect.center = self.bounds.center
+
+ self.coins = CoinGroup(self.bounds)
+
+ # create initial coins
+ for i in range(self.initial_coins):
+ self.coins.spawn()
+
+ # start the background music
+ play_song(self.song)
+
+ def update(self, dt):
+ self.player.update(dt)
+ self.coins.update(dt)
+
+ # lock player in bounds
+ self.player.rect.clamp_ip(self.bounds)
+
+ # collide player with coins
+ if spritecollide(self.player, self.coins, True):
+ self.coin_sfx.stop()
+ self.coin_sfx.play()
+
+ def draw(self, surf):
+ self.draw_background(surf)
+ self.coins.draw(surf)
+ surf.blit(self.player.image, self.player.rect)
View
19 samplecode/menus_and_states/main.py
@@ -0,0 +1,19 @@
+import pygame
+
+from app import Application
+from game import MainMenu
+
+def main():
+ # initialize pygame
+ pygame.init()
+ pygame.display.set_mode((800, 800))
+
+ # create game
+ app = Application(MainMenu)
+ try:
+ app.run()
+ except KeyboardInterrupt:
+ app.quit()
+
+if __name__ == "__main__":
+ main()
View
98 samplecode/menus_and_states/player.py
@@ -0,0 +1,98 @@
+"""
+player.py
+
+"""
+import math
+
+import pygame
+from pygame.locals import *
+from pygame import Surface
+from pygame.sprite import Sprite
+
+from anim import Animation
+from spritesheet import SpriteSheet
+
+DIAG = 1 / math.sqrt(2)
+
+
+class PlayerAnimation(Animation):
+ _rows = {( 0, 1): 0,
+ (-1, 0): 1,
+ ( 1, 0): 2,
+ ( 0,-1): 3,
+ (-1, 1): 4,
+ (-1,-1): 5,
+ ( 1, 1): 6,
+ ( 1,-1): 7 }
+
+ def __init__(self, player, image, duration):
+ self.player = player
+ self.y = self._rows[(0, 1)]
+
+ spritesheet = SpriteSheet(image, (3, 8))
+ frames = [ (duration, 0),
+ (duration, 1),
+ (duration, 2),
+ (duration, 1) ]
+
+ Animation.__init__(self, spritesheet, frames)
+
+ def update(self, dt):
+ vx, vy = self.player.vx, self.player.vy
+
+ # calculate the direction facing
+ try:
+ vx /= abs(vx)
+ except:
+ vx = 0
+
+ try:
+ vy /= abs(vy)
+ except:
+ vy = 0
+
+ # figure out spritesheet row
+ if vx == 0 and vy == 0:
+ self.time = 0
+ self.x = 1
+ else:
+ self.time += dt
+ self.x = self.get_frame_data(self.time)
+ self.y = self._rows[(vx, vy)]
+
+
+class Player(Sprite):
+ speed = 300
+
+ def __init__(self):
+ Sprite.__init__(self)
+ self.vx = 0
+ self.vy = 0
+
+ self.anim = PlayerAnimation(self, "mario", 80)
+ self.image = self.anim.get_current_frame()
+ self.rect = self.image.get_rect()
+
+
+ def update(self, dt):
+ self.anim.update(dt)
+ self.image = self.anim.get_current_frame()
+
+ self.vx, self.vy = 0, 0
+ keys = pygame.key.get_pressed()
+ if keys[K_UP]:
+ self.vy = -self.speed
+ if keys[K_DOWN]:
+ self.vy = self.speed
+ if keys[K_LEFT]:
+ self.vx = -self.speed
+ if keys[K_RIGHT]:
+ self.vx = self.speed
+
+ if self.vx and self.vy:
+ self.vx *= DIAG
+ self.vy *= DIAG
+
+ dt = dt / 1000.0
+ self.rect.x += self.vx * dt
+ self.rect.y += self.vy * dt
View
34 samplecode/menus_and_states/resource.py
@@ -0,0 +1,34 @@
+import os
+from os.path import abspath, dirname
+
+import pygame
+
+ROOT_DIR = dirname(abspath(__file__))
+DATA_DIR = os.path.join(ROOT_DIR, "data")
+
+SFX_DIR = os.path.join(DATA_DIR, "sfx")
+MUSIC_DIR = os.path.join(DATA_DIR, "music")
+IMG_DIR = os.path.join(DATA_DIR, "images")
+
+
+def play_song(song, times=-1):
+ path = os.path.join(MUSIC_DIR, song + ".ogg")
+ pygame.mixer.music.load(path)
+ pygame.mixer.music.play(times)
+
+
+_images = {}
+def load_image(name):
+ if name not in _images:
+ path = os.path.join(IMG_DIR, name + ".bmp")
+ _images[name] = pygame.image.load(path)
+
+ return _images[name].convert()
+
+_sfx = {}
+def load_sfx(name):
+ if name not in _sfx:
+ path = os.path.join(SFX_DIR, name + ".ogg")
+ _sfx[name] = pygame.mixer.Sound(path)
+
+ return _sfx[name]
View
29 samplecode/menus_and_states/spritesheet.py
@@ -0,0 +1,29 @@
+from resource import load_image
+
+class SpriteSheet(object):
+ def __init__(self, image, dimensions, colorkey=-1):
+
+ # load the image
+ if type(image) is str:
+ image = load_image(image)
+
+ if colorkey == -1:
+ colorkey = image.get_at((0,0))
+
+ if colorkey:
+ image.set_colorkey(colorkey)
+
+ cols, rows = dimensions
+ w = self.width = 1.0 * image.get_width() / cols
+ h = self.height = 1.0 * image.get_height() / rows
+
+ # build the images
+ self._images = []
+ for y in range(rows):
+ row = []
+ for x in range(cols):
+ row.append(image.subsurface((x*w, y*h, w, h)))
+ self._images.append(row)
+
+ def get(self, x, y):
+ return self._images[y][x]
Please sign in to comment.
Something went wrong with that request. Please try again.