python制作小游戏之二2048第一部分

最近闲来无事,做了一个2048类似的小游戏。其中的算法思想,如果有的话,都是本人花了一点点时间想出来的,完全没有参考任何教程,所以可能(其实是肯定)使用的方法比较傻一些,算是抛砖引玉了。

为了制作这个游戏,我先下载了一个2048小游戏来玩,以便学习规则。根据20分钟的游玩体验,我总结的规则大致如下:

  1. 4*4方格。
  2. 游戏开始时出现2个2。
  3. 然后每移动一次出现新的2,如果某个方向无法移动,则不会增加新的2。
  4. 只有相同的数字才能够相加。
  5. 新增的只会出现2
  6. 相加时,只会加一次,不会累加。不知道为啥。
  7. 游戏结束检查没有空位且任意数字周围都没有相同数字,如果都没有,则游戏结束。
  8. 敏感的察觉到不需要外部图片素材,只需要画框还有画数字即可。
  9. 动画过程应该最麻烦,pygame画动画我是没什么信心。

因为之前做了好多这种类似的棋盘类型的游戏,比如扫雷,五子连珠(有机会一并写出来),所以画2048的棋盘部分格外容易,难点在配色,好在我是不在乎颜色好看与否,所以直接开始弄。

首先依然是基础的pygame配置代码,涉及到各种初始化配置,颜色代码等等,边距一大堆,基本基本上棋盘游戏我都是通用的,修改一下就可以用了。

import pygame
import sys
import random
from pygame.locals import *
board_width = 4
board_height = 4
tile_size = 80
screen_width = 640
screen_height = 480
fps = 30


white = (255, 255, 255)
bright_blue = 'sky blue'
dark_turquoise = (250, 234, 211)
green = 'green'

bg_color = (107, 81, 82)
tile_color = bright_blue
text_color = (144, 59, 28)
border_color = bright_blue
basic_font_size = 30
message_color = white
x_margin = int((screen_width-(tile_size*board_width + (board_width-1)))/2)
y_margin = int((screen_height-(tile_size*board_height + (board_height - 1)))/2)

up = 'up'
down = 'down'
left = 'left'
right = 'right'

# 四个方向
directions = [(0, 1), (0, -1), (-1, 0), (1, 0)]

来一个主函数,把pygame框架搭起来

if __name__ == '__main__':

    pygame.init()
    fps_clock = pygame.time.Clock()
    display = pygame.display.set_mode((screen_width, screen_height))
    pygame.display.set_caption('2048')
    basic_font = pygame.font.Font('freesansbold.ttf', basic_font_size)

    while True:
        for event in pygame.event.get():
           if event.type == QUIT:
                pygame.quit()
        pygame.display.update()
        fps_clock.tick(fps)

运行后的样子
请添加图片描述

接下来编写一个生成二维列表的函数,生成的二维列表即对应了游戏界面,直接对应游戏界面。比如说二维列表长这样
[
[0, 2, 0, 2],
[0, 0, 0, ],
[0, 0, 0, 0],
[0, 0, 0, 0]
]
那么我们使用pygame绘制的时候所有0的位置都是空白的小块,而有数字的地方则会直接绘制数字,并且位置与二维列表位置一一对应。即二维列表[0][0]对应左上角第一个小块,[3][3]对应右下角最后一个小块。这样对应的好处是直观,劣势是我们需要计算小块的横纵坐标也就是在pygame界面中的位置时,第一个下标是用来计算y值即纵向位置,第二个下标用来计算x数值即横向位置,这与一般认知相矛盾,这是容易搞错的地方。

现在来写生成二维列表的函数,比较简单,先生成一个数值全为None的列表,然后,在随机位置生成两个数值2。然后返回这个二维列表的值。

def get_starting_board():
    counter = 2
    board = [[None for _ in range(board_width)] for _ in range(board_height)]
    while counter > 0:
        random_x = random.randint(0, board_height-1)
        random_y = random.randint(0, board_width-1)
        if board[random_x][random_y] is None:
            board[random_x][random_y] = 2
            counter -= 1
    return board

