欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

python机器学习 玩飞行小鸟游戏

程序员文章站 2022-06-25 15:47:55
python机器学习 玩飞行小鸟游戏截图 视频效果代码截图 视频效果 机器学习玩飞行的小鸟游戏 代码#coding:utf-8import randomimport PATHimport cv2from itertools import cycleFPS = 30ScreenWidth = 288ScreenHeight = 512Image = PATH.l...

python机器学习 玩飞行小鸟游戏

截图 视频效果

机器学习玩飞行的小鸟游戏

python机器学习 玩飞行小鸟游戏

代码

#coding:utf-8
import random
import PATH
import cv2
from itertools import cycle

FPS = 30
ScreenWidth  = 288
ScreenHeight = 512

Image = PATH.load()
Screen = Image['background']
PipGapSize = 100 # 管道障碍物中间间隔的长度设置为100
Basey = 400 # 基底线所在的位置

index = random.randint(50, 250) #在gapYs中随机选取
PlayerWidth = Image['player'][0].shape[1]
PlayerHeight = Image['player'][0].shape[0]
PipeWidth = Image['pipe'][0].shape[1]
PipeHeight = Image['pipe'][0].shape[0]
BackgroundHeight = Image['background'].shape[0]

PlayerIndex = cycle([0, 1, 2, 1])

class Bird:
    def __init__(self):
        self.playerx = int(ScreenWidth * 0.2)
        self.playery = int((ScreenHeight - PlayerHeight) / 2)
        self.playerVy = 0
        self.playerMaxVy = 8 # 小鸟最快的下落速度是每帧8格
        self.playerMinVy = -6 # 小鸟最快的上升速度是每帧6格
        self.playerAccY = 1 # 小鸟的下落加速度
        self.playerFlapAcc = -8 #在小鸟扇动翅膀时的速度
        self.playerFlapped = False # 标识符,小鸟扇动翅膀时为True
        self.score = self.playerIndex = self.loopIter = 0
        self.action = [0,0]
        self.reward = 0.1
        self.endpoint = False
        self.screen = None
        self.flag = 0

class GameState:
    def __init__(self):
        self.basex = 0
        self.baseUpline = Image['base'].shape[0] - BackgroundHeight

        newPipe1 = GetPipe()
        self.upPipes = [
            {'x': ScreenWidth, 'y': newPipe1[0]['y']},
        ]
        self.downPipes = [
            {'x': ScreenWidth, 'y': newPipe1[1]['y']},
        ]

        self.pipeVx = -4 # 管道障碍物在x轴方向上的移动速度是每帧4格,向x轴负方向移动。就是向左
        self.interval_n =0 #间隔加速度
        self.interval =40 #间隔
        # self.baseground=None #基础画面
        # self.showground=None #显示画面
        self.score = 0#通用分数
        self.playerx = int(ScreenWidth * 0.2)

    def pipeline(self):
        self.baseground=Screen.copy()
        # 管道障碍物向左移动时候的速度 
        for uPipe, lPipe in zip(self.upPipes, self.downPipes):
            uPipe['x'] += self.pipeVx
            lPipe['x'] += self.pipeVx

        # 生成新的管道
        self.interval_n +=1
        if self.interval_n ==self.interval:
            newPipe = GetPipe()
            self.upPipes.append({'x': ScreenWidth+PipeWidth-1, 'y': newPipe[0]['y']})
            self.downPipes.append({'x': ScreenWidth+PipeWidth-1, 'y': newPipe[1]['y']})
            self.interval_n=0

        # 当旧的管道移动到屏幕最左边的时候,将其从upPips与downPips中删除
        if self.upPipes[0]['x'] <0:
            self.upPipes.pop(0)
            self.downPipes.pop(0)

        #显示管子
        for uPipe, lPipe in zip(self.upPipes, self.downPipes):
            self.baseground[0:uPipe['y']+PipeHeight,uPipe['x']-PipeWidth if uPipe['x']-PipeWidth > 0 else 0: ScreenWidth if uPipe['x']>ScreenWidth else uPipe['x']]=Image['pipe'][0][abs(uPipe['y']):320,PipeWidth-uPipe['x'] if PipeWidth-uPipe['x'] > 0 else 0:ScreenWidth+PipeWidth-uPipe['x'] if ScreenWidth+PipeWidth-uPipe['x']>0 else PipeWidth]
            self.baseground[lPipe['y']:400,lPipe['x']-PipeWidth if lPipe['x']-PipeWidth > 0 else 0:lPipe['x'] if ScreenWidth >ScreenWidth else lPipe['x']]=Image['pipe'][1][0:400-lPipe['y'],PipeWidth-lPipe['x'] if PipeWidth-lPipe['x'] > 0 else 0:ScreenWidth+PipeWidth-lPipe['x'] if ScreenWidth+PipeWidth-lPipe['x']>0 else PipeWidth]
        
        self.showground = self.baseground.copy()

    def frame_step(self, birds):


        self.pipeline()
      
        # 确定分数,在小鸟的x超过管道右边界的x时,获得的分数+1
        if self.upPipes[0]['x'] <self.playerx  < self.upPipes[0]['x'] + 4:
            self.score += 1

        for bird in birds:
            bird.screen =  self.baseground.copy()
            bird.reward = 0.1
            bird.endpoint = False
            # 0:小鸟不做任务事    1:小鸟扇动翅膀
            if bird.action[1] == 1:
                if bird.playery > -2 * PlayerHeight:
                    bird.playerVy = bird.playerFlapAcc
                    bird.playerFlapped = True


            if (bird.loopIter + 1) % 3 == 0:
                bird.playerIndex = next(PlayerIndex)
            bird.loopIter = (bird.loopIter + 1) % 30
            self.basex = -((-self.basex + 100) % self.baseUpline)

            # 小鸟在y轴上的移动方式
            if bird.playerVy < bird.playerMaxVy and not bird.playerFlapped:
                bird.playerVy += bird.playerAccY
            if bird.playerFlapped:
                bird.playerFlapped = False
            bird.playery += min(bird.playerVy, Basey - bird.playery - PlayerHeight)
            if bird.playery < 0:
                bird.playery = 0



            #显示小鸟
            bird.playery = int(bird.playery)
            self.showground[bird.playery:PlayerHeight+bird.playery,bird.playerx:bird.playerx+PlayerWidth]  = addpng(self.showground[bird.playery:PlayerHeight+bird.playery,bird.playerx:bird.playerx+PlayerWidth],Image['player'][bird.playerIndex]) 
            bird.screen[bird.playery:PlayerHeight+bird.playery,bird.playerx:bird.playerx+PlayerWidth]  = addpng(bird.screen[bird.playery:PlayerHeight+bird.playery,bird.playerx:bird.playerx+PlayerWidth],Image['player'][bird.playerIndex]) 


            cv2.imshow(str(bird.flag),bird.screen)

            # 碰撞检测。发生碰撞时结束游戏,并马上开始新一局的游戏
            Crash = CrashHappen({'x': bird.playerx, 'y': bird.playery,
                                'index': bird.playerIndex},
                                self.upPipes, self.downPipes)
            if Crash:
                bird.score = self.score
                bird.endpoint = True
                # self.__init__()
                bird.reward = -1

        self.showground = showScore(self.score,self.showground)
        # 游戏界面的显示
        cv2.imshow("Screen",self.showground)
        cv2.waitKey(10)

        return birds

