Python版《超级玛丽+源码》-Python制作超级玛丽游戏
小时候最喜欢玩的小游戏就是超级玛丽了,有刺激有又技巧,通关真的很难,救下小公主还被抓走了,唉,心累,最后还是硬着头皮继续闯,终于要通关了,之后再玩还是没有那么容易,哈哈,不知道现在能不能通关,今天就来简单实现一下。
超级玛丽
运行起来是这样的,可以简单作为试玩。
绘制金币:
class Coin(EntityBase):def __init__(self, screen, spriteCollection, x, y, gravity=0):super(Coin, self).__init__(x, y, gravity)self.screen = screenself.spriteCollection = spriteCollectionself.animation = copy(self.spriteCollection.get("coin").animation)self.type = "Item"def update(self, cam):if self.alive:self.animation.update()self.screen.blit(self.animation.image, (self.rect.x + cam.x, self.rect.y))
绘制玛丽:
spriteCollection = Sprites().spriteCollection
smallAnimation = Animation([spriteCollection["mario_run1"].image,spriteCollection["mario_run2"].image,spriteCollection["mario_run3"].image,],spriteCollection["mario_idle"].image,spriteCollection["mario_jump"].image,
)
bigAnimation = Animation([spriteCollection["mario_big_run1"].image,spriteCollection["mario_big_run2"].image,spriteCollection["mario_big_run3"].image,],spriteCollection["mario_big_idle"].image,spriteCollection["mario_big_jump"].image,
)class Mario(EntityBase):def __init__(self, x, y, level, screen, dashboard, sound, gravity=0.8):super(Mario, self).__init__(x, y, gravity)self.camera = Camera(self.rect, self)self.sound = soundself.input = Input(self)self.inAir = Falseself.inJump = Falseself.powerUpState = 0self.invincibilityFrames = 0self.traits = {"jumpTrait": JumpTrait(self),"goTrait": GoTrait(smallAnimation, screen, self.camera, self),"bounceTrait": bounceTrait(self),}self.levelObj = levelself.collision = Collider(self, level)self.screen = screenself.EntityCollider = EntityCollider(self)self.dashboard = dashboardself.restart = Falseself.pause = Falseself.pauseObj = Pause(screen, self, dashboard)def update(self):if self.invincibilityFrames > 0:self.invincibilityFrames -= 1self.updateTraits()self.moveMario()self.camera.move()self.applyGravity()self.checkEntityCollision()self.input.checkForInput()def moveMario(self):self.rect.y += self.vel.yself.collision.checkY()self.rect.x += self.vel.xself.collision.checkX()def checkEntityCollision(self):for ent in self.levelObj.entityList:collisionState = self.EntityCollider.check(ent)if collisionState.isColliding:if ent.type == "Item":self._onCollisionWithItem(ent)elif ent.type == "Block":self._onCollisionWithBlock(ent)elif ent.type == "Mob":self._onCollisionWithMob(ent, collisionState)def _onCollisionWithItem(self, item):self.levelObj.entityList.remove(item)self.dashboard.points += 100self.dashboard.coins += 1self.sound.play_sfx(self.sound.coin)def _onCollisionWithBlock(self, block):if not block.triggered:self.dashboard.coins += 1self.sound.play_sfx(self.sound.bump)block.triggered = Truedef _onCollisionWithMob(self, mob, collisionState):if isinstance(mob, RedMushroom) and mob.alive:self.powerup(1)self.killEntity(mob)self.sound.play_sfx(self.sound.powerup)elif collisionState.isTop and (mob.alive or mob.bouncing):self.sound.play_sfx(self.sound.stomp)self.rect.bottom = mob.rect.topself.bounce()self.killEntity(mob)elif collisionState.isTop and mob.alive and not mob.active:self.sound.play_sfx(self.sound.stomp)self.rect.bottom = mob.rect.topmob.timer = 0self.bounce()mob.alive = Falseelif collisionState.isColliding and mob.alive and not mob.active and not mob.bouncing:mob.bouncing = Trueif mob.rect.x < self.rect.x:mob.leftrightTrait.direction = -1mob.rect.x += -5self.sound.play_sfx(self.sound.kick)else:mob.rect.x += 5mob.leftrightTrait.direction = 1self.sound.play_sfx(self.sound.kick)elif collisionState.isColliding and mob.alive and not self.invincibilityFrames:if self.powerUpState == 0:self.gameOver()elif self.powerUpState == 1:self.powerUpState = 0self.traits['goTrait'].updateAnimation(smallAnimation)x, y = self.rect.x, self.rect.yself.rect = pygame.Rect(x, y + 32, 32, 32)self.invincibilityFrames = 60self.sound.play_sfx(self.sound.pipe)def bounce(self):self.traits["bounceTrait"].jump = Truedef killEntity(self, ent):if ent.__class__.__name__ != "Koopa":ent.alive = Falseelse:ent.timer = 0ent.leftrightTrait.speed = 1ent.alive = Trueent.active = Falseent.bouncing = Falseself.dashboard.points += 100def gameOver(self):srf = pygame.Surface((640, 480))srf.set_colorkey((255, 255, 255), pygame.RLEACCEL)srf.set_alpha(128)self.sound.music_channel.stop()self.sound.music_channel.play(self.sound.death)for i in range(500, 20, -2):srf.fill((0, 0, 0))pygame.draw.circle(srf,(255, 255, 255),(int(self.camera.x + self.rect.x) + 16, self.rect.y + 16),i,)self.screen.blit(srf, (0, 0))pygame.display.update()self.input.checkForInput()while self.sound.music_channel.get_busy():pygame.display.update()self.input.checkForInput()self.restart = Truedef getPos(self):return self.camera.x + self.rect.x, self.rect.ydef setPos(self, x, y):self.rect.x = xself.rect.y = ydef powerup(self, powerupID):if self.powerUpState == 0:if powerupID == 1:self.powerUpState = 1self.traits['goTrait'].updateAnimation(bigAnimation)self.rect = pygame.Rect(self.rect.x, self.rect.y-32, 32, 64)self.invincibilityFrames = 20
绘制土坯,金币盒子,动物,乌龟等的文件:
class CoinBox(EntityBase):def __init__(self, screen, spriteCollection, x, y, sound, dashboard, gravity=0):super(CoinBox, self).__init__(x, y, gravity)self.screen = screenself.spriteCollection = spriteCollectionself.animation = copy(self.spriteCollection.get("CoinBox").animation)self.type = "Block"self.triggered = Falseself.time = 0self.maxTime = 10self.sound = soundself.dashboard = dashboardself.vel = 1self.item = Item(spriteCollection, screen, self.rect.x, self.rect.y)def update(self, cam):if self.alive and not self.triggered:self.animation.update()else:self.animation.image = self.spriteCollection.get("empty").imageself.item.spawnCoin(cam, self.sound, self.dashboard)if self.time < self.maxTime:self.time += 1self.rect.y -= self.velelse:if self.time < self.maxTime * 2:self.time += 1self.rect.y += self.velself.screen.blit(self.spriteCollection.get("sky").image,(self.rect.x + cam.x, self.rect.y + 2),)self.screen.blit(self.animation.image, (self.rect.x + cam.x, self.rect.y - 1))
直接运行main.py文件就可以进入游戏了:
windowSize = 640, 480def main():pygame.mixer.pre_init(44100, -16, 2, 4096)pygame.init()screen = pygame.display.set_mode(windowSize)max_frame_rate = 60dashboard = Dashboard("./img/font.png", 8, screen)sound = Sound()level = Level(screen, sound, dashboard)menu = Menu(screen, dashboard, level, sound)while not menu.start:menu.update()mario = Mario(0, 0, level, screen, dashboard, sound)clock = pygame.time.Clock()while not mario.restart:pygame.display.set_caption("Super Mario running with {:d} FPS".format(int(clock.get_fps())))if mario.pause:mario.pauseObj.update()else:level.drawLevel(mario.camera)dashboard.update()mario.update()pygame.display.update()clock.tick(max_frame_rate)return 'restart'if __name__ == "__main__":exitmessage = 'restart'while exitmessage == 'restart':exitmessage = main()