Python基礎(chǔ)夠扎實(shí)了评凝,不妨挑戰(zhàn)一下二十分鐘開(kāi)發(fā)一款游戲!

一肥哎、Python及Pygame簡(jiǎn)介

作為一款開(kāi)源的程序設(shè)計(jì)語(yǔ)言篡诽,Python有著眾多優(yōu)勢(shì)。憑借著越來(lái)越豐富朱浴、功能越來(lái)越強(qiáng)大的擴(kuò)展庫(kù)达椰,Python在各個(gè)領(lǐng)域越來(lái)越突出:數(shù)據(jù)分析(R語(yǔ)言)啰劲、矩陣運(yùn)算(Matlab)、深度學(xué)習(xí)……Python的強(qiáng)大正在于它有著如此多的外部擴(kuò)展庫(kù)廷支,你可以只關(guān)注你感興趣的功能,而不必在意它的底層是如何實(shí)現(xiàn)的垛孔。 目前流行的版本是2.7與3.5施敢,后者是作為新版本有某些改變,但Python2用戶(hù)仍居多概作。不過(guò)值得注意的是Python3對(duì)于Unicode的處理更加方便悯许,也因此逐漸被普及先壕。本文的所使用Python版本為3.5谆甜。

Pygame是Python的一個(gè)package,是一個(gè)很經(jīng)典的游戲制作包谆棺,可以完成幾乎所有的2D游戲制作罕袋。Pygame需要通過(guò)pip安裝(具體可百度)浴讯,其中各模塊的方法和屬性信息可在Pygame官網(wǎng)的幫助手冊(cè)查詢(xún)。本文使用的Pygame版本匹配Python3.5-win64仰猖。

**二奈籽、初次實(shí)現(xiàn)

現(xiàn)在我們嘗試著用Pygame來(lái)制作一個(gè)微信打飛機(jī)小游戲衣屏。首先我們要做的是制作一個(gè)簡(jiǎn)單的游戲模型,而不是在一開(kāi)始就讓程序過(guò)于復(fù)雜膨疏。因此,我們從最簡(jiǎn)單的開(kāi)始卖局,先通過(guò)以下幾步來(lái)實(shí)現(xiàn)一只飛機(jī)下降的動(dòng)畫(huà)双霍。

(1)初始化Pygame主框架

(2)初始化plane類(lèi)

(3)對(duì)按鍵進(jìn)行檢查并響應(yīng)

(4)更新畫(huà)面

(5)重復(fù)(3)(4)

首先洒闸,導(dǎo)入相關(guān)庫(kù)。

import sys,pygame

from pygame.locals import*

from random import randrange

然后初始化pygame主框架单鹿。我們將會(huì)使用到display模塊下這些函數(shù):

set_mode:設(shè)定顯示的類(lèi)型和尺寸深纲。默認(rèn)為窗口,有可選參數(shù)FULLSCREEN(全屏)儒喊。

get_surface:返回一個(gè)可畫(huà)圖的Surface對(duì)象币呵,相當(dāng)于一幀。一個(gè)Surface對(duì)象到另一個(gè)Surface對(duì)象的變化即產(chǎn)生動(dòng)畫(huà)的變化芯义。其blit()方法可更新Surface對(duì)象妻柒。

flip:更新顯示。

update:更新屏幕一部分鬼癣,可以提高游戲性能啤贩”砸伲可以配合后文的RenderUpdates類(lèi)draw方法中返回的矩形列表使用。

set_caption:設(shè)定Pygame程序標(biāo)題暖庄,窗口化時(shí)會(huì)用做窗口標(biāo)題。

Pygame中兩個(gè)最重要的類(lèi)是Sprite類(lèi)和Group類(lèi)(Sprite類(lèi)將在后文飛機(jī)初始化部分介紹)惹悄。Group類(lèi)(和它的子類(lèi))是Sprite類(lèi)的容器泣港,RenderUpdates類(lèi)是Group類(lèi)的子類(lèi)价匠。創(chuàng)建了一個(gè)RenderUpdates類(lèi)對(duì)象之后,可以使用add()方法向其中添加Sprite類(lèi)對(duì)象坡氯,也就產(chǎn)生了一只飛機(jī)洋腮。用該容器存儲(chǔ)Sprite對(duì)象的好處是容易管理徐矩,并且可以只對(duì)需要進(jìn)行更新的顯示部分進(jìn)行更新叁幢,提高游戲性能曼玩。

初始化

