如何在python中使用pygame框架

这篇文章将为大家详细讲解有关如何在python中使用pygame框架,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。

具体内容如下

如何在python中使用pygame框架

#StarPusher(aSokobanclone)
#ByAlSweigartal@inventwithpython.com
#http://inventwithpython.com/pygame
#Releasedundera"SimplifiedBSD"license

importrandom,sys,copy,os,pygame
frompygame.localsimport*

FPS=30#framespersecondtoupdatethescreen
WINWIDTH=800#widthoftheprogram'swindow,inpixels
WINHEIGHT=600#heightinpixels
HALF_WINWIDTH=int(WINWIDTH/2)
HALF_WINHEIGHT=int(WINHEIGHT/2)

#Thetotalwidthandheightofeachtileinpixels.
TILEWIDTH=50
TILEHEIGHT=85
TILEFLOORHEIGHT=40

CAM_MOVE_SPEED=5#howmanypixelsperframethecameramoves

#Thepercentageofoutdoortilesthathaveadditional
#decorationonthem,suchasatreeorrock.
OUTSIDE_DECORATION_PCT=20

BRIGHTBLUE=(0,170,255)
WHITE=(255,255,255)
BGCOLOR=BRIGHTBLUE
TEXTCOLOR=WHITE

UP='up'
DOWN='down'
LEFT='left'
RIGHT='right'


defmain():
globalFPSCLOCK,DISPLAYSURF,IMAGESDICT,TILEMAPPING,OUTSIDEDECOMAPPING,BASICFONT,PLAYERIMAGES,currentImage

#Pygameinitializationandbasicsetupoftheglobalvariables.
pygame.init()
FPSCLOCK=pygame.time.Clock()

#BecausetheSurfaceobjectstoredinDISPLAYSURFwasreturned
#fromthepygame.display.set_mode()function,thisisthe
#Surfaceobjectthatisdrawntotheactualcomputerscreen
#whenpygame.display.update()iscalled.
DISPLAYSURF=pygame.display.set_mode((WINWIDTH,WINHEIGHT))

pygame.display.set_caption('StarPusher')
BASICFONT=pygame.font.Font('freesansbold.ttf',18)

#AglobaldictvaluethatwillcontainallthePygame
#Surfaceobjectsreturnedbypygame.image.load().
IMAGESDICT={'uncoveredgoal':pygame.image.load('RedSelector.png'),
'coveredgoal':pygame.image.load('Selector.png'),
'star':pygame.image.load('Star.png'),
'corner':pygame.image.load('Wall_Block_Tall.png'),
'wall':pygame.image.load('Wood_Block_Tall.png'),
'insidefloor':pygame.image.load('Plain_Block.png'),
'outsidefloor':pygame.image.load('Grass_Block.png'),
'title':pygame.image.load('star_title.png'),
'solved':pygame.image.load('star_solved.png'),
'princess':pygame.image.load('princess.png'),
'boy':pygame.image.load('boy.png'),
'catgirl':pygame.image.load('catgirl.png'),
'horngirl':pygame.image.load('horngirl.png'),
'pinkgirl':pygame.image.load('pinkgirl.png'),
'rock':pygame.image.load('Rock.png'),
'shorttree':pygame.image.load('Tree_Short.png'),
'talltree':pygame.image.load('Tree_Tall.png'),
'uglytree':pygame.image.load('Tree_Ugly.png')}

#Thesedictvaluesareglobal,andmapthecharacterthatappears
#inthelevelfiletotheSurfaceobjectitrepresents.
TILEMAPPING={'x':IMAGESDICT['corner'],
'#':IMAGESDICT['wall'],
'o':IMAGESDICT['insidefloor'],
'':IMAGESDICT['outsidefloor']}
OUTSIDEDECOMAPPING={'1':IMAGESDICT['rock'],
'2':IMAGESDICT['shorttree'],
'3':IMAGESDICT['talltree'],
'4':IMAGESDICT['uglytree']}

#PLAYERIMAGESisalistofallpossiblecharacterstheplayercanbe.
#currentImageistheindexoftheplayer'scurrentplayerimage.
currentImage=0
PLAYERIMAGES=[IMAGESDICT['princess'],
IMAGESDICT['boy'],
IMAGESDICT['catgirl'],
IMAGESDICT['horngirl'],
IMAGESDICT['pinkgirl']]

