• 写简单游戏,学编程语言-python篇:传说哥大战剧毒术士


      上篇写的动画示例其实算不上一个游戏,顶多算是利用pygame进行的图形操作,今天着手实现一个小游戏:传说哥大战剧毒术士。名字很玄乎,其实就是最简单的一个射击游戏。好了废话不多说,先上截图吧:

      

      

    一、初始化程序和定义变量

      

    import pygame
    import math
    import random
    
    # 1 - Initialize the game
    pygame.init()
    # prepare the variables
    width, height = 640, 480
    screen=pygame.display.set_mode((width, height))   
    playerpos=[100,100]
    speed_x=5
    speed_y=5   
    speed_bullet=10
    speed_shit=3
    shot=0
    alive=True
    bullet=[]
    shit=[] 
    green=[0,255,0]   
    # 2 - Load images
    player = pygame.image.load("1.bmp")
    badguy = pygame.image.load("2.bmp")
    backgroud= pygame.image.load("3.bmp")
    bullet_bmp=pygame.image.load("4.bmp")
    shit_bmp=pygame.image.load("5.bmp")
    player.set_colorkey([0,0,0])
    badguy.set_colorkey([0,0,0])
    shit_bmp.set_colorkey([255,255,255])

    第一部分声明的变量中主要是传说哥的移动速度,子弹的数据,剧毒术士喷出的便便速度等。第二部分预载入图片资源:角色,背景图等。注意设置set_colorkey进行透明色处理(书上有介绍)。

    二、响应事件处理相关

      

     1 # 4 - clear the screen before drawing it again
     2      screen.fill(0)
     3     # 5 - draw the backgroud    
     4      for x in range(width/backgroud.get_width()+1):
     5          for y in range(height/backgroud.get_height()+1):
     6                 screen.blit(backgroud,(x*90,y*65))                   
     7      # 6 - loop through the events
     8      for event in pygame.event.get():
     9          # check if the event is the X button 
    10          if event.type==pygame.QUIT:
    11              # if it is quit the game
    12              pygame.quit() 
    13              exit(0)
    14          if event.type==pygame.KEYDOWN:
    15             if event.key == pygame.K_w:
    16                     playerpos[1]-=speed_y
    17             elif event.key == pygame.K_s:
    18                     playerpos[1]+=speed_y
    19             elif event.key == pygame.K_a:
    20                     playerpos[0]-=speed_x
    21             elif event.key == pygame.K_d:
    22                     playerpos[0]+=speed_x       
    23          position = pygame.mouse.get_pos()
    24          angle = math.atan2(position[1]-(playerpos[1]+32),position[0]-(playerpos[0]+32))
    25          playerrot = pygame.transform.rotate(player, 360-angle*57.29)
    26          playerpos1 = (playerpos[0]-playerrot.get_rect().width/2, playerpos[1]-playerrot.get_rect().height/2)
    27          if event.type==pygame.MOUSEBUTTONDOWN:
    28              position=pygame.mouse.get_pos()
    29              bullet.append([math.atan2(position[1]-(playerpos1[1]+32),
    30                     position[0]-(playerpos1[0]+32)),playerpos1[0]+32,playerpos1[1]+32])

      这一部分首先将加载进的背景图片利用blit函数贴到窗口里。随后进入事件循环:这里主要是两种事件:WSAD控制人物运动,鼠标点击射出子弹,由于是用鼠标控制射击方向,因此需要获取图片的新位置,简单的数学知识,偏转角计算如下图,这块的处理具体参照一篇不错的文章http://bbs.chinaunix.net/thread-4094150-1-2.html,这个小东东借鉴了里面很多知识。

      

    三、处理对战逻辑

      

     1         # 7 - process fight        
     2          screen.blit(playerrot, playerpos1)
     3          for oneshot in bullet:
     4              index=0
     5              velx=math.cos(oneshot[0])*speed_bullet
     6              vely=math.sin(oneshot[0])*speed_bullet
     7              oneshot[1]+=velx
     8              oneshot[2]+=vely
     9              if oneshot[1]<-64 or oneshot[1]>640 or oneshot[2]<-64 or oneshot[2]>480:
    10                  bullet.pop(index)
    11              index+=1
    12              for eachone in bullet:
    13                 pos_x=int(eachone[1])
    14                 pos_y=int(eachone[2])
    15                 pos=[pos_x,pos_y]
    16                 bullet_bmp_new=pygame.transform.rotate(bullet_bmp,360-eachone[0]*57.29)
    17                 screen.blit(bullet_bmp_new,pos)
    18                 pygame.display.flip()
    19          for oneshot in bullet:
    20              if oneshot[1]<badguy_pos[0]+57 and oneshot[1]>badguy_pos[0] and
    21                 oneshot[2]<badguy_pos[1]+70 and oneshot[2]>badguy_pos[1]:
    22                  shot+=1
    23                  alive=False
    24                  break
    25          if shot<5 and alive==False:
    26              badguy_x=random.randrange(0,640-57)
    27              badguy_y=random.randrange(0,480-70)
    28              badguy_pos=[badguy_x,badguy_y] 
    29              alive=True
    30          if alive ==True:
    31             screen.blit(badguy, badguy_pos)
    32          else: 
    33             pygame.quit() 
    34             exit(0)
    35          if len(shit)<2:
    36              shit.append([math.atan2(playerpos1[1]-(badguy_pos[1]+32),
    37                     playerpos1[0]-(badguy_pos[0]+32)),badguy_pos[0]+32,badguy_pos[1]+32])
    38          for oneshit in shit:
    39              index=0
    40              velx=math.cos(oneshit[0])*speed_shit
    41              vely=math.sin(oneshit[0])*speed_shit
    42              oneshit[1]+=velx
    43              oneshit[2]+=vely
    44              if oneshit[1]<-64 or oneshit[1]>640 or oneshit[2]<-64 or oneshit[2]>480:
    45                  shit.pop(index)
    46              index+=1
    47              for eachshit in shit:
    48                 pos_x=int(eachshit[1])
    49                 pos_y=int(eachshit[2])
    50                 pos=[pos_x,pos_y]
    51                 shit_bmp_new=pygame.transform.rotate(shit_bmp,360-eachshit[0]*57.29)
    52                 screen.blit(shit_bmp_new,pos)
    53                 pygame.display.flip()
    54          for oneshit in shit:
    55              if oneshit[1]<playerpos1[0]+66 and oneshit[1]>playerpos1[0] and
    56                 oneshit[2]<playerpos1[1]+66 and oneshit[2]>playerpos1[1]:
    57                 pygame.quit() 
    58                 exit(0) 
    59          pygame.display.flip() 

      每次点击一次鼠标,子弹发射,保存到列表中,但是当子弹离开屏幕需要删除掉改子弹,同时记得由第二部分保存的偏转角计算子弹的偏转。剧毒喷出的大便处理类似,也要由传说哥的位置计算出偏转角利用设定的速度甩向我们的主人公火枪哥。

       这里的输赢判定为火枪打死5个剧毒即获取胜利,扔出的便便有一次砸到我们的主人公,游戏失败即结束,不管胜利还是失败,游戏均退出处理。

    以上便是整个游戏的大体逻辑,可以看出利用python 100行左右的代码即可以实现一个最简单的人机对战,不过代码写的比较乱得说,也没有用函数编程和面向对象的东西。另外提一下写游戏这块效率性能确实不敢恭维(明显的迟钝)。。不管怎么样,利用pygame实现小游戏还是比较方便的。

      这个小游戏写的确实虽然简单和幼稚,不过花了半天时间就能从零搞起来,确实有所收获。有时间的话可以进一步增加敌方的难度和可玩性,先这样吧。

    附下代码吧:

      1 import pygame
      2 import math
      3 import random
      4 
      5 # 1 - Initialize the game
      6 pygame.init()
      7 # prepare the variables
      8 width, height = 640, 480
      9 screen=pygame.display.set_mode((width, height))   
     10 playerpos=[100,100]
     11 speed_x=5
     12 speed_y=5   
     13 speed_bullet=10
     14 speed_shit=3
     15 shot=0
     16 alive=True
     17 bullet=[]
     18 shit=[]
     19 badguy_x=random.randrange(0,640)
     20 badguy_y=random.randrange(0,480)
     21 badguy_pos=[badguy_x,badguy_y]
     22 green=[0,255,0]   
     23 # 2 - Load images
     24 player = pygame.image.load("1.bmp")
     25 badguy = pygame.image.load("2.bmp")
     26 backgroud= pygame.image.load("3.bmp")
     27 bullet_bmp=pygame.image.load("4.bmp")
     28 shit_bmp=pygame.image.load("5.bmp")
     29 player.set_colorkey([0,0,0])
     30 badguy.set_colorkey([0,0,0])
     31 shit_bmp.set_colorkey([255,255,255])
     32 # 3 - main loop
     33 while 1:
     34      # 4 - clear the screen before drawing it again
     35      screen.fill(0)
     36     # 5 - draw the backgroud    
     37      for x in range(width/backgroud.get_width()+1):
     38          for y in range(height/backgroud.get_height()+1):
     39                 screen.blit(backgroud,(x*90,y*65))
     40      
     41                 
     42      # 6 - loop through the events
     43      for event in pygame.event.get():
     44          # check if the event is the X button 
     45          if event.type==pygame.QUIT:
     46              # if it is quit the game
     47              pygame.quit() 
     48              exit(0)
     49          if event.type==pygame.KEYDOWN:
     50             if event.key == pygame.K_w:
     51                     playerpos[1]-=speed_y
     52             elif event.key == pygame.K_s:
     53                     playerpos[1]+=speed_y
     54             elif event.key == pygame.K_a:
     55                     playerpos[0]-=speed_x
     56             elif event.key == pygame.K_d:
     57                     playerpos[0]+=speed_x       
     58          position = pygame.mouse.get_pos()
     59          angle = math.atan2(position[1]-(playerpos[1]+32),position[0]-(playerpos[0]+32))
     60          playerrot = pygame.transform.rotate(player, 360-angle*57.29)
     61          playerpos1 = (playerpos[0]-playerrot.get_rect().width/2, playerpos[1]-playerrot.get_rect().height/2)
     62          if event.type==pygame.MOUSEBUTTONDOWN:
     63              position=pygame.mouse.get_pos()
     64              bullet.append([math.atan2(position[1]-(playerpos1[1]+32),
     65                     position[0]-(playerpos1[0]+32)),playerpos1[0]+32,playerpos1[1]+32])
     66          # 7 - process fight        
     67          screen.blit(playerrot, playerpos1)
     68          for oneshot in bullet:
     69              index=0
     70              velx=math.cos(oneshot[0])*speed_bullet
     71              vely=math.sin(oneshot[0])*speed_bullet
     72              oneshot[1]+=velx
     73              oneshot[2]+=vely
     74              if oneshot[1]<-64 or oneshot[1]>640 or oneshot[2]<-64 or oneshot[2]>480:
     75                  bullet.pop(index)
     76              index+=1
     77              for eachone in bullet:
     78                 pos_x=int(eachone[1])
     79                 pos_y=int(eachone[2])
     80                 pos=[pos_x,pos_y]
     81                 bullet_bmp_new=pygame.transform.rotate(bullet_bmp,360-eachone[0]*57.29)
     82                 screen.blit(bullet_bmp_new,pos)
     83                 pygame.display.flip()
     84          for oneshot in bullet:
     85              if oneshot[1]<badguy_pos[0]+57 and oneshot[1]>badguy_pos[0] and
     86                 oneshot[2]<badguy_pos[1]+70 and oneshot[2]>badguy_pos[1]:
     87                  shot+=1
     88                  alive=False
     89                  break
     90          if shot<5 and alive==False:
     91              badguy_x=random.randrange(0,640-57)
     92              badguy_y=random.randrange(0,480-70)
     93              badguy_pos=[badguy_x,badguy_y] 
     94              alive=True
     95          if alive ==True:
     96             screen.blit(badguy, badguy_pos)
     97          else: 
     98             pygame.quit() 
     99             exit(0)
    100          if len(shit)<2:
    101              shit.append([math.atan2(playerpos1[1]-(badguy_pos[1]+32),
    102                     playerpos1[0]-(badguy_pos[0]+32)),badguy_pos[0]+32,badguy_pos[1]+32])
    103          for oneshit in shit:
    104              index=0
    105              velx=math.cos(oneshit[0])*speed_shit
    106              vely=math.sin(oneshit[0])*speed_shit
    107              oneshit[1]+=velx
    108              oneshit[2]+=vely
    109              if oneshit[1]<-64 or oneshit[1]>640 or oneshit[2]<-64 or oneshit[2]>480:
    110                  shit.pop(index)
    111              index+=1
    112              for eachshit in shit:
    113                 pos_x=int(eachshit[1])
    114                 pos_y=int(eachshit[2])
    115                 pos=[pos_x,pos_y]
    116                 shit_bmp_new=pygame.transform.rotate(shit_bmp,360-eachshit[0]*57.29)
    117                 screen.blit(shit_bmp_new,pos)
    118                 pygame.display.flip()
    119          for oneshit in shit:
    120              if oneshit[1]<playerpos1[0]+66 and oneshit[1]>playerpos1[0] and
    121                 oneshit[2]<playerpos1[1]+66 and oneshit[2]>playerpos1[1]:
    122                 pygame.quit() 
    123                 exit(0) 
    124          pygame.display.flip()
    View Code
  • 相关阅读:
    ASP.NET Core 中的依赖注入 [共7篇]
    ASP.NET Core的配置(4):多样性的配置来源[下篇]
    ASP.NET Core的配置(4):多样性的配置来源[中篇]
    ASP.NET Core的配置(4):多样性的配置来源[上篇]
    ASP.NET Core的配置(3): 将配置绑定为对象[下篇]
    ASP.NET Core的配置(3): 将配置绑定为对象[上篇]
    ASP.NET Core的配置(2):配置模型详解
    ASP.NET Core的配置(1):读取配置信息
    ASP.NET Core中的依赖注入(5):ServicePrvider实现揭秘【补充漏掉的细节】
    ASP.NET Core中的依赖注入(5): ServiceProvider实现揭秘 【解读ServiceCallSite 】
  • 原文地址:https://www.cnblogs.com/lophy/p/3504180.html
Copyright © 2020-2023  润新知