这样我们生成了一个二维列表并且随机生成了数字2所在位置。接下来还不能直接开始绘制小块,我们还需要一个函数把二维列表的下标转换成实际在pygmae中的位置。

x_margin = int((screen_width-(tile_size*board_width + (board_width-1)))/2)
y_margin = int((screen_height-(tile_size*board_height + (board_height - 1)))/2)

这是已经定义好的横纵方向的间距,利用这个间距以及计算得出二维列表每一个元素在pygame游戏界面即棋盘中的位置。

# 将board[x][y]转为游戏屏幕对应的坐标点
def get_left_top_of_tile(x, y):
    left = x_margin + y * tile_size + (y - 1)
    top = y_margin + x * tile_size + (x - 1)
    return left, top

终于可以开始编写绘制函数了,该函数根据二维列表的数据内容绘制相应的图形到指定位置。

# 绘制游戏背景面板,此处开始根据board中的内容绘制游戏主界面了,一开始绘制的是已经完成好的界面
def draw_board(board, message):
# 填充背景
    display.fill(bg_color)
    # 如果有信息,则将信息写在左上角
    if message:
        text_surf, text_rect = make_text(message, message_color, bg_color, 0, 0)
        display.blit(text_surf, text_rect)
    # 遍历二维列表中所有内容,绘图
    for x in range(board_width):
        for y in range(board_height):
            if board[x][y]:
            # 如果有数字则绘制数字
                draw_tile(x, y, board[x][y])
            else:
            # 否则仅绘制小块
                draw_tile(x, y, '')

    # 绘制游戏边框
    left, top = get_left_top_of_tile(0, 0)
    width = board_width * tile_size
    height = board_height * tile_size
    # 边框不要和滑片重合,所以稍微往四周挪动一点距离
    pygame.draw.rect(display, border_color, (left-11, top-11, width+16, height+16), 4)
   

接下来最底层的绘制图形函数

#绘制游戏界面上的小滑片,其中adj_x,y偏移量是用来后期做动#画用的
def draw_tile(board_x, board_y, number, adj_x=0, adj_y=0):
#获取实际位置
    left, top = get_left_top_of_tile(board_x, board_y)
    # 画出滑片的背景色,即一个填充了颜色的矩形

    # 在同样的位置显示滑片对应的数字,即board[x][y]中对应的数字
    # 画数字时修改了一下位置,看起来更合适一些
    if number:
        pygame.draw.rect(display, dark_turquoise, (left + adj_x, top + adj_y, tile_size - 10, tile_size - 10))
        text_surf = basic_font.render(str(number), True, text_color)
        text_rect = text_surf.get_rect()
        text_rect.center = left + int((tile_size-10)/2) + adj_x, top + int((tile_size-10)/2) + adj_y
        # text_rect.center = left + adj_x, top + adj_y
        display.blit(text_surf, text_rect)
    else:
        pygame.draw.rect(display, bright_blue, (left + adj_x, top + adj_y, tile_size - 10, tile_size - 10))

然后在定义一个综合的生成游戏界面的函数

# 创建新游戏谜题
def generate_new_puzzle():

   board = get_starting_board()
   draw_board(board, '')
   pygame.display.update()
   pygame.time.wait(500)
   last_move = None

   return board

在主函数中调用并获得二维列表

if __name__ == '__main__':

   pygame.init()
   fps_clock = pygame.time.Clock()
   display = pygame.display.set_mode((screen_width, screen_height))
   pygame.display.set_caption('2048')
   basic_font = pygame.font.Font('freesansbold.ttf', basic_font_size)

   # 配置三个按键位置以及颜色,大小
   # reset_surf, reset_rect = make_text('Reset', text_color, tile_color, screen_width - 120, screen_height - 90)
   main_board = generate_new_puzzle()
   while True:
       for event in pygame.event.get():
           if event.type == QUIT:
               pygame.quit()
       pygame.display.update()
       fps_clock.tick(fps)

运行程序,开始有点意思了
请添加图片描述

待续…

猜你喜欢

转载自blog.csdn.net/jackwsd/article/details/126429853