startScreen()#showthetitlescreenuntiltheuserpressesakey

#Readinthelevelsfromthetextfile.SeethereadLevelsFile()for
#detailsontheformatofthisfileandhowtomakeyourownlevels.
levels=readLevelsFile('starPusherLevels.txt')
currentLevelIndex=0

#Themaingameloop.Thislooprunsasinglelevel,whentheuser
#finishesthatlevel,thenext/previouslevelisloaded.
whileTrue:#maingameloop
#Runtheleveltoactuallystartplayingthegame:
result=runLevel(levels,currentLevelIndex)

ifresultin('solved','next'):
#Gotothenextlevel.
currentLevelIndex+=1
ifcurrentLevelIndex>=len(levels):
#Iftherearenomorelevels,gobacktothefirstone.
currentLevelIndex=0
elifresult=='back':
#Gotothepreviouslevel.
currentLevelIndex-=1
ifcurrentLevelIndex<0:
#Iftherearenopreviouslevels,gotothelastone.
currentLevelIndex=len(levels)-1
elifresult=='reset':
pass#Donothing.Loopre-callsrunLevel()toresetthelevel


defrunLevel(levels,levelNum):
globalcurrentImage
levelObj=levels[levelNum]
mapObj=decorateMap(levelObj['mapObj'],levelObj['startState']['player'])
gameStateObj=copy.deepcopy(levelObj['startState'])
mapNeedsRedraw=True#settoTruetocalldrawMap()
levelSurf=BASICFONT.render('Level%sof%s'%(levelNum+1,len(levels)),1,TEXTCOLOR)
levelRect=levelSurf.get_rect()
levelRect.bottomleft=(20,WINHEIGHT-35)
mapWidth=len(mapObj)*TILEWIDTH
mapHeight=(len(mapObj[0])-1)*TILEFLOORHEIGHT+TILEHEIGHT
MAX_CAM_X_PAN=abs(HALF_WINHEIGHT-int(mapHeight/2))+TILEWIDTH
MAX_CAM_Y_PAN=abs(HALF_WINWIDTH-int(mapWidth/2))+TILEHEIGHT

levelIsComplete=False
#Trackhowmuchthecamerahasmoved:
cameraOffsetX=0
cameraOffsetY=0
#Trackifthekeystomovethecameraarebeinghelddown:
cameraUp=False
cameraDown=False
cameraLeft=False
cameraRight=False

whileTrue:#maingameloop
#Resetthesevariables:
playerMoveTo=None
keyPressed=False

foreventinpygame.event.get():#eventhandlingloop
ifevent.type==QUIT:
#Playerclickedthe"X"atthecornerofthewindow.
terminate()

elifevent.type==KEYDOWN:
#Handlekeypresses
keyPressed=True
ifevent.key==K_LEFT:
playerMoveTo=LEFT
elifevent.key==K_RIGHT:
playerMoveTo=RIGHT
elifevent.key==K_UP:
playerMoveTo=UP
elifevent.key==K_DOWN:
playerMoveTo=DOWN

#Setthecameramovemode.
elifevent.key==K_a:
cameraLeft=True
elifevent.key==K_d:
cameraRight=True
elifevent.key==K_w:
cameraUp=True
elifevent.key==K_s:
cameraDown=True

elifevent.key==K_n:
return'next'
elifevent.key==K_b:
return'back'

elifevent.key==K_ESCAPE:
terminate()#Esckeyquits.
elifevent.key==K_BACKSPACE:
return'reset'#Resetthelevel.
elifevent.key==K_p:
#Changetheplayerimagetothenextone.
currentImage+=1
ifcurrentImage>=len(PLAYERIMAGES):
#Afterthelastplayerimage,usethefirstone.
currentImage=0
mapNeedsRedraw=True

elifevent.type==KEYUP:
#Unsetthecameramovemode.
ifevent.key==K_a:
cameraLeft=False
elifevent.key==K_d:
cameraRight=False
elifevent.key==K_w:
cameraUp=False
elifevent.key==K_s:
cameraDown=False

ifplayerMoveTo!=NoneandnotlevelIsComplete:
#Iftheplayerpushedakeytomove,makethemove
#(ifpossible)andpushanystarsthatarepushable.
moved=makeMove(mapObj,gameStateObj,playerMoveTo)

