使用python制作钻地小子demo
相信应该不少90后的伙伴,多少玩过这款GBA游戏

讯享网
接下来我是用python来制作一款钻地小子的游戏demo
直接上开发完成的游戏
说实话有背景音乐还是很带劲的


效果就如下一个小demo还有写细节没有完全做完,先这样以后有空再做
实现玩法
- 设计好游戏主界面
- 设计好游戏地图,方块随机的
- 制作角色、移动
- 可以实现钻地下掉
OK闲话少说开干
实现思路
- 从网上下载好素材图片、音乐等
- 通过python的pygame库来实现游戏demo
- 具体实现
项目结构

Graph是保存了游戏中的所有素材图片
Sound存了所有的音效
gd.py 就是写demo的主程序
大概效果图:

Graph内容如下
所有的图片都归类好了

Sound内容如下

开发阶段
1.制作游戏框架
首先导入所有需要用到的包
# -*- coding:utf-8 -*- import pygame,os from sys import exit from random import randint as ri from pygame.locals import * pygame.init()
讯享网
我们需要绘制地图上所有方块的坐标,传入一个关卡id,函数代码如下:

讯享网#地图方块绘制 def LEVEL_POSITION(level): level_pos = [] if level == 1:#第一关 for j in range(7,45+7):#45 for i in range(11): level_pos.append([ i*(32), j*(32),ri(1, 495+1)]) #填充最后的纯绿色 for j in range(7): for i in range(11): level_pos.append([ i*(32), 1632+32+j*(32),-1]) return level_pos
制作好测试每个方块代号的颜色表,函数代码如下:
#测试方块的颜色 def colorTYPE(leP): if 1<=leP<=110: #红色 return 'r' elif 111<=leP<=220:#蓝色 return 'b' elif 221<=leP<=330:#绿色 return 'g' elif 331<=leP<=440:#黄色 return 'y' elif 441<=leP<=487:#棕色 return 'Br' elif 488<=leP<=495:#气囊 return 'AIR' elif leP == -1: #绘制最后的关卡结束方块 纯绿色 return 'cG'
创建要给main方法,然后成为主方法,在main方法里面写入按键检测事件,代码块如下:
讯享网#---------------------行走动画效果和坠落动画效果------------------------ for event in pygame.event.get(): if event.type == QUIT: exit() if event.type == KEYDOWN: #在主界面的时候 等于 false if gameing == False: if event.key == K_SPACE: gameing = True #可以开始游戏了 else:#可以开始游戏的行为了------------------------------
接下来是主调main函数的入口,代码如下:
if __name__ == '__main__': trs = True level = 1 argc = False while trs: trs = main(argc,level) level+=1
接下来定义好所有游戏中使用的变量和资源加载,代码如下:
讯享网def main(gameing_argc,level_argc):
w,h = 510,480
recSIZE = 350
timer = 30
patth = 0
score = 0
life = 1
screen = pygame.display.set_mode([w,h],0,32)
caption = pygame.display.set_caption("钻地小子")
screen.fill([0,0,0]);
pygame.display.flip()
pygame.key.set_repeat(1,100)
#背景
bg = pygame.image.load('Graph/Title/Bg.jpg').convert_alpha()
bg = pygame.transform.scale(bg, (int(bg.get_width()*0.75), int(bg.get_height()*0.75)))
#载入声音
pygame.mixer_music.load('Sound/bgm/Airman.mp3')
pygame.mixer.music.play(-1,0,)
pygame.mixer.music.set_volume(0.5)
#please space 的按钮
spacebg = pygame.image.load('Graph/Common/PleasePushSpace.png').convert_alpha()
spacebg = pygame.transform.scale(spacebg, (int(spacebg.get_width()*0.7), int(spacebg.get_height()*0.7)))
spacetimer = 0 #空格闪烁定时器
gameing = gameing_argc #默认游戏还没开始
#左边壁纸
leftbg = pygame.image.load('Graph/Play/Bg.jpg').convert_alpha();
leftbg = pygame.transform.scale(leftbg,(int(leftbg.get_width()*0.145), int(leftbg.get_height()*0.2)))
#右边壁纸
rightbg = pygame.image.load('Graph/Play/UI.PNG').convert_alpha();
rightbg = pygame.transform.scale(rightbg,(int(rightbg.get_width()*0.6), int(rightbg.get_height()*0.7)))
#空气瓶条
air1 = pygame.image.load('Graph/Play/AirGauge1.png').convert_alpha()
air1 = pygame.transform.scale(air1, (100, int(air1.get_height()*0.4)))
fs = pygame.font.SysFont("arial", 30)
air_lifeV = 100 #气囊条血量 100代表100% 高度为:height == 26
air_timer = 0
#方块 32*32
blue1 = pygame.image.load('Graph/Play/blue1.png').convert_alpha()
blue1 = pygame.transform.scale(blue1,(32, 32))
brow1 = pygame.image.load('Graph/Play/brown1.png').convert_alpha()
brow1 = pygame.transform.scale(brow1,(32, 32))
green1 = pygame.image.load('Graph/Play/green1.png').convert_alpha()
green1 = pygame.transform.scale(green1,(32, 32))
green2 = pygame.image.load('Graph/Play/green2.png').convert_alpha()
green2 = pygame.transform.scale(green2,(32, 32))
red1 = pygame.image.load('Graph/Play/red1.png').convert_alpha()
red1 = pygame.transform.scale(red1,(32, 32))
yellow1 = pygame.image.load('Graph/Play/yellow1.png').convert_alpha()
yellow1 = pygame.transform.scale(yellow1,(32, 32))
#空气瓶
air = pygame.image.load('Graph/Play/air.png').convert_alpha()
air = pygame.transform.scale(air,(32, 32))
#角色坠落 fall
fall1 = pygame.image.load('Graph/Play/fall/fall1.png').convert_alpha()
fall1 = pygame.transform.scale(fall1, (32, 32))
fall_h = -50 #坠落高度
#角色移动 left
left1 = pygame.image.load('Graph/Play/leftm/walk_left1.png').convert_alpha()
left1 = pygame.transform.scale(left1, (32, 32))
left2 = pygame.image.load('Graph/Play/leftm/walk_left2.png').convert_alpha()
left2 = pygame.transform.scale(left2, (32, 32))
left3 = pygame.image.load('Graph/Play/leftm/walk_left3.png').convert_alpha()
left3 = pygame.transform.scale(left3, (32, 32))
left4 = pygame.image.load('Graph/Play/leftm/walk_left4.png').convert_alpha()
left4 = pygame.transform.scale(left4, (32, 32))
left5 = pygame.image.load('Graph/Play/leftm/walk_left5.png').convert_alpha()
left5 = pygame.transform.scale(left5, (32, 32))
#角色移动 right
right1 = pygame.image.load('Graph/Play/rightm/walk_right1.png').convert_alpha()
right1 = pygame.transform.scale(right1, (32, 32))
right2 = pygame.image.load('Graph/Play/rightm/walk_right2.png').convert_alpha()
right2 = pygame.transform.scale(right2, (32, 32))
right3 = pygame.image.load('Graph/Play/rightm/walk_right3.png').convert_alpha()
right3 = pygame.transform.scale(right3, (32, 32))
right4 = pygame.image.load('Graph/Play/rightm/walk_right4.png').convert_alpha()
right4 = pygame.transform.scale(right4, (32, 32))
right5 = pygame.image.load('Graph/Play/rightm/walk_right5.png').convert_alpha()
right5 = pygame.transform.scale(right5, (32, 32))
#上钻
upd = pygame.image.load('Graph/Play/upm/up.png').convert_alpha()
upd = pygame.transform.scale(upd, (32, 32))
#下钻
downd = pygame.image.load('Graph/Play/downm/down.png').convert_alpha()
downd = pygame.transform.scale(downd, (32, 32))
#关卡1 红 蓝 绿 黄 棕 气
# 110,110,110, 110, 47, 8
LEVEL = [1,0,0,0,0,0,0,0,0,0] #10个关卡
leveF = 1 #默认第一关标志 (用来测试随机生成第几关的地图标志)
level_pos = [] #关卡所有的方块坐标
Bindlist = [] #绑定的同色和在一块的方块数组
reducer = 0 #累减器
#角色状态
drc = 'sp'#默认炫富状态 sp 悬空 l 左 r右 st 静止
butup = False #按键松开判断
butup2 = False #松开按键判断
from_drc = drc #记录前一个方向
moveTimer = 0#移动定时器
P=[ 160 , 193 ]#角色默认位置
right_first_RECT = []#检测右边的方块坐标[ level_pos[0][0] , level_pos[0][1] ]
right_first_RECT2 = [] #钻机的右边的方块坐标
#棕色方块列表
color_brown = []
esc_stop = False #暂停游戏
循环往下掉的代码块如下:
#循环往下面掉---------- index = 0 ind_pos = [] ind_index = 0 for j in range(495): if level_pos[index+11][2] == 0 and level_pos[index][2] != 0 and P[1] >= level_pos[index+11][1]: ind_pos = level_pos[index+11] ind_index = index+11 index += 1 #print(P,ind_pos) ind_inde_ind = 0 while ind_index>0: if level_pos[ind_index] == ind_pos and ind_pos[0]!=0 and ind_pos[1]!=0: level_pos[ind_index-(ind_inde_ind+1)*11][1] = level_pos[ind_index-ind_inde_ind*11][1]-32 ind_inde_ind += 1 if level_pos[ind_index][2] == 0: level_pos[ind_index-11][0] = level_pos[ind_index][0] level_pos[ind_index-11][1] = level_pos[ind_index][1] level_pos[ind_index][0] = 0 level_pos[ind_index][1] = 0 ind_index-=1
因为pygame这个游戏库没有动画的任何接口只能手动一个一个来码,所以我只能在这里手动实现序列帧的动画来设计角色,设计行走动画和坠落动画如下代码块:
讯享网--------------------行走动画效果和坠落动画效果------------------------ if drc == 'sp': if fall_h < 193: fall_h+=4 else:fall_h=193 screen.blit(fall1,(level_pos[5][0],fall_h)) elif drc == 'r': moveTimer += 1 if moveTimer <= 2: screen.blit(right1,P) elif moveTimer <= 4: screen.blit(right2,P) elif moveTimer <= 6: screen.blit(right3,P) elif moveTimer <= 8: screen.blit(right4,P) elif moveTimer <= 10: screen.blit(right5,P) elif moveTimer <= 12: moveTimer = 0 elif drc == 'l': moveTimer += 1 if moveTimer <= 2: screen.blit(left1,P) elif moveTimer <= 4: screen.blit(left2,P) elif moveTimer <= 6: screen.blit(left3,P) elif moveTimer <= 8: screen.blit(left4,P) elif moveTimer <= 10: screen.blit(left5,P) elif moveTimer <= 12: moveTimer = 0 elif drc == 'd': if from_drc == 'l': screen.blit(left1,P) elif from_drc == 'r': screen.blit(right1,P) elif from_drc == 'd': screen.blit(downd,P) else: screen.blit(downd,P) elif drc == 'u': if from_drc == 'l': screen.blit(left1,P) elif from_drc == 'r': screen.blit(right1,P) else: screen.blit(upd,P) #print(drc,from_drc)
添加按了ESC然后暂停游戏功能,使用Run变量来控制游戏的正常运行和停止,带代码如下:
def stopFun(): Run = True pygame.mixer_music.load('Sound/effect/effect10.mp3') pygame.mixer.music.play(1,0,) pygame.mixer.music.set_volume(0.5) pygame.display.flip() while Run: for event in pygame.event.get(): if event.type == QUIT: exit() if event.type == KEYDOWN: if event.key == K_ESCAPE: Run = False pygame.display.update()
接下来是真正的最核心的代码块,实现了最终的行走动画和方块坠落、主角坠落的动画和逻辑,代码如下:
讯享网#---------------------行走动画效果和坠落动画效果------------------------ for event in pygame.event.get(): if event.type == QUIT: exit() if event.type == KEYDOWN: #在主界面的时候 等于 false if gameing == False: if event.key == K_SPACE: gameing = True #可以开始游戏了 else:#可以开始游戏的行为了------------------------------ if fall_h >= 193:#坠落状态已经到达 #print('0-4坐标:',level_pos[3][0],level_pos[3][1]) #print('P:',P) if event.key == K_ESCAPE: stopFun() if event.key == K_LEFT: drc = 'l' #------------------------- #检测是不是最开始的状态,为了移动人物 if level_pos[0][1] > P[1] : P[0]-=8 #elif True: #print('begin_left') else: #左边移动判断撞到 方块的坐标 left_first_RECT = []#[ level_pos[0][0] , level_pos[0][1] ]#默认第一个方块 #检测和自己左边最近的方块坐标 left_indsss = 0 for reP in level_pos: #遍历是否撞到方块 if reP[0]<= P[0] and reP[1] <= P[1] and reP[0] >= P[0]-32 and reP[1] >= P[1]-32: left_first_RECT = reP #左边有最近的方块 try: #print(left_first_RECT) #pygame.draw.rect(screen, (255,0,0), (left_first_RECT[0],left_first_RECT[1],32,32)) if left_first_RECT[0]<=P[0] and left_first_RECT[1]<=P[1] and left_first_RECT[2]!=0: #pygame.draw.rect(screen, (255,255,255), (left_first_RECT[0],left_first_RECT[1],32,32), 1) #正在行走时...判断气囊是否在左边 是就吃掉加血 if colorTYPE(left_first_RECT[2]) == 'AIR': indext = 0 for reP in level_pos: if reP == left_first_RECT: level_pos[indext][2] = 0 air_lifeV += 20 if air_lifeV >= 100:air_lifeV = 100 #print('yes qinang') break indext += 1 elif colorTYPE(left_first_RECT[2]) == 'Br': #print('棕色') air_lifeV -= 2 if air_lifeV<=0:air_lifeV = 0 try: level_pos[left_indsss][2] = 0 except:pass #没有最近的方块 是空格 elif left_first_RECT[2] == 0: P[0]-=8 #print('DRECTION---left:',P[0]) except:pass#print('error1',left_first_RECT) #------------------------- #是否超出游戏最大盒子 if P[0]+32>recSIZE:P[0]=recSIZE-32 if P[0]<0:P[0]=0 if event.key == K_RIGHT: drc = 'r' #------------------------- #检测是不是最开始的状态,为了移动人物 if level_pos[0][1] > P[1]: P[0]+=8 #print('begin_right') else: #右边移动判断撞到 方块的坐标 right_first_RECT = [0,0,0] right_indsss = 0 #检测和自己右边最近的方块坐标 #if reP[0]<= P[0] and reP[1] <= P[1] and reP[0] >= P[0]-32 and reP[1] >= P[1]-30: for reP in level_pos: #遍历是否撞到方块 if reP[0]>=P[0]+32 and reP[0]+32<=P[0]+64 and reP[1] <= P[1] and reP[1] >= P[1]-30: right_first_RECT = reP right_indsss += 1 #------要到与自己平行的方块才被钻掉------ if(reP[1]+3)>=P[1] and (P[1]+32)>=(reP[1]+30):break #------要到与自己平行的方块才被钻掉------ try: #pygame.draw.rect(screen,(0,255,0), (right_first_RECT[0],right_first_RECT[1],32,32)) #右边有最近的方块 if right_first_RECT[0]>=P[0]+32 and right_first_RECT[1]<=P[1] and right_first_RECT[2]!=0: #pygame.draw.rect(screen,(255,0,0), (right_first_RECT[0],right_first_RECT[1],32,32), 1) #正在行走时...判断气囊是否在右边 是就吃掉加血 if colorTYPE(right_first_RECT[2]) == 'AIR': indext = 0 for reP in level_pos: if reP == right_first_RECT: level_pos[indext][2] = 0 air_lifeV += 20 if air_lifeV >= 100:air_lifeV = 100 #print('yes qinang') break indext += 1 elif colorTYPE(right_first_RECT[2]) == 'Br': #print('棕色') air_lifeV -= 2 if air_lifeV<=0:air_lifeV=0 try: level_pos[right_indsss][2] = 0 except:pass #没有最近的方块 是空格 elif right_first_RECT[2] == 0: P[0]+=8 #print('DRECTION---right:',P[0]) except: print('error2',right_first_RECT) #------------------------- #是否产出游戏最大盒子 if P[0]+32>recSIZE:P[0]=recSIZE-32 if P[0]<0:P[0]=0 if event.key == K_DOWN: from_drc = 'd' drc = 'd' right_indsss = 0 indes = 0 for i in range(495): #p[0]+16是取角色的中心点坐标运算 if level_pos[indes][0]+32 >= P[0]+22 and P[0]+10 >= level_pos[indes][0] and \ P[1]+32 >= level_pos[indes][1] and level_pos[indes][2]!=0: #print(level_pos[indes]) #print(P) if level_pos[indes][0] >= P[0] and level_pos[indes][1]>= P[1]: #红色'r' #蓝色'b' #绿色 'g' #黄色'y' #棕色'Br' #气囊'AIR' #纯绿色'cG' if colorTYPE(level_pos[indes][2]) == 'Br': #print('棕色') air_lifeV -= 2 if air_lifeV<=0:air_lifeV=0 try: if right_indsss!=0: level_pos[right_indsss][2] = 0 except:pass #break indes += 1 if event.key == K_UP: from_drc = 'u' drc = 'u' right_indsss = 0 indes = 0 for i in range(495): #p[0]+16是取角色的中心点坐标运算 if level_pos[indes][0]+32 >= P[0]+22 and P[0]+10 >= level_pos[indes][0] and \ P[1] >= level_pos[indes][1] and level_pos[indes][2]!=0: #print('up') if level_pos[indes][0] >= P[0] and level_pos[indes][1]>= P[1]-32: #红色'r' #蓝色'b' #绿色 'g' #黄色'y' #棕色'Br' #气囊'AIR' #纯绿色'cG' if colorTYPE(level_pos[indes][2]) == 'Br': #print('棕色') air_lifeV -= 2 if air_lifeV<=0:air_lifeV = 0 try: level_pos[right_indsss][2] = 0 except:pass #break indes += 1 if event.key == K_RETURN or event.key == K_KP_ENTER: if drc == 'd':#开始钻机 indes = 0 for i in range(495): #p[0]+16是取角色的中心点坐标运算 if level_pos[indes][0]+32 >= P[0]+22 and P[0]+10 >= level_pos[indes][0] and \ P[1]+32 >= level_pos[indes][1] and level_pos[indes][2]!=0: #print(level_pos[indes]) #print(P) if level_pos[indes][0] >= P[0] and level_pos[indes][1]>= P[1]: patth += 1 score += patth+ri(1, 4) #红色'r' #蓝色'b' #绿色 'g' #黄色'y' #棕色'Br' #气囊'AIR' #纯绿色'cG' if colorTYPE(level_pos[indes][2]) == 'Br': air_lifeV -= 2 if air_lifeV <=0:air_lifeV = 0 #BindTop(level_pos,level_pos[indes]) level_pos[indes][2] = 0#这个为空格方块 #break indes += 1 if drc == 'u':#开始钻机 indes = 0 for i in range(495): #p[0]+16是取角色的中心点坐标运算 if level_pos[indes][0]+32 >= P[0]+22 and P[0]+10 >= level_pos[indes][0] and \ P[1] >= level_pos[indes][1] and level_pos[indes][2]!=0: #print('up') if level_pos[indes][0] >= P[0] and level_pos[indes][1]>= P[1]-32: patth += 1 score += patth*ri(1, 4) if colorTYPE(level_pos[indes][2]) == 'Br': air_lifeV -= 2 if air_lifeV <=0:air_lifeV = 0 level_pos[indes][2] = 0#这个为空格方块 break indes += 1 if drc == 'l':#开始钻机 #------------------------- #左边移动判断撞到 方块的坐标 left_first_RECT = [] #检测和自己左边最近的方块坐标 为了消除坐标方块 for reP in level_pos: #遍历是否撞到方块 if reP[0]<= P[0] and reP[1] <= P[1] and reP[2]!=0 \ and reP[0] >= P[0]-32 and reP[1] >= P[1]-30: left_first_RECT = reP #左边有最近的方块 try: if left_first_RECT[0]<=P[0] and left_first_RECT[1]<=P[1] and left_first_RECT[2]!=0: #level_pos[indes][2] = 0 index = 0 for reP in level_pos: if reP == left_first_RECT: #pygame.draw.rect(screen, (255,255,255), (left_first_RECT[0],left_first_RECT[1],32,32), 1) patth += 1 score += patth*ri(1, 4) if colorTYPE(level_pos[indes][2]) == 'Br': air_lifeV -= 2 if air_lifeV <=0:air_lifeV = 0 level_pos[index][2] = 0 index += 1 except:pass #------------------------- if drc == 'r':#开始钻机 #------------------------- #右边移动判断撞到 方块的坐标 #检测和自己右边最近的方块坐标 #and reP[1] <= P[1] and reP[1] >= P[1]-30 for reP in level_pos: #遍历是否撞到方块 if reP[0]>=P[0]+32 and reP[0]+32<=P[0]+64 and reP[2]!=0\ and reP[1] <= P[1] and reP[1] >= P[1]-30 : right_first_RECT2 = reP #---------要到与自己平行的方块才被钻掉------------- if (reP[1]+3)>=P[1] and (P[1]+32)>=(reP[1]+30):break #---------要到与自己平行的方块才被钻掉------------- #右边有最近的方块 try: #pygame.draw.rect(screen, (255,255,255), (right_first_RECT[0],right_first_RECT[1],32,32)) if right_first_RECT2[0]>=P[0] and right_first_RECT2[1]<=P[1] and right_first_RECT2[2]!=0: index = 0 for reP in level_pos: if reP == right_first_RECT2: #pygame.draw.rect(screen, (255,255,255), (right_first_RECT2[0],right_first_RECT2[1],32,32), 1) patth += 1 score += patth*ri(1, 4) if colorTYPE(level_pos[indes][2]) == 'Br':#为棕色的方块 #print('棕色') pass#level_pos[indes][2] = 0 else: if colorTYPE(level_pos[indes][2]) == 'Br': air_lifeV -= 2 if air_lifeV <=0:air_lifeV = 0 level_pos[index][2] = 0 #------要到与自己平行的方块才被钻掉------ if (reP[1]+3)>=P[1] and (P[1]+32)>=(reP[1]+30):break #------要到与自己平行的方块才被钻掉------ index += 1 except:pass #------------------------- if event.type == KEYUP: if fall_h >= 193: if event.key == K_LEFT or event.key == K_RIGHT: from_drc = drc #记录前一个方向 #drc = 'd'#成为静止状态 moveTimer = 0 if event.key == K_RETURN or event.key == K_KP_ENTER: butup = True butup2 = True

至此游戏全部代码量867行做完
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/43962.html