python pygame实现简单的网游

简介: 版权声明:本文可能为博主原创文章,若标明出处可随便转载。 https://blog.csdn.net/Jailman/article/details/79005394 此示例为简单的实现游戏服务器端和客户端的消息同步,使用自定定义协议,引入了twisted网络框架,还有诸多不足(其实就是半成品)。
版权声明:本文可能为博主原创文章,若标明出处可随便转载。 https://blog.csdn.net/Jailman/article/details/79005394

此示例为简单的实现游戏服务器端和客户端的消息同步,使用自定定义协议,引入了twisted网络框架,还有诸多不足(其实就是半成品)。

资源下载地址:

http://download.csdn.net/download/jailman/10194853

截图



服务器端:

# coding=utf8


'''
Game server
'''

import threading
from random import randint as rint

import pygame
import queue
from pygame.locals import *
from twisted.internet import reactor
from twisted.internet.protocol import Protocol, Factory

ctrl_q = queue.Queue()
enemy_q = queue.Queue()
player_pos_q = queue.LifoQueue()

'''
The game
'''


class MySprite(pygame.sprite.Sprite):
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)
        self.master_image = None
        self.frame = 0
        self.old_frame = -1
        self.frame_width = 1
        self.frame_height = 1
        self.first_frame = 0
        self.last_frame = 0
        self.columns = 1
        self.last_time = 0
        self.direction = 0
        self.velocity = Point(0.0, 0.0)

    # X property
    def _getx(self):
        return self.rect.x

    def _setx(self, value):
        self.rect.x = value

    X = property(_getx, _setx)

    # Y property
    def _gety(self):
        return self.rect.y

    def _sety(self, value):
        self.rect.y = value

    Y = property(_gety, _sety)

    # position property
    def _getpos(self):
        return self.rect.topleft

    def _setpos(self, pos):
        self.rect.topleft = pos

    position = property(_getpos, _setpos)

    def load(self, filename, width, height, columns):
        self.master_image = pygame.image.load(filename).convert_alpha()
        self.frame_width = width
        self.frame_height = height
        self.rect = Rect(0, 0, width, height)
        self.columns = columns
        # try to auto-calculate total frames
        rect = self.master_image.get_rect()
        self.last_frame = (rect.width // width) * (rect.height // height) - 1

    def update(self, current_time, rate=30):
        # update animation frame number
        if current_time > self.last_time + rate:
            self.frame += 1
            if self.frame > self.last_frame:
                self.frame = self.first_frame
            self.last_time = current_time

        # build current frame only if it changed
        if self.frame != self.old_frame:
            frame_x = (self.frame % self.columns) * self.frame_width
            frame_y = (self.frame // self.columns) * self.frame_height
            rect = Rect(frame_x, frame_y, self.frame_width, self.frame_height)
            self.image = self.master_image.subsurface(rect)
            self.old_frame = self.frame

    def __str__(self):
        return str(self.frame) + "," + str(self.first_frame) + \
               "," + str(self.last_frame) + "," + str(self.frame_width) + \
               "," + str(self.frame_height) + "," + str(self.columns) + \
               "," + str(self.rect)


# Point class


class Point(object):
    def __init__(self, x, y):
        self.__x = x
        self.__y = y

    # X property
    def getx(self): return self.__x

    def setx(self, x): self.__x = x

    x = property(getx, setx)

    # Y property
    def gety(self): return self.__y

    def sety(self, y): self.__y = y

    y = property(gety, sety)

    def __str__(self):
        return "{X:" + "{:.0f}".format(self.__x) + \
               ",Y:" + "{:.0f}".format(self.__y) + "}"


def rungame():
    pygame.init()
    playerHealth = 100
    keys = [False, False, False, False]
    skybg = pygame.image.load("resources/images/skybg.png")
    missile = pygame.image.load("resources/images/bullet2.png")
    screen = pygame.display.set_mode((1024, 600))
    pygame.display.set_caption("ChopperGun Server")
    timer = pygame.time.Clock()
    # warship sprite
    warship_group = pygame.sprite.Group()
    # enemy sprite
    chopper_group = pygame.sprite.Group()
    # player sprite
    player_group = pygame.sprite.Group()
    player = MySprite()
    player.load("resources/images/playerchopper.png", 173, 58, 4)
    player.position = 0, 350
    player_group.add(player)
    # player missile sprite
    missile_group = pygame.sprite.Group()
    # enemy missile sprite
    enemy_missile_group = pygame.sprite.Group()
    # warship missile group
    warship_missile_group = pygame.sprite.Group()
    # flame sprite
    flame_group = pygame.sprite.Group()

    def addNewFlame(position):
        flame = MySprite()
        flame.load("resources/images/flame.png", 64, 64, 4)
        flame.position = position
        flame_group.add(flame)

    # warship flame
    warship_flame_group = pygame.sprite.Group()

    def addNewWarshipFlame(position):
        warship_flame = MySprite()
        warship_flame.load("resources/images/warship_flame.png", 64, 64, 4)
        warship_flame.position = position
        warship_flame_group.add(warship_flame)

    badtimer = 100
    badtimer1 = 0
    missile_launched = 0
    missile_hit = 0
    missile_hit_warship = 0
    total_enemy_showedup = 0
    enemy_missile_launched = 0
    warship_health = 10
    # to make autopilot missile launch interval
    tickstart = []
    tickstart.append(pygame.time.get_ticks())
    # player move speed
    player_move_speed = 5
    while True:
        # start game ticks
        timer.tick(60)
        ticks = pygame.time.get_ticks()
        screen.fill(0)
        # draw background sky
        screen.blit(skybg, (0, 0))
        # add warship sprite (only one warship on the screen)
        if len(warship_group) == 0:
            warship = MySprite()
            warship.load("resources/images/warship.png", 350, 70, 1)
            warship.position = 1024, 500
            warship_group.add(warship)
        # adjust warship to come close to player
        if warship.X < player.X + 200:
            warship.X += 1
        elif warship.X > player.X + 200:
            warship.X -= 1
        # draw warship
        warship_group.update(ticks)
        warship_group.draw(screen)

        # warship launch missile
        for warship in warship_group:
            if len(warship_missile_group) == 0:
                if warship.X < 800:
                    warship_missile = MySprite()
                    warship_missile.load(
                        "resources/images/warship_missile.png", 32, 121, 1)
                    warship_missile.position = warship.X + 160, warship.Y - 60
                    warship_missile_group.add(warship_missile)

        # guide missile & change missile position
        for warship_missilex in warship_missile_group:
            warship_missilex.Y -= 1
            if warship_missilex.Y < -121:
                warship_missile_group.remove(warship_missilex)
            # warship missile & enemy collision detect
            collision = None
            collision = pygame.sprite.spritecollideany(
                warship_missilex, chopper_group)
            if collision != None:
                if pygame.sprite.collide_circle_ratio(0.65)(warship_missilex, collision):
                    chopper_group.remove(collision)
                    flameposition = warship_missilex.position
                    addNewFlame(flameposition)
            # warship missile & enemy missile collision detect
            collision = None
            collision = pygame.sprite.spritecollideany(
                warship_missilex, enemy_missile_group)
            if collision != None:
                if pygame.sprite.collide_circle_ratio(0.65)(warship_missilex, collision):
                    enemy_missile_group.remove(collision)
                    flameposition = warship_missilex.position
                    addNewFlame(flameposition)
            # warship missile & player missile collision detect
            collision = None
            collision = pygame.sprite.spritecollideany(
                warship_missilex, missile_group)
            if collision != None:
                if pygame.sprite.collide_circle_ratio(0.65)(warship_missilex, collision):
                    missile_group.remove(collision)
                    flameposition = warship_missilex.position
                    addNewFlame(flameposition)
            # warship missile & player collision detect
            collision = None
            collision = pygame.sprite.spritecollideany(
                warship_missilex, player_group)
            if collision != None:
                if pygame.sprite.collide_circle_ratio(0.65)(warship_missilex, collision):
                    playerHealth -= 10
                    warship_missile_group.remove(warship_missilex)
                    flameposition = warship_missilex.position
                    addNewFlame(flameposition)

        # add random enenmy chopper
        badtimer -= 1
        if badtimer == 0:
            chopper = MySprite()
            chopper.load("resources/images/enemychopper.png", 173, 60, 4)
            chopper.position = 1024, rint(0, 400)
            # add enemy position to queue
            enemy_q.put(str([chopper.X, chopper.Y]))
            chopper_group.add(chopper)
            total_enemy_showedup += 1
            badtimer = 150 - (badtimer1 * 2)
            if badtimer1 >= 35:
                badtimer1 = 35
            else:
                badtimer1 += 5
        # change enemy chopper position
        for chopper in chopper_group:
            chopper.X -= 2
            if chopper.X < -173:
                chopper_group.remove(chopper)
            # enemy chopper launch missile
            if chopper.X % 500 == 0:
                enemy_missile_launched += 1
                enemy_missile = MySprite()
                enemy_missile.load("resources/images/missile.png", 64, 16, 1)
                enemy_missile.position = chopper.X, chopper.Y + 25
                enemy_missile_group.add(enemy_missile)
        # change enemy missile position
        for enemy_missilex in enemy_missile_group:
            enemy_missilex.X -= 4
            if enemy_missilex.X < -64:
                enemy_missile_group.remove(enemy_missilex)
            # enemy missile & player collision detect
            collision = None
            collision = pygame.sprite.spritecollideany(
                enemy_missilex, player_group)
            if collision != None:
                if pygame.sprite.collide_circle_ratio(0.65)(enemy_missilex, collision):
                    enemy_missile_group.remove(enemy_missilex)
                    playerHealth -= 1
                    flameposition = player.X + 70, player.Y
                    addNewFlame(flameposition)
            # enemy missile & player missile collision detect (to remove enemy/player missile & add flame)
            collision = None
            collision = pygame.sprite.spritecollideany(
                enemy_missilex, missile_group)
            if collision != None:
                if pygame.sprite.collide_circle_ratio(0.65)(enemy_missilex, collision):
                    missile_group.remove(collision)
                    enemy_missile_group.remove(enemy_missilex)
                    flameposition = enemy_missilex.X, enemy_missilex.Y - 30
                    addNewFlame(flameposition)

        # draw enemy chopper spritew
        chopper_group.update(ticks)
        chopper_group.draw(screen)
        # draw player
        player_group.update(ticks)
        player_group.draw(screen)

        # change player missile position
        for missilex in missile_group:
            missilex.velocity.x += 0.5
            missilex.X += missilex.velocity.x
            if missilex.X > 1056:
                missile_group.remove(missilex)
            # player missile & enemy chopper collision detect
            collision = None
            collision = pygame.sprite.spritecollideany(missilex, chopper_group)
            if collision != None:
                if pygame.sprite.collide_circle_ratio(1)(missilex, collision):
                    missile_hit += 1
                    chopper_group.remove(collision)
                    missile_group.remove(missilex)
                    flameposition = missilex.X + \
                                    80, missilex.Y - 30
                    addNewFlame(flameposition)
            # player missile & enemy warship collision detect
            collision = None
            collision = pygame.sprite.spritecollideany(missilex, warship_group)
            if collision != None:
                if pygame.sprite.collide_circle_ratio(0.65)(missilex, collision):
                    missile_hit_warship += 1
                    warship_health -= 1
                    missile_group.remove(missilex)
                    warshipflameposition = missilex.X + \
                                           rint(1, 100), missilex.Y - 20
                    addNewWarshipFlame(warshipflameposition)
                    # random flame after warship is destroyed
                    if warship_health == 0:
                        for i in xrange(20):
                            position = warship.X + \
                                       rint(-10, 300), warship.Y + \
                                       rint(-20, 100)
                            addNewFlame(position)
                        warship_health = 10
                        warship_group.remove(collision)

        # enemy collision with player
        collision = None
        collision = pygame.sprite.spritecollideany(player, chopper_group)
        if collision != None:
            if pygame.sprite.collide_circle_ratio(0.65)(player, collision):
                chopper_group.remove(collision)
                playerHealth -= 1
                flameposition = player.X + 70, player.Y
                addNewFlame(flameposition)

        # draw player missiles
        missile_group.update(ticks)
        missile_group.draw(screen)

        # draw enemy missiles
        enemy_missile_group.update(ticks)
        enemy_missile_group.draw(screen)

        # draw warship missile
        warship_missile_group.update(ticks)
        warship_missile_group.draw(screen)

        # draw flame
        for x in flame_group:
            if x.frame == x.last_frame:
                flame_group.remove(x)
        flame_group.update(ticks)
        flame_group.draw(screen)

        # draw warship flame
        for x in warship_flame_group:
            if x.frame == x.last_frame:
                warship_flame_group.remove(x)
        warship_flame_group.update(ticks)
        warship_flame_group.draw(screen)

        # game statistics
        font = pygame.font.SysFont(None, 25)
        text1 = font.render("Player Health: " +
                            str(playerHealth), True, (255, 0, 0))
        screen.blit(text1, (0, 480))
        text2 = font.render("Missile Launched: " +
                            str(missile_launched), True, (255, 0, 0))
        screen.blit(text2, (0, 500))
        text3 = font.render("Missile Hit: " +
                            str(missile_hit), True, (255, 0, 0))
        screen.blit(text3, (0, 520))
        if not missile_launched == 0:
            hitrate = float(missile_hit) / float(missile_launched) * 100
            text4 = font.render("Hit Rate: " +
                                str(hitrate) + "%", True, (255, 0, 0))
        else:
            text4 = font.render("Hit Rate: " +
                                "0%", True, (255, 0, 0))
        screen.blit(text4, (0, 540))
        text5 = font.render("Total Enemies: " +
                            str(total_enemy_showedup), True, (255, 0, 0))
        screen.blit(text5, (0, 560))
        text6 = font.render("Enemy Missile Launched: " +
                            str(enemy_missile_launched), True, (255, 0, 0))
        screen.blit(text6, (0, 580))

        pygame.display.update()

        key = pygame.key.get_pressed()
        if key[pygame.K_ESCAPE]:
            exit()
        for event in pygame.event.get():
            # if event.type == pygame.KEYDOWN:
            #     if event.key == K_w:
            #         keys[0] = True
            #     elif event.key == K_a:
            #         keys[1] = True
            #     elif event.key == K_s:
            #         keys[2] = True
            #     elif event.key == K_d:
            #         keys[3] = True
            # if event.type == pygame.KEYUP:
            #     if event.key == pygame.K_w:
            #         keys[0] = False
            #     elif event.key == pygame.K_a:
            #         keys[1] = False
            #     elif event.key == pygame.K_s:
            #         keys[2] = False
            #     elif event.key == pygame.K_d:
            #         keys[3] = False
            # # add missile sprite
            # if event.type == pygame.MOUSEBUTTONDOWN:
            #     pressed_array = pygame.mouse.get_pressed()
            #     for index in range(len(pressed_array)):
            #         if pressed_array[index]:
            #             if index == 0:
            #                 missile_launched += 1
            #                 missile = MySprite()
            #                 missile.load("resources/images/bullet2.png", 32, 16, 1)
            #                 missile.position = player.X + \
            #                                    120, player.Y + 35
            #                 missile_group.add(missile)
            if event.type == pygame.QUIT:
                pygame.quit()
                exit()

        # move player sprite
        if keys[0]:
            if not player.Y < 0:
                player.Y -= player_move_speed
        elif keys[1]:
            if not player.X < 0:
                player.X -= player_move_speed
        if keys[2]:
            if not player.Y > 500:
                player.Y += player_move_speed
        elif keys[3]:
            if not player.X > 1024:
                player.X += player_move_speed

        # print player.position
        '''
        Auto pilot
        The codes below will drive the player chopper automaticly
        The player vs enemy loss ratio is around 10:1
        '''
        # if not len(chopper_group) == 0:
        #     enemy = chopper_group.sprites()[0]
        #     posdiffy = enemy.Y - player.Y
        #     # print posdiffy
        #     if posdiffy < -10:
        #         for em in enemy_missile_group:
        #             if abs(em.X - player.X) < 100 and -100 < (em.Y - player.Y) < 0:
        #                 keys[0] = False
        #                 keys[2] = False
        #                 break
        #             else:
        #                 keys[0] = True
        #                 keys[2] = False
        #     elif posdiffy > 10:
        #         for em in enemy_missile_group:
        #             if abs(em.X - player.X) < 100 and 0 < (em.Y - player.Y) < 100:
        #                 keys[0] = False
        #                 keys[2] = False
        #                 break
        #             else:
        #                 keys[0] = False
        #                 keys[2] = True
        #     elif -10 <= posdiffy <= 10:
        #         keys[0] = False
        #         keys[2] = False
        #         missile_launched += 1
        #         if len(missile_group) < 2:
        #             if ticks - tickstart[0] > 200:
        #                 tickstart.pop(0)
        #                 tickstart.append(ticks)
        #                 missile = MySprite()
        #                 missile.load("resources/images/bullet2.png", 32, 16, 1)
        #                 missile.position = player.X + \
        #                                    120, player.Y + 35
        #                 missile_group.add(missile)

        '''
        Remote pilot
        The codes below will receive control orders from remote server
        '''
        if not ctrl_q.empty():
            ctrl = ctrl_q.get()
            if ctrl == "w":
                keys[0] = True
            if ctrl == "a":
                keys[1] = True
            if ctrl == "s":
                keys[2] = True
            if ctrl == "d":
                keys[3] = True
            if ctrl == "wq":
                keys[0] = False
            if ctrl == "aq":
                keys[1] = False
            if ctrl == "sq":
                keys[2] = False
            if ctrl == "dq":
                keys[3] = False
            if ctrl == "j":
                missile = MySprite()
                missile.load("resources/images/bullet2.png", 32, 16, 1)
                missile.position = player.X + \
                                   120, player.Y + 35
                missile_group.add(missile)

        if not player_pos_q.empty():
            pos = eval(player_pos_q.get())
            player.X = pos[0]
            player.Y = pos[1]


# run game in thread
class Server_Thread(threading.Thread):
    def __init__(self):
        super(Server_Thread, self).__init__()

    def run(self):
        rungame()


# twisted socket communication
class TSServProtocol(Protocol):
    def connectionMade(self):
        clnt = self.clnt = self.transport.getPeer().host
        print '...connected from :', clnt
        # start server game thread when client connects
        st = Server_Thread()
        st.start()

    def dataReceived(self, data):
        # message = "Server roger!"
        # self.transport.write('[%s] %s' % (ctime(), message))
        send_message = {"alive": "ok"}
        try:
            send_message["enemypos"] = enemy_q.get(False)
        except:
            pass
        self.transport.write(str(send_message))
        if data:
            print "Received from client: " + data
            try:
                ctrl = eval(data)["ctrl"]
                ctrl_q.put(ctrl)
                pos = eval(data)["pos"]
                player_pos_q.put(pos)
            except:
                pass



def run_socketserver(Port):
    factory = Factory()
    factory.protocol = TSServProtocol
    print 'waiting for connection...'
    reactor.listenTCP(Port, factory)
    reactor.run()


Port = 9999
run_socketserver(Port)

客户端:

# coding=utf8


'''
Game client
'''

import threading
import time
from random import randint as rint

import pygame
import queue
from pygame.locals import *
from twisted.internet import reactor
from twisted.internet.protocol import Protocol, ClientFactory

ctrl_q = queue.Queue()
pos_q = queue.LifoQueue()
enemy_q = queue.Queue()

'''
The game
'''


class MySprite(pygame.sprite.Sprite):
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)
        self.master_image = None
        self.frame = 0
        self.old_frame = -1
        self.frame_width = 1
        self.frame_height = 1
        self.first_frame = 0
        self.last_frame = 0
        self.columns = 1
        self.last_time = 0
        self.direction = 0
        self.velocity = Point(0.0, 0.0)

    # X property
    def _getx(self):
        return self.rect.x

    def _setx(self, value):
        self.rect.x = value

    X = property(_getx, _setx)

    # Y property
    def _gety(self):
        return self.rect.y

    def _sety(self, value):
        self.rect.y = value

    Y = property(_gety, _sety)

    # position property
    def _getpos(self):
        return self.rect.topleft

    def _setpos(self, pos):
        self.rect.topleft = pos

    position = property(_getpos, _setpos)

    def load(self, filename, width, height, columns):
        self.master_image = pygame.image.load(filename).convert_alpha()
        self.frame_width = width
        self.frame_height = height
        self.rect = Rect(0, 0, width, height)
        self.columns = columns
        # try to auto-calculate total frames
        rect = self.master_image.get_rect()
        self.last_frame = (rect.width // width) * (rect.height // height) - 1

    def update(self, current_time, rate=30):
        # update animation frame number
        if current_time > self.last_time + rate:
            self.frame += 1
            if self.frame > self.last_frame:
                self.frame = self.first_frame
            self.last_time = current_time

        # build current frame only if it changed
        if self.frame != self.old_frame:
            frame_x = (self.frame % self.columns) * self.frame_width
            frame_y = (self.frame // self.columns) * self.frame_height
            rect = Rect(frame_x, frame_y, self.frame_width, self.frame_height)
            self.image = self.master_image.subsurface(rect)
            self.old_frame = self.frame

    def __str__(self):
        return str(self.frame) + "," + str(self.first_frame) + \
               "," + str(self.last_frame) + "," + str(self.frame_width) + \
               "," + str(self.frame_height) + "," + str(self.columns) + \
               "," + str(self.rect)


# Point class


class Point(object):
    def __init__(self, x, y):
        self.__x = x
        self.__y = y

    # X property
    def getx(self): return self.__x

    def setx(self, x): self.__x = x

    x = property(getx, setx)

    # Y property
    def gety(self): return self.__y

    def sety(self, y): self.__y = y

    y = property(gety, sety)

    def __str__(self):
        return "{X:" + "{:.0f}".format(self.__x) + \
               ",Y:" + "{:.0f}".format(self.__y) + "}"


def rungame():
    pygame.init()
    playerHealth = 100
    keys = [False, False, False, False]
    skybg = pygame.image.load("resources/images/skybg.png")
    missile = pygame.image.load("resources/images/bullet2.png")
    screen = pygame.display.set_mode((1024, 600))
    pygame.display.set_caption("ChopperGun Client")
    timer = pygame.time.Clock()
    # warship sprite
    warship_group = pygame.sprite.Group()
    # enemy sprite
    chopper_group = pygame.sprite.Group()
    # player sprite
    player_group = pygame.sprite.Group()
    player = MySprite()
    player.load("resources/images/playerchopper.png", 173, 58, 4)
    player.position = 0, 350
    player_group.add(player)
    # player missile sprite
    missile_group = pygame.sprite.Group()
    # enemy missile sprite
    enemy_missile_group = pygame.sprite.Group()
    # warship missile group
    warship_missile_group = pygame.sprite.Group()
    # flame sprite
    flame_group = pygame.sprite.Group()

    def addNewFlame(position):
        flame = MySprite()
        flame.load("resources/images/flame.png", 64, 64, 4)
        flame.position = position
        flame_group.add(flame)

    # warship flame
    warship_flame_group = pygame.sprite.Group()

    def addNewWarshipFlame(position):
        warship_flame = MySprite()
        warship_flame.load("resources/images/warship_flame.png", 64, 64, 4)
        warship_flame.position = position
        warship_flame_group.add(warship_flame)


    missile_launched = 0
    missile_hit = 0
    missile_hit_warship = 0
    total_enemy_showedup = 0
    enemy_missile_launched = 0
    warship_health = 10
    # to make autopilot missile launch interval
    tickstart = []
    tickstart.append(pygame.time.get_ticks())
    # to calc time
    timestart = []
    timestart.append(int(time.time()))
    # player move speed
    player_move_speed = 5
    while True:
        # start game ticks
        timer.tick(60)
        ticks = pygame.time.get_ticks()
        screen.fill(0)
        # draw background sky
        screen.blit(skybg, (0, 0))
        # add warship sprite (only one warship on the screen)
        if len(warship_group) == 0:
            warship = MySprite()
            warship.load("resources/images/warship.png", 350, 70, 1)
            warship.position = 1024, 500
            warship_group.add(warship)
        # adjust warship to come close to player
        if warship.X < player.X + 200:
            warship.X += 1
        elif warship.X > player.X + 200:
            warship.X -= 1
        # draw warship
        warship_group.update(ticks)
        warship_group.draw(screen)

        # warship launch missile
        for warship in warship_group:
            if len(warship_missile_group) == 0:
                if warship.X < 800:
                    warship_missile = MySprite()
                    warship_missile.load(
                        "resources/images/warship_missile.png", 32, 121, 1)
                    warship_missile.position = warship.X + 160, warship.Y - 60
                    warship_missile_group.add(warship_missile)

        # guide missile & change missile position
        for warship_missilex in warship_missile_group:
            warship_missilex.Y -= 1
            if warship_missilex.Y < -121:
                warship_missile_group.remove(warship_missilex)
            # warship missile & enemy collision detect
            collision = None
            collision = pygame.sprite.spritecollideany(
                warship_missilex, chopper_group)
            if collision != None:
                if pygame.sprite.collide_circle_ratio(0.65)(warship_missilex, collision):
                    chopper_group.remove(collision)
                    flameposition = warship_missilex.position
                    addNewFlame(flameposition)
            # warship missile & enemy missile collision detect
            collision = None
            collision = pygame.sprite.spritecollideany(
                warship_missilex, enemy_missile_group)
            if collision != None:
                if pygame.sprite.collide_circle_ratio(0.65)(warship_missilex, collision):
                    enemy_missile_group.remove(collision)
                    flameposition = warship_missilex.position
                    addNewFlame(flameposition)
            # warship missile & player missile collision detect
            collision = None
            collision = pygame.sprite.spritecollideany(
                warship_missilex, missile_group)
            if collision != None:
                if pygame.sprite.collide_circle_ratio(0.65)(warship_missilex, collision):
                    missile_group.remove(collision)
                    flameposition = warship_missilex.position
                    addNewFlame(flameposition)
            # warship missile & player collision detect
            collision = None
            collision = pygame.sprite.spritecollideany(
                warship_missilex, player_group)
            if collision != None:
                if pygame.sprite.collide_circle_ratio(0.65)(warship_missilex, collision):
                    playerHealth -= 10
                    warship_missile_group.remove(warship_missilex)
                    flameposition = warship_missilex.position
                    addNewFlame(flameposition)

        # add random enenmy chopper
        chopper = MySprite()
        chopper.load("resources/images/enemychopper.png", 173, 60, 4)
        # chopper.position = 1024, rint(0, 400)
        # add enemy from server
        try:
            enemy_pos = eval(enemy_q.get(False))
            chopper.position = enemy_pos[0], enemy_pos[1]
            chopper_group.add(chopper)
            total_enemy_showedup += 1
        except:
            pass

        # change enemy chopper position
        for chopper in chopper_group:
            chopper.X -= 2
            if chopper.X < -173:
                chopper_group.remove(chopper)
            # enemy chopper launch missile
            if chopper.X % 500 == 0:
                enemy_missile_launched += 1
                enemy_missile = MySprite()
                enemy_missile.load("resources/images/missile.png", 64, 16, 1)
                enemy_missile.position = chopper.X, chopper.Y + 25
                enemy_missile_group.add(enemy_missile)
        # change enemy missile position
        for enemy_missilex in enemy_missile_group:
            enemy_missilex.X -= 4
            if enemy_missilex.X < -64:
                enemy_missile_group.remove(enemy_missilex)
            # enemy missile & player collision detect
            collision = None
            collision = pygame.sprite.spritecollideany(
                enemy_missilex, player_group)
            if collision != None:
                if pygame.sprite.collide_circle_ratio(0.65)(enemy_missilex, collision):
                    enemy_missile_group.remove(enemy_missilex)
                    playerHealth -= 1
                    flameposition = player.X + 70, player.Y
                    addNewFlame(flameposition)
            # enemy missile & player missile collision detect (to remove enemy/player missile & add flame)
            collision = None
            collision = pygame.sprite.spritecollideany(
                enemy_missilex, missile_group)
            if collision != None:
                if pygame.sprite.collide_circle_ratio(0.65)(enemy_missilex, collision):
                    missile_group.remove(collision)
                    enemy_missile_group.remove(enemy_missilex)
                    flameposition = enemy_missilex.X, enemy_missilex.Y - 30
                    addNewFlame(flameposition)

        # draw enemy chopper spritew
        chopper_group.update(ticks)
        chopper_group.draw(screen)
        # draw player
        player_group.update(ticks)
        player_group.draw(screen)

        # change player missile position
        for missilex in missile_group:
            missilex.velocity.x += 0.5
            missilex.X += missilex.velocity.x
            if missilex.X > 1056:
                missile_group.remove(missilex)
            # player missile & enemy chopper collision detect
            collision = None
            collision = pygame.sprite.spritecollideany(missilex, chopper_group)
            if collision != None:
                if pygame.sprite.collide_circle_ratio(1)(missilex, collision):
                    missile_hit += 1
                    chopper_group.remove(collision)
                    missile_group.remove(missilex)
                    flameposition = missilex.X + \
                                    80, missilex.Y - 30
                    addNewFlame(flameposition)
            # player missile & enemy warship collision detect
            collision = None
            collision = pygame.sprite.spritecollideany(missilex, warship_group)
            if collision != None:
                if pygame.sprite.collide_circle_ratio(0.65)(missilex, collision):
                    missile_hit_warship += 1
                    warship_health -= 1
                    missile_group.remove(missilex)
                    warshipflameposition = missilex.X + \
                                           rint(1, 100), missilex.Y - 20
                    addNewWarshipFlame(warshipflameposition)
                    # random flame after warship is destroyed
                    if warship_health == 0:
                        for i in xrange(20):
                            position = warship.X + \
                                       rint(-10, 300), warship.Y + \
                                       rint(-20, 100)
                            addNewFlame(position)
                        warship_health = 10
                        warship_group.remove(collision)

        # enemy collision with player
        collision = None
        collision = pygame.sprite.spritecollideany(player, chopper_group)
        if collision != None:
            if pygame.sprite.collide_circle_ratio(0.65)(player, collision):
                chopper_group.remove(collision)
                playerHealth -= 1
                flameposition = player.X + 70, player.Y
                addNewFlame(flameposition)

        # draw player missiles
        missile_group.update(ticks)
        missile_group.draw(screen)

        # draw enemy missiles
        enemy_missile_group.update(ticks)
        enemy_missile_group.draw(screen)

        # draw warship missile
        warship_missile_group.update(ticks)
        warship_missile_group.draw(screen)

        # draw flame
        for x in flame_group:
            if x.frame == x.last_frame:
                flame_group.remove(x)
        flame_group.update(ticks)
        flame_group.draw(screen)

        # draw warship flame
        for x in warship_flame_group:
            if x.frame == x.last_frame:
                warship_flame_group.remove(x)
        warship_flame_group.update(ticks)
        warship_flame_group.draw(screen)

        # game statistics
        font = pygame.font.SysFont(None, 25)
        text1 = font.render("Player Health: " +
                            str(playerHealth), True, (255, 0, 0))
        screen.blit(text1, (0, 480))
        text2 = font.render("Missile Launched: " +
                            str(missile_launched), True, (255, 0, 0))
        screen.blit(text2, (0, 500))
        text3 = font.render("Missile Hit: " +
                            str(missile_hit), True, (255, 0, 0))
        screen.blit(text3, (0, 520))
        if not missile_launched == 0:
            hitrate = float(missile_hit) / float(missile_launched) * 100
            text4 = font.render("Hit Rate: " +
                                str(hitrate) + "%", True, (255, 0, 0))
        else:
            text4 = font.render("Hit Rate: " +
                                "0%", True, (255, 0, 0))
        screen.blit(text4, (0, 540))
        text5 = font.render("Total Enemies: " +
                            str(total_enemy_showedup), True, (255, 0, 0))
        screen.blit(text5, (0, 560))
        text6 = font.render("Enemy Missile Launched: " +
                            str(enemy_missile_launched), True, (255, 0, 0))
        screen.blit(text6, (0, 580))

        pygame.display.update()

        '''
        Local human pilot
        The codes below will drive the player chopper with local control
        '''
        # key = pygame.key.get_pressed()
        # if key[pygame.K_ESCAPE]:
        #     exit()
        # for event in pygame.event.get():
        #     if event.type == pygame.KEYDOWN:
        #         if event.key == K_w:
        #             keys[0] = True
        #         elif event.key == K_a:
        #             keys[1] = True
        #         elif event.key == K_s:
        #             keys[2] = True
        #         elif event.key == K_d:
        #             keys[3] = True
        #     if event.type == pygame.KEYUP:
        #         if event.key == pygame.K_w:
        #             keys[0] = False
        #         elif event.key == pygame.K_a:
        #             keys[1] = False
        #         elif event.key == pygame.K_s:
        #             keys[2] = False
        #         elif event.key == pygame.K_d:
        #             keys[3] = False
        #     # add missile sprite
        #     if event.type == pygame.MOUSEBUTTONDOWN:
        #         pressed_array = pygame.mouse.get_pressed()
        #         for index in range(len(pressed_array)):
        #             if pressed_array[index]:
        #                 if index == 0:
        #                     missile_launched += 1
        #                     missile = MySprite()
        #                     missile.load("resources/images/bullet2.png", 32, 16, 1)
        #                     missile.position = player.X + \
        #                         120, player.Y + 35
        #                     missile_group.add(missile)
        #     if event.type == pygame.QUIT:
        #         pygame.quit()
        #         exit()

        # move player sprite
        if keys[0]:
            if not player.Y < 0:
                player.Y -= player_move_speed
        elif keys[1]:
            if not player.X < 0:
                player.X -= player_move_speed
        if keys[2]:
            if not player.Y > 500:
                player.Y += player_move_speed
        elif keys[3]:
            if not player.X > 1024:
                player.X += player_move_speed

        # print player.position
        '''
        Auto pilot
        The codes below will drive the player chopper automaticly
        The player vs enemy loss ratio is around 10:1
        '''
        # if not len(chopper_group) == 0:
        #     enemy = chopper_group.sprites()[0]
        #     posdiffy = enemy.Y - player.Y
        #     # print posdiffy
        #     if posdiffy < -10:
        #         for em in enemy_missile_group:
        #             if abs(em.X - player.X) < 100 and -100 < (em.Y - player.Y) < 0:
        #                 keys[0] = False
        #                 keys[2] = False
        #                 break
        #             else:
        #                 keys[0] = True
        #                 keys[2] = False
        #     elif posdiffy > 10:
        #         for em in enemy_missile_group:
        #             if abs(em.X - player.X) < 100 and 0 < (em.Y - player.Y) < 100:
        #                 keys[0] = False
        #                 keys[2] = False
        #                 break
        #             else:
        #                 keys[0] = False
        #                 keys[2] = True
        #     elif -10 <= posdiffy <= 10:
        #         keys[0] = False
        #         keys[2] = False
        #         missile_launched += 1
        #         if len(missile_group) < 2:
        #             if ticks - tickstart[0] > 200:
        #                 tickstart.pop(0)
        #                 tickstart.append(ticks)
        #                 missile = MySprite()
        #                 missile.load("resources/images/bullet2.png", 32, 16, 1)
        #                 missile.position = player.X + \
        #                                    120, player.Y + 35
        #                 missile_group.add(missile)

        '''
        Remote pilot
        The codes below will send control orders to remote server
        '''
        key = pygame.key.get_pressed()
        if key[pygame.K_ESCAPE]:
            exit()
        for event in pygame.event.get():
            if event.type == pygame.KEYDOWN:
                if event.key == K_w:
                    keys[0] = True
                    ctrl_q.put("w")
                elif event.key == K_a:
                    keys[1] = True
                    ctrl_q.put("a")
                elif event.key == K_s:
                    keys[2] = True
                    ctrl_q.put("s")
                elif event.key == K_d:
                    keys[3] = True
                    ctrl_q.put("d")
            if event.type == pygame.KEYUP:
                if event.key == pygame.K_w:
                    keys[0] = False
                    ctrl_q.put("wq")
                elif event.key == pygame.K_a:
                    keys[1] = False
                    ctrl_q.put("aq")
                elif event.key == pygame.K_s:
                    keys[2] = False
                    ctrl_q.put("sq")
                elif event.key == pygame.K_d:
                    keys[3] = False
                    ctrl_q.put("dq")
            if event.type == pygame.QUIT:
                pygame.quit()
                exit()
            # add missile sprite
            if event.type == pygame.MOUSEBUTTONDOWN:
                pressed_array = pygame.mouse.get_pressed()
                for index in range(len(pressed_array)):
                    if pressed_array[index]:
                        if index == 0:
                            ctrl_q.put("j")
                            missile_launched += 1
                            missile = MySprite()
                            missile.load("resources/images/bullet2.png", 32, 16, 1)
                            missile.position = player.X + \
                                               120, player.Y + 35
                            missile_group.add(missile)

        # player position
        # timenow = time.time()
        # if timenow - timestart[0] > 1:
        #     timestart.pop()
        #     timestart.append(timenow)
        #     print "ingame:" + str(player.position)
        pos_q.put(str([player.X, player.Y]))


# run game in thread
class Client_Thread(threading.Thread):
    def __init__(self):
        super(Client_Thread, self).__init__()

    def run(self):
        rungame()


ct = Client_Thread()
ct.start()


# twisted socket communication
class TSClntProtocol(Protocol):
    def sendData(self):
        send_message = {"alive": "ok"}
        try:
            ctrl = ctrl_q.get(False)
            send_message["ctrl"] = ctrl
            pos = pos_q.get(False)
            send_message["pos"] = pos
        except:
            pass

        # print send_message
        self.transport.write(str(send_message))

    def connectionMade(self):
        self.sendData()

    def dataReceived(self, data):
        if data:
            print data
            try:
                enemypos = eval(data)["enemypos"]
                enemy_q.put(enemypos)
            except:
                pass
            self.sendData()
        else:
            self.transport.loseConnection()


class TSClntFactory(ClientFactory):
    protocol = TSClntProtocol
    clientConnectionLost = clientConnectionFailed = \
        lambda self, connector, reason: reactor.stop()


def run_socketclient(Host, Port):
    reactor.connectTCP(Host, Port, TSClntFactory())
    reactor.run()


Host = "127.0.0.1"
Port = 9999
run_socketclient(Host, Port)


目录
相关文章
|
12天前
|
JSON 开发工具 git
基于Python和pygame的植物大战僵尸游戏设计源码
本项目是基于Python和pygame开发的植物大战僵尸游戏,包含125个文件,如PNG图像、Python源码等,提供丰富的游戏开发学习素材。游戏设计源码可从提供的链接下载。关键词:Python游戏开发、pygame、植物大战僵尸、源码分享。
|
2月前
|
数据采集 前端开发 Python
Python pygame 实现游戏 彩色 五子棋 详细注释 附源码 单机版
Python pygame 实现游戏 彩色 五子棋 详细注释 附源码 单机版
78 0
|
4月前
|
定位技术 Python
【python】python基于pygame坦克大战游戏设计(源码+图像+操作说明)【独一无二】
【python】python基于pygame坦克大战游戏设计(源码+图像+操作说明)【独一无二】
|
4月前
|
Linux iOS开发 MacOS
【Python】Python基于Pygame疯狂赛车游戏设计(源码+报告)【独一无二】
【Python】Python基于Pygame疯狂赛车游戏设计(源码+报告)【独一无二】
|
4月前
|
Python
【python】python基于pygame弹珠游戏设计(源码)【独一无二】
【python】python基于pygame弹珠游戏设计(源码)【独一无二】
|
4月前
|
算法 数据安全/隐私保护 UED
【python】python基于Pygame扫雷游戏设计实现(源码+报告)【独一无二】
【python】python基于Pygame扫雷游戏设计实现(源码+报告)【独一无二】
|
6月前
|
开发框架 Python
Python的`pygame`库用于2D游戏开发,涵盖图形、音频和输入处理。
【6月更文挑战第21天】Python的`pygame`库用于2D游戏开发,涵盖图形、音频和输入处理。要开始,先通过`pip install pygame`安装。基本流程包括:初始化窗口、处理事件循环、添加游戏元素(如玩家和敌人)、响应用户输入、更新游戏状态及结束条件。随着项目发展,可逐步增加复杂性。
152 1
|
6月前
|
Linux 开发工具 开发者
Pygame是一个免费且开源的Python库
【6月更文挑战第12天】Pygame是一个免费且开源的Python库
111 3
|
6月前
|
Python
【Python的魅力】:利用Pygame实现游戏坦克大战——含完整源码
【Python的魅力】:利用Pygame实现游戏坦克大战——含完整源码
|
6月前
|
索引 Python
技术好文共享:用Python的Pygame包做飞行棋
技术好文共享:用Python的Pygame包做飞行棋