pygame开发的"雷电"游戏雏形

资源文件上传到个人资源里了

源代码:

stars.py

#-*- coding=utf-8 -*-
#!/usr/bin/python

import pygame
from pygame.locals import *
from random import randint
import math
 
class Star(object):
    def __init__(self, x, y, speed, color=(255,255,255)):
 
        self.x = x
        self.y = y
        self.speed = speed
        self.color = color

class Stars(object):
    '''
        用于绘制星星背景
    '''
    def __init__(self, num = 0, SCREEN_SIZE=(800,600), color=(255,255,255)):
        self.stars = []
        self.MIN_SPEED = 10
        self.MAX_SPEED = 300
        self.SCREEN_SIZE = SCREEN_SIZE
        if num > 0:
            self.create_star(num, color)

    def set_min_speed(self,speed):
        self.MIN_SPEED = speed
    def set_max_speed(self,speed):
        self.MAX_SPEED = speed

    def create_star(self,num = 1, color = (255,255,255)):
        '''创建一个或多个星星,颜色可选'''
        for i in xrange(0,num):
            x = float(randint(0, self.SCREEN_SIZE[0]))
            y = float(randint(0, self.SCREEN_SIZE[1]))
            speed = float(randint(self.MIN_SPEED, self.MAX_SPEED))
            self.stars.append( Star(x, y, speed, color) )

    def move(self,time_passed_seconds):
        '''移动星星并过滤'''
        for star in self.stars:
            star.y = star.y + time_passed_seconds * star.speed
        #过滤跑出画面的星星
        self.stars = filter(lambda one: one.y<=self.SCREEN_SIZE[1], self.stars)

    def draw(self, surface):
        '''将星星画到指定图像对象'''
        for star in self.stars:
            #pygame.draw.aaline(surface, star.color,\
            #        (star.x, star.y), (star.x+1., star.y))
            surface.set_at((int(star.x),int(star.y)),star.color)
 

def test():
 
    pygame.init()
    screen = pygame.display.set_mode((800, 600)) #, FULLSCREEN)
 
    stars = Stars()
    #stars.set_max_speed(1000)
    #stars.set_min_speed(300)
 
    # 在第一帧,画上一些星星
    stars.create_star(200)
     
    clock = pygame.time.Clock()
 
    white = (255, 255, 255)
     
    while True:
 
        for event in pygame.event.get():
            if event.type == QUIT:
                return
            if event.type == KEYDOWN:
                return

        time_passed = clock.tick(30)
        time_passed_seconds = time_passed / 1000.
 
        #update_background(stars, screen, time_passed_seconds)
        # 增加一颗新的星星
        stars.create_star(1)
        stars.move(time_passed_seconds)
 
        screen.fill((0, 0, 0))
 
        # 绘制所有的星
        stars.draw(screen)
 
        pygame.display.update()
 
if __name__ == "__main__":
    test()

game.py

#-*- coding=utf-8 -*-
#!/usr/bin/python

import pygame
from pygame.locals import *
from random import randint
#from gameobjects import vector2
import math
import time

SCREEN_RECT = pygame.Rect(0,0,800,600)

class Player(pygame.sprite.Sprite):
    '''玩家类'''
    speed  = 10
    images = []
    def __init__(self):
        pygame.sprite.Sprite.__init__(self, self.containers)
        self.image = Player.images[0]
        self.rect  = self.image.get_rect(midbottom=SCREEN_RECT.midbottom)
        self.health= 4
        #self.time  = 0
        #self.reloading = False

    #def update(self, time_passed_seconds=0.0): if not self.reloading: super(Player,self).update(time_passed_seconds) else: self.time += time_passed_seconds if self.time > 1.5: print self.time self.time = 0.0 self.reloading = False self.groups()[0].remove(self)

    def move(self, directions):
        '''移动,direction == 'up' or 'down' or 'left' or 'right' '''
        for direction in directions:
            if direction == 'up':
                self.rect.move_ip(0, -1 * Player.speed)
            elif direction == 'down':
                self.rect.move_ip(0, 1 * Player.speed)
            elif direction == 'left':
                self.rect.move_ip(-1 * Player.speed, 0)
            elif direction == 'right':
                self.rect.move_ip(1 * Player.speed, 0)
            else:
                print 'argument error'
                return None
        self.rect.clamp_ip(SCREEN_RECT)

    def shoted_and_live(self, harm):
        '''被攻击处理,依然存活返回True,否则返回False'''
        self.health -= harm
        if self.health <= 0:
            return False
        else:
            return True

    def attack_pos(self):
        return self.rect.x + self.rect.width / 2, self.rect.y

