首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

pyopengl网络游戏施用

2012-12-19 
pyopengl网络游戏应用??? ? 这个游戏很简单,可以操纵的飞机不断发子弹,前面不断有敌机来袭,子弹打中敌机然

pyopengl网络游戏应用

?

?? ? 这个游戏很简单,可以操纵的飞机不断发子弹,前面不断有敌机来袭,子弹打中敌机然后敌机和子弹消失,最后实现了网络互联功能,允许两个人在局域网中不同机器上操作各自的飞机,平且两个游戏界面是同步的。

我这样设计的:自己维护一个飞机,子弹队列,敌机队列,将网络来的数据打包成另一个飞机,子弹队列,敌机队列,所以这里面传送的数据有自己飞机数据,子弹队列,敌机队列,这些数据通过TCP在服务器和客户端之间不断更新,传递。

?? ? 图形用opengl渲染,由于python不能直接访问指针,通过网络只能传递字符串型,所以传送二进制数据有点问题,自己写了对函数,用于字符串和二进制数的转换,每个数由长度为4的字符串组成,索引高的为数据高位,最高位为符号位,所以只能保存-1600万到1600万之间的数,对于视频游戏这个范围足矣,但有个缺陷,不知道怎么传浮点数,所以需要浮点数的地方先*1000,传送后除以1000得到浮点数。

?? ? 为了更像网络游戏,跟CS一样能自动搜索局域网中的服务器,实现了一个较简单实用的方法,大致是这样的:服务器启动后开放一个udp端口udpport,客户端向局域网中所有机器udpport发送验证信息,建立一个临时TCP端口tcpport0,当服务器端客户验证通过后向刚才的客户机tcpport0发送欢迎信息,这样客户机就得到了服务器的ip地址(还可同时进行一些必要的初始化),到此客户端便开始正式通过tcp与服务器交换游戏信息。

?

pyOpengl安装方法:http://pyopengl.sourceforge.net/documentation/installation.html

?

游戏代码:

?