ifmoved:
#incrementthestepcounter.
gameStateObj['stepCounter']+=1
mapNeedsRedraw=True

ifisLevelFinished(levelObj,gameStateObj):
#levelissolved,weshouldshowthe"Solved!"image.
levelIsComplete=True
keyPressed=False

DISPLAYSURF.fill(BGCOLOR)

ifmapNeedsRedraw:
mapSurf=drawMap(mapObj,gameStateObj,levelObj['goals'])
mapNeedsRedraw=False

ifcameraUpandcameraOffsetY<MAX_CAM_X_PAN:
cameraOffsetY+=CAM_MOVE_SPEED
elifcameraDownandcameraOffsetY>-MAX_CAM_X_PAN:
cameraOffsetY-=CAM_MOVE_SPEED
ifcameraLeftandcameraOffsetX<MAX_CAM_Y_PAN:
cameraOffsetX+=CAM_MOVE_SPEED
elifcameraRightandcameraOffsetX>-MAX_CAM_Y_PAN:
cameraOffsetX-=CAM_MOVE_SPEED

#AdjustmapSurf'sRectobjectbasedonthecameraoffset.
mapSurfRect=mapSurf.get_rect()
mapSurfRect.center=(HALF_WINWIDTH+cameraOffsetX,HALF_WINHEIGHT+cameraOffsetY)

#DrawmapSurftotheDISPLAYSURFSurfaceobject.
DISPLAYSURF.blit(mapSurf,mapSurfRect)

DISPLAYSURF.blit(levelSurf,levelRect)
stepSurf=BASICFONT.render('Steps:%s'%(gameStateObj['stepCounter']),1,TEXTCOLOR)
stepRect=stepSurf.get_rect()
stepRect.bottomleft=(20,WINHEIGHT-10)
DISPLAYSURF.blit(stepSurf,stepRect)

iflevelIsComplete:
#issolved,showthe"Solved!"imageuntiltheplayer
#haspressedakey.
solvedRect=IMAGESDICT['solved'].get_rect()
solvedRect.center=(HALF_WINWIDTH,HALF_WINHEIGHT)
DISPLAYSURF.blit(IMAGESDICT['solved'],solvedRect)

ifkeyPressed:
return'solved'

pygame.display.update()#drawDISPLAYSURFtothescreen.
FPSCLOCK.tick()


defisWall(mapObj,x,y):
"""ReturnsTrueifthe(x,y)positionon
themapisawall,otherwisereturnFalse."""
ifx<0orx>=len(mapObj)ory<0ory>=len(mapObj[x]):
returnFalse#xandyaren'tactuallyonthemap.
elifmapObj[x][y]in('#','x'):
returnTrue#wallisblocking
returnFalse


defdecorateMap(mapObj,startxy):
"""Makesacopyofthegivenmapobjectandmodifiesit.
Hereiswhatisdonetoit:
*Wallsthatarecornersareturnedintocornerpieces.
*Theoutside/insidefloortiledistinctionismade.
*Tree/rockdecorationsarerandomlyaddedtotheoutsidetiles.
Returnsthedecoratedmapobject."""

startx,starty=startxy#Syntacticsugar

#Copythemapobjectsowedon'tmodifytheoriginalpassed
mapObjCopy=copy.deepcopy(mapObj)

#Removethenon-wallcharactersfromthemapdata
forxinrange(len(mapObjCopy)):
foryinrange(len(mapObjCopy[0])):
ifmapObjCopy[x][y]in('$','.','@','+','*'):
mapObjCopy[x][y]=''

#Floodfilltodetermineinside/outsidefloortiles.
floodFill(mapObjCopy,startx,starty,'','o')

#Converttheadjoinedwallsintocornertiles.
forxinrange(len(mapObjCopy)):
foryinrange(len(mapObjCopy[0])):

ifmapObjCopy[x][y]=='#':
if(isWall(mapObjCopy,x,y-1)andisWall(mapObjCopy,x+1,y))or\
(isWall(mapObjCopy,x+1,y)andisWall(mapObjCopy,x,y+1))or\
(isWall(mapObjCopy,x,y+1)andisWall(mapObjCopy,x-1,y))or\
(isWall(mapObjCopy,x-1,y)andisWall(mapObjCopy,x,y-1)):
mapObjCopy[x][y]='x'

