这届世界杯是不是让你出乎意料?写个足球小游戏来模拟一下!

前言

      今年世界杯有人欢喜有人愁,我想愁的人应该居多,不得不说,小日本是真菜啊,特么的!

今天还是搞点咱们好玩点的,世界杯嘛,大家看看就行,大家不是都说,看国足比看相声还搞笑吗?

 好了,不笑了。今天给大家带来一款非常简单的足球小游戏,希望大家喜欢,也喜欢大家能在这次世界杯旗开得胜。如果喜欢的话,点点小赞呗

开发工具

Python版本:3.7.8

相关模块:

pygame模块;

以及一些python自带的模块。

环境搭建

安装Python并添加到环境变量,pip安装需要的相关模块即可。

游戏实现

这里简单介绍一下原理吧,首先我们整个简单的开始界面吧:

'''定义游戏开始界面'''
def StartInterface(screen, resource_loader, cfg):
    clock = pygame.time.Clock()
    font, flag, count = resource_loader.fonts['default30'], True, 0
    font_render = font.render('按任意键开始游戏', False, cfg.RED)
    while True:
        count += 1
        if count > 20: count, flag = 0, not flag
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                QuitGame()
            elif event.type == pygame.KEYDOWN:
                return True
        screen.blit(resource_loader.images['background_start'], (0, 0))
        if flag: screen.blit(font_render, ((cfg.SCREENSIZE[0] - font.size('按任意键开始游戏')[0]) // 2, cfg.SCREENSIZE[1] - 200))
        clock.tick(cfg.FPS)
        pygame.display.update()

效果大概是这样子的:

 

方便起见,我们设置成了按任意键都可以开始游戏。

接下来,我们来定义一下球员类,球员分为电脑自动控制和我们手动控制两种类型,其中我们手动控制的核心代码如下:

 


'''更新'''
def update(self, screen_size, ball):
    # 电脑自动控制
    if self.auto_control:
        self.autoupdate(screen_size, ball)
        return
    # 静止状态
    if not self.is_moving: return
    # 切换人物动作实现动画效果
    self.switch()
    # 根据方向移动人物
    ori_position = self.position.copy()
    speed = self.speed * self.direction[0], self.speed * self.direction[1]
    self.position[0] = min(max(0, self.position[0] + speed[0]), screen_size[0] - 48)
    self.position[1] = min(max(0, self.position[1] + speed[1]), screen_size[1] - 48)
    self.rect.left, self.rect.top = self.position
    if self.rect.bottom > 305 and self.rect.top < 505 and (self.rect.right > 1121 or self.rect.left < 75):
        self.position = ori_position
        self.rect.left, self.rect.top = self.position
    # 设置为静止状态
    self.is_moving = False

电脑自动控制的核心代码如下:


'''自动更新'''
def autoupdate(self, screen_size, ball):
    # 守门员
    if self.player_type == 'goalkeeper':
        self.speed = 1
        # --沿着门漫步
        def wondering(self):
            self.switch()
            self.position[1] = min(max(305, self.position[1] + self.direction[1] * self.speed), 459)
            self.rect.left, self.rect.top = self.position
            if self.rect.top == 305 or self.rect.top == 459: 
                self.direction = self.direction[0], -self.direction[1]
                self.setdirection(self.direction)
        # --有球就随机射球
        if ball.taken_by_player == self:
            if self.group_id == 1:
                if random.random() > 0.8 or self.prepare_for_kicking:
                    self.prepare_for_kicking = True
                    self.setdirection((1, 0))
                    if self.prepare_for_kicking:
                        self.prepare_for_kicking_count += 1
                        if self.prepare_for_kicking_count > self.prepare_for_kicking_freq:
                            self.prepare_for_kicking_count = 0
                            self.prepare_for_kicking = False
                            ball.kick(self.direction)
                            self.setdirection(random.choice([(0, 1), (0, -1)]))
                else:
                    wondering(self)
            else:
                if random.random() > 0.8 or self.prepare_for_kicking:
                    self.prepare_for_kicking = True
                    self.setdirection((-1, 0))
                    if self.prepare_for_kicking:
                        self.prepare_for_kicking_count += 1
                        if self.prepare_for_kicking_count > self.prepare_for_kicking_freq:
                            self.prepare_for_kicking_count = 0
                            self.prepare_for_kicking = False
                            ball.kick(self.direction)
                            self.setdirection(random.choice([(0, 1), (0, -1)]))
                else:
                    wondering(self)
        # --没球来回走
        else:
            wondering(self)
    # 其他球员跟着球走
    else:
        if ball.taken_by_player == self:
            self.switch()
            if self.group_id == 1:
                self.direction = min(max(1150 - self.rect.left, -1), 1), min(max(405 - self.rect.top, -1), 1)
            else:
                self.direction = min(max(350 - self.rect.left, -1), 1), min(max(405 - self.rect.top, -1), 1)
            self.setdirection(self.direction)
            if (random.random() > 0.9 and self.position[0] > 350 and self.position[0] < 1150) or self.prepare_for_kicking:
                if self.group_id == 1:
                    self.direction = min(max(1190 - self.rect.left, -1), 1), min(max(405 - self.rect.top, -1), 1)
                else:
                    self.direction = min(max(310 - self.rect.left, -1), 1), min(max(405 - self.rect.top, -1), 1)
                self.setdirection(self.direction)
                self.prepare_for_kicking = True
                if self.prepare_for_kicking:
                    self.prepare_for_kicking_count += 1
                    if self.prepare_for_kicking_count > self.prepare_for_kicking_freq:
                        self.prepare_for_kicking_count = 0
                        self.prepare_for_kicking = False
                        ball.kick(self.direction)
            else:
                speed = self.speed * self.direction[0], self.speed * self.direction[1]
                ori_position = self.position.copy()
                self.position[0] = min(max(0, self.position[0] + speed[0]), screen_size[0] - 48)
                self.position[1] = min(max(0, self.position[1] + speed[1]), screen_size[1] - 48)
                self.rect.left, self.rect.top = self.position
                if self.rect.bottom > 305 and self.rect.top < 505 and (self.rect.right > 1121 or self.rect.left < 75):
                    self.position = ori_position
                    self.rect.left, self.rect.top = self.position
        else:
            self.switch()
            if (ball.rect.centery > 400 and self.player_type == 'bottomhalf') or (ball.rect.centery <= 400 and self.player_type == 'upperhalf') or self.player_type == 'common':
                self.direction = min(max(ball.rect.left - self.rect.left, -1), 1), min(max(ball.rect.top - self.rect.top, -1), 1)
                self.direction = self.direction[0] * random.random(), self.direction[1] * random.random()
            else:
                if self.keep_direction_count >= self.keep_direction_freq:
                    self.direction = random.choice([-1, 0, 1]), random.choice([-1, 0, 1])
                    self.keep_direction_count = 0
                else:
                    self.keep_direction_count += 1
            self.setdirection(self.direction)
            speed = self.speed * self.direction[0], self.speed * self.direction[1]
            ori_position = self.position.copy()
            self.position[0] = min(max(0, self.position[0] + speed[0]), screen_size[0] - 48)
            self.position[1] = min(max(0, self.position[1] + speed[1]), screen_size[1] - 48)
            self.rect.left, self.rect.top = self.position
            if self.rect.bottom > 305 and self.rect.top < 505 and (self.rect.right > 1121 or self.rect.left < 75):
                self.position = ori_position
                self.rect.left, self.rect.top = self.position

逻辑比较简单,大概是这样子的:

  • 守门员:就在球门边上来回走

  • 负责上半场的球员:在上半场出现球的时候就往球的位置移动,如果捕获到了球,则往对方球门移动并随机射门,否则随机移动;

  • 负责下半场的球员:在下半场出现球的时候就往球的位置移动,如果捕获到了球,则往对方球门移动并随机射门,否则随机移动;

  • 负责全场的球员:往球的位置移动,果捕获到了球,则往对方球门移动并随机射门。

接下来定义一下足球类:


'''定义足球类'''
class Ball(pygame.sprite.Sprite):
    def __init__(self, images, position):
        pygame.sprite.Sprite.__init__(self)
        self.images = images
        self.image = self.images[0]
        self.rect = self.image.get_rect()
        self.rect.centerx, self.rect.centery = position
        self.mask = pygame.mask.from_surface(self.image)
        # 球的速度
        self.speed = 0
        # 球的方向
        self.direction = [0, 0]
        # 控制球的球员
        self.taken_by_player = None
        # 用于切换球动作的变量
        self.action_pointer = 0
        self.count = 0
        self.switch_frequency = 3
        # 是否在运动状态
        self.is_moving = False
    '''更新'''
    def update(self, screen_size):
        # 静止状态
        if not self.is_moving: return
        # 切换球动作实现动画效果
        self.count += 1
        if self.count == self.switch_frequency:
            self.count = 0
            self.action_pointer = (self.action_pointer + 1) % len(self.images)
            self.image = self.images[self.action_pointer]
        # 如果球是被球员控制的
        if self.taken_by_player is not None:
            self.setdirection(self.taken_by_player.direction)
            if self.taken_by_player.direction[0] < 0:
                self.rect.left, self.rect.top = self.taken_by_player.rect.left - 15, self.taken_by_player.rect.top + 30
            elif self.taken_by_player.direction[0] > 0:
                self.rect.left, self.rect.top = self.taken_by_player.rect.left + 30, self.taken_by_player.rect.top + 30
            elif self.taken_by_player.direction[1] < 0:
                self.rect.left, self.rect.top = self.taken_by_player.rect.left + 15, self.taken_by_player.rect.top - 15
            elif self.taken_by_player.direction[1] > 0:
                self.rect.left, self.rect.top = self.taken_by_player.rect.left + 10, self.taken_by_player.rect.top + 50
            return
        # 根据方向移动球
        ori_position = self.rect.left, self.rect.right, self.rect.top, self.rect.bottom
        self.speed = max(self.speed - 1.7 * 0.05, 0.0)
        if self.speed == 0.0: self.is_moving = False
        vector = [self.speed * self.direction[0], self.speed * self.direction[1]]
        vector[0] = vector[0] / math.pow(self.direction[0] ** 2 + self.direction[1] ** 2, 0.5)
        vector[1] = vector[1] / math.pow(self.direction[0] ** 2 + self.direction[1] ** 2, 0.5)
        self.rect.left = min(max(0, self.rect.left + vector[0]), screen_size[0] - 48)
        if self.rect.left == 0 or self.rect.left == screen_size[0] - 48: 
            self.direction = self.direction[0] * -0.8, self.direction[1]
        self.rect.top = min(max(0, self.rect.top + vector[1]), screen_size[1] - 48)
        if ori_position[1] > 1121 or ori_position[0] < 75:
            if self.rect.bottom > 305 and self.rect.top < 505:
                if self.direction[1] > 0:
                    self.rect.bottom = 305
                    self.direction = self.direction[0], self.direction[1] * -0.8
                elif self.direction[1] < 0:
                    self.rect.top = 505
                    self.direction = self.direction[0], self.direction[1] * -0.8
        if self.rect.top == 0 or self.rect.top == screen_size[1] - 48:
            self.direction = self.direction[0], self.direction[1] * -0.8
    '''设置方向'''
    def setdirection(self, direction):
        self.is_moving = True
        self.direction = direction
    '''踢球'''
    def kick(self, direction):
        self.speed = 12
        self.direction = direction
        self.taken_by_player = None
        self.is_moving = True
    '''在屏幕上显示'''
    def draw(self, screen):
        screen.blit(self.image, self.rect)

比较简单,主要就是两种状态:

  • 被球员捕获,跟着球员走;

  • 被球员踢出去之后根据球员踢的方向和设定的初速度进行减速运动,如果碰到边界则反方向弹出。

最后写个主循环就大功告成啦:

# 游戏主循环
clock = pygame.time.Clock()
while True:
    # --基础背景绘制
    screen.fill(cfg.LIGHTGREEN)
    pygame.draw.circle(screen, cfg.WHITE, (600, 400), 80, 5)
    pygame.draw.rect(screen, cfg.WHITE, (10, 10, 600, 790), 5)
    pygame.draw.rect(screen, cfg.WHITE, (600, 10, 590, 790), 5)
    pygame.draw.rect(screen, cfg.WHITE, (10, 150, 300, 500), 5)
    pygame.draw.rect(screen, cfg.WHITE, (890, 150, 300, 500), 5)
    screen.blit(resource_loader.images['doors'][0].convert(), (8, 305))
    screen.blit(resource_loader.images['doors'][1].convert(), (1121, 305))
    screen.blit(score_board, (565, 15))
    # --事件监听
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            QuitGame()
        elif event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE:
            QuitGame()
    pressed_keys = pygame.key.get_pressed()
    direction = [0, 0]
    if pressed_keys[pygame.K_w]: direction[1] -= 1
    if pressed_keys[pygame.K_d]: direction[0] += 1
    if pressed_keys[pygame.K_s]: direction[1] += 1
    if pressed_keys[pygame.K_a]: direction[0] -= 1
    if direction != [0, 0]: player_controlled.setdirection(direction)
    if pressed_keys[pygame.K_SPACE] and player_controlled == ball.taken_by_player: 
        ball.kick(player_controlled.direction)
    # --更新玩家
    for item in players_group1:
        if pygame.sprite.collide_mask(item, ball) and ball.taken_by_player != item: 
            ball.is_moving = True
            ball.taken_by_player = item
    for item in players_group2:
        if pygame.sprite.collide_mask(item, ball) and ball.taken_by_player != item: 
            ball.is_moving = True
            ball.taken_by_player = item
    for item in players_group1:
        item.update(cfg.SCREENSIZE_GAMING, ball)
    for item in players_group2:
        item.update(cfg.SCREENSIZE_GAMING, ball)
    # --更新球
    ball.update(cfg.SCREENSIZE_GAMING)
    # --更新屏幕
    ball.draw(screen)
    players_group1.draw(screen)
    players_group2.draw(screen)
    clock.tick(cfg.FPS)
    pygame.display.update()
    # --计算得分
    if ball.rect.bottom > 305 and ball.rect.top < 505:
        if ball.rect.right > 1121: return 1
        elif ball.rect.left < 75: return 2

比较简单,就不过多介绍了,按WASD控制上下左右,空格键射门。

完整源代码详见相关文件~

效果展示

首先安装最新版本的cpgames:

pip install cpgames==0.1.2

然后写如下代码调用即可运行:

from cpgames import cpgames
game_client = cpgames.CPGames()game_client.execute('bloodfootball')

 效果展示

 是不是很简单吗,是个非常简易版的游戏,适合和自己的小孩边看世界杯边玩,谢谢大家观看到这里,需要源代码的可以关注下方小卡片哦,点点赞呗。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值