#-*- coding:utf-8 -*-import sys,structimport random,math,thread,time,socket,string,retry:  from OpenGL.GLUT import *  from OpenGL.GL import *  from OpenGL.GLU import *except:  print '''ERROR: PyOpenGL not installed properly.          '''  sys.exit()x_coord=10y_coord=10isAserver=False     #True为服务端,False为客户端#数值统统为4个字节,最高位为符号位,1600万足矣,低字节为低位def westicenumtostring(num):    tempnum=abs(num)    tempnum=int(tempnum)    s=''    i=0    while tempnum>0:       s=s+chr(tempnum%256)       tempnum=int(tempnum/256)        i+=1    while len(s)<3:#补齐3位       s=s+chr(0)    if num<0:        s=s+chr(1)    else:#0和正数最高位为0        s=s+chr(0)    return sdef westicestringtonum(s):    if len(s)!=4:        print 'len(s) must be 4'        return None    n0=ord(s[0])    n1=ord(s[1])    n2=ord(s[2])    n3=ord(s[3])    num=n0+256*n1+256*256*n2    if n3==1:#负数        num=(-num)    if n3!=0 and n3!=1:        return "wrong string when convert ro number"    return numdef drawenemy(x,y): #画敌人形象    glLoadIdentity()    glTranslate(x,y,0.0)    glScale(0.2,0.2,0.2)    glBegin(GL_POLYGON)      glVertex3f(1.0,1.0,0)    glVertex3f(1.0,-1.0,0)    glColor3f(1.0,0.0,0.0)    glVertex3f(-1.0,-1.0,0)    glVertex3f(-1.0,1.0,0)    glEnd()def drawbullet(x,y):#画子弹形象   glLoadIdentity()   glTranslate(x,y,0.0)   glScale(0.1,0.1,0.1)   glBegin(GL_POLYGON)     glColor3f(0.0,1.0,0.0)             glVertex3f(0.5,1.0,0)   glVertex3f(0.5,-1.0,0)   glVertex3f(-0.5,-1.0,0)   glVertex3f(-0.5,1.0,0)   glEnd()def drawpalne(x,y,rquad):#画玩家飞机形象    glLoadIdentity()    glTranslate(x,y,0.0)    glRotatef(rquad,0.0,1.0,0.0)        # Rotate     glScale(0.5,0.5,0.5)    glBegin(GL_POLYGON)                   # Start drawing     glColor3f(1.0,0.0,0.0)    glVertex3f(1.0,0.0,0.0)           glColor3f(0.0,1.0,0.0)    glVertex3f(-1.0,0.0,0.0)             glColor3f(0.0,0.0,1.0)    glVertex3f(0.0,3.0,0.0)             glEnd()                             # We are done with the polygon        glBegin(GL_POLYGON)      glVertex3f(0.0,0.0,0)    glVertex3f(0.0,3.0,0)    glColor3f(1.0,0.0,0.0)    glVertex3f(0.0,0.5,0.5)    glEnd()    class Enemy(): #定义敌人    def __init__(self):        self.reset()    def update(self):        if self.live:           self.y-=0.01           self.draw()           if self.y<0:               self.live=False     def setxy(self,x,y):        self.x=x        self.y=y    def draw(self):        drawenemy(self.x,self.y)    def reset(self):        self.x=x_coord*random.random()        self.y=y_coord        self.live=True #活着状态        class Bullet():#定义子弹    def __init__(self,x,y):        self.reset(x,y)        self.live=False    def update(self):        if self.live:           self.y+=0.05           self.draw()           if self.y>y_coord:               self.live=False               def draw(self):        drawbullet(self.x,self.y)    def reset(self,x,y):        self.x=x        self.y=y        self.live=Trueclass Plane():    def __init__(self,x,y):        self.x=x        self.y=y        self.rquad=0    def update(self):        self.draw()        if self.rquad<0:           self.rquad+=1.0        if self.rquad>0:           self.rquad-=1.0    def draw(self):        drawpalne(self.x,self.y,self.rquad)    def left(self):        self.x-=0.1        if self.rquad>-40:#限制           self.rquad-=3    def right(self):        self.x+=0.1        if self.rquad<40:           self.rquad+=3           westiceplane=Nonemyenemylist=Nonebulletlist=Noneotherplane=Noneotherenemylist=Noneotherbulletlist=Noneframeobj=None#网络用帧class netframe():    def __init__(self,player,mybulletlist,enemylist):        self.player=player        self.mybulletlist=mybulletlist        self.enemylist=enemylist    def senddata(self,conn):        global isconnected        senddata=''        senddata+=westicenumtostring(self.player.x*1000)        senddata+=westicenumtostring(self.player.y*1000)         senddata+=westicenumtostring(self.player.rquad*1000)#自己的位置        senddata+=westicenumtostring(len(self.mybulletlist))#子弹个数        for bullet in self.mybulletlist:            senddata+=westicenumtostring(bullet.x*1000)            senddata+=westicenumtostring(bullet.y*1000)#子弹位置        senddata+=westicenumtostring(len(self.enemylist))#敌人个数        for enemy in self.enemylist:            senddata+=westicenumtostring(enemy.x*1000)            senddata+=westicenumtostring(enemy.y*1000)#敌人位置        if isconnected:           try:                   conn.send(senddata)           except socket.error:              isconnected=False        #conn.sendall(senddata)    #接收数据    def recvdata(self,conn):        global otherplane        global otherenemylist        global otherbulletlist        global isconnected        if isconnected:            try:                 recvdata=conn.recv(4)                 otherplanex=westicestringtonum(recvdata)/1000.0                 recvdata=conn.recv(4)                 otherplaney=westicestringtonum(recvdata)/1000.0                 otherplane=Plane(otherplanex,otherplaney)                 recvdata=conn.recv(4)                 otherplane.rquad=westicestringtonum(recvdata)/1000.0                 recvdata=conn.recv(4)#接收子弹数据                 bulletnum=westicestringtonum(recvdata)                 otherbulletlist=[]                 for i in range(bulletnum):                     recvdata=conn.recv(4)                     bulletx=westicestringtonum(recvdata)/1000.0                     recvdata=conn.recv(4)                     bullety=westicestringtonum(recvdata)/1000.0                     bullet=Bullet(bulletx,bullety)                     bullet.live=True                     otherbulletlist.append(bullet)                                      recvdata=conn.recv(4)                 enemynum=westicestringtonum(recvdata)                 otherenemylist=[]                 for i in range(enemynum):                     recvdata=conn.recv(4)                     enemyx=westicestringtonum(recvdata)/1000.0                     recvdata=conn.recv(4)                     enemyy=westicestringtonum(recvdata)/1000.0                     enemy=Enemy()                         enemy.setxy(enemyx,enemyy)                     otherenemylist.append(enemy)            except socket.error:                isconnected=False    #游戏服务器port=8088  #主数据通道conn=None#socket连接对象,可能是服务器或客户端serverUDPport=9090  clientTCPport=9091  isconnected=Falseclass GameServer():    def __init__(self):        print '初始化游戏服务器'        global conn        global otherplane        global otherenemylist        global otherbulletlist        global frameobj        global isconnected        global serverUDPport        global clientTCPport                #服务器接收客户UDP报文,如果验证通过向客户发送TCP回应        UDPsock0=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)            UDPsock0.bind(("",serverUDPport))        #还需验证客户端,用udp        recvstring,clientaddr=UDPsock0.recvfrom(1024)        if recvstring=="west":            print "服务器收到验证from ",clientaddr[0]        UDPsock0.close()                #服务器发送tcp回应        tempconn=socket.socket(socket.AF_INET,socket.SOCK_STREAM)          tempconn.connect((clientaddr[0],clientTCPport))        tempconn.send("sure")        tempconn.close()                #创建TCP服务器        TCPsock=socket.socket(socket.AF_INET,socket.SOCK_STREAM)        TCPsock.bind(('',port))        TCPsock.listen(5)                conn,clientaddr=TCPsock.accept()        print "来自客户端:",clientaddr        isconnected=True            while isconnected: #服务端循环,先发后收            frameobj.senddata(conn)            time.sleep(0.02)            frameobj.recvdata(conn)        conn.close()            #游戏客户端class GameClient():    def __init__(self):        print '初始化游戏客户端'        global conn        global frameobj        global isconnected        global serverUDPport        global clientTCPport        self.lanserverip=None        #搜索服务器,向局域网内发送udp数据        ip=socket.gethostbyname(socket.gethostname())        match_str="\d+\.\d+\.\d+\."        ipheader=re.match(match_str,ip)        ipheader=ipheader.group()        UDPsock0=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)            for i in range(1,256):            self.lanserverip=ipheader+str(i)            UDPsock0.sendto("west",(self.lanserverip,serverUDPport))        UDPsock0.close()                #客户端建立tcp服务器  接收服务器ip和其它信息,之后断开,连接服务器的tcp        TCPsock=socket.socket(socket.AF_INET,socket.SOCK_STREAM)        TCPsock.bind(('',clientTCPport))        TCPsock.listen(5)            tempconn,serveraddr=TCPsock.accept()        hellomsg=tempconn.recv(4)        tempconn.close()        self.lanserverip=serveraddr[0]        print "服务器为:",self.lanserverip        print "服务器信息:",hellomsg                #连接tcp服务器发送数据        conn=socket.socket(socket.AF_INET,socket.SOCK_STREAM)          conn.connect((self.lanserverip,port))        isconnected=True        while isconnected:#客户端循环,先收后发            frameobj.recvdata(conn)            frameobj.senddata(conn)            time.sleep(0.02)        conn.close()def threadfunc():#线程函数    global isAserver    if isAserver:        gameserver=GameServer()    else:        gameclient=GameClient()def GameInit():    global x_coord    global y_coord    global westiceplane    global myenemylist    global mybulletlist    global frameobj    westiceplane=Plane(x_coord/2,1)#加入飞机    myenemylist=[]    for i in range(4):  #加入敌人        westiceenemy=Enemy()        myenemylist.append(westiceenemy)    mybulletlist=[]    for i in range(20):        mywesticebullet=Bullet(westiceplane.x,westiceplane.y)        mybulletlist.append(mywesticebullet)    #新建一个线程处理网络    thread.start_new_thread(threadfunc,())    frameobj=netframe(westiceplane,mybulletlist,myenemylist)    def init():    glClearColor(0.5,0.5,0.5,0.0)    glClearDepth(1.0)                    # Enables Clearing Of The Depth Buffer    glDepthFunc(GL_LESS)                # The Type Of Depth Test To Do    glEnable(GL_DEPTH_TEST)                # Enables Depth Testing    glShadeModel(GL_SMOOTH)                # Enables Smooth Color Shadingdef calcdistance(object0,object1):    return math.sqrt(pow(object0.x-object1.x,2)+pow(object0.y-object1.y,2))count=0def display():    #print 'display'    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)    westiceplane.update()    for enemy in myenemylist:        enemy.update()        if not enemy.live:            enemy.reset()         for bullet in mybulletlist:            if calcdistance(bullet,enemy)<=0.2:#是否相遇                bullet.live=False                enemy.live=False    #自动发射子弹    global count    if count>=15:        count=0        for bullet in mybulletlist:            if not bullet.live:                bullet.reset(westiceplane.x,westiceplane.y+1)#激活一颗                break        for bullet in mybulletlist:        bullet.update()        count+=1    #显示网络来的数据    global otherplane    global otherenemylist    global otherbulletlist    if isconnected and otherplane:       otherplane.draw()    if isconnected and otherbulletlist and otherenemylist and otherplane:        otherplane.draw()        for myenemy in myenemylist:            for otherbullet in otherbulletlist:                if calcdistance(otherbullet,myenemy)<=0.2:#是否相遇                   otherbullet.live=False                       myenemy.live=False           for otherenemy in otherenemylist:            if otherenemy.live:               otherenemy.draw()        for otherbullet in otherbulletlist:            if otherbullet.live:               otherbullet.draw()        glutSwapBuffers()    #glFlush()def reshape(w,h):   print 'reshape'   glViewport(0,0,w,h)   glMatrixMode(GL_PROJECTION)   glLoadIdentity()   print 'w:',w,' h:',h   if w!=0 and h!=0:       global x_coord       global y_coord       if(w<=h):          gluOrtho2D(0.0,x_coord,0.0,x_coord*h/w)       else:          gluOrtho2D(0.0,x_coord*w/h,0.0,x_coord)   glMatrixMode(GL_MODELVIEW)def keyboard(key,x,y):#   if key==chr(27):#      sys.exit(0)    if key=='a'or key=='A':       westiceplane.left()    if key=='d'or key=='D':       westiceplane.right()GameInit()glutInit(sys.argv)glutInitDisplayMode(GLUT_RGBA|GLUT_DOUBLE|GLUT_DEPTH) #使用双缓冲和深度测试glutInitWindowSize(600,500) glutInitWindowPosition(100,100)if isAserver:    glutCreateWindow('Game Server')else:    glutCreateWindow('Game Client')init()glutReshapeFunc(reshape)glutKeyboardFunc(keyboard)glutDisplayFunc(display)glutIdleFunc(display)glutMainLoop()
?

?

热点排行