elifmapObjCopy[x][y]==''andrandom.randint(0,99)<OUTSIDE_DECORATION_PCT:
mapObjCopy[x][y]=random.choice(list(OUTSIDEDECOMAPPING.keys()))

returnmapObjCopy


defisBlocked(mapObj,gameStateObj,x,y):
"""ReturnsTrueifthe(x,y)positiononthemapis
blockedbyawallorstar,otherwisereturnFalse."""

ifisWall(mapObj,x,y):
returnTrue

elifx<0orx>=len(mapObj)ory<0ory>=len(mapObj[x]):
returnTrue#xandyaren'tactuallyonthemap.

elif(x,y)ingameStateObj['stars']:
returnTrue#astarisblocking

returnFalse


defmakeMove(mapObj,gameStateObj,playerMoveTo):
"""Givenamapandgamestateobject,seeifitispossibleforthe
playertomakethegivenmove.Ifitis,thenchangetheplayer's
position(andthepositionofanypushedstar).Ifnot,donothing.
ReturnsTrueiftheplayermoved,otherwiseFalse."""

#Makesuretheplayercanmoveinthedirectiontheywant.
playerx,playery=gameStateObj['player']

#Thisvariableis"syntacticsugar".Typing"stars"ismore
#readablethantyping"gameStateObj['stars']"inourcode.
stars=gameStateObj['stars']

#Thecodeforhandlingeachofthedirectionsissosimilaraside
#fromaddingorsubtracting1tothex/ycoordinates.Wecan
#simplifyitbyusingthexOffsetandyOffsetvariables.
ifplayerMoveTo==UP:
xOffset=0
yOffset=-1
elifplayerMoveTo==RIGHT:
xOffset=1
yOffset=0
elifplayerMoveTo==DOWN:
xOffset=0
yOffset=1
elifplayerMoveTo==LEFT:
xOffset=-1
yOffset=0

#Seeiftheplayercanmoveinthatdirection.
ifisWall(mapObj,playerx+xOffset,playery+yOffset):
returnFalse
else:
if(playerx+xOffset,playery+yOffset)instars:
#Thereisastarintheway,seeiftheplayercanpushit.
ifnotisBlocked(mapObj,gameStateObj,playerx+(xOffset*2),playery+(yOffset*2)):
#Movethestar.
ind=stars.index((playerx+xOffset,playery+yOffset))
stars[ind]=(stars[ind][0]+xOffset,stars[ind][1]+yOffset)
else:
returnFalse
#Movetheplayerupwards.
gameStateObj['player']=(playerx+xOffset,playery+yOffset)
returnTrue


defstartScreen():
"""Displaythestartscreen(whichhasthetitleandinstructions)
untiltheplayerpressesakey.ReturnsNone."""

#Positionthetitleimage.
titleRect=IMAGESDICT['title'].get_rect()
topCoord=50#topCoordtrackswheretopositionthetopofthetext
titleRect.top=topCoord
titleRect.centerx=HALF_WINWIDTH
topCoord+=titleRect.height

#Unfortunately,Pygame'sfont&textsystemonlyshowsonelineat
#atime,sowecan'tusestringswith\nnewlinecharactersinthem.
#Sowewillusealistwitheachlineinit.
instructionText=['Pushthestarsoverthemarks.',
'Arrowkeystomove,WASDforcameracontrol,Ptochangecharacter.',
'Backspacetoresetlevel,Esctoquit.',
'Nfornextlevel,Btogobackalevel.']

#Startwithdrawingablankcolortotheentirewindow:
DISPLAYSURF.fill(BGCOLOR)

#Drawthetitleimagetothewindow:
DISPLAYSURF.blit(IMAGESDICT['title'],titleRect)

#Positionanddrawthetext.
foriinrange(len(instructionText)):
instSurf=BASICFONT.render(instructionText[i],1,TEXTCOLOR)
instRect=instSurf.get_rect()
topCoord+=10#10pixelswillgoinbetweeneachlineoftext.
instRect.top=topCoord
instRect.centerx=HALF_WINWIDTH
topCoord+=instRect.height#Adjustfortheheightoftheline.
DISPLAYSURF.blit(instSurf,instRect)

