为您推荐:
精华内容
最热下载
问答
  • 5星
    450KB m0_52957036 2020-05-19 23:46:39
  • 5星
    3.7MB Accelerato 2020-11-23 22:51:42
  • 1.67MB arzha 2020-01-23 03:20:24
  • 4星
    1.53MB hongbin_xu 2017-06-19 22:31:27
  • 8.65MB weixin_44863905 2019-07-07 14:47:48
  • 804KB qq_43558971 2019-07-07 16:44:03
  • 103KB weixin_43393770 2020-11-28 20:05:26
  • 14.15MB t3573393 2016-01-08 10:53:25
  • 5KB weixin_38669628 2019-03-19 01:48:33
  • 4星
    188KB abacaba 2012-07-26 16:56:56
  • 60KB weixin_38706743 2020-09-19 07:08:12
  • 这篇博客是用书本项目的前半段知识,自己写出来的小游戏,一些计分之类的功能还没有加上去。主要内容是控制一个挡板,躲避从上空掉落下来的球。 我把下面的挡板和上面的球都设置为黑色长方体了,可以自己把上面的...

    学习《python编程:从入门到实践》的第一个项目案例后,本来想把自己的注释笔记分享出来,但考虑到这样不得不把书上的代码暴露出来,为了保护版权所以还是算了。

    这篇博客是用书本项目的前半段知识,自己写出来的小游戏,一些计分之类的功能还没有加上去。主要内容是控制一个挡板,躲避从上空掉落下来的球。

    我把下面的挡板和上面的球都设置为黑色长方体了,可以自己把上面的黑色方块想象成小球
    在这里插入图片描述

    这是项目结构截图
    在这里插入图片描述
    下面是代码和我写上去的注释
    game_main.py
    运行游戏时的主体部分,在这里运行函数run()即可开始游戏

    import pygame
    from configure import Configure
    import functions as func
    from baffle import Baffle
    from pygame.sprite import Group
    
    
    def run():
        # 初始化游戏并创建一个屏幕对象
            # 初始化背景设置,让pygame正常工作
        pygame.init()
        # 创建一个Configure实例,并将其存储在变量 conf 中
        conf = Configure()
        # 创建一个名为screen 的显示窗口,用来绘制这个游戏的所有图形元素
        screen = pygame.display.set_mode((conf.screen_width, conf.screen_height))
        # caption的意思是给漫画添加说明文字,这里是修改窗口名称
        pygame.display.set_caption("Catch the ball")
        # 创建一个挡板实例
        baffle = Baffle(conf,screen)
        # 创建一个balls列表
        balls = Group()
        # 调用create_fleet函数往balls列表里面添加ball
        func.create_fleet(conf,screen,balls)
        # 当运行游戏也就是执行run()之后,这个while循环将一直执行,里面的函数也一直在被调用
        while True:
            # 导入functions.py文件中的check_events函数,检测鼠标与键盘事件
                # 前面说过,这个循环一直在执行,所以一旦出现鼠标键盘事件就会被立刻捕捉
            func.check_events(baffle)
            # 更新挡板baffle的最新位置
            baffle.update()
            # 更新balls也就是掉落的球组的最新位置
            func.update_balls(conf,screen,baffle,balls)
            # 刷新背景屏幕
            func.update_screen(conf,screen,baffle,balls)
    
    
    run()
    

    ball.py,这个是从屏幕上方要掉落的小球

    import pygame	
    from pygame.sprite import Sprite
    
    class Ball(Sprite):
        def __init__(self,conf,screen):
            super().__init__()
            # 初始化conf与screen
            self.conf = conf
            self.screen = screen
            # 获取球ball的图像,并获取其尺寸大小
            self.image = pygame.image.load('image/baffle.bmp')
            self.rect = self.image.get_rect()
            # 初始化球所在的位置
            self.rect.x = self.rect.width
            self.rect.y = self.rect.height
    
            self.y = float(self.rect.y)
    
        # 更新球的y轴位置,也就是模拟球向下掉落的过程
        def update(self):
            self.y += self.conf.balls_drop_speed
            self.rect.y = self.y
    
    

    baffle.py ,这个是屏幕下方的挡板,由玩家控制,要躲避从上方掉落的小球

    import pygame
    
    class Baffle():
        def __init__(self,conf,screen):
            # 初始化conf与screen
            self.screen = screen
            self.conf = conf
            # 获取挡板baffle的图像,并获取其尺寸大小
            self.image = pygame.image.load('image/baffle.bmp')
            self.rect = self.image.get_rect()
            # 获取背景屏幕的尺寸
            self.screen_rect = screen.get_rect()
            # 初始化挡板的位置,也就是屏幕底部中间的位置
                # 当游戏开始后,挡板就会出现在这个设置好的位置上
            self.rect.centerx = self.screen_rect.centerx
            self.rect.bottom = self.screen_rect.bottom
    
            self.center = float(self.rect.centerx)
            # 初始化挡板的左右移动标志,标志为False时挡板不在移动
            self.moving_right = False
            self.moving_left = False
    
        def update(self):
            # 当向右移动标志为True而且挡板没有超过背景屏幕右侧时
            if self.moving_right and self.rect.right < self.screen_rect.right:
                self.center += self.conf.baffle_speed
            # 当向左移动标志为True而且挡板没有超过背景屏幕左侧时
            if self.moving_left and self.rect.left > 0:
                self.center -= self.conf.baffle_speed
    
            # 根据self.center更新rect对象
            self.rect.centerx = self.center
    
        def blitme(self):
            # 在指定的地方绘制飞船
            self.screen.blit(self.image,self.rect)
    
    

    functions.py,这个用来存放游戏中会被调用的各种函数

    import sys
    import pygame
    import random
    from ball import  Ball
    from pygame.sprite import spritecollideany
    from baffle import  Baffle
    
    # 键盘按下事件:keydown() 是在键盘按下就会触发
    def check_keydown_events(event,baffle):
        # 检测到右键被按下
        if event.key == pygame.K_RIGHT:
            # 更改向右移动状态为True,表明此时的挡板正在向右移动
            baffle.moving_right = True
        # 检测到左键被按下
        elif event.key == pygame.K_LEFT:
            # 更改向左移动状态为True,表明此时的挡板正在向左移动
            baffle.moving_left = True
    
    # 键盘弹起事件:keyup() 是在键盘松手就会触发
    def check_keyup_events(event,baffle):
        # 检测到右键被松开
        if event.key == pygame.K_RIGHT:
            # 恢复向右移动状态为False
            baffle.moving_right = False
        # 检测到左键被送开
        elif event.key == pygame.K_LEFT:
            # 恢复向左移动状态为False
            baffle.moving_left = False
    
    
    def check_events(baffle):
        for event in pygame.event.get():
            # 如果鼠标点击窗口右上角的x,则退出游戏
            if event.type == pygame.QUIT:
                sys.exit()
    
            # 如果事件类型为按下键盘
            elif event.type == pygame.KEYDOWN:
                check_keydown_events(event, baffle)
    
            # 如果事件类型为松开键盘
            elif event.type == pygame.KEYUP:
                check_keyup_events(event,baffle)
    
    def update_screen(conf,screen,baffle,balls):
        # 每次循环时都重绘屏幕
        screen.fill(conf.color)
        # 绘制挡板
        baffle.blitme()
        # 在屏幕上面绘制球
        balls.draw(screen)
        pygame.display.flip()
    
    def update_balls(conf,screen,baffle,balls):
        # 获取背景屏幕尺寸
        screen_rect = screen.get_rect()
        # 遍历balls中的每一个球ball,如果球落到了屏幕的下方,则删除这个球
        for ball in balls.copy():
            if ball.rect.bottom >= screen_rect.bottom:
                balls.remove(ball)
        # 检查屏幕上所剩的球的个数
        check_num_balls(conf,screen,balls)
    
        balls.update()
    
        # 如果球和挡板发生了碰撞,则在终端打印“collision”
        if pygame.sprite.spritecollideany(baffle,balls):
            print("collision")
    
    
    def check_num_balls(conf,screen,balls):
        # 检查balls里面剩下的ball的数量,如果数量为0,则刷新出来新的balls
        if len(balls) == 0:
            create_fleet(conf,screen,balls)
    
    
    
    def get_num_x(conf,ball_width):
        # 计算一行里面可以有多少个球
        available_space_x = conf.screen_width
        #球之间要有一定的空格,所以一个球所占的实际空间按两个球来算
        number_ball_x = int(available_space_x / (ball_width * 2))
        return number_ball_x
    
    def create_fleet(conf,screen,balls):
        ball = Ball(conf,screen)
        # 查看一行可以有多少个球
        number_ball_x = get_num_x(conf,ball.rect.width)
        # 建立一个随机数列表,这样传入create_ball中的number_ball_x参数数值是随机的
        ran = []
        for n in range(number_ball_x):
            nums = random.randint(0,number_ball_x)
            ran.append(nums)
        # 遍历每一个球,调用create_ball,计算被遍历到的球的所在位置,然后加入balls列表中
        for num in ran:
            create_ball(conf,screen,balls,num)
    
    def create_ball(conf,screen,balls,number_ball_x):
        ball = Ball(conf,screen)
        ball_width = ball.rect.width
        # 计算当前被遍历到的球所在的x轴位置
            # 坐标在屏幕的左上角为(0,0),往右下角则x,y值增大
        ball.rect.x = ball_width * 2 * number_ball_x
        # 球的y轴位置
        ball.rect.y = ball.rect.height
        # 根据上面的x轴与y轴位置,将ball放入列表balls中
        balls.add(ball)
    

    configure.py,用来存放各种游戏元素的设置

    class Configure():
        def __init__(self):
            # 设置屏幕的尺寸大小
            self.screen_width = 1000
            self.screen_height = 600
            # 设置屏幕的背景颜色
            self.color = (230, 230, 230)
            # 设置挡板的移动速度
            self.baffle_speed = 1
            # 设置球的下落速度
            self.balls_drop_speed = 0.5
    
    
    展开全文
    qq_44823756 2021-09-15 13:23:53
  • 136KB weixin_38657290 2021-01-02 17:57:08
  • 游戏功能:小球从屏幕顶端随机位置出现,垂直落下。...效果如图:代码如下:#coding=utf-8import pygamefrom pygame.locals import *import sysimport randomBLACK =(0,0,0)WHITE = (255,255,255)bg_color = (0,...

    游戏功能:小球从屏幕顶端随机位置出现,垂直落下。鼠标左右键控制挡板左右移动,接住下落的小球。若没有接到则游戏失败,退出并显示分数。效果如图:

    0ad52b628c9a92ad4d6416dffbd89e09.png

    代码如下:#coding=utf-8

    import pygame

    from pygame.locals import *

    import sys

    import random

    BLACK =(0,0,0)

    WHITE = (255,255,255)

    bg_color = (0, 0, 70)# 背景颜色

    SCREEN_SIZE = [320,400]#屏幕大小

    BAR_SIZE = [20,5]#挡板大小

    BALL_SIZE = [15,15]#球的尺寸

    class Game(object):

    def __init__(self):

    pygame.init()

    self.clock = pygame.time.Clock()#定时器

    self.screen = pygame.display.set_mode(SCREEN_SIZE)

    pygame.display.set_caption('My Game')#设置标题

    #ball 初始位置

    self.ball_pos_x = SCREEN_SIZE[0]//2 - BALL_SIZE[0]/2

    self.ball_pos_y = 0

    #ball 移动方向

    #self.ball_dir_x = -1 #-1:left 1:right

    self.ball_dir_y = 1# 1:down

    self.ball_pos = pygame.Rect(self.ball_pos_x,self.ball_pos_y,BALL_SIZE[0],BALL_SIZE[1])

    self.score =0

    self.bar_pos_x = SCREEN_SIZE[0]//2 - BAR_SIZE[0]//2

    self.bar_pos = pygame.Rect(self.bar_pos_x,SCREEN_SIZE[1]-BAR_SIZE[1],BAR_SIZE[0],BALL_SIZE[1])

    def bar_move_left(self):#左移

    self.bar_pos_x = self.bar_pos_x - 2

    def bar_move_right(self):#右移

    self.bar_pos_x = self.bar_pos_x + 2

    def run(self):

    pygame.mouse.set_visible(0) #移动鼠标不可见

    bar_move_left =False

    bar_move_right = False

    while True:

    for event in pygame.event.get():

    if event.type == QUIT: #当按下关闭按键

    pygame.quit()

    sys.exit()#接收到退出事件后退出程序

    elif event.type == pygame.MOUSEBUTTONDOWN and event.button ==1:#鼠标左键按下

    bar_move_left = True

    elif event.type == pygame.MOUSEBUTTONUP and event.button == 1: #左键弹起

    bar_move_left = False

    elif event.type == pygame.MOUSEBUTTONDOWN and event.button == 3:#右键

    bar_move_right = True

    elif event.type == pygame.MOUSEBUTTONUP and event.button == 3: #左键弹起

    bar_move_right = False

    if bar_move_left == True and bar_move_right ==False:

    self.bar_move_left()

    if bar_move_left == False and bar_move_right == True:

    self.bar_move_right()

    self.screen.fill(bg_color)

    self.bar_pos.left = self.bar_pos_x

    pygame.draw.rect(self.screen, WHITE, self.bar_pos)

    ## 球移动

    self.ball_pos.bottom += self.ball_dir_y * 3

    pygame.draw.rect(self.screen, WHITE, self.ball_pos)

    ## 判断球是否落到板上

    if self.bar_pos.top <= self.ball_pos.bottom and (

    self.bar_pos.left <= self.ball_pos.right and self.bar_pos.right >= self.ball_pos.left):

    self.score += 1

    print("Score: ", self.score, end='\r')

    elif self.bar_pos.top <= self.ball_pos.bottom and (

    self.bar_pos.left > self.ball_pos.right or self.bar_pos.right < self.ball_pos.left):

    print("Game Over: ", self.score)

    return self.score

    ## 更新球下落的初始位置

    if self.bar_pos.top <= self.ball_pos.bottom:

    self.ball_pos_x = random.randint(0, SCREEN_SIZE[0] - BALL_SIZE[0])

    self.ball_pos_y = 0

    self.ball_pos = pygame.Rect(self.ball_pos_x, self.ball_pos_y, BALL_SIZE[0], BALL_SIZE[1])

    pygame.display.update()#更新软件界面显示

    self.clock.tick(60)

    game = Game()

    game.run()#启动

    展开全文
    weixin_34809884 2021-02-04 07:29:36
  • 点击查看象棋小游戏系列目录导航 流程图: 效果图: 主函数代码: import pygame from pygame.locals import * import sys import time import traceback import ChessPieces import random # 初始化 ...

    源码及资源请前往github获取
    如果觉得还不错的话,请赏个 star 呗。

    点击查看象棋小游戏系列目录导航

    流程图:
    这里写图片描述
    效果图:
    这里写图片描述
    主函数代码:

    import pygame
    from pygame.locals import *
    import sys
    import time
    import traceback
    import ChessPieces
    import random
    
    
    # 初始化
    pygame.init()
    try:
        pygame.mixer.init()
    except:
        print("您没有音频设备!")
        raise Exception
    
    bg_size = width,height = 474,663
    screen = pygame.display.set_mode(bg_size)
    bg_rect = screen.get_rect()
    pygame.display.set_caption("象棋小游戏")
    
    # 初始化音乐
    pygame.mixer.music.load('./sounds/bg.ogg')
    
    # 初始化图片
    
    chess_pan_img = pygame.image.load('./pic/chess_bg.png').convert()
    chess_select1_img = pygame.image.load('./pic/selected.png').convert()
    chess_select2_img = pygame.image.load('./pic/selected2.png').convert()
    
    # 初始化移动,翻棋子,吃棋子
    choosed = False
    
    # 初始化字体
    my_font = pygame.font.Font('./font/simhei.ttf',25)
    
    # 定义颜色
    WHITE = (255,255,255)
    BLACK = (0,0,0)
    GREEN = (0,255,0)
    RED = (255,0,0)
    BLUE = (0,0,255)
    
    # 象棋 1*将 + 2*(士+象+马+车+炮)+ 5 * 兵 = 一共16子*2 = 32 子
    chess_class = [] #[shi_chess,xiang_chess,ma_chess,che_chess,pao_chess]*2
    for j in range(2):
        for i in range(2):
            chess_class.append(ChessPieces.ShiChess(bg_rect))
            chess_class.append(ChessPieces.XiangChess(bg_rect))
            chess_class.append(ChessPieces.MaChess(bg_rect))
            chess_class.append(ChessPieces.CheChess(bg_rect))
            chess_class.append(ChessPieces.PaoChess(bg_rect))
    
        chess_class.append(ChessPieces.JiangChess(bg_rect))
        for i in range(5):
            chess_class.append(ChessPieces.ZuChess(bg_rect))
    
    # 一半的棋子为黑色
    for i in range(len(chess_class)//2):
        chess_class[i].role = ChessPieces.BLACK_ROLE
    
    running = True
    
    # 首先翻牌的为type 为 0
    player_role = ChessPieces.BLACK_ROLE
    
    def getChessList():
        # 产生随机数 0-31
        resultList = random.sample(range(0,32), 32);
        j = 0;
        #print('chess_class 的长度 %d  resultList 的长度 %d' % (len(chess_class),len(resultList)))
        for i in resultList:
            #print((i,j,chess_class[j].type))
            chess_class[j].position = (86+(i%4)*90, \
                                       66+((i//4))*71)
            chess_class[j].rect.left = 86+(i%4)*90
            chess_class[j].rect.top = 66+((i//4))*71
            #print(chess_class[j].position)
            j+=1
        return chess_class
    
    def is_chess_clicked(chess_list,event):
        for each in chess_list:
            if (each.rect.collidepoint(event.pos)):
                return each
        return None
    
    def operation_completed():
        global player_role
        if player_role == ChessPieces.BLACK_ROLE:
            player_role = ChessPieces.RED_ROLE
        else:
            player_role = ChessPieces.BLACK_ROLE
    
    def draw_text(text,font_color,center):
        mytext = my_font.render(text, True, font_color)
        text_rect = mytext.get_rect()
        text_rect.center = center
        screen.blit(mytext,text_rect)
    
    def main():
        global player_role
        overturn_count = 0
        # 初始化音乐
        pygame.mixer.music.play(-1)
        clock = pygame.time.Clock()
        # 获得打乱之后,并且有位置信息的对象数组
        chess_list = getChessList()
        selected_img_rect = chess_select1_img.get_rect()
        selected_img_rect.left = -20
        select_chess = None
        #is_start = False
    
        player1_role = ChessPieces.BLACK_ROLE
        player2_role = ChessPieces.BLACK_ROLE
    
        player1_color = BLACK
        player2_color = BLACK
        global running
    
        while running:
    
            # 首先绘制棋盘
            screen.blit(chess_pan_img, (10, 10))
    
            for event in pygame.event.get():
                if event.type == QUIT:
                    pygame.quit()
                    sys.exit()
                if event.type == MOUSEBUTTONDOWN:
                    if event.button == 1:# 按下鼠标左键
                        #print(event.pos)
                        selected = is_chess_clicked(chess_list,event)
                        #print(selected)
                        if selected is not None:
                            # 本次点击点击到了棋子
                            if selected.state == ChessPieces.CHOOSED_STATE:
                                pass
                            elif selected.state == ChessPieces.ACTIVE_STATE:
                                if player_role == selected.role:
                                    # 当前用户点击自己的棋子
                                    select_chess = selected
                                    selected.state = ChessPieces.ACTIVE_STATE
                                    selected_img_rect.left = selected.rect.left + 4
                                    selected_img_rect.top = selected.rect.top + 4
                                else:
                                    # 当前用户点击别人的棋子
                                    if select_chess is not None:
                                        # 判断是否可以吃该子
                                        if select_chess.eat(selected,event.pos,chess_list):
                                            operation_completed()
                                            select_chess = None
    
                            elif selected.state == ChessPieces.HIDDEN_STATE:
                                # 翻转
                                selected.state = ChessPieces.ACTIVE_STATE
                                selected_img_rect.left = selected.rect.left + 4
                                selected_img_rect.top = selected.rect.top + 4
                                #is_start = True  暂时认为该标签无用
                                if overturn_count == 0:
                                    player_role = selected.role
                                # 统计翻转的次数
                                overturn_count += 1
                                # 如果当前翻出的是对方的棋子,则 对方自动选中该子
                                if selected.role is not player_role:
                                    select_chess = selected
                                else:
                                    select_chess = None
                                # 翻转之后相当于一次操作完成
                                operation_completed()
                        else:
                            # 本次点击没有点击棋子,只是点击到了棋盘
                            print('本次点击没有点击棋子,只是点击到了棋盘')
                            print(select_chess)
    
                            if select_chess is not None:
                                # 判断被选中的棋子是否可以移动到当前位置
                                if select_chess.move(event.pos):
                                    operation_completed()
                                    select_chess=None
    
            # 绘制棋子
            for each in chess_list:
                #pass
                if each.state is not ChessPieces.DEAD_STATE:
                    screen.blit(each.getImage(each.role),each.rect)
                #print(each.position)
            #绘制被选中的图标
            #print(player_role)
            if player_role == ChessPieces.BLACK_ROLE:
                screen.blit(chess_select1_img, selected_img_rect)
            else:
                screen.blit(chess_select2_img, selected_img_rect)
    
            # 绘制当前玩家提示
            marked_words = ''
            font_color = RED
            if overturn_count == 1:
                print('---------------------------------111111')
                player1_role = player_role
                if player1_role == ChessPieces.BLACK_ROLE:
                    player1_color = BLACK
                else:
                    player1_color = RED
    
            if overturn_count == 2:
                print('---------------------------------222222')
                player2_role = player_role
                if player2_role == ChessPieces.BLACK_ROLE:
                    player2_color = BLACK
                else:
                    player2_color = RED
    
            if player_role == player1_role:
                marked_words = '玩家1'
                font_color = player1_color
            else:
                marked_words = '玩家2'
                font_color = player2_color
            # 确定颜色
            if overturn_count == 0:
                marked_words = '未选定颜色,请玩家1翻牌'
                font_color = GREEN
    
            draw_text(marked_words,font_color,(width // 2, 25))
    
            # 判断游戏是否结束
            # 方法,计算棋盘上存活的棋子数量,如果为零就,停止
            black_count = 0
            red_count = 0
            for each in chess_list:
                if each.state == ChessPieces.ACTIVE_STATE or each.state == ChessPieces.HIDDEN_STATE:
                    if each.role == ChessPieces.BLACK_ROLE:
                        black_count +=1
                    else:
                        red_count+=1
    
            if black_count == 0:
                # 红方胜利
                draw_text('红方胜利!',RED,(width//2,height//2))
            elif red_count ==0:
                # 黑方胜利
                draw_text('黑方胜利',BLACK,(width//2,height//2))
    
            pygame.display.flip()
            clock.tick(60)
    
    if __name__ == "__main__":
        try:
           main()
        except SystemExit:
            print("游戏正常退出")
        except:
            print("游戏退出异常")
            traceback.print_exc()
            pygame.quit()
            input()
    
    

    象棋类代码:ChessPieces.py

    import pygame
    from pygame.locals import *
    import math
    
    RED_ROLE = 0
    BLACK_ROLE = 1
    
    HIDDEN_STATE = 3
    ACTIVE_STATE = 4
    DEAD_STATE = 5
    CHOOSED_STATE = 6
    
    JIANG_TYPE = 11
    SHI_TYPE = 12
    XIANG_TYPE = 13
    CHE_TYPE = 14
    MA_TYPE = 15
    PAO_TYPE = 16
    ZU_TYPE = 17
    
    to_left = (-90,0)
    to_right = (90,0)
    to_up = (0,-66)
    to_down = (0,66)
    
    bg_image = pygame.image.load('./pic/blankchess.png')
    
    def can_eat(typea,typeb):
        if typea in (JIANG_TYPE,PAO_TYPE):
            return True
        elif typea in (SHI_TYPE,XIANG_TYPE,MA_TYPE,CHE_TYPE):
            if typea <= typeb:
                return True
        elif typea == ZU_TYPE:
            if typeb == JIANG_TYPE or typeb == ZU_TYPE:
                return True
        return False
    
    def can_move_one_step(self,pos):
        # 首先判断移动方向,然后进行移动
        # 判断移动方向
        # 判断是否在棋盘之内
        if pos[0] < 80 or pos[0] > 399 or pos[1] < 63 or pos[1] > 596:
            print("点击超出了范围")
        elif self.rect.left - 90 < pos[0] < self.rect.left - 50 and self.rect.top < pos[1] < self.rect.top + 50:
            # 需要向左移动一位
            self.rect.left -= 90
            print('需要向左移动一位')
            return True
        elif self.rect.left < pos[0] < self.rect.left + 40 and self.rect.top - 70 < pos[1] < self.rect.top - 40:
            # 需要向上移动一位
            self.rect.top -= 71
            print('需要向上移动一位')
            return True
        elif self.rect.left + 90 < pos[0] < self.rect.left + 130 and self.rect.top < pos[1] < self.rect.top + 40:
            # 需要向右移动一位
            self.rect.left += 90
            print('需要向右移动一位')
            return True
        elif self.rect.left < pos[0] < self.rect.left + 40 and self.rect.top + 70 < pos[1] < self.rect.top + 110:
            # 需要向下移动一位
            self.rect.top += 71
            print('需要向下移动一位')
            return True
    
    #-----------------------------------------------------------------------------------------1111 将
    class JiangChess:
        def __init__(self,rect):
            self.r_image = pygame.image.load('./pic/rshuai.png')
            self.b_image = pygame.image.load('./pic/bjiang.png')
            self.position = x,y = 86,66
            self.state = HIDDEN_STATE
            self.type = JIANG_TYPE
            self.role = RED_ROLE
            self.rect = self.b_image.get_rect()
    
    
        def getImage(self,role):
            if self.state == HIDDEN_STATE:
                return bg_image
            elif self.state == DEAD_STATE:
                return -1
            else:
                if role == RED_ROLE:
                    return self.r_image
                elif role == BLACK_ROLE:
                    return self.b_image
                else:
                    print('传入参数有误,无法判断是红方还是黑方!')
                    return -1
    
        def move(self,pos):
            return can_move_one_step(self,pos)
    
        # 将 可以吃 其它所有
        # 是否可吃需要满足两个条件
        # 1、是否满足该子的行走规律
        # 2、是否满足该子的吃子规律
        def eat(self,enemy_chess,pos,chess_list):
            if can_eat(self.type,enemy_chess.type):
                if self.move(pos):
                    self.rect.left = enemy_chess.rect.left
                    self.rect.top = enemy_chess.rect.top
                    enemy_chess.state = DEAD_STATE
                    enemy_chess.rect.left = -100
                    enemy_chess.rect.top = -100
                    return True
                else:
                    print('点击位置不在范围内,无法吃子')
            return False
    
    #----------------------------------------------------------------------------------------2222 士
    class ShiChess:
        def __init__(self,rect):
            self.r_image = pygame.image.load('./pic/rshi.png')
            self.b_image = pygame.image.load('./pic/bshi.png')
            self.position = x,y = 86,66
            self.state = HIDDEN_STATE
            self.type = SHI_TYPE
            self.role = RED_ROLE
            self.rect = self.b_image.get_rect()
    
        def getImage(self,role):
            if self.state == HIDDEN_STATE:
                return bg_image
            elif self.state == DEAD_STATE:
                return -1
            else:
                if role == RED_ROLE:
                    return self.r_image
                elif role == BLACK_ROLE:
                    return self.b_image
                else:
                    print('传入参数有误,无法判断是红方还是黑方!')
                    return -1
    
        def move(self,pos):
            return can_move_one_step(self,pos)
    
        # 将 可以吃 其它所有
        # 是否可吃需要满足两个条件
        # 1、是否满足该子的行走规律
        # 2、是否满足该子的吃子规律
        def eat(self,enemy_chess,pos,chess_list):
            if can_eat(self.type,enemy_chess.type):
                if self.move(pos):
                    self.rect.left = enemy_chess.rect.left
                    self.rect.top = enemy_chess.rect.top
                    enemy_chess.state = DEAD_STATE
                    enemy_chess.rect.left = -100
                    enemy_chess.rect.top = -100
                    return True
                else:
                    print('点击位置不在范围内,无法吃子')
            return False
    
    #----------------------------------------------------------------------------------------3333 象
    class XiangChess:
        def __init__(self,rect):
            self.r_image = pygame.image.load('./pic/rxiang.png')
            self.b_image = pygame.image.load('./pic/bxiang.png')
            self.position = x,y = 86,66
            self.state = HIDDEN_STATE
            self.type = XIANG_TYPE
            self.role = RED_ROLE
            self.rect = self.b_image.get_rect()
    
        def getImage(self,role):
            if self.state == HIDDEN_STATE:
                return bg_image
            elif self.state == DEAD_STATE:
                return -1
            else:
                if role == RED_ROLE:
                    return self.r_image
                elif role == BLACK_ROLE:
                    return self.b_image
                else:
                    print('传入参数有误,无法判断是红方还是黑方!')
                    return -1
    
        def move(self,pos):
            return can_move_one_step(self,pos)
    
        # 将 可以吃 其它所有
        # 是否可吃需要满足两个条件
        # 1、是否满足该子的行走规律
        # 2、是否满足该子的吃子规律
        def eat(self,enemy_chess,pos,chess_list):
            if can_eat(self.type,enemy_chess.type):
                if self.move(pos):
                    self.rect.left = enemy_chess.rect.left
                    self.rect.top = enemy_chess.rect.top
                    enemy_chess.state = DEAD_STATE
                    enemy_chess.rect.left = -100
                    enemy_chess.rect.top = -100
                    return True
                else:
                    print('点击位置不在范围内,无法吃子')
            return False
    
    #----------------------------------------------------------------------------------------4444 马
    class MaChess:
        def __init__(self,rect):
            self.r_image = pygame.image.load('./pic/rma.png')
            self.b_image = pygame.image.load('./pic/bma.png')
            self.position = x,y = 86,66
            self.state = HIDDEN_STATE
            self.type = MA_TYPE
            self.role = RED_ROLE
            self.rect = self.b_image.get_rect()
    
    
        def getImage(self,role):
            if self.state == HIDDEN_STATE:
                return bg_image
            elif self.state == DEAD_STATE:
                return -1
            else:
                if role == RED_ROLE:
                    return self.r_image
                elif role == BLACK_ROLE:
                    return self.b_image
                else:
                    print('传入参数有误,无法判断是红方还是黑方!')
                    return -1
    
        def move(self,pos):
            return can_move_one_step(self,pos)
    
        # 将 可以吃 其它所有
        # 是否可吃需要满足两个条件
        # 1、是否满足该子的行走规律
        # 2、是否满足该子的吃子规律
        def eat(self,enemy_chess,pos,chess_list):
            if can_eat(self.type,enemy_chess.type):
                if self.move(pos):
                    self.rect.left = enemy_chess.rect.left
                    self.rect.top = enemy_chess.rect.top
                    enemy_chess.state = DEAD_STATE
                    enemy_chess.rect.left = -100
                    enemy_chess.rect.top = -100
                    True
                else:
                    print('点击位置不在范围内,无法吃子')
            return False
    
    #-----------------------------------------------------------------------------------------5555 车
    class CheChess:
        def __init__(self,rect):
            self.r_image = pygame.image.load('./pic/rche.png')
            self.b_image = pygame.image.load('./pic/bche.png')
            self.position = x,y = 86,66
            self.state = HIDDEN_STATE
            self.type = CHE_TYPE
            self.role = RED_ROLE
            self.rect = self.b_image.get_rect()
    
    
        def getImage(self,role):
            if self.state == HIDDEN_STATE:
                return bg_image
            elif self.state == DEAD_STATE:
                return -1
            else:
                if role == RED_ROLE:
                    return self.r_image
                elif role == BLACK_ROLE:
                    return self.b_image
                else:
                    print('传入参数有误,无法判断是红方还是黑方!')
                    return -1
    
        def move(self,pos):
            return can_move_one_step(self,pos)
    
        # 将 可以吃 其它所有
        # 是否可吃需要满足两个条件
        # 1、是否满足该子的行走规律
        # 2、是否满足该子的吃子规律
        def eat(self,enemy_chess,pos,chess_list):
            if can_eat(self.type,enemy_chess.type):
                if self.move(pos):
                    self.rect.left = enemy_chess.rect.left
                    self.rect.top = enemy_chess.rect.top
                    enemy_chess.state = DEAD_STATE
                    enemy_chess.rect.left = -100
                    enemy_chess.rect.top = -100
                    return True
                else:
                    print('点击位置不在范围内,无法吃子')
            return False
    #----------------------------------------------------------------------------------------5555 炮
    class PaoChess:
        def __init__(self,rect):
            self.r_image = pygame.image.load('./pic/rpao.png')
            self.b_image = pygame.image.load('./pic/bpao.png')
            self.position = x,y = 86,66
            self.state = HIDDEN_STATE
            self.type = PAO_TYPE
            self.role = RED_ROLE
            self.rect = self.b_image.get_rect()
    
    
        def getImage(self,role):
            if self.state == HIDDEN_STATE:
                return bg_image
            elif self.state == DEAD_STATE:
                return -1
            else:
                if role == RED_ROLE:
                    return self.r_image
                elif role == BLACK_ROLE:
                    return self.b_image
                else:
                    print('传入参数有误,无法判断是红方还是黑方!')
                    return -1
    
        def move(self,pos):
           return can_move_one_step(self,pos)
    
        # 将 可以吃 其它所有
        # 是否可吃需要满足两个条件
        # 1、是否满足该子的行走规律
        # 2、是否满足该子的吃子规律
        def eat(self,enemy_chess,pos,chess_list):
            if can_eat(self.type,enemy_chess.type):
                if self.can_move_and_eat(enemy_chess,pos,chess_list):
                    self.rect.left = enemy_chess.rect.left
                    self.rect.top = enemy_chess.rect.top
                    enemy_chess.state = DEAD_STATE
                    enemy_chess.rect.left = -100
                    enemy_chess.rect.top = -100
                    return True
                else:
                    print('点击位置不在范围内,无法吃子')
            return False
    
        def can_move_and_eat(self,enemy_chess,pos,chess_list):
            # 首先判断,pos 和当前棋子是否在同一行或同一列
            # 然后判断,两个棋子之间有几个棋子
            if self.rect.left -10 < enemy_chess.rect.left < self.rect.left + 50:
                # 说明在同一列
                count = 0
                for each in chess_list:
                    if self.rect.left -10 < each.rect.left < self.rect.left + 50 \
                            and min(self.rect.center[1],enemy_chess.rect.center[1]) < \
                            each.rect.center[1] < max(self.rect.center[1],enemy_chess.rect.center[1]):
                        count+=1
                if count==1:
                    return True
            elif self.rect.top -10 < enemy_chess.rect.top < self.rect.top +50:
                # 说明在同一行
                count = 0
                for each in chess_list:
                    if self.rect.top -10 < each.rect.top < self.rect.top +50 and \
                            min(self.rect.center[0], enemy_chess.rect.center[0]) < \
                                each.rect.center[0] < max(self.rect.center[0], enemy_chess.rect.center[0]):
                        count += 1
                if count==1:
                    return True
            return False
    
    #----------------------------------------------------------------------------------------5555 卒
    class ZuChess:
        def __init__(self,rect):
            self.r_image = pygame.image.load('./pic/rbing.png')
            self.b_image = pygame.image.load('./pic/bzu.png')
            self.position = x,y = 86,66
            self.state = HIDDEN_STATE
            self.type = ZU_TYPE
            self.role = RED_ROLE
            self.rect = self.b_image.get_rect()
    
    
        def getImage(self,role):
            if self.state == HIDDEN_STATE:
                return bg_image
            elif self.state == DEAD_STATE:
                return -1
            else:
                if role == RED_ROLE:
                    return self.r_image
                elif role == BLACK_ROLE:
                    return self.b_image
                else:
                    print('传入参数有误,无法判断是红方还是黑方!')
                    return -1
    
        def move(self,pos):
            return can_move_one_step(self,pos)
    
        # 将 可以吃 其它所有
        # 是否可吃需要满足两个条件
        # 1、是否满足该子的行走规律
        # 2、是否满足该子的吃子规律
        def eat(self,enemy_chess,pos,chess_list):
            if can_eat(self.type,enemy_chess.type):
                if self.move(pos):
                    self.rect.left = enemy_chess.rect.left
                    self.rect.top = enemy_chess.rect.top
                    enemy_chess.state = DEAD_STATE
                    enemy_chess.rect.left = -100
                    enemy_chess.rect.top = -100
                    return True
                else:
                    print('点击位置不在范围内,无法吃子')
            return False
    
    
    展开全文
    chenxiaoping1993 2018-05-04 16:15:21
  • 62KB weixin_38582685 2020-09-19 09:28:37
  • 10KB qq_43098438 2018-10-26 21:55:53
  • 5星
    763KB qq_48484950 2020-06-10 09:21:50
  • PyGame是跨平台Python模块,专为电子游戏设计。包含图像、声音。创建在SDL基础上,允许实时电子游戏研发而无需被低端语言,如C语言或是更低端的汇编语言束缚。基于这样一个设想,所有需要的游戏功能和理念都(主要是...

    简介

    PyGame 是 SDL库的 Python包装器(wrapper)。SDL 是一个跨平台库,支持访问计算机多媒体硬件(声音,视频,输入等)。SDL 非常强大,但美中不足的是,它是基于 C语言的,而 C语言比较难懂,因此我们采用 PyGame!

    img

    在本文中,我们将介绍 PyGame的基本逻辑和冲突检测,以及如何在屏幕上绘图和将外部文件导入游戏中。

    准备工作

    执行 pip install pygame ,安装 Pygame库

    新建一个 .py文件,然后输入如下代码

    # 导入 pygame
    import pygame
    # 导入 pygame 中的一些常量
    from pygame.locals import *
    
    # 初始化所有导入的PyGame模块,在做其他操作之前必须调用该函数
    pygame.init()
    

    与其它 Python程序一样,我们首先导入想要使用的模块。这里,我们导入 pygame 和 pygame.locals ,后续我们将使用其中的一些常量。最后一行会初始化所有导入的 PyGame 模块,在做其它操作之前必须执行调用该函数!

    基础对象

    屏幕对象

    首先,我们需要一张画布,我们称之为 “屏幕”,它是我们绘画的平台。为了创建一个屏幕,我们需要调用 pygame.display 中的 set_mode 方法,然后向 set_mode() 传递包含屏幕窗口宽度和高度的元组

    import pygame
    from pygame.locals import *
    
    pygame.init()
    
    # 创建一个 800*600 的窗口
    screen = pygame.display.set_mode((800, 600))
    # 设置窗口名称
    pygame.display.set_caption("飞机大战")
    

    img

    运行上述代码,将会弹出一个窗口,然后又立即消失,一点都不酷嘛,对吧?

    下一节,我们将介绍游戏的主循环,它将确保只有在我们给它正确的输入时程序才会退出。

    游戏主循环

    游戏主循环/事件循环是所有操作放生的地方。在游戏过程中,它不断更新游戏状态,渲染游戏画面和收集输入指令。创建循环时,需要确保我们有办法跳出循环,退出应用。

    为此,我们将同时介绍一些基本的用户输入指令。所有的用户输入(和我们稍后提到的其它事件)都会进入 PyGame的事件队列,通过调用 pygame.event.get() 可以访问该队列。这将返回一个包含队列里所有事件的列表,我们循环这个列表,并针对相应的事件类型做出反应。现在,我们只关心 KEYDOWNQUIT 事件。

    # 用户保证主循环运行的变量
    running = True
    
    # 主循环
    while running:
        # for 循环遍历事件队列
        for event in pygame.event.get():
            # 检测 KEYDOWN 事件:KEYDOWN 是 pygame.locals 中定义的常量
            if event.type == KEYDOWN:
                # 如果按下 ESC 那么主循环停止
                if event.key == K_ESCAPE:
                    running = False
            # 如果用户点击 X ,终止主循环
            elif event.type == QUIT:
                running = False
    

    将上述代码添加到之前的代码下,并运行。应该会看到一个空的窗口,只有你按下 ESC键 或者出发一个 QUIT 事件,否则这个窗口不会消失。

    Surface 和 Rects

    Surface 和 Rects 是 PyGame 中的基本构件。可以将 Surface 看作一张白纸,你可以在上面随意绘画。我们的屏幕对象也是一个 Surface。它们可以包含图片。Rects 是 Surface 中矩形区域的表示。

    让我们创建一个 50*50 像素的 Surface,然后给它涂色。由于屏幕是黑色的,所以我们使用白色进行涂色,然后调用 get_rect() 在 Surface 上得到一个矩形区域和 Surface 的 x 轴 和 y 轴。

    # 创建 Surface 并设定它的长度和宽度
    surf = pygame.Surface((50, 50))
    # 设定 Surface 的颜色
    surf.fill((255, 255, 255))
    # 得到矩形区域及坐标
    rect = surf.get_rect()
    print(rect)
    # <rect(0, 0, 50, 50)>
    

    Blit 和 Flip

    仅仅只是创建了 Surface 并不能在屏幕上看到它。为此我们需要将这个 Surface绘制(Bilt)到另一个 Surface上Bilt是一个专业术语,意思就是绘图。你仅仅只能从一个 Surface Blit 到另一个 Surface 上,我们的屏幕对象就是一个 Surface 对象。以下是我们如何将 surf 画到屏幕上:

    # 将 surf 画到屏幕 x:400 , y:300的坐标上
    screen.blit(surf, (400, 300))
    # 更新屏幕
    pygame.display.flip()
    

    blit() 有两个参数:要画的 Surface 和在 源Surface 上的坐标。此处我们使用屏幕的中心,但是当你运行代码是,你会发现我们的 surf 并没有出现在屏幕的中心。这是因为 blit() 是从左上角开始画 surf

    注意在 blit之后的 pygame.display.filp() 的调用。flip将会更新自上次 flip后的整个屏幕,两次 flip之间发生的修改都会在屏幕上显示。没有调用 flip() 那就什么也不会出现!

    Sprites

    什么是 Sprites ? 从编程术语来讲,Sprites 是屏幕上事物的二维表法。本质上来讲,Sprites就是一个图片。

    Pygame提供一个叫做 Sprites 的基础类,他就是用来扩展的,可以包含想要在屏幕上呈现的对象一个或多个图形表示。我们将会扩展 Sprite 类,这样可以使用它的内建方法。我们称这个新的对象为 Player。

    Player将扩展 Sprite,现在只有两个属性:surd 和 rect,我们也会给 surf 涂色,如之前 Surface 例子,只是现在 Surface 属于 Player

    class Player(pygame.sprite.Sprite):
        def __init__(self):
            super(Player,self).__init__()
            self.surf = pygame.Surface((25,25))
            self.surf.fill((255,255,255))
            self.rect = self.surf.get_rect()
    

    现在我们将上述代码整合在一起:

    import pygame
    from pygame.locals import *
    
    pygame.init()
    
    screen = pygame.display.set_mode((800, 600))
    pygame.display.set_caption("飞机大战")
    
    
    class Player(pygame.sprite.Sprite):
        def __init__(self):
            super(Player, self).__init__()
            self.surf = pygame.Surface((25, 25))
            self.surf.fill((255, 255, 255))
            self.rect = self.surf.get_rect()
    
    
    player = Player()
    running = True
    
    while running:
        for event in pygame.event.get():
            if event.type == KEYDOWN:
                if event.key == K_ESCAPE:
                    running = False
            elif event.type == QUIT:
                running = False
    
            # 将 surf 画到屏幕上
            screen.blit(player.surf, (400, 300))
            pygame.display.flip()
    

    运行上述代码,你会在屏幕中心看到一个白色的矩形

    如果将 screen.blit(player.surf, (400, 300)) 改成 screen.blit(player.surf, player.rect) , 你觉得会发生什么?rect 的前两个属性分别是 rect 左上角的 x 和 y 轴坐标。当你将rect传递给blit,它会根据这个坐标画 surface。我们后续将使用它控制 player移动。

    用户输入

    现在开始才是最有趣的部分,我们要把 player 变得可控制。PyGame中有一个事件方法 pygame.key.get_pressed(),get_pressed()方法返回一个队列,其中包含了所有按键事件组成的元组,我们把它放在循环中,这样我们将获取每一帧的按键。

    pressed_keys = pygame.key.get_pressed()
    

    现在我们写一个方法,接收上面那个元组,并根据按下键定义 sprite的行为,代码如下:

        def update(self, keys):
            if keys[K_UP]:
                self.rect.move_ip((0, -5))
            if keys[K_DOWN]:
                self.rect.move_ip((0, 5))
            if keys[K_LEFT]:
                self.rect.move_ip((-5, 0))
            if keys[K_RIGHT]:
                self.rect.move_ip((5, 0))
    

    K_UPK_DOWNK_LEFTK_RIGHT 对应键盘上的 上,下,左,右 方向键。我们判断这些键是否按下,如果它为真,那么我们使用 move_ip() 方法朝响应的方向移动 rect。

    现在你可以使用方向键移动矩形块了,也许你注意到了,你可以将矩形块移出屏幕,这可能并不是你想要的,所以我们需要在 update() 方法中添加一些逻辑,检测矩阵的坐标是移出了屏幕;如果移出了边界,那么就将它放回在边界上。

        def update(self, keys):
            if keys[K_UP]:
                self.rect.move_ip((0, -5))
                # 如果 rect 的顶部超出边界 ,那么将它放回边界上
                self.rect.top = 0 if self.rect.top <= 0 else self.rect.top
            if keys[K_DOWN]:
                self.rect.move_ip((0, 5))
                self.rect.bottom = 600 if self.rect.bottom >= 600 else self.rect.bottom
            if keys[K_LEFT]:
                self.rect.move_ip((-5, 0))
                self.rect.left = 0 if self.rect.left <= 0 else self.rect.left
            if keys[K_RIGHT]:
                self.rect.move_ip((5, 0))
                self.rect.right = 800 if self.rect.right >= 800 else self.rect.right
    

    现在我们添加一些敌人!
    首先我们创建一个新的 sprite类,命名为 Enemy,依照创建 player的格式创建:

    class Enemy(pygame.sprite.Sprite):
        def __init__(self):
            super(Enemy, self).__init__()
            self.surf = pygame.Surface((25, 25))
            self.surf.fill((68, 236, 44))
            self.rect = self.surf.get_rect(x=random.randint(50, 400), y=400)
            self.speed = random.randint(5, 15)
    
        def update(self):
            self.rect.move_ip((0, -self.speed))
            if self.rect.bottom <= 0:
                self.kill()
    

    以上有几点需要说明。首先,当我们在 surface 上调用 get_rect 时,我们将 y 坐标设置为 400 , x 坐标为一个随机数,因为我们希望敌人随机出现。我们还是用 random 设置敌人的速度属性,这样敌人就有快有慢!

    敌人的 update() 方法没有参数限制(我们不关心敌人的输入),只要让它们向着屏幕上方以一定的速度移动就可以了。update 方法最后有一个 if语句检测敌人是否通过了屏幕上方边界。当它们通过边界后,我们调用 Sprite的内建方法 kill()删除它们,这样它们就不会再被渲染出来。

    kill不会释放被它们占用的内存,需要你确保不在引用它们,以便 Python的垃圾回收器回收。

    Groups

    PyGame 提供的另一个很有用的对象时 sprite的 Groups。诚如其名,是 Sprite的集合。为什么我们要使用 sprite.Groups 而不是列表呢?因为 sprite.Groups它有一些内建的方法,有助于解决碰撞和更新问题

    那现在就创建一个 Group,用来包含游戏中所有的 Sprite。我们也可以为敌人创建一个 Group。当我们调用 Sprite 的 kill() 方法时,会将其从所在的全部 Group 中删除。

    enemies = pygame.sprite.Group()
    all_sprites = pygame.sprite.Group()
    # 将 player 添加到 all_sprites 中
    all_sprites.add(player)
    

    现在有了 all_sprites 的 group,我们接着改变对象渲染方式,只要渲染 group中的所有对象即可:

    for entity in all_sprites:
        screen.blit(entity.surf, entity.rect)
    

    现在,任何放到 all_sprites 中的对象对会被渲染出来。

    自定义事件

    现在我们为敌人创建了一个 sprite.Group,但是并没有实际的敌人。那怎样才能在屏幕上出现敌人呢?我们当然可以在刚开始的时候创建一堆的敌人,但是这样游戏玩不了几秒。

    为此,我们创建一个自定义事件,它每隔几秒就会触发创建一批敌人。

    创建自定义事件十分容易,只要命名即可:

    ADDENEMY = pygame.USEREVENT + 1
    

    注意:自定义事件本质上就是整数常量,又因为比 USEREVENT 小的数值已经被内置函数占据,所以创建的自定义事件都要比 USEREVENT 大,这就是我们为什么设定它为 USEREVENT+1

    定义好事件之后,我们需要将它插入事件队列中,因为整个游戏过程中都要创建它们,所有我们还要设置一个定时器,可以通过 PyGame的 time() 实现

    pygame.time.set_timer(ADDENEMY, 250)
    

    注意:set_timer() 只能用来将事件插入到 PyGame 事件队列中,不能做其它任何事情。

    这行代码告诉 PyGame 每隔250毫秒触发一次 ADDENEMY 事件。这是在主游戏循环之外执行的,不过在整个游戏中都处于执行状态。现在我们添加一些监听事件的代码:

    for event in pygame.event.get():
        if event.type == KEYDOWN:
            if event.key == K_ESCAPE:
                running = False
        elif event.type == QUIT:
            running = False
        elif event.type == ADDENEMY:
            # 如果监听到 ADDENEMY事件,新建一个敌人,并添加至 enemys 中
            new_enemy = Enemy()
            enemys.add(new_enemy)
    

    现在我们会监听 ADDENEMY 事件,当它触发时,将创建一个 Enemy 类的实例。然后我们将实例添加到 enemys这个 Sprite Group(后续用它来检测碰撞

    碰撞

    这才是 PyGame 的魅力所在!写碰撞检测代码(collision code)很难,但是 PyGame 提供了很多碰撞检测方法,你可以在 这里 查看其中的一部分。本次使用 spritecollideany
    spritecollideany() 接收一个 Sprite对象和一个 Sprite.Group,检测 Sprite对象是否和Sprite.Group中的 Sprite 发生碰撞。这样我们就可以拿 player 和 敌人所在的 Sprite Group 对比,检测 player 是否被敌人 击中,代码实现如下:

    if pygame.sprite.spritecollideany(player, enemys):
        # 如果发生碰撞,玩家角色死亡!
        player.kill()
    

    完整案例

    目前完整代码如下:

    import random
    import pygame
    from pygame.locals import *
    
    # 初始化初始化所有导入的PyGame模块
    pygame.init()
    
    # 设置游戏窗口宽高
    W_WIDTH = 400
    W_HEIGHT = 600
    
    # 创建游戏窗口
    screen = pygame.display.set_mode((W_WIDTH, W_HEIGHT))
    # 设置窗口标题
    pygame.display.set_caption("别碰我!")
    
    
    class Player(pygame.sprite.Sprite):
        """玩家类"""
    
        def __init__(self):
            super(Player, self).__init__()
            self.surf = pygame.Surface((25, 25))
            self.surf.fill((255, 255, 255))
            self.rect = self.surf.get_rect(x=int(W_WIDTH / 2), y=50)
    
        def update(self, keys):
            """设置只能左右移动"""
            if keys[K_LEFT]:
                self.rect.move_ip((-5, 0))
                self.rect.left = 0 if self.rect.left <= 0 else self.rect.left
            if keys[K_RIGHT]:
                self.rect.move_ip((5, 0))
                self.rect.right = W_WIDTH if self.rect.right >= W_WIDTH else self.rect.right
    
    
    class Enemy(pygame.sprite.Sprite):
        """敌人类"""
    
        def __init__(self):
            super(Enemy, self).__init__()
            self.surf = pygame.Surface((25, 25))
            self.surf.fill((68, 236, 44))
            self.rect = self.surf.get_rect(x=random.randint(0, W_WIDTH), y=W_HEIGHT)
            self.speed = random.randint(5, 10)
    
        def update(self):
            self.rect.move_ip((0, -self.speed))
            if self.rect.bottom <= 0:
                self.kill()
    
    
    # 创建游戏背景 Surface
    background = pygame.Surface((W_WIDTH, W_HEIGHT))
    background.fill((0, 0, 0))
    
    # 创建users 玩家Group 以及 enemys 敌人Group
    enemys = pygame.sprite.Group()
    users = pygame.sprite.Group()
    player = Player()
    users.add(player)
    
    # 设置自定义事件
    ADDENEMY = USEREVENT + 1
    # 设置定时器每250ms生成一次自定义事件
    pygame.time.set_timer(ADDENEMY, 250)
    
    running = True
    # 控制游戏执行的速度
    clock = pygame.time.Clock()
    
    while running:
        # 设置游戏的帧速,每秒为60帧
        clock.tick(60)
        # 获取按键事件
        pressed_keys = pygame.key.get_pressed()
    
        # 绘制背景
        screen.blit(background, (0, 0))
        # 绘制users Group
        for user in users:
            screen.blit(user.surf, user.rect)
            player.update(pressed_keys)
        # 绘制enemys Group
        for enemy in enemys:
            screen.blit(enemy.surf, enemy.rect)
            enemy.update()
    
        # 监听事件
        for event in pygame.event.get():
            if event.type == KEYDOWN:
                if event.key == K_ESCAPE:
                    running = False
            elif event.type == QUIT:
                running = False
            elif event.type == ADDENEMY:
                new_enemy = Enemy()
                enemys.add(new_enemy)
                # print(enemys)
    
        # 碰撞检测
        if pygame.sprite.spritecollideany(player, enemys):
            player.kill()
            print("GAME OVER!!!!")
            running = False
    
        # 更新屏幕
        pygame.display.flip()
    

    最终我们实现的效果如下:

    在这里插入图片描述

    展开全文
    qq_36078992 2020-04-22 22:29:19
  • qq_45279235 2021-10-27 21:15:40
  • 89KB weixin_38703277 2020-09-19 22:30:12
  • 105KB weixin_38649091 2020-09-16 10:01:01
  • 4.39MB qq_41828603 2019-03-01 20:15:37
  • SouthGiserr 2021-08-05 19:24:40
  • weixin_39522698 2020-12-23 11:45:36
  • weixin_55822277 2021-09-07 13:51:47
  • weixin_39627481 2020-11-20 21:11:40
  • hongbin_xu 2017-06-20 15:06:55

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 9,598
精华内容 3,839
关键字:

pygame小游戏代码