class Shot(pygame.sprite.Sprite):
    '''通用子弹类'''
    speed_tab = [ 13, 13, 26, 30 ]
    #子弹攻击力表
    harm_tab  = [  1,  2 , 3, 12]
    images    = []
    #子弹大小表
    shot_size = []
    def __init__(self, pos, angle, id=1 ):
        '''pos为射出位置
           angle参数为子弹射出的方向角度,以12点钟方向为0度,逆时针增大'''
        pygame.sprite.Sprite.__init__(self, self.containers)
        self.id    = id
        self.angle = angle
        self.speed = Shot.speed_tab[id-1]
        self.harm  = Shot.harm_tab[id-1]
        self.image = pygame.transform.scale(Shot.images[id-1], Shot.shot_size[id-1])
        self.image = pygame.transform.rotate(self.image, angle)
        self.rect  = self.image.get_rect(midbottom=pos)

    def update(self,time_passed_seconds=0.0):
        radian = self.angle / 180.0 * math.pi
        self.rect.move_ip(math.sin(radian) * -self.speed,\
                -self.speed * math.cos(radian) )
        if self.rect.x+self.rect.width < 0 or\
                self.rect.x > SCREEN_RECT.width or\
                self.rect.y+self.rect.height < 0 or\
                self.rect.y > SCREEN_RECT.height:
            self.kill()

class AlienShot(Shot):
    '''
        敌方子弹类
        为了对象分组专为敌人的子弹使用一个新类,并定制子弹射速
    '''
    def __init__(self, pos, angle, id=1, speed=20 ):
        Shot.__init__(self, pos, angle, id)
        self.speed = speed

def SectorShot(pos, shot_id):
    '''扇形子弹的封装'''
    Shot(pos, 0,  shot_id)
    Shot(pos, 15, shot_id)
    Shot(pos, 30, shot_id)
    Shot(pos, 45, shot_id)
    Shot(pos, 315,shot_id)
    Shot(pos, 330,shot_id)
    Shot(pos, 345,shot_id)


def CommonShot(pos, shot_id):
    '''常规子弹'''
    Shot(pos, 0, shot_id)

class Alien(pygame.sprite.Sprite):
    '''通用敌人类'''
    #默认速度表,速度为像素/秒
    speed_tab = [ 400, 200, 200 ]
    images= []
    #用于射击间隔
    times = [0.15, 0.3, 0.4]
    
    def __init__(self, id=1, health=5):
        pygame.sprite.Sprite.__init__(self, self.containers)
        self.id     = id
        self.speed  = Alien.speed_tab[id-1]
        self.health = health
        self.image  = Alien.images[id-1]
        self.rect   = self.image.get_rect()
        self.rect.topleft = (randint(0, SCREEN_RECT.width-self.rect.width),0)

        self.move_tab  = [ self.move_line, self.move_circle, self.move_curve ]
        #用于射击的时间计算
        self.time   = 0.0

    def update(self, time_passed_seconds=0.0):
        self.move_tab[self.id-1](time_passed_seconds)
        if self.rect.x < 0 or self.rect.x > SCREEN_RECT.width or self.rect.y < 0 or self.rect.y > SCREEN_RECT.height:
            self.kill()
        self.time += time_passed_seconds
        if self.time > Alien.times[self.id-1]:
            self.time = 0.0
            if self.id == 1:
                AlienShot(self.attack_pos(), 180, 1, 30)
            elif self.id == 2:
                AlienShot(self.attack_pos(), 120, 1, 10)
                AlienShot(self.attack_pos(), 150, 1, 10)
                AlienShot(self.attack_pos(), 180, 1, 10)
                AlienShot(self.attack_pos(), 210, 1, 10)
                AlienShot(self.attack_pos(), 240, 1, 10)
            elif self.id == 3:
                AlienShot(self.attack_pos(), 180, 2, 10)


    def shoted_and_live(self, harm):
        '''被攻击处理,依然存活返回True,否则返回False'''
        self.health -= harm
        if self.health <= 0:
            return False
        else:
            return True

    def move_line(self, time_passed_seconds):
        self.rect.move_ip(0, self.speed * time_passed_seconds)

    def move_circle(self, time_passed_seconds):
        if not hasattr(self, 'angle'):
            self.angle = 180
        else:
            self.angle = self.angle+time_passed_seconds*360
        if not hasattr(self, 'radius'):
            self.radius = 60
        if not hasattr(self, 'center'):
            x = self.rect.x+self.radius if self.rect.x < self.radius else self.rect.x-self.radius
            self.center = [ x, 0+self.radius]
        self.center[1] += 2
        new_pos = self.__circle_next( self.center, self.radius, self.angle) 
        #self.rect.move_ip(new_pos[0], new_pos[1])
        self.rect.x, self.rect.y = new_pos[0], new_pos[1]

    def __circle_next(self, center, radius, angle):
        x = math.sin(angle/180.0*math.pi) * radius + center[0]
        y = math.cos(angle/180.0*math.pi) * radius + center[1]
        return x, y

    def move_curve(self, time_passed_seconds):
        if not hasattr(self, 'ray'):
            self.ray = self.rect.x
        if not hasattr(self, 'angle'):
            self.angle = 0
        else:
            self.angle = self.angle + time_passed_seconds * 360
        if not hasattr(self, 'curve_width'):
            self.curve_width = 50
        x = math.sin(self.angle/180*math.pi) * self.curve_width + self.ray
        y = self.rect.y + self.speed * time_passed_seconds
        self.rect.x, self.rect.y = x, y

    def attack_pos(self):
        return self.rect.x + self.rect.width / 2, self.rect.y + self.rect.height
    
