飞道的博客

pygame教你从0到1一步步实现点到点的智能追踪系统(其三)

222人阅读  评论(0)

更强大的智能追踪系统。

涉及到运动小球和追踪飞机

为了更通用,更好管理,所以把小球和飞机都聚化为类。

一、运动小球类

from random import randint
import pygame

class Ball:

    def __init__(self, width,height,screen):
        self.scrnwidth = width
        self.scrnheight = height
        self.screen = screen
        self.reset()
        self.color = (randint(0,255),randint(0,255),randint(0,255))

    def draw_ball(self):
        pygame.draw.circle(self.screen, self.color, (self.xpos, self.ypos), self.radius)

    def reset(self):
        self.radius = randint(2, 10)
        self.xpos = randint(self.radius, int(self.scrnwidth)-self.radius)
        self.ypos = randint(self.radius, int(self.scrnheight)-self.radius)
        self.xvelocity = randint(1, 2)
        self.yvelocity = randint(1, 2)
        self.color = (randint(0,255),randint(0,255),randint(0,255))

    def move(self):
        # 进行相应的移动,如果坐标超过屏幕边缘则向相反方向移动
        # 让球的x坐标和y坐标,按照向量的大小进行增加,表示球的运行,向下和向右

        self.xpos += self.xvelocity
        self.ypos += self.yvelocity

        # 如果球的y坐标大于等于屏幕高度和球的半径的差,则调整球的运行y轴方向朝上
        if self.ypos >= self.scrnheight - self.radius:
            self.yvelocity = -self.yvelocity

        # 如果球的y坐标小于等于屏幕高度和球的半径的差,则调整球的y轴运行方向朝下
        if self.ypos <= self.radius:
            self.yvelocity = abs(self.yvelocity)

        # 如果球的x坐标大于等于屏幕宽度和球的半径差,则调整球的运行x轴方向朝左
        if self.xpos >= self.scrnwidth - self.radius:
            self.xvelocity = -self.xvelocity

        # 如果球的x坐标小于等于屏幕宽度和球半径的差,则调整球的运行x轴方向朝右
        if self.xpos <= self.radius:
            self.xvelocity = abs(self.xvelocity)

二、追踪飞机类

class Plane:
    def __init__(self,xpos,ypos,velocity,screen,ball,xpos_small,ypos_small,colors=None):
        self.plane = pygame.image.load('plane.png').convert_alpha()
        self.plane.fill((random.randint(0,255), random.randint(0,255), random.randint(0,255), random.randint(0,255)), special_flags=pygame.BLEND_ADD)
        self.plane_small = pygame.transform.scale(self.plane,(35,35))
        self.height = self.plane.get_height()
        self.width = self.plane.get_width()
        self.velocity = velocity
        self.ball = ball
        self.angel = None
        self.xpos = xpos
        self.ypos = ypos
        self.screen = screen
        self.score = 0
        self.xpos_small = xpos_small
        self.ypos_small = ypos_small
        self.font = pygame.font.Font(r'C:\Windows\Fonts\simsun.ttc', 16)

    def move(self):
        if self.ball is None:
            return
        self.velocity += 0.001
        # print(self.ball.xpos,self.ball.ypos)
        distance = sqrt(pow(self.xpos - self.ball.xpos, 2) + pow(self.ypos - self.ball.ypos, 2))
        section = self.velocity  # 每个时间片需要移动的距离
        sina = (self.ypos - self.ball.ypos) / distance
        cosa = (self.ball.xpos - self.xpos) / distance
        self.angle = atan2(self.ball.ypos-self.ypos, self.ball.xpos-self.xpos)  # 两点间线段的弧度值
        fangle = degrees(self.angle)  # 弧度转角度
        self.xpos, self.ypos = (self.xpos + section * cosa, self.ypos - section * sina)
        self.planed = pygame.transform.rotate(self.plane, -(fangle))
        if 0 <= -fangle <= 90:
            A = (self.width * cosa + self.xpos - self.width, self.ypos - self.height / 2)
            B = (A[0] + self.height * sina, A[1] + self.height * cosa)
        if 90 < -fangle <= 180:
            A = (self.xpos - self.width, self.ypos - self.height / 2 + self.height * (-cosa))
            B = (self.xpos - self.width + self.height * sina, self.ypos - self.height / 2)
        if -90 <= -fangle < 0:
            A = (self.xpos - self.width + self.planed.get_width(), self.ypos - self.height / 2 + self.planed.get_height() - self.height * cosa)
            B = (A[0] + self.height * sina, self.ypos - self.height / 2 + self.planed.get_height())
        if -180 < -fangle < -90:
            A = (self.xpos - self.width - self.height * sina, self.ypos - self.height / 2 + self.planed.get_height())
            B = (self.xpos - self.width, A[1] + self.height * cosa)
        C = ((A[0] + B[0]) / 2, (A[1] + B[1]) / 2)
        self.screen.blit(self.planed, (self.xpos - self.width + (self.xpos - C[0]), self.ypos - self.height / 2 + (self.ypos - C[1])))
        self.screen.blit(self.plane_small, (self.xpos_small,self.ypos_small))
        text1 = self.font.render(str(self.score), True, (255, 255, 0))
        screen.blit(text1, (self.xpos_small+45, self.ypos_small+15))

    def compose(self):
        # 碰撞检测
        if abs(self.xpos - self.ball.xpos) < 5 and abs(self.ypos - self.ball.ypos) < 5:
            self.score += 1
            # print(x - x1, y - y1)
            return True
        else:
            return False

    def setBall(self,ball):
        self.ball = ball

    def reset(self):
        self.velocity = 0.8+random.randint(100,1000)/1000

