class TheEnd(State): def __init__(self): State.__init__(self) self.bg_image = GLOBALS["backgrounds"]["the_end.png"] self.overlay = StaticWidget((638, 169)) self.overlay.set_pos((2, 160)) self.overlay.set_alpha(255) self.overlay.fill((0, 0, 0)) self.wait = Timer(50) def main_start(self): pygame.mouse.set_visible(0) GLOBALS["jb"].stop() def update_screen(self): self.background.fill((0, 0, 0)) self.background.blit(self.bg_image, (0, 0)) if not self.wait.active: alpha = self.overlay.get_alpha() if alpha > 0: self.overlay.set_alpha(alpha - 10) if alpha < 20: self.add_kbevent(KEYDOWN, K_ESCAPE, self.quit) elif self.wait.update(): self.wait.deactivate() self.overlay.draw(self.background) State.update_screen(self)
class FadeState(State): def __init__(self, old_screen, new_screen, next_state): State.__init__(self) self.fps = 30 self.background.blit(old_screen, (0, 0)) self.new_screen = pygame.Surface(new_screen.get_size()) self.new_screen.blit(new_screen, (0, 0)) self.new_screen.set_alpha(0) self.alpha_add = 1 self.alpha_max = 100 self.blend_timer = Timer(2) self.next = next_state def update_other(self): if not self.blend_timer.update(): return alpha = self.new_screen.get_alpha() + self.alpha_add if self.alpha_add < 15: self.alpha_add += 1 self.new_screen.set_alpha(alpha) self.background.blit(self.new_screen, (0, 0)) if alpha > self.alpha_max: self.quit()
class Vortex(Kitten): def __init__(self, centerpos): img = GLOBALS["ui_stuff"]["vortex.png"] Kitten.__init__(self, img) self.angle = 0 self.angle_add = 10 self.image_copy = img.copy() self.centerpos = centerpos self.rect.centerx = centerpos[0] self.rect.top = centerpos[1] self.set_pos(self.rect.topleft) self.center_diff = 1 self.center_diff_timer = Timer(5) def update(self): center = self.rect.center self.angle += self.angle_add if self.angle > 360: self.angle = self.angle - 360 self.image = pygame.transform.rotate(self.image_copy, self.angle) self.rect.size = self.image.get_size() self.rect.center = center if self.center_diff_timer.update(): #small movement around center self.rect.centerx = center[0] + self.center_diff self.rect.centery = center[1] + self.center_diff self.center_diff *= -1 self.set_pos(self.rect.topleft) Kitten.update(self)
class Fizzle(StaticWidget): def __init__(self, images, delay=5): size = images[0].get_size() StaticWidget.__init__(self, size) self.images = images self.bg = pygame.Surface(size) self.delay = delay self.nr = 0 self.timer = Timer(delay) self.active = 0 self.flip() def update(self): if self.active and self.timer.update(): self.flip() return True return False def set_bg(self, img): self.bg = img self.blit(self.bg, (0,0)) if self.active: self.blit(self.images[self.nr], (0,0)) def flip(self): self.blit(self.bg, (0,0)) self.blit(self.images[self.nr], (0,0)) self.nr += 1 if self.nr >= len(self.images): self.nr = 0
class Outro(State): def __init__(self): State.__init__(self) self.fps = 40 #animation checkpoints and flags self.opening = 0 self.closing = 0 self.door_timer = Timer(15) #open slowly, then faster self.maelstrom_timer = Timer(30) #open doors a bit.. then pull self.nanji_command = None #generate pseudo-map screen_size = GLOBALS["screen_size"] self.bg_image = pygame.Surface(screen_size) self.top_layer = pygame.Surface(screen_size) self.top_layer.set_colorkey((255, 0, 255)) self.top_layer.fill((255, 0, 255)) #draw map background bg = GLOBALS["backgrounds"]["fuji.png"] self.bg_image.blit(bg, (0, 0)) #draw grass tsize = GLOBALS["tile_size"] grass_tile = GLOBALS["ts_tileset"][1, 0] x = -tsize y = screen_size[1] - tsize for i in xrange(22): self.top_layer.blit(grass_tile, (x, y)) x += tsize #draw mysterious myst = GLOBALS["ui_stuff"]["mysterious.png"] #draw full signet board on mysterious board = GLOBALS["ui_stuff"]["board_filled.png"] x, y = 66, 197 myst.blit(board, (x, y)) x = 5 * tsize y = screen_size[1] - myst.get_size()[1] - tsize self.myst = StaticWidget(myst.get_size()) self.myst.set_colorkey((255, 0, 255)) self.myst.fill((255, 0, 255)) self.myst.blit(myst, (0, 0)) self.myst.set_pos((x, y)) self.myst.pos = (x, y) self.myst.draw(self.top_layer) myst_centerx = x + myst.get_size()[0] / 2 myst_top = y + 30 #init doors self.door_speed = 1 door_left_image = GLOBALS["ui_stuff"]["door_left.png"] door_right_image = GLOBALS["ui_stuff"]["door_right.png"] self.door_left = StaticWidget(door_left_image.get_size()) self.door_left.blit(door_left_image, (0, 0)) self.door_left.set_pos((self.myst.pos[0] + 99, self.myst.pos[1] + 63)) self.door_right = StaticWidget(door_right_image.get_size()) self.door_right.blit(door_right_image, (0, 0)) self.door_right.set_pos( (self.myst.pos[0] + 177, self.myst.pos[1] + 63)) #init whirling vortex self.vortex = Vortex(centerpos=(myst_centerx, myst_top)) #init Nanji self.nanji = Nanji(cam=None) self.nanji.status = 0 self.nanji.set_pos((205, 401)) self.nanji_angle = 0 self.nanji_fly_img = self.nanji.all_images["landing"][0] self.nanji_shrink = 1 self.sprites.add(self.nanji) self.nanji_do("throw") def main_start(self): pygame.mouse.set_visible(0) State.main_start(self) def update_doors(self): if self.opening: lx, ly = self.door_left.get_pos() rx, ry = self.door_right.get_pos() self.door_left.set_pos((lx - self.door_speed, ly)) self.door_right.set_pos((rx + self.door_speed, ry)) if self.door_timer.update(): self.door_speed = 2 self.opening = lx > 165 elif self.closing: self.door_speed = 1 lx, ly = self.door_left.get_pos() rx, ry = self.door_right.get_pos() self.door_left.set_pos((lx + 1, ly)) self.door_right.set_pos((rx - 1, ry)) self.closing = lx < 258 if not self.closing: self.maelstrom_timer.set_interval(50) self.nanji_do("waitquit") self.door_left.draw(self.background) self.door_right.draw(self.background) def nanji_do(self, do="throw"): self.nanji_command = do if do == "throw": #lift paw self.nanji.change_images("throwing") self.nanji.anim_timer.set_interval(5) self.nanji.play() elif do == "unthrow": #put paw down images = self.nanji.images[:] images.reverse() self.nanji.set_images(images) self.nanji.play() elif do == "wait_door": self.nanji.change_images("idle") self.opening = 1 self.nanji.pause() elif do == "walk" or do == "walk2": self.nanji.look = -1 self.nanji.change_images("walking") self.nanji.anim_timer.set_interval(8) self.nanji.play() elif do == "sprint" or do == "sprint2": self.nanji.change_images("sprinting") self.nanji.anim_timer.set_interval(8) self.nanji.play() elif do == "duck": self.nanji.change_images("ducking") self.nanji.pause() elif do == "lift": self.nanji.change_images("landing") self.nanji.pause() def update_nanji(self): if self.nanji_command is None: return #update old command cmd = self.nanji_command x, y = self.nanji.pos #get pulled if cmd == "throw" and self.nanji.cur_image >= 3: #paw up self.nanji_do("unthrow") elif cmd == "unthrow" and self.nanji.cur_image >= 3: #paw down self.nanji_do("wait_door") elif cmd == "wait_door" and self.maelstrom_timer.update(): #wait self.nanji_do("walk") elif cmd == "walk": if x > 150: #walk left self.nanji.set_pos((x - 1, y)) else: self.nanji_do("walk2") elif cmd == "walk2": if x < 190: self.nanji.set_pos((x + 1, y)) else: self.nanji_do("sprint") elif cmd == "sprint": #try to sprint if x > 170: self.nanji.set_pos((x - 1, y)) else: self.nanji_do("sprint2") elif cmd == "sprint2": self.nanji.set_pos((x + 1, y)) if self.maelstrom_timer.update(): self.nanji_do("duck") elif cmd == "duck" and self.maelstrom_timer.update(): self.nanji_do("duckpull") elif cmd == "duckpull": if x < 250: self.nanji.set_pos((x + 1, y)) else: self.nanji_do("lift") elif cmd == "lift": if x < 280: self.nanji.set_pos((x + 1, y)) else: self.nanji_do("liftoff") self.maelstrom_timer.set_interval(10) elif cmd == "liftoff": self.nanji.set_pos((x, y - 1)) if self.maelstrom_timer.update(): self.nanji_do("whirl") elif cmd == "whirl": img = self.nanji_fly_img.copy() sx, sy = img.get_size() img = pygame.transform.scale( img, (sx - self.nanji_shrink, sy - self.nanji_shrink)) self.nanji_shrink += 1 if sx - self.nanji_shrink < 0 or sy - self.nanji_shrink < 0: self.nanji_do("done") self.nanji_angle += 10 if self.nanji_angle > 360: self.nanji_angle = self.nanji_angle - 360 img = pygame.transform.rotate(img, self.nanji_angle) center = self.nanji.rect.center self.nanji.set_image(img) self.nanji.rect.center = center if y > 350: y -= 1 if x < 350: x += 1 self.nanji.set_pos((x, y)) elif cmd == "done": self.nanji_do(None) self.closing = 1 elif cmd == "waitquit" and self.maelstrom_timer.update(): self.next = TheEnd() self.quit() def update_screen(self): self.background.blit(self.bg_image, (0, 0)) #update and draw vortex self.vortex.update() self.background.blit(self.vortex.image, self.vortex.pos) #update and draw doors self.update_doors() #draw grass, building self.background.blit(self.top_layer, (0, 0)) #draw nanji self.update_nanji() State.update_screen(self)
class Level(State): def __init__(self, lvl_map="tutorial.map", testing=False, prev=None): State.__init__(self) self.fps = 60 self.prev = prev tsize = GLOBALS["tile_size"] self.trigger = None self.exit_timer = Timer(50) self.exit_timer.deactivate() pygame.mixer.music.set_volume(1) GLOBALS["jb"].play("bgm.xm", -1) player_data["health"] = 9 #always full health on map start #player_data["lives"] = #for gameover testing #scrolling background - maybe later XD #bg_back = GLOBALS["backgrounds"]["fuji.png"] #bg_front = GLOBALS["backgrounds"]["trees.png"] #self.scroll_bg = Background(bg_back, bg_front) #non-scrolling background self.bg = GLOBALS["backgrounds"]["fuji.png"] #map self.map_filename = lvl_map self.map = Map(lvl_map) self.lvl_map = self.map["tilemap"] x, y = self.map["max"] self.lvl_img, self.blocks = self.map.draw(editing=False) self.lvl_layer = pygame.Surface(self.lvl_img.get_size()) #other spritegroups self.bullets = pygame.sprite.Group() #player self.player = Nanji(None) self.player.set_pos((self.map["start"][0]*tsize, self.map["start"][1]*tsize)) self.sprites.add(self.player) #camera self.camera = Camera(self.player) screen_x, screen_y = GLOBALS["screen_size"] mx = self.map["max"][0] * tsize - screen_x my = self.map["max"][1] * tsize - screen_y + 4*tsize self.camera.set_max(mx,my) self.player.camera = self.camera self.camera.update() #add enemies self.enemies = pygame.sprite.Group() clan = self.map["options"]["clan"] for e in self.map.enemies: ninjat = Ninjat(self.camera, clan) ninjat.set_pos((e[0]*tsize, e[1]*tsize-32))#FIXME:enemies are spawned too low..? self.enemies.add(ninjat) self.sprites.add(ninjat) #ui layer self.ui_layer = StaticWidget((GLOBALS["screen_size"][0], 30)) self.ui_layer.fill((255,0,255)) self.ui_layer.set_colorkey((255,0,255)) self.ui_layer.set_pos((0,0)) self.heart_img = GLOBALS["ui_stuff"]["heart"] self.heart_empty_img = GLOBALS["ui_stuff"]["heart_empty"] self.life_img = GLOBALS["ui_stuff"]["life"] self.fontholder = TextLine("", fontsize=16) self.update_ui() #keyboard events self.key_pressed = { "up": 0, "down": 0, "left": 0, "right": 0, "jump":0, "sprint":0, "throw": 0, "shuriken": 0, } self.add_kbevent(KEYDOWN, K_LEFT, self.set_keypress, k="left", v=1) #move self.add_kbevent(KEYDOWN, K_RIGHT, self.set_keypress, k="right", v=1) self.add_kbevent(KEYDOWN, K_UP, self.set_keypress, k="up", v=1) self.add_kbevent(KEYDOWN, K_DOWN, self.set_keypress, k="down", v=1) self.add_kbevent(KEYDOWN, K_SPACE, self.set_keypress, k="jump", v=1) #jump self.add_kbevent(KEYDOWN, K_LSHIFT, self.set_keypress, k="sprint", v=1) #sprint self.add_kbevent(KEYDOWN, K_RSHIFT, self.set_keypress, k="sprint", v=1) self.add_kbevent(KEYDOWN, K_RCTRL, self.set_keypress, k="throw", v=1) #throw self.add_kbevent(KEYDOWN, K_LCTRL, self.set_keypress, k="throw", v=1) self.add_kbevent(KEYUP, K_LEFT, self.set_keypress, k="left", v=0) self.add_kbevent(KEYUP, K_RIGHT, self.set_keypress, k="right", v=0) self.add_kbevent(KEYUP, K_UP, self.set_keypress, k="up", v=0) self.add_kbevent(KEYUP, K_DOWN, self.set_keypress, k="down", v=0) self.add_kbevent(KEYUP, K_SPACE, self.set_keypress, k="jump", v=0) self.add_kbevent(KEYUP, K_LSHIFT, self.set_keypress, k="sprint", v=0) self.add_kbevent(KEYUP, K_RSHIFT, self.set_keypress, k="sprint", v=0) self.add_kbevent(KEYUP, K_RCTRL, self.set_keypress, k="throw", v=0) self.add_kbevent(KEYUP, K_LCTRL, self.set_keypress, k="throw", v=0) if testing: self.add_kbevent(KEYUP, K_ESCAPE, self.quit) def main_start(self): pygame.mouse.set_visible(0) State.main_start(self) def reset_keys(self): self.key_pressed = { "up": 0, "down": 0, "left": 0, "right": 0, "jump":0, "sprint":0, "throw": 0, "shuriken": 0, } def update_other(self): if self.player.exiting: self.show_exit_anim() return kp = self.key_pressed vx = 0 if kp["left"] and not kp["right"]: vx = -1 if kp["right"] and not kp["left"]: vx = 1 self.player.mod_vel(vx=vx) if kp["jump"]: self.player.jump() elif self.player.status==4: self.player.unjump() if kp["sprint"]: self.player.sprint() #self.scroll_bg.front_speed = 8 elif self.player.status==2: self.player.unsprint() #self.scroll_bg.front_speed = 4 if kp["down"]: self.player.duck() elif self.player.status==7: self.player.unduck() if kp["throw"]: kp["throw"] = 0 if self.player.throw(): self.bullets.add(Shuriken(self.player, self.camera)) def set_keypress(self, k, v): self.key_pressed[k] = v def show_exit_anim(self): self.fps = 30 self.reset_keys() if self.player.exiting == -1: self.player.set_vel((0,0)) self.player.set_image(GLOBALS["nanji"]["idle"][0]) if not self.exit_timer.active: self.exit_timer.activate() elif self.player.vel[1]: self.player.status = 5 else: self.player.status = 1 self.player.mod_vel(vx=1) if self.player.pos[0] > self.map["exit"][0]*tsize+10*tsize or \ self.exit_timer.update(): #TODO: play some funky tune / do SOMETHING on level exit if self.prev: self.prev.success = True self.quit() def show_dialog(self, dialog_id): self.pause() self.next = ShowDialog(dialog_id, self.screen) self.quit() def unpause(self): self.reset_keys() State.unpause(self) def check_collisions(self): #check bullet collisions b = self.bullets s = self.enemies bl = self.blocks #test if bullet hit player coll = pygame.sprite.spritecollide(self.player, self.bullets, False) for bullet in coll: if bullet.thrower is not self.player and bullet.flying and not \ self.player.invincible: bullet.kill() self.player.get_hit() self.rem_health() #test if bullet hit wall dead = [] for bullet in self.bullets: if bullet.rect.collidelist(bl) > -1: dead.append(bullet) for d in dead: if d.flying: d.kill() #test if bullet hit enemy (ninjats can't shoot each other) coll = pygame.sprite.groupcollide(s, b, False, False) for victim in coll.keys(): #my code gets weird... for murderer in coll[victim]: if murderer.thrower is self.player: victim.die() murderer.kill() #test player vs. enemy collisions coll = pygame.sprite.spritecollide(self.player, s, False) pbottom = self.player.rect.bottom for enemy in coll: if enemy.status == 8: #enemy dead.. ignore! continue etop = enemy.rect.top if self.player.status==5 and pbottom >= etop: #enemy below player and player is falling -> enemy crushed! enemy.die() self.player.bounce() elif not self.player.invincible and not self.player.status==7: #not ducking -> get hit self.player.get_hit() self.rem_health() def rem_health(self): player_data["health"] -= 1 GLOBALS["sfx"][sfx_hit].play() if player_data["health"] <= 0: self.player.die() self.update_ui() def update_ui(self): self.ui_layer.fill((255,0,255)) #health x, y, add = 4, 2, self.heart_img.get_size()[0] + 2 for i in xrange(9): if i < player_data["health"]: #TODO: if i < hp self.ui_layer.blit(self.heart_img, (x,y)) else: self.ui_layer.blit(self.heart_empty_img, (x,y)) x += add #lives x, y, add = 595, 2, self.life_img.get_size()[0] + 2 self.ui_layer.blit(self.life_img, (x,y)) lives = player_data["lives"] life_text = self.fontholder.font.render("x"+str(lives), False, (255,255,255)) self.ui_layer.blit(life_text, (x+add, y+10)) def update_screen(self): for s in self.sprites: s.update_status() if not s.ai: #update player s.update() if not s.status==8 and not self.player.off_screen(): s.check_mapcollisions(self.blocks) trig = s.check_trigcollisions(self.map.triggers) if trig: if trig.name=="exit": self.player.exiting = 1 elif trig.name=="dtrigger": self.show_dialog(trig.params) if trig.params=="tut08": self.player.exiting = -1 self.player.set_image(GLOBALS["nanji"]["idle"][0]) else: player_data["health"] = 9 player_data["lives"] -= 1 if player_data["lives"] > 0: next = Level(self.map_filename, prev=self.prev) else: next = GameOver() self.next = FadeState(self.screen, next.background, next) self.quit() else: #update ai if s.ai_update(self): #throw shuriken? self.bullets.add(Shuriken(s, self.camera)) self.bullets.update() self.camera.update() #draw bg #self.scroll_bg.update(self.player.vel[0]) self.background.blit(self.bg, (0,0)) #draw map and sprites self.lvl_layer.fill((255,0,255)) self.lvl_layer.blit(self.lvl_img, self.camera.pos, [self.camera.pos, GLOBALS["screen_size"]]) self.lvl_layer.set_colorkey((255,0,255)) self.bullets.draw(self.lvl_layer) self.sprites.draw(self.lvl_layer) #pygame.draw.rect(self.lvl_layer, (255,255,0), self.player.colrect, 1) #draw collision rect of nanji if self.player.exiting: #draw semi-black image over dojo entry while entering self.lvl_layer.blit(GLOBALS["objects"]["dojo_entry"], self.map.dojo_pos) self.background.blit(self.lvl_layer, (0,0), [self.camera.pos, GLOBALS["screen_size"]]) self.ui_layer.draw(self.background) self.screen.blit(self.background, (0,0)) pygame.display.flip()
class LevelSelection(State): def __init__(self, new=True): State.__init__(self) self.success = False self.new = new #start tutorial before showing level selection! self.signet_pos = { "wood": (83, 181), "day": (158, 75), "fire": (284, 34), "life": (410, 75), "earth": (485, 181), "night": (456, 307), "metal": (348, 368), "water": (220, 368), "death": (112, 307) } self.light_pos = { "wood": (239, 225), "day": (261, 173), "fire": (315, 155), "life": (369, 173), "earth": (391, 225), "night": (383, 271), "metal": (345, 307), "water": (285, 307), "death": (247, 271) } self.cur_blinking = None self.cur_blending = None self.cur_clan = None self.blink_timer = Timer(50) self.blink_count = 0 self.blink_max = 10 self.light = GLOBALS["ui_stuff"]["green_light"] r = pygame.Rect([281, 203, 78, 77]) r.inflate(-10, -10) bigredbutton = ClickArea(r, self.bigred_pressed) self.widgets.append(bigredbutton) self.donotpress = pygame.Rect([267, 188, 106, 95]) self.signets = GLOBALS["signets"] self.bg_image = GLOBALS["backgrounds"]["gameboard.png"].copy() self.ui_layer = pygame.Surface(GLOBALS["screen_size"]) self.ui_layer.fill((255, 0, 255)) self.ui_layer.set_colorkey((255, 0, 255)) self.tooltip_layer = pygame.Surface(GLOBALS["screen_size"]) self.tooltip_layer.fill((255, 0, 255)) self.tooltip_layer.set_colorkey((255, 0, 255)) self.tooltip = StaticWidget((80, 20)) self.dnp_tooltip = GLOBALS["ui_stuff"]["donotpress"] #level selection buttons self.signet_buttons = [] levels = GLOBALS["clan_levels"] for k in self.signet_pos.keys(): if self.signets.has_key(k) and levels.has_key(k): btn = ImgButton(self.signets[k][0], self.start_level, \ clan=k, level=levels[k]) btn.set_pos(self.signet_pos[k]) btn.rect = pygame.Rect([self.signet_pos[k], btn.get_size()]) btn.rect.inflate(-20, -20) btn.clan = k self.widgets.append(btn) self.signet_buttons.append(btn) #show savegame progress self.show_signet(player_data["unlocked"]) #keyboard events self.add_kbevent(KEYDOWN, K_ESCAPE, self.quit) self.background.blit(self.bg_image, (0, 0)) self.background.blit(self.tooltip_layer, (0, 0)) self.background.blit(self.ui_layer, (0, 0)) self.tooltip_layer.fill((255, 0, 255)) def main_start(self): if pygame.mixer.music.get_busy(): pygame.mixer.music.fadeout(300) pygame.mouse.set_visible(1) if self.new is True: self.new = "somewhere in between" self.cur_clan = None self.next = Level("tutorial.map", prev=self) self.pause() self.quit() elif self.new == "somewhere in between": self.new = False self.update_screen() self.next = ShowDialog("donotpress", self.screen) self.pause() self.quit() def start_level(self, clan, level): if clan in player_data[ "unlocked"] or self.cur_blending or self.cur_blinking: #do not start finished maps and wait while blending new signet in return self.success = False self.cur_clan = clan self.next = Level(level, prev=self) self.pause() self.quit() def unpause(self): if self.success: if self.cur_clan: self.show_signet([self.cur_clan]) player_data["unlocked"].append(self.cur_clan) #track progress self.cur_clan = None self.autosave() #save progress State.unpause(self) def autosave(self): try: save_object(player_data, "save.dat") except: print "Autosave failed. Uh.. guess you need to keep playing?" def show_signet(self, clans): #show recently gained signet(s) self.cur_blending = [] self.cur_blinking = [] for clan in clans: #signet signet = self.signets[clan][0] blend = StaticWidget(signet.get_size()) blend.fill((255, 0, 255)) blend.set_colorkey((255, 0, 255)) blend.blit(signet, (0, 0)) blend.set_pos(self.signet_pos[clan]) blend.set_alpha(0) self.cur_blending.append(blend) #green light img = self.light blink = StaticWidget(img.get_size()) blink.fill((255, 0, 255)) blink.set_colorkey((255, 0, 255)) blink.blit(img, (0, 0)) blink.set_pos(self.light_pos[clan]) self.cur_blinking.append(blink) self.blink_timer.set_interval(3) def update_other(self): if self.cur_blending: #fancy alpha blending effect for new signet alpha = self.cur_blending[0].get_alpha() + 5 if alpha > 100: #stop blending for blend in self.cur_blending: blend.set_alpha(None) blend.draw(self.bg_image) self.cur_blending = None else: #keep blending for blend in self.cur_blending: blend.set_alpha(alpha) blend.draw(self.bg_image) elif self.cur_blinking: if not self.blink_timer.update(): return #fancy blinking light o/ self.blink_count += 1 b = self.blink_count #simulate irregular flickering if b == 1: self.blink_timer.set_interval(2) elif b == 3: self.blink_timer.set_interval(3) elif b == 6: self.blink_timer.set_interval(1) #to draw or not to draw... if self.blink_count % 2: for blink in self.cur_blinking: blink.draw(self.ui_layer) else: self.ui_layer.fill((255, 0, 255)) #ok, stop flickering. if self.blink_count > self.blink_max: for blink in self.cur_blinking: blink.draw(self.bg_image) self.ui_layer.fill((255, 0, 255)) self.blink_count = 0 self.cur_blinking = None else: self.check_mouseover() def check_mouseover(self): #check if mouse hovers signet and show tooltip mpos = pygame.mouse.get_pos() for b in self.signet_buttons: if b.rect.collidepoint(mpos): self.tooltip.fill((255, 255, 255)) self.tooltip.draw_border((0, 0, 0)) self.tooltip.blit(GLOBALS["kanji"]["clan"], (10, 3)) self.tooltip.blit(GLOBALS["kanji"][b.clan], (60, 4)) pos = (mpos[0] + 10, mpos[1] + 20) x = (b.rect.centerx - self.tooltip.get_size()[0] / 2) y = b.rect.top pos = (x, y) self.tooltip_layer.blit(self.tooltip, pos) break dnp = self.donotpress if dnp.collidepoint(mpos): pos = (dnp.left - 60, dnp.top - 22) self.tooltip_layer.blit(self.dnp_tooltip, pos) def bigred_pressed(self): if self.cur_blending or self.cur_blinking: return if len(player_data["unlocked"]) < 9: self.next = ShowDialog("nothinghappened", self.screen) self.pause() self.quit() else: self.next = Outro() self.quit() def update_screen(self): self.background.blit(self.bg_image, (0, 0)) self.background.blit(self.tooltip_layer, (0, 0)) self.background.blit(self.ui_layer, (0, 0)) self.tooltip_layer.fill((255, 0, 255)) State.update_screen(self)
class Ninjat(Ninja): def __init__(self, cam, clan="fire"): if not GLOBALS["ninjats"].has_key(clan): clan = "fire" Ninja.__init__(self, cam, GLOBALS["ninjats"][clan]) self.name = "ninjat" self.ai = 1 self.speed = 2 self.set_vel((-1, 0)) self.sit_timer = Timer(10) self.shuriken_timer.set_interval(70) self.reaction_timer = Timer(10) def update(self): Ninja.update(self) def ai_update(self, parent): if self.off_screen(): return 0 elif self.status == 8: #not visible or dying px, py = self.pos self.set_pos((px, py + 4)) return 0 blocks = parent.blocks vx, vy = self.vel #can you see nanji? nanji = parent.player if not nanji.status == 7 and not self.shuriken_timer.active: nanji_rect = nanji.colrect own_rect = self.colrect in_height = own_rect.top <= nanji_rect.centery <= own_rect.bottom if self.look < 0: in_look = own_rect.left > nanji_rect.left else: in_look = own_rect.right < nanji_rect.right if in_height and in_look and self.reaction_timer.update(): if not self.shuriken_timer.active: self.throw() self.update() self.reaction_timer.activate() return 1 #loockityerfeets, little kitteh - try not to fall down >.< if self.look > 0: x = self.colrect.right + vx x2 = self.colrect.left else: x = self.colrect.left - vx x2 = self.colrect.right front_paws = pygame.Rect([x, self.colrect.bottom + 10, 2, 2]) back_paws = pygame.Rect([x2, self.colrect.bottom + 10, 2, 2]) if front_paws.collidelist(blocks) < 0: #no graunds in front :/ if back_paws.collidelist( blocks) > -1: #but grawnds in bak. go bak! :) self.turn() self.mod_vel(vx=self.look) else: self.mod_vel(vx=0) #fall down. #turn around if bumped against block col_x, col_y = self.check_mapcollisions(blocks) if col_x: self.turn() self.mod_vel(vx=self.look) self.update() if self.status == 0 and self.sit_timer.update(): self.set_vel((self.look, 0)) return 0
class Ninja(AnimatedKitten): def __init__(self, cam, images): self.all_images = images self.camera = cam AnimatedKitten.__init__(self, self.all_images["idle"], delay=10) self.colrect = pygame.Rect([0, 0, 35, 35]) self.angle = 0 #rotation angle for death animation self.shuriken = None self.idle_timer = Timer(200) self.jump_timer = Timer(20) self.shuriken_timer = Timer(20) self.invincible = 0 self.invincible_timer = Timer( 100) #on hit nanji is invincible for set time self.blink_timer = Timer(2) self.name = "" self.cur_images = "idle" self.speed = 4 self.look = 1 #1 => looking right self.statlist = [ "idle", #0 "walking", #1 "sprinting", #2 "throwing", #3 "jumping", #4 "falling", #5 "landing", #6 "ducking", #7 "dying", #8 ] self.on_ground = [0, 1, 2] self.status = 0 self.fall() def set_image(self, img): #return #DELETEME top = self.rect.top bottom = self.rect.bottom left = self.rect.left right = self.rect.right vx, vy = self.vel AnimatedKitten.set_image(self, img) self.rect.size = self.image.get_size() if vy < 0: self.rect.top = top else: self.rect.bottom = bottom if self.look > 0: self.rect.left = left else: self.rect.right = right self.rect.centerx = self.colrect.centerx self.rect.bottom = self.colrect.bottom self.set_pos(self.rect.topleft) def get_hit(self): if not self.invincible: self.invincible = 1 self.invincible_timer.activate() def bounce(self): #TODO: bouncing looks.. kind of not bouncy self.status = 4 self.jump_timer.activate() self.jump_timer.counter = self.jump_timer.interval - 2 #GLOBALS["sfx"][sfx_bounce].play() def die(self): if self.status == 3 and self.shuriken: self.shuriken.kill() #remove shuriken self.status = 8 GLOBALS["sfx"][sfx_die].play() def change_images(self, name, lookupdate=False): change = self.cur_images != name if change or lookupdate: nname = name nr = self.cur_image counter = self.anim_timer.counter if self.look < 0: nname = name + "_l" AnimatedKitten.set_images(self, self.all_images[nname]) self.cur_images = name if name == "sprinting" or name == "throwing": self.anim_timer.set_interval(3) elif name == "jump": self.anim_timer.set_interval(5) elif name == "landing": self.anim_timer.set_interval(7) else: self.anim_timer.set_interval(10) if lookupdate: self.set_image(self.images[nr]) self.cur_image = nr self.anim_timer.counter = counter #self.stop() def sprint(self): if self.status in self.on_ground: self.status = 2 def unsprint(self): if self.status == 2: self.status = 0 def jump(self): if self.status in self.on_ground: GLOBALS["sfx"][sfx_jump].play() self.status = 4 self.jump_timer.activate() def unjump(self): if self.status == 4 and self.jump_timer.counter > 8: self.status = 5 self.jump_timer.deactivate() def land(self): if self.status == 5: self.status = 6 GLOBALS["sfx"][sfx_land].play() def fall(self): self.status = 5 def throw(self): if (self.status in self.on_ground or self.status==7) and \ self.status != 3 and not self.shuriken_timer.active: self.status = 3 GLOBALS["sfx"][sfx_throw].play() self.mod_vel(vx=0, vy=0) #stand still while throwing!! self.change_images("idle") self.shuriken_timer.activate() return True return False def unthrow(self): if self.status == 3: self.status = 0 def turn(self): self.look = self.look * -1 self.change_images(self.cur_images, lookupdate=True) def duck(self): if self.status in self.on_ground: self.status = 7 def unduck(self): self.status = 0 def mod_vel(self, vx=None, vy=None): nx, ny = self.vel if vx is not None: nx = vx elif nx > 0: nx = 1 elif nx < 0: nx = -1 if vy is not None: ny = vy elif ny > 0: ny = 1 elif ny < 0: ny = -1 self.set_vel((nx, ny)) def set_vel(self, vel): vx, vy = vel sprint, jump = 0, 0 if self.status == 2: sprint = 6 * vx if self.status == 4 and vy < 0: jump = 4 AnimatedKitten.set_vel( self, (vx * self.speed + sprint, vy * self.speed - jump)) def update_status(self): if self.vel[0] > 0 and self.look < 0: self.turn() elif self.vel[0] < 0 and self.look > 0: self.turn() if self.status == 8: #dying :/ self.image = pygame.transform.rotate(self.all_images["jump"][2], self.angle) self.angle += 5 self.pause() return if self.status in self.on_ground: if self.status == 2 and self.vel[0]: self.change_images("sprinting") elif self.vel[0]: self.status = 1 self.change_images("walking") elif not self.cur_images == "idle": self.change_images("idle") self.status = 0 self.idle_timer.activate() self.stop() elif self.status == 7: self.set_vel((0, 0)) self.change_images("ducking") elif self.status == 3: self.change_images("throwing") self.mod_vel(vx=0) if self.cur_image >= len(self.images) -1 and \ self.anim_timer.counter >= self.anim_timer.interval -1: self.unthrow() elif self.status == 6: self.change_images("landing") if self.cur_image >= len(self.images) - 1: self.status = 0 self.change_images("idle") elif self.cur_image == 1 and self.anim_timer.interval < 10: self.anim_timer.set_interval(10) elif self.status == 5: self.mod_vel(vy=1) self.change_images("flight") elif self.status == 4: self.change_images("jump") if self.status in [4, 5] and self.cur_image >= len(self.images) - 1: self.pause() #pause last image of falling and jumping elif self.status == 0: if self.idle_timer.update(): #play idle animation after some time self.play() self.idle_timer.deactivate() else: self.play() if self.shuriken_timer.update(): self.shuriken_timer.deactivate() def update(self): if self.status == 4: if self.cur_image < 3: self.mod_vel(vy=0) else: self.mod_vel(vy=-1) if self.jump_timer.update(): self.jump_timer.counter = 9 self.unjump() #cannibalized from AnimatedKitten.update because that code was a booboo if self.animate and self.anim_timer.update(): self.cur_image += 1 if self.cur_image >= len(self.images): self.cur_image = 0 self.set_image(self.images[self.cur_image]) if self.invincible: if self.blink_timer.update(): if self.image.get_alpha() > 0: self.image = self.image.copy() self.image.set_alpha(0) else: self.image = self.image.copy() self.image.set_alpha(255) if self.invincible_timer.update(): self.image = self.image.copy() self.image.set_alpha(255) self.invincible_timer.deactivate() self.invincible = 0 def set_pos(self, pos): AnimatedKitten.set_pos(self, pos) self.colrect.centerx = self.rect.centerx self.colrect.bottom = self.rect.bottom def check_mapcollisions(self, blocks): bl = blocks vx, vy = self.vel px, py = self.colrect.topleft width, height = self.colrect.size test = 0 if vy == 0: vy = 1 test = 1 colliding = [0, 0] #vertical collisions vrect = pygame.Rect([px, py + vy, width, height]) blocks = vrect.collidelistall(bl) for nr in blocks: block = bl[nr] colliding[1] = vy if vy > 0 and vrect.bottom > block.top and not self.status == 6: if not test: self.land() self.colrect.bottom = block.top self.mod_vel(vy=0) elif vy < 0 and vrect.top < block.bottom: self.unjump() self.colrect.top = block.bottom self.mod_vel(vy=0) if test and not blocks and not self.status == 4 and not self.status == 6: #fall unless you are jumping or landing self.fall() elif not blocks: self.colrect.top += vy #kk, move along #horizontal collisions hrect = pygame.Rect([px + vx, py, width, height]) blocks = hrect.collidelistall(bl) for nr in blocks: block = bl[nr] colliding[0] = vx if vx > 0 and hrect.right > block.left: self.colrect.right = block.left self.mod_vel(vx=0) elif vx < 0 and hrect.left < block.right: self.colrect.left = block.right self.mod_vel(vx=0) if not blocks: self.colrect.left += vx #gogo little kitteh! self.rect.midbottom = self.colrect.midbottom self.set_pos(self.rect.topleft) return colliding def off_screen(self): #returns true if character off screen off_x, off_y = self.camera.pos real_x, real_y = self.pos[0] - off_x, self.pos[1] - off_y screen_x, screen_y = GLOBALS["screen_size"] w, h = self.get_size() #set larger screen to keep updating ninjats w += 600 h += 100 off_x -= 300 off_y -= 50 return real_x > screen_x + w or real_y > screen_y + h or real_x < -w or real_y < -h def check_trigcollisions(self, trigger): pass #keep this.