国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Python “貪吃蛇”游戲,在不斷改進(jìn)中學(xué)習(xí)pygame編程

這篇具有很好參考價(jià)值的文章主要介紹了Python “貪吃蛇”游戲,在不斷改進(jìn)中學(xué)習(xí)pygame編程。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

Python “貪吃蛇”游戲,在不斷改進(jìn)中學(xué)習(xí)pygame編程,Python,pygame,python,開發(fā)語(yǔ)言

目錄

前言

改進(jìn)過程一

增加提示信息

原版幫助摘要

pygame.draw

pygame.font

class Rect

class Surface

改進(jìn)過程二

增加顯示得分

改進(jìn)過程三

增加背景景樂

增加提示音效

音樂切換

靜音切換

mixer.music.play 注意事項(xiàng)

原版幫助摘要

pygame.mixer

pygame.mixer.Sound

改進(jìn)過程四

增加WASD方向鍵

增加退出事件的確認(rèn)

小結(jié)

pygame編程框架

完整代碼


前言

在上一篇博文里,從訊飛星火中獲取到游戲“貪吃蛇”的代碼,運(yùn)行效果如上圖。代碼并不完整,當(dāng)蛇死了就退出游戲,不能多次玩這個(gè)游戲。

前文鏈接:

訊飛星火、文心一言和通義千問同時(shí)編“貪吃蛇”游戲,誰(shuí)會(huì)勝出?

代碼如下:

import pygame
import sys
import random
 
# 定義顏色
WHITE = (255, 255, 255)
GREEN = (0, 255, 0)
RED  = (255, 0, 0)
GREY = (211, 211, 211)  # 淡灰色
 
def init():
    global screen, screen_size
    global snake_pos, food_pos, snake_speed
 
    # 初始化pygame
    pygame.init()
 
    # 設(shè)置屏幕大小
    screen_size = (640, 480)
    screen = pygame.display.set_mode(screen_size)
 
    # 設(shè)置游戲標(biāo)題
    pygame.display.set_caption("貪吃蛇")
 
    # 蛇的初始位置
    snake_pos = [[100, 100], [80, 100], [60, 100]]
 
    # 食物的初始位置
    food_pos = [300, 300]
 
    # 蛇的初始速度
    snake_speed = [20, 0]
 
def repaint():
    # 繪制游戲界面
    screen.fill(WHITE)
 
    # 定義線段的端點(diǎn)坐標(biāo)
    x,y = (-1,640,640,-1)*16, []
    for i in range(36):
        for _ in range(2):
            y.append(19+i*20)
 
    # 使用pygame.draw.lines()函數(shù)繪制線段
    points = list(zip(x,y))
    pygame.draw.lines(screen, GREY, False, points, 1) # 線寬為1
    points = list(zip(y,x))
    pygame.draw.lines(screen, GREY, False, points, 1)   
 
    # 重畫蛇和食物
    for pos in snake_pos:
        pygame.draw.rect(screen, GREEN, pygame.Rect(pos[0], pos[1], 20, 20))
    pygame.draw.rect(screen, RED, pygame.Rect(food_pos[0], food_pos[1], 20, 20))
    pygame.display.flip()
 
def game_quit():
    pygame.quit()
    sys.exit()
 
def main():
    global screen, screen_size
    global snake_pos, food_pos, snake_speed
    
    # 主循環(huán)
    while True:
        # 處理游戲事件
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                game_quit()
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_UP:
                    snake_speed = [0, -20]
                elif event.key == pygame.K_DOWN:
                    snake_speed = [0, 20]
                elif event.key == pygame.K_LEFT:
                    snake_speed = [-20, 0]
                elif event.key == pygame.K_RIGHT:
                    snake_speed = [20, 0]
 
        # 更新蛇的位置
        snake_pos.insert(0, [snake_pos[0][0] + snake_speed[0], snake_pos[0][1] + snake_speed[1]])
 
        # 檢查蛇頭是否碰到食物
        if snake_pos[0] == food_pos:
            food_pos = [random.randrange(1, screen_size[0] // 20) * 20, random.randrange(1, screen_size[1] // 20) * 20]
        else:
            snake_pos.pop()
 
        # 檢查蛇頭是否碰到墻壁或者蛇身
        if snake_pos[0][0] < 0 or snake_pos[0][0] >= screen_size[0] or snake_pos[0][1] < 0 or snake_pos[0][1] >= screen_size[1] or snake_pos[0] in snake_pos[1:]:
            game_quit()
            '''
            此處可增加與用戶的交互,如:
            if askyesno('title','again?'):
                init() # Yes to Play again
            else:
                game_quit() # No to Exit
            '''
 
        # 重畫界面及蛇和食物
        repaint()
 
        # 控制游戲速度
        pygame.time.Clock().tick(10)
 
if __name__ == "__main__":
 
    init()
    main()
 

改進(jìn)過程一

增加提示信息

之前沒有仔細(xì)學(xué)過pygame的編程,剛好拿這例程練練手,在不斷改進(jìn)中學(xué)習(xí)pygame編程。

原代碼一執(zhí)行,蛇就開始游動(dòng)了,就從這里入手。開始前,增加顯示“按任意鍵開始...”的提示。

Python “貪吃蛇”游戲,在不斷改進(jìn)中學(xué)習(xí)pygame編程,Python,pygame,python,開發(fā)語(yǔ)言

蛇死后,提醒是否重來?Yes to play again, No to quit game.

Python “貪吃蛇”游戲,在不斷改進(jìn)中學(xué)習(xí)pygame編程,Python,pygame,python,開發(fā)語(yǔ)言

同時(shí),在游戲中允許按ESC鍵暫停游戲,再按一次繼續(xù)。

Python “貪吃蛇”游戲,在不斷改進(jìn)中學(xué)習(xí)pygame編程,Python,pygame,python,開發(fā)語(yǔ)言

由于沒查到 pygame 有彈出信息窗口的方法(函數(shù)),于是用了DOS時(shí)代顯示信息窗口的辦法,畫多個(gè)矩形窗口來模擬窗口,最后在矩形框上寫上提示文字。代碼如下:

def show_msg(msg, color = BLUE):
? ? x = screen.get_rect().centerx
? ? y = screen.get_rect().centery - 50
? ? font = pygame.font.Font(None, 36)
? ? text = font.render(msg, True, color)
? ? text_rect = text.get_rect()
? ? text_rect.centerx = x
? ? text_rect.centery = y
? ? rectangle1 = pygame.Rect(x-155, y-25, 320, 60)
? ? rectangle2 = pygame.Rect(x-160, y-30, 320, 60)
? ? pygame.draw.rect(screen, DARK, rectangle1)
? ? pygame.draw.rect(screen, GREY, rectangle2)
? ? pygame.draw.rect(screen, BLACK, rectangle2, 2) # 邊框?qū)挒?
? ? screen.blit(text, text_rect)
? ? pygame.display.flip()


原版幫助摘要

pygame.draw

NAME
? ? pygame.draw - pygame module for drawing shapes

FUNCTIONS
? ? aaline(...)
? ? ? ? aaline(surface, color, start_pos, end_pos) -> Rect
? ? ? ? aaline(surface, color, start_pos, end_pos, blend=1) -> Rect
? ? ? ? draw a straight antialiased line
? ??
? ? aalines(...)
? ? ? ? aalines(surface, color, closed, points) -> Rect
? ? ? ? aalines(surface, color, closed, points, blend=1) -> Rect
? ? ? ? draw multiple contiguous straight antialiased line segments
? ??
? ? arc(...)
? ? ? ? arc(surface, color, rect, start_angle, stop_angle) -> Rect
? ? ? ? arc(surface, color, rect, start_angle, stop_angle, width=1) -> Rect
? ? ? ? draw an elliptical arc
? ??
? ? circle(...)
? ? ? ? circle(surface, color, center, radius) -> Rect
? ? ? ? circle(surface, color, center, radius, width=0, draw_top_right=None, draw_top_left=None, draw_bottom_left=None, draw_bottom_right=None) -> Rect
? ? ? ? draw a circle
? ??
? ? ellipse(...)
? ? ? ? ellipse(surface, color, rect) -> Rect
? ? ? ? ellipse(surface, color, rect, width=0) -> Rect
? ? ? ? draw an ellipse
? ??
? ? line(...)
? ? ? ? line(surface, color, start_pos, end_pos) -> Rect
? ? ? ? line(surface, color, start_pos, end_pos, width=1) -> Rect
? ? ? ? draw a straight line
? ??
? ? lines(...)
? ? ? ? lines(surface, color, closed, points) -> Rect
? ? ? ? lines(surface, color, closed, points, width=1) -> Rect
? ? ? ? draw multiple contiguous straight line segments
? ??
? ? polygon(...)
? ? ? ? polygon(surface, color, points) -> Rect
? ? ? ? polygon(surface, color, points, width=0) -> Rect
? ? ? ? draw a polygon
? ??
? ? rect(...)
? ? ? ? rect(surface, color, rect) -> Rect
? ? ? ? rect(surface, color, rect, width=0, border_radius=0, border_top_left_radius=-1, border_top_right_radius=-1, border_bottom_left_radius=-1, border_bottom_right_radius=-1) -> Rect
? ? ? ? draw a rectangle


pygame.font

NAME
? ? pygame.font - pygame module for loading and rendering fonts

CLASSES
? ? builtins.object
? ? ? ? Font
? ??
? ? class Font(builtins.object)
? ? ?| ?Font(file_path=None, size=12) -> Font
? ? ?| ?Font(file_path, size) -> Font
? ? ?| ?Font(pathlib.Path, size) -> Font
? ? ?| ?Font(object, size) -> Font
? ? ?| ?create a new Font object from a file
? ? ?| ?
? ? ?| ?Methods defined here:
? ? ?| ?
? ? ?| ?__init__(self, /, *args, **kwargs)
? ? ?| ? ? ?Initialize self. ?See help(type(self)) for accurate signature.
? ? ?| ?
? ? ?| ?get_ascent(...)
? ? ?| ? ? ?get_ascent() -> int
? ? ?| ? ? ?get the ascent of the font
? ? ?| ?
? ? ?| ?get_bold(...)
? ? ?| ? ? ?get_bold() -> bool
? ? ?| ? ? ?check if text will be rendered bold
? ? ?| ?
? ? ?| ?get_descent(...)
? ? ?| ? ? ?get_descent() -> int
? ? ?| ? ? ?get the descent of the font
? ? ?| ?
? ? ?| ?get_height(...)
? ? ?| ? ? ?get_height() -> int
? ? ?| ? ? ?get the height of the font
? ? ?| ?
? ? ?| ?get_italic(...)
? ? ?| ? ? ?get_italic() -> bool
? ? ?| ? ? ?check if the text will be rendered italic
? ? ?| ?
? ? ?| ?get_linesize(...)
? ? ?| ? ? ?get_linesize() -> int
? ? ?| ? ? ?get the line space of the font text
? ? ?| ?
? ? ?| ?get_strikethrough(...)
? ? ?| ? ? ?get_strikethrough() -> bool
? ? ?| ? ? ?check if text will be rendered with a strikethrough
? ? ?| ?
? ? ?| ?get_underline(...)
? ? ?| ? ? ?get_underline() -> bool
? ? ?| ? ? ?check if text will be rendered with an underline
? ? ?| ?
? ? ?| ?metrics(...)
? ? ?| ? ? ?metrics(text) -> list
? ? ?| ? ? ?gets the metrics for each character in the passed string
? ? ?| ?
? ? ?| ?render(...)
? ? ?| ? ? ?render(text, antialias, color, background=None) -> Surface
? ? ?| ? ? ?draw text on a new Surface
? ? ?| ?
? ? ?| ?set_bold(...)
? ? ?| ? ? ?set_bold(bool) -> None
? ? ?| ? ? ?enable fake rendering of bold text
? ? ?| ?
? ? ?| ?set_italic(...)
? ? ?| ? ? ?set_italic(bool) -> None
? ? ?| ? ? ?enable fake rendering of italic text
? ? ?| ?
? ? ?| ?set_script(...)
? ? ?| ? ? ?set_script(str) -> None
? ? ?| ? ? ?set the script code for text shaping
? ? ?| ?
? ? ?| ?set_strikethrough(...)
? ? ?| ? ? ?set_strikethrough(bool) -> None
? ? ?| ? ? ?control if text is rendered with a strikethrough
? ? ?| ?
? ? ?| ?set_underline(...)
? ? ?| ? ? ?set_underline(bool) -> None
? ? ?| ? ? ?control if text is rendered with an underline
? ? ?| ?
? ? ?| ?size(...)
? ? ?| ? ? ?size(text) -> (width, height)
? ? ?| ? ? ?determine the amount of space needed to render text
? ? ?| ?
? ? ?| ?----------------------------------------------------------------------
? ? ?| ?Data descriptors defined here:
? ? ?| ?
? ? ?| ?bold
? ? ?| ? ? ?bold -> bool
? ? ?| ? ? ?Gets or sets whether the font should be rendered in (faked) bold.
? ? ?| ?
? ? ?| ?italic
? ? ?| ? ? ?italic -> bool
? ? ?| ? ? ?Gets or sets whether the font should be rendered in (faked) italics.
? ? ?| ?
? ? ?| ?strikethrough
? ? ?| ? ? ?strikethrough -> bool
? ? ?| ? ? ?Gets or sets whether the font should be rendered with a strikethrough.
? ? ?| ?
? ? ?| ?underline
? ? ?| ? ? ?underline -> bool
? ? ?| ? ? ?Gets or sets whether the font should be rendered with an underline.


class Rect

Help on class Rect in module pygame.rect:

class Rect(builtins.object)
?| ?Rect(left, top, width, height) -> Rect
?| ?Rect((left, top), (width, height)) -> Rect
?| ?Rect(object) -> Rect
?| ?pygame object for storing rectangular coordinates
?| ?
?| ?Methods defined here:
?| ?
?| ?clamp(...)
?| ? ? ?clamp(Rect) -> Rect
?| ? ? ?moves the rectangle inside another
?| ?
?| ?clamp_ip(...)
?| ? ? ?clamp_ip(Rect) -> None
?| ? ? ?moves the rectangle inside another, in place
?| ?
?| ?clip(...)
?| ? ? ?clip(Rect) -> Rect
?| ? ? ?crops a rectangle inside another
?| ?
?| ?clipline(...)
?| ? ? ?clipline(x1, y1, x2, y2) -> ((cx1, cy1), (cx2, cy2))
?| ? ? ?clipline(x1, y1, x2, y2) -> ()
?| ? ? ?clipline((x1, y1), (x2, y2)) -> ((cx1, cy1), (cx2, cy2))
?| ? ? ?clipline((x1, y1), (x2, y2)) -> ()
?| ? ? ?clipline((x1, y1, x2, y2)) -> ((cx1, cy1), (cx2, cy2))
?| ? ? ?clipline((x1, y1, x2, y2)) -> ()
?| ? ? ?clipline(((x1, y1), (x2, y2))) -> ((cx1, cy1), (cx2, cy2))
?| ? ? ?clipline(((x1, y1), (x2, y2))) -> ()
?| ? ? ?crops a line inside a rectangle
?| ?
?| ?collidedict(...)
?| ? ? ?collidedict(dict) -> (key, value)
?| ? ? ?collidedict(dict) -> None
?| ? ? ?collidedict(dict, use_values=0) -> (key, value)
?| ? ? ?collidedict(dict, use_values=0) -> None
?| ? ? ?test if one rectangle in a dictionary intersects
?| ?
?| ?collidedictall(...)
?| ? ? ?collidedictall(dict) -> [(key, value), ...]
?| ? ? ?collidedictall(dict, use_values=0) -> [(key, value), ...]
?| ? ? ?test if all rectangles in a dictionary intersect
?| ?
?| ?collidelist(...)
?| ? ? ?collidelist(list) -> index
?| ? ? ?test if one rectangle in a list intersects
?| ?
?| ?collidelistall(...)
?| ? ? ?collidelistall(list) -> indices
?| ? ? ?test if all rectangles in a list intersect
?| ?
?| ?collideobjects(...)
?| ? ? ?collideobjects(rect_list) -> object
?| ? ? ?collideobjects(obj_list, key=func) -> object
?| ? ? ?test if any object in a list intersects
?| ?
?| ?collideobjectsall(...)
?| ? ? ?collideobjectsall(rect_list) -> objects
?| ? ? ?collideobjectsall(obj_list, key=func) -> objects
?| ? ? ?test if all objects in a list intersect
?| ?
?| ?collidepoint(...)
?| ? ? ?collidepoint(x, y) -> bool
?| ? ? ?collidepoint((x,y)) -> bool
?| ? ? ?test if a point is inside a rectangle
?| ?
?| ?colliderect(...)
?| ? ? ?colliderect(Rect) -> bool
?| ? ? ?test if two rectangles overlap
?| ?
?| ?contains(...)
?| ? ? ?contains(Rect) -> bool
?| ? ? ?test if one rectangle is inside another
?| ?
?| ?copy(...)
?| ? ? ?copy() -> Rect
?| ? ? ?copy the rectangle
?| ?
?| ?fit(...)
?| ? ? ?fit(Rect) -> Rect
?| ? ? ?resize and move a rectangle with aspect ratio
?| ?
?| ?inflate(...)
?| ? ? ?inflate(x, y) -> Rect
?| ? ? ?grow or shrink the rectangle size
?| ?
?| ?inflate_ip(...)
?| ? ? ?inflate_ip(x, y) -> None
?| ? ? ?grow or shrink the rectangle size, in place
?| ?
?| ?move(...)
?| ? ? ?move(x, y) -> Rect
?| ? ? ?moves the rectangle
?| ?
?| ?move_ip(...)
?| ? ? ?move_ip(x, y) -> None
?| ? ? ?moves the rectangle, in place
?| ?
?| ?normalize(...)
?| ? ? ?normalize() -> None
?| ? ? ?correct negative sizes
?| ?
?| ?scale_by(...)
?| ? ? ?scale_by(scalar) -> Rect
?| ? ? ?scale_by(scalex, scaley) -> Rect
?| ? ? ?scale the rectangle by given a multiplier
?| ?
?| ?scale_by_ip(...)
?| ? ? ?scale_by_ip(scalar) -> None
?| ? ? ?scale_by_ip(scalex, scaley) -> None
?| ? ? ?grow or shrink the rectangle size, in place
?| ?
?| ?union(...)
?| ? ? ?union(Rect) -> Rect
?| ? ? ?joins two rectangles into one
?| ?
?| ?union_ip(...)
?| ? ? ?union_ip(Rect) -> None
?| ? ? ?joins two rectangles into one, in place
?| ?
?| ?unionall(...)
?| ? ? ?unionall(Rect_sequence) -> Rect
?| ? ? ?the union of many rectangles
?| ?
?| ?unionall_ip(...)
?| ? ? ?unionall_ip(Rect_sequence) -> None
?| ? ? ?the union of many rectangles, in place
?| ?
?| ?update(...)
?| ? ? ?update(left, top, width, height) -> None
?| ? ? ?update((left, top), (width, height)) -> None
?| ? ? ?update(object) -> None
?| ? ? ?sets the position and size of the rectangle


class Surface

class Surface(builtins.object)
?| ?Surface((width, height), flags=0, depth=0, masks=None) -> Surface
?| ?Surface((width, height), flags=0, Surface) -> Surface
?| ?pygame object for representing images
?| ?
?| ?Methods defined here:
?| ?
?| ?blit(...)
?| ? ? ?blit(source, dest, area=None, special_flags=0) -> Rect
?| ? ? ?draw one image onto another
?| ?
?| ?blits(...)
?| ? ? ?blits(blit_sequence=((source, dest), ...), doreturn=1) -> [Rect, ...] or None
?| ? ? ?blits(((source, dest, area), ...)) -> [Rect, ...]
?| ? ? ?blits(((source, dest, area, special_flags), ...)) -> [Rect, ...]
?| ? ? ?draw many images onto another
?| ?
?| ?convert(...)
?| ? ? ?convert(Surface=None) -> Surface
?| ? ? ?convert(depth, flags=0) -> Surface
?| ? ? ?convert(masks, flags=0) -> Surface
?| ? ? ?change the pixel format of an image
?| ?
?| ?convert_alpha(...)
?| ? ? ?convert_alpha(Surface) -> Surface
?| ? ? ?convert_alpha() -> Surface
?| ? ? ?change the pixel format of an image including per pixel alphas
?| ?
?| ?copy(...)
?| ? ? ?copy() -> Surface
?| ? ? ?create a new copy of a Surface
?| ?
?| ?fill(...)
?| ? ? ?fill(color, rect=None, special_flags=0) -> Rect
?| ? ? ?fill Surface with a solid color
?| ?
?| ?get_abs_offset(...)
?| ? ? ?get_abs_offset() -> (x, y)
?| ? ? ?find the absolute position of a child subsurface inside its top level parent
?| ?
?| ?get_abs_parent(...)
?| ? ? ?get_abs_parent() -> Surface
?| ? ? ?find the top level parent of a subsurface
?| ?
?| ?get_alpha(...)
?| ? ? ?get_alpha() -> int_value
?| ? ? ?get the current Surface transparency value
?| ?
?| ?get_at(...)
?| ? ? ?get_at((x, y)) -> Color
?| ? ? ?get the color value at a single pixel
?| ?
?| ?get_at_mapped(...)
?| ? ? ?get_at_mapped((x, y)) -> Color
?| ? ? ?get the mapped color value at a single pixel
?| ?
?| ?get_bitsize(...)
?| ? ? ?get_bitsize() -> int
?| ? ? ?get the bit depth of the Surface pixel format
?| ?
?| ?get_blendmode(...)
?| ? ? ?Return the surface's SDL 2 blend mode
?| ?
?| ?get_bounding_rect(...)
?| ? ? ?get_bounding_rect(min_alpha = 1) -> Rect
?| ? ? ?find the smallest rect containing data
?| ?
?| ?get_buffer(...)
?| ? ? ?get_buffer() -> BufferProxy
?| ? ? ?acquires a buffer object for the pixels of the Surface.
?| ?
?| ?get_bytesize(...)
?| ? ? ?get_bytesize() -> int
?| ? ? ?get the bytes used per Surface pixel
?| ?
?| ?get_clip(...)
?| ? ? ?get_clip() -> Rect
?| ? ? ?get the current clipping area of the Surface
?| ?
?| ?get_colorkey(...)
?| ? ? ?get_colorkey() -> RGB or None
?| ? ? ?Get the current transparent colorkey
?| ?
?| ?get_flags(...)
?| ? ? ?get_flags() -> int
?| ? ? ?get the additional flags used for the Surface
?| ?
?| ?get_height(...)
?| ? ? ?get_height() -> height
?| ? ? ?get the height of the Surface
?| ?
?| ?get_locked(...)
?| ? ? ?get_locked() -> bool
?| ? ? ?test if the Surface is current locked
?| ?
?| ?get_locks(...)
?| ? ? ?get_locks() -> tuple
?| ? ? ?Gets the locks for the Surface
?| ?
?| ?get_losses(...)
?| ? ? ?get_losses() -> (R, G, B, A)
?| ? ? ?the significant bits used to convert between a color and a mapped integer
?| ?
?| ?get_masks(...)
?| ? ? ?get_masks() -> (R, G, B, A)
?| ? ? ?the bitmasks needed to convert between a color and a mapped integer
?| ?
?| ?get_offset(...)
?| ? ? ?get_offset() -> (x, y)
?| ? ? ?find the position of a child subsurface inside a parent
?| ?
?| ?get_palette(...)
?| ? ? ?get_palette() -> [RGB, RGB, RGB, ...]
?| ? ? ?get the color index palette for an 8-bit Surface
?| ?
?| ?get_palette_at(...)
?| ? ? ?get_palette_at(index) -> RGB
?| ? ? ?get the color for a single entry in a palette
?| ?
?| ?get_parent(...)
?| ? ? ?get_parent() -> Surface
?| ? ? ?find the parent of a subsurface
?| ?
?| ?get_pitch(...)
?| ? ? ?get_pitch() -> int
?| ? ? ?get the number of bytes used per Surface row
?| ?
?| ?get_rect(...)
?| ? ? ?get_rect(**kwargs) -> Rect
?| ? ? ?get the rectangular area of the Surface
?| ?
?| ?get_shifts(...)
?| ? ? ?get_shifts() -> (R, G, B, A)
?| ? ? ?the bit shifts needed to convert between a color and a mapped integer
?| ?
?| ?get_size(...)
?| ? ? ?get_size() -> (width, height)
?| ? ? ?get the dimensions of the Surface
?| ?
?| ?get_view(...)
?| ? ? ?get_view(<kind>='2') -> BufferProxy
?| ? ? ?return a buffer view of the Surface's pixels.
?| ?
?| ?get_width(...)
?| ? ? ?get_width() -> width
?| ? ? ?get the width of the Surface
?| ?
?| ?lock(...)
?| ? ? ?lock() -> None
?| ? ? ?lock the Surface memory for pixel access
?| ?
?| ?map_rgb(...)
?| ? ? ?map_rgb(Color) -> mapped_int
?| ? ? ?convert a color into a mapped color value
?| ?
?| ?mustlock(...)
?| ? ? ?mustlock() -> bool
?| ? ? ?test if the Surface requires locking
?| ?
?| ?premul_alpha(...)
?| ? ? ?premul_alpha() -> Surface
?| ? ? ?returns a copy of the surface with the RGB channels pre-multiplied by the alpha channel.
?| ?
?| ?scroll(...)
?| ? ? ?scroll(dx=0, dy=0) -> None
?| ? ? ?Shift the surface image in place
?| ?
?| ?set_alpha(...)
?| ? ? ?set_alpha(value, flags=0) -> None
?| ? ? ?set_alpha(None) -> None
?| ? ? ?set the alpha value for the full Surface image
?| ?
?| ?set_at(...)
?| ? ? ?set_at((x, y), Color) -> None
?| ? ? ?set the color value for a single pixel
?| ?
?| ?set_clip(...)
?| ? ? ?set_clip(rect) -> None
?| ? ? ?set_clip(None) -> None
?| ? ? ?set the current clipping area of the Surface
?| ?
?| ?set_colorkey(...)
?| ? ? ?set_colorkey(Color, flags=0) -> None
?| ? ? ?set_colorkey(None) -> None
?| ? ? ?Set the transparent colorkey
?| ?
?| ?set_masks(...)
?| ? ? ?set_masks((r,g,b,a)) -> None
?| ? ? ?set the bitmasks needed to convert between a color and a mapped integer
?| ?
?| ?set_palette(...)
?| ? ? ?set_palette([RGB, RGB, RGB, ...]) -> None
?| ? ? ?set the color palette for an 8-bit Surface
?| ?
?| ?set_palette_at(...)
?| ? ? ?set_palette_at(index, RGB) -> None
?| ? ? ?set the color for a single index in an 8-bit Surface palette
?| ?
?| ?set_shifts(...)
?| ? ? ?set_shifts((r,g,b,a)) -> None
?| ? ? ?sets the bit shifts needed to convert between a color and a mapped integer
?| ?
?| ?subsurface(...)
?| ? ? ?subsurface(Rect) -> Surface
?| ? ? ?create a new surface that references its parent
?| ?
?| ?unlock(...)
?| ? ? ?unlock() -> None
?| ? ? ?unlock the Surface memory from pixel access
?| ?
?| ?unmap_rgb(...)
?| ? ? ?unmap_rgb(mapped_int) -> Color
?| ? ? ?convert a mapped integer color value into a Color


另外增加了3個(gè)狀態(tài)變量,初始狀態(tài)為:

? ? is_running = False
? ? is_paused = False
? ? is_dead = False

增加了4個(gè)按鍵判別:

is_dead時(shí),判斷重新開始還是退出游戲

pygame.K_y: 字母Y/y
pygame.K_n: 字母N/n

暫停和恢復(fù)

pygame.K_ESCAPE: Esc鍵
pygame.K_SPACE: 空格鍵

完整代碼如下:

import pygame
import sys
import random

# 定義顏色
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
RED   = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE  = (0, 0, 255)
GREY  = (220, 220, 220)  # 淡灰色
DARK  = (120, 120, 120)  # 深灰色

def init():
    global screen, screen_size
    global snake_pos, food_pos, snake_speed

    # 初始化pygame
    pygame.init()

    # 設(shè)置屏幕大小
    screen_size = (640, 480)
    screen = pygame.display.set_mode(screen_size)

    # 設(shè)置游戲標(biāo)題
    pygame.display.set_caption("貪吃蛇")

    # 蛇的初始位置
    snake_pos = [[100, 100], [80, 100], [60, 100]]

    # 食物的初始位置
    food_pos = [300, 300]

    # 蛇的初始速度
    snake_speed = [20, 0]


def show_msg(msg, color = BLUE):
    x = screen.get_rect().centerx
    y = screen.get_rect().centery - 50
    font = pygame.font.Font(None, 36)
    text = font.render(msg, True, color)
    text_rect = text.get_rect()
    text_rect.centerx = x
    text_rect.centery = y
    rectangle1 = pygame.Rect(x-155, y-25, 320, 60)
    rectangle2 = pygame.Rect(x-160, y-30, 320, 60)
    pygame.draw.rect(screen, DARK, rectangle1)
    pygame.draw.rect(screen, GREY, rectangle2)
    pygame.draw.rect(screen, BLACK, rectangle2, 2) # 邊框?qū)挒?
    screen.blit(text, text_rect)
    pygame.display.flip()

def repaint():
    # 繪制游戲界面
    screen.fill(WHITE)

    # 定義線段的端點(diǎn)坐標(biāo)
    x,y = (-1,640,640,-1)*16, []
    for i in range(36):
        for _ in range(2):
            y.append(19+i*20)

    # 使用pygame.draw.lines()函數(shù)繪制線段
    points = list(zip(x,y))
    pygame.draw.lines(screen, GREY, False, points, 1) # 線寬為1
    points = list(zip(y,x))
    pygame.draw.lines(screen, GREY, False, points, 1)   

    # 重畫蛇和食物
    for pos in snake_pos:
        pygame.draw.rect(screen, GREEN, pygame.Rect(pos[0], pos[1], 20, 20))
    pygame.draw.rect(screen, RED, pygame.Rect(food_pos[0], food_pos[1], 20, 20))
    pygame.display.flip()

def game_quit():
    pygame.quit()
    sys.exit()

def main():
    global screen, screen_size
    global snake_pos, food_pos, snake_speed

    is_running = False
    is_paused = False
    is_dead = False

    repaint()
    show_msg("Press any key to start ...")

    # 主循環(huán)
    while True:
        # 處理游戲事件
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                game_quit()
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_UP:
                    snake_speed = [0, -20]
                elif event.key == pygame.K_DOWN:
                    snake_speed = [0, 20]
                elif event.key == pygame.K_LEFT:
                    snake_speed = [-20, 0]
                elif event.key == pygame.K_RIGHT:
                    snake_speed = [20, 0]
                elif event.key == pygame.K_y:
                    if is_dead:
                        init()
                        is_dead = False
                    is_running = True
                elif event.key == pygame.K_n:
                    if is_dead: game_quit()
                    else: is_running = True
                elif event.key == pygame.K_ESCAPE:
                    if is_running:
                        show_msg(">>> Paused <<<")
                        is_paused = not is_paused
                else: # 任意鍵進(jìn)入開始狀態(tài)
                    is_running = True

        if not is_running: continue
        if is_paused and is_running: continue

        # 更新蛇的位置
        snake_pos.insert(0, [snake_pos[0][0] + snake_speed[0], snake_pos[0][1] + snake_speed[1]])

        # 檢查蛇頭是否碰到食物
        if snake_pos[0] == food_pos:
            food_pos = [random.randrange(1, screen_size[0] // 20) * 20, random.randrange(1, screen_size[1] // 20) * 20]
        else:
            snake_pos.pop()

        # 檢查蛇頭是否碰到墻壁或者蛇身
        if snake_pos[0][0] < 0 or snake_pos[0][0] >= screen_size[0] or snake_pos[0][1] < 0 or snake_pos[0][1] >= screen_size[1] or snake_pos[0] in snake_pos[1:]:
            show_msg("Dead! Again? (Y or N)")
            is_running = False
            is_dead = True
            continue

        # 重畫界面及蛇和食物
        repaint()

        # 控制游戲速度
        pygame.time.Clock().tick(10)

if __name__ == "__main__":

    init()
    main()

改進(jìn)過程二

增加顯示得分

每吃到一個(gè)食物+10分,蛇長(zhǎng)和食物靠近邊界會(huì)有額外加分;順帶顯示出蛇的坐標(biāo)位置。

Python “貪吃蛇”游戲,在不斷改進(jìn)中學(xué)習(xí)pygame編程,Python,pygame,python,開發(fā)語(yǔ)言

函數(shù)show_msg_at(),比show_msg增加x,y坐標(biāo),把信息顯示到指定的位置:

def show_msg_at(x, y, msg):
? ? font = pygame.font.SysFont('Consolas', 14)? # 使用系統(tǒng)字庫(kù)
? ? text = font.render(msg, True, BLACK)
? ? text_rect = text.get_rect()
? ? text_rect.x, text_rect.y = x, y
? ? screen.blit(text, text_rect)
? ? pygame.display.flip()

另外新增一個(gè)全局變量?scores,當(dāng)碰到食物時(shí)加10分,蛇長(zhǎng)超過5以及食物靠近邊界的距離小3會(huì)有額外加分,規(guī)則可以自己定,例如:

? ? ? ? if snake_pos[0] == food_pos:
? ? ? ? ? ? scores += 10?+ len(snake_pos) // 5
? ? ? ? ? ? if not 1 < snake_pos[0][0]//20 < 30 or not 1 < snake_pos[0][1]//20 < 22:
? ? ? ? ? ? ? ? scores += 5
?

完整代碼如下:?

import pygame
import sys
import random

# 定義顏色
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
RED   = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE  = (0, 0, 255)
GREY  = (220, 220, 220)  # 淡灰色
DARK  = (120, 120, 120)  # 深灰色

def init():
    global screen, screen_size, scores
    global snake_pos, food_pos, snake_speed

    # 初始化pygame
    scores = 0
    pygame.init()

    # 設(shè)置屏幕大小
    screen_size = (640, 480)
    screen = pygame.display.set_mode(screen_size)

    # 設(shè)置游戲標(biāo)題
    pygame.display.set_caption("貪吃蛇")

    # 蛇的初始位置
    snake_pos = [[100, 100], [80, 100], [60, 100]]

    # 食物的初始位置
    food_pos = [300, 300]

    # 蛇的初始速度
    snake_speed = [20, 0]


def show_msg(msg, color = BLUE):
    x = screen.get_rect().centerx
    y = screen.get_rect().centery - 50
    font = pygame.font.Font(None, 36)
    text = font.render(msg, True, color)
    text_rect = text.get_rect()
    text_rect.centerx = x
    text_rect.centery = y
    rectangle1 = pygame.Rect(x-155, y-25, 320, 60)
    rectangle2 = pygame.Rect(x-160, y-30, 320, 60)
    pygame.draw.rect(screen, DARK, rectangle1)
    pygame.draw.rect(screen, GREY, rectangle2)
    pygame.draw.rect(screen, BLACK, rectangle2, 2) # 邊框?qū)挒?
    screen.blit(text, text_rect)
    pygame.display.flip()

def repaint():
    # 繪制游戲界面
    screen.fill(WHITE)

    # 定義線段的端點(diǎn)坐標(biāo)
    x,y = (-1,640,640,-1)*16, []
    for i in range(36):
        for _ in range(2):
            y.append(19+i*20)

    # 使用pygame.draw.lines()函數(shù)繪制線段
    points = list(zip(x,y))
    pygame.draw.lines(screen, GREY, False, points, 1) # 線寬為1
    points = list(zip(y,x))
    pygame.draw.lines(screen, GREY, False, points, 1)   

    # 重畫蛇和食物
    for pos in snake_pos:
        pygame.draw.rect(screen, GREEN, pygame.Rect(pos[0], pos[1], 20, 20))
    pygame.draw.rect(screen, RED, pygame.Rect(food_pos[0], food_pos[1], 20, 20))
    pygame.display.flip()
    show_msg_at(22, 6, f'Scores: {scores}')
    show_msg_at(410, 6, f'Snake coordinate: ({1+snake_pos[0][0]//20:2}, {1+snake_pos[0][1]//20:2})')

def show_msg_at(x, y, msg):
    font = pygame.font.SysFont('Consolas', 14)
    text = font.render(msg, True, BLACK)
    text_rect = text.get_rect()
    text_rect.x, text_rect.y = x, y
    screen.blit(text, text_rect)
    pygame.display.flip()

def game_quit():
    pygame.quit()
    sys.exit()

def main():
    global screen, screen_size, scores
    global snake_pos, food_pos, snake_speed

    is_running = False
    is_paused = False
    is_dead = False

    repaint()
    show_msg("Press any key to start ...")

    # 主循環(huán)
    while True:
        # 處理游戲事件
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                game_quit()
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_UP:
                    snake_speed = [0, -20]
                elif event.key == pygame.K_DOWN:
                    snake_speed = [0, 20]
                elif event.key == pygame.K_LEFT:
                    snake_speed = [-20, 0]
                elif event.key == pygame.K_RIGHT:
                    snake_speed = [20, 0]
                elif event.key == pygame.K_y:
                    if is_dead:
                        init()
                        is_dead = False
                    is_running = True
                elif event.key == pygame.K_n:
                    if is_dead: game_quit()
                    else: is_running = True
                elif event.key == pygame.K_SPACE:
                    if is_dead: continue
                    if is_paused: is_paused = False
                    is_running = True
                elif event.key == pygame.K_ESCAPE:
                    if is_running:
                        show_msg(">>> Paused <<<")
                        is_paused = not is_paused
                else: # 任意鍵進(jìn)入開始狀態(tài)
                    if is_dead: continue
                    is_running = True

        if not is_running: continue
        if is_paused and is_running: continue

        # 更新蛇的位置
        snake_pos.insert(0, [snake_pos[0][0] + snake_speed[0], snake_pos[0][1] + snake_speed[1]])

        # 檢查蛇頭是否碰到食物
        if snake_pos[0] == food_pos:
? ? ? ? ? ? scores += 10?+ len(snake_pos) // 5
? ? ? ? ? ? if not 1 < snake_pos[0][0]//20 < 30 or not 1 < snake_pos[0][1]//20 < 22:
? ? ? ? ? ? ? ? scores += 5????????
            food_pos = [random.randrange(1, screen_size[0] // 20) * 20, random.randrange(1, screen_size[1] // 20) * 20]
        else:
            snake_pos.pop()

        # 檢查蛇頭是否碰到墻壁或者蛇身
        if snake_pos[0][0] < 0 or snake_pos[0][0] >= screen_size[0] or snake_pos[0][1] < 0 or snake_pos[0][1] >= screen_size[1] or snake_pos[0] in snake_pos[1:]:
            show_msg("Dead! Again? (Y or N)")
            is_running = False
            is_dead = True
            continue

        # 重畫界面及蛇和食物
        repaint()

        # 控制游戲速度
        pygame.time.Clock().tick(10)

if __name__ == "__main__":

    init()
    main()

改進(jìn)過程三

增加背景景樂

def play_music(mp3, volume = 1, loops = -1):
? ? # 初始化pygame的mixer模塊
? ? pygame.mixer.init()
? ? # 加載音樂文件
? ? pygame.mixer.music.load(mp3)
? ? # 控制音量?volume = 0~1,1為最高音量
? ? pygame.mixer.music.set_volume(volume)
? ? # 播放音樂 loops = -1 為循環(huán)播放
? ? pygame.mixer.music.play(loops)

增加提示音效

def play_sound(wav_no):
? ? sound_fn = f'sound{wav_no}.wav'
? ? if os.path.exists(sound_fn):
? ? ? ? alert_sound = pygame.mixer.Sound(sound_fn)
? ? ? ? alert_sound.play()

音樂切換

快捷鍵 Ctrl+M?

? ? elif event.key == pygame.K_m and event.mod & pygame.KMOD_CTRL:
? ? ? ? # Ctrl+M 切換背景音樂
? ? ? ? is_mute = False
? ? ? ? music_no = 1 if music_no == 3 else music_no + 1
? ? ? ? music_fn = f"voice{music_no}.mp3"
? ? ? ? if os.path.exists(music_fn):
? ? ? ? ? ? t = threading.Thread(target=play_music, args=(music_fn,0.8,))
? ? ? ? ? ? t.start()

靜音切換

快捷鍵 Ctrl+S

? ? elif event.key == pygame.K_s and event.mod & pygame.KMOD_CTRL:
? ? ? ? # Ctrl+S 切換靜音狀態(tài)
? ? ? ? is_mute = not is_mute
? ? ? ? if is_mute:
? ? ? ? ? ? pygame.mixer.music.pause()
? ? ? ? else:
? ? ? ? ? ? pygame.mixer.music.unpause()

mixer.music.play 注意事項(xiàng)

1. pygame.mixer.music.play() 只能播放pygame支持的音頻格式,包括WAV, MP3等。

2. 如果音頻文件未找到或無法讀取,pygame.mixer.music.play( ) 會(huì)拋出一個(gè)異常。使用需要確保音頻文件的路徑正確,且文件存在。導(dǎo)入os庫(kù),用os.path.exists(music_file) 判斷文件是否存在。

3. pygame.mixer.music.play() 是一個(gè)阻塞函數(shù),在音頻播放期間程序?qū)⒉粫?huì)執(zhí)行其他操作。如果需要在播放同時(shí)執(zhí)行其他操作,需要在一個(gè)單獨(dú)的線程中調(diào)用pygame.mixer.music.play()。

4. 多線程需要導(dǎo)入threading庫(kù),例如:

? ? ? ? ??t = threading.Thread(target=play_music, args=(music_fn,0.8,))
? ? ? ? ? t.start()


原版幫助摘要

pygame.mixer

NAME
? ? pygame.mixer_music - pygame module for controlling streamed audio

FUNCTIONS
? ? fadeout(...)
? ? ? ? fadeout(time) -> None
? ? ? ? stop music playback after fading out
? ??
? ? get_busy(...)
? ? ? ? get_busy() -> bool
? ? ? ? check if the music stream is playing
? ??
? ? get_endevent(...)
? ? ? ? get_endevent() -> type
? ? ? ? get the event a channel sends when playback stops
? ??
? ? get_pos(...)
? ? ? ? get_pos() -> time
? ? ? ? get the music play time
? ??
? ? get_volume(...)
? ? ? ? get_volume() -> value
? ? ? ? get the music volume
? ??
? ? load(...)
? ? ? ? load(filename) -> None
? ? ? ? load(fileobj, namehint=) -> None
? ? ? ? Load a music file for playback
? ??
? ? pause(...)
? ? ? ? pause() -> None
? ? ? ? temporarily stop music playback
? ??
? ? play(...)
? ? ? ? play(loops=0, start=0.0, fade_ms=0) -> None
? ? ? ? Start the playback of the music stream
? ??
? ? queue(...)
? ? ? ? queue(filename) -> None
? ? ? ? queue(fileobj, namehint=, loops=0) -> None
? ? ? ? queue a sound file to follow the current
? ??
? ? rewind(...)
? ? ? ? rewind() -> None
? ? ? ? restart music
? ??
? ? set_endevent(...)
? ? ? ? set_endevent() -> None
? ? ? ? set_endevent(type) -> None
? ? ? ? have the music send an event when playback stops
? ??
? ? set_pos(...)
? ? ? ? set_pos(pos) -> None
? ? ? ? set position to play from
? ??
? ? set_volume(...)
? ? ? ? set_volume(volume) -> None
? ? ? ? set the music volume
? ??
? ? stop(...)
? ? ? ? stop() -> None
? ? ? ? stop the music playback
? ??
? ? unload(...)
? ? ? ? unload() -> None
? ? ? ? Unload the currently loaded music to free up resources
? ??
? ? unpause(...)
? ? ? ? unpause() -> None
? ? ? ? resume paused music


pygame.mixer.Sound

class Sound(builtins.object)
?| ?Sound(filename) -> Sound
?| ?Sound(file=filename) -> Sound
?| ?Sound(file=pathlib_path) -> Sound
?| ?Sound(buffer) -> Sound
?| ?Sound(buffer=buffer) -> Sound
?| ?Sound(object) -> Sound
?| ?Sound(file=object) -> Sound
?| ?Sound(array=object) -> Sound
?| ?Create a new Sound object from a file or buffer object
?| ?
?| ?Methods defined here:
?| ?
?| ?__init__(self, /, *args, **kwargs)
?| ? ? ?Initialize self. ?See help(type(self)) for accurate signature.
?| ?
?| ?fadeout(...)
?| ? ? ?fadeout(time) -> None
?| ? ? ?stop sound playback after fading out
?| ?
?| ?get_length(...)
?| ? ? ?get_length() -> seconds
?| ? ? ?get the length of the Sound
?| ?
?| ?get_num_channels(...)
?| ? ? ?get_num_channels() -> count
?| ? ? ?count how many times this Sound is playing
?| ?
?| ?get_raw(...)
?| ? ? ?get_raw() -> bytes
?| ? ? ?return a bytestring copy of the Sound samples.
?| ?
?| ?get_volume(...)
?| ? ? ?get_volume() -> value
?| ? ? ?get the playback volume
?| ?
?| ?play(...)
?| ? ? ?play(loops=0, maxtime=0, fade_ms=0) -> Channel
?| ? ? ?begin sound playback
?| ?
?| ?set_volume(...)
?| ? ? ?set_volume(value) -> None
?| ? ? ?set the playback volume for this Sound
?| ?
?| ?stop(...)
?| ? ? ?stop() -> None
?| ? ? ?stop sound playback


完整代碼:

import pygame
import sys, os
import random
import threading

# 定義顏色
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
RED   = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE  = (0, 0, 255)
GREY  = (220, 220, 220)  # 淡灰色
DARK  = (120, 120, 120)  # 深灰色

def init():
    global screen, screen_size, scores
    global snake_pos, food_pos, snake_speed

    # 初始化pygame
    scores = 0
    pygame.init()

    # 設(shè)置屏幕大小
    screen_size = (640, 480)
    screen = pygame.display.set_mode(screen_size)

    # 設(shè)置游戲標(biāo)題
    pygame.display.set_caption("貪吃蛇")

    # 蛇的初始位置
    snake_pos = [[100, 100], [80, 100], [60, 100]]

    # 食物的初始位置
    food_pos = [300, 300]

    # 蛇的初始速度
    snake_speed = [20, 0]

def play_music(mp3, volume = 1, loops = -1):
    # 初始化pygame的mixer模塊
    pygame.mixer.init()
    # 加載音樂文件
    pygame.mixer.music.load(mp3)
    # 控制音量
    pygame.mixer.music.set_volume(volume)
    # 播放音樂
    pygame.mixer.music.play(loops)

def play_sound(wav_no):
    sound_fn = f'sound{wav_no}.wav'
    if os.path.exists(sound_fn):
        alert_sound = pygame.mixer.Sound(sound_fn)
        alert_sound.play()

def show_msg(msg, color = BLUE):
    x = screen.get_rect().centerx
    y = screen.get_rect().centery - 50
    font = pygame.font.Font(None, 36)
    text = font.render(msg, True, color)
    text_rect = text.get_rect()
    text_rect.centerx = x
    text_rect.centery = y
    rectangle1 = pygame.Rect(x-155, y-25, 320, 60)
    rectangle2 = pygame.Rect(x-160, y-30, 320, 60)
    pygame.draw.rect(screen, DARK, rectangle1)
    pygame.draw.rect(screen, GREY, rectangle2)
    pygame.draw.rect(screen, BLACK, rectangle2, 2) # 邊框?qū)挒?
    screen.blit(text, text_rect)
    pygame.display.flip()

def repaint():
    # 繪制游戲界面
    screen.fill(WHITE)

    # 定義線段的端點(diǎn)坐標(biāo)
    x,y = (-1,640,640,-1)*16, []
    for i in range(36):
        for _ in range(2):
            y.append(19+i*20)

    # 使用pygame.draw.lines()函數(shù)繪制線段
    points = list(zip(x,y))
    pygame.draw.lines(screen, GREY, False, points, 1) # 線寬為1
    points = list(zip(y,x))
    pygame.draw.lines(screen, GREY, False, points, 1)   

    # 重畫蛇和食物
    for pos in snake_pos:
        pygame.draw.rect(screen, GREEN, pygame.Rect(pos[0], pos[1], 20, 20))
    pygame.draw.rect(screen, RED, pygame.Rect(food_pos[0], food_pos[1], 20, 20))
    pygame.display.flip()
    show_msg_at(22, 6, f'Scores: {scores}')
    show_msg_at(410, 6, f'Snake coordinate: ({1+snake_pos[0][0]//20:2}, {1+snake_pos[0][1]//20:2})')

def show_msg_at(x, y, msg):
    font = pygame.font.SysFont('Consolas', 14)
    text = font.render(msg, True, BLACK)
    text_rect = text.get_rect()
    text_rect.x, text_rect.y = x, y
    screen.blit(text, text_rect)
    pygame.display.flip()

def game_quit():
    pygame.quit()
    sys.exit()

def main():
    global screen, screen_size, scores
    global snake_pos, food_pos, snake_speed

    is_running = False
    is_paused = False
    is_dead = False
    is_mute = False
    
    repaint()
    show_msg("Press any key to start ...")

    # 創(chuàng)建一個(gè)線程來播放音樂
    music_no = 1
    music_fn = "voice1.mp3"
    if os.path.exists(music_fn):
        t = threading.Thread(target=play_music, args=(music_fn,0.8,))
        t.start()

    # 主循環(huán)
    while True:
        # 處理游戲事件
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                game_quit()
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_UP:
                    snake_speed = [0, -20]
                elif event.key == pygame.K_DOWN:
                    snake_speed = [0, 20]
                elif event.key == pygame.K_LEFT:
                    snake_speed = [-20, 0]
                elif event.key == pygame.K_RIGHT:
                    snake_speed = [20, 0]
                elif event.key == pygame.K_y:
                    if is_dead:
                        init()
                        is_dead = False
                    is_running = True
                elif event.key == pygame.K_n:
                    if is_dead: game_quit()
                    else: is_running = True
                elif event.key == pygame.K_SPACE:
                    if is_dead: continue
                    if is_paused: is_paused = False
                    is_running = True
                elif event.key == pygame.K_ESCAPE:
                    if is_running:
                        show_msg(">>> Paused <<<")
                        is_paused = not is_paused
                        if not is_mute and is_paused: play_sound(1)
                elif event.key == pygame.K_m and event.mod & pygame.KMOD_CTRL:
                    # Ctrl+M 切換背景音樂
                    is_mute = False
                    music_no = 1 if music_no == 3 else music_no + 1
                    music_fn = f"voice{music_no}.mp3"
                    if os.path.exists(music_fn):
                        t = threading.Thread(target=play_music, args=(music_fn,0.8,))
                        t.start()
                elif event.key == pygame.K_s and event.mod & pygame.KMOD_CTRL:
                    # Ctrl+S 切換靜音狀態(tài)
                    is_mute = not is_mute
                    if is_mute:
                        pygame.mixer.music.pause()
                    else:
                        pygame.mixer.music.unpause()
                    is_running = True
                else: # 任意鍵進(jìn)入開始狀態(tài)
                    if is_dead: continue
                    is_running = True

        if not is_running: continue
        if is_paused and is_running: continue

        # 更新蛇的位置
        snake_pos.insert(0, [snake_pos[0][0] + snake_speed[0], snake_pos[0][1] + snake_speed[1]])

        # 檢查蛇頭是否碰到食物
        if snake_pos[0] == food_pos:
            scores += 10 + len(snake_pos) // 5
            if not 1 < snake_pos[0][0]//20 < 30 or not 1 < snake_pos[0][1]//20 < 22:
                scores += 5
            if not is_mute: play_sound(2)
            food_pos = [random.randrange(1, screen_size[0] // 20) * 20, random.randrange(1, screen_size[1] // 20) * 20]
        else:
            snake_pos.pop()

        # 檢查蛇頭是否碰到墻壁或者蛇身
        if snake_pos[0][0] < 0 or snake_pos[0][0] >= screen_size[0] or snake_pos[0][1] < 0 or snake_pos[0][1] >= screen_size[1] or snake_pos[0] in snake_pos[1:]:
            show_msg("Dead! Again? (Y or N)")
            is_running = False
            is_dead = True
            if not is_mute: play_sound(3)
            continue

        # 重畫界面及蛇和食物
        repaint()

        # 控制游戲速度
        pygame.time.Clock().tick(10)

if __name__ == "__main__":

    init()
    main()

改進(jìn)過程四

增加WASD方向鍵

DOS時(shí)代的游戲經(jīng)常用W、A、S、D四個(gè)字母,對(duì)應(yīng)上左下右四個(gè)方向鍵,上面的代碼中,快捷鍵 ctrl+S 換成 strl+Q 避免沖突。

另外,游戲中按了與前進(jìn)方向相反的鍵,相當(dāng)于蛇的自殺行為。為了避免這個(gè)bug,引入一個(gè)表示蛇移動(dòng)方向的變量direction:

? ? if not is_paused:
? ? ? ? if ? (event.key == pygame.K_w or event.key == pygame.K_UP) ? ?and direction != DOWN:
? ? ? ? ? ? direction = UP
? ? ? ? elif (event.key == pygame.K_s or event.key == pygame.K_DOWN) ?and direction != UP:
? ? ? ? ? ? direction = DOWN
? ? ? ? elif (event.key == pygame.K_a or event.key == pygame.K_LEFT) ?and direction != RIGHT:
? ? ? ? ? ? direction = LEFT
? ? ? ? elif (event.key == pygame.K_f or event.key == pygame.K_RIGHT) and direction != LEFT:
? ? ? ? ? ? direction = RIGHT

把移動(dòng)和按鍵分離,控制移動(dòng)的代碼放到后面去:

? ? ? ? if direction ? == UP:
? ? ? ? ? ? snake_speed = [0, -20]
? ? ? ? elif direction == DOWN:
? ? ? ? ? ? snake_speed = [0, 20]
? ? ? ? elif direction == LEFT:
? ? ? ? ? ? snake_speed = [-20, 0]
? ? ? ? elif direction == RIGHT:
? ? ? ? ? ? snake_speed = [20, 0]

增加退出事件的確認(rèn)

pygame 沒有彈窗一類的方法,導(dǎo)入tkinter庫(kù),由messagebox來實(shí)現(xiàn):

from tkinter import messagebox
......
? ? ? ? for event in pygame.event.get():
? ? ? ? ? ? if event.type == pygame.QUIT:
? ? ? ? ? ? ? ? if messagebox.askyesno("確認(rèn)", "是否要退出?"):
? ? ? ? ? ? ? ? ? ? game_quit()
? ? ? ? ? ?......

效果如下:

Python “貪吃蛇”游戲,在不斷改進(jìn)中學(xué)習(xí)pygame編程,Python,pygame,python,開發(fā)語(yǔ)言

最后,增加了按暫停鍵時(shí)背景音樂也暫停的功能;另外修改了一些小錯(cuò)誤,估計(jì)還會(huì)有bug出現(xiàn),狀態(tài)變量設(shè)置多了感覺邏輯有點(diǎn)亂。


小結(jié)

本文以貪吃蛇游戲?yàn)槔?,?duì)pygame編程的一個(gè)簡(jiǎn)單框架進(jìn)行了深入的學(xué)習(xí),包括對(duì)畫圖、字體、音樂等各個(gè)方面操作的各種方法和函數(shù),學(xué)習(xí)后在pygame這方面的編程能力有所長(zhǎng)進(jìn)提高。

pygame編程框架

import pygame
import sys

# 初始化Pygame
pygame.init()

# 設(shè)置窗口大小
screen_size = (800, 600)

# 創(chuàng)建窗口
screen = pygame.display.set_mode(screen_size)

# 設(shè)置窗口標(biāo)題
pygame.display.set_caption("Pygame Example")

# 主循環(huán)
while True:
    # 處理事件
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()
        elif event.type == ...
            ... // 處理按鍵事件

    # 填充背景色
    screen.fill((255, 255, 255))

    # 繪制矩形
    pygame.draw.rect(screen, (0, 0, 255), (400, 300, 100, 50))

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

完整代碼

import pygame
from sys import exit as system
from random  import randrange
from os.path import exists
from tkinter import messagebox
from threading import Thread

# 定義顏色
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
RED   = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE  = (0, 0, 255)
GREY  = (220, 220, 220)  # 淡灰色
DARK  = (120, 120, 120)  # 深灰色

def init():
    global screen, screen_size, scores
    global snake_pos, food_pos, snake_speed

    # 初始化pygame
    scores = 0
    pygame.init()

    # 設(shè)置屏幕大小
    screen_size = (640, 480)
    screen = pygame.display.set_mode(screen_size)

    # 設(shè)置游戲標(biāo)題
    pygame.display.set_caption("貪吃蛇")

    # 蛇的初始位置
    snake_pos = [[100, 100], [80, 100], [60, 100]]

    # 食物的初始位置
    food_pos = [300, 300]

    # 蛇的初始速度
    snake_speed = [20, 0]

def play_music(mp3, volume = 1, loops = -1):
    # 初始化pygame的mixer模塊
    pygame.mixer.init()
    # 加載音樂文件
    pygame.mixer.music.load(mp3)
    # 控制音量
    pygame.mixer.music.set_volume(volume)
    # 播放音樂
    pygame.mixer.music.play(loops)

def play_sound(wav_no):
    sound_fn = f'sound{wav_no}.wav'
    if exists(sound_fn):
        alert_sound = pygame.mixer.Sound(sound_fn)
        alert_sound.play()

def show_msg(msg, color = BLUE):
    x = screen.get_rect().centerx
    y = screen.get_rect().centery - 50
    font = pygame.font.Font(None, 36)
    text = font.render(msg, True, color)
    text_rect = text.get_rect()
    text_rect.centerx = x
    text_rect.centery = y
    rectangle1 = pygame.Rect(x-155, y-25, 320, 60)
    rectangle2 = pygame.Rect(x-160, y-30, 320, 60)
    pygame.draw.rect(screen, DARK, rectangle1)
    pygame.draw.rect(screen, GREY, rectangle2)
    pygame.draw.rect(screen, BLACK, rectangle2, 2) # 邊框?qū)挒?
    screen.blit(text, text_rect)
    pygame.display.flip()

def repaint():
    # 繪制游戲界面
    screen.fill(WHITE)

    # 定義線段的端點(diǎn)坐標(biāo)
    x,y = (-1,640,640,-1)*16, []
    for i in range(36):
        for _ in range(2):
            y.append(19+i*20)

    # 使用pygame.draw.lines()函數(shù)繪制線段
    points = list(zip(x,y))
    pygame.draw.lines(screen, GREY, False, points, 1) # 線寬為1
    points = list(zip(y,x))
    pygame.draw.lines(screen, GREY, False, points, 1)   

    # 重畫蛇和食物
    for pos in snake_pos:
        pygame.draw.rect(screen, GREEN, pygame.Rect(pos[0], pos[1], 20, 20))
    pygame.draw.rect(screen, RED, pygame.Rect(food_pos[0], food_pos[1], 20, 20))
    pygame.display.flip()
    show_msg_at(22, 6, f'Scores: {scores}')
    show_msg_at(410, 6, f'Snake coordinate: ({1+snake_pos[0][0]//20:2}, {1+snake_pos[0][1]//20:2})')

def show_msg_at(x, y, msg):
    font = pygame.font.SysFont('Consolas', 14)
    text = font.render(msg, True, BLACK)
    text_rect = text.get_rect()
    text_rect.x, text_rect.y = x, y
    screen.blit(text, text_rect)
    pygame.display.flip()

def game_quit():
    pygame.quit()
    system()

def main():
    global screen, screen_size, scores
    global snake_pos, food_pos, snake_speed

    is_running = False
    is_paused = False
    is_dead = False
    is_mute = False
    
    repaint()
    show_msg("Press any key to start ...")

    # 創(chuàng)建一個(gè)線程來播放音樂
    music_no = 1
    music_fn = "voice1.mp3"
    if exists(music_fn):
        t = Thread(target=play_music, args=(music_fn,0.8,))
        t.start()

    # 主循環(huán)
    UP, DOWN, LEFT, RIGHT = 1, 2, 3, 4
    direction = RIGHT
    while True:
        # 處理游戲事件
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                if messagebox.askyesno("確認(rèn)", "是否要退出?"):
                    game_quit()
            elif event.type == pygame.KEYDOWN:
                # 增加 WASD 四鍵對(duì)應(yīng) 上左下右 方向鍵
                if not is_paused:
                    if   (event.key == pygame.K_w or event.key == pygame.K_UP)    and direction != DOWN:
                        direction = UP
                    elif (event.key == pygame.K_s or event.key == pygame.K_DOWN)  and direction != UP:
                        direction = DOWN
                    elif (event.key == pygame.K_a or event.key == pygame.K_LEFT)  and direction != RIGHT:
                        direction = LEFT
                    elif (event.key == pygame.K_f or event.key == pygame.K_RIGHT) and direction != LEFT:
                        direction = RIGHT
                if event.key == pygame.K_y:
                    if is_dead:
                        init()
                        is_dead = False
                    is_running = True
                elif event.key == pygame.K_n:
                    if is_dead: game_quit()
                    else: is_running = True
                elif event.key == pygame.K_SPACE:
                    if is_dead: continue
                    if is_paused:
                        is_paused = False
                        pygame.mixer.music.unpause()
                    is_running = True
                elif event.key == pygame.K_ESCAPE:
                    if is_running:
                        show_msg(">>> Paused <<<")
                        is_paused = not is_paused
                        if is_paused:
                            pygame.mixer.music.pause()
                            if not is_mute: play_sound(1)
                        else:
                            pygame.mixer.music.unpause()
                elif event.key == pygame.K_m and event.mod & pygame.KMOD_CTRL:
                    # Ctrl+M 切換背景音樂
                    is_mute = False
                    music_no = 1 if music_no == 3 else music_no + 1
                    music_fn = f"voice{music_no}.mp3"
                    if exists(music_fn):
                        t = Thread(target=play_music, args=(music_fn,0.8,))
                        t.start()
                elif event.key == pygame.K_q and event.mod & pygame.KMOD_CTRL:
                    # Ctrl+Q 切換靜音狀態(tài)
                    is_mute = not is_mute
                    if is_mute:
                        pygame.mixer.music.pause()
                    else:
                        pygame.mixer.music.unpause()
                    is_running = True
                else: # 任意鍵進(jìn)入開始狀態(tài)
                    if is_dead: continue
                    is_running = True

        if not is_running: continue
        if is_paused: continue

        if direction   == UP:
            snake_speed = [0, -20]
        elif direction == DOWN:
            snake_speed = [0, 20]
        elif direction == LEFT:
            snake_speed = [-20, 0]
        elif direction == RIGHT:
            snake_speed = [20, 0]

        # 更新蛇的位置
        snake_pos.insert(0, [snake_pos[0][0] + snake_speed[0], snake_pos[0][1] + snake_speed[1]])

        # 檢查蛇頭是否碰到食物
        if snake_pos[0] == food_pos:
            scores += 10 + len(snake_pos) // 5
            if not 1 < snake_pos[0][0]//20 < 30 or not 1 < snake_pos[0][1]//20 < 22:
                scores += 5
            if not is_mute: play_sound(2)
            food_pos = [randrange(1, screen_size[0] // 20) * 20, randrange(1, screen_size[1] // 20) * 20]
        else:
            snake_pos.pop()

        # 檢查蛇頭是否碰到墻壁或者蛇身
        if snake_pos[0][0] < 0 or snake_pos[0][0] >= screen_size[0] or snake_pos[0][1] < 0 or snake_pos[0][1] >= screen_size[1] or snake_pos[0] in snake_pos[1:]:
            show_msg("Dead! Again? (Y or N)")
            is_running = False
            is_dead = True
            direction = RIGHT
            if not is_mute: play_sound(3)
            continue

        # 重畫界面及蛇和食物
        repaint()

        # 控制游戲速度
        pygame.time.Clock().tick(10)

if __name__ == "__main__":

    init()
    main()

最終版的源代碼及音樂文件列表如下:

Python “貪吃蛇”游戲,在不斷改進(jìn)中學(xué)習(xí)pygame編程,Python,pygame,python,開發(fā)語(yǔ)言

下載地址:?

https://download.csdn.net/download/boysoft2002/88231961文章來源地址http://www.zghlxwxcb.cn/news/detail-658305.html

到了這里,關(guān)于Python “貪吃蛇”游戲,在不斷改進(jìn)中學(xué)習(xí)pygame編程的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 學(xué)生學(xué)python編程---實(shí)現(xiàn)貪吃蛇小游戲+源碼

    學(xué)生學(xué)python編程---實(shí)現(xiàn)貪吃蛇小游戲+源碼

    前言 這幾年人工智能技術(shù)大發(fā)展,Python因此幾乎成了第一位的語(yǔ)言。實(shí)際上,多年來,它不僅在軟件工程師中得到廣泛使用,也是各行業(yè)通用的專家語(yǔ)言,就是說,不管孩子以后做什么,都可能用得著。準(zhǔn)備針對(duì)我自己上小學(xué)的孩子,每周抽出些時(shí)間,通過學(xué)習(xí)他們感興趣的

    2023年04月09日
    瀏覽(34)
  • Python基礎(chǔ)篇(十五)-- Pygame游戲編程

    Python基礎(chǔ)篇(十五)-- Pygame游戲編程

    ????????Pygame是一個(gè)開源的Python模塊,專門用于多媒體應(yīng)用(如電子游戲)的開發(fā),其中包含對(duì)圖像、聲音、視頻、事件、碰撞等的支持。Pygame建立在SDL的基礎(chǔ)上,SDL是一套跨平臺(tái)的多媒體開發(fā)庫(kù),用C語(yǔ)言實(shí)現(xiàn),被廣泛的應(yīng)用于游戲、模擬器、播放器等的開發(fā)。而Pygame讓

    2024年02月05日
    瀏覽(29)
  • ChatGPT4寫貪吃蛇游戲(Notion)[pygame的學(xué)習(xí)]

    ChatGPT4寫貪吃蛇游戲(Notion)[pygame的學(xué)習(xí)]

    這里我使用的是Notion寫出來的貪吃蛇,開始使用百度的文心一言來試下效果,生成了好幾次的代碼都是有bug,所以生成代碼這塊還得是ChatGPT。這篇主要就是了解下 pygame 庫(kù)的一些方法,當(dāng)然在沒有安裝這個(gè)庫(kù)的,需要先安裝,安裝的時(shí)候還是一直都推薦的安裝方法,帶上國(guó)內(nèi)

    2023年04月27日
    瀏覽(24)
  • 15. python從入門到精通——Pygame游戲編程

    15. python從入門到精通——Pygame游戲編程

    目錄 游戲的原理 安裝Pygame Pygame常用模塊 Pygame的基本使用? ? ? 實(shí)例:制作一個(gè)跳躍的小球游戲,如果碰到窗口邊緣會(huì)改變小球移動(dòng)方向 實(shí)現(xiàn)步驟: ?運(yùn)行效果: 小球圖片:? ?? ?python代碼: 開發(fā)Flappy Bird游戲 游戲簡(jiǎn)介: 運(yùn)行效果: 圖片素材 游戲分析? 以面向?qū)ο蟮乃季S

    2024年02月12日
    瀏覽(67)
  • Python 實(shí)現(xiàn)經(jīng)典游戲“貪吃蛇”:從零開始的趣味編程之旅

    在計(jì)算機(jī)科學(xué)和編程教育中,通過實(shí)現(xiàn)小游戲是學(xué)習(xí)和掌握一門編程語(yǔ)言的重要實(shí)踐方式。今天,我們將一起探索如何使用Python來打造一款經(jīng)典的、風(fēng)靡全球的游戲——貪吃蛇。這個(gè)項(xiàng)目不僅涵蓋了Python的基礎(chǔ)語(yǔ)法、面向?qū)ο缶幊趟枷?,還會(huì)涉及pygame庫(kù)的使用以及游戲循環(huán)、

    2024年02月21日
    瀏覽(28)
  • python | 基礎(chǔ)學(xué)習(xí)(六)pygame游戲開發(fā):飛機(jī)大戰(zhàn)

    python | 基礎(chǔ)學(xué)習(xí)(六)pygame游戲開發(fā):飛機(jī)大戰(zhàn)

    pygame 模塊,轉(zhuǎn)為電子游戲設(shè)計(jì) $ sudo pip3 install pygame windows: pip install pygame (1)新建項(xiàng)目 飛機(jī)大戰(zhàn) (2)新建文件 pygame.py (3)建立游戲窗口: ①pygame的初始化和退出 pygame.init() :導(dǎo)入并初始化所有pygame模塊,使用其他模塊之前,必須先調(diào)用init方法。 pygame.quit() :卸載所有

    2024年02月08日
    瀏覽(28)
  • 【python】 pygame學(xué)習(xí)示例 --飛機(jī)大戰(zhàn)小游戲制作

    【python】 pygame學(xué)習(xí)示例 --飛機(jī)大戰(zhàn)小游戲制作

    python版本:3.8.5 所需模塊:pygame random os pygame版本:20.1 開發(fā)環(huán)境:pycharm專業(yè)版 硬件環(huán)境:win11 8G內(nèi)存以上 使用python的第三方庫(kù)–pygame 制作飛機(jī)大戰(zhàn)小游戲 小游戲的內(nèi)容包括: 玩家player的移動(dòng) 子彈的發(fā)射 隕石的隨機(jī)掉落(包括旋轉(zhuǎn) 大小 下落角度) 玩家 子彈 隕石的碰撞交互

    2024年02月04日
    瀏覽(24)
  • 小游戲?qū)崙?zhàn)丨基于PyGame的貪吃蛇小游戲

    小游戲?qū)崙?zhàn)丨基于PyGame的貪吃蛇小游戲

    本期內(nèi)容:基于pygame的貪吃蛇小游戲 下載地址:https://download.csdn.net/download/m0_68111267/88700188 實(shí)驗(yàn)環(huán)境 python3.11及以上 pycharm pygame 安裝pygame的命令: pygame是一個(gè)開源的Python模塊,專門用于編寫電子游戲。它使用簡(jiǎn)單、功能強(qiáng)大,因此非常適合初學(xué)者入門。pygame的主要特點(diǎn)包括圖

    2024年02月03日
    瀏覽(100)
  • 游戲開發(fā)丨基于Pygame的AI版貪吃蛇小游戲

    游戲開發(fā)丨基于Pygame的AI版貪吃蛇小游戲

    本期內(nèi)容 基于pygame的AI版貪吃蛇小游戲 所需環(huán)境 python pycharm或anaconda pygame 下載地址 https://download.csdn.net/download/m0_68111267/88789665 本游戲使用Pygame模塊開發(fā),不需要玩家操縱貪吃蛇,貪吃蛇會(huì)自動(dòng)吃掉屏幕上隨機(jī)出現(xiàn)的食物,每吃一個(gè)食物貪吃蛇長(zhǎng)度增加一節(jié)。如果貪吃蛇撞到

    2024年02月20日
    瀏覽(29)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包