def addpng(img,png):
    img = cv2.split(img)
    png = cv2.split(png)
    for i in range(3):
        img[i] = img[i]*(255.0  - png[3])/255 + png[i]*(png[3]/255)
    return cv2.merge(img)

def showScore(score,sc):
    scorenum = [int(x) for x in list(str(score))]
    Total = 0

    for num in scorenum:
        Total += Image['numbers'][num].shape[1]

    Xoffset = int((ScreenWidth - Total) / 2)

    for num in scorenum:
        # Screen.blit(Image['numbers'][num], (Xoffset, ScreenHeight * 0.1))
        sc[int(ScreenHeight * 0.1):int(ScreenHeight * 0.1)+Image['numbers'][num].shape[0],Xoffset:Xoffset+Image['numbers'][num].shape[1]]=addpng (sc[int(ScreenHeight * 0.1):int(ScreenHeight * 0.1)+Image['numbers'][num].shape[0],Xoffset:Xoffset+Image['numbers'][num].shape[1]],Image['numbers'][num])
        Xoffset += Image['numbers'][num].shape[1]
    return sc
def GetPipe():
    gapYs = [20, 30, 40, 50, 60, 70, 80, 90] # 管道间隙的上边所在的y轴的值
    index = random.randint(0, len(gapYs)-1) #在gapYs中随机选取
    gapY = gapYs[index]

    gapY += int(Basey * 0.2)
    pipeX = ScreenWidth + 10

    return [
        {'x': pipeX, 'y': gapY - PipeHeight},  # 上管道的起始坐标值
        {'x': pipeX, 'y': gapY + PipGapSize},  # 下管道的起始坐标值
    ]

def CrashHappen(player, upPipes, downPipes):
    pi = player['index']
    player['w'] = Image['player'][0].shape[1]
    player['h'] = Image['player'][0].shape[0]

    # 判断小鸟是否与地面相碰撞
    if player['y'] + player['h'] >= Basey - 1:
        return True
    else:

        for uPipe, lPipe in zip(upPipes, downPipes):
            # 上下管道的矩形位置和长宽数据
            if uPipe['x']-PipeWidth < player['x']+PlayerWidth/4*3 and player['x']+PlayerWidth/4<uPipe['x']:
                if player['y']+PlayerHeight/4 <uPipe['y']+PipeHeight or lPipe['y'] <player['y'] +PlayerHeight/4*3:
                    return True

    return False

if __name__ == '__main__':
    game = GameState()
    birds = []
    for i in range(1):
       birds.append(Bird())

    for _ in range(100):
        birds[0].action[1]=1

        birds = game.frame_step(birds)

本文地址:https://blog.csdn.net/qq_26696715/article/details/108576552