小时候最喜欢玩的小游戏就是超级玛丽了,有刺激有又技巧,通关真的很难,救下小公主还被抓走了,唉,心累,最后还是硬着头皮继续闯,终于要通关了,之后再玩还是没有那么容易,哈哈,不知道现在能不能通关,今天就来简单实现一下。
超级玛丽
运行起来是这样的,可以简单作为试玩。
绘制金币:
class Coin(EntityBase):
def __init__(self, screen, spriteCollection, x, y, gravity=0):
super(Coin, self).__init__(x, y, gravity)
self.screen = screen
self.spriteCollection = spriteCollection
self.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 = sound
self.input = Input(self)
self.inAir = False
self.inJump = False
self.powerUpState = 0
self.invincibilityFrames = 0
self.traits = {
"jumpTrait": JumpTrait(self),
"goTrait": GoTrait(smallAnimation, screen, self.camera, self),
"bounceTrait": bounceTrait(self),
}
self.levelObj = level
self.collision = Collider(self, level)
self.screen = screen
self.EntityCollider = EntityCollider(self)
self.dashboard = dashboard
self.restart = False
self.pause = False
self.pauseObj = Pause(screen, self, dashboard)
def update(self):
if self.invincibilityFrames > 0:
self.invincibilityFrames -= 1
self.updateTraits()
self.moveMario()
self.camera.move()
self.applyGravity()
self.checkEntityCollision()
self.input.checkForInput()
def moveMario(self):
self.rect.y += self.vel.y
self.collision.checkY()
self.rect.x += self.vel.x
self.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 += 100
self.dashboard.coins += 1
self.sound.play_sfx(self.sound.coin)
def _onCollisionWithBlock(self, block):
if not block.triggered:
self.dashboard.coins += 1
self.sound.play_sfx(self.sound.bump)
block.triggered = True
def _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.top
self.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.top
mob.timer = 0
self.bounce()
mob.alive = False
elif collisionState.isColliding and mob.alive and not mob.active and not mob.bouncing:
mob.bouncing = True
if mob.rect.x < self.rect.x:
mob.leftrightTrait.direction = -1
mob.rect.x += -5
self.sound.play_sfx(self.sound.kick)
else:
mob.rect.x += 5
mob.leftrightTrait.direction = 1
self.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 = 0
self.traits['goTrait'].updateAnimation(smallAnimation)
x, y = self.rect.x, self.rect.y
self.rect = pygame.Rect(x, y + 32, 32, 32)
self.invincibilityFrames = 60
self.sound.play_sfx(self.sound.pipe)
def bounce(self):
self.traits["bounceTrait"].jump = True
def killEntity(self, ent):
if ent.__class__.__name__ != "Koopa":
ent.alive = False
else:
ent.timer = 0
ent.leftrightTrait.speed = 1
ent.alive = True
ent.active = False
ent.bouncing = False
self.dashboard.points += 100
def 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 = True
def getPos(self):
return self.camera.x + self.rect.x, self.rect.y
def setPos(self, x, y):
self.rect.x = x
self.rect.y = y
def powerup(self, powerupID):
if self.powerUpState == 0:
if powerupID == 1:
self.powerUpState = 1
self.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 = screen
self.spriteCollection = spriteCollection
self.animation = copy(self.spriteCollection.get("CoinBox").animation)
self.type = "Block"
self.triggered = False
self.time = 0
self.maxTime = 10
self.sound = sound
self.dashboard = dashboard
self.vel = 1
self.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").image
self.item.spawnCoin(cam, self.sound, self.dashboard)
if self.time < self.maxTime:
self.time += 1
self.rect.y -= self.vel
else:
if self.time < self.maxTime * 2:
self.time += 1
self.rect.y += self.vel
self.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, 480
def main():
pygame.mixer.pre_init(44100, -16, 2, 4096)
pygame.init()
screen = pygame.display.set_mode(windowSize)
max_frame_rate = 60
dashboard = 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()