whileTrue:#Mainloopforthestartscreen.
foreventinpygame.event.get():
ifevent.type==QUIT:
terminate()
elifevent.type==KEYDOWN:
ifevent.key==K_ESCAPE:
terminate()
return#userhaspressedakey,soreturn.

#DisplaytheDISPLAYSURFcontentstotheactualscreen.
pygame.display.update()
FPSCLOCK.tick()


defreadLevelsFile(filename):
assertos.path.exists(filename),'Cannotfindthelevelfile:%s'%(filename)
mapFile=open(filename,'r')
#Eachlevelmustendwithablankline
content=mapFile.readlines()+['\r\n']
mapFile.close()

levels=[]#Willcontainalistoflevelobjects.
levelNum=0
mapTextLines=[]#containsthelinesforasinglelevel'smap.
mapObj=[]#themapobjectmadefromthedatainmapTextLines
forlineNuminrange(len(content)):
#Processeachlinethatwasinthelevelfile.
line=content[lineNum].rstrip('\r\n')

if';'inline:
#Ignorethe;lines,they'recommentsinthelevelfile.
line=line[:line.find(';')]

ifline!='':
#Thislineispartofthemap.
mapTextLines.append(line)
elifline==''andlen(mapTextLines)>0:
#Ablanklineindicatestheendofalevel'smapinthefile.
#ConvertthetextinmapTextLinesintoalevelobject.

#Findthelongestrowinthemap.
maxWidth=-1
foriinrange(len(mapTextLines)):
iflen(mapTextLines[i])>maxWidth:
maxWidth=len(mapTextLines[i])
#Addspacestotheendsoftheshorterrows.This
#ensuresthemapwillberectangular.
foriinrange(len(mapTextLines)):
mapTextLines[i]+=''*(maxWidth-len(mapTextLines[i]))

#ConvertmapTextLinestoamapobject.
forxinrange(len(mapTextLines[0])):
mapObj.append([])
foryinrange(len(mapTextLines)):
forxinrange(maxWidth):
mapObj[x].append(mapTextLines[y][x])

#Loopthroughthespacesinthemapandfindthe@,.,and$
#charactersforthestartinggamestate.
startx=None#Thexandyfortheplayer'sstartingposition
starty=None
goals=[]#listof(x,y)tuplesforeachgoal.
stars=[]#listof(x,y)foreachstar'sstartingposition.
forxinrange(maxWidth):
foryinrange(len(mapObj[x])):
ifmapObj[x][y]in('@','+'):
#'@'isplayer,'+'isplayer&goal
startx=x
starty=y
ifmapObj[x][y]in('.','+','*'):
#'.'isgoal,'*'isstar&goal
goals.append((x,y))
ifmapObj[x][y]in('$','*'):
#'$'isstar
stars.append((x,y))

#Basicleveldesignsanitychecks:
assertstartx!=Noneandstarty!=None,'Level%s(aroundline%s)in%sismissinga"@"or"+"tomarkthestartpoint.'%(levelNum+1,lineNum,filename)
assertlen(goals)>0,'Level%s(aroundline%s)in%smusthaveatleastonegoal.'%(levelNum+1,lineNum,filename)
assertlen(stars)>=len(goals),'Level%s(aroundline%s)in%sisimpossibletosolve.Ithas%sgoalsbutonly%sstars.'%(levelNum+1,lineNum,filename,len(goals),len(stars))

#Createlevelobjectandstartinggamestateobject.
gameStateObj={'player':(startx,starty),
'stepCounter':0,
'stars':stars}
levelObj={'width':maxWidth,
'height':len(mapObj),
'mapObj':mapObj,
'goals':goals,
'startState':gameStateObj}

levels.append(levelObj)

#Resetthevariablesforreadingthenextmap.
mapTextLines=[]
mapObj=[]
gameStateObj={}
levelNum+=1
returnlevels


deffloodFill(mapObj,x,y,oldCharacter,newCharacter):
"""ChangesanyvaluesmatchingoldCharacteronthemapobjectto
newCharacteratthe(x,y)position,anddoesthesameforthe
positionstotheleft,right,down,andupof(x,y),recursively."""