pygame.init()

screen_size=400,600 #screen屏幕大小

pygame.display.set_mode(screen_size) #窗口

全屏為.set_mode(screen_size,FULLSCREEN)

pygame.mouse.set_visible(0) #隱藏鼠標(biāo)

plane_image=pygame.image.load('plane2.png')

導(dǎo)入飛機(jī)圖片(圖片大小應(yīng)做調(diào)整)

sprites=pygame.sprite.RenderUpdates()

創(chuàng)建Sprite的容器

sprites.add(plane())

向容器中添加一個(gè)plane對(duì)象

screen=pygame.display.get_surface()

可用于畫(huà)圖的Surface對(duì)象

bg=(255,255,255) #背景顏色RGB格式red-blue-green

screen.fill(bg) #屏幕填充背景顏色

pygame.display.flip() #顯示更新后的屏幕

構(gòu)造函數(shù)init(注意是兩個(gè)下劃線+)中image屬性可為其賦值.png/.jpg圖片以改變其外觀黍判,在這里我們先用plane_image代替,在前面的主函數(shù)編寫(xiě)中已為其指定具體的圖片(本文圖片均為自制美旧,隨代碼給出贬墩。大家也可以直接在網(wǎng)上找圖片素材或者PS自制,甚至可以直接用Python圖像處理處理)嗽测。rect屬性記錄位置信息肿孵,rect.top/bottom/left/right分別記錄坐標(biāo)信息,rect.height/width分別記錄長(zhǎng)寬晤愧。Pygame中的Sprite類(lèi)是所有可視游戲?qū)ο蟮幕?lèi),我們需要從它繼承創(chuàng)建子類(lèi)plane葵硕,用來(lái)表示下降的飛機(jī)贯吓,并覆蓋它的構(gòu)造函數(shù)和image悄谐,rect屬性(相當(dāng)于其數(shù)據(jù)成員)。

reset()函數(shù)隨機(jī)確定飛機(jī)產(chǎn)生的橫坐標(biāo)爬舰,并固定縱坐標(biāo)在畫(huà)面最上方们陆。

update()函數(shù)改變飛機(jī)的位置。當(dāng)飛機(jī)抵達(dá)畫(huà)面下方時(shí)情屹,調(diào)用reset()函數(shù)隨機(jī)重置其于頂端坪仇。

class plane(pygame.sprite.Sprite):

definit(self):

pygame.sprite.Sprite.init(self)

self.image=plane_image

self.rect=self.image.get_rect()

self.rect.top=-self.rect.height

self.rect.centerx=

randrange(screen_size[0]-self.rect.width)

+self.rect.width/2

控制飛機(jī)在窗口內(nèi)

def update(self):

self.rect.top+=1

if self.rect.top>screen_size[1]:

self.kill()

飛機(jī)飛出屏幕則將其移除

接下來(lái),只要在主程序中添加響應(yīng)部分垃你、更新部分和循環(huán)部分即可椅文。

其中pygame.event.get()獲取用戶(hù)操作事件列表,比如鍵盤(pán)輸入皆刺、鼠標(biāo)點(diǎn)擊等×枭悖可以通過(guò)判斷按鍵來(lái)做出響應(yīng)∠鄱辏現(xiàn)在我們只是簡(jiǎn)單地響應(yīng)“退出”事件,在之后程序完善時(shí)完全可以使其響應(yīng)“暫拖强鳎”痴怨、“重新開(kāi)始”等。

def clear_callback(surf,rect):

清除舊Sprite圖形

surf.fill(bg,rect)

while True:

for eventinpygame.event.get():

if event.type==QUIT: #關(guān)閉窗口

sys.exit()

if event.type==KEYDOWNand

event.key==K_ESCAPE:

Esc退出

sys.exit()

sprites.clear(screen,clear_callback)

sprites.update() def clear_callback(surf,rect):

清除舊Sprite圖形

surf.fill(bg,rect)

while True:

for eventinpygame.event.get():

if event.type==QUIT: #關(guān)閉窗口

sys.exit()

if event.type==KEYDOWNand

event.key==K_ESCAPE:

Esc退出

sys.exit()

sprites.clear(screen,clear_callback)

sprites.update()

調(diào)用update()方法更新Sprites對(duì)象

updates=sprites.draw(screen)

調(diào)用父類(lèi)RenderUpdates的draw方法

返回需要更新的部分

pygame.display.update(updates)

更新顯示

