import pygame import GraphicsUtil as Graph import random from Util import * # the minimum class for an object that can be displayed on the screen class ImageObject: def __init__(self, x, y, img): self.x = x self.y = y self.img = img # the method that should update the status of game depending on the game. # Its subclass should overrides it def update(self, game): pass # a great example of an object that can move on the screen # Hero is a subclass of ImageObject so it has l class Hero(ImageObject): def __init__(self): # call the initializer of its super class super().__init__(0, 0, Graph.heroSprite) # ------------------------ self.vx = 0 self.vy = 0 # this method overrides the def update(self, game): self.x += self.vx self.y += self.vy bounceIn(self, 0, 0, 500, 500) # a greate example for an object that does animation class Star(ImageObject): def __init__(self, x, y, time): super().__init__(x, y, Graph.shiningAnimation[0]) self.birthTime = time def update(self, game): self.x += 1 self.y += 1 showAnimationOn(self, Graph.shiningAnimation, (game.time - self.birthTime) / 2) wrapAroundIn(self, 20, 20, 480, 480) class Game: def __init__(self): # initialize the time and state time to zero. ## self.time is a clock that record how many ticks has elapsed ## self.stateTime is a clock that record how many ticks has elapsed since switched to this state self.time = self.stateTime = 0 # set the initial background of the game self.background = Graph.background # set the initial state of game to be "Normal" self.state = "Normal" # put hero as an attribute of the game self.hero = Hero() self.ball = ImageObject(250, 250, Graph.someLoadedImage) self.stars = [] # put all objects that will be drawn on the screen in a list self.objectsOnScreen = [self.hero, self.ball] # updateGame() is called before each frame is displayed def updateGame(self): # update both the time and state time self.time += 1 self.stateTime += 1 # check what state the game is at if self.inState("Normal"): # dectect collision of stars and hero using rectangle for s in self.stars: if hasCollideRect(self.hero, s): self.stars.remove(s) # showAnimationOn() takes three argument, the object, the animation, and the frameNumber # it returns whether a complete animation is shown if showAnimationOn(self.ball, Graph.shiningAnimation, self.stateTime / 5): self.switchState("Pause") elif self.inState("Pause"): if self.stateTime > 200: self.switchState("Normal") else: raise Exception("Undefined game state " + str(state)) # a magic that update all elements on the screen for you # However, all methods need to implement obj.update(game) def updateObj(objls): for obj in objls: if type(obj) is list: updateObj(obj) else: obj.update(self) updateObj(self.objectsOnScreen) def switchState(self, newState): # configure the game when state swiched if newState == "Normal": self.background = Graph.background self.objectsOnScreen = [self.hero, self.ball] elif newState == "Pause": self.background = Graph.BLACK self.objectsOnScreen = [self.hero, self.stars] # reset the stateTime when switching to a new state self.stateTime = 0 self.state = newState def inState(self, lookFor): # sometimes you might have small states within big state like "Normal-A", "Normal-B" # inState() makes it easier to add those substate later on without breaking previous features return self.state.startswith(lookFor) # an example of adding an object to the screen def addAnRandomBall(self): addedStar = Star(random.randint(0, 500),random.randint(0, 500), self.time) self.stars.append(addedStar) # A method that does all the drawing for you def draw(self, screen): # set the background of the game if type(self.background) is tuple: screen.fill(self.background) else: screen.blit(self.background, (0, 0)) # the magic that draw all the objects in objectsOnScreen onto the screen def drawOnScreen(objls): for obj in objls: if type(obj) is list: drawOnScreen(obj) else: screen.blit(obj.img, (obj.x, obj.y)) drawOnScreen(self.objectsOnScreen)