作业1

import pygame
import sys
import random

# 初始化Pygame
pygame.init()

# 游戏窗口设置
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("超级马里奥克隆")

# 确保中文正常显示
pygame.font.init()
font = pygame.font.SysFont(['SimHei', 'WenQuanYi Micro Hei', 'Heiti TC'], 36)

# 颜色定义
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
SKY_BLUE = (135, 206, 235)
BROWN = (139, 69, 19)
YELLOW = (255, 255, 0)

# 游戏参数
FPS = 60
GRAVITY = 0.75
SCROLL_THRESH = 200  # 玩家到达这个位置时开始滚动屏幕

# 玩家类
class Player(pygame.sprite.Sprite):
    def __init__(self, x, y):
        super().__init__()
        self.width = 40
        self.height = 60
        self.image = pygame.Surface((self.width, self.height))
        self.image.fill(RED)
        self.rect = self.image.get_rect()
        self.rect.x = x
        self.rect.y = y
        self.vel_y = 0
        self.speed = 5
        self.jump_strength = -16
        self.on_ground = False
        self.facing_right = True
        self.score = 0
        self.lives = 3
        self.invincible = False
        self.invincible_time = 0

    def update(self, world):
        # 重置变量
        self.on_ground = False
        dx = 0
        dy = 0

        # 处理输入
        key = pygame.key.get_pressed()
        if key[pygame.K_LEFT]:
            dx -= self.speed
            self.facing_right = False
        if key[pygame.K_RIGHT]:
            dx += self.speed
            self.facing_right = True
        if key[pygame.K_SPACE] and self.on_ground:
            self.vel_y = self.jump_strength

        # 应用重力
        self.vel_y += GRAVITY
        dy += self.vel_y

        # 检查无敌状态
        if self.invincible:
            self.invincible_time += 1
            if self.invincible_time >= 120:  # 2秒无敌时间
                self.invincible = False
                self.invincible_time = 0

        # 碰撞检测 - 方块
        for tile in world.tile_list:
            # 水平碰撞
            if tile[1].colliderect(self.rect.x + dx, self.rect.y, self.width, self.height):
                dx = 0
            # 垂直碰撞
            if tile[1].colliderect(self.rect.x, self.rect.y + dy, self.width, self.height):
                # 跳跃碰到方块底部
                if self.vel_y < 0:
                    dy = tile[1].bottom - self.rect.top
                    self.vel_y = 0
                # 下落碰到方块顶部
                elif self.vel_y >= 0:
                    dy = tile[1].top - self.rect.bottom
                    self.vel_y = 0
                    self.on_ground = True

        # 碰撞检测 - 敌人
        if not self.invincible:
            for enemy in world.enemy_group:
                if pygame.sprite.collide_rect(self, enemy):
                    if self.vel_y > 0:  # 从上方踩敌人
                        self.vel_y = -10  # 给玩家一个小弹跳
                        enemy.kill()
                        self.score += 100
                    else:  # 被敌人碰到
                        self.lives -= 1
                        self.invincible = True
                        self.invincible_time = 0

        # 碰撞检测 - 金币
        for coin in world.coin_group:
            if pygame.sprite.collide_rect(self, coin):
                coin.kill()
                self.score += 50

        # 碰撞检测 - 蘑菇
        for mushroom in world.mushroom_group:
            if pygame.sprite.collide_rect(self, mushroom):
                mushroom.kill()
                self.score += 200
                self.lives += 1  # 增加一条命

        # 更新玩家位置
        self.rect.x += dx
        self.rect.y += dy

        # 屏幕滚动
        if self.rect.right > SCREEN_WIDTH - SCROLL_THRESH:
            scroll = SCREEN_WIDTH - SCROLL_THRESH - self.rect.right
            world.move_sprites(scroll)
            self.rect.right = SCREEN_WIDTH - SCROLL_THRESH
        if self.rect.left < SCROLL_THRESH:
            scroll = SCROLL_THRESH - self.rect.left
            world.move_sprites(scroll)
            self.rect.left = SCROLL_THRESH

        # 确保玩家不会掉出屏幕底部
        if self.rect.bottom > SCREEN_HEIGHT:
            self.lives -= 1
            self.rect.y = 0
            self.vel_y = 0

    def draw(self, screen):
        # 无敌状态闪烁效果
        if not self.invincible or pygame.time.get_ticks() % 200 < 100:
            screen.blit(self.image, self.rect)

# 敌人类
class Enemy(pygame.sprite.Sprite):
    def __init__(self, x, y):
        super().__init__()
        self.width = 40
        self.height = 40
        self.image = pygame.Surface((self.width, self.height))
        self.image.fill(GREEN)
        self.rect = self.image.get_rect()
        self.rect.x = x
        self.rect.y = y
        self.speed = 2

    def update(self, scroll):
        # 移动敌人
        self.rect.x += self.speed

        # 翻转方向如果碰到障碍物
        for tile in world.tile_list:
            if tile[1].colliderect(self.rect.x + self.speed, self.rect.y, self.width, self.height):
                self.speed *= -1

        # 屏幕滚动
        self.rect.y += scroll

        # 如果敌人离开屏幕,删除它
        if self.rect.top > SCREEN_HEIGHT:
            self.kill()

# 金币类
class Coin(pygame.sprite.Sprite):
    def __init__(self, x, y):
        super().__init__()
        self.width = 20
        self.height = 20
        self.image = pygame.Surface((self.width, self.height))
        self.image.fill(YELLOW)
        self.rect = self.image.get_rect()
        self.rect.x = x
        self.rect.y = y

    def update(self, scroll):
        # 屏幕滚动
        self.rect.y += scroll

        # 如果金币离开屏幕,删除它
        if self.rect.top > SCREEN_HEIGHT:
            self.kill()