class Explosion(pygame.sprite.Sprite):
    '''爆炸类'''
    #用于存储爆炸图像每帧的坐标
    areas  = [\
(0,0,104,135), (104,0,104,135), (208,0,104,135),(312,0,104,135),(416,0,94,135),\
(0,135,102,112),(102,135,102,112),(204,135,102,112),(306,135,102,112),(408,135,102,112),\
(0,247,108,144),(108,247,100,144),(208,247,102,144),(310,247,100,144),(412,247,98,144),\
(0,400,95,100) ]
    images = []
    
    def __init__(self, pos, id=1, areas=None):
        pygame.sprite.Sprite.__init__(self, self.containers)
        self.pos = pos
        self.fps = 0
        self.image_data = Explosion.images[id-1]
        if areas is not None:
            self.areas = areas

        self.update()


    def update(self, time_passed_seconds=0.0):
        self.rect  = pygame.Rect(self.areas[self.fps])
        self.image = self.image_data.subsurface(Rect(self.areas[self.fps]))
        self.rect.topleft = self.pos
        self.fps += 1
        if self.fps >= len(self.areas):
            self.kill()

class Score(pygame.sprite.Sprite):

    score = 0
    health= 0
    life  = 0
    def __init__(self, font_type = "文泉驿点阵正黑"):
        pygame.sprite.Sprite.__init__(self)
        self.font =  pygame.font.SysFont(font_type, 20)
        self.color=  (255,255,255)
        self.msg  =  u"得分:%d\n生命:%d"
        self.update()
        self.rect =  self.image.get_rect()
        self.rect.topleft = (10,10)

    def update(self, time_passed_seconds=0.0):
        self.msg = u"生命:%d   得分:%d"% (Score.life, Score.score)
        self.image = self.font.render(self.msg, True, self.color)

main.py

#-*- coding=utf-8 -*-
#!/usr/bin/python

import os
import time
import pygame
from pygame.locals import *
from random import randint

import stars 
from game import *

#默认星空的速度
default_stars_speed = (50, 300)
#子弹种数和当前子弹ID,以及对应的子弹大小、发射频率(个/秒)
SHOT_NUM = 4
shot_id  = 1
shot_size= [(2,9), (16, 16), (19,14), (99,120)]
shot_rate= [ 0.15, 0.3, 0.10, 0.7 ]

dest_area = [\
(0,0,104,135), (104,0,104,135), (208,0,104,135),(312,0,104,135),(416,0,104,135),\
(0,135,102,112),(102,135,102,112),(204,135,102,112),(306,135,102,112),(408,135,102,112),\
(0,247,108,144),(108,247,100,144),(208,247,102,144),(310,247,100,144),(412,247,98,144),\
(0,400,95,100) ]