三、主程序

1、初始化相关参数

    pygame.init()
    screen = pygame.display.set_mode((800, 700))
    velocity = 0.8  # 导弹速度
    x1, y1 = 100, 600  # 导弹的初始发射位置
    x, y = 500, 200  # 目标位置
    x2 = 300
    y2 = 200
    x3 = 100
    y3 = 350

2、初始化运动小球和飞机

    myballs = []
    i = random.randint(3,5)
    j = 0
    while j<i:
        myballs.append(Ball(random.randint(100, 800), random.randint(100, 700), screen))
        j += 1

    plane = Plane(x1,y1,velocity,screen,None,20,20)
    plane1 = Plane(x2,y2,velocity,screen,None,80,20)
    plane2 = Plane(x3,y3,velocity,screen,None,140,20)

    plane_list = []
    plane_list.append(plane)
    plane_list.append(plane1)
    plane_list.append(plane2)

3、初始化飞机锁定的小球

    for plan in plane_list:
        plan.setBall(random.choice(myballs))

4、不断循环

    clock = pygame.time.Clock()
    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
        clock.tick(200)
        screen.fill((0, 0, 0))
        
		# 主体业务逻辑

        pygame.display.update()

5、增加小球运动代码

for myball in myballs:
    myball.move()
    myball.draw_ball()

6、增加飞机运动代码

for plan in plane_list:
    plan.move()

7、碰撞检测及相关处理事件

for plan in plane_list:
    if plan.compose():
        plan.ball.reset()
        plan.reset()
        plan.setBall(random.choice(myballs))

8、完整的主程序

if __name__ == '__main__':
    pygame.init()
    screen = pygame.display.set_mode((800, 700))
    velocity = 0.8  # 导弹速度
    x1, y1 = 100, 600  # 导弹的初始发射位置
    x, y = 500, 200  # 目标位置
    x2 = 300
    y2 = 200
    x3 = 100
    y3 = 350

    myballs = []
    i = random.randint(3,5)
    j = 0
    while j<i:
        myballs.append(Ball(random.randint(100, 800), random.randint(100, 700), screen))
        j += 1

    plane = Plane(x1,y1,velocity,screen,None,20,20)
    plane1 = Plane(x2,y2,velocity,screen,None,80,20)
    plane2 = Plane(x3,y3,velocity,screen,None,140,20)

    plane_list = []
    plane_list.append(plane)
    plane_list.append(plane1)
    plane_list.append(plane2)

    for plan in plane_list:
        plan.setBall(random.choice(myballs))

    clock = pygame.time.Clock()
    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
        clock.tick(200)
        screen.fill((0, 0, 0))
        for myball in myballs:
            myball.move()
            myball.draw_ball()
        for plan in plane_list:
            # plan.setBall(random.choice(myballs))
            plan.move()
        # plane.move()
        # plane1.move()
        # velocity += 0.001
        for plan in plane_list:
            if plan.compose():
                plan.ball.reset()
                plan.reset()
                plan.setBall(random.choice(myballs))
                # for plan1 in plane_list:
                #     plan1.reset()
        #     velocity = 0.8
        pygame.display.update()

四、运行效果


好吧,今天的代码量不大,而且相对来说已经越来越简洁、都已经封装好了,使用起来只需要做函数调用,而无需知晓具体的实现细节。

好吧,写完,码字不易,请持续关注。比心


转载:https://blog.csdn.net/dhjabc_1/article/details/116713065
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场