# 蘑菇类 (生命道具)
class Mushroom(pygame.sprite.Sprite):
    def __init__(self, x, y):
        super().__init__()
        self.width = 30
        self.height = 30
        self.image = pygame.Surface((self.width, self.height))
        self.image.fill(RED)
        pygame.draw.rect(self.image, WHITE, (5, 5, 20, 20), 2)  # 白色边框
        self.rect = self.image.get_rect()
        self.rect.x = x
        self.rect.y = y
        self.speed = 1

    def update(self, scroll):
        # 移动蘑菇
        self.rect.x += self.speed

        # 翻转方向如果碰到障碍物
        for tile in world.tile_list:
            if tile[1].colliderect(self.rect.x + self.speed, self.rect.y, self.width, self.height):
                self.speed *= -1

        # 屏幕滚动
        self.rect.y += scroll

        # 如果蘑菇离开屏幕,删除它
        if self.rect.top > SCREEN_HEIGHT:
            self.kill()

# 世界类
class World:
    def __init__(self, data):
        self.tile_list = []
        self.enemy_group = pygame.sprite.Group()
        self.coin_group = pygame.sprite.Group()
        self.mushroom_group = pygame.sprite.Group()
        self.scroll_amount = 0
        
        # 加载图块
        self.grass_img = pygame.Surface((50, 50))
        self.grass_img.fill(GREEN)
        self.dirt_img = pygame.Surface((50, 50))
        self.dirt_img.fill(BROWN)
        
        # 生成世界
        self.process_data(data)

    def process_data(self, data):
        for y, row in enumerate(data):
            for x, tile in enumerate(row):
                if tile == 1:  # 草块
                    img = self.grass_img
                    rect = img.get_rect()
                    rect.x = x * 50
                    rect.y = y * 50
                    self.tile_list.append((img, rect))
                if tile == 2:  # 土块
                    img = self.dirt_img
                    rect = img.get_rect()
                    rect.x = x * 50
                    rect.y = y * 50
                    self.tile_list.append((img, rect))
                if tile == 3:  # 敌人
                    enemy = Enemy(x * 50, y * 50)
                    self.enemy_group.add(enemy)
                if tile == 4:  # 金币
                    coin = Coin(x * 50 + 15, y * 50 + 15)
                    self.coin_group.add(coin)
                if tile == 5:  # 蘑菇
                    mushroom = Mushroom(x * 50, y * 50)
                    self.mushroom_group.add(mushroom)

    def move_sprites(self, scroll):
        self.scroll_amount += scroll
        # 更新所有图块的位置
        for tile in self.tile_list:
            tile[1].y += scroll

    def draw(self, screen):
        for tile in self.tile_list:
            screen.blit(tile[0], tile[1])
        self.enemy_group.draw(screen)
        self.coin_group.draw(screen)
        self.mushroom_group.draw(screen)

    def update(self):
        self.enemy_group.update(self.scroll_amount)
        self.coin_group.update(self.scroll_amount)
        self.mushroom_group.update(self.scroll_amount)
        self.scroll_amount = 0  # 重置滚动量,避免累积

# 游戏地图数据
# 1 = 草块, 2 = 土块, 3 = 敌人, 4 = 金币, 5 = 蘑菇
world_data = [
    [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
    [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
    [1, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 1],
    [1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 2, 2, 1],
    [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 5, 0, 0, 0, 0, 1],
    [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
    [1, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
    [1, 7, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
    [1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
    [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 7, 0, 0, 0, 0, 1],
    [1, 0, 4, 0, 0, 7, 0, 7, 0, 0, 0, 2, 0, 0, 2, 0, 0, 0, 0, 1],
    [1, 0, 0, 0, 0, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
    [1, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
    [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
    [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
    [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
    [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
    [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
    [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
    [2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2]
]

# 创建游戏世界
world = World(world_data)

# 创建玩家
player = Player(100, SCREEN_HEIGHT - 100)

# 创建时钟控制帧率
clock = pygame.time.Clock()

# 游戏主循环
running = True
game_over = False
while running:
    clock.tick(FPS)
    
    # 填充背景色
    screen.fill(SKY_BLUE)
    
    # 事件处理
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
    
    if not game_over:
        # 更新玩家
        player.update(world)
        
        # 更新世界
        world.update()
        
        # 绘制世界
        world.draw(screen)
        
        # 绘制玩家
        player.draw(screen)
        
        # 显示分数和生命值
        score_text = font.render(f"分数: {player.score}", True, WHITE)
        screen.blit(score_text, (10, 10))
        
        lives_text = font.render(f"生命: {player.lives}", True, WHITE)
        screen.blit(lives_text, (10, 50))
        
        # 检查游戏是否结束
        if player.lives <= 0:
            game_over = True
    else:
        # 显示游戏结束画面
        game_over_text = font.render("游戏结束!按 R 键重新开始", True, WHITE)
        screen.blit(game_over_text, (SCREEN_WIDTH // 2 - game_over_text.get_width() // 2, SCREEN_HEIGHT // 2 - 50))
        
        # 重新开始游戏
        key = pygame.key.get_pressed()
        if key[pygame.K_r]:
            # 重置游戏状态
            player = Player(100, SCREEN_HEIGHT - 100)
            world = World(world_data)
            game_over = False
    
    # 更新显示
    pygame.display.flip()

# 退出游戏
pygame.quit()
sys.exit()    

 

posted @ 2025-06-23 17:21  杯影  阅读(16)  评论(0)    收藏  举报