star_bmg = []
def update_background(stars, screen, time_passed_seconds):
    '''在指定图像上生成一些星星并移动,绘制'''
    stars.create_star(2,(randint(0,255),randint(0,255),randint(0,255)))
    #stars.create_star(1,(255,255,255))
    stars.move(time_passed_seconds)
    screen.fill((0, 0, 0))
    stars.draw(screen) 
    #screen.blit(star_bmg[0],(100,100))
    #screen.blit(star_bmg[1],(100,100))

def load_image(file, alpha=False):
    '''加载一张图片,可指定是否为alpha转换'''
    file = 'data/image/' + file
    try:
        surface = pygame.image.load(file)
    except pygame.error:
        raise SystemExit('加载图像 "%s" 失败 %s' % (file, pygame.get_error()) )
    if alpha:
        return surface.convert_alpha()
    return surface.convert()

def load_sound(file):
    file = 'data/music/' + file
    try:
        sound = pygame.mixer.Sound(file)
        return sound
    except pygame.error:
        print ('加载音乐 "%s" 失败' % file)
    return None

def main():
    global shot_id 
    global star_bmg

    pygame.mixer.pre_init(44100, -16, 2, 4096)
    pygame.init()
    screen = pygame.display.set_mode((800, 600)) #, FULLSCREEN)
 
    #加载各种资源数据
    image_list        = os.listdir('data/image')
    image_list.sort()
    Player.images     = [ load_image(file,True) for file in image_list if 'player' in file  ]
    Alien.images      = [ pygame.transform.rotate(load_image(file,True),180)\
                            for file in image_list if 'alien' in file  ]
    Shot.images       = [ load_image(file,True) for file in image_list if 'shot'   in file  ]
    star_bmg          = [ load_image(file,True) for file in image_list if 'star' in file ]

    Shot.shot_size    = shot_size
    shot_sound        = load_sound('shot2.wav')
    Explosion.images  = [ load_image(file,True) for file in image_list if 'explosion' in file ]
    explosion_sound1  = load_sound('explosion1.wav')
    explosion_sound2  = load_sound('explosion2.wav')
    change_shot_sound = load_sound('change_shot.wav')
    alarm_sound       = load_sound('alarm.wav')
    #加载并播放BGM
    pygame.mixer.music.load('data/music/bgm01.ogg')
    pygame.mixer.music.play(-1)

    # 初始化并生成一些星星
    world = stars.Stars(200)
    world.set_min_speed(default_stars_speed[0])
    world.set_max_speed(default_stars_speed[1])

    #为各种游戏对象分组,all组存储了所有游戏对象
    shots = pygame.sprite.Group()  #玩家的子弹和敌人的子弹分成2组
    alien_shots = pygame.sprite.Group() 
    aliens= pygame.sprite.Group()
    explosions = pygame.sprite.Group()
    all   = pygame.sprite.Group()

    Player.containers = all
    Alien.containers = aliens, all
    Shot.containers   = shots, all
    AlienShot.containers = alien_shots, all
    Explosion.containers = explosions, all

    player = Player()

    #玩家生命数,重载标志和重载时间
    life   = 3
    reloading = False
    reloading_time = 1.5

    Score.score = 0
    Score.life  = life
    score = Score()
    all.add(score)
    #无敌标志,重生后需要进入一段无敌时间
    iamyourdaddy = False

    clock = pygame.time.Clock()
    prev_time = 0.0
     
    while life or len(explosions.sprites())>0:
        allkill=None 
        for event in pygame.event.get():
            if event.type == QUIT:
                return
            if event.type == KEYDOWN and event.key == K_ESCAPE:
                return
            if event.type == KEYDOWN:
                #处理子弹切换
                if event.key == K_TAB:
                    shot_id = shot_id % SHOT_NUM + 1
                    change_shot_sound.play()
                elif event.key == K_x:
                    for alien in aliens:
                        alien.kill()
                        explosion_sound2.play()
                        Explosion(alien.rect.topleft)
                    for shot in alien_shots:
                        shot.kill()
                        explosion_sound2.play()
                        Explosion(shot.rect.topleft)

        keystate = pygame.key.get_pressed()
        time_passed = clock.tick(30)
        time_passed_seconds = time_passed / 1000.

        update_background(world, screen, time_passed_seconds)
        #all.clear(screen, screen)
        all.update(time_passed_seconds)

        #处理方向控制
        direct = []
        if keystate[K_UP]:
            direct.append('up')
            #模拟加速星空
            world.set_min_speed(default_stars_speed[0] * 10)
            world.set_max_speed(default_stars_speed[1] * 2)
        if keystate[K_DOWN]:
            direct.append('down')
            #模拟减速星空
            world.set_min_speed(10)
            world.set_max_speed(default_stars_speed[1] / 2)
        if keystate[K_LEFT]:
            direct.append('left')
        if keystate[K_RIGHT]:
            direct.append('right')
        player.move(direct)
        #若不是上下则恢复默认速度
        if  not (keystate[K_UP] or keystate[K_DOWN]):
            world.set_min_speed(default_stars_speed[0])
            world.set_max_speed(default_stars_speed[1])

        #处理攻击行为,用攻击间隔控制频率
        if  not reloading and keystate[K_SPACE]:
            if time.time()-prev_time > shot_rate[shot_id-1]:
                #第二个参数为射出角度,以12点钟方向为0度逆时针变大
                #Shot(player.attack_pos(), 45, shot_id)
                if shot_id==1:
                    SectorShot(player.attack_pos(), shot_id)
                else:
                    CommonShot(player.attack_pos(), shot_id)
                shot_sound.play()
                #Explosion(player.attack_pos())
                prev_time = time.time()

        #随机生成敌人,不同敌人血量不同
        n = randint(0,100)
        if n==1: 
            Alien(1,3)
        elif n==2:
            Alien(2,5)
        elif n==3:
            Alien(3,5)

        #处理玩家子弹与敌方的碰撞,碰撞字典键为第一个组的对象,值为第二个组的对象列表
        collide_dict = pygame.sprite.groupcollide(aliens,shots,False,False)
        for alien in collide_dict:
            for shot in collide_dict[alien]:
                if shot_id!=4:
                    shot.kill()
                explosion_sound1.play()
                harm = shot.harm
                if not alien.shoted_and_live(harm):
                    Score.score += 1
                    alien.kill()
                    explosion_sound2.play()
                    Explosion(alien.rect.topleft)

        #检测无敌时间是否结束
        if iamyourdaddy:
            wait += time_passed_seconds
            if wait > 1.5:
                iamyourdaddy = False
                wait = 0.0

        #如果玩家处于重生中则不检测玩家碰撞
        if not reloading:
            #处理玩家与敌人的碰撞
            for alien in pygame.sprite.spritecollide(player, aliens,True):
                explosion_sound2.play()
                Explosion(alien.rect.topleft)
                if iamyourdaddy:
                    pass
                else:
                    alarm_sound.play(2)

                    Explosion(player.rect.topleft)
                    Score.score += 1
                    Score.life  -= 1
                    player.kill()
                    reloading = True
                    wait = 0.0
                    life -= 1

        if not reloading:
            #处理玩家与敌方子弹的碰撞
            for shot in pygame.sprite.spritecollide(player, alien_shots, True):
                explosion_sound1.play()
                harm = shot.harm
                if iamyourdaddy:
                    pass
                elif not player.shoted_and_live(harm):
                    alarm_sound.play(2)

                    explosion_sound2.play()
                    Explosion(player.rect.topleft)
                    Score.life  -= 1
                    player.kill()
                    reloading = True
                    wait = 0.0
                    life -= 1

        #处理子弹与子弹的碰撞
        if shot_id==4:
            collide_dict = pygame.sprite.groupcollide(alien_shots,shots,True,False)
            for alien_shot in collide_dict:
                explosion_sound2.play()
                Explosion(alien_shot.rect.topleft)

        #死亡后重置玩家,生命数-1
        if reloading:  
            wait += time_passed_seconds 
            if wait > reloading_time: 
                reloading = False 
                player = Player()
                wait = 0.0
                #进入无敌模式
                iamyourdaddy = True

        # 增加一颗新的星星
        #stars.create_star(1)
        #stars.move(time_passed_seconds)
        #screen.fill((0, 0, 0))
        # 绘制所有的星
        #stars.draw(screen)
        #screen.blit(image,(300,300))
        all.draw(screen)
        pygame.display.update()

    #绘制结束画面
    #设置字体
    font = pygame.font.SysFont("文泉驿点阵正黑", 80)
    end  = font.render(u"YOU LOST!!!", True, (255,0,0))
    screen.blit(end, (180, 270))
    pygame.display.update()
    time.sleep(2.5)
 
if __name__ == "__main__":
    main()


测试画面:

pygame开发的



你可能感兴趣的:(python)