def _build_gui(self): """ Make a menu widget. """ gui = LayeredDirty() # only reblit when dirty=1 # TODO: prepare a rect menu_widget = MenuWidget(self._em, self.evtlabels) gui.add(menu_widget) return gui
def add(self, *args, **kwargs): """Add object O to field object list.""" LayeredDirty.add(self, *args, **kwargs) # Append object in-place, even if ticking for o in args: if hasattr(o, "tick"): self.objects.append(o)
def init_sprites(self): """temp, this will go in the init.""" sprite_list = [self.elephant, self.cat, self.score_text] self.allsprites = LayeredDirty(sprite_list, _time_threshold=1000 / 10.0) scene = self self.shark = Shark(self.allsprites, scene, self.width, self.height) self.allsprites.add(self.shark) self.allsprites.clear(self.screen, self.background)
def __init__(self, world): LayeredDirty.__init__(self) self.world = world self.name = None #the name of the team self.suit = None #the pygame.image that shows the team self.controlpoint = None #the pygame.image of an controlpoint when this team controls it self.brain = None #the AgentBrain class that all agents of this team use to generate actions self.spawn_point = (0,0) #the spawning location of this team in the current map self.score = 0 #the score of the team in this game self.stats = collections.defaultdict(float) #saves all the statistics.
def __init__(self, engine, *, background_color=(0, 0, 55), container_class=GameObjectCollection, **kwargs): super().__init__(engine) self.background_color = background_color self.background = engine.display.copy() self.background.fill(self.background_color) self.game_objects = container_class() self.render_group = LayeredDirty()
def __init__(self, engine, *, background_color=(0, 0, 100), container_class=GameObjectCollection, set_up=None, **kwargs): super().__init__(engine) self.background_color = background_color self.background = None self.game_objects = container_class() self.render_group = LayeredDirty() if set_up is not None: set_up(self)
class Scene(object): def __init__(self, screen): """Create the scene's objects.""" self.screen = screen self.running = True # Groups for sprites self.players = Group() self.enemies = Group() self.chars = Group() self.weapons = Group() self.projs = Group() self.all = LayeredDirty() # Room self.room = Room(self) self.all.add(self.room) # Weapons self.weapon_list = [ LaserGun(self), Bow(self) ] for weapon in self.weapon_list: self.weapons.add(weapon) # Players self.player = Player(self) self.players.add(self.player) self.all.add(self.players) # Enemies enemy_list = [ Human, Glork ] for enemy in range(0, randint(50,100)): self.enemies.add(choice(enemy_list)(self)) self.all.add(self.enemies) # Characters self.chars.add([self.players, self.enemies]) # Layers self.all = LayeredDirty([ self.room, self.enemies, self.players, self.weapons, self.projs ]) def draw(self): """Draw all of the objects to the screen.""" # Update all scene layers to the screen. self.all.update() self.dirty_rects = self.all.draw(self.screen) display.update(self.dirty_rects)
def __init__(self, sequence:Sequence, offset:tuple, rect:pygame.Rect, skin:Skin): LayeredDirty.__init__(self) self.sequence = sequence self.sequence.addObserver(self) self.offset = offset self.rect = rect self.skin = skin self.blocks = [] self.trackLines = [] self.barLines = [] self.lastTime = sequence.getTime() self.widthInBeats = sequence.timeSignature.getBeatsForBars(self.Width.DEF_WIDTH_IN_BARS) self.activeTrackCount = Sequence.MIN_TRACKS self._initializeGridSprites()
def __init__(self, action_handler, index): # Init clock self.clock = pyg.time.Clock() # Set handler self.action_handler = action_handler # Init groupsView self.all_sprites = LayeredDirty() Fps.containers += (self.all_sprites,) # Create window self.screen, self.background = reset_screen() if DISPLAY_FPS: Fps(self.clock) # Blit level image, rect = get_stage_image(index) self.background.blit(image, rect) # Tile handling from TileView import TileView TileView.layer_container = self.all_sprites # Initialize attributes self.exit = False self.done = False self.countdown = None
def __init__(self, name='untitled', par=3, origin=Point(50, 50), width=1080, height=900, ball=None, **labeled_groups): self.score = -1 self.name = name self.par = par self.origin = origin self.width = width self.height = height self.image = Surface((width, height)) self.rect = pygame.Rect(*origin.as_2d_tuple(), width, height) self.groups = {'all': LayeredDirty()} for label, group in labeled_groups.items(): self.groups[label] = group self.groups['all'].add(*group.sprites()) self.ball = GolfBall(ball, 0, self.groups['all']) if ball else None
def __init__(self, engine): super().__init__(engine, background_color=(10, 21, 41)) self.render_group = LayeredDirty() self.spawn_objects = [InfiniteObjectManager(self, Chimney, self.groups[config.KEY_CHIMNEY])] self.spawner = Spawner() self.spawn_objects.append(self.spawner) santa = Santa(self, Vector(*self.engine.display.get_rect().center), self.groups[config.KEY_GIFTS], self.groups[config.KEY_SANTA]) self.controller = Controller(actor=santa) channel = resources.sounds["santaclauseiscoming"].play(-1) channel.set_volume(0.1) self.score = 0 self.missed_chimneys = 0 Score(self, lambda: self.score, self.groups[config.KEY_UI])
def __init__(self, name): State.name = name State.screen = self State.controls = State.screens[State.name]['controls'] State.groups = {} self.layers = LayeredDirty() self.add_all() State.save(State.name)
def _build_gui(self): """ Add a score widget on the right """ gui = LayeredDirty() # only reblit when dirty=1 # score at top-right of the window rec = Rect(600 + 10, 0, 100, font_size * 1.5) evt_txt_dict = {RecipeMatchEvent: "current_score"} score_widget = TextLabelWidget( self._em, "0", events_attrs=evt_txt_dict, rect=rec, txtcolor=(0, 0, 0), bgcolor=(222, 222, 222) ) gui.add(score_widget) # CPU at bottom-right of the window rec = Rect(600 + 10, 600 - font_size * 1.5, 100, font_size * 1.5) cpu_widget = CPUDisplayWidget(self._em, "0", rect=rec, txtcolor=(0, 0, 0), bgcolor=(222, 222, 222)) gui.add(cpu_widget) # the recipe widget added when the game is built return gui
def build_gui(self): """ Add widgets to the screen. Widgets on the left need only be reblitted when they get dirty. Widgets that overlay the world screen need to be reblitted every frame. """ # start adding widgets leftgui = LayeredDirty() # only reblit when dirty=1 overlaygui = LayeredUpdates() # reblit every frame w, h = self.win_size line_h = config_get_fontsize() gui_w = self.gui_offset # -- name label at top-left of the screen rec = pygame.Rect(0, 0, gui_w - 1, line_h - 1) evt_txt_dict = {MMyNameChangedEvent: 'newname', MGreetNameEvt:'newname'} txtcol = config_get_txtlabel_txtcolor() bgcol = config_get_txtlabel_bgcolor() namebox = TextLabelWidget(self._em, '', events_attrs=evt_txt_dict, rect=rec, txtcolor=txtcol, bgcolor=bgcol) leftgui.add(namebox) # -- list of connected players, until middle of the screen rec = pygame.Rect(0, line_h, gui_w - 1, line_h - 1) txt = 'Connected players:' txtcol = config_get_txtlabel_txtcolor() bgcol = config_get_txtlabel_bgcolor() whosonlinetitle = TextLabelWidget(self._em, txt, rect=rec, txtcolor=txtcol, bgcolor=bgcol) leftgui.add(whosonlinetitle) rec = pygame.Rect(0, 2 * line_h, gui_w - 1, h / 2 - 2 * line_h - 1) numlines = int(rec.height / line_h) txtcol = config_get_chatlog_txtcolor() bgcol = None #config_get_chatlog_bgcolor() whosonlinebox = PlayerListWidget(self._em, numlines, rect=rec, txtcolor=txtcol, bgcolor=bgcol) leftgui.add(whosonlinebox) # -- chat window overlay at bottom of the world screen chat_height = h / 4 numlines = int(chat_height / line_h) if numlines > 0: # text input field rec = pygame.Rect(gui_w + 1, h - line_h, w - gui_w - 1, line_h - 1) chatbox = InputFieldWidget(self._em, rect=rec) overlaygui.add(chatbox) if numlines > 1: # text display line rec = pygame.Rect(gui_w + 1, h * 3 / 4, w - gui_w - 1, h / 4 - line_h - 1) txtcol = config_get_chatlog_txtcolor() # no bg color to disply on top of world screen chatwindow = ChatLogWidget(self._em, numlines=numlines, rect=rec, txtcolor=txtcol) overlaygui.add(chatwindow) self.left_gui_sprites = leftgui self.overlay_gui_sprites = overlaygui
def __init__(self, screen: Surface): ''' Constructor of the class, takes the screen to gain control over the render of the game objects ''' # Get display info info = Info() # Get Clock to ensure frame rating self.clock = Clock() # The default return value of the Scene self.return_value = -1 # Set the continue condition self.running = True # Get the relevant information from info self.screen_h, self.screen_w = info.current_h, info.current_w # Set the screen of the Scene self.screen: Surface = screen # Main Sprite groups self.event_group = Group() self.update_group = Group() self.render_group = LayeredDirty()
class Game(BaseScene): def __init__(self, engine): super().__init__(engine, background_color=(10, 21, 41)) self.render_group = LayeredDirty() self.spawn_objects = [InfiniteObjectManager(self, Chimney, self.groups[config.KEY_CHIMNEY])] self.spawner = Spawner() self.spawn_objects.append(self.spawner) santa = Santa(self, Vector(*self.engine.display.get_rect().center), self.groups[config.KEY_GIFTS], self.groups[config.KEY_SANTA]) self.controller = Controller(actor=santa) channel = resources.sounds["santaclauseiscoming"].play(-1) channel.set_volume(0.1) self.score = 0 self.missed_chimneys = 0 Score(self, lambda: self.score, self.groups[config.KEY_UI]) def render(self): window = display.get_surface() for group in self.groups.values(): self.render_group.add(group.sprites()) for sprite in self.render_group.sprites(): self.render_group.change_layer(sprite, sprite.layer) sprite.pre_draw() return self.render_group.draw(window, self.background) def simulate(self, time_delta: float): self.controller.respond() super().simulate(time_delta) for spawn_object in self.spawn_objects: spawn_object.resolve(time_delta) collisions = groupcollide(self.groups[config.KEY_CHIMNEY], self.groups[config.KEY_GIFTS], False, False) successes = 0 for chimney, gifts in collisions.items(): for gift in gifts: if chimney.rect.left < gift.position.x < chimney.rect.right: successes += 1 gift.kill() chimney.delivered = True if successes: self.score += config.POINTS_GIFT_DELIVERED * successes logging.debug(f"{successes} Successes!") if self.missed_chimneys >= config.LIMIT_CHIMNEYS_MISSED: self.running = False
def __init__(self, em, ev): """ Score and recipe widgets on the right, game board on the left. em is the mode's event manager, ev is an event containing data from the previous mode (e.g. menu or level transition). ev contains the level number. """ pygame.display.init() # OK to init multiple times pygame.font.init() self._em = em window = pygame.display.set_mode(resolution) self.window = window pygame.display.set_caption("Smoothie Factory - In Play") # blit the bg screen: all black bg = Surface(window.get_size()) bg.fill((0, 0, 0)) bg = bg.convert() self.window_bg = bg self.window.blit(bg, (0, 0)) # fruit sprites self.fruit_to_spr = {} # map a fruit to its sprite self.fruit_sprites = LayeredDirty() # only reblit when dirty=1 self.interp_steps = 0 # 2 interpolation steps between 2 model updates # build GUI self.gui = self._build_gui() # return a sprite group em.subscribe(BoardBuiltEvent, self.on_board_built) em.subscribe(GameBuiltEvent, self.on_game_built) em.subscribe(FruitKilledEvent, self.on_fruit_killed) em.subscribe(FruitPlacedEvent, self.on_fruit_spawned) em.subscribe(FruitSpeedEvent, self.on_speed_change) em.subscribe(QuitEvent, self.on_quit)
class CatUniScene(Scene): def __init__(self, *args, **kwargs): Scene.__init__(self, *args, **kwargs) (width, height) = (1920 // 2, 1080 // 2) self.width, self.height = width, height # Loading screen should always be a fallback active scene self.active = False self.first_render = True self.myfont = pygame.font.SysFont("monospace", 20) self.background = gfx('background.png', convert=True) # self.cat_unicycle = gfx('cat_unicycle.png').convert_alpha() # self.fish = gfx('fish.png').convert_alpha() # self.foot = gfx('foot.png').convert_alpha() # self.foot_part = gfx('foot_part.png').convert_alpha() # self.shark = gfx('shark.png').convert_alpha() sfx('cat_jump.ogg') sfx('eatfish.ogg') sfx('splash.ogg') sfx('cat_crash.ogg') self.meow_names = [ 'cat_meow01.ogg', 'cat_meow02.ogg', 'cat_meow03.ogg' ] self.last_meow = None self.touching_ground = True self.jumping = False self.jumping_time = 0 self.jump_key = None for meow_name in self.meow_names: sfx(meow_name) self.boing_names = ['boing1.ogg', 'boing2.ogg', 'boing3.ogg'] for boing_name in self.boing_names: sfx(boing_name) #cat variables self.cat_wire_height = height - 100 self.cat_location = [width / 2, height - 100] self.cat_speed = [0, 0] self.cat_speed_max = 8 self.cat_fall_speed_max = 16 self.cat_roll_speed = .01 self.cat_angle = 0 self.cat_angular_vel = 0 self.cat_head_location = [ int(self.cat_location[0] + 100 * math.cos(self.cat_angle - math.pi / 2)), int(self.cat_location[1] + 100 * math.sin(self.cat_angle - math.pi / 2)), ] self.people_mad = False self.people_mad_duration = 3000 #ms self.people_mad_current_time = 0 self.next_notfish = 0 self.notfish_time = 0 self.last_joy_right_tilt = 0 self.last_joy_left_tilt = 0 self.left_pressed = False self.right_pressed = False self.score = 0 #timing self.dt_scaled = 0 self.total_time = 0 #elephant and shark classes self.elephant = Elephant(self) self.shark_active = False #is the shark enabled yet self.elephant_active = False self.cat = Cat(self) self.score_text = Score(self) self.deadzones = [] # self.deadzones = [ # DeadZone( # [ # [0, height - 100], # [0.1 * width, height - 100], # [0.1 * width, height], # [0, height], # ], # ), # DeadZone( # [ # [0.9 * width, height - 100], # [width, height - 100], # [width, height], # [0.9 * width, height], # ], # ), # ] self.init_sprites() # lists of things to catch by [posx, posy, velx, vely] # self.fish = [[0, height / 2, 10, -5]] self.fish = LayeredDirtyAppend() self.fish.extend([Fish(self.allsprites, 0, height / 2, 10, -5)]) self.not_fish = LayeredDirtyAppend() self.unicycle_sound = sfx('unicycle.ogg', play=True, loops=-1, fadein=500) self.reset_meow() #difficulty varibles self.number_of_not_fish = 0 def reset_meow(self): self.next_meow = random.uniform(5000, 10000) def meow(self): # Play a meow sound, but not the same one twice in a row meow_names = self.meow_names[:] if self.last_meow in self.meow_names: meow_names.remove(self.last_meow) self.last_meow = random.choice(meow_names) sfx(self.last_meow, play=1) self.reset_meow() def init_sprites(self): """temp, this will go in the init. """ sprite_list = [self.elephant, self.cat, self.score_text] sprite_list += self.deadzones self.allsprites = LayeredDirty(sprite_list, _time_threshold=1000 / 10.0) scene = self self.shark = Shark(self.allsprites, scene, self.width, self.height) self.allsprites.add(self.shark) self.allsprites.clear(self.screen, self.background) #what to do when you die, reset the level def reset_on_death(self): self.cat_location = [self.width / 2, self.height - 100] self.cat_speed = [0, 0] self.cat_angle = 0 self.cat_angular_vel = 0 self.score = 0 self.total_time = 0 self.elephant.last_animation = 0 self.elephant.state = 0 self.elephant.just_happened = None self.elephant.dirty = 1 self.elephant_active = False self.elephant.animate(self.total_time) #make the shark leave self.shark_active = False self.shark.last_animation = 0 self.shark.dirty = True if self.shark.get_state() in ('aiming', 'fire laser'): self.shark.just_happenend = None self.shark.set_state('leaving') self.shark.applaud = False else: self.shark.just_happenend = None self.shark.set_state('offscreen') self.shark.animate(self.total_time) sfx('shark_appear.ogg', fadeout=1000) if self.shark.lazer: self.shark.lazer.kill() #periodically increase the difficulty def increase_difficulty(self): self.number_of_not_fish = 0 if self.score > 3: self.number_of_not_fish = 1 if self.score > 9: self.number_of_not_fish = 1 if self.score > 15: self.number_of_not_fish = 2 if self.score > 19: self.number_of_not_fish = 1 if self.score > 25: self.number_of_not_fish = 2 if self.score > 35: self.number_of_not_fish = 3 if self.score >= 50: self.number_of_not_fish = int((self.score - 20) / 10) #TODO: to make it easier to test. # if self.score >= 15: # self.shark_active = True if self.score >= 10: self.shark_active = True #TODO: to make it easier to test. # Elephant doesn't work yet, so let's not use it # if self.score >= 20: # self.elephant_active = True def annoy_crowd(self): self.people_mad = True self.people_mad_current_time = 0 def render_sprites(self): rects = [] self.allsprites.update() rects.extend(self.allsprites.draw(self.screen)) return rects def render(self): rects = [] if self.first_render: self.first_render = False rects.append(self.screen.get_rect()) rects.extend(self.render_sprites()) return rects def tick(self, dt): self.increase_difficulty() self.cat.animate(dt) self.total_time += dt #keep track of the total number of ms passed during the game dt_scaled = dt / 17 self.dt_scaled = dt_scaled width, height = self.width, self.height ##cat physics self.cat_angular_vel *= 0.9**dt_scaled #max(0.9/(max(0.1,dt_scaled)),0.999) #make the cat slide in the direction it's rotated self.cat_speed[0] += math.sin( self.cat_angle) * (dt_scaled * self.cat_roll_speed) # add gravity self.cat_speed[1] = min(self.cat_speed[1] + (1 * dt_scaled), self.cat_fall_speed_max) self.unicycle_sound.set_volume( abs(self.cat_speed[0] / self.cat_speed_max)) # accelerate the cat left or right if self.right_pressed: self.cat_speed[0] = min(self.cat_speed[0] + 0.3 * dt_scaled, self.cat_speed_max) self.cat_angle -= 0.003 * dt_scaled if self.left_pressed: self.cat_speed[0] = max(self.cat_speed[0] - 0.3 * dt_scaled, -self.cat_speed_max) self.cat_angle += 0.003 * dt_scaled # make the cat fall angle_sign = 1 if self.cat_angle > 0 else -1 self.cat_angular_vel += 0.0002 * angle_sign * dt_scaled self.cat_angle += self.cat_angular_vel * dt_scaled if (self.cat_angle > math.pi / 2 or self.cat_angle < -math.pi / 2 ) and self.cat_location[1] > height - 160: sfx('cat_crash.ogg', play=1) self.reset_on_death() # move cat self.cat_location[0] += self.cat_speed[0] * dt_scaled self.cat_location[1] += self.cat_speed[1] * dt_scaled if self.cat_location[1] > self.cat_wire_height and self.cat_location[ 0] > 0.25 * width: self.touching_ground = True self.cat_location[1] = self.cat_wire_height self.cat_speed[1] = 0 else: self.touching_ground = False if self.cat_location[1] > height: sfx('splash.ogg', play=1) self.meow() self.reset_on_death() if self.cat_location[0] > width: self.cat_location[0] = width if self.cat_angle > 0: self.cat_angle *= 0.7 self.cat_head_location = [ int(self.cat_location[0] + 100 * math.cos(self.cat_angle - math.pi / 2)), int(self.cat_location[1] + 100 * math.sin(self.cat_angle - math.pi / 2)), ] # check for out of bounds if self.cat_location[0] > 0.98 * width and self.cat_location[ 1] > self.cat_wire_height - 30: #bump the cat back in self.meow() sfx(random.choice(self.boing_names), play=True) self.cat_angular_vel -= 0.01 * dt_scaled self.cat_speed[0] = -5 self.cat_speed[1] = -20 #self.reset_on_death() if self.cat_location[0] < 0.25 * width and self.cat_location[ 1] > self.cat_wire_height - 30: pass #check for collision with the elephant stomp if self.elephant_active: self.elephant.animate(self.total_time) self.elephant.collide(self, width, height, self.cat_head_location) if self.shark_active or self.shark.states[ self.shark.state] == 'leaving': self.shark.animate(self.total_time) self.shark.collide(self, width, height, self.cat_location) #jumping physics if self.jumping: self.cat_speed[1] -= dt * ( (CAT_MAX_JUMPING_TIME - self.jumping_time) / CAT_MAX_JUMPING_TIME) * CAT_JUMP_SPEED self.jumping_time += dt if self.jumping_time >= CAT_MAX_JUMPING_TIME: self.jumping = False ##meow timing if self.next_meow <= 0: self.meow() self.next_meow -= dt ##angry people (increased throwing of not-fish) if self.people_mad: self.people_mad_current_time += dt self.notfish_time += dt if self.notfish_time >= self.next_notfish: self.next_notfish = random.randint(100, 400) self.notfish_time = 0 self.SpawnNotFish() if self.people_mad_current_time >= self.people_mad_duration: self.people_mad = False ##object physics # move fish and not fish for f in reversed(self.fish.sprites()): f.pos[0] += f.velocity[0] * dt_scaled # speed of the throw f.velocity[1] += 0.2 * dt_scaled # gravity f.pos[1] += f.velocity[1] * dt_scaled # y velocity # check out of bounds if f.pos[1] > height: self.fish.remove(f) f.kill() for f in reversed(self.not_fish.sprites()): f.pos[0] += f.velocity[0] * dt_scaled # speed of the throw f.velocity[1] += 0.2 * dt_scaled # gravity f.pos[1] += f.velocity[1] * dt_scaled # y velocity # check out of bounds if f.pos[1] > height: self.not_fish.remove(f) f.kill() # check collision with the cat for f in reversed(self.fish.sprites()): if distance([f.rect[0], f.rect[1]], self.cat_head_location) < 100: self.score += 1 self.fish.remove(f) sfx('eatfish.ogg', play=1) f.kill() for f in reversed(self.not_fish.sprites()): if distance([f.rect[0], f.rect[1]], self.cat_head_location) < 50: self.not_fish.remove(f) f.kill() self.angle_to_not_fish = (math.atan2( self.cat_head_location[1] - f.rect[1], self.cat_head_location[0] - f.rect[0], ) - math.pi / 2) side = 1 if self.angle_to_not_fish < 0 else -1 self.cat_angular_vel += side * random.uniform(0.08, 0.15) sfx(random.choice(self.boing_names), play=True) # refresh lists while len(self.fish) < 1 and not self.people_mad: # choose a side of the screen if random.choice([0, 1]) == 0: self.fish.append( Fish( self.allsprites, 0, height / 2, #random.randint(0, height / 2), random.randint(3, 7), -random.randint(5, 12), )) else: self.fish.append( Fish( self.allsprites, width, height / 2, #random.randint(0, height / 2), -random.randint(3, 7), -random.randint(5, 12), )) while len(self.not_fish) < self.number_of_not_fish: self.SpawnNotFish() def SpawnNotFish(self): # choose a side of the screen velocity_multiplier = 1 x_pos = 0 if random.randint(0, 1): velocity_multiplier *= -1 x_pos = self.width self.not_fish.append( NotFish( self.allsprites, x_pos, self.height / 2, random.randint(3, 7) * velocity_multiplier, -random.randint(5, 12), )) def start_jump(self, key): self.jump_key = key if self.touching_ground and not self.jumping: self.jumping = True self.jumping_time = 0 self.cat_speed[1] -= 12.5 sfx('cat_jump.ogg', play=1) def stop_jump(self): self.jumping = False sfx('cat_jump.ogg', fadeout=50) def tilt_left(self): self.cat_angular_vel -= random.uniform(0.01 * math.pi, 0.03 * math.pi) def tilt_right(self): self.cat_angular_vel += random.uniform(0.01 * math.pi, 0.03 * math.pi) def event(self, event): if event.type == KEYDOWN: if event.key == K_RIGHT: self.right_pressed = True elif event.key == K_LEFT: self.left_pressed = True elif event.key == K_a: self.tilt_left() elif event.key == K_d: self.tilt_right() elif event.key in (K_UP, K_SPACE): self.start_jump(event.key) elif event.type == KEYUP: if event.key == self.jump_key: self.stop_jump() elif event.key == K_RIGHT: self.right_pressed = False elif event.key == K_LEFT: self.left_pressed = False if event.type == JOYBUTTONDOWN: if event.button in JOY_JUMP_BUTTONS: self.start_jump("JOY" + str(event.button)) if event.button in JOY_LEFT_BUTTONS: self.tilt_left() if event.button in JOY_RIGHT_BUTTONS: self.tilt_right() if event.type == JOYBUTTONUP: if "JOY" + str(event.button) == self.jump_key: self.stop_jump() if event.type == JOYAXISMOTION: if event.axis == 0: if event.value >= JOY_SENSE: self.right_pressed = True self.left_pressed = False elif event.value <= -JOY_SENSE: self.right_pressed = False self.left_pressed = True else: self.right_pressed = False self.left_pressed = False if event.axis == JOY_TILT_RIGHT_AXIS: if self.last_joy_right_tilt < JOY_SENSE and event.value >= JOY_SENSE: self.tilt_right() self.last_joy_right_tilt = event.value if event.axis == JOY_TILT_LEFT_AXIS: if self.last_joy_left_tilt < JOY_SENSE and event.value >= JOY_SENSE: self.tilt_left() self.last_joy_left_tilt = event.value
class GameView: def __init__(self, em, ev): """ Score and recipe widgets on the right, game board on the left. em is the mode's event manager, ev is an event containing data from the previous mode (e.g. menu or level transition). ev contains the level number. """ pygame.display.init() # OK to init multiple times pygame.font.init() self._em = em window = pygame.display.set_mode(resolution) self.window = window pygame.display.set_caption("Smoothie Factory - In Play") # blit the bg screen: all black bg = Surface(window.get_size()) bg.fill((0, 0, 0)) bg = bg.convert() self.window_bg = bg self.window.blit(bg, (0, 0)) # fruit sprites self.fruit_to_spr = {} # map a fruit to its sprite self.fruit_sprites = LayeredDirty() # only reblit when dirty=1 self.interp_steps = 0 # 2 interpolation steps between 2 model updates # build GUI self.gui = self._build_gui() # return a sprite group em.subscribe(BoardBuiltEvent, self.on_board_built) em.subscribe(GameBuiltEvent, self.on_game_built) em.subscribe(FruitKilledEvent, self.on_fruit_killed) em.subscribe(FruitPlacedEvent, self.on_fruit_spawned) em.subscribe(FruitSpeedEvent, self.on_speed_change) em.subscribe(QuitEvent, self.on_quit) def _build_gui(self): """ Add a score widget on the right """ gui = LayeredDirty() # only reblit when dirty=1 # score at top-right of the window rec = Rect(600 + 10, 0, 100, font_size * 1.5) evt_txt_dict = {RecipeMatchEvent: "current_score"} score_widget = TextLabelWidget( self._em, "0", events_attrs=evt_txt_dict, rect=rec, txtcolor=(0, 0, 0), bgcolor=(222, 222, 222) ) gui.add(score_widget) # CPU at bottom-right of the window rec = Rect(600 + 10, 600 - font_size * 1.5, 100, font_size * 1.5) cpu_widget = CPUDisplayWidget(self._em, "0", rect=rec, txtcolor=(0, 0, 0), bgcolor=(222, 222, 222)) gui.add(cpu_widget) # the recipe widget added when the game is built return gui def on_game_built(self, ev): """ Build the recipe GUI, and set the spr movement timer. """ # recipe widget evt_recipe_dict = {RecipeMatchEvent: "recipe"} rec = Rect(600, font_size * 1.5, 150, 400) # ev.recipes maps tuples of fruit type to score rwid = RecipesWidget( self._em, ev.recipes, evt_recipe_dict, rect=rec, txtcolor=(222, 222, 222), bgcolor=(0, 0, 0) ) self.gui.add(rwid) # spr movement timer model_mvt_timer = 1000 / ev.fruit_speed self.base_spr_timer = model_mvt_timer / steps_per_cell self.spr_timer = self.base_spr_timer self._em.subscribe(VTickEvent, self.on_tick) def on_board_built(self, ev): """ Build the board background. """ width, height = ev.width, ev.height board = ev.board # to obtain cells from coords win_height = self.window.get_height() bg = Surface((win_height, win_height)) bg = bg.convert() bg.fill(bg_color) for left in range(width): for top in range(height): cell = board.get_cell(left, top) bg.blit(cell.image, cell.rect) # blit the board bg onto the window's bg self.window_bg.blit(bg, (0, 0)) self._em.subscribe(BoardUpdatedEvent, self.on_board_update) def on_fruit_spawned(self, ev): """ When a fruit appears, add it to the sprite group """ fruit = ev.fruit fruit_spr = FruitSpr(fruit, self.interp_steps) self.fruit_to_spr[fruit] = fruit_spr self.fruit_sprites.add(fruit_spr) def on_fruit_killed(self, ev): """ When a fruit is killed, remove the spr """ fruit = ev.fruit fruit_spr = self.fruit_to_spr[fruit] fruit_spr.kill() # remove fruit_spr from self.fruit_sprites del self.fruit_to_spr[fruit] def on_board_update(self, ev): """ Store the new fruits' positions. The actual display happens at clock tick. """ # prepare spr interpolation timer and step counter self.spr_timer = self.base_spr_timer self.interp_steps = 0 # restart interpolating fruit positions for fruit_spr in self.fruit_sprites: fruit_spr.resync(self.interp_steps) def on_tick(self, ev): """ Blit the active board elements and the GUI on the screen. """ if not pygame.display.get_init(): # if the display is ON return # spr positions duration = ev.loopduration self.spr_timer -= duration if self.spr_timer <= 0: self.spr_timer = self.base_spr_timer self.interp_steps += 1 # interpolate 3 positions, # but the last one is done when board is updated (so only 2) if self.interp_steps < steps_per_cell: for fruit in self.fruit_sprites: fruit.resync(self.interp_steps) # display gui = self.gui fruits = self.fruit_sprites screen = self.window bg = self.window_bg # clear the window from all the sprites, replacing them with the bg gui.clear(screen, bg) fruits.clear(screen, bg) gui.update(duration) # call update() on each sprite of the group fruits.update(duration) # reset the dirty flag to 0 # collect the display areas that need to be redrawn dirty_gui = gui.draw(screen) dirty_fruits = fruits.draw(screen) dirty_rects = dirty_gui + dirty_fruits pygame.display.update(dirty_rects) # redisplay those areas only # flip the screen pygame.display.flip() def on_speed_change(self, ev): """ When the fruit speed changes, update the speed of fruit sprites. """ model_mvt_timer = 1000 / ev.speed self.base_spr_timer = model_mvt_timer / steps_per_cell def on_quit(self, ev): """ Shut down the display """ pygame.display.quit()
from pygame import Color, font from pygame.math import Vector2 from pygame.sprite import LayeredDirty from src.models import Hole as BaseHole from src.sprites import * from src.utils import colors, Point Hole = BaseHole( 'Hole #3', par=3, origin=Point(50, 50, 0), ball=Point(253, 555, 0), noncollidibles=LayeredDirty( Text(Point(850, 183), 'Par 3', font.Font(None, 30), colors.WHITE) ), collidibles=LayeredDirty( Green([Point(180, 140, 0), Point(830, 140, 0), Point(830, 240, 0), Point(310, 240, 0), Point(310, 590, 0), Point(180, 590, 0)]), Rough([Point(310, 240, 0), Point(380, 240, 0), Point(380, 590, 0), Point(310, 590, 0)]), Sand([Point(380, 240, 0), Point(830, 240, 0), Point(830, 310, 0), Point(380, 310, 0)]), Pin(Point(780, 190, 0)), Money(Point(773, 265)), Wall(Point(180, 140, 0), Point(830, 140, 0), 5), Wall(Point(830, 140, 0), Point(830, 310, 0), 5), Wall(Point(830, 310, 0), Point(380, 310, 0), 5), Wall(Point(380, 310, 0), Point(380, 590, 0), 5), Wall(Point(380, 590, 0), Point(180, 590, 0), 5), Wall(Point(180, 590, 0), Point(180, 140, 0), 5) ) )
class Screen(object): def __init__(self, name): State.name = name State.screen = self State.controls = State.screens[State.name]['controls'] State.groups = {} self.layers = LayeredDirty() self.add_all() State.save(State.name) def add_all(self): """Add all the objects specified in the screen's configuration resource to their proper sprite groups for rendering.""" for obj in State.screens[State.name]['objects']: self.add_object(obj) def add_object(self, name, amount=1, pos=None): """Add one or many of a single game object resource to the screen. name: the name of the game object. amount: the amount of instances to add. pos: if value is 'random', every object will start in a random location. if value is a (x,y) tuple, every object will start at that screen location.""" obj = State.objects[name] new_pos = None for i in range(0, amount): if pos == 'random': scr = State.window.get_size() spr = obj['size'] new_pos = (randint(0, scr[0]/spr[0]), randint(0, scr[1]/spr[1])) elif type(pos) == type(tuple()): new_pos = pos if new_pos: obj['pos'] = new_pos group = obj['group'] if group not in State.groups: State.groups[group] = Group() sprite = eval(group.capitalize())(obj) State.groups[group].add(sprite) if obj['cursor']: State.cursor = sprite self.layers.add(State.groups[group]) def draw(self): """Run the update method of every sprite, keeping track of which ones are dirty and need updating, and then finally updating only the dirty areas.""" self.layers.update() State.dirty = self.layers.draw(State.window) display.update(State.dirty) def switch(self, name): """Switch to a new screen by saving the current state, and then restoring the specified state.""" State.save(State.name) State.prev_name = State.name State.restore(name) def restore(self): """Called when a screen is restored from a saved state.""" State.pressed = [] for group in State.groups: for sprite in State.groups[group]: sprite.dirty = 1 sprite.stopped = True
from pygame import Color, font from pygame.math import Vector2 from pygame.sprite import LayeredDirty from src.models import Hole as BaseHole from src.sprites import * from src.utils import colors, Point Hole = BaseHole( 'Hole #11', par=3, origin=Point(75, 50, 0), ball=Point(180, 680, 0), noncollidibles=LayeredDirty( Text(Point(900, 75), 'Par 3', font.Font(None, 30), colors.WHITE), ), collidibles=LayeredDirty( Green([Point(130, 620, 0), Point(230, 620, 0), Point(230, 730, 0), Point(130, 730, 0)]), Rough([Point(230, 730, 0), Point(230, 680, 0), Point(350, 680, 0), Point(350, 730, 0)]), Slope([Point(230, 620, 0), Point(230, 540, 0), Point(350, 540, 0), Point(350, 620, 0)], Color(200, 0, 0, 255), Vector2(0.15, 0.4)), Green([Point(230, 620, 0), Point(230, 680, 0), Point(350, 680, 0), Point(350, 620, 0)]), Rough([Point(350, 460, 0), Point(470, 460, 0), Point(470, 730, 0), Point(350, 730, 0)]), Green([Point(470, 620, 0), Point(710, 620, 0), Point(710, 680, 0), Point(590, 680, 0), Point(590, 730, 0), Point(470, 730, 0)]), Green([Point(650, 620, 0), Point(650, 310, 0), Point(790, 310, 0), Point(790, 620, 0)]), Sand([Point(790, 620, 0), Point(790, 560, 0), Point(880, 560, 0), Point(880, 620, 0)]), Water([Point(790, 560, 0), Point(790, 450, 0), Point(880, 450, 0), Point(880, 560, 0)]), Sand([Point(790, 450, 0), Point(790, 310, 0), Point(880, 310, 0), Point(880, 450, 0)]), Slope([Point(470, 510, 0), Point(470, 390, 0), Point(650, 390, 0), Point(650, 510, 0)], Color(200, 0, 0, 255), Vector2(-0.2, -0.15)), Green([Point(470, 460, 0), Point(130, 460, 0), Point(130, 310, 0), Point(470, 310, 0)]), Rough([Point(470, 390, 0), Point(470, 190, 0), Point(560, 190, 0), Point(560, 390, 0)]),
class MapView: def __init__(self, action_handler, index): # Init clock self.clock = pyg.time.Clock() # Set handler self.action_handler = action_handler # Init groupsView self.all_sprites = LayeredDirty(_use_updates = True, _time_threshold = 1000) Fps.containers += (self.all_sprites,) # Create window self.screen, self.background = reset_screen() if DISPLAY_FPS: Fps(self.clock) # Blit level image, rect = get_stage_image(index) self.background.blit(image, rect) self.screen.blit(self.background, self.background.get_rect()) # Tile handling from TileView import TileView TileView.layer_container = self.all_sprites # Initialize attributes self.exit = False self.done = False self.countdown = None def win(self): self.done = True self.win = True self.countdown = countdown(GoalView.len_animation) def lose(self, nb_tiles): self.done = True self.win = False value = MinimizingPlayerView.len_animation value += TeleportingPlayerView.len_animation * (nb_tiles-2) value += FallingPlayerView.len_animation value *= 2 self.countdown = countdown(value) def reactor_loop(self): # Infinite loop while True: # Get input for ev in pyg.event.get(): # Quit if (ev.type == pyg.KEYDOWN and ev.key == pyg.K_ESCAPE)\ or ev.type == pyg.QUIT: safe_exit() # Fullscreen if ev.type == pyg.KEYDOWN and ev.key == pyg.K_f: # Toggle fullscreen Constants.FULLSCREEN ^= True # Reset screen self.screen, _ = reset_screen() args = self.background, self.background.get_rect() self.screen.blit(*args) # Repaint all self.all_sprites._use_update = False # Mute if ev.type == pyg.KEYDOWN and ev.key == pyg.K_SEMICOLON: volume = 0 if pyg.mixer.music.get_volume() else VOLUME pyg.mixer.music.set_volume(float(volume)/100) # Reset if (ev.type == pyg.KEYDOWN and ev.key == pyg.K_r) or\ (ev.type == pyg.JOYBUTTONDOWN and ev.button in RESET_BUTTONS): win_reset = False, True return win_reset # Handle countdown if self.done and next(self.countdown): self.all_sprites.empty() win_reset = self.win, False return win_reset # Read input if not self.done: self.action_handler.read_inputs() # Clear sprites from screen self.all_sprites.clear(self.screen, self.background) # Update sprites self.all_sprites.update() # Draw sprites on screen dirty = self.all_sprites.draw(self.screen) # Update display pyg.display.update(dirty) # Frame rate control self.clock.tick(FPS)
from pygame import Color, font from pygame.math import Vector2 from pygame.sprite import LayeredDirty from src.models import Hole as BaseHole from src.sprites import * from src.utils import colors, Point Hole = BaseHole( 'Hole #13', par=3, origin=Point(100, 0, 0), ball=Point(495, 315, 0), noncollidibles=LayeredDirty( Text(Point(775, 605), 'Par 3', font.Font(None, 30), colors.WHITE), ), collidibles=LayeredDirty( Green([ Point(440, 260, 0), Point(540, 260, 0), Point(540, 360, 0), Point(440, 360, 0) ]), Slope([ Point(440, 360, 0), Point(510, 360, 0), Point(510, 410, 0), Point(470, 410, 0), Point(470, 460, 0), Point(440, 460, 0) ], Color(200, 0, 0, 255), Vector2(0.5, 0.5)), Slope([
from pygame import Color, font from pygame.math import Vector2 from pygame.sprite import LayeredDirty from src.models import Hole as BaseHole from src.sprites import * from src.utils import colors, Point Hole = BaseHole( 'Hole #4', par=4, origin=Point(50, 100, 0), ball=Point(312, 580, 0), noncollidibles=LayeredDirty( Text(Point(900, 268), 'Par 4', font.Font(None, 30), colors.WHITE), ), collidibles=LayeredDirty( Green([Point(250, 600, 0), Point(250, 150, 0), Point(370, 150, 0), Point(370, 250, 0), Point(770, 250, 0), Point(770, 150, 0), Point(870, 150, 0), Point(870, 400, 0), Point(770, 400, 0), Point(770, 300, 0), Point(370, 300, 0), Point(370, 600, 0)]), Slope([Point(250, 150, 0), Point(250, 90, 0), Point(370, 90, 0), Point(370, 150, 0)], Color(100, 0, 0, 255), Vector2(0.0, -0.7)), Sand([Point(250, 90, 0), Point(250, 50, 0), Point(370, 50, 0), Point(370, 90, 0)]), Slope([Point(410, 250, 0), Point(410, 200, 0), Point(770, 200, 0), Point(770, 250, 0)], Color(100, 0, 0, 255), Vector2(-0.33, -0.6)), Slope([Point(410, 300, 0), Point(410, 360, 0), Point(770, 360, 0), Point(770, 300, 0)], Color(100, 0, 0, 255), Vector2(-0.33, 0.6)), Rough([Point(410, 200, 0), Point(410, 150, 0), Point(770, 150, 0), Point(770, 200, 0)]), Rough([Point(770, 400, 0), Point(410, 400, 0), Point(410, 360, 0), Point(770, 360, 0)]), Pin(Point(840, 275, 0)), Money(Point(305, 200)), Wall(Point(250, 50, 0), Point(370, 50, 0), 5), Wall(Point(370, 50, 0), Point(370, 250, 0), 5), Wall(Point(370, 250, 0), Point(410, 250, 0), 5), Wall(Point(410, 250, 0), Point(410, 150, 0), 5),
from pygame import Color, font from pygame.math import Vector2 from pygame.sprite import LayeredDirty from src.models import Hole as BaseHole from src.sprites import * from src.utils import colors, Point Hole = BaseHole('Hole #12', par=5, origin=Point(80, 30, 0), ball=Point(440, 125, 0), noncollidibles=LayeredDirty( Text(Point(530, 15), 'Par 5', font.Font(None, 30), colors.WHITE), ), collidibles=LayeredDirty( Green([ Point(50, 50, 0), Point(500, 50, 0), Point(500, 200, 0), Point(100, 200, 0), Point(100, 450, 0), Point(50, 450, 0) ]), Slope([ Point(100, 200, 0), Point(200, 200, 0), Point(200, 450, 0), Point(100, 450, 0) ], Color(200, 0, 0, 255), Vector2(0.3, 0.0)), Sand([
class BaseScene(Scene): def __init__(self, engine, *, background_color=(0, 0, 55), container_class=GameObjectCollection, **kwargs): super().__init__(engine) self.background_color = background_color self.background = engine.display.copy() self.background.fill(self.background_color) self.game_objects = container_class() self.render_group = LayeredDirty() def __contains__(self, item: Hashable) -> bool: return item in self.game_objects def render(self): window = self.engine.display self.render_group.add(s for s in self.game_objects) return self.render_group.draw(window, self.background) def simulate(self, time_delta: float): for game_object in self.game_objects: game_object.update(time_delta) def change(self): """ Default case, override in subclass as necessary. """ return self.running, {"scene_class": self.next} def add(self, game_object: Hashable, tags: Iterable = ()) -> None: """ Add a game_object to the scene. game_object: Any GameObject object. The item to be added. tags: An iterable of Hashable objects. Values that can be used to retrieve a group containing the game_object. Examples: scene.add(MyGameObject()) scene.add(MyGameObject(), tags=("red", "blue") """ self.game_objects.add(game_object, tags) def get(self, *, kind: Type = None, tag: Hashable = None, **kwargs) -> Iterator: """ Get an iterator of GameObjects by kind or tag. kind: Any type. Pass to get a subset of contained GameObjects with the given type. tag: Any Hashable object. Pass to get a subset of contained GameObjects with the given tag. Pass both kind and tag to get objects that are both that type and that tag. Examples: scene.get(type=MyGameObject) scene.get(tag="red") scene.get(type=MyGameObject, tag="red") """ return self.game_objects.get(kind=kind, tag=tag, **kwargs) def remove(self, game_object: Hashable) -> None: """ Remove the given object from the scene. game_object: A game object. Example: scene.remove(my_game_object) """ self.game_objects.remove(game_object)
from pygame import Color, font from pygame.math import Vector2 from pygame.sprite import LayeredDirty from src.models import Hole as BaseHole from src.sprites import * from src.utils import colors, Point Hole = BaseHole('Hole #10', par=2, origin=Point(50, 75, 0), ball=Point(485, 690, 0), noncollidibles=LayeredDirty( Text(Point(810, 340), 'Par 2', font.Font(None, 30), colors.WHITE), ), collidibles=LayeredDirty( Rough([ Point(300, 430, 0), Point(340, 430, 0), Point(340, 470, 0), Point(300, 470, 0) ]), Rough([ Point(630, 430, 0), Point(670, 430, 0), Point(670, 470, 0), Point(630, 470, 0) ]), Slope([ Point(300, 430, 0), Point(260, 390, 0),
class MapView: def __init__(self, action_handler, index): # Init clock self.clock = pyg.time.Clock() # Set handler self.action_handler = action_handler # Init groupsView self.all_sprites = LayeredDirty() Fps.containers += (self.all_sprites,) # Create window self.screen, self.background = reset_screen() if DISPLAY_FPS: Fps(self.clock) # Blit level image, rect = get_stage_image(index) self.background.blit(image, rect) # Tile handling from TileView import TileView TileView.layer_container = self.all_sprites # Initialize attributes self.exit = False self.done = False self.countdown = None def win(self): self.done = True self.win = True self.countdown = countdown(GoalView.len_animation) def lose(self, nb_tiles): self.done = True self.win = False value = MinimizingPlayerView.len_animation value += TeleportingPlayerView.len_animation * (nb_tiles-2) value += FallingPlayerView.len_animation value *= 2 self.countdown = countdown(value) def reactor_loop(self): # Infinite loop while True: # Get input for ev in pyg.event.get(): # Quit if (ev.type == pyg.KEYDOWN and ev.key == pyg.K_ESCAPE)\ or ev.type == pyg.QUIT: safe_exit() # Reset if ev.type == pyg.JOYBUTTONDOWN and \ ev.button in RESET_BUTTONS: win_reset = False, True return win_reset # Handle countdown if self.done and next(self.countdown): self.all_sprites.empty() win_reset = self.win, False return win_reset # Read input if not self.done: self.action_handler.read_inputs() # Clear sprites from screen self.all_sprites.clear(self.screen, self.background) # Update sprites self.all_sprites.update() # Draw sprites on screen dirty = self.all_sprites.draw(self.screen) # Update display pyg.display.flip() # Frame rate control self.clock.tick(FPS)
def init(cls): cls.contents = LayeredDirty() cls.clock = time.Clock()
def applyColour(self, colour): """Very simple colour substitution""" for x in range(0, self.rect.width): for y in range(0, self.rect.height): pixel = self.image.get_at((x, y)).r if (pixel > 50): self.image.set_at((x, y), colour) # create sprites bg = PpuiImage("assets/lcars_screen_1.png") button = PpuiImage("assets/button.png") button.applyColour((255, 204, 153)) # add sprites to layer sprites = LayeredDirty() sprites.add(bg) sprites.add(button) # event loop while pygame.display.get_init(): sprites.draw(screenSurface) pygame.display.update() for event in pygame.event.get(): if event.type == KEYUP: pygame.quit() break if (event.type == MOUSEMOTION): # move button around as mouse moves (or touch-drag)
def addGroup(): newGroup = LayeredDirty() groupList.append(newGroup)
class CatUniScene(Scene): # pylint:disable=too-many-instance-attributes """Cat unicycle scene.""" def __init__(self, *args, **kwargs): Scene.__init__(self, *args, **kwargs) (width, height) = (1920 // 2, 1080 // 2) self.width, self.height = width, height # Loading screen should always be a fallback active scene self.active = False self.first_render = True self.myfont = pygame.font.SysFont("monospace", 20) self.background = gfx("background.png", convert=True) # self.cat_unicycle = gfx('cat_unicycle.png').convert_alpha() # self.fish = gfx('fish.png').convert_alpha() # self.foot = gfx('foot.png').convert_alpha() # self.foot_part = gfx('foot_part.png').convert_alpha() # self.shark = gfx('shark.png').convert_alpha() sfx("cat_jump.ogg") sfx("eatfish.ogg") sfx("splash.ogg") sfx("cat_crash.ogg") self.meow_names = [ "cat_meow01.ogg", "cat_meow02.ogg", "cat_meow03.ogg" ] self.last_meow = None self.touching_ground = True self.jumping = False self.jumping_time = 0 self.jump_key = None for meow_name in self.meow_names: sfx(meow_name) self.boing_names = ["boing1.ogg", "boing2.ogg", "boing3.ogg"] for boing_name in self.boing_names: sfx(boing_name) self.people_mad = False self.people_mad_duration = 3000 # ms self.people_mad_current_time = 0 self.next_notfish = 0 self.notfish_time = 0 self.last_joy_right_tilt = 0 self.last_joy_left_tilt = 0 self.left_pressed = False self.right_pressed = False self.player_data = PlayerData(width, height) # timing self.dt_scaled = 0 self.total_time = 0 # elephant and shark classes self.elephant = Elephant(self) self.shark_active = False # is the shark enabled yet self.elephant_active = False self.cat = Cat(self) self.score_text = Score(self) self.allsprites = None # type: Optional[LayeredDirty] self.shark = None # type: Optional[Shark] self.init_sprites() # lists of things to catch by [posx, posy, velx, vely] # self.fish = [[0, height / 2, 10, -5]] self.fish = LayeredDirtyAppend() self.fish.extend([Fish(self.allsprites, (0, height / 2), (10, -5))]) self.not_fish = LayeredDirtyAppend() self.unicycle_sound = sfx("unicycle.ogg", play=True, loops=-1, fadein=500) self._reset_meow() # difficulty varibles self.number_of_not_fish = 0 def _reset_meow(self): self.next_meow = random.uniform(5000, 10000) def _meow(self): # Play a meow sound, but not the same one twice in a row meow_names = self.meow_names[:] if self.last_meow in self.meow_names: meow_names.remove(self.last_meow) self.last_meow = random.choice(meow_names) sfx(self.last_meow, play=1) self._reset_meow() def init_sprites(self): """temp, this will go in the init.""" sprite_list = [self.elephant, self.cat, self.score_text] self.allsprites = LayeredDirty(sprite_list, _time_threshold=1000 / 10.0) scene = self self.shark = Shark(self.allsprites, scene, self.width, self.height) self.allsprites.add(self.shark) self.allsprites.clear(self.screen, self.background) def reset_on_death(self): """Reset on death. What to do when you die, reset the level. """ self.player_data.reset() self.total_time = 0 self.elephant.last_animation = 0 self.elephant.state = 0 self.elephant.just_happened = None self.elephant.dirty = 1 self.elephant_active = False self.elephant.animate(self.total_time) # make the shark leave self.shark_active = False self.shark.last_animation = 0 self.shark.dirty = True if self.shark.get_state() in ("aiming", "fire laser"): self.shark.just_happened = None self.shark.set_state("leaving") self.shark.applaud = False else: self.shark.just_happened = None self.shark.set_state("offscreen") self.shark.animate(self.total_time) sfx("shark_appear.ogg", fadeout=1000) if self.shark.lazer: self.shark.lazer.kill() def increase_difficulty(self): """ Periodically increase the difficulty.""" self.number_of_not_fish = 0 if self.player_data.score > 3: self.number_of_not_fish = 1 if self.player_data.score > 9: self.number_of_not_fish = 1 if self.player_data.score > 15: self.number_of_not_fish = 2 if self.player_data.score > 19: self.number_of_not_fish = 1 if self.player_data.score > 25: self.number_of_not_fish = 2 if self.player_data.score > 35: self.number_of_not_fish = 3 if self.player_data.score >= 50: self.number_of_not_fish = int((self.player_data.score - 20) / 10) if self.player_data.score >= 10: self.shark_active = True # Elephant doesn't work yet, so let's not use it # if self.player_data.score >= 20: # self.elephant_active = True def annoy_crowd(self): """ Annoy the crowd.""" self.people_mad = True self.people_mad_current_time = 0 def render_sprites(self): """ Render the sprites.""" rects = [] self.allsprites.update(time_delta=self.dt_scaled, height=self.height, player_data=self.player_data) rects.extend(self.allsprites.draw(self.screen)) return rects def render(self): rects = [] if self.first_render: self.first_render = False rects.append(self.screen.get_rect()) rects.extend(self.render_sprites()) return rects def tick(self, time_delta): self.increase_difficulty() self.cat.animate(time_delta) self.total_time += ( time_delta # keep track of the total number of ms passed during the game ) dt_scaled = time_delta / 17 self.dt_scaled = dt_scaled width, height = self.width, self.height ##cat physics self.player_data.cat_angular_vel *= ( 0.9**dt_scaled) # max(0.9/(max(0.1,dt_scaled)),0.999) # make the cat slide in the direction it's rotated self.player_data.cat_speed[0] += math.sin( self.player_data.cat_angle) * (dt_scaled * self.player_data.cat_roll_speed) # add gravity self.player_data.cat_speed[1] = min( self.player_data.cat_speed[1] + (1 * dt_scaled), self.player_data.cat_fall_speed_max, ) self.unicycle_sound.set_volume( abs(self.player_data.cat_speed[0] / self.player_data.cat_speed_max)) self._move_cat() self._cat_out_of_bounds() # check for collision with the elephant stomp if self.elephant_active: self.elephant.animate(self.total_time) self.elephant.collide(width) if self.shark_active or self.shark.states[ self.shark.state] == "leaving": self.shark.animate(self.total_time) self.shark.collide(self, width, height, self.player_data.cat_location) self._cat_jumping(time_delta) self._cats_meow(time_delta) self._angry_people(time_delta) self._collide_flying_objects() self._spawn_flying_objects() def _move_cat(self): """Move, accelerate, and tilt the cat.""" # accelerate the cat left or right if self.right_pressed: self.player_data.cat_speed[0] = min( self.player_data.cat_speed[0] + 0.3 * self.dt_scaled, self.player_data.cat_speed_max, ) self.player_data.cat_angle -= 0.003 * self.dt_scaled if self.left_pressed: self.player_data.cat_speed[0] = max( self.player_data.cat_speed[0] - 0.3 * self.dt_scaled, -self.player_data.cat_speed_max, ) self.player_data.cat_angle += 0.003 * self.dt_scaled # make the cat fall angle_sign = 1 if self.player_data.cat_angle > 0 else -1 self.player_data.cat_angular_vel += 0.0002 * angle_sign * self.dt_scaled self.player_data.cat_angle += self.player_data.cat_angular_vel * self.dt_scaled if (self.player_data.cat_angle > math.pi / 2 or self.player_data.cat_angle < -math.pi / 2 ) and self.player_data.cat_location[1] > self.height - 160: sfx("cat_crash.ogg", play=1) self.reset_on_death() # move cat self.player_data.cat_location[0] += (self.player_data.cat_speed[0] * self.dt_scaled) self.player_data.cat_location[1] += (self.player_data.cat_speed[1] * self.dt_scaled) if (self.player_data.cat_location[1] > self.player_data.cat_wire_height and self.player_data.cat_location[0] > 0.25 * self.width): self.touching_ground = True self.player_data.cat_location[1] = self.player_data.cat_wire_height self.player_data.cat_speed[1] = 0 else: self.touching_ground = False def _cat_out_of_bounds(self): """check for out of bounds""" # in the pool if self.player_data.cat_location[1] > self.height: sfx("splash.ogg", play=1) self._meow() self.reset_on_death() # to the right of screen. if self.player_data.cat_location[0] > self.width: self.player_data.cat_location[0] = self.width if self.player_data.cat_angle > 0: self.player_data.cat_angle *= 0.7 self.player_data.cat_head_location = [ int(self.player_data.cat_location[0] + 100 * math.cos(self.player_data.cat_angle - math.pi / 2)), int(self.player_data.cat_location[1] + 100 * math.sin(self.player_data.cat_angle - math.pi / 2)), ] if (self.player_data.cat_location[0] > 0.98 * self.width and self.player_data.cat_location[1] > self.player_data.cat_wire_height - 30): # bump the cat back in self._meow() sfx(random.choice(self.boing_names), play=True) self.player_data.cat_angular_vel -= 0.01 * self.dt_scaled self.player_data.cat_speed[0] = -5 self.player_data.cat_speed[1] = -20 # self.reset_on_death() if (self.player_data.cat_location[0] < 0.25 * self.width and self.player_data.cat_location[1] > self.player_data.cat_wire_height - 30): pass def _cat_jumping(self, time_delta): """jumping physics""" if self.jumping: self.player_data.cat_speed[1] -= ( time_delta * ((CAT_MAX_JUMPING_TIME - self.jumping_time) / CAT_MAX_JUMPING_TIME) * CAT_JUMP_SPEED) self.jumping_time += time_delta if self.jumping_time >= CAT_MAX_JUMPING_TIME: self.jumping = False def _cats_meow(self, time_delta): """meow timing""" if self.next_meow <= 0: self._meow() self.next_meow -= time_delta def _angry_people(self, time_delta): """angry people (increased throwing of not-fish)""" if self.people_mad: self.people_mad_current_time += time_delta self.notfish_time += time_delta if self.notfish_time >= self.next_notfish: self.next_notfish = random.randint(100, 400) self.notfish_time = 0 self._spawn_not_fish() if self.people_mad_current_time >= self.people_mad_duration: self.people_mad = False def _collide_flying_objects(self): """object physics""" height = self.height dt_scaled = self.dt_scaled # move fish and not fish for fish in reversed(self.fish.sprites()): fish.pos[0] += fish.velocity[0] * dt_scaled # speed of the throw fish.velocity[1] += 0.2 * dt_scaled # gravity fish.pos[1] += fish.velocity[1] * dt_scaled # y velocity # check out of bounds if fish.pos[1] > height: self.fish.remove(fish) fish.kill() for fish in reversed(self.not_fish.sprites()): fish.pos[0] += fish.velocity[0] * dt_scaled # speed of the throw fish.velocity[1] += 0.2 * dt_scaled # gravity fish.pos[1] += fish.velocity[1] * dt_scaled # y velocity # check out of bounds if fish.pos[1] > height: self.not_fish.remove(fish) fish.kill() # check collision with the cat for fish in reversed(self.fish.sprites()): if (distance([fish.rect[0], fish.rect[1]], self.player_data.cat_head_location) < 100): self.player_data.increment_score() self.fish.remove(fish) sfx("eatfish.ogg", play=1) fish.kill() for fish in reversed(self.not_fish.sprites()): if (distance([fish.rect[0], fish.rect[1]], self.player_data.cat_head_location) < 50): self.not_fish.remove(fish) fish.kill() self.player_data.angle_to_not_fish = (math.atan2( self.player_data.cat_head_location[1] - fish.rect[1], self.player_data.cat_head_location[0] - fish.rect[0], ) - math.pi / 2) side = 1 if self.player_data.angle_to_not_fish < 0 else -1 self.player_data.cat_angular_vel += side * random.uniform( 0.08, 0.15) sfx(random.choice(self.boing_names), play=True) def _spawn_flying_objects(self): """Throws random objects at the cat.""" width, height = self.width, self.height # refresh lists while len(self.fish) < 1 and not self.people_mad: # choose a side of the screen if random.choice([0, 1]) == 0: self.fish.append( Fish( self.allsprites, (0, height / 2), # random.randint(0, height / 2), (random.randint(3, 7), -random.randint(5, 12)), )) else: self.fish.append( Fish( self.allsprites, (width, height / 2), # random.randint(0, height / 2), (-random.randint(3, 7), -random.randint(5, 12)), )) while len(self.not_fish) < self.number_of_not_fish: self._spawn_not_fish() def _spawn_not_fish(self): """Choose a side of the screen.""" velocity_multiplier = 1 x_pos = 0 if random.randint(0, 1): velocity_multiplier *= -1 x_pos = self.width self.not_fish.append( NotFish( self.allsprites, (x_pos, self.height / 2), (random.randint(3, 7) * velocity_multiplier, -random.randint(5, 12)), )) def _start_jump(self, key): self.jump_key = key if self.touching_ground and not self.jumping: self.jumping = True self.jumping_time = 0 self.player_data.cat_speed[1] -= 12.5 sfx("cat_jump.ogg", play=1) def _stop_jump(self): self.jumping = False sfx("cat_jump.ogg", fadeout=50) def _tilt_left(self): self.player_data.cat_angular_vel -= random.uniform( 0.01 * math.pi, 0.03 * math.pi) def _tilt_right(self): self.player_data.cat_angular_vel += random.uniform( 0.01 * math.pi, 0.03 * math.pi) def _event_keydown(self, event): if event.key == pygame.K_RIGHT: self.right_pressed = True elif event.key == pygame.K_LEFT: self.left_pressed = True elif event.key == pygame.K_a: self._tilt_left() elif event.key == pygame.K_d: self._tilt_right() elif event.key in (pygame.K_UP, pygame.K_SPACE): self._start_jump(event.key) def _event_keyup(self, event): if event.key == self.jump_key: self._stop_jump() elif event.key == pygame.K_RIGHT: self.right_pressed = False elif event.key == pygame.K_LEFT: self.left_pressed = False def _event_joybuttondown(self, event): if event.button in JOY_JUMP_BUTTONS: self._start_jump("JOY" + str(event.button)) if event.button in JOY_LEFT_BUTTONS: self._tilt_left() if event.button in JOY_RIGHT_BUTTONS: self._tilt_right() def _event_joybuttonup(self, event): if "JOY" + str(event.button) == self.jump_key: self._stop_jump() def _event_joyaxismotion(self, event): if event.axis == 0: if event.value >= JOY_SENSE: self.right_pressed = True self.left_pressed = False elif event.value <= -JOY_SENSE: self.right_pressed = False self.left_pressed = True else: self.right_pressed = False self.left_pressed = False if event.axis == JOY_TILT_RIGHT_AXIS: # if self.last_joy_right_tilt < JOY_SENSE and event.value >= JOY_SENSE: if self.last_joy_right_tilt < JOY_SENSE < event.value: self._tilt_right() self.last_joy_right_tilt = event.value if event.axis == JOY_TILT_LEFT_AXIS: # if self.last_joy_left_tilt < JOY_SENSE and event.value >= JOY_SENSE: if self.last_joy_left_tilt < JOY_SENSE < event.value: self._tilt_left() self.last_joy_left_tilt = event.value def event(self, event): if event.type == pygame.KEYDOWN: self._event_keydown(event) elif event.type == pygame.KEYUP: self._event_keyup(event) elif event.type == pygame.JOYBUTTONDOWN: self._event_joybuttondown(event) elif event.type == pygame.JOYBUTTONUP: self._event_joybuttonup(event) elif event.type == pygame.JOYAXISMOTION: self._event_joyaxismotion(event)
def __init__(self, *args, **kwargs): kwargs.setdefault("_time_threshold", 9e9) LayeredDirty.__init__(self, *args, **kwargs)
class CatUniScene(Scene): def __init__(self, *args, **kwargs): Scene.__init__(self, *args, **kwargs) (width, height) = (1920//2, 1080//2) self.width, self.height = width, height # Loading screen should always be a fallback active scene self.active = False self.first_render = True self.myfont = pygame.font.SysFont("monospace", 20) self.background = gfx('background.png').convert() # self.cat_unicycle = gfx('cat_unicycle.png').convert_alpha() # self.fish = gfx('fish.png').convert_alpha() # self.foot = gfx('foot.png').convert_alpha() # self.foot_part = gfx('foot_part.png').convert_alpha() # self.shark = gfx('shark.png').convert_alpha() sfx('cat_jump.ogg') sfx('eatfish.ogg') #cat variables self.cat_wire_height = height - 100 self.cat_location = [width / 2, height - 100] self.cat_speed = [0, 0] self.cat_speed_max = 8 self.cat_fall_speed_max = 16 self.cat_angle = 0 self.cat_angular_vel = 0 self.cat_head_location = [ int(self.cat_location[0] + 100 * math.cos(self.cat_angle - math.pi / 2)), int(self.cat_location[1] + 100 * math.sin(self.cat_angle - math.pi / 2)), ] self.left_pressed = False self.right_pressed = False self.score = 0 #timing self.dt_scaled = 0 self.total_time = 0 #elephant and shark classes self.elephant = Elephant(self) self.shark_active = False #is the shark enabled yet self.elephant_active = False self.cat = Cat(self) self.score_text = Score(self) self.deadzones = [] # self.deadzones = [ # DeadZone( # [ # [0, height - 100], # [0.1 * width, height - 100], # [0.1 * width, height], # [0, height], # ], # ), # DeadZone( # [ # [0.9 * width, height - 100], # [width, height - 100], # [width, height], # [0.9 * width, height], # ], # ), # ] self.init_sprites() # lists of things to catch by [posx, posy, velx, vely] # self.fish = [[0, height / 2, 10, -5]] self.fish = LayeredDirtyAppend() self.fish.extend([Fish(self.allsprites, 0, height / 2, 10, -5)]) self.not_fish = LayeredDirtyAppend() #difficulty varibles self.number_of_not_fish = 0 def init_sprites(self): """temp, this will go in the init. """ sprite_list = [ self.elephant, self.cat, self.score_text ] sprite_list += self.deadzones self.allsprites = LayeredDirty( sprite_list, _time_threshold=1000/10.0 ) scene = self self.shark = Shark(self.allsprites, scene, self.width, self.height) self.allsprites.add(self.shark) self.allsprites.clear(self.screen, self.background) #what to do when you die, reset the level def reset_on_death(self): self.cat_location = [self.width / 2, self.height - 100] self.cat_speed = [0, 0] self.cat_angle = 0 self.cat_angular_vel = 0 self.score = 0 self.total_time = 0 self.elephant.last_animation = 0 self.elephant.state = 0 self.elephant.just_happened = None self.elephant.dirty = 1 self.elephant_active = False self.shark.last_animation = 0 self.shark.state = 0 self.shark_active = False self.shark.just_happened = None self.shark.dirty = 1 if hasattr(self.shark, 'lazer'): self.shark.lazer.kill() #periodically increase the difficulty def increase_difficulty(self): self.number_of_not_fish = 0 if self.score > 3: self.number_of_not_fish = 1 if self.score > 9: self.number_of_not_fish = 1 if self.score > 15: self.number_of_not_fish = 2 if self.score > 19: self.number_of_not_fish = 1 if self.score > 25: self.number_of_not_fish = 2 if self.score > 35: self.number_of_not_fish = 3 if self.score >= 50: self.number_of_not_fish = int((self.score - 20)/10) #TODO: to make it easier to test. # if self.score >= 15: # self.shark_active = True if self.score >= 10: self.shark_active = True #TODO: to make it easier to test. if self.score >= 20: self.elephant_active = True def render_sprites(self): rects = [] self.allsprites.update() rects.extend(self.allsprites.draw(self.screen)) return rects def render(self): rects = [] if self.first_render: self.first_render = False rects.append(self.screen.get_rect()) rects.extend(self.render_sprites()) return rects # we draw the sprites, and then the lines over the top. self.render_sprites() screen = self.screen width, height = self.width, self.height if 0: background_colour = (0, 0, 0) screen.fill(background_colour) screen.blit(self.background, (0, 0)) self.elephant.render(screen, width, height) self.shark.render(screen, width, height) # draw cat pygame.draw.line( screen, [0, 0, 255], self.cat_location, self.cat_head_location, 20 ) pygame.draw.circle(screen, [0, 0, 255], self.cat_head_location, 50, 1) pygame.draw.circle(screen, [0, 255, 0], self.cat_head_location, 100, 1) # draw dead zones pygame.draw.polygon( screen, [255, 0, 0], [ [0, height - 100], [0.1 * width, height - 100], [0.1 * width, height], [0, height], ], ) pygame.draw.polygon( screen, [255, 0, 0], [ [0.9 * width, height - 100], [width, height - 100], [width, height], [0.9 * width, height], ], ) # draw fish and not fish for f in self.fish: pygame.draw.circle(screen, [0, 255, 0], [int(f.pos[0]), int(f.pos[1])], 10) for f in self.not_fish: pygame.draw.circle(screen, [255, 0, 0], [int(f.pos[0]), int(f.pos[1])], 10) # draw score textsurface = self.myfont.render(str(self.score), True, [0, 0, 0] ) screen.blit(textsurface, (200, 300)) return [screen.get_rect()] def tick(self, dt): self.increase_difficulty() self.total_time += dt #keep track of the total number of ms passed during the game dt_scaled = dt/17 self.dt_scaled = dt_scaled width, height = self.width, self.height ##cat physics self.cat_angular_vel *= 0.9**dt_scaled #max(0.9/(max(0.1,dt_scaled)),0.999) # add gravity self.cat_speed[1] = min(self.cat_speed[1] + (1 * dt_scaled), self.cat_fall_speed_max) # accelerate the cat left or right if self.right_pressed: self.cat_speed[0] = min( self.cat_speed[0] + 0.3 * dt_scaled, self.cat_speed_max ) self.cat_angle -= 0.003 * dt_scaled if self.left_pressed: self.cat_speed[0] = max( self.cat_speed[0] - 0.3 * dt_scaled, -self.cat_speed_max ) self.cat_angle += 0.003 * dt_scaled # make the cat fall angle_sign = 1 if self.cat_angle > 0 else -1 self.cat_angular_vel += 0.0002 * angle_sign * dt_scaled self.cat_angle += self.cat_angular_vel * dt_scaled if (self.cat_angle > math.pi / 2 or self.cat_angle < -math.pi / 2) and self.cat_location[1] > height - 160: self.reset_on_death() # move cat self.cat_location[0] += self.cat_speed[0] * dt_scaled self.cat_location[1] += self.cat_speed[1] * dt_scaled if self.cat_location[1] > self.cat_wire_height and self.cat_location[0] > 0.25 * width: self.cat_location[1] = self.cat_wire_height self.cat_speed[1] = 0 if self.cat_location[1] > height: self.reset_on_death() if self.cat_location[0] > width: self.cat_location[0] = width if self.cat_angle > 0: self.cat_angle *= 0.7 self.cat_head_location = [ int(self.cat_location[0] + 100 * math.cos(self.cat_angle - math.pi / 2)), int(self.cat_location[1] + 100 * math.sin(self.cat_angle - math.pi / 2)), ] # check for out of bounds if self.cat_location[0] > 0.98 * width and self.cat_location[1] > self.cat_wire_height - 30: #bump the cat back in self.cat_angular_vel -= 0.01*dt_scaled self.cat_speed[0] = -5 self.cat_speed[1] = -20 #self.reset_on_death() if self.cat_location[0] < 0.25 * width and self.cat_location[1] > self.cat_wire_height - 30: pass #check for collision with the elephant stomp if self.elephant_active: self.elephant.animate(self.total_time) self.elephant.collide(self, width, height, self.cat_head_location) if self.shark_active: self.shark.animate(self.total_time) self.shark.collide(self, width, height, self.cat_location) ##object physics # move fish and not fish for f in reversed(self.fish.sprites()): f.pos[0] += f.velocity[0] * dt_scaled # speed of the throw f.velocity[1] += 0.2 * dt_scaled # gravity f.pos[1] += f.velocity[1] * dt_scaled # y velocity # check out of bounds if f.pos[1] > height: self.fish.remove(f) f.kill() for f in reversed(self.not_fish.sprites()): f.pos[0] += f.velocity[0] * dt_scaled # speed of the throw f.velocity[1] += 0.2 * dt_scaled # gravity f.pos[1] += f.velocity[1] * dt_scaled # y velocity # check out of bounds if f.pos[1] > height: self.not_fish.remove(f) f.kill() # check collision with the cat for f in reversed(self.fish.sprites()): if distance([f.rect[0], f.rect[1]], self.cat_head_location) < 100: self.score += 1 self.fish.remove(f) sfx('eatfish.ogg', play=1) f.kill() for f in reversed(self.not_fish.sprites()): if distance([f.rect[0], f.rect[1]], self.cat_head_location) < 50: self.not_fish.remove(f) f.kill() self.angle_to_not_fish = ( math.atan2( self.cat_head_location[1] - f.rect[1], self.cat_head_location[0] - f.rect[0], ) - math.pi / 2 ) side = 1 if self.angle_to_not_fish < 0 else -1 self.cat_angular_vel += side * random.uniform(0.08, 0.15) # refresh lists while len(self.fish) < 1: # choose a side of the screen if random.choice([0, 1]) == 0: self.fish.append( Fish(self.allsprites, 0, height/2,#random.randint(0, height / 2), random.randint(3, 7), -random.randint(5, 12), ) ) else: self.fish.append( Fish(self.allsprites, width, height/2,#random.randint(0, height / 2), -random.randint(3, 7), -random.randint(5, 12), ) ) while len(self.not_fish) < self.number_of_not_fish: # choose a side of the screen if random.choice([0, 1]) == 0: self.not_fish.append( NotFish(self.allsprites, 0, height/2,#random.randint(0, height / 2), random.randint(3, 7), -random.randint(5, 12), ) ) else: self.not_fish.append( NotFish(self.allsprites, width, height/2,#random.randint(0, height / 2), -random.randint(3, 7), -random.randint(5, 12), ) ) def event(self, event): width, height = self.width, self.height if event.type == KEYDOWN: if event.key == K_RIGHT: self.right_pressed = True # cat_speed[0] = min(cat_speed[0] + 2, cat_speed_max) # cat_angle -= random.uniform(0.02*math.pi, 0.05*math.pi) elif event.key == K_LEFT: self.left_pressed = True # cat_speed[0] = min(cat_speed[0] - 2, cat_speed_max) # cat_angle += random.uniform(0.02*math.pi, 0.05*math.pi) elif event.key == K_a: self.cat_angular_vel -= random.uniform(0.01 * math.pi, 0.03 * math.pi) elif event.key == K_d: self.cat_angular_vel += random.uniform(0.01 * math.pi, 0.03 * math.pi) elif event.key == K_UP: if self.cat_location[1] > self.cat_wire_height - 1: self.cat_speed[1] -= 25 sfx('cat_jump.ogg', play=1) elif event.type == KEYUP: if event.key == K_UP: if self.cat_speed[1] < 0: self.cat_speed[1] = 0 elif event.key == K_RIGHT: self.right_pressed = False elif event.key == K_LEFT: self.left_pressed = False
from pygame import Color, font from pygame.math import Vector2 from pygame.sprite import LayeredDirty from src.models import Hole as BaseHole from src.sprites import * from src.utils import colors, Point Hole = BaseHole( 'Hole #7', par=4, origin=Point(50, 50, 0), ball=Point(255, 630, 0), noncollidibles=LayeredDirty( Text(Point(805, 70), 'Par 4', font.Font(None, 30), colors.WHITE)), collidibles=LayeredDirty( Green([ Point(50, 500, 0), Point(450, 500, 0), Point(450, 700, 0), Point(50, 700, 0) ]), Slope([ Point(200, 500, 0), Point(300, 500, 0), Point(300, 325, 0), Point(200, 325, 0) ], Color(125, 0, 0, 255), Vector2(0.0, -0.1)), Rough([ Point(200, 325, 0), Point(200, 200, 0),
import pygame, sys, os, time from pygame.locals import * from pygame import font from pygame.sprite import DirtySprite, LayeredDirty pygame.init() global allFont allFont = font.SysFont("monospace",11) # set up the window global MAINWINDOW MAINWINDOW = pygame.display.set_mode((1200, 1000), 0, 32) pygame.display.set_caption('Character Generator') global fullWindowGroup fullWindowGroup = LayeredDirty() global groupList groupList = [] groupList.append(fullWindowGroup) def drawSquare(xposition,yposition,length,color): pygame.draw.rect(MAINWINDOW, color, (xposition,yposition,length,length)) def drawRect(rect,color): r = pygame.draw.rect(MAINWINDOW, color, rect) return r #groups def addGroup(): newGroup = LayeredDirty() groupList.append(newGroup) def drawGroup(group): dirty = group.draw(MAINWINDOW) pygame.display.update(dirty) def drawAllGroups(): for g in groupList: drawGroup(g)
from pygame import Color, font from pygame.math import Vector2 from pygame.sprite import LayeredDirty from src.models import Hole as BaseHole from src.sprites import * from src.utils import colors, Point Hole = BaseHole( 'Hole #6', par=3, origin=Point(150, 100, 0), ball=Point(200, 630, 0), noncollidibles=LayeredDirty( Text(Point(88, 92), 'Par 3', font.Font(None, 30), colors.WHITE)), collidibles=LayeredDirty( Water([ Point(150, 150, 0), Point(150, 550, 0), Point(550, 550, 0), Point(550, 150, 0) ]), Green([ Point(150, 550, 0), Point(550, 550, 0), Point(550, 700, 0), Point(150, 700, 0) ]), Green([ Point(150, 150, 0), Point(150, 50, 0),
def init(cls): cls.objects = LayeredDirty() cls.selected_objects = []
from pygame import Color, font from pygame.math import Vector2 from pygame.sprite import LayeredDirty from src.models import Hole as BaseHole from src.sprites import * from src.utils import colors, Point Hole = BaseHole( 'Hole #8', par=2, origin=Point(50, 50, 0), ball=Point(145, 520, 0), noncollidibles=LayeredDirty( Text(Point(708, 20), 'Par 2', font.Font(None, 30), colors.WHITE), Text(Point(925, 310), 'Is this lava?', font.Font(None, 24), colors.WHITE) ), collidibles=LayeredDirty( Green([Point(50, 50, 0), Point(50, 580, 0), Point(250, 580, 0), Point(250, 200, 0), Point(650, 200, 0), Point(650, 50, 0)]), Rough([Point(650, 50, 0), Point(800, 50, 0), Point(800, 200, 0), Point(650, 200, 0)]), Lava([Point(250, 580, 0), Point(250, 200, 0), Point(800, 200, 0), Point(800, 50, 0), Point(900, 50, 0), Point(900, 580, 0)]), Pin(Point(730, 125, 0)), Money(Point(225, 175)), Wall(Point(50, 50, 0), Point(900, 50, 0), 5), Wall(Point(900, 50, 0), Point(900, 580, 0), 5), Wall(Point(900, 580, 0), Point(50, 580, 0), 5), Wall(Point(50, 580, 0), Point(50, 50, 0), 5) ) )
class Scene: ''' Describe a Scene in a game. This is a base class for every scene in the game, has a main_loop that can be called from the main process and the functions start and update to controll the first and sucesives ticks respectively. ''' def __init__(self, screen: Surface): ''' Constructor of the class, takes the screen to gain control over the render of the game objects ''' # Get display info info = Info() # Get Clock to ensure frame rating self.clock = Clock() # The default return value of the Scene self.return_value = -1 # Set the continue condition self.running = True # Get the relevant information from info self.screen_h, self.screen_w = info.current_h, info.current_w # Set the screen of the Scene self.screen: Surface = screen # Main Sprite groups self.event_group = Group() self.update_group = Group() self.render_group = LayeredDirty() def start(self): ''' This function will is the first function called when the scene starts running, here you can configure the position and starting behaviour of your scene ''' pass def update(self): ''' This function will be called every tick of the game and needs to be overrided in every scene to fill the desired behaviour ''' pass def clear(self): ''' This function will be called on the end of the scene to clean any configuration or variables to the next scene. It will raise NotImplementedError if it's not implemented, at least needs a pass function if no work is needed ''' raise NotImplementedError def exit(self, return_value): ''' This function will end the scene and return the value to the parent ''' self.running = False self.return_value = return_value self.event_group.empty() self.update_group.empty() self.render_group.empty() self.clear() def main_loop(self): ''' This is the main loop of the scene, don't overrive if not necesary. Here you will find the main workflow for an scene ''' # Ensures the starts conditions self.running = True self.return_value = -1 # Calls the start function, to configurate the scene self.start() # Main loop of the scene while self.running: # Event catch # Set the event queue of the objet itself self.events = [] for e in event.get(): self.events.append(e) for s in self.event_group.sprites(): s.add_event(e) if e.type == QUIT: self.exit(-1) # Group update self.update_group.update(self.clock.get_time()) # Calls the update function for every tick of the game self.update() # Render group self.render_group.draw(self.screen) display.flip() # Ensure frame rate if DEBUG: print(self.clock.get_fps()) self.clock.tick(60) return self.return_value
from pygame import Color, font from pygame.math import Vector2 from pygame.sprite import LayeredDirty from src.models import Hole as BaseHole from src.sprites import * from src.utils import colors, Point Hole = BaseHole('Hole #5', par=4, origin=Point(50, 100, 0), ball=Point(490, 550, 0), noncollidibles=LayeredDirty( Text(Point(670, 138), 'Par 4', font.Font(None, 30), colors.WHITE), ), collidibles=LayeredDirty( Green([ Point(440, 100, 0), Point(540, 100, 0), Point(540, 200, 0), Point(440, 200, 0) ]), Slope([ Point(440, 100, 0), Point(380, 50, 0), Point(600, 50, 0), Point(540, 100, 0) ], Color(100, 0, 0, 255), Vector2(0.0, -0.4)), Slope([ Point(600, 50, 0), Point(540, 100, 0),
from pygame import Color, font from pygame.math import Vector2 from pygame.sprite import LayeredDirty from src.models import Hole as BaseHole from src.sprites import * from src.utils import colors, Point Hole = BaseHole('Hole #1', par=1, origin=Point(50, 50, 0), ball=Point(535, 545, 0), noncollidibles=LayeredDirty( Text(Point(515, 160), 'Par 1', font.Font(None, 30), colors.WHITE), ), collidibles=LayeredDirty( Green([ Point(360, 190, 0), Point(700, 190, 0), Point(700, 600, 0), Point(360, 600, 0) ]), Pin(Point(535, 260, 0)), Money(Point(529, 215)), Wall(Point(360, 190, 0), Point(700, 190, 0), 5), Wall(Point(700, 190, 0), Point(700, 600, 0), 5), Wall(Point(700, 600, 0), Point(360, 600, 0), 5), Wall(Point(360, 600, 0), Point(360, 190, 0), 5)))
def applyColour(self, colour): """Very simple colour substitution""" for x in range(0, self.rect.width): for y in range(0, self.rect.height): pixel = self.image.get_at((x, y)).r if pixel > 50: self.image.set_at((x, y), colour) # create sprites bg = PpuiImage("assets/lcars_screen_1.png") button = PpuiImage("assets/button.png") button.applyColour((255, 204, 153)) # add sprites to layer sprites = LayeredDirty() sprites.add(bg) sprites.add(button) # event loop while pygame.display.get_init(): sprites.draw(screenSurface) pygame.display.update() for event in pygame.event.get(): if event.type == KEYUP: pygame.quit() break if event.type == MOUSEMOTION: # move button around as mouse moves (or touch-drag)
from pygame import Color, font from pygame.math import Vector2 from pygame.sprite import LayeredDirty from src.models import Hole as BaseHole from src.sprites import * from src.utils import colors, Point Hole = BaseHole( 'Hole #9', par=3, origin=Point(150, 50, 0), ball=Point(505, 450, 0), noncollidibles=LayeredDirty( Text(Point(590, 143), 'Par 3', font.Font(None, 30), colors.WHITE), ), collidibles=LayeredDirty( Green([Point(450, 100, 0), Point(560, 100, 0), Point(560, 200, 0), Point(450, 200, 0)]), Lava([Point(450, 200, 0), Point(440, 200, 0), Point(440, 90, 0), Point(450, 90, 0)]), Lava([Point(450, 100, 0), Point(450, 90, 0), Point(570, 90, 0), Point(570, 100, 0)]), Lava([Point(560, 100, 0), Point(560, 210, 0), Point(570, 210, 0), Point(570, 100, 0)]), Lava([Point(560, 210, 0), Point(440, 210, 0), Point(440, 200, 0), Point(560, 200, 0)]), Green([Point(440, 210, 0), Point(440, 510, 0), Point(570, 510, 0), Point(570, 210, 0)]), Slope([Point(570, 510, 0), Point(570, 360, 0), Point(620, 360, 0), Point(620, 510, 0)], Color(200, 0, 0, 255), Vector2(0.33, 0.0)), Green([Point(620, 360, 0), Point(750, 510, 0), Point(620, 510, 0)]), Slope([Point(620, 510, 0), Point(620, 560, 0), Point(750, 560, 0), Point(750, 510, 0)], Color(200, 0, 0, 255), Vector2(0.0, 0.4)), Green([Point(620, 560, 0), Point(620, 700, 0), Point(750, 560, 0)]), Slope([Point(620, 560, 0), Point(570, 560, 0), Point(570, 700, 0), Point(620, 700, 0)], Color(200, 0, 0, 255), Vector2(-0.5, 0.0)), Green([Point(340, 560, 0), Point(340, 620, 0), Point(570, 620, 0), Point(570, 560, 0)]), Rough([Point(570, 700, 0), Point(570, 620, 0), Point(340, 620, 0), Point(340, 700, 0)]),
def __init__(self, console=None): self.console = console self.players = [] # players on the field self.objects = [] # objects on the field self.deleted = [] # object to delete LayeredDirty.__init__(self, _update=True, _time_threshold=1000.0/FPS) self.game_over = False self.screen = pygame.display.get_surface() self.lockfps = FPS self.clock = pygame.time.Clock() self.bg = load_texture("Misc/backdrop.png") self.ice = load_texture("Misc/ice.png", True) self.ice_mask = pygame.mask.from_surface(self.ice) self.ice_rects = [pygame.Rect(FLIMIT_WIDTH[0], FLIMIT_HEIGHT[0], FLIMIT_WIDTH[1]-FLIMIT_WIDTH[0], FLIMIT_HEIGHT[1]-FLIMIT_HEIGHT[0]), self.ice_mask.get_bounding_rects()[0]] self.ice_gap_rect = pygame.Rect(270, 0, 66, 175) if 'field' in option('debug'): debug("FIELD: ice rects: %s"%self.ice_rects) self.start = pygame.Surface((640,480)) self.start.blit(self.bg, (0, 0)) self.start.blit(self.ice, (0, ICE_YOFFSET)) self.field = self.start.copy() self.ticks = 0 # total ticks field played self.screen.blit(self.field, (0,0)) # System font, for messages and FPS self.sfont = load_font("default.ttf", 14) # FPS drawer if needed if "fps" in option("show"): self.fps = pygame.sprite.GroupSingle() self.fps.add(pygame.sprite.DirtySprite()) # self.fpsprite = pygame.sprite.DirtySprite() self.update_fpsprite() # show FPS rate on top of everything self.add(self.fps, layer=TOP_LAYER) # Messages self.messages = [] self.show_messages = [] self.msgs = pygame.sprite.DirtySprite() self.msgs.visible = 0 self.msgs_offset = 0 self.msgs_linesize = self.sfont.get_linesize() _ssh = self.msgs_linesize * option("max-messages") sprite_image(self.msgs, pygame.Surface((640, _ssh))) sprite_move(self.msgs, 0, 71) self.add(self.msgs, layer=0) # Sprite for level's progress self.lp_font = load_font('trebuc.ttf', 14) self.lp_font.set_bold(True) self.level_prgrs = pygame.sprite.DirtySprite() sprite_image(self.level_prgrs, pygame.Surface((640, 20))) sprite_move(self.level_prgrs, 0, 0) self.level_prgrs.image.blit(self.bg, (0,0), self.level_prgrs.rect) self.add(self.level_prgrs, layer=TOP_LAYER)
def remove(self, *args): """Remove object O from field's object list.""" LayeredDirty.remove(self, *args) # Mark as deleted, so object will be deleted on next tick self.deleted.extend(args)
class Screen(object): def __init__(self, name): State.name = name State.screen = self State.controls = State.screens[State.name]['controls'] State.groups = util.GroupCache() self.layers = LayeredDirty() self.add_all() State.save(State.name) def new_game(self): self.switch('world') def quit(self): if State.name == 'title': State.running = False else: self.switch(State.prev_name) def menu_up(self): pass def menu_down(self): pass def add_all(self): """Add all the objects specified in the screen's configuration resource to their proper sprite groups for rendering.""" for obj in State.screens[State.name]['objects']: self.add_object(obj) def add_object(self, name, group=None, pos=None): """Add a game object resource to the screen. name: the name of the game object. pos: object will be placed on this tile.""" # Get object data from given name data = State.objects[name] # If group is not set, use object's default group. if not group: group = data['group'] # Creates a game object from the name of its group, and adds it to # the group. sprite = eval(group.capitalize())(data) State.groups[group].add(sprite) # Set the object's starting tile. if pos: data['pos'] = sprite.set_pos(data, pos) # If an object is a player, tell the state so it can be controlled. # TODO: Make State.player a list of sprites. if sprite in State.groups['player']: State.player = sprite # Add the sprite groups to the rendering queue. self.layers.add(State.groups[group]) return sprite def draw(self): """Run the update method of every sprite, keeping track of which ones are dirty and need updating, and then finally updating only the dirty areas.""" self.layers.update() State.dirty = self.layers.draw(State.window) display.update(State.dirty) def switch(self, name): """Switch to a new screen by saving the current state, and then restoring the specified state.""" State.save(State.name) State.prev_name = State.name State.restore(name) def restore(self): """Called when a screen is restored from a saved state.""" State.pressed = [] for group in State.groups: for sprite in State.groups[group]: sprite.dirty = 1 sprite.stopped = True