pygame实现雷电游戏雏形开发
本文实例为大家分享了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()
测试画面:
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持【听图阁-专注于Python设计】。