Python語(yǔ)言程序設(shè)計(jì)課程論文
項(xiàng)目名稱:飛機(jī)大戰(zhàn)
?姓名:陸海波
學(xué)號(hào):171110035
班級(jí):1701
成績(jī):
博客鏈接:
摘要
飛機(jī)大戰(zhàn)是一個(gè)很經(jīng)典的大眾游戲镐确,這個(gè)學(xué)期我學(xué)習(xí)了關(guān)于Python的很多知識(shí)饼拍,所以我用Python做了這個(gè)游戲,在這個(gè)游戲中,我實(shí)現(xiàn)了游戲背景圖片的移動(dòng)效果业岁,背景音樂(lè)和飛機(jī)中彈后的一個(gè)爆炸音效操禀,還有敵機(jī)的產(chǎn)生,子彈的發(fā)射犹撒,飛機(jī)中彈銷毀和計(jì)算得分等功能折联。
目錄
?
1.引言
1.1背景
?? 飛機(jī)大戰(zhàn)是一個(gè)很經(jīng)典的大眾游戲,在學(xué)習(xí)了一個(gè)學(xué)期的Python之后识颊,我決定使用Python來(lái)學(xué)習(xí)和實(shí)現(xiàn)這個(gè)游戲诚镰。
1.2意義
??? 我覺(jué)得做這個(gè)游戲的意義就是要體現(xiàn)這個(gè)學(xué)期所學(xué)到的關(guān)于Python的知識(shí)。
1.3相關(guān)研究
??? 由于我比較喜歡游戲方面的,因此我就在網(wǎng)上學(xué)習(xí)了Pygame,Pygame是一個(gè)游戲的開(kāi)發(fā)庫(kù)怕享,包括了圖形执赡、動(dòng)畫、聲音以及鍵盤鼠標(biāo)的控制函筋。
每個(gè)游戲的核心都是一個(gè)循環(huán)沙合,將其稱為“游戲循環(huán)”。這個(gè)循環(huán)一直在不斷運(yùn)行跌帐,一遍又一遍地完成游戲工作所需的所有事情首懈。每次循環(huán)顯示一次游戲當(dāng)前畫面,稱為幀谨敛。
Pygame的游戲循環(huán)究履,主要處理3件事情:
①處理外部輸入(鼠標(biāo)點(diǎn)擊或鍵盤按下事件)
②更新游戲?qū)ο蟮臓顟B(tài)
③游戲畫面的渲染
??????? 另外Pygame還有一個(gè)時(shí)鐘,它可以控制游戲循環(huán)的快慢脸狸,也就是我們平時(shí)玩王者榮耀和吃雞的幀率FPS最仑。
1.4實(shí)現(xiàn)的功能
??? 實(shí)現(xiàn)了背景圖片的滾動(dòng)效果,背景音樂(lè)和飛機(jī)爆炸音效炊甲,敵機(jī)的產(chǎn)生泥彤,子彈的發(fā)射,飛機(jī)中彈銷毀和計(jì)算得分等功能
2. 系統(tǒng)結(jié)構(gòu)
??? 游戲的總框架如圖1所示:
圖1 游戲總框架
這個(gè)游戲的實(shí)現(xiàn)使用了Pygame模塊卿啡。實(shí)現(xiàn)功能的原理如下表1所示:
功能原理
背景圖片滾動(dòng)用兩張相同的的圖片不斷地進(jìn)行進(jìn)行重畫
背景音樂(lè)和飛機(jī)爆炸音效用pygame.mixer來(lái)播放背景音樂(lè)與飛機(jī)的爆炸音效
子彈的發(fā)射在飛機(jī)頭部坐標(biāo)繪制子彈吟吝,然后重畫子彈的移動(dòng)位置
敵機(jī)產(chǎn)生每隔一定時(shí)間在屏幕上方隨機(jī)位置繪制敵機(jī)
飛機(jī)中彈銷毀不斷地檢測(cè)我方飛機(jī)是否和敵機(jī)或者敵機(jī)子彈是否碰撞,碰撞后輪播爆炸效果圖
得分計(jì)算每次擊中敵機(jī)分?jǐn)?shù)+1
表1 功能原理
?? 類圖如圖2所示:
圖2 類圖
3. 實(shí)現(xiàn)代碼
首先颈娜,需要引進(jìn)實(shí)現(xiàn)這款游戲所需要用到的模塊
import pygame
import sys
from pygame.locals import *
import time
import random
import copy
設(shè)計(jì)背景類剑逃,繪制背景圖片,實(shí)現(xiàn)背景圖片的滾動(dòng)效果
# 背景圖片
class GameBackground:
??? image1 = None
??? image2 = None
??? main_scene =None
??? y1 = None
??? y2 = None
??? #初始化背景圖片
??? def__init__(self, scene):
??????? #加載相同張圖片資源,做交替實(shí)現(xiàn)背景圖片滾動(dòng)
???????self.image1 = pygame.image.load("images/plane/map.jpg")
???????self.image2 = copy.copy(self.image1)
??????? #保存場(chǎng)景對(duì)象
???????self.main_scene = scene
??????? #輔助移動(dòng)背景圖片
??????? self.y1 =0
??????? self.y2 =-self.main_scene.size[1]
??? #計(jì)算地圖圖片繪制坐標(biāo)
??? defaction(self):
??????? self.y1 =self.y1 + 1
??????? self.y2 =self.y2 + 1
??????? if self.y1>= self.main_scene.size[1]:
???????????self.y1 = 0
??????? if self.y2>= 0:
???????????self.y2 = -self.main_scene.size[1]
??? #繪制地圖的兩張圖片
??? defdraw(self):
???????self.main_scene.scene.blit(self.image1, (0, self.y1))
???????self.main_scene.scene.blit(self.image2, (0, self.y2))
設(shè)計(jì)我方飛機(jī)的子彈類官辽,固定飛行速度為10
# 子彈
class Bullet:
??? speed = 10
??? x = None
??? y = None
??? width = None
??? hieght = None
??? def__init__(self, x, y, w, h):
??????? self.x = x
??????? self.y = y
??????? self.width= w
???????self.height = h
??? defmove(self):
??????? self.y -=self.speed
設(shè)計(jì)敵方飛機(jī)的子彈類蛹磺,敵方飛機(jī)的子彈飛行速度為7到15的隨機(jī)值
# 敵機(jī)子彈
class EnemyBullet:
??? speed = None
??? x = None
??? y = None
??? width = None
??? hieght = None
??? def__init__(self, x, y, w, h):
??????? self.x = x
??????? self.y = y
??????? self.width= w
???????self.height = h
??????? self.speed= random.randint(7, 15)
??? defmove(self):
??????? self.y +=self.speed
設(shè)計(jì)飛機(jī)類,實(shí)現(xiàn)飛機(jī)的移動(dòng)同仆,子彈的發(fā)射等功能
# 飛機(jī)
class Plane:
??? x = None
??? y = None
??? image = []
??? main_scene =None
??? speed = 8
??? style = 0
??? width = None
??? height = None
???shoot_frequency = 0
??? bullet_image =None
??? bullets = []
??? boom = None
??? isHit = False
??? def__init__(self, scene):
??????? #加載飛機(jī)外觀圖片
???????self.image.append(pygame.image.load("images/plane/plane.png"))
???????self.image.append(pygame.image.load("images/plane/plane_left.png"))
???????self.image.append(pygame.image.load("images/plane/plane_right.png"))
??????? #加載飛機(jī)子彈圖片
???????self.bullet_image = pygame.image.load("images/plane/bullet.png")
???????self.main_scene = scene
??????? self.x =self.main_scene.size[0] / 2 - self.image[self.style].get_width() / 2
??????? self.y =600
??????? self.width= self.image[self.style].get_width()
???????self.height = self.image[self.style].get_height()
??? #發(fā)射子彈
??? defshoot(self):
??????? ifself.shoot_frequency % 15 == 0:
???????????bullet_x = self.x + self.image[self.style].get_width() // 2 -self.bullet_image.get_width() // 2
???????????bullet_y = self.y - self.bullet_image.get_height() + 10
??????????? b_w =self.bullet_image.get_width()
??????????? b_h =self.bullet_image.get_height()
???????????self.bullets.append(Bullet(bullet_x, bullet_y, b_w, b_h))
???????????self.main_scene.bullet_sound.play()
???????self.shoot_frequency += 1
??????? ifself.shoot_frequency >= 15:
???????????self.shoot_frequency = 0
??? #繪制子彈
??? defdrawBullets(self):
??????? for b inself.bullets[:]:
???????????b.move()
??????????? if b.y< 0:
???????????????self.bullets.remove(b)
???????????self.main_scene.scene.blit(self.bullet_image, (b.x, b.y))
??? #向上
??? defmoveUp(self):
?????? ?if self.y > 0:
??????????? self.y-= self.speed
??? #向下
??? defmoveDown(self):
??????? if self.y+ self.image[self.style].get_height() < self.main_scene.size[1]:
??????????? self.y+= self.speed
??? #向左
??? defmoveLeft(self):
??????? if self.x> 0:
??????????? self.x-= self.speed
??? #向右
??? defmoveRight(self):
??????? if self.x+ self.image[self.style].get_width() < self.main_scene.size[0]:
??????????? self.x+= self.speed
??? #繪制飛機(jī)
??? defdraw(self):
??????? self.main_scene.scene.blit(self.image[self.style],(self.x, self.y))
??? #設(shè)置擊中狀態(tài)
??? defsetHit(self, hit):
??????? self.isHit= hit
??????? if hit:
???????????self.main_scene.game_music.stop()
???????????self.main_scene.over_sound.play()
??????? else:
??????? ????self.x = self.main_scene.size[0] / 2 -self.image[self.style].get_width() / 2
??????????? self.y= 600
???????????self.bullets.clear()
設(shè)計(jì)敵方飛機(jī)類称开,給敵方飛機(jī)設(shè)計(jì)一個(gè)移動(dòng)軌跡
# 敵機(jī)
class Enemy:
??? image = None
??? x = None
??? y = None
??? speed = 5
??? width = None
??? hieght = None
??? def__init__(self, image, init_pos):
??????? self.image= image
??????? self.x =init_pos[0]
??????? self.y =init_pos[1]
??????? self.width= self.image.get_width()
???????self.height = self.image.get_height()
?? ?def move(self):
??????? self.y +=self.speed
設(shè)計(jì)爆炸類,用輪播圖實(shí)現(xiàn)飛機(jī)銷毀后的爆炸效果
# 爆炸效果
class Boom:
??? x = None
??? y = None
??? main_scene =None
??? image_index =0 #效果圖片播放索引
??? def__init__(self, init_pos, scene):
??????? self.x =init_pos[0]
??????? self.y =init_pos[1]
???????self.main_scene = scene
??? def show(self,images):
??????? ifself.image_index < len(images) - 1:
???????????self.main_scene.scene.blit(images[self.image_index], (self.x, self.y))
?????? ?????self.image_index += 1
設(shè)計(jì)主場(chǎng)景類乓梨,設(shè)置游戲窗口的大小和標(biāo)題等鳖轰,實(shí)現(xiàn)飛機(jī)、子彈圖片和背景音樂(lè)的加載扶镀,然后繪制圖片蕴侣,實(shí)現(xiàn)碰撞檢測(cè)以及得分計(jì)算還有鍵盤事件的處理,以及游戲結(jié)束事件臭觉。
# 主場(chǎng)景
class MainScene:
??? size = None
??? scene = None
??? bg = None
??? plane = None
??? timer = None
??? running = True
??? enemy_images =[]
??? enemies = []
??? enemy_bullet =None
??? enemy_bullets= []
???enemy_frequency = 0
??? boom_images =[]
??? booms = []
??? score = 0
???game_over_image = None
??? boom_sound =None
??? game_music =None
??? bullet_sound =None
???enemy_bullet_sound = None
??? over_sound =None
??? #初始化主場(chǎng)景
??? def__init__(self):
??????? #初始化 pygame昆雀,使用自定義字體必須用到
???????pygame.init()
??????? #場(chǎng)景尺寸
??????? self.size= (458, 752)
??????? #場(chǎng)景對(duì)象
??????? self.scene= pygame.display.set_mode([self.size[0], self.size[1]])
??????? #設(shè)置標(biāo)題
???????pygame.display.set_caption("飛機(jī)大戰(zhàn)")
??????? #創(chuàng)建clock對(duì)象控制幀數(shù)
??????? self.timer= pygame.time.Clock()
??????? #創(chuàng)建地圖對(duì)象
??????? self.bg =GameBackground(self)
??????? #創(chuàng)建飛機(jī)對(duì)象
??????? self.plane= Plane(self)
??????? #加載敵機(jī)外形圖片
??????? for n inrange(4):
???????????self.enemy_images.append(pygame.image.load("images/plane/enemy/e_"+ str(n + 1) + ".png"))
??????? #加載敵機(jī)子彈圖片
???????self.enemy_bullet = pygame.image.load("images/plane/enemy_bullet.png")
??????? #縮小敵機(jī)子彈圖片為原來(lái)的一半
??????? new_size =(self.enemy_bullet.get_width() // 2, self.enemy_bullet.get_height() // 2)
???????self.enemy_bullet = pygame.transform.scale(self.enemy_bullet, new_size)
??????? #加載爆炸效果圖片
??????? for n inrange(6):
???????????self.boom_images.append(pygame.image.load("images/plane/boom/b"+ str(n + 1) + ".png"))
??????? # GameOver的背景圖
???????self.game_over_image =pygame.image.load("images/plane/gameover.png")
??????? #加載聲音文件
???????self.game_music = pygame.mixer.Sound("music/game_music.wav")
???????self.boom_sound = pygame.mixer.Sound("sounds/plane/boom.wav")
???????self.bullet_sound =pygame.mixer.Sound("sounds/plane/bullet.wav")
???????self.enemy_bullet_sound = pygame.mixer.Sound("sounds/plane/enemy_bullet.wav")
???????self.over_sound =pygame.mixer.Sound("sounds/plane/game_over.wav")
???????self.game_music.play(-1)
??? #重置場(chǎng)景數(shù)據(jù)
??? defreset(self):
???????self.enemies.clear()
???????self.booms.clear()
???????self.enemy_bullets.clear()
??????? self.score= 0
???????self.game_music.play(-1)
??? #繪制
??? defdraw_elements(self):
??????? if notself.plane.isHit:
???????????self.bg.draw()?????????? #繪制背景
???????????self.plane.draw()??????? #繪制飛機(jī)
???? ???????self.plane.drawBullets() #繪制飛機(jī)子彈
??????????? #繪制敵機(jī)移動(dòng)
??????????? for ein self.enemies:
???????????????self.scene.blit(e.image, (e.x, e.y))
??????????? #繪制敵機(jī)子彈移動(dòng)
??????????? for ebin self.enemy_bullets:
???????????????self.scene.blit(self.enemy_bullet, (eb.x, eb.y))
??????????? #繪制敵機(jī)爆炸效果
??????????? for bin self.booms[:]:
???????????????b.show(self.boom_images)
??????????????? ifb.image_index == len(self.boom_images) - 1:
???????????????????self.booms.remove(b)
??????????? #繪制得分
??? ????????font =pygame.font.Font("fonts/katong.ttf", 30)
??????????? text =font.render("分?jǐn)?shù):"+ str(self.score), True, (255, 255, 255))
???????????text_rect = text.get_rect()
???????????text_rect.centerx = self.scene.get_rect().centerx
???????????text_rect.centery = 20
???????????self.scene.blit(text, text_rect)
??????? else:
??????????? if notself.plane.boom:
???????????????self.plane.boom = Boom([self.plane.x, self.plane.y], self)
???????????self.plane.boom.show(self.boom_images)
??????????? ifself.plane.boom.image_index == len(self.boom_images) - 1:
??????????????? #繪制最終得分文字
???????????????font = pygame.font.Font("fonts/katong.ttf", 30)
???????????????text = font.render("本次得分:"+ str(self.score), True, (255, 0, 0))
???????????????text_rect = text.get_rect()
???????????????text_rect.centerx = self.scene.get_rect().centerx
???????????????text_rect.centery = self.scene.get_rect().centery + 24
??????????????? #繪制重新開(kāi)始文字
???????????????text2 = font.render("按下回車重新開(kāi)始", True, (255, 0, 0))
???????????????text_rect2 = text2.get_rect()
???????????????text_rect2.centerx = self.scene.get_rect().centerx
???????????????text_rect2.centery = self.scene.get_rect().centery + 200
??????????????? #繪制游戲結(jié)束界面
???????????????self.scene.blit(self.game_over_image, (0, 0))
???????????????self.scene.blit(text, text_rect)
???????????????self.scene.blit(text2, text_rect2)
??? #計(jì)算元素坐標(biāo)及生成元素
??? defaction_elements(self):
??????? if notself.plane.isHit:
???????????self.bg.action()
??????????? #生成敵機(jī)辱志,需要控制生成頻率
??????????? ifself.enemy_frequency % 50 == 0:
???????????????enemy_image = self.enemy_images[random.randint(0, len(self.enemy_images)- 1)]
??????????????? #縮小敵機(jī)圖片為原來(lái)的一半
???????????????new_size = (enemy_image.get_width() // 2, enemy_image.get_height() // 2)
???????????????enemy_image = pygame.transform.scale(enemy_image, new_size)
??????????????? #設(shè)置敵機(jī)隨機(jī)外觀
???????????????enemy_pos = [random.randint(0, self.size[0] - enemy_image.get_width()),0]
???????????????enemy = Enemy(enemy_image, enemy_pos)
???????????????self.enemies.append(enemy)
??????????????? #生成敵機(jī)子彈,需要控制生成頻率
???????????????ret = random.randint(1, 100)
???????????? ???if ret >= 1 and ret <= 65: # 65%概率發(fā)射子彈
???????????????????w = self.enemy_bullet.get_width()
???????????????????h = self.enemy_bullet.get_height()
???????????????????b_x = enemy.x + enemy.width // 2 - w // 2
???????????????????b_y = enemy.y + enemy.height
???????????????????self.enemy_bullets.append(EnemyBullet(b_x, b_y, w, h))
???????????????????self.enemy_bullet_sound.play()
???????????self.enemy_frequency += 1
??????????? ifself.enemy_frequency >= 100:
???????????????self.enemy_frequency = 0
??????????? #計(jì)算敵機(jī)坐標(biāo)
??????????? for ein self.enemies[:]:
???????????????e.move()
??????????????? ife.y > self.size[1]:
???????????????????self.enemies.remove(e)
??????????? #計(jì)算敵機(jī)子彈坐標(biāo)
??????????? for ebin self.enemy_bullets[:]:
???????????????eb.move()
??????????????? ifeb.y > self.size[1]:
???????????????????self.enemy_bullets.remove(eb)
??? #處理事件
??? defhandle_event(self):
??????? for eventin pygame.event.get():
??????????? #檢測(cè)松開(kāi)鍵盤事件
??????????? if event.type== pygame.KEYUP:
??????????????? #檢測(cè)松開(kāi)的按鍵是否是方向鍵左
??????????????? ifevent.key == K_LEFT or event.key == K_RIGHT:
???????????????????self.plane.style = 0
??????????? #檢測(cè)到事件為退出時(shí)
??????????? ifevent.type == pygame.QUIT:
???????????????self.running = False
??? #碰撞檢測(cè)
??? defdetect_collision(self):
??????? if notself.plane.isHit:
??????????? for ein self.enemies[:]:
??????????????? #敵機(jī)是否被飛機(jī)子彈擊中
???????????????for b in self.plane.bullets[:]:
???????????????????if self.collision(e, b) or self.collision(b, e):
???????????????????????self.enemies.remove(e)
???????????????????????self.plane.bullets.remove(b)
???????????????????????self.booms.append(Boom([e.x, e.y], self))
???????????????????????self.score += 1
???????????????????????self.boom_sound.play()
??????????????? #敵機(jī)是否碰到飛機(jī)
???????????????if? self.collision(e, self.plane)or self.collision(self.plane, e):
???????????????????self.plane.setHit(True)
???????????????????break
?????? ?????#敵機(jī)子彈是否擊中飛機(jī)
??????????? for ebin self.enemy_bullets[:]:
??????????????? ifself.collision(eb, self.plane) or self.collision(self.plane, eb):
???????????????????self.plane.setHit(True)
???????????????????break
??? #驗(yàn)證是否碰撞
??? defcollision(self, a, b):
??????? temp1 =(b.x <= a.x + a.width <= b.x + b.width)
??????? temp2 =(b.y <= a.y + a.height <= b.y + b.height)
??????? returntemp1 and temp2
??? #處理按鍵
??? defkey_pressed(self):
??????? #獲取按下按鍵信息
???????key_pressed = pygame.key.get_pressed()
??????? if notself.plane.isHit:
??????????? ifkey_pressed[K_UP]:
???????????????self.plane.moveUp()
??????????? ifkey_pressed[K_DOWN]:
???????????????self.plane.moveDown()
??????????? ifkey_pressed[K_LEFT]:
???????????????self.plane.style = 1
???????????????self.plane.moveLeft()
??????????? ifkey_pressed[K_RIGHT]:
???????????????self.plane.style = 2
???????????????self.plane.moveRight()
??????????? ifkey_pressed[K_SPACE]:
???????????????self.plane.shoot()
??????? else:
??????????? ifkey_pressed[K_RETURN]:
??????????????? #重置游戲數(shù)據(jù)
???????????????self.plane.setHit(False)
???????????????self.reset()
??? #處理幀數(shù)
??? defset_fps(self):
??????? #刷新顯示
???????pygame.display.update()
??????? #設(shè)置幀率為60fps
???????self.timer.tick(60)
??? #主循環(huán),主要處理各種事件
??? defrun_scene(self):
??????? whileself.running:
??????????? #計(jì)算元素坐標(biāo)及生成元素
???????????self.action_elements()
??????????? #繪制元素圖片
???????????self.draw_elements()
??????????? #處理事件
???????????self.handle_event()
??????????? #碰撞檢測(cè)
???????????self.detect_collision()
??????????? #按鍵處理
???????????self.key_pressed()
??????????? #更新畫布設(shè)置fps
???????????self.set_fps()
??????????? forevent in pygame.event.get():
??????????????? ifevent.type == pygame.QUIT:
???????????????????pygame.quit()
???????????????????sys.exit()
編寫main函數(shù)狞膘,開(kāi)始游戲
if __name__ == "__main__":
??? #創(chuàng)建主場(chǎng)景
??? mainScene =MainScene()
??? #開(kāi)始游戲
???mainScene.run_scene()
4. 實(shí)驗(yàn)
5. 總結(jié)和展望
??? 這個(gè)游戲的實(shí)現(xiàn)揩懒,我是跟著網(wǎng)上的教學(xué)思路學(xué)著做的,我覺(jué)得實(shí)現(xiàn)這個(gè)飛機(jī)大戰(zhàn)的也運(yùn)用到了很多知識(shí)挽封,通過(guò)這次實(shí)驗(yàn)已球,我對(duì)Python的理解也更加深刻。我覺(jué)得這個(gè)游戲的實(shí)現(xiàn)還是有一些不足的辅愿,例如沒(méi)有實(shí)現(xiàn)多種子彈智亮,隨機(jī)道具拾取等等。