[Python] 制作钻地小子demo

码来的小朋友们 2022-08-06 05:21:35 阅读数:1,001

Pythondemo制作小子钻地

使用python制作钻地小子demo

相信应该不少90后的伙伴,多少玩过这款GBA游戏
在这里插入图片描述
接下来我是用python来制作一款钻地小子的游戏demo

直接上开发完成的游戏

说实话有背景音乐还是很带劲的
请添加图片描述请添加图片描述

效果就如下一个小demo还有写细节没有完全做完,先这样以后有空再做

实现玩法

  1. 设计好游戏主界面
  2. 设计好游戏地图,方块随机的
  3. 制作角色、移动
  4. 可以实现钻地下掉

OK闲话少说开干

实现思路

  1. 从网上下载好素材图片、音乐等
  2. 通过python的pygame库来实现游戏demo
  3. 具体实现

项目结构

在这里插入图片描述
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://blog.csdn.net/qq_25755645/article/details/126024545