用pygame制作的我的世界2D版

 

"""用pygame制作的我的世界2D版,作者李兴球,游戏操作:按空格键捡东西,按数字键放东西,按数字键同时单击鼠标左键合成物质,合成规则见下面代码。"""

import time
import random
import pygame,sys
from pygame.locals import *

class Role(pygame.sprite.Sprite):
    def __init__(self,images):
        pygame.sprite.Sprite.__init__(self)
        self.images = [pygame.image.load(image) for image in images]                
        self.index = 0
        self.image = self.images[self.index]   # 初始造型为上       
        self.playerPos = [0,0]
    def set_costume(self,index):
        self.image = self.images[index]        # 初始造型为上    
        
class Effect(pygame.sprite.Sprite):
    def __init__(self,images,position,group):
        """参数说明:
           images:转换成surface的列表
           position:坐标双元组,效果生成的坐标
           group:自己所在的组(效果组)
        """
        pygame.sprite.Sprite.__init__(self)
        self.images = images
        self.index = 0                         # 起始造型索引      
        self.amounts = len(self.images)        # 总共造型数量
        self.interval = 0.1                    # 造型切换间隔时间(秒)
        self.begin_time = time.time()          # 造型切换起始时间
        self.image = self.images[0]            # 起始造型
        self.rect = self.image.get_rect()      # 矩形对象(用来表示坐标和图形宽高)
        self.rect.center = position            # 矩形对象的中心点坐标
        self.group = group                     # 可引用自己所在的组
        self.group.add(self)                   # 添加进自己所在的组中
        
    def update(self):
        """切换造型"""
        self.rect.move_ip(0,-12)                # 向上移动
        if self.rect.bottom >=0 :
            self.image = self.images[self.index]
            if time.time() - self.begin_time >=0 : # 超时则索引加1,
               self.index = self.index + 1
               self.index = self.index % self.amounts 
               self.begin_time = time.time()       # 起始时间要重设
        else:
            self.group.remove(self)
    
BLACK = (0,0,0)
BROWN = (153,76,0)
GREEN = (0,255,0)
BLUE = (0,0,255)
WHITE = (255,255,255)

cloudx = -200
cloudy = 0

DIRT = 0
GRASS = 1
WATER = 2
COAL = 3
CLOUD = 4
WOOD = 5
FIRE = 6
SAND = 7
GLASS = 8
ROCK  = 9
STONE = 10
BRICK = 11
DIAMOND = 12

textures = {
           DIRT : pygame.image.load('dirt.png'),
           GRASS: pygame.image.load('grass.png'),
           WATER: pygame.image.load('water.png'),
           COAL : pygame.image.load('coal.png'),
           CLOUD: pygame.image.load('cloud.png'),
           WOOD : pygame.image.load('wood.png'),
           FIRE : pygame.image.load('fire.png'),
           SAND : pygame.image.load('sand.png'),
           GLASS: pygame.image.load('glass.png'),
           ROCK : pygame.image.load('rock.png'),
           STONE: pygame.image.load('stone.png'),
           BRICK: pygame.image.load('brick.png'),
           DIAMOND:pygame.image.load('diamond.png')
          }

inventory = {
               DIRT : 0,
               GRASS: 0,
               WATER: 0,
               COAL : 0,
               WOOD : 0,
               FIRE : 0,
               SAND : 0,
               GLASS: 0,
               ROCK : 0,
               STONE: 0,
               BRICK: 0,
               DIAMOND:0
            }
res_names = {
               DIRT : "地面",
               GRASS: "草皮",
               WATER: "水面",
               COAL : "碳黑",
               WOOD : "木片",
               FIRE : "火把",
               SAND : "沙粒",
               GLASS: "玻璃",
               ROCK : "岩石",
               STONE: "石头",
               BRICK: "砖块",
               DIAMOND:"钻石"
            }

TILESIZE = 20
MAPWIDTH = 50
MAPHEIGHT = 20
 
play_images = ['player_up.png','player_down.png','player_left.png','player_right.png'] # 上下左右图

PLAYER = Role(play_images)   # 它有属性playerPos和images,用于坐标定位和图像渲染

resource = [DIRT,GRASS,WATER,COAL,WOOD,FIRE,SAND,GLASS,ROCK,STONE,BRICK,DIAMOND]  # 显示在下栏的资源种类

tilemap = [ [DIRT for w in range(MAPWIDTH)] for h in range(MAPHEIGHT) ]           # 初始化方块地图,都是DIRT