#Inthisgame,thefloodfillalgorithmcreatestheinside/outside
#floordistinction.Thisisa"recursive"function.
#FormoreinfoontheFloodFillalgorithm,see:
#http://en.wikipedia.org/wiki/Flood_fill
ifmapObj[x][y]==oldCharacter:
mapObj[x][y]=newCharacter

ifx<len(mapObj)-1andmapObj[x+1][y]==oldCharacter:
floodFill(mapObj,x+1,y,oldCharacter,newCharacter)#callright
ifx>0andmapObj[x-1][y]==oldCharacter:
floodFill(mapObj,x-1,y,oldCharacter,newCharacter)#callleft
ify<len(mapObj[x])-1andmapObj[x][y+1]==oldCharacter:
floodFill(mapObj,x,y+1,oldCharacter,newCharacter)#calldown
ify>0andmapObj[x][y-1]==oldCharacter:
floodFill(mapObj,x,y-1,oldCharacter,newCharacter)#callup


defdrawMap(mapObj,gameStateObj,goals):
"""DrawsthemaptoaSurfaceobject,includingtheplayerand
stars.Thisfunctiondoesnotcallpygame.display.update(),nor
doesitdrawthe"Level"and"Steps"textinthecorner."""

#mapSurfwillbethesingleSurfaceobjectthatthetilesaredrawn
#on,sothatitiseasytopositiontheentiremapontheDISPLAYSURF
#Surfaceobject.First,thewidthandheightmustbecalculated.
mapSurfWidth=len(mapObj)*TILEWIDTH
mapSurfHeight=(len(mapObj[0])-1)*TILEFLOORHEIGHT+TILEHEIGHT
mapSurf=pygame.Surface((mapSurfWidth,mapSurfHeight))
mapSurf.fill(BGCOLOR)#startwithablankcoloronthesurface.

#Drawthetilespritesontothissurface.
forxinrange(len(mapObj)):
foryinrange(len(mapObj[x])):
spaceRect=pygame.Rect((x*TILEWIDTH,y*TILEFLOORHEIGHT,TILEWIDTH,TILEHEIGHT))
ifmapObj[x][y]inTILEMAPPING:
baseTile=TILEMAPPING[mapObj[x][y]]
elifmapObj[x][y]inOUTSIDEDECOMAPPING:
baseTile=TILEMAPPING['']

#Firstdrawthebaseground/walltile.
mapSurf.blit(baseTile,spaceRect)

ifmapObj[x][y]inOUTSIDEDECOMAPPING:
#Drawanytree/rockdecorationsthatareonthistile.
mapSurf.blit(OUTSIDEDECOMAPPING[mapObj[x][y]],spaceRect)
elif(x,y)ingameStateObj['stars']:
if(x,y)ingoals:
#AgoalANDstarareonthisspace,drawgoalfirst.
mapSurf.blit(IMAGESDICT['coveredgoal'],spaceRect)
#Thendrawthestarsprite.
mapSurf.blit(IMAGESDICT['star'],spaceRect)
elif(x,y)ingoals:
#Drawagoalwithoutastaronit.
mapSurf.blit(IMAGESDICT['uncoveredgoal'],spaceRect)

#Lastdrawtheplayerontheboard.
if(x,y)==gameStateObj['player']:
#Note:Thevalue"currentImage"refers
#toakeyin"PLAYERIMAGES"whichhasthe
#specificplayerimagewewanttoshow.
mapSurf.blit(PLAYERIMAGES[currentImage],spaceRect)

returnmapSurf


defisLevelFinished(levelObj,gameStateObj):
"""ReturnsTrueifallthegoalshavestarsinthem."""
forgoalinlevelObj['goals']:
ifgoalnotingameStateObj['stars']:
#Foundaspacewithagoalbutnostaronit.
returnFalse
returnTrue


defterminate():
pygame.quit()
sys.exit()


if__name__=='__main__':
main()

关于如何在python中使用pygame框架就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。

发布于 2021-03-26 01:50:29
收藏
分享
海报
0 条评论
182
上一篇:如何在vue中使用laydate时间插件 下一篇:GenericApplicationContext怎么在Spring Boot中使用
目录

    推荐阅读

    0 条评论

    本站已关闭游客评论,请登录或者注册后再评论吧~

    忘记密码?

    图形验证码