pygame实现雷电游戏雏形开发

yipeiwu_com5年前Python基础

本文实例为大家分享了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设计】。

相关文章

详解Python的Django框架中的模版继承

在实际应用中,你将用 Django 模板系统来创建整个 HTML 页面。 这就带来一个常见的 Web 开发问题: 在整个网站中,如何减少共用页面区域(比如站点导航)所引起的重复和冗余代码...

Python中list查询及所需时间计算操作示例

本文实例讲述了Python中list查询及所需时间计算操作。分享给大家供大家参考,具体如下: # -*-coding=utf-8 -*- #! python2 #filename:...

python实现银联支付和支付宝支付接入

本文实例为大家分享了python银联支付和支付宝支付接入的具体代码,供大家参考,具体内容如下 前置条件:需要安装Python的OpenSSL模块,我使用的版本是16.1.0,可以使用pi...

Python中修改字符串的四种方法

在Python中,字符串是不可变类型,即无法直接修改字符串的某一位字符。  因此改变一个字符串的元素需要新建一个新的字符串。 常见的修改方法有以下4种。 方法1:将字符串转...

Django后端发送小程序微信模板消息示例(服务通知)

Django后端发送小程序微信模板消息示例(服务通知)

模板消息 官方文档:https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/template-mess...