"以下是在方块地图上分配资源,"
for rw in range(MAPHEIGHT):                                                      
    for cl in range(MAPWIDTH):
        randomNumber = random.randint(0,20)
        if randomNumber == 0:                           # 随机数为0 分配的是 炭
            tile = COAL
        elif randomNumber ==1 or randomNumber < 5:      # 1,2,3,4分配的是 水
            tile = WATER
        elif randomNumber >=5 and randomNumber <=6:     # 5,6分配的是 沙
            tile = SAND
        elif randomNumber > 6 and randomNumber <9:      # 7,8分配的 木
            tile = WOOD            
        elif randomNumber > 9 and randomNumber <13:     # 10,11,12分配 岩石
            tile = ROCK
        elif randomNumber >= 13 and randomNumber <17:   # 13,14,15,16 草皮 
            tile = GRASS          
        else:
            tile = DIRT                               
        tilemap[rw][cl] = tile
        
controls = {
             DIRT   : 49,           # 1键
             GRASS  : 50,           # 2键  
             WATER  : 51,           # 3键 
             COAL   : 52,           # 4键
             WOOD   : 53,           # 5键
             FIRE   : 54,           # 6键 
             SAND   : 55,           # 7键
             GLASS  : 56,           # 8键 
             ROCK   : 57,           # 9键
             STONE  : 48,           # 0键
             BRICK  : 45,           # -键 
             DIAMOND: 61            # =键
            }

"合成表里合成规则"

rules = "# 两块木片和2块岩石合成一把火  # 两块岩石合成石头    # 两块石头和一团火合成砖块  # 两块石头合成沙   # 一团火,2沙合成玻璃   # 2木,3炭,2玻璃合成钻石"
operate_method_string = "按空格键捡东西,按数字键放东西,按数字键同时单击鼠标左键满足要求时合成物质。游戏目标可以是合成钻石,请先看教程。"

craft = {
           FIRE : { WOOD :2,ROCK : 2 }, # 两块木片和2块岩石合成一把火         
           STONE: { ROCK :2},           # 两块岩石合成石头
           BRICK : { STONE:2,FIRE : 1}, # 两块石头和一团火合成砖块
           SAND : { STONE : 2 },        # 两块石头合成沙
           GLASS: { FIRE :1,SAND : 2 }, # 一团火,2沙合成玻璃
           DIAMOND:{ WOOD:2,COAL : 3,GLASS:2 }  # 2木,3炭,2玻璃合成钻石
         }
    
pygame.init()
DISPLAYSURF = pygame.display.set_mode((MAPWIDTH*TILESIZE,MAPHEIGHT*TILESIZE + 120 )) # 渲染面
pygame.display.set_caption("2D Minecraft,我的世界2D版,作者:李兴球_风火轮少儿编程_www.scratch8.net")

INVFONT = pygame.font.Font('FreeSansBold.ttf',18)                                   # 新建字体对象
MSYHFONT = pygame.font.Font('msyh.ttf',12)                                          # 新建微软雅黑字体
operate_method_surface = MSYHFONT.render(operate_method_string,True,WHITE,BLACK)    # 渲染成surface
rules_surface = MSYHFONT.render(rules,True,WHITE,BLACK)                             # 渲染成surface

"效果造型表,换效果只要直接更换effect文件夹下面的图形即可,文件名为0001,0002,0003...."
effect_costumes = [ "effect/" + '0'* (4-len(str(i))) + str(i) + ".png" for i in range(1,6)] # 补零加序号形成图形文件表
effect_costumes = [pygame.image.load(image) for image in effect_costumes]   # 转换成surface
[image.set_alpha(150) for image in effect_costumes]   

group_effect = pygame.sprite.Group()                                                # 效果组

fpsClock = pygame.time.Clock()                                                      # 新建时钟对象
while True:
    for event in pygame.event.get():                                                # 事件轮换查询
        if event.type == QUIT:                                                      # 如果事件类型为QUIT,则退出pygame 
            pygame.quit()
            sys.exit()
        elif event.type == KEYDOWN:                                                 # 如果事件类型为按住某键
            if event.key == K_RIGHT and PLAYER.playerPos[0] < MAPWIDTH  - 1:               # 如果按的是右键且玩家没有超出右边界
                PLAYER.playerPos[0] +=1                                                    # 玩家的水平位置加一
                PLAYER.set_costume(3)                                     # 设为右造型
            if event.key == K_LEFT and PLAYER.playerPos[0] > 0 :                           # 如果按的是左键且玩家没有超出左边界
                PLAYER.playerPos[0] -=1                                                    # 玩家的水平位置减一
                PLAYER.set_costume(2)                                     # 设为左造型  
                
            if event.key == K_UP and PLAYER.playerPos[1]>0:                                # 如果按的是上键且玩家没有超出上边界
                PLAYER.playerPos[1] -=1                                                    # 玩家的垂直位置减一
                PLAYER.set_costume(0)                                     # 设为上造型
            if event.key == K_DOWN and PLAYER.playerPos[1] < MAPHEIGHT -1 :                # 如果按的是下键且玩家没有超出下边界
                PLAYER.playerPos[1] +=1                                                    # 玩家的垂直位置加一
                PLAYER.set_costume(1)                                     # 设为下造型  
            if event.key == K_SPACE:                                                # 按空格键捡东西
                currentTile = tilemap[PLAYER.playerPos[1]][PLAYER.playerPos[0]]                   # 保存玩家位置的方块   
                inventory[currentTile] +=1                                          # 仓库中这个方块的数量加一  
                tilemap[PLAYER.playerPos[1]][PLAYER.playerPos[0]] = DIRT             # 捡到东西后,玩家位置的方块应该变成DIRT地面
    all_keys = pygame.key.get_pressed()                        # 返回所有按键的布尔值表
     
    for key in controls:                                       # 对于controls中的每个按键 
        index = controls[key]
        if (all_keys[index] == 1):                    
             
            if pygame.mouse.get_pressed()[0] :                 # 按住键后 单击鼠标左键就是合成元素
                print("单击左键,准备合成")
                if key not in craft :break                     # 按的键代表某物质,不在合成表里则不合成
                canBeMade = True                               # 假设能被合成
                for i in craft[key]:
                    if craft[key][i] > inventory[i]:           # 合成所需的数量大于仓库中数量
                        canBeMade = False                      # 无法合成
                        break
                if canBeMade == True:                          # 如果能被合成
                    for i in craft[key]:                       # 仓库中的每项都根据规则减去相应的数量
                        inventory[i] -= craft[key][i]          #
                    inventory[key] += 1                        # 合成的这种物质数量加1
                    Effect(effect_costumes,(PLAYER.playerPos[0]*TILESIZE,PLAYER.playerPos[1]*TILESIZE),group_effect)
            else:                                              # 没有单击鼠标左键则只是把inventory中的资源放在地面  
                "按数字键放东西在史蒂夫风火轮少儿编程所在的位置"
                currentTile = tilemap[PLAYER.playerPos[1]][PLAYER.playerPos[0]]
                if inventory[key] > 0:                         # 如果仓库中这种物质数量大于0
                    inventory[key] -= 1                        # 那么数量减去1 
                    tilemap[PLAYER.playerPos[1]][PLAYER.playerPos[0]] = key  # 放到史蒂夫所在的位置
                    inventory[currentTile] += 1                # 仓库中相应数量加1

    group_effect.update()
    
    DISPLAYSURF.fill(BLACK)                                            # 填充黑色           
    for row in range(MAPHEIGHT):                                       # 每一行   
        for column in range(MAPWIDTH):                                 # 每一列
            DISPLAYSURF.blit(textures[tilemap[row][column]],(column*TILESIZE,row*TILESIZE,TILESIZE,TILESIZE)) # 取纹理,贴上

    DISPLAYSURF.blit(PLAYER.image,(PLAYER.playerPos[0]*TILESIZE,PLAYER.playerPos[1]*TILESIZE)) # 贴玩家图
    
    DISPLAYSURF.blit(textures[CLOUD].convert_alpha(),(cloudx,cloudy))      # 贴云图,纯属装饰
    cloudx +=1
    if cloudx > MAPWIDTH * TILESIZE:                                       # 如果云的水平位置大于宽度
        cloudy = random.randint(0,MAPHEIGHT*TILESIZE)                      # 移到左边-200的位置,y为随意
        cloudx = -200

    placePosition = 10                                                     # 开始放捡到的或合成到的资源的水平位置
    for item in resource:
        DISPLAYSURF.blit(textures[item],(placePosition,MAPHEIGHT*TILESIZE + 20)) # 贴资源图
        placePosition +=30
        textObj = INVFONT.render(str(inventory[item]),True,WHITE,BLACK)          
        DISPLAYSURF.blit(textObj,(placePosition,MAPHEIGHT*TILESIZE+20))       # 写数量
        placePosition +=50
        
    "下面只是写每个资源的中文名"
    index = 1
    placePosition = 10                                                     
    for item in resource:
        name = chr(controls[item])  + res_names[item]                          # 按键  + 资源的中文名
        chinese_name = MSYHFONT.render(name,True,WHITE,BLACK)
        DISPLAYSURF.blit(chinese_name,(placePosition,MAPHEIGHT*TILESIZE+50))
        placePosition += 80
    "下面只是提示合成规则和操作说明。"
    placePosition = 10         
    DISPLAYSURF.blit(rules_surface,(placePosition,MAPHEIGHT*TILESIZE+80))
    DISPLAYSURF.blit(operate_method_surface,(placePosition,MAPHEIGHT*TILESIZE+100))
    group_effect.draw(DISPLAYSURF)
    pygame.display.update()
    fpsClock.tick(24)

 

本站所有作品,教程等皆为原创,盗版必究。一旦付款,表示同意本站知识付费原则:数字商品,不支持退款。扫码付款后的朋友可以加QQ: 406273900,提供技术支持及发送作品图片与配音素材。亦可直接向微信号scratch8付款购买。
李兴球的博客_Python创意编程技术前沿 » 用pygame制作的我的世界2D版

学本领,探索更大的世界!

李兴球博客 风火轮编程主页
error: Content is protected !!