至此器予,我們將上述代碼保存在一個(gè).py文件中便可以運(yùn)行了浪藻。結(jié)果如下:


但是,實(shí)現(xiàn)后會(huì)發(fā)現(xiàn)飛機(jī)的速度實(shí)在是太快了劣摇,我們可以考慮在其構(gòu)造時(shí)為其加上幀率的限制珠移。

首先,在第一步初始化主框架的時(shí)候定義pygame中的Clock對(duì)象。

定義一個(gè)時(shí)間對(duì)象

clock=pygame.time.Clock()

最大幀率

speed=100

然后在最后主程序循環(huán)中钧惧,更新之前加入語(yǔ)句:

clock.tick(speed)

三暇韧、進(jìn)一步完善

現(xiàn)在我們已經(jīng)有了一個(gè)基本的框架,但是這僅僅是一只慢慢飛過(guò)的飛機(jī)浓瞪。不過(guò)不要灰心懈玻,我們只要再完成3小步,就可以制作出基本的打飛機(jī)小游戲啦乾颁。

(1)初始化我方戰(zhàn)機(jī)

(2)實(shí)現(xiàn)敵方戰(zhàn)機(jī)的產(chǎn)生

(3)實(shí)現(xiàn)敵我戰(zhàn)機(jī)的相互作用

首先涂乌,仿造之前敵方戰(zhàn)機(jī)的構(gòu)造方式,編寫(xiě)如下類(lèi):

class myplane(pygame.sprite.Sprite):

definit(self):

pygame.sprite.Sprite.init(self)

self.image=myplane_image

self.rect=self.image.get_rect()

self.rect.bottom=screen_size[1]

self.rect.centerx=screen_size[0]/2

def update(self,pressed_keys):

if pressed_keys[K_UP]:

self.rect.move_ip(0,-3)

if pressed_keys[K_DOWN]:

self.rect.move_ip(0,3)

if pressed_keys[K_LEFT]:

self.rect.move_ip(-3,0)

if pressed_keys[K_RIGHT]:

self.rect.move_ip(3,0)

限定player在屏幕中

if self.rect.bottom>screen_size[1]:

self.rect.bottom=screen_size[1]

elif self.rect.top<=0:

self.rect.top=0

if self.rect.left<=0:

self.rect.left=0

elif self.rect.right>screen_size[0]:

self.rect.right=screen_size[0]

其中與plane類(lèi)不同的地方有兩處英岭,一是其更新方式不同湾盒,它需要傳入一個(gè)pressed_keys參數(shù),代表鍵盤(pán)的按鍵诅妹,分別對(duì)上下左右四個(gè)鍵做出響應(yīng)罚勾。二是要限制myplane對(duì)象運(yùn)動(dòng)不超出屏幕。

接著吭狡,我們不妨把子彈bullets類(lèi)也編寫(xiě)了再把他們一起實(shí)例化尖殃。因?yàn)樽訌椀奈恢眯枰蒻yplane確定,因此我們可以在myplane類(lèi)中定義特定的fire()函數(shù)划煮,實(shí)現(xiàn)子彈的生成送丰。

def fire(self):

axis=[self.rect.centerx,self.rect.top]

new_bullets=bullets(axis)

mybullets.add(new_bullets)

all_sprites.add(new_bullets)

以下是bullets類(lèi),其構(gòu)造函數(shù)需坐標(biāo)參數(shù)axis弛秋。

class bullets(pygame.sprite.Sprite):

definit(self,axis):

pygame.sprite.Sprite.init(self)

self.image=bullets_image

self.rect=self.image.get_rect()

self.rect.centerx=axis[0]

self.rect.centery=axis[1]

def update(self):

self.rect.top-=3

if self.rect.bottom<=0:

self.kill()

現(xiàn)在這三種類(lèi)的實(shí)例化應(yīng)改為:

sprites=pygame.sprite.RenderUpdates()

sprites.add(plane())

mysprites=pygame.sprite.RenderUpdates()

myplane=myplane()

mysprites.add(myplane)

mybullets=pygame.sprite.RenderUpdates()

all_sprites=pygame.sprite.RenderUpdates()

all_sprites.add(mysprites)

all_sprites.add(sprites)

all_sprites.add(mybullets)

all_sprites表示所有的類(lèi)實(shí)例(或?qū)ο螅┢黪铮@是為了更新的簡(jiǎn)便起見(jiàn):

注意:其中plane()為plane類(lèi)的對(duì)象,但我們無(wú)法直接對(duì)其進(jìn)行操作铐懊;而myplane=myplane()這里簡(jiǎn)便起見(jiàn)對(duì)象與類(lèi)取相同的名字邀桑,之后才能在主程序中直接調(diào)用其方法(函數(shù))。

while True:

while True:

for eventinpygame.event.get():

if event.type==QUIT:

sys.exit()

elif event.type==KEYDOWNandevent.key==K_ESCAPE:

sys.exit()

myplane.fire()

pressed_keys=pygame.key.get_pressed()

clock.tick(speed)

all_sprites.clear(screen,clear_callback)

sprites.update()

mybullets.update()

mysprites.update(pressed_keys)

updates=all_sprites.draw(screen)

pygame.display.update(updates)

現(xiàn)在科乎,我們已經(jīng)有了可以運(yùn)動(dòng)的我方戰(zhàn)機(jī),雖然子彈速度太快以致于我們的子彈像是激光搶?zhuān)覀兘酉聛?lái)會(huì)解決這個(gè)問(wèn)題贼急,并且嘗試著產(chǎn)生更多的敵方戰(zhàn)機(jī)茅茂。

這兩個(gè)問(wèn)題都涉及到對(duì)象產(chǎn)生的速率,我們不妨先看看怎么產(chǎn)生更多敵方戰(zhàn)機(jī)太抓。首先應(yīng)該定義產(chǎn)生敵機(jī)事件:

ADDENEMY=pygame.USEREVENT+1 #為添加敵人創(chuàng)建自定義事件

pygame.time.set_timer(ADDENEMY,1200) #產(chǎn)生事件的時(shí)間(毫秒)

通過(guò)這種方式空闲,我們使產(chǎn)生敵機(jī)的速率降低,同樣的我們也可以這樣來(lái)限制子彈產(chǎn)生的速度(具體見(jiàn)源代碼)走敌。

然后再在循環(huán)過(guò)程中判斷事件event是否為ADDENEMY來(lái)決定是否產(chǎn)生敵機(jī)碴倾。

現(xiàn)在我們的游戲變成了這樣:


終于到了最后一步!我們只要為各種類(lèi)之間加上相應(yīng)的關(guān)系就完成啦。

對(duì)于敵機(jī)跌榔,只要觸碰到子彈便被kill异雁,對(duì)于我機(jī),只要觸碰到敵機(jī)便kill而且gameover了僧须。在主循環(huán)中可加入如下判斷語(yǔ)句:

for j in mybullets.sprites():

for i in antisprites.sprites():

if j.rect.colliderect(i.rect):

i.kill()

j.kill()

break

接下來(lái)判斷我機(jī)與敵機(jī)的位置:

其中mybullets.sprites(),antisprites.sprites()分別返回現(xiàn)有的子彈纲刀,敵機(jī)對(duì)象的列表。它們是按產(chǎn)生時(shí)間先后順序排列的担平。rect的colliderect()方法可以判斷兩個(gè)矩形是否相交并返回布爾值示绊。通過(guò)遍歷子彈和敵機(jī)對(duì)象,我們可以判斷子彈和敵機(jī)的位置關(guān)系暂论,但是考慮到一顆子彈應(yīng)該只能消滅一只敵機(jī)面褐,因此每當(dāng)一顆子彈消滅一只敵機(jī)時(shí),我們應(yīng)跳出內(nèi)層循環(huán)取胎,繼續(xù)遍歷剩下的子彈對(duì)象盆耽。

if pygame.sprite.spritecollideany(myplane,antisprites):

myplane.kill()

游戲結(jié)束提示

screen.fill((255,255,255)) #填充顏色

font=pygame.font.Font(None,48) #設(shè)置字體

text="YOU LOST!"

height=font.get_linesize() #獲取文字高度

設(shè)置字體顯示參數(shù)

antialias=1#光滑字體

black=0,0,0#字體顏色

text2=font.render(text,antialias,black)

r=text2.get_rect() #獲取文字圖形的矩形

center,top=screen.get_rect().center #設(shè)置文字位置

r.midtop=center,top

screen.blit(text2,r) #更新Surfacee對(duì)象

pygame.display.flip() #更新顯示

break

其中pygame.sprite.spritecollideany()方法可以用來(lái)判斷兩個(gè)Group里sprites對(duì)象間的交叉部分。

四扼菠、最后說(shuō)幾句

至此摄杂,我們已經(jīng)制作出了簡(jiǎn)單的打飛機(jī)小游戲。其實(shí)還有很多可以豐富改善的地方循榆,比如:

最后判斷不同對(duì)象是否接觸的時(shí)候僅僅用對(duì)象的矩形判斷可能不夠準(zhǔn)確析恢,為此我們可以考慮將對(duì)象的真實(shí)部分切分為幾個(gè)小矩形再進(jìn)行判斷;

我們的程序僅僅包含在一個(gè).py文件中秧饮,我們可以考慮對(duì)其進(jìn)行封裝映挂,把游戲?qū)ο蟆⒂螒蛐畔ⅲǖ梅值潦⒌燃?jí))柑船、游戲狀態(tài)(暫停、結(jié)束)等分別抽象成一個(gè)或幾個(gè)類(lèi)泼各,使程序更容易拓展鞍时;

我們可以使用py2exe包將.py文件制作為.exe可執(zhí)行文件。

反觀全文扣蜻,我們的整體思路應(yīng)該是:

類(lèi)的功能——類(lèi)的實(shí)現(xiàn)——類(lèi)間的關(guān)系逆巍。

我們從需要實(shí)現(xiàn)的功能出發(fā),定義相應(yīng)的類(lèi)及其方法莽使、屬性锐极;再到復(fù)雜的情形需要不同類(lèi)的相互聯(lián)系作用,因此再回頭豐富某些類(lèi)的方法(或者派生繼承)芳肌,使它們能產(chǎn)生聯(lián)系灵再;完成上述兩步之后肋层,又重新回到第一步,考慮類(lèi)仍可完善的功能翎迁,循環(huán)反復(fù)……

為了給大家一個(gè)好的學(xué)習(xí)機(jī)會(huì)栋猖!小編給大家準(zhǔn)備了十套Python零基礎(chǔ)的學(xué)習(xí)資料

加小編Python學(xué)習(xí)群:862703141?即可自動(dòng)獲取大量python視頻教程以及各類(lèi)PDF!


?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末鸳兽,一起剝皮案震驚了整個(gè)濱河市掂铐,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌揍异,老刑警劉巖全陨,帶你破解...
    沈念sama閱讀 217,657評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異衷掷,居然都是意外死亡辱姨,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,889評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門(mén)戚嗅,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)雨涛,“玉大人,你說(shuō)我怎么就攤上這事懦胞√婢茫” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,057評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵躏尉,是天一觀的道長(zhǎng)蚯根。 經(jīng)常有香客問(wèn)我,道長(zhǎng)胀糜,這世上最難降的妖魔是什么颅拦? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,509評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮教藻,結(jié)果婚禮上距帅,老公的妹妹穿的比我還像新娘。我一直安慰自己括堤,他們只是感情好碌秸,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,562評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著痊臭,像睡著了一般哮肚。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上广匙,一...
    開(kāi)封第一講書(shū)人閱讀 51,443評(píng)論 1 302
  • 那天,我揣著相機(jī)與錄音恼策,去河邊找鬼鸦致。 笑死潮剪,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的分唾。 我是一名探鬼主播抗碰,決...
    沈念sama閱讀 40,251評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼绽乔!你這毒婦竟也來(lái)了弧蝇?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,129評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤折砸,失蹤者是張志新(化名)和其女友劉穎看疗,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體睦授,經(jīng)...
    沈念sama閱讀 45,561評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡两芳,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,779評(píng)論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了去枷。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片怖辆。...
    茶點(diǎn)故事閱讀 39,902評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖删顶,靈堂內(nèi)的尸體忽然破棺而出竖螃,到底是詐尸還是另有隱情,我是刑警寧澤逗余,帶...
    沈念sama閱讀 35,621評(píng)論 5 345
  • 正文 年R本政府宣布特咆,位于F島的核電站,受9級(jí)特大地震影響猎荠,放射性物質(zhì)發(fā)生泄漏坚弱。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,220評(píng)論 3 328
  • 文/蒙蒙 一关摇、第九天 我趴在偏房一處隱蔽的房頂上張望荒叶。 院中可真熱鬧,春花似錦输虱、人聲如沸些楣。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,838評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)愁茁。三九已至,卻和暖如春亭病,著一層夾襖步出監(jiān)牢的瞬間鹅很,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,971評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工罪帖, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留促煮,地道東北人邮屁。 一個(gè)月前我還...
    沈念sama閱讀 48,025評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像菠齿,于是被迫代替她去往敵國(guó)和親佑吝。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,843評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容