主頁 > 後端開發 > python小游戲

python小游戲

2021-07-30 07:51:21 後端開發

在這里插入圖片描述

'''
公眾號:一行資料,關注領取5T編程資料
'''

import pygame
import sys
import random


class Bird(object):
    """定義一個鳥類"""

    def __init__(self):
        """定義初始化方法"""
        self.birdRect = pygame.Rect(65, 50, 50, 50)  # 鳥的矩形
        # 定義鳥的3種狀態串列
        self.birdStatus = [pygame.image.load("assets/1.png"),
                           pygame.image.load("assets/2.png"),
                           pygame.image.load("assets/dead.png")]
        self.status = 0      # 默認飛行狀態
        self.birdX = 120     # 鳥所在X軸坐標,即是向右飛行的速度
        self.birdY = 350     # 鳥所在Y軸坐標,即上下飛行高度
        self.jump = False    # 默認情況小鳥自動降落
        self.jumpSpeed = 10  # 跳躍高度
        self.gravity = 5     # 重力
        self.dead = False    # 默認小鳥生命狀態為活著

    def birdUpdate(self):
        if self.jump:
            # 小鳥跳躍
            self.jumpSpeed -= 1           # 速度遞減,上升越來越慢
            self.birdY -= self.jumpSpeed  # 鳥Y軸坐標減小,小鳥上升
        else:
            # 小鳥墜落
            self.gravity += 0.2           # 重力遞增,下降越來越快
            self.birdY += self.gravity    # 鳥Y軸坐標增加,小鳥下降
        self.birdRect[1] = self.birdY     # 更改Y軸位置


class Pipeline(object):
    """定義一個管道類"""

    def __init__(self):
        """定義初始化方法"""
        self.wallx = 400  # 管道所在X軸坐標
        self.pineUp = pygame.image.load("assets/top.png")
        self.pineDown = pygame.image.load("assets/bottom.png")

    def updatePipeline(self):
        """"管道移動方法"""
        self.wallx -= 5  # 管道X軸坐標遞減,即管道向左移動
        # 當管道運行到一定位置,即小鳥飛越管道,分數加1,并且重置管道
        if self.wallx < -80:
            global score
            score += 1
            self.wallx = 400


def createMap():
    """定義創建地圖的方法"""
    screen.fill((255, 255, 255))     # 填充顏色
    screen.blit(background, (0, 0))  # 填入到背景

    # 顯示管道
    screen.blit(Pipeline.pineUp, (Pipeline.wallx, -300))   # 上管道坐標位置
    screen.blit(Pipeline.pineDown, (Pipeline.wallx, 500))  # 下管道坐標位置
    Pipeline.updatePipeline()  # 管道移動

    # 顯示小鳥
    if Bird.dead:              # 撞管道狀態
        Bird.status = 2
    elif Bird.jump:            # 起飛狀態
        Bird.status = 1
    screen.blit(Bird.birdStatus[Bird.status], (Bird.birdX, Bird.birdY))              # 設定小鳥的坐標
    Bird.birdUpdate()          # 鳥移動

    # 顯示分數
    screen.blit(font.render('Score:' + str(score), -1, (255, 255, 255)), (100, 50))  # 設定顏色及坐標位置
    pygame.display.update()    # 更新顯示


def checkDead():
    # 上方管子的矩形位置
    upRect = pygame.Rect(Pipeline.wallx, -300,
                         Pipeline.pineUp.get_width() - 10,
                         Pipeline.pineUp.get_height())

    # 下方管子的矩形位置
    downRect = pygame.Rect(Pipeline.wallx, 500,
                           Pipeline.pineDown.get_width() - 10,
                           Pipeline.pineDown.get_height())
    # 檢測小鳥與上下方管子是否碰撞
    if upRect.colliderect(Bird.birdRect) or downRect.colliderect(Bird.birdRect):
        Bird.dead = True
    # 檢測小鳥是否飛出上下邊界
    if not 0 < Bird.birdRect[1] < height:
        Bird.dead = True
        return True
    else:
        return False


def getResutl():
    final_text1 = "Game Over"
    final_text2 = "Your final score is:  " + str(score)
    ft1_font = pygame.font.SysFont("Arial", 70)                                      # 設定第一行文字字體
    ft1_surf = font.render(final_text1, 1, (242, 3, 36))                             # 設定第一行文字顏色
    ft2_font = pygame.font.SysFont("Arial", 50)                                      # 設定第二行文字字體
    ft2_surf = font.render(final_text2, 1, (253, 177, 6))                            # 設定第二行文字顏色
    screen.blit(ft1_surf, [screen.get_width() / 2 - ft1_surf.get_width() / 2, 100])  # 設定第一行文字顯示位置
    screen.blit(ft2_surf, [screen.get_width() / 2 - ft2_surf.get_width() / 2, 200])  # 設定第二行文字顯示位置
    pygame.display.flip()                                                            # 更新整個待顯示的Surface物件到螢屏上


if __name__ == '__main__':
    """主程式"""
    pygame.init()                            # 初始化pygame
    pygame.font.init()                       # 初始化字體
    font = pygame.font.SysFont("ziti.ttf", 50)  # 設定字體和大小
    size = width, height = 400, 650          # 設定視窗
    screen = pygame.display.set_mode(size)   # 顯示視窗
    clock = pygame.time.Clock()              # 設定時鐘
    Pipeline = Pipeline()                    # 實體化管道類
    Bird = Bird()                            # 實體化鳥類
    score = 0
    while True:
        clock.tick(60)                       # 每秒執行60次
        # 輪詢事件
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                sys.exit()
            if (event.type == pygame.KEYDOWN or event.type == pygame.MOUSEBUTTONDOWN) and not Bird.dead:
                Bird.jump = True             # 跳躍
                Bird.gravity = 5             # 重力
                Bird.jumpSpeed = 10          # 跳躍速度

        background = pygame.image.load("assets/background.png")  # 加載背景圖片
        if checkDead():                      # 檢測小鳥生命狀態
            getResutl()                      # 如果小鳥死亡,顯示游戲總分數
        else:
            createMap()                      # 創建地圖
    pygame.quit()



俄羅斯方塊

# -*- coding:utf-8 -*-
'''
公眾號:【一行資料】,關注領取5T編程資料
'''
import sys
import random, copy
import pygame as pg
from pygame.locals import *

'''
常量宣告
'''
EMPTY_CELL = 0  # 空區標識,表示沒有方塊
FALLING_BLOCK = 1  # 下落中的方塊標識,也就是活動方塊,
STATIC_BLOCK = 2  # 固實方塊標識

'''
全域變數宣告
變數值以sysInit函式中初始化后的結果為準
'''
defaultFont = None  # 默認字體
screen = None  # 螢屏輸出物件
backSurface = None  # 影像輸出緩沖畫板
score = 0  # 玩家得分記錄
clearLineScore = 0  # 玩家清除的方塊行數
level = 1  # 關卡等級
clock = None  # 游戲時鐘
nowBlock = None  # 當前下落中的方塊
nextBlock = None  # 下一個將出現的方塊
fallSpeed = 10  # 當前方塊下落速度
beginFallSpeed = fallSpeed  # 游戲初始時方塊下落速度
speedBuff = 0  # 下落速度緩沖變數
keyBuff = None  # 上一次按鍵記錄
maxBlockWidth = 10  # 舞臺堆疊區X軸最大可容納基礎方塊數
maxBlockHeight = 18  # 舞臺堆疊區Y軸最大可容納基礎方塊數
blockWidth = 30  # 以像素為單位的基礎方塊寬度
blockHeight = 30  # 以像素為單位的基礎方塊高度
blocks = []  # 方塊形狀矩陣四維串列,第一維為不同的方塊形狀,第二維為每個方塊形狀不同的方向(以0下標起始,一共四個方向),第三維為Y軸方塊形狀占用情況,第四維為X軸方塊形狀占用情況,矩陣中0表示沒有方塊,1表示有方塊,
stage = []  # 舞臺堆疊區矩陣二維串列,第一維為Y軸方塊占用情況,第二維為X軸方塊占用情況,矩陣中0表示沒有方塊,1表示有固實方塊,2表示有活動方塊,
gameOver = False  # 游戲結束標志
pause = False  # 游戲暫圖示志


def printTxt(content, x, y, font, screen, color=(255, 255, 255)):
    '''顯示文本
    args:
        content:待顯示文本內容
        x,y:顯示坐標
        font:字體
        screen:輸出的screen
        color:顏色
    '''
    imgTxt = font.render(content, True, color)
    screen.blit(imgTxt, (x, y))


class point(object):
    '''平面坐標點類
    attributes:
        x,y:坐標值
    '''

    def __init__(self, x, y):
        self.__x = x
        self.__y = y

    def getx(self):
        return self.__x

    def setx(self, x):
        self.__x = x

    x = property(getx, setx)

    def gety(self):
        return self.__y

    def sety(self, y):
        self.__y = y

    y = property(gety, sety)

    def __str__(self):
        return "{x:" + "{:.0f}".format(self.__x) + ",y:" + "{:.0f}".format(self.__y) + "}"


class blockSprite(object):
    '''
    方塊形狀精靈類
    下落方塊的定義全靠它了,
    attributes:
        shape:方塊形狀編號
        direction:方塊方向編號
        xy,方塊形狀左上角方塊坐標
        block:方塊形狀矩陣
    '''

    def __init__(self, shape, direction, xy):
        self.shape = shape
        self.direction = direction
        self.xy = xy

    def chgDirection(self, direction):
        '''
        改變方塊的方向
        args:
            direction:1為向右轉,0為向左轉,
        '''
        dirNumb = len(blocks[self.shape]) - 1
        if direction == 1:
            self.direction += 1
            if self.direction > dirNumb:
                self.direction = 0
        else:
            self.direction -= 1
            if self.direction < 0:
                self.direction = dirNumb

    def clone(self):
        '''
        克隆本體
        return:
            回傳自身的克隆
        '''
        return blockSprite(self.shape, self.direction, point(self.xy.x, self.xy.y))

    def _getBlock(self):
        return blocks[self.shape][self.direction]

    block = property(_getBlock)


def getConf(fileName):
    '''
    從組態檔中讀取方塊形狀資料
    每個方塊以4*4矩陣表示形狀,組態檔每行代表一個方塊,用分號分隔矩陣行,用逗號分隔矩陣列,0表示沒有方塊,1表示有方塊,
    因為此程式只針對俄羅斯方塊的經典版,所以方塊矩陣大小以硬編碼的形式寫死為4*4,
    args:
        fileName:組態檔名
    '''
    global blocks  # blocks記錄方塊形狀,
    with open(fileName, 'rt') as fp:
        for temp in fp.readlines():
            blocks.append([])
            blocksNumb = len(blocks) - 1
            blocks[blocksNumb] = []
            # 每種方塊形狀有四個方向,以0~3表示,組態檔中只記錄一個方向形狀,另外三個方向的矩陣排列在sysInit中通過呼叫transform計算出來,
            blocks[blocksNumb].append([])
            row = temp.split(";")
            for r in range(len(row)):
                col = []
                ct = row[r].split(",")
                # 對矩陣列資料做規整,首先將非“1”的值全修正成“0”以過濾空字串或回車符,
                for c in range(len(ct)):
                    if ct[c] != "1":
                        col.append(0)
                    else:
                        col.append(1)
                # 將不足4列的矩陣通過補“0”的方式,補足4列,
                for c in range(len(ct) - 1, 3):
                    col.append(0)
                blocks[blocksNumb][0].append(col)
            # 如果矩陣某行沒有方塊,則組態檔中可以省略此行,程式會在末尾補上空行資料,
            for r in range(len(row) - 1, 3):
                blocks[blocksNumb][0].append([0, 0, 0, 0])
            blocks[blocksNumb][0] = formatBlock(blocks[blocksNumb][0])


def sysInit():
    '''
    系統初始化
    包括pygame環境初始化,全域變數賦值,生成每個方塊形狀的四個方向矩陣,
    '''
    global defaultFont, screen, backSurface, clock, blocks, stage, gameOver, fallSpeed, beginFallSpeed, nowBlock, nextBlock, score, level, clearLineScore, pause

    # pygame運行環境初始化
    pg.init()
    screen = pg.display.set_mode((500, 550))
    backSurface = pg.Surface((screen.get_rect().width, screen.get_rect().height))
    pg.display.set_caption("block")
    clock = pg.time.Clock()
    pg.mouse.set_visible(False)

    # 游戲全域變數初始化
    defaultFont = pg.font.Font(None, 16)  # yh.ttf這個字體檔案請自行上網搜索下載,如果找不到就隨便用個ttf格式字體檔案替換一下,
    nowBlock = None
    nextBlock = None
    gameOver = False
    pause = False
    score = 0
    level = 1
    clearLineScore = 0
    beginFallSpeed = 20
    fallSpeed = beginFallSpeed - level * 2

    # 初始化游戲舞臺
    stage = []
    for y in range(maxBlockHeight):
        stage.append([])
        for x in range(maxBlockWidth):
            stage[y].append(EMPTY_CELL)

    # 生成每個方塊形狀4個方向的矩陣資料
    for x in range(len(blocks)):
        # 因為重新開始游戲時會呼叫sysinit對系統所有引數重新初始化,為了避免方向矩陣資料重新生成,需要在此判斷是否已經生成,如果已經生成則跳過,
        if len(blocks[x]) < 2:
            t = blocks[x][0]
            for i in range(3):
                t = transform(t, 1)
                blocks[x].append(formatBlock(t))


# transform,removeTopBlank,formatBlock這三個函式只為生成方塊形狀4個方向矩陣使用,在游戲其他環節無作用,在閱讀程式時可以先跳過,
def transform(block, direction=0):
    '''
    生成指定方塊形狀轉換方向后的矩陣資料
    args:
        block:方塊形狀矩陣引數
        direction:轉換的方向,0代表向左,1代表向右
    return:
        變換方向后的方塊形狀矩陣引數
    '''
    result = []
    for y in range(4):
        result.append([])
        for x in range(4):
            if direction == 0:
                result[y].append(block[x][3 - y])
            else:
                result[y].append(block[3 - x][y])
    return result


def removeTopBlank(block):
    '''
    清除方塊矩陣頂部空行資料
    args:
        block:方塊開關矩陣
    return:
        整理后的方塊矩陣資料
    '''
    result = copy.deepcopy(block)
    blankNumb = 0
    while sum(result[0]) < 1 and blankNumb < 4:
        del result[0]
        result.append([0, 0, 0, 0])
        blankNumb += 1
    return result


def formatBlock(block):
    '''
    整理方塊矩陣資料,使方塊在矩陣中處于左上角的位置
    args:
        block:方塊開關矩陣
    return:
        整理后的方塊矩陣資料
    '''
    result = removeTopBlank(block)
    # 將矩陣右轉,用于計算左側X軸線空行,計算完成后再轉回
    result = transform(result, 1)
    result = removeTopBlank(result)
    result = transform(result, 0)
    return result


def checkDeany(sprite):
    '''
    檢查下落方塊是否與舞臺堆疊區中固實方塊發生碰撞
    args:
        sprite:下落方塊
    return:
        如果發生碰撞則回傳True
    '''
    topX = sprite.xy.x
    topY = sprite.xy.y
    for y in range(len(sprite.block)):
        for x in range(len(sprite.block[y])):
            if sprite.block[y][x] == 1:
                yInStage = topY + y
                xInStage = topX + x
                if yInStage > maxBlockHeight - 1 or yInStage < 0:
                    return True
                if xInStage > maxBlockWidth - 1 or xInStage < 0:
                    return True
                if stage[yInStage][xInStage] == STATIC_BLOCK:
                    return True
    return False


def checkLine():
    '''
    檢測堆疊區是否有可消除的整行固實方塊
    根據檢測結果重新生成堆疊區矩陣資料,呼叫updateScore函式更新玩家積分等資料,
    return:
        本輪下落周期消除的固實方塊行數
    '''
    global stage
    clearCount = 0  # 本輪下落周期消除的固實方塊行數
    tmpStage = []  # 根據消除情況新生成的堆疊區矩陣,在有更新的情況下會替換全域的堆疊區矩陣,

    for y in stage:
        # 因為固實方塊在堆疊矩陣里以2表示,所以判斷方塊是否已經滿一整行只要計算矩陣行數值合計是否等于堆疊區X軸最大方塊數*2就可以,
        if sum(y) >= maxBlockWidth * 2:
            tmpStage.insert(0, maxBlockWidth * [0])
            clearCount += 1
        else:
            tmpStage.append(y)
    if clearCount > 0:
        stage = tmpStage
        updateScore(clearCount)
    return clearCount


def updateStage(sprite, updateType=1):
    '''
    將下落方塊坐標資料更新到堆疊區資料中,下落方塊涉及的坐標在堆疊區中用數字1標識,固實方塊在堆疊區中用數字2標識,
    args:
        sprite:下落方塊形狀
        updateType:更新方式,0代表清除,1代表動態加入,2代表固實加入,
    '''

    global stage
    topX = sprite.xy.x
    topY = sprite.xy.y
    for y in range(len(sprite.block)):
        for x in range(len(sprite.block[y])):
            if sprite.block[y][x] == 1:
                if updateType == 0:
                    if stage[topY + y][topX + x] == FALLING_BLOCK:
                        stage[topY + y][topX + x] = EMPTY_CELL
                elif updateType == 1:
                    if stage[topY + y][topX + x] == EMPTY_CELL:
                        stage[topY + y][topX + x] = FALLING_BLOCK
                else:
                    stage[topY + y][topX + x] = STATIC_BLOCK


def updateScore(clearCount):
    '''
    更新玩家游戲記錄,包括積分、關卡、消除方塊行數,并且根據關卡數更新方塊下落速度,
    args:
        clearCount:本輪下落周期內清除的方塊行數,
    return:
        當前游戲的最新積分
    '''
    global score, fallSpeed, level, clearLineScore

    prizePoint = 0  # 額外獎勵分數,同時消除的行數越多,獎勵分值越高,
    if clearCount > 1:
        if clearCount < 4:
            prizePoint = clearCount ** clearCount
        else:
            prizePoint = clearCount * 5
    score += (clearCount + prizePoint) * level + 10
    # 玩得再牛又有何用? :)
    if score > 99999999:
        score = 0
    clearLineScore += clearCount
    if clearLineScore > 10:
        clearLineScore = 0
        level += 1
        if level > (beginFallSpeed / 2):
            level = 1
            fallSpeed = beginFallSpeed
        fallSpeed = beginFallSpeed - level * 2
    return score


def drawStage(drawScreen):
    '''
    在給定的畫布上繪制舞臺
    args:
        drawScreen:待繪制的畫布
    '''
    staticColor = 30, 102, 76  # 固實方塊顏色
    activeColor = 255, 239, 0  # 方塊形狀顏色
    fontColor = 200, 10, 120  # 文字顏色
    baseRect = 0, 0, blockWidth * maxBlockWidth + 1, blockHeight * maxBlockHeight + 1  # 堆疊區方框

    # 繪制堆疊區外框
    drawScreen.fill((180, 200, 170))
    pg.draw.rect(drawScreen, staticColor, baseRect, 1)

    # 繪制堆疊區內的所有方塊,包括下落方塊形狀
    for y in range(len(stage)):
        for x in range(len(stage[y])):
            baseRect = x * blockWidth, y * blockHeight, blockWidth, blockHeight
            if stage[y][x] == 2:
                pg.draw.rect(drawScreen, staticColor, baseRect)
            elif stage[y][x] == 1:
                pg.draw.rect(drawScreen, activeColor, baseRect)

    # 繪制下一個登場的下落方塊形狀
    printTxt("Next:", 320, 350, defaultFont, backSurface, fontColor)
    if nextBlock != None:
        for y in range(len(nextBlock.block)):
            for x in range(len(nextBlock.block[y])):
                baseRect = 320 + x * blockWidth, 380 + y * blockHeight, blockWidth, blockHeight
                if nextBlock.block[y][x] == 1:
                    pg.draw.rect(drawScreen, activeColor, baseRect)

    # 繪制關卡、積分、當前關卡消除整行數
    printTxt("Level:%d" % level, 320, 40, defaultFont, backSurface, fontColor)
    printTxt("Score:%d" % score, 320, 70, defaultFont, backSurface, fontColor)
    printTxt("Clear:%d" % clearLineScore, 320, 100, defaultFont, backSurface, fontColor)

    # 特殊游戲狀態的輸出
    if gameOver:
        printTxt("GAME OVER", 230, 200, defaultFont, backSurface, fontColor)
        printTxt("<PRESS ENTER TO REPLAY>", 200, 260, defaultFont, backSurface, fontColor)
    if pause:
        printTxt("Game pausing", 230, 200, defaultFont, backSurface, fontColor)
        printTxt("<PRESS ENTER TO CONTINUE>", 200, 260, defaultFont, backSurface, fontColor)


def process():
    '''
    游戲控制及邏輯處理
    '''
    global gameOver, nowBlock, nextBlock, speedBuff, backSurface, keyBuff, pause

    if nextBlock is None:
        nextBlock = blockSprite(random.randint(0, len(blocks) - 1), random.randint(0, 3),
                                point(maxBlockWidth + 4, maxBlockHeight))
    if nowBlock is None:
        nowBlock = nextBlock.clone()
        nowBlock.xy = point(maxBlockWidth // 2, 0)
        nextBlock = blockSprite(random.randint(0, len(blocks) - 1), random.randint(0, 3),
                                point(maxBlockWidth + 4, maxBlockHeight))
        # 每次生成新的下落方塊形狀時檢測碰撞,如果新的方塊形狀一出現就發生碰撞,則顯然玩家已經沒有機會了,
        gameOver = checkDeany(nowBlock)
        # 游戲失敗后,要將活動方塊形狀做固實處理
        if gameOver:
            updateStage(nowBlock, 2)

    '''
    對于下落方塊形狀操控以及移動,采用影子形狀進行預判斷,如果沒有碰撞則將變化應用到下落方塊形狀上,否則不變化,
    '''
    tmpBlock = nowBlock.clone()  # 影子方塊形狀
    '''
    處理用戶輸入
    對于用戶輸入分為兩部分處理,
    第一部分,將退出、暫停、重新開始以及形狀變換的操作以敲擊事件處理,
    這樣做的好處是只對敲擊一次鍵盤做出處理,避免用戶按住單一按鍵后程式反復處理影響操控,特別是形狀變換操作,敲擊一次鍵盤換變一次方向,玩家很容易控制,
    '''
    for event in pg.event.get():
        if event.type == pg.QUIT:
            sys.exit()
            pg.quit()
        elif event.type == pg.KEYDOWN:
            if event.key == pg.K_ESCAPE:
                sys.exit()
                pg.quit()
            elif event.key == pg.K_RETURN:
                if gameOver:
                    sysInit()
                    return
                elif pause:
                    pause = False
                else:
                    pause = True
                    return
            elif not gameOver and not pause:
                if event.key == pg.K_SPACE:
                    tmpBlock.chgDirection(1)
                elif event.key == pg.K_UP:
                    tmpBlock.chgDirection(0)

    if not gameOver and not pause:
        '''
        用戶輸入處理第二部分,將左右移動和快速下落的操作以按下事件處理,
        這樣做的好處是不需要玩家反復敲擊鍵盤進行操作,保證了操作的連貫性,
        由于連續移動的速度太快,不利于定位,所以在程式中采用了簡單的輸入級訓處理,即通過keyBuff保存上一次操作按鍵,如果此次按鍵與上一次按鍵相同,則跳過此輪按鍵處理,
        '''
        keys = pg.key.get_pressed()
        if keys[K_DOWN]:
            tmpBlock.xy = point(tmpBlock.xy.x, tmpBlock.xy.y + 1)
            keyBuff = None
        elif keys[K_LEFT]:
            if keyBuff != pg.K_LEFT:
                tmpBlock.xy = point(tmpBlock.xy.x - 1, tmpBlock.xy.y)
                keyBuff = pg.K_LEFT
            else:
                keyBuff = None
        elif keys[K_RIGHT]:
            if keyBuff != pg.K_RIGHT:
                tmpBlock.xy = point(tmpBlock.xy.x + 1, tmpBlock.xy.y)
                keyBuff = pg.K_RIGHT
            else:
                keyBuff = None
        if not checkDeany(tmpBlock):
            updateStage(nowBlock, 0)
            nowBlock = tmpBlock.clone()

        # 處理自動下落
        speedBuff += 1
        if speedBuff >= fallSpeed:
            speedBuff = 0
            tmpBlock = nowBlock.clone()
            tmpBlock.xy = point(nowBlock.xy.x, nowBlock.xy.y + 1)
            if not checkDeany(tmpBlock):
                updateStage(nowBlock, 0)
                nowBlock = tmpBlock.clone()
                updateStage(nowBlock, 1)
            else:
                # 在自動下落程序中一但發生活動方塊形狀的碰撞,則將活動方塊形狀做固實處理,并檢測是否有可消除的整行方塊
                updateStage(nowBlock, 2)
                checkLine()
                nowBlock = None
        else:
            updateStage(nowBlock, 1)
    drawStage(backSurface)
    screen.blit(backSurface, (0, 0))
    pg.display.update()
    clock.tick(40)


def main():
    '''
    主程式
    '''
    getConf("elsfk.cfg")
    sysInit()
    while True:
        process()


if __name__ == "__main__":
    main()

我的世界
在這里插入圖片描述

'''
公眾號:【一行資料】,關注領取5T編程資料
'''
from __future__ import division

import sys
import math
import random
import time

from collections import deque
from pyglet import image
from pyglet.gl import *
from pyglet.graphics import TextureGroup
from pyglet.window import key, mouse

TICKS_PER_SEC = 60

# Size of sectors used to ease block loading.
SECTOR_SIZE = 16

WALKING_SPEED = 5
FLYING_SPEED = 15

GRAVITY = 20.0
MAX_JUMP_HEIGHT = 1.0 # About the height of a block.
# To derive the formula for calculating jump speed, first solve
#    v_t = v_0 + a * t
# for the time at which you achieve maximum height, where a is the acceleration
# due to gravity and v_t = 0. This gives:
#    t = - v_0 / a
# Use t and the desired MAX_JUMP_HEIGHT to solve for v_0 (jump speed) in
#    s = s_0 + v_0 * t + (a * t^2) / 2
JUMP_SPEED = math.sqrt(2 * GRAVITY * MAX_JUMP_HEIGHT)
TERMINAL_VELOCITY = 50

PLAYER_HEIGHT = 2

if sys.version_info[0] >= 3:
    xrange = range

def cube_vertices(x, y, z, n):
    """ Return the vertices of the cube at position x, y, z with size 2*n.

    """
    return [
        x-n,y+n,z-n, x-n,y+n,z+n, x+n,y+n,z+n, x+n,y+n,z-n,  # top
        x-n,y-n,z-n, x+n,y-n,z-n, x+n,y-n,z+n, x-n,y-n,z+n,  # bottom
        x-n,y-n,z-n, x-n,y-n,z+n, x-n,y+n,z+n, x-n,y+n,z-n,  # left
        x+n,y-n,z+n, x+n,y-n,z-n, x+n,y+n,z-n, x+n,y+n,z+n,  # right
        x-n,y-n,z+n, x+n,y-n,z+n, x+n,y+n,z+n, x-n,y+n,z+n,  # front
        x+n,y-n,z-n, x-n,y-n,z-n, x-n,y+n,z-n, x+n,y+n,z-n,  # back
    ]


def tex_coord(x, y, n=4):
    """ Return the bounding vertices of the texture square.

    """
    m = 1.0 / n
    dx = x * m
    dy = y * m
    return dx, dy, dx + m, dy, dx + m, dy + m, dx, dy + m


def tex_coords(top, bottom, side):
    """ Return a list of the texture squares for the top, bottom and side.

    """
    top = tex_coord(*top)
    bottom = tex_coord(*bottom)
    side = tex_coord(*side)
    result = []
    result.extend(top)
    result.extend(bottom)
    result.extend(side * 4)
    return result


TEXTURE_PATH = 'texture.png'

GRASS = tex_coords((1, 0), (0, 1), (0, 0))
SAND = tex_coords((1, 1), (1, 1), (1, 1))
BRICK = tex_coords((2, 0), (2, 0), (2, 0))
STONE = tex_coords((2, 1), (2, 1), (2, 1))

FACES = [
    ( 0, 1, 0),
    ( 0,-1, 0),
    (-1, 0, 0),
    ( 1, 0, 0),
    ( 0, 0, 1),
    ( 0, 0,-1),
]


def normalize(position):
    """ Accepts `position` of arbitrary precision and returns the block
    containing that position.

    Parameters
    ----------
    position : tuple of len 3

    Returns
    -------
    block_position : tuple of ints of len 3

    """
    x, y, z = position
    x, y, z = (int(round(x)), int(round(y)), int(round(z)))
    return (x, y, z)


def sectorize(position):
    """ Returns a tuple representing the sector for the given `position`.

    Parameters
    ----------
    position : tuple of len 3

    Returns
    -------
    sector : tuple of len 3

    """
    x, y, z = normalize(position)
    x, y, z = x // SECTOR_SIZE, y // SECTOR_SIZE, z // SECTOR_SIZE
    return (x, 0, z)


class Model(object):

    def __init__(self):

        # A Batch is a collection of vertex lists for batched rendering.
        self.batch = pyglet.graphics.Batch()

        # A TextureGroup manages an OpenGL texture.
        self.group = TextureGroup(image.load(TEXTURE_PATH).get_texture())

        # A mapping from position to the texture of the block at that position.
        # This defines all the blocks that are currently in the world.
        self.world = {}

        # Same mapping as `world` but only contains blocks that are shown.
        self.shown = {}

        # Mapping from position to a pyglet `VertextList` for all shown blocks.
        self._shown = {}

        # Mapping from sector to a list of positions inside that sector.
        self.sectors = {}

        # Simple function queue implementation. The queue is populated with
        # _show_block() and _hide_block() calls
        self.queue = deque()

        self._initialize()

    def _initialize(self):
        """ Initialize the world by placing all the blocks.

        """
        n = 80  # 1/2 width and height of world
        s = 1  # step size
        y = 0  # initial y height
        for x in xrange(-n, n + 1, s):
            for z in xrange(-n, n + 1, s):
                # create a layer stone an grass everywhere.
                self.add_block((x, y - 2, z), GRASS, immediate=False)
                self.add_block((x, y - 3, z), STONE, immediate=False)
                if x in (-n, n) or z in (-n, n):
                    # create outer walls.
                    for dy in xrange(-2, 3):
                        self.add_block((x, y + dy, z), STONE, immediate=False)

        # generate the hills randomly
        o = n - 10
        for _ in xrange(120):
            a = random.randint(-o, o)  # x position of the hill
            b = random.randint(-o, o)  # z position of the hill
            c = -1  # base of the hill
            h = random.randint(1, 6)  # height of the hill
            s = random.randint(4, 8)  # 2 * s is the side length of the hill
            d = 1  # how quickly to taper off the hills
            t = random.choice([GRASS, SAND, BRICK])
            for y in xrange(c, c + h):
                for x in xrange(a - s, a + s + 1):
                    for z in xrange(b - s, b + s + 1):
                        if (x - a) ** 2 + (z - b) ** 2 > (s + 1) ** 2:
                            continue
                        if (x - 0) ** 2 + (z - 0) ** 2 < 5 ** 2:
                            continue
                        self.add_block((x, y, z), t, immediate=False)
                s -= d  # decrement side lenth so hills taper off

    def hit_test(self, position, vector, max_distance=8):
        """ Line of sight search from current position. If a block is
        intersected it is returned, along with the block previously in the line
        of sight. If no block is found, return None, None.

        Parameters
        ----------
        position : tuple of len 3
            The (x, y, z) position to check visibility from.
        vector : tuple of len 3
            The line of sight vector.
        max_distance : int
            How many blocks away to search for a hit.

        """
        m = 8
        x, y, z = position
        dx, dy, dz = vector
        previous = None
        for _ in xrange(max_distance * m):
            key = normalize((x, y, z))
            if key != previous and key in self.world:
                return key, previous
            previous = key
            x, y, z = x + dx / m, y + dy / m, z + dz / m
        return None, None

    def exposed(self, position):
        """ Returns False is given `position` is surrounded on all 6 sides by
        blocks, True otherwise.

        """
        x, y, z = position
        for dx, dy, dz in FACES:
            if (x + dx, y + dy, z + dz) not in self.world:
                return True
        return False

    def add_block(self, position, texture, immediate=True):
        """ Add a block with the given `texture` and `position` to the world.

        Parameters
        ----------
        position : tuple of len 3
            The (x, y, z) position of the block to add.
        texture : list of len 3
            The coordinates of the texture squares. Use `tex_coords()` to
            generate.
        immediate : bool
            Whether or not to draw the block immediately.

        """
        if position in self.world:
            self.remove_block(position, immediate)
        self.world[position] = texture
        self.sectors.setdefault(sectorize(position), []).append(position)
        if immediate:
            if self.exposed(position):
                self.show_block(position)
            self.check_neighbors(position)

    def remove_block(self, position, immediate=True):
        """ Remove the block at the given `position`.

        Parameters
        ----------
        position : tuple of len 3
            The (x, y, z) position of the block to remove.
        immediate : bool
            Whether or not to immediately remove block from canvas.

        """
        del self.world[position]
        self.sectors[sectorize(position)].remove(position)
        if immediate:
            if position in self.shown:
                self.hide_block(position)
            self.check_neighbors(position)

    def check_neighbors(self, position):
        """ Check all blocks surrounding `position` and ensure their visual
        state is current. This means hiding blocks that are not exposed and
        ensuring that all exposed blocks are shown. Usually used after a block
        is added or removed.

        """
        x, y, z = position
        for dx, dy, dz in FACES:
            key = (x + dx, y + dy, z + dz)
            if key not in self.world:
                continue
            if self.exposed(key):
                if key not in self.shown:
                    self.show_block(key)
            else:
                if key in self.shown:
                    self.hide_block(key)

    def show_block(self, position, immediate=True):
        """ Show the block at the given `position`. This method assumes the
        block has already been added with add_block()

        Parameters
        ----------
        position : tuple of len 3
            The (x, y, z) position of the block to show.
        immediate : bool
            Whether or not to show the block immediately.

        """
        texture = self.world[position]
        self.shown[position] = texture
        if immediate:
            self._show_block(position, texture)
        else:
            self._enqueue(self._show_block, position, texture)

    def _show_block(self, position, texture):
        """ Private implementation of the `show_block()` method.

        Parameters
        ----------
        position : tuple of len 3
            The (x, y, z) position of the block to show.
        texture : list of len 3
            The coordinates of the texture squares. Use `tex_coords()` to
            generate.

        """
        x, y, z = position
        vertex_data = cube_vertices(x, y, z, 0.5)
        texture_data = list(texture)
        # create vertex list
        # FIXME Maybe `add_indexed()` should be used instead
        self._shown[position] = self.batch.add(24, GL_QUADS, self.group,
            ('v3f/static', vertex_data),
            ('t2f/static', texture_data))

    def hide_block(self, position, immediate=True):
        """ Hide the block at the given `position`. Hiding does not remove the
        block from the world.

        Parameters
        ----------
        position : tuple of len 3
            The (x, y, z) position of the block to hide.
        immediate : bool
            Whether or not to immediately remove the block from the canvas.

        """
        self.shown.pop(position)
        if immediate:
            self._hide_block(position)
        else:
            self._enqueue(self._hide_block, position)

    def _hide_block(self, position):
        """ Private implementation of the 'hide_block()` method.

        """
        self._shown.pop(position).delete()

    def show_sector(self, sector):
        """ Ensure all blocks in the given sector that should be shown are
        drawn to the canvas.

        """
        for position in self.sectors.get(sector, []):
            if position not in self.shown and self.exposed(position):
                self.show_block(position, False)

    def hide_sector(self, sector):
        """ Ensure all blocks in the given sector that should be hidden are
        removed from the canvas.

        """
        for position in self.sectors.get(sector, []):
            if position in self.shown:
                self.hide_block(position, False)

    def change_sectors(self, before, after):
        """ Move from sector `before` to sector `after`. A sector is a
        contiguous x, y sub-region of world. Sectors are used to speed up
        world rendering.

        """
        before_set = set()
        after_set = set()
        pad = 4
        for dx in xrange(-pad, pad + 1):
            for dy in [0]:  # xrange(-pad, pad + 1):
                for dz in xrange(-pad, pad + 1):
                    if dx ** 2 + dy ** 2 + dz ** 2 > (pad + 1) ** 2:
                        continue
                    if before:
                        x, y, z = before
                        before_set.add((x + dx, y + dy, z + dz))
                    if after:
                        x, y, z = after
                        after_set.add((x + dx, y + dy, z + dz))
        show = after_set - before_set
        hide = before_set - after_set
        for sector in show:
            self.show_sector(sector)
        for sector in hide:
            self.hide_sector(sector)

    def _enqueue(self, func, *args):
        """ Add `func` to the internal queue.

        """
        self.queue.append((func, args))

    def _dequeue(self):
        """ Pop the top function from the internal queue and call it.

        """
        func, args = self.queue.popleft()
        func(*args)

    def process_queue(self):
        """ Process the entire queue while taking periodic breaks. This allows
        the game loop to run smoothly. The queue contains calls to
        _show_block() and _hide_block() so this method should be called if
        add_block() or remove_block() was called with immediate=False

        """
        start = time.clock()
        while self.queue and time.clock() - start < 1.0 / TICKS_PER_SEC:
            self._dequeue()

    def process_entire_queue(self):
        """ Process the entire queue with no breaks.

        """
        while self.queue:
            self._dequeue()


class Window(pyglet.window.Window):

    def __init__(self, *args, **kwargs):
        super(Window, self).__init__(*args, **kwargs)

        # Whether or not the window exclusively captures the mouse.
        self.exclusive = False

        # When flying gravity has no effect and speed is increased.
        self.flying = False

        # Strafing is moving lateral to the direction you are facing,
        # e.g. moving to the left or right while continuing to face forward.
        #
        # First element is -1 when moving forward, 1 when moving back, and 0
        # otherwise. The second element is -1 when moving left, 1 when moving
        # right, and 0 otherwise.
        self.strafe = [0, 0]

        # Current (x, y, z) position in the world, specified with floats. Note
        # that, perhaps unlike in math class, the y-axis is the vertical axis.
        self.position = (0, 0, 0)

        # First element is rotation of the player in the x-z plane (ground
        # plane) measured from the z-axis down. The second is the rotation
        # angle from the ground plane up. Rotation is in degrees.
        #
        # The vertical plane rotation ranges from -90 (looking straight down) to
        # 90 (looking straight up). The horizontal rotation range is unbounded.
        self.rotation = (0, 0)

        # Which sector the player is currently in.
        self.sector = None

        # The crosshairs at the center of the screen.
        self.reticle = None

        # Velocity in the y (upward) direction.
        self.dy = 0

        # A list of blocks the player can place. Hit num keys to cycle.
        self.inventory = [BRICK, GRASS, SAND]

        # The current block the user can place. Hit num keys to cycle.
        self.block = self.inventory[0]

        # Convenience list of num keys.
        self.num_keys = [
            key._1, key._2, key._3, key._4, key._5,
            key._6, key._7, key._8, key._9, key._0]

        # Instance of the model that handles the world.
        self.model = Model()

        # The label that is displayed in the top left of the canvas.
        self.label = pyglet.text.Label('', font_name='Arial', font_size=18,
            x=10, y=self.height - 10, anchor_x='left', anchor_y='top',
            color=(0, 0, 0, 255))

        # This call schedules the `update()` method to be called
        # TICKS_PER_SEC. This is the main game event loop.
        pyglet.clock.schedule_interval(self.update, 1.0 / TICKS_PER_SEC)

    def set_exclusive_mouse(self, exclusive):
        """ If `exclusive` is True, the game will capture the mouse, if False
        the game will ignore the mouse.

        """
        super(Window, self).set_exclusive_mouse(exclusive)
        self.exclusive = exclusive

    def get_sight_vector(self):
        """ Returns the current line of sight vector indicating the direction
        the player is looking.

        """
        x, y = self.rotation
        # y ranges from -90 to 90, or -pi/2 to pi/2, so m ranges from 0 to 1 and
        # is 1 when looking ahead parallel to the ground and 0 when looking
        # straight up or down.
        m = math.cos(math.radians(y))
        # dy ranges from -1 to 1 and is -1 when looking straight down and 1 when
        # looking straight up.
        dy = math.sin(math.radians(y))
        dx = math.cos(math.radians(x - 90)) * m
        dz = math.sin(math.radians(x - 90)) * m
        return (dx, dy, dz)

    def get_motion_vector(self):
        """ Returns the current motion vector indicating the velocity of the
        player.

        Returns
        -------
        vector : tuple of len 3
            Tuple containing the velocity in x, y, and z respectively.

        """
        if any(self.strafe):
            x, y = self.rotation
            strafe = math.degrees(math.atan2(*self.strafe))
            y_angle = math.radians(y)
            x_angle = math.radians(x + strafe)
            if self.flying:
                m = math.cos(y_angle)
                dy = math.sin(y_angle)
                if self.strafe[1]:
                    # Moving left or right.
                    dy = 0.0
                    m = 1
                if self.strafe[0] > 0:
                    # Moving backwards.
                    dy *= -1
                # When you are flying up or down, you have less left and right
                # motion.
                dx = math.cos(x_angle) * m
                dz = math.sin(x_angle) * m
            else:
                dy = 0.0
                dx = math.cos(x_angle)
                dz = math.sin(x_angle)
        else:
            dy = 0.0
            dx = 0.0
            dz = 0.0
        return (dx, dy, dz)

    def update(self, dt):
        """ This method is scheduled to be called repeatedly by the pyglet
        clock.

        Parameters
        ----------
        dt : float
            The change in time since the last call.

        """
        self.model.process_queue()
        sector = sectorize(self.position)
        if sector != self.sector:
            self.model.change_sectors(self.sector, sector)
            if self.sector is None:
                self.model.process_entire_queue()
            self.sector = sector
        m = 8
        dt = min(dt, 0.2)
        for _ in xrange(m):
            self._update(dt / m)

    def _update(self, dt):
        """ Private implementation of the `update()` method. This is where most
        of the motion logic lives, along with gravity and collision detection.

        Parameters
        ----------
        dt : float
            The change in time since the last call.

        """
        # walking
        speed = FLYING_SPEED if self.flying else WALKING_SPEED
        d = dt * speed # distance covered this tick.
        dx, dy, dz = self.get_motion_vector()
        # New position in space, before accounting for gravity.
        dx, dy, dz = dx * d, dy * d, dz * d
        # gravity
        if not self.flying:
            # Update your vertical speed: if you are falling, speed up until you
            # hit terminal velocity; if you are jumping, slow down until you
            # start falling.
            self.dy -= dt * GRAVITY
            self.dy = max(self.dy, -TERMINAL_VELOCITY)
            dy += self.dy * dt
        # collisions
        x, y, z = self.position
        x, y, z = self.collide((x + dx, y + dy, z + dz), PLAYER_HEIGHT)
        self.position = (x, y, z)

    def collide(self, position, height):
        """ Checks to see if the player at the given `position` and `height`
        is colliding with any blocks in the world.

        Parameters
        ----------
        position : tuple of len 3
            The (x, y, z) position to check for collisions at.
        height : int or float
            The height of the player.

        Returns
        -------
        position : tuple of len 3
            The new position of the player taking into account collisions.

        """
        # How much overlap with a dimension of a surrounding block you need to
        # have to count as a collision. If 0, touching terrain at all counts as
        # a collision. If .49, you sink into the ground, as if walking through
        # tall grass. If >= .5, you'll fall through the ground.
        pad = 0.25
        p = list(position)
        np = normalize(position)
        for face in FACES:  # check all surrounding blocks
            for i in xrange(3):  # check each dimension independently
                if not face[i]:
                    continue
                # How much overlap you have with this dimension.
                d = (p[i] - np[i]) * face[i]
                if d < pad:
                    continue
                for dy in xrange(height):  # check each height
                    op = list(np)
                    op[1] -= dy
                    op[i] += face[i]
                    if tuple(op) not in self.model.world:
                        continue
                    p[i] -= (d - pad) * face[i]
                    if face == (0, -1, 0) or face == (0, 1, 0):
                        # You are colliding with the ground or ceiling, so stop
                        # falling / rising.
                        self.dy = 0
                    break
        return tuple(p)

    def on_mouse_press(self, x, y, button, modifiers):
        """ Called when a mouse button is pressed. See pyglet docs for button
        amd modifier mappings.

        Parameters
        ----------
        x, y : int
            The coordinates of the mouse click. Always center of the screen if
            the mouse is captured.
        button : int
            Number representing mouse button that was clicked. 1 = left button,
            4 = right button.
        modifiers : int
            Number representing any modifying keys that were pressed when the
            mouse button was clicked.

        """
        if self.exclusive:
            vector = self.get_sight_vector()
            block, previous = self.model.hit_test(self.position, vector)
            if (button == mouse.RIGHT) or \
                    ((button == mouse.LEFT) and (modifiers & key.MOD_CTRL)):
                # ON OSX, control + left click = right click.
                if previous:
                    self.model.add_block(previous, self.block)
            elif button == pyglet.window.mouse.LEFT and block:
                texture = self.model.world[block]
                if texture != STONE:
                    self.model.remove_block(block)
        else:
            self.set_exclusive_mouse(True)

    def on_mouse_motion(self, x, y, dx, dy):
        """ Called when the player moves the mouse.

        Parameters
        ----------
        x, y : int
            The coordinates of the mouse click. Always center of the screen if
            the mouse is captured.
        dx, dy : float
            The movement of the mouse.

        """
        if self.exclusive:
            m = 0.15
            x, y = self.rotation
            x, y = x + dx * m, y + dy * m
            y = max(-90, min(90, y))
            self.rotation = (x, y)

    def on_key_press(self, symbol, modifiers):
        """ Called when the player presses a key. See pyglet docs for key
        mappings.

        Parameters
        ----------
        symbol : int
            Number representing the key that was pressed.
        modifiers : int
            Number representing any modifying keys that were pressed.

        """
        if symbol == key.W:
            self.strafe[0] -= 1
        elif symbol == key.S:
            self.strafe[0] += 1
        elif symbol == key.A:
            self.strafe[1] -= 1
        elif symbol == key.D:
            self.strafe[1] += 1
        elif symbol == key.SPACE:
            if self.dy == 0:
                self.dy = JUMP_SPEED
        elif symbol == key.ESCAPE:
            self.set_exclusive_mouse(False)
        elif symbol == key.TAB:
            self.flying = not self.flying
        elif symbol in self.num_keys:
            index = (symbol - self.num_keys[0]) % len(self.inventory)
            self.block = self.inventory[index]

    def on_key_release(self, symbol, modifiers):
        """ Called when the player releases a key. See pyglet docs for key
        mappings.

        Parameters
        ----------
        symbol : int
            Number representing the key that was pressed.
        modifiers : int
            Number representing any modifying keys that were pressed.

        """
        if symbol == key.W:
            self.strafe[0] += 1
        elif symbol == key.S:
            self.strafe[0] -= 1
        elif symbol == key.A:
            self.strafe[1] += 1
        elif symbol == key.D:
            self.strafe[1] -= 1

    def on_resize(self, width, height):
        """ Called when the window is resized to a new `width` and `height`.

        """
        # label
        self.label.y = height - 10
        # reticle
        if self.reticle:
            self.reticle.delete()
        x, y = self.width // 2, self.height // 2
        n = 10
        self.reticle = pyglet.graphics.vertex_list(4,
            ('v2i', (x - n, y, x + n, y, x, y - n, x, y + n))
        )

    def set_2d(self):
        """ Configure OpenGL to draw in 2d.

        """
        width, height = self.get_size()
        glDisable(GL_DEPTH_TEST)
        viewport = self.get_viewport_size()
        glViewport(0, 0, max(1, viewport[0]), max(1, viewport[1]))
        glMatrixMode(GL_PROJECTION)
        glLoadIdentity()
        glOrtho(0, max(1, width), 0, max(1, height), -1, 1)
        glMatrixMode(GL_MODELVIEW)
        glLoadIdentity()

    def set_3d(self):
        """ Configure OpenGL to draw in 3d.

        """
        width, height = self.get_size()
        glEnable(GL_DEPTH_TEST)
        viewport = self.get_viewport_size()
        glViewport(0, 0, max(1, viewport[0]), max(1, viewport[1]))
        glMatrixMode(GL_PROJECTION)
        glLoadIdentity()
        gluPerspective(65.0, width / float(height), 0.1, 60.0)
        glMatrixMode(GL_MODELVIEW)
        glLoadIdentity()
        x, y = self.rotation
        glRotatef(x, 0, 1, 0)
        glRotatef(-y, math.cos(math.radians(x)), 0, math.sin(math.radians(x)))
        x, y, z = self.position
        glTranslatef(-x, -y, -z)

    def on_draw(self):
        """ Called by pyglet to draw the canvas.

        """
        self.clear()
        self.set_3d()
        glColor3d(1, 1, 1)
        self.model.batch.draw()
        self.draw_focused_block()
        self.set_2d()
        self.draw_label()
        self.draw_reticle()

    def draw_focused_block(self):
        """ Draw black edges around the block that is currently under the
        crosshairs.

        """
        vector = self.get_sight_vector()
        block = self.model.hit_test(self.position, vector)[0]
        if block:
            x, y, z = block
            vertex_data = cube_vertices(x, y, z, 0.51)
            glColor3d(0, 0, 0)
            glPolygonMode(GL_FRONT_AND_BACK, GL_LINE)
            pyglet.graphics.draw(24, GL_QUADS, ('v3f/static', vertex_data))
            glPolygonMode(GL_FRONT_AND_BACK, GL_FILL)

    def draw_label(self):
        """ Draw the label in the top left of the screen.

        """
        x, y, z = self.position
        self.label.text = '%02d (%.2f, %.2f, %.2f) %d / %d' % (
            pyglet.clock.get_fps(), x, y, z,
            len(self.model._shown), len(self.model.world))
        self.label.draw()

    def draw_reticle(self):
        """ Draw the crosshairs in the center of the screen.

        """
        glColor3d(0, 0, 0)
        self.reticle.draw(GL_LINES)


def setup_fog():
    """ Configure the OpenGL fog properties.

    """
    # Enable fog. Fog "blends a fog color with each rasterized pixel fragment's
    # post-texturing color."
    glEnable(GL_FOG)
    # Set the fog color.
    glFogfv(GL_FOG_COLOR, (GLfloat * 4)(0.5, 0.69, 1.0, 1))
    # Say we have no preference between rendering speed and quality.
    glHint(GL_FOG_HINT, GL_DONT_CARE)
    # Specify the equation used to compute the blending factor.
    glFogi(GL_FOG_MODE, GL_LINEAR)
    # How close and far away fog starts and ends. The closer the start and end,
    # the denser the fog in the fog range.
    glFogf(GL_FOG_START, 20.0)
    glFogf(GL_FOG_END, 60.0)


def setup():
    """ Basic OpenGL configuration.

    """
    # Set the color of "clear", i.e. the sky, in rgba.
    glClearColor(0.5, 0.69, 1.0, 1)
    # Enable culling (not rendering) of back-facing facets -- facets that aren't
    # visible to you.
    glEnable(GL_CULL_FACE)
    # Set the texture minification/magnification function to GL_NEAREST (nearest
    # in Manhattan distance) to the specified texture coordinates. GL_NEAREST
    # "is generally faster than GL_LINEAR, but it can produce textured 圖片
    # with sharper edges because the transition between texture elements is not
    # as smooth."
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
    setup_fog()


def main():
    window = Window(width=1800, height=1600, caption='Pyglet', resizable=True)
    # Hide the mouse cursor and prevent the mouse from leaving the window.
    window.set_exclusive_mouse(True)
    setup()
    pyglet.app.run()


if __name__ == '__main__':
    main()



在這里插入圖片描述

# coding: utf-8
'''
公眾號:一行資料,關注領取5T編程資料
'''
import sys
import pygame
import scene
import bullet
import food
import tanks
import home
from pygame.locals import *


# 開始界面顯示
def show_start_interface(screen, width, height):
	tfont = pygame.font.Font('./font/simkai.ttf', width//4)
	cfont = pygame.font.Font('./font/simkai.ttf', width//20)
	title = tfont.render(u'坦克大戰', True, (255, 0, 0))
	content1 = cfont.render(u'按1鍵進入單人游戲', True, (0, 0, 255))
	content2 = cfont.render(u'按2鍵進入雙人人游戲', True, (0, 0, 255))
	trect = title.get_rect()
	trect.midtop = (width/2, height/4)
	crect1 = content1.get_rect()
	crect1.midtop = (width/2, height/1.8)
	crect2 = content2.get_rect()
	crect2.midtop = (width/2, height/1.6)
	screen.blit(title, trect)
	screen.blit(content1, crect1)
	screen.blit(content2, crect2)
	pygame.display.update()
	while True:
		for event in pygame.event.get():
			if event.type == QUIT:
				sys.exit()
			elif event.type == pygame.KEYDOWN:
				if event.key == pygame.K_1:
					return 1
				if event.key == pygame.K_2:
					return 2


# 結束界面顯示
def show_end_interface(screen, width, height, is_win):
	bg_img = pygame.image.load("./圖片/others/background.png")
	screen.blit(bg_img, (0, 0))
	if is_win:
		font = pygame.font.Font('./font/simkai.ttf', width//10)
		content = font.render(u'恭喜通關!', True, (255, 0, 0))
		rect = content.get_rect()
		rect.midtop = (width/2, height/2)
		screen.blit(content, rect)
	else:
		fail_img = pygame.image.load("./圖片/others/gameover.png")
		rect = fail_img.get_rect()
		rect.midtop = (width/2, height/2)
		screen.blit(fail_img, rect)
	pygame.display.update()
	while True:
		for event in pygame.event.get():
			if event.type == QUIT:
				sys.exit()


# 關卡切換
def show_switch_stage(screen, width, height, stage):
	bg_img = pygame.image.load("./圖片/others/background.png")
	screen.blit(bg_img, (0, 0))
	font = pygame.font.Font('./font/simkai.ttf', width//10)
	content = font.render(u'第%d關' % stage, True, (0, 255, 0))
	rect = content.get_rect()
	rect.midtop = (width/2, height/2)
	screen.blit(content, rect)
	pygame.display.update()
	delay_event = pygame.constants.USEREVENT
	pygame.time.set_timer(delay_event, 1000)
	while True:
		for event in pygame.event.get():
			if event.type == QUIT:
				sys.exit()
			if event.type == delay_event:
				return


# 主函式
def main():
	# 初始化
	pygame.init()
	screen = pygame.display.set_mode((630, 630))
	pygame.display.set_caption("坦克大戰")
	# 加載圖片
	bg_img = pygame.image.load("./圖片/others/background.png")
	# 開始界面
	num_player = show_start_interface(screen, 630, 630)
	# 關卡
	stage = 0
	num_stage = 2
	# 游戲是否結束
	is_gameover = False
	# 時鐘
	clock = pygame.time.Clock()
	# 主回圈
	while not is_gameover:
		# 關卡
		stage += 1
		if stage > num_stage:
			break
		show_switch_stage(screen, 630, 630, stage)
		# 該關卡坦克總數量
		enemytanks_total = min(stage * 18, 80)
		# 場上存在的敵方坦克總數量
		enemytanks_now = 0
		# 場上可以存在的敵方坦克總數量
		enemytanks_now_max = min(max(stage * 2, 4), 8)
		# 精靈組
		tanksGroup = pygame.sprite.Group()
		mytanksGroup = pygame.sprite.Group()
		enemytanksGroup = pygame.sprite.Group()
		bulletsGroup = pygame.sprite.Group()
		mybulletsGroup = pygame.sprite.Group()
		enemybulletsGroup = pygame.sprite.Group()
		myfoodsGroup = pygame.sprite.Group()
		# 自定義事件
		# 	-生成敵方坦克事件
		genEnemyEvent = pygame.constants.USEREVENT + 0
		pygame.time.set_timer(genEnemyEvent, 100)
		# 	-敵方坦克靜止恢復事件
		recoverEnemyEvent = pygame.constants.USEREVENT + 1
		pygame.time.set_timer(recoverEnemyEvent, 8000)
		# 	-我方坦克無敵恢復事件
		noprotectMytankEvent = pygame.constants.USEREVENT + 2
		pygame.time.set_timer(noprotectMytankEvent, 8000)
		# 關卡地圖
		map_stage = scene.Map(stage)
		# 我方坦克
		tank_player1 = tanks.myTank(1)
		tanksGroup.add(tank_player1)
		mytanksGroup.add(tank_player1)
		if num_player > 1:
			tank_player2 = tanks.myTank(2)
			tanksGroup.add(tank_player2)
			mytanksGroup.add(tank_player2)
		is_switch_tank = True
		player1_moving = False
		player2_moving = False
		# 為了輪胎的影片效果
		time = 0
		# 敵方坦克
		for i in range(0, 3):
			if enemytanks_total > 0:
				enemytank = tanks.enemyTank(i)
				tanksGroup.add(enemytank)
				enemytanksGroup.add(enemytank)
				enemytanks_now += 1
				enemytanks_total -= 1
		# 大本營
		myhome = home.Home()
		# 出場特效
		appearance_img = pygame.image.load("./圖片/others/appear.png").convert_alpha()
		appearances = []
		appearances.append(appearance_img.subsurface((0, 0), (48, 48)))
		appearances.append(appearance_img.subsurface((48, 0), (48, 48)))
		appearances.append(appearance_img.subsurface((96, 0), (48, 48)))
		# 關卡主回圈
		while True:
			if is_gameover is True:
				break
			if enemytanks_total < 1 and enemytanks_now < 1:
				is_gameover = False
				break
			for event in pygame.event.get():
				if event.type == pygame.QUIT:
					pygame.quit()
					sys.exit()
				if event.type == genEnemyEvent:
					if enemytanks_total > 0:
						if enemytanks_now < enemytanks_now_max:
							enemytank = tanks.enemyTank()
							if not pygame.sprite.spritecollide(enemytank, tanksGroup, False, None):
								tanksGroup.add(enemytank)
								enemytanksGroup.add(enemytank)
								enemytanks_now += 1
								enemytanks_total -= 1
				if event.type == recoverEnemyEvent:
					for each in enemytanksGroup:
						each.can_move = True
				if event.type == noprotectMytankEvent:
					for each in mytanksGroup:
						mytanksGroup.protected = False
			# 檢查用戶鍵盤操作
			key_pressed = pygame.key.get_pressed()
			# 玩家一
			# WSAD -> 上下左右
			# 空格鍵射擊
			if key_pressed[pygame.K_w]:
				tanksGroup.remove(tank_player1)
				tank_player1.move_up(tanksGroup, map_stage.brickGroup, map_stage.ironGroup, myhome)
				tanksGroup.add(tank_player1)
				player1_moving = True
			elif key_pressed[pygame.K_s]:
				tanksGroup.remove(tank_player1)
				tank_player1.move_down(tanksGroup, map_stage.brickGroup, map_stage.ironGroup, myhome)
				tanksGroup.add(tank_player1)
				player1_moving = True
			elif key_pressed[pygame.K_a]:
				tanksGroup.remove(tank_player1)
				tank_player1.move_left(tanksGroup, map_stage.brickGroup, map_stage.ironGroup, myhome)
				tanksGroup.add(tank_player1)
				player1_moving = True
			elif key_pressed[pygame.K_d]:
				tanksGroup.remove(tank_player1)
				tank_player1.move_right(tanksGroup, map_stage.brickGroup, map_stage.ironGroup, myhome)
				tanksGroup.add(tank_player1)
				player1_moving = True
			elif key_pressed[pygame.K_SPACE]:
				if not tank_player1.bullet.being:
					tank_player1.shoot()
			# 玩家二
			# ↑↓←→ -> 上下左右
			# 小鍵盤0鍵射擊
			if num_player > 1:
				if key_pressed[pygame.K_UP]:
					tanksGroup.remove(tank_player2)
					tank_player2.move_up(tanksGroup, map_stage.brickGroup, map_stage.ironGroup, myhome)
					tanksGroup.add(tank_player2)
					player2_moving = True
				elif key_pressed[pygame.K_DOWN]:
					tanksGroup.remove(tank_player2)
					tank_player2.move_down(tanksGroup, map_stage.brickGroup, map_stage.ironGroup, myhome)
					tanksGroup.add(tank_player2)
					player2_moving = True
				elif key_pressed[pygame.K_LEFT]:
					tanksGroup.remove(tank_player2)
					tank_player2.move_left(tanksGroup, map_stage.brickGroup, map_stage.ironGroup, myhome)
					tanksGroup.add(tank_player2)
					player2_moving = True
				elif key_pressed[pygame.K_RIGHT]:
					tanksGroup.remove(tank_player2)
					tank_player2.move_right(tanksGroup, map_stage.brickGroup, map_stage.ironGroup, myhome)
					tanksGroup.add(tank_player2)
					player2_moving = True
				elif key_pressed[pygame.K_KP0]:
					if not tank_player2.bullet.being:
						tank_player2.shoot()
			# 背景
			screen.blit(bg_img, (0, 0))
			# 石頭墻
			for each in map_stage.brickGroup:
				screen.blit(each.brick, each.rect)
			# 鋼墻
			for each in map_stage.ironGroup:
				screen.blit(each.iron, each.rect)
			# 冰
			for each in map_stage.iceGroup:
				screen.blit(each.ice, each.rect)
			# 河流
			for each in map_stage.riverGroup:
				screen.blit(each.river, each.rect)
			# 樹
			for each in map_stage.treeGroup:
				screen.blit(each.tree, each.rect)
			time += 1
			if time == 5:
				time = 0
				is_switch_tank = not is_switch_tank
			# 我方坦克
			if tank_player1 in mytanksGroup:
				if is_switch_tank and player1_moving:
					screen.blit(tank_player1.tank_0, (tank_player1.rect.left, tank_player1.rect.top))
					player1_moving = False
				else:
					screen.blit(tank_player1.tank_1, (tank_player1.rect.left, tank_player1.rect.top))
				if tank_player1.protected:
					screen.blit(tank_player1.protected_mask1, (tank_player1.rect.left, tank_player1.rect.top))
			if num_player > 1:
				if tank_player2 in mytanksGroup:
					if is_switch_tank and player2_moving:
						screen.blit(tank_player2.tank_0, (tank_player2.rect.left, tank_player2.rect.top))
						player1_moving = False
					else:
						screen.blit(tank_player2.tank_1, (tank_player2.rect.left, tank_player2.rect.top))
					if tank_player2.protected:
						screen.blit(tank_player1.protected_mask1, (tank_player2.rect.left, tank_player2.rect.top))
			# 敵方坦克
			for each in enemytanksGroup:
				# 出生特效
				if each.born:
					if each.times > 0:
						each.times -= 1
						if each.times <= 10:
							screen.blit(appearances[2], (3+each.x*12*24, 3))
						elif each.times <= 20:
							screen.blit(appearances[1], (3+each.x*12*24, 3))
						elif each.times <= 30:
							screen.blit(appearances[0], (3+each.x*12*24, 3))
						elif each.times <= 40:
							screen.blit(appearances[2], (3+each.x*12*24, 3))
						elif each.times <= 50:
							screen.blit(appearances[1], (3+each.x*12*24, 3))
						elif each.times <= 60:
							screen.blit(appearances[0], (3+each.x*12*24, 3))
						elif each.times <= 70:
							screen.blit(appearances[2], (3+each.x*12*24, 3))
						elif each.times <= 80:
							screen.blit(appearances[1], (3+each.x*12*24, 3))
						elif each.times <= 90:
							screen.blit(appearances[0], (3+each.x*12*24, 3))
					else:
						each.born = False
				else:
					if is_switch_tank:
						screen.blit(each.tank_0, (each.rect.left, each.rect.top))
					else:
						screen.blit(each.tank_1, (each.rect.left, each.rect.top))
					if each.can_move:
						tanksGroup.remove(each)
						each.move(tanksGroup, map_stage.brickGroup, map_stage.ironGroup, myhome)
						tanksGroup.add(each)
			# 我方子彈
			for tank_player in mytanksGroup:
				if tank_player.bullet.being:
					tank_player.bullet.move()
					screen.blit(tank_player.bullet.bullet, tank_player.bullet.rect)
					# 子彈碰撞敵方子彈
					for each in enemybulletsGroup:
						if each.being:
							if pygame.sprite.collide_rect(tank_player.bullet, each):
								tank_player.bullet.being = False
								each.being = False
								enemybulletsGroup.remove(each)
								break
						else:
							enemybulletsGroup.remove(each)	
					# 子彈碰撞敵方坦克
					for each in enemytanksGroup:
						if each.being:
							if pygame.sprite.collide_rect(tank_player.bullet, each):
								if each.is_red == True:
									myfood = food.Food()
									myfood.generate()
									myfoodsGroup.add(myfood)
									each.is_red = False
								each.blood -= 1
								each.color -= 1
								if each.blood < 0:
									each.being = False
									enemytanksGroup.remove(each)
									enemytanks_now -= 1
									tanksGroup.remove(each)
								else:
									each.reload()
								tank_player.bullet.being = False
								break
						else:
							enemytanksGroup.remove(each)
							tanksGroup.remove(each)
					# 子彈碰撞石頭墻
					if pygame.sprite.spritecollide(tank_player.bullet, map_stage.brickGroup, True, None):
						tank_player.bullet.being = False
					'''
					# 等價方案(更科學點)
					for each in map_stage.brickGroup:
						if pygame.sprite.collide_rect(tank_player.bullet, each):
							tank_player.bullet.being = False
							each.being = False
							map_stage.brickGroup.remove(each)
							break
					'''
					# 子彈碰鋼墻
					if tank_player.bullet.stronger:
						if pygame.sprite.spritecollide(tank_player.bullet, map_stage.ironGroup, True, None):
							tank_player.bullet.being = False
					else:
						if pygame.sprite.spritecollide(tank_player.bullet, map_stage.ironGroup, False, None):
							tank_player.bullet.being = False
					'''
					# 等價方案(更科學點)
					for each in map_stage.ironGroup:
						if pygame.sprite.collide_rect(tank_player.bullet, each):
							tank_player.bullet.being = False
							if tank_player.bullet.stronger:
								each.being = False
								map_stage.ironGroup.remove(each)
							break
					'''
					# 子彈碰大本營
					if pygame.sprite.collide_rect(tank_player.bullet, myhome):
						tank_player.bullet.being = False
						myhome.set_dead()
						is_gameover = True
			# 敵方子彈
			for each in enemytanksGroup:
				if each.being:
					if each.can_move and not each.bullet.being:
						enemybulletsGroup.remove(each.bullet)
						each.shoot()
						enemybulletsGroup.add(each.bullet)
					if not each.born:
						if each.bullet.being:
							each.bullet.move()
							screen.blit(each.bullet.bullet, each.bullet.rect)
							# 子彈碰撞我方坦克
							for tank_player in mytanksGroup:
								if pygame.sprite.collide_rect(each.bullet, tank_player):
									if not tank_player.protected:
										tank_player.life -= 1
										if tank_player.life < 0:
											mytanksGroup.remove(tank_player)
											tanksGroup.remove(tank_player)
											if len(mytanksGroup) < 1:
												is_gameover = True
										else:
											tank_player.reset()
									each.bullet.being = False
									enemybulletsGroup.remove(each.bullet)
									break
							# 子彈碰撞石頭墻
							if pygame.sprite.spritecollide(each.bullet, map_stage.brickGroup, True, None):
								each.bullet.being = False
								enemybulletsGroup.remove(each.bullet)
							'''
							# 等價方案(更科學點)
							for one in map_stage.brickGroup:
								if pygame.sprite.collide_rect(each.bullet, one):
									each.bullet.being = False
									one.being = False
									enemybulletsGroup.remove(one)
									break
							'''
							# 子彈碰鋼墻
							if each.bullet.stronger:
								if pygame.sprite.spritecollide(each.bullet, map_stage.ironGroup, True, None):
									each.bullet.being = False
							else:
								if pygame.sprite.spritecollide(each.bullet, map_stage.ironGroup, False, None):
									each.bullet.being = False
							'''
							# 等價方案(更科學點)
							for one in map_stage.ironGroup:
								if pygame.sprite.collide_rect(each.bullet, one):
									each.bullet.being = False
									if each.bullet.stronger:
										one.being = False
										map_stage.ironGroup.remove(one)
									break
							'''
							# 子彈碰大本營
							if pygame.sprite.collide_rect(each.bullet, myhome):
								each.bullet.being = False
								myhome.set_dead()
								is_gameover = True
				else:
					enemytanksGroup.remove(each)
					tanksGroup.remove(each)
			# 家
			screen.blit(myhome.home, myhome.rect)
			# 食物
			for myfood in myfoodsGroup:
				if myfood.being and myfood.time > 0:
					screen.blit(myfood.food, myfood.rect)
					myfood.time -= 1
					for tank_player in mytanksGroup:
						if pygame.sprite.collide_rect(tank_player, myfood):
							# 消滅當前所有敵人
							if myfood.kind == 0:
								enemytanksGroup = pygame.sprite.Group()
								enemytanks_total -= enemytanks_now
								enemytanks_now = 0
							# 敵人靜止
							if myfood.kind == 1:
								for each in enemytanksGroup:
									each.can_move = False
							# 子彈增強
							if myfood.kind == 2:
								tank_player.bullet.stronger = True
							# 使得大本營的墻變為鋼板
							if myfood.kind == 3:
								map_stage.protect_home()
							# 坦克獲得一段時間的保護罩
							if myfood.kind == 4:
								for tank_player in mytanksGroup:
									tank_player.protected = True
							# 坦克升級
							if myfood.kind == 5:
								tank_player.up_level()
							# 坦克生命+1
							if myfood.kind == 6:
								tank_player.life += 1
							myfood.being = False
							myfoodsGroup.remove(myfood)
							break
				else:
					myfood.being = False
					myfoodsGroup.remove(myfood)
			pygame.display.flip()
			clock.tick(60)
	if not is_gameover:
		show_end_interface(screen, 630, 630, True)
	else:
		show_end_interface(screen, 630, 630, False)


if __name__ == '__main__':
	main()






轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/290886.html

標籤:python

上一篇:python:洗掉串列中重復元素

下一篇:【python】資料分析實戰:分析全國旅游景點資料,暑假還不知道去哪玩的看過來

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • Rust中的智能指標:Box<T> Rc<T> Arc<T> Cell<T> RefCell<T> Weak

    Rust中的智能指標是什么 智能指標(smart pointers)是一類資料結構,是擁有資料所有權和額外功能的指標。是指標的進一步發展 指標(pointer)是一個包含記憶體地址的變數的通用概念。這個地址參考,或 ” 指向”(points at)一些其 他資料 。參考以 & 符號為標志并借用了他們所 ......

    uj5u.com 2023-04-20 07:24:10 more
  • Java的值傳遞和參考傳遞

    值傳遞不會改變本身,參考傳遞(如果傳遞的值需要實體化到堆里)如果發生修改了會改變本身。 1.基本資料型別都是值傳遞 package com.example.basic; public class Test { public static void main(String[] args) { int ......

    uj5u.com 2023-04-20 07:24:04 more
  • [2]SpinalHDL教程——Scala簡單入門

    第一個 Scala 程式 shell里面輸入 $ scala scala> 1 + 1 res0: Int = 2 scala> println("Hello World!") Hello World! 檔案形式 object HelloWorld { /* 這是我的第一個 Scala 程式 * 以 ......

    uj5u.com 2023-04-20 07:23:58 more
  • 理解函式指標和回呼函式

    理解 函式指標 指向函式的指標。比如: 理解函式指標的偽代碼 void (*p)(int type, char *data); // 定義一個函式指標p void func(int type, char *data); // 宣告一個函式func p = func; // 將指標p指向函式func ......

    uj5u.com 2023-04-20 07:23:52 more
  • Django筆記二十五之資料庫函式之日期函式

    本文首發于公眾號:Hunter后端 原文鏈接:Django筆記二十五之資料庫函式之日期函式 日期函式主要介紹兩個大類,Extract() 和 Trunc() Extract() 函式作用是提取日期,比如我們可以提取一個日期欄位的年份,月份,日等資料 Trunc() 的作用則是截取,比如 2022-0 ......

    uj5u.com 2023-04-20 07:23:45 more
  • 一天吃透JVM面試八股文

    什么是JVM? JVM,全稱Java Virtual Machine(Java虛擬機),是通過在實際的計算機上仿真模擬各種計算機功能來實作的。由一套位元組碼指令集、一組暫存器、一個堆疊、一個垃圾回收堆和一個存盤方法域等組成。JVM屏蔽了與作業系統平臺相關的資訊,使得Java程式只需要生成在Java虛擬機 ......

    uj5u.com 2023-04-20 07:23:31 more
  • 使用Java接入小程式訂閱訊息!

    更新完微信服務號的模板訊息之后,我又趕緊把微信小程式的訂閱訊息給實作了!之前我一直以為微信小程式也是要企業才能申請,沒想到小程式個人就能申請。 訊息推送平臺🔥推送下發【郵件】【短信】【微信服務號】【微信小程式】【企業微信】【釘釘】等訊息型別。 https://gitee.com/zhongfuch ......

    uj5u.com 2023-04-20 07:22:59 more
  • java -- 緩沖流、轉換流、序列化流

    緩沖流 緩沖流, 也叫高效流, 按照資料型別分類: 位元組緩沖流:BufferedInputStream,BufferedOutputStream 字符緩沖流:BufferedReader,BufferedWriter 緩沖流的基本原理,是在創建流物件時,會創建一個內置的默認大小的緩沖區陣列,通過緩沖 ......

    uj5u.com 2023-04-20 07:22:49 more
  • Java-SpringBoot-Range請求頭設定實作視頻分段傳輸

    老實說,人太懶了,現在基本都不喜歡寫筆記了,但是網上有關Range請求頭的文章都太水了 下面是抄的一段StackOverflow的代碼...自己大修改過的,寫的注釋挺全的,應該直接看得懂,就不解釋了 寫的不好...只是希望能給視頻網站開發的新手一點點幫助吧. 業務場景:視頻分段傳輸、視頻多段傳輸(理 ......

    uj5u.com 2023-04-20 07:22:42 more
  • Windows 10開發教程_編程入門自學教程_菜鳥教程-免費教程分享

    教程簡介 Windows 10開發入門教程 - 從簡單的步驟了解Windows 10開發,從基本到高級概念,包括簡介,UWP,第一個應用程式,商店,XAML控制元件,資料系結,XAML性能,自適應設計,自適應UI,自適應代碼,檔案管理,SQLite資料庫,應用程式到應用程式通信,應用程式本地化,應用程式 ......

    uj5u.com 2023-04-20 07:22:35 more