Python实现我的世界小游戏源代码!
我的世界小游戏使用方法:
移动
前进:W,后退:S,向左:A,向右:D,环顾四周:鼠标,跳起:空格键,切换飞行模式:Tab;
选择建筑材料
砖:1,草:2,沙子:3,删除建筑:鼠标左键单击,创建建筑块:鼠标右键单击
ESC退出程序。
完整程序包请通过文末地址下载,程序运行截图如下:
from__future__importdivision
importsys
importmath
importrandom
importtime
fromcollectionsimportdeque
frompygletimportimage
frompyglet.glimport*
frompyglet.graphicsimportTextureGroup
frompyglet.windowimportkey,mouse
TICKS_PER_SEC=60
#Sizeofsectorsusedtoeaseblockloading.
SECTOR_SIZE=16
WALKING_SPEED=5
FLYING_SPEED=15
GRAVITY=20.0
MAX_JUMP_HEIGHT=1.0#Abouttheheightofablock.
#Toderivetheformulaforcalculatingjumpspeed,firstsolve
#v_t=v_0+a*t
#forthetimeatwhichyouachievemaximumheight,whereaistheacceleration
#duetogravityandv_t=0.Thisgives:
#t=-v_0/a
#UsetandthedesiredMAX_JUMP_HEIGHTtosolveforv_0(jumpspeed)in
#s=s_0+v_0*t+(a*t^2)/2
JUMP_SPEED=math.sqrt(2*GRAVITY*MAX_JUMP_HEIGHT)
TERMINAL_VELOCITY=50
PLAYER_HEIGHT=2
ifsys.version_info[0]>=3:
xrange=range
defcube_vertices(x,y,z,n):
"""Returntheverticesofthecubeatpositionx,y,zwithsize2*n.
"""
return[
x-n,y+n,z-n,x-n,y+n,z+n,x+n,y+n,z+n,x+n,y+n,z-n,#top
x-n,y-n,z-n,x+n,y-n,z-n,x+n,y-n,z+n,x-n,y-n,z+n,#bottom
x-n,y-n,z-n,x-n,y-n,z+n,x-n,y+n,z+n,x-n,y+n,z-n,#left
x+n,y-n,z+n,x+n,y-n,z-n,x+n,y+n,z-n,x+n,y+n,z+n,#right
x-n,y-n,z+n,x+n,y-n,z+n,x+n,y+n,z+n,x-n,y+n,z+n,#front
x+n,y-n,z-n,x-n,y-n,z-n,x-n,y+n,z-n,x+n,y+n,z-n,#back
]
deftex_coord(x,y,n=4):
"""Returntheboundingverticesofthetexturesquare.
"""
m=1.0/n
dx=x*m
dy=y*m
returndx,dy,dx+m,dy,dx+m,dy+m,dx,dy+m
deftex_coords(top,bottom,side):
"""Returnalistofthetexturesquaresforthetop,bottomandside.
"""
top=tex_coord(*top)
bottom=tex_coord(*bottom)
side=tex_coord(*side)
result=[]
result.extend(top)
result.extend(bottom)
result.extend(side*4)
returnresult
TEXTURE_PATH='texture.png'
GRASS=tex_coords((1,0),(0,1),(0,0))
SAND=tex_coords((1,1),(1,1),(1,1))
BRICK=tex_coords((2,0),(2,0),(2,0))
STONE=tex_coords((2,1),(2,1),(2,1))
FACES=[
(0,1,0),
(0,-1,0),
(-1,0,0),
(1,0,0),
(0,0,1),
(0,0,-1),
]
defnormalize(position):
"""Accepts`position`ofarbitraryprecisionandreturnstheblock
containingthatposition.
Parameters
----------
position:tupleoflen3
Returns
-------
block_position:tupleofintsoflen3
"""
x,y,z=position
x,y,z=(int(round(x)),int(round(y)),int(round(z)))
return(x,y,z)
defsectorize(position):
"""Returnsatuplerepresentingthesectorforthegiven`position`.
Parameters
----------
position:tupleoflen3
Returns
-------
sector:tupleoflen3
"""
x,y,z=normalize(position)
x,y,z=x//SECTOR_SIZE,y//SECTOR_SIZE,z//SECTOR_SIZE
return(x,0,z)
classModel(object):
def__init__(self):
#ABatchisacollectionofvertexlistsforbatchedrendering.
self.batch=pyglet.graphics.Batch()
#ATextureGroupmanagesanOpenGLtexture.
self.group=TextureGroup(image.load(TEXTURE_PATH).get_texture())
#Amappingfrompositiontothetextureoftheblockatthatposition.
#Thisdefinesalltheblocksthatarecurrentlyintheworld.
self.world={}
#Samemappingas`world`butonlycontainsblocksthatareshown.
self.shown={}
#Mappingfrompositiontoapyglet`VertextList`forallshownblocks.
self._shown={}
#Mappingfromsectortoalistofpositionsinsidethatsector.
self.sectors={}
#Simplefunctionqueueimplementation.Thequeueispopulatedwith
#_show_block()and_hide_block()calls
self.queue=deque()
self._initialize()
def_initialize(self):
"""Initializetheworldbyplacingalltheblocks.
"""
n=80#1/2widthandheightofworld
s=1#stepsize
y=0#initialyheight
forxinxrange(-n,n+1,s):
forzinxrange(-n,n+1,s):
#createalayerstoneangrasseverywhere.
self.add_block((x,y-2,z),GRASS,immediate=False)
self.add_block((x,y-3,z),STONE,immediate=False)
ifxin(-n,n)orzin(-n,n):
#createouterwalls.
fordyinxrange(-2,3):
self.add_block((x,y+dy,z),STONE,immediate=False)
#generatethehillsrandomly
o=n-10
for_inxrange(120):
a=random.randint(-o,o)#xpositionofthehill
b=random.randint(-o,o)#zpositionofthehill
c=-1#baseofthehill
h=random.randint(1,6)#heightofthehill
s=random.randint(4,8)#2*sisthesidelengthofthehill
d=1#howquicklytotaperoffthehills
t=random.choice([GRASS,SAND,BRICK])
foryinxrange(c,c+h):
forxinxrange(a-s,a+s+1):
forzinxrange(b-s,b+s+1):
if(x-a)**2+(z-b)**2>(s+1)**2:
continue
if(x-0)**2+(z-0)**2<5**2:
continue
self.add_block((x,y,z),t,immediate=False)
s-=d#decrementsidelenthsohillstaperoff
defhit_test(self,position,vector,max_distance=8):
"""Lineofsightsearchfromcurrentposition.Ifablockis
intersecteditisreturned,alongwiththeblockpreviouslyintheline
ofsight.Ifnoblockisfound,returnNone,None.
Parameters
----------
position:tupleoflen3
The(x,y,z)positiontocheckvisibilityfrom.
vector:tupleoflen3
Thelineofsightvector.
max_distance:int
Howmanyblocksawaytosearchforahit.
"""
m=8
x,y,z=position
dx,dy,dz=vector
previous=None
for_inxrange(max_distance*m):
key=normalize((x,y,z))
ifkey!=previousandkeyinself.world:
returnkey,previous
previous=key
x,y,z=x+dx/m,y+dy/m,z+dz/m
returnNone,None
defexposed(self,position):
"""ReturnsFalseisgiven`position`issurroundedonall6sidesby
blocks,Trueotherwise.
"""
x,y,z=position
fordx,dy,dzinFACES:
if(x+dx,y+dy,z+dz)notinself.world:
returnTrue
returnFalse
defadd_block(self,position,texture,immediate=True):
"""Addablockwiththegiven`texture`and`position`totheworld.
Parameters
----------
position:tupleoflen3
The(x,y,z)positionoftheblocktoadd.
texture:listoflen3
Thecoordinatesofthetexturesquares.Use`tex_coords()`to
generate.
immediate:bool
Whetherornottodrawtheblockimmediately.
"""
ifpositioninself.world:
self.remove_block(position,immediate)
self.world[position]=texture
self.sectors.setdefault(sectorize(position),[]).append(position)
ifimmediate:
ifself.exposed(position):
self.show_block(position)
self.check_neighbors(position)
defremove_block(self,position,immediate=True):
"""Removetheblockatthegiven`position`.
Parameters
----------
position:tupleoflen3
The(x,y,z)positionoftheblocktoremove.
immediate:bool
Whetherornottoimmediatelyremoveblockfromcanvas.
"""
delself.world[position]
self.sectors[sectorize(position)].remove(position)
ifimmediate:
ifpositioninself.shown:
self.hide_block(position)
self.check_neighbors(position)
defcheck_neighbors(self,position):
"""Checkallblockssurrounding`position`andensuretheirvisual
stateiscurrent.Thismeanshidingblocksthatarenotexposedand
ensuringthatallexposedblocksareshown.Usuallyusedafterablock
isaddedorremoved.
"""
x,y,z=position
fordx,dy,dzinFACES:
key=(x+dx,y+dy,z+dz)
ifkeynotinself.world:
continue
ifself.exposed(key):
ifkeynotinself.shown:
self.show_block(key)
else:
ifkeyinself.shown:
self.hide_block(key)
defshow_block(self,position,immediate=True):
"""Showtheblockatthegiven`position`.Thismethodassumesthe
blockhasalreadybeenaddedwithadd_block()
Parameters
----------
position:tupleoflen3
The(x,y,z)positionoftheblocktoshow.
immediate:bool
Whetherornottoshowtheblockimmediately.
"""
texture=self.world[position]
self.shown[position]=texture
ifimmediate:
self._show_block(position,texture)
else:
self._enqueue(self._show_block,position,texture)
def_show_block(self,position,texture):
"""Privateimplementationofthe`show_block()`method.
Parameters
----------
position:tupleoflen3
The(x,y,z)positionoftheblocktoshow.
texture:listoflen3
Thecoordinatesofthetexturesquares.Use`tex_coords()`to
generate.
"""
x,y,z=position
vertex_data=cube_vertices(x,y,z,0.5)
texture_data=list(texture)
#createvertexlist
#FIXMEMaybe`add_indexed()`shouldbeusedinstead
self._shown[position]=self.batch.add(24,GL_QUADS,self.group,
('v3f/static',vertex_data),
('t2f/static',texture_data))
defhide_block(self,position,immediate=True):
"""Hidetheblockatthegiven`position`.Hidingdoesnotremovethe
blockfromtheworld.
Parameters
----------
position:tupleoflen3
The(x,y,z)positionoftheblocktohide.
immediate:bool
Whetherornottoimmediatelyremovetheblockfromthecanvas.
"""
self.shown.pop(position)
ifimmediate:
self._hide_block(position)
else:
self._enqueue(self._hide_block,position)
def_hide_block(self,position):
"""Privateimplementationofthe'hide_block()`method.
"""
self._shown.pop(position).delete()
defshow_sector(self,sector):
"""Ensureallblocksinthegivensectorthatshouldbeshownare
drawntothecanvas.
"""
forpositioninself.sectors.get(sector,[]):
ifpositionnotinself.shownandself.exposed(position):
self.show_block(position,False)
defhide_sector(self,sector):
"""Ensureallblocksinthegivensectorthatshouldbehiddenare
removedfromthecanvas.
"""
forpositioninself.sectors.get(sector,[]):
ifpositioninself.shown:
self.hide_block(position,False)
defchange_sectors(self,before,after):
"""Movefromsector`before`tosector`after`.Asectorisa
contiguousx,ysub-regionofworld.Sectorsareusedtospeedup
worldrendering.
"""
before_set=set()
after_set=set()
pad=4
fordxinxrange(-pad,pad+1):
fordyin[0]:#xrange(-pad,pad+1):
fordzinxrange(-pad,pad+1):
ifdx**2+dy**2+dz**2>(pad+1)**2:
continue
ifbefore:
x,y,z=before
before_set.add((x+dx,y+dy,z+dz))
ifafter:
x,y,z=after
after_set.add((x+dx,y+dy,z+dz))
show=after_set-before_set
hide=before_set-after_set
forsectorinshow:
self.show_sector(sector)
forsectorinhide:
self.hide_sector(sector)
def_enqueue(self,func,*args):
"""Add`func`totheinternalqueue.
"""
self.queue.append((func,args))
def_dequeue(self):
"""Popthetopfunctionfromtheinternalqueueandcallit.
"""
func,args=self.queue.popleft()
func(*args)
defprocess_queue(self):
"""Processtheentirequeuewhiletakingperiodicbreaks.Thisallows
thegamelooptorunsmoothly.Thequeuecontainscallsto
_show_block()and_hide_block()sothismethodshouldbecalledif
add_block()orremove_block()wascalledwithimmediate=False
"""
start=time.perf_counter()
whileself.queueandtime.time()-start<1.0/TICKS_PER_SEC:
self._dequeue()
defprocess_entire_queue(self):
"""Processtheentirequeuewithnobreaks.
"""
whileself.queue:
self._dequeue()
classWindow(pyglet.window.Window):
def__init__(self,*args,**kwargs):
super(Window,self).__init__(*args,**kwargs)
#Whetherornotthewindowexclusivelycapturesthemouse.
self.exclusive=False
#Whenflyinggravityhasnoeffectandspeedisincreased.
self.flying=False
#Strafingismovinglateraltothedirectionyouarefacing,
#e.g.movingtotheleftorrightwhilecontinuingtofaceforward.
#
#Firstelementis-1whenmovingforward,1whenmovingback,and0
#otherwise.Thesecondelementis-1whenmovingleft,1whenmoving
#right,and0otherwise.
self.strafe=[0,0]
#Current(x,y,z)positionintheworld,specifiedwithfloats.Note
#that,perhapsunlikeinmathclass,they-axisistheverticalaxis.
self.position=(0,0,0)
#Firstelementisrotationoftheplayerinthex-zplane(ground
#plane)measuredfromthez-axisdown.Thesecondistherotation
#anglefromthegroundplaneup.Rotationisindegrees.
#
#Theverticalplanerotationrangesfrom-90(lookingstraightdown)to
#90(lookingstraightup).Thehorizontalrotationrangeisunbounded.
self.rotation=(0,0)
#Whichsectortheplayeriscurrentlyin.
self.sector=None
#Thecrosshairsatthecenterofthescreen.
self.reticle=None
#Velocityinthey(upward)direction.
self.dy=0
#Alistofblockstheplayercanplace.Hitnumkeystocycle.
self.inventory=[BRICK,GRASS,SAND]
#Thecurrentblocktheusercanplace.Hitnumkeystocycle.
self.block=self.inventory[0]
#Conveniencelistofnumkeys.
self.num_keys=[
key._1,key._2,key._3,key._4,key._5,
key._6,key._7,key._8,key._9,key._0]
#Instanceofthemodelthathandlestheworld.
self.model=Model()
#Thelabelthatisdisplayedinthetopleftofthecanvas.
self.label=pyglet.text.Label('',font_name='Arial',font_size=18,
x=10,y=self.height-10,anchor_x='left',anchor_y='top',
color=(0,0,0,255))
#Thiscallschedulesthe`update()`methodtobecalled
#TICKS_PER_SEC.Thisisthemaingameeventloop.
pyglet.clock.schedule_interval(self.update,1.0/TICKS_PER_SEC)
defset_exclusive_mouse(self,exclusive):
"""If`exclusive`isTrue,thegamewillcapturethemouse,ifFalse
thegamewillignorethemouse.
"""
super(Window,self).set_exclusive_mouse(exclusive)
self.exclusive=exclusive
defget_sight_vector(self):
"""Returnsthecurrentlineofsightvectorindicatingthedirection
theplayerislooking.
"""
x,y=self.rotation
#yrangesfrom-90to90,or-pi/2topi/2,somrangesfrom0to1and
#is1whenlookingaheadparalleltothegroundand0whenlooking
#straightupordown.
m=math.cos(math.radians(y))
#dyrangesfrom-1to1andis-1whenlookingstraightdownand1when
#lookingstraightup.
dy=math.sin(math.radians(y))
dx=math.cos(math.radians(x-90))*m
dz=math.sin(math.radians(x-90))*m
return(dx,dy,dz)
defget_motion_vector(self):
"""Returnsthecurrentmotionvectorindicatingthevelocityofthe
player.
Returns
-------
vector:tupleoflen3
Tuplecontainingthevelocityinx,y,andzrespectively.
"""
ifany(self.strafe):
x,y=self.rotation
strafe=math.degrees(math.atan2(*self.strafe))
y_angle=math.radians(y)
x_angle=math.radians(x+strafe)
ifself.flying:
m=math.cos(y_angle)
dy=math.sin(y_angle)
ifself.strafe[1]:
#Movingleftorright.
dy=0.0
m=1
ifself.strafe[0]>0:
#Movingbackwards.
dy*=-1
#Whenyouareflyingupordown,youhavelessleftandright
#motion.
dx=math.cos(x_angle)*m
dz=math.sin(x_angle)*m
else:
dy=0.0
dx=math.cos(x_angle)
dz=math.sin(x_angle)
else:
dy=0.0
dx=0.0
dz=0.0
return(dx,dy,dz)
defupdate(self,dt):
"""Thismethodisscheduledtobecalledrepeatedlybythepyglet
clock.
Parameters
----------
dt:float
Thechangeintimesincethelastcall.
"""
self.model.process_queue()
sector=sectorize(self.position)
ifsector!=self.sector:
self.model.change_sectors(self.sector,sector)
ifself.sectorisNone:
self.model.process_entire_queue()
self.sector=sector
m=8
dt=min(dt,0.2)
for_inxrange(m):
self._update(dt/m)
def_update(self,dt):
"""Privateimplementationofthe`update()`method.Thisiswheremost
ofthemotionlogiclives,alongwithgravityandcollisiondetection.
Parameters
----------
dt:float
Thechangeintimesincethelastcall.
"""
#walking
speed=FLYING_SPEEDifself.flyingelseWALKING_SPEED
d=dt*speed#distancecoveredthistick.
dx,dy,dz=self.get_motion_vector()
#Newpositioninspace,beforeaccountingforgravity.
dx,dy,dz=dx*d,dy*d,dz*d
#gravity
ifnotself.flying:
#Updateyourverticalspeed:ifyouarefalling,speedupuntilyou
#hitterminalvelocity;ifyouarejumping,slowdownuntilyou
#startfalling.
self.dy-=dt*GRAVITY
self.dy=max(self.dy,-TERMINAL_VELOCITY)
dy+=self.dy*dt
#collisions
x,y,z=self.position
x,y,z=self.collide((x+dx,y+dy,z+dz),PLAYER_HEIGHT)
self.position=(x,y,z)
defcollide(self,position,height):
"""Checkstoseeiftheplayeratthegiven`position`and`height`
iscollidingwithanyblocksintheworld.
Parameters
----------
position:tupleoflen3
The(x,y,z)positiontocheckforcollisionsat.
height:intorfloat
Theheightoftheplayer.
Returns
-------
position:tupleoflen3
Thenewpositionoftheplayertakingintoaccountcollisions.
"""
#Howmuchoverlapwithadimensionofasurroundingblockyouneedto
#havetocountasacollision.If0,touchingterrainatallcountsas
#acollision.If.49,yousinkintotheground,asifwalkingthrough
#tallgrass.If>=.5,you'llfallthroughtheground.
pad=0.25
p=list(position)
np=normalize(position)
forfaceinFACES:#checkallsurroundingblocks
foriinxrange(3):#checkeachdimensionindependently
ifnotface[i]:
continue
#Howmuchoverlapyouhavewiththisdimension.
d=(p[i]-np[i])*face[i]
ifd
我的世界小游戏python源代码包下载地址:
链接:https://pan.baidu.com/s/1gKAheRzAeNmRXgSU-A4PPg
提取码:rya9
到此这篇关于Python实现我的世界小游戏源代码的文章就介绍到这了,更多相关Python小游戏源代码内容请搜索毛票票以前的文章或继续浏览下面的相关文章希望大家以后多多支持毛票票!
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。