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

续上篇,上篇实现了点到点的智能追踪系统,这篇将实现图片到目标点的智能追踪。
还是参照上篇的代码,将追踪点修改为图片,实现一个版本。

一、失败的图片到目标点版本

(一)核心代码

增加plane的对象:

plane = pygame.image.load('plane.png').convert_alpha()

在循环过程中blit图形到界面上显示:

screen.blit(plane,  (int(x1), int(y1)))

(二)完整代码

import pygame,sys
from math import *
pygame.init()
screen=pygame.display.set_mode((800,700))
plane = pygame.image.load('plane.png').convert_alpha()
x1,y1=100,600           #导弹的初始发射位置
x,y =500,200            #目标位置
velocity=0.8            #导弹速度
clock=pygame.time.Clock()
while True:
    x, y = pygame.mouse.get_pos()  # 获取鼠标位置,鼠标就是需要打击的目标
    for event in pygame.event.get():
        if event.type==pygame.QUIT:
            pygame.quit()
            sys.exit()
    clock.tick(300)
    distance=sqrt(pow(x1-x,2)+pow(y1-y,2))      #两点距离公式
    section=velocity               #每个时间片需要移动的距离
    sina=(y1-y)/distance
    cosa=(x-x1)/distance
    angle=atan2(y-y1,x-x1)              #两点线段的弧度值
    x1,y1=(x1+section*cosa,y1-section*sina)
    screen.fill((0,0,0))
    screen.blit(plane,  (int(x1), int(y1)))
    # pygame.draw.circle(screen, (255, 0, 0), (int(x1), int(y1)), 10)
    pygame.draw.circle(screen, (0, 0, 255), (x,y), 10)
    pygame.display.update()

(三)效果显示

在这里插入图片描述
可以发现,有两个问题。

二、失败原因分析

1、图片在运行过程中,不会旋转角度,让机头跟随鼠标运动。
2、图片框的中心点位置不对,需要做矫正。

三、修订版本

(一)让图片跟随鼠标运动旋转

1、核心代码

    angle=atan2(y-y1,x-x1)            #两点线段的弧度值
    angle = atan2(y - y1, x - x1)  # 两点间线段的弧度值
    fangle = degrees(angle)  # 弧度转角度
    x1,y1=(x1+section*cosa,y1-section*sina)
    planed = pygame.transform.rotate(plane, -(fangle))
    screen.blit(planed,  (int(x1), int(y1)))

2、完整代码

import pygame,sys
from math import *
pygame.init()
screen=pygame.display.set_mode((800,700))
plane = pygame.image.load('plane.png').convert_alpha()
x1,y1=100,600           #导弹的初始发射位置
x,y =500,200            #目标位置
velocity=0.8            #导弹速度
clock=pygame.time.Clock()
while True:
    x, y = pygame.mouse.get_pos()  # 获取鼠标位置,鼠标就是需要打击的目标
    for event in pygame.event.get():
        if event.type==pygame.QUIT:
            pygame.quit()
            sys.exit()
    clock.tick(300)
    distance=sqrt(pow(x1-x,2)+pow(y1-y,2))      #两点距离公式
    section=velocity               #每个时间片需要移动的距离
    sina=(y1-y)/distance
    cosa=(x-x1)/distance
    angle=atan2(y-y1,x-x1)            #两点线段的弧度值
    angle = atan2(y - y1, x - x1)  # 两点间线段的弧度值
    fangle = degrees(angle)  # 弧度转角度
    x1,y1=(x1+section*cosa,y1-section*sina)
    planed = pygame.transform.rotate(plane, -(fangle))
    screen.fill((0,0,0))
    screen.blit(planed,  (int(x1), int(y1)))
    # pygame.draw.circle(screen, (255, 0, 0), (int(x1), int(y1)), 10)
    pygame.draw.circle(screen, (0, 0, 255), (x,y), 10)
    pygame.display.update()

3、运行效果

在这里插入图片描述

(二)矫正图形的位置

1、核心代码

height = plane.get_height()
width = plane.get_width()

if 0 <= -fangle <= 90:
    A = (width * cosa + x1 - width, y1 - height / 2)
    B = (A[0] + height * sina, A[1] + height * cosa)
if 90 < -fangle <= 180:
    A = (x1 - width, y1 - height / 2 + height * (-cosa))
    B = (x1 - width + height * sina, y1 - height / 2)
if -90 <= -fangle < 0:
    A = (x1 - width + planed.get_width(), y1 - height / 2 + planed.get_height() - height * cosa)
    B = (A[0] + height * sina, y1 - height / 2 + planed.get_height())
if -180 < -fangle < -90:
    A = (x1 - width - height * sina, y1 - height / 2 + planed.get_height())
    B = (x1 - width, A[1] + height * cosa)
C = ((A[0] + B[0]) / 2, (A[1] + B[1]) / 2)
screen.blit(planed, (x1 - width + (x1 - C[0]), y1 - height / 2 + (y1 - C[1])))

2、完整代码

import pygame,sys
from math import *
pygame.init()
screen=pygame.display.set_mode((800,700))
plane = pygame.image.load('plane.png').convert_alpha()
x1,y1=100,600           #导弹的初始发射位置
x,y =500,200            #目标位置
velocity=0.8            #导弹速度
clock=pygame.time.Clock()
height = plane.get_height()
width = plane.get_width()
while True:
    x, y = pygame.mouse.get_pos()  # 获取鼠标位置,鼠标就是需要打击的目标
    for event in pygame.event.get():
        if event.type==pygame.QUIT:
            pygame.quit()
            sys.exit()
    clock.tick(300)
    distance=sqrt(pow(x1-x,2)+pow(y1-y,2))      #两点距离公式
    section=velocity               #每个时间片需要移动的距离
    sina=(y1-y)/distance
    cosa=(x-x1)/distance
    angle=atan2(y-y1,x-x1)            #两点线段的弧度值
    angle = atan2(y - y1, x - x1)  # 两点间线段的弧度值
    fangle = degrees(angle)  # 弧度转角度
    x1,y1=(x1+section*cosa,y1-section*sina)
    planed = pygame.transform.rotate(plane, -(fangle))
    screen.fill((0,0,0))
    if 0 <= -fangle <= 90:
        A = (width * cosa + x1 - width, y1 - height / 2)
        B = (A[0] + height * sina, A[1] + height * cosa)

    if 90 < -fangle <= 180:
        A = (x1 - width, y1 - height / 2 + height * (-cosa))
        B = (x1 - width + height * sina, y1 - height / 2)

    if -90 <= -fangle < 0:
        A = (x1 - width + planed.get_width(), y1 - height / 2 + planed.get_height() - height * cosa)
        B = (A[0] + height * sina, y1 - height / 2 + planed.get_height())

    if -180 < -fangle < -90:
        A = (x1 - width - height * sina, y1 - height / 2 + planed.get_height())
        B = (x1 - width, A[1] + height * cosa)

    C = ((A[0] + B[0]) / 2, (A[1] + B[1]) / 2)

    screen.blit(planed, (x1 - width + (x1 - C[0]), y1 - height / 2 + (y1 - C[1])))
    # screen.blit(planed,  (int(x1), int(y1)))
    # pygame.draw.circle(screen, (255, 0, 0), (int(x1), int(y1)), 10)
    pygame.draw.circle(screen, (0, 0, 255), (x,y), 10)
    pygame.display.update()

3、运行效果

在这里插入图片描述
大致的雏形已经出来了,后续是完善代码成函数和类,并增加更多趣味性的内容了。

四、核心代码块封装成函数

(一)核心代码块

def move(x,y,plane,x1,y1,velocity):
    height = plane.get_height()
    width = plane.get_width()
    distance = sqrt(pow(x1 - x, 2) + pow(y1 - y, 2))  # 两点距离公式
    section = velocity  # 每个时间片需要移动的距离
    sina = (y1 - y) / distance
    cosa = (x - x1) / distance
    angle = atan2(y - y1, x - x1)  # 两点间线段的弧度值
    fangle = degrees(angle)  # 弧度转角度
    x1, y1 = (x1 + section * cosa, y1 - section * sina)
    planed = pygame.transform.rotate(plane, -(fangle))
    if 0 <= -fangle <= 90:
        A = (width * cosa + x1 - width, y1 - height / 2)
        B = (A[0] + height * sina, A[1] + height * cosa)
    if 90 < -fangle <= 180:
        A = (x1 - width, y1 - height / 2 + height * (-cosa))
        B = (x1 - width + height * sina, y1 - height / 2)
    if -90 <= -fangle < 0:
        A = (x1 - width + planed.get_width(), y1 - height / 2 + planed.get_height() - height * cosa)
        B = (A[0] + height * sina, y1 - height / 2 + planed.get_height())
    if -180 < -fangle < -90:
        A = (x1 - width - height * sina, y1 - height / 2 + planed.get_height())
        B = (x1 - width, A[1] + height * cosa)
    C = ((A[0] + B[0]) / 2, (A[1] + B[1]) / 2)
    screen.blit(planed, (x1 - width + (x1 - C[0]), y1 - height / 2 + (y1 - C[1])))

(二)增加碰撞检测

碰撞了返回True,否则返回False

# 碰撞检测
if abs(x-x1)<5 and abs(y - y1)<5:
    print(x - x1, y - y1)
    return True,x1,y1
else:
    return False,x1,y1

(三)完整代码

import pygame,sys
from math import *

def move(x,y,plane,x1,y1,velocity):
    height = plane.get_height()
    width = plane.get_width()
    distance = sqrt(pow(x1 - x, 2) + pow(y1 - y, 2))  # 两点距离公式
    section = velocity  # 每个时间片需要移动的距离
    sina = (y1 - y) / distance
    cosa = (x - x1) / distance
    angle = atan2(y - y1, x - x1)  # 两点间线段的弧度值
    fangle = degrees(angle)  # 弧度转角度
    x1, y1 = (x1 + section * cosa, y1 - section * sina)
    planed = pygame.transform.rotate(plane, -(fangle))
    if 0 <= -fangle <= 90:
        A = (width * cosa + x1 - width, y1 - height / 2)
        B = (A[0] + height * sina, A[1] + height * cosa)
    if 90 < -fangle <= 180:
        A = (x1 - width, y1 - height / 2 + height * (-cosa))
        B = (x1 - width + height * sina, y1 - height / 2)
    if -90 <= -fangle < 0:
        A = (x1 - width + planed.get_width(), y1 - height / 2 + planed.get_height() - height * cosa)
        B = (A[0] + height * sina, y1 - height / 2 + planed.get_height())
    if -180 < -fangle < -90:
        A = (x1 - width - height * sina, y1 - height / 2 + planed.get_height())
        B = (x1 - width, A[1] + height * cosa)
    C = ((A[0] + B[0]) / 2, (A[1] + B[1]) / 2)
    screen.blit(planed, (x1 - width + (x1 - C[0]), y1 - height / 2 + (y1 - C[1])))
    # 碰撞检测
    if abs(x-x1)<5 and abs(y - y1)<5:
        print(x - x1, y - y1)
        return True,x1,y1
    else:
        return False,x1,y1

if __name__ == '__main__':
    pygame.init()
    screen = pygame.display.set_mode((800, 700))
    plane = pygame.image.load('plane.png').convert_alpha()
    x1, y1 = 100, 600  # 导弹的初始发射位置
    x, y = 500, 200  # 目标位置
    velocity = 0.8  # 导弹速度
    clock = pygame.time.Clock()
    while True:
        x, y = pygame.mouse.get_pos()  # 获取鼠标位置,鼠标就是需要打击的目标
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
        clock.tick(300)
        screen.fill((0, 0, 0))
        T, x1, y1 = move(x, y, plane, x1, y1, velocity)
        pygame.draw.circle(screen, (0, 0, 255), (x, y), 10)
        pygame.display.update()

五、趣味性的小游戏

(一)让飞机跟着运动的小球跑

让飞机跟着运动的小球跑,然后碰撞了就重新更新小球的位置,持续动起来

1、BALL类

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)

2、初始化BALL类

myball = Ball(800, 700, screen)

3、让BALL运动起来并画在画布上

myball.move()
myball.draw_ball()

4、让飞机跟随运动小球追踪

T, x1, y1 = move(myball.xpos, myball.ypos, plane, x1, y1, velocity)

5、碰撞监测,碰撞后重置小球

if T:
    myball.reset()

6、完整代码

import pygame,sys
from math import *
from Ball import Ball

def move(x,y,plane,x1,y1,velocity):
    height = plane.get_height()
    width = plane.get_width()
    distance = sqrt(pow(x1 - x, 2) + pow(y1 - y, 2))  # 两点距离公式
    section = velocity  # 每个时间片需要移动的距离
    sina = (y1 - y) / distance
    cosa = (x - x1) / distance
    angle = atan2(y - y1, x - x1)  # 两点间线段的弧度值
    fangle = degrees(angle)  # 弧度转角度
    x1, y1 = (x1 + section * cosa, y1 - section * sina)
    planed = pygame.transform.rotate(plane, -(fangle))
    if 0 <= -fangle <= 90:
        A = (width * cosa + x1 - width, y1 - height / 2)
        B = (A[0] + height * sina, A[1] + height * cosa)
    if 90 < -fangle <= 180:
        A = (x1 - width, y1 - height / 2 + height * (-cosa))
        B = (x1 - width + height * sina, y1 - height / 2)
    if -90 <= -fangle < 0:
        A = (x1 - width + planed.get_width(), y1 - height / 2 + planed.get_height() - height * cosa)
        B = (A[0] + height * sina, y1 - height / 2 + planed.get_height())
    if -180 < -fangle < -90:
        A = (x1 - width - height * sina, y1 - height / 2 + planed.get_height())
        B = (x1 - width, A[1] + height * cosa)
    C = ((A[0] + B[0]) / 2, (A[1] + B[1]) / 2)
    screen.blit(planed, (x1 - width + (x1 - C[0]), y1 - height / 2 + (y1 - C[1])))

    # 碰撞检测
    if abs(x-x1)<5 and abs(y - y1)<5:
        print(x - x1, y - y1)
        return True,x1,y1
    else:
        return False,x1,y1

if __name__ == '__main__':
    pygame.init()
    screen = pygame.display.set_mode((800, 700))
    plane = pygame.image.load('plane.png').convert_alpha()
    x1, y1 = 100, 600  # 导弹的初始发射位置
    x, y = 500, 200  # 目标位置
    velocity = 0.8  # 导弹速度
    myball = Ball(800, 700, screen)
    clock = pygame.time.Clock()
    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
        clock.tick(300)
        screen.fill((0, 0, 0))
        myball.move()
        myball.draw_ball()
        T, x1, y1 = move(myball.xpos, myball.ypos, plane, x1, y1, velocity)
        if T:
            myball.reset()
        # pygame.draw.circle(screen, (0, 0, 255), (x, y), 10)
        pygame.display.update()

7、运行效果

在这里插入图片描述

8、解决飞机追不上小球的问题

核心代码如下:

    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
        clock.tick(300)
        screen.fill((0, 0, 0))
        myball.move()
        myball.draw_ball()
        T, x1, y1 = move(myball.xpos, myball.ypos, plane, x1, y1, velocity)
        velocity += 0.001
        if T:
            myball.reset()
            velocity = 0.8
        # pygame.draw.circle(screen, (0, 0, 255), (x, y), 10)
        pygame.display.update()

9、优化后的运行效果

在这里插入图片描述

(二)让多个飞机争抢运动小球

1、让plane呈现不同的颜色

plane = pygame.image.load('hero.png').convert_alpha()
plane.fill((0,0,250,10),special_flags = pygame.BLEND_ADD)
plane1 = pygame.image.load('hero.png').convert_alpha()
plane1.fill((250,0,250,10),special_flags = pygame.BLEND_ADD)

2、完整代码

import pygame,sys
from math import *
from Ball import Ball
import random

def move(x,y,plane,x1,y1,velocity):
    height = plane.get_height()
    width = plane.get_width()
    distance = sqrt(pow(x1 - x, 2) + pow(y1 - y, 2))  # 两点距离公式
    section = velocity  # 每个时间片需要移动的距离
    sina = (y1 - y) / distance
    cosa = (x - x1) / distance
    angle = atan2(y - y1, x - x1)  # 两点间线段的弧度值
    fangle = degrees(angle)  # 弧度转角度
    x1, y1 = (x1 + section * cosa, y1 - section * sina)
    planed = pygame.transform.rotate(plane, -(fangle))
    if 0 <= -fangle <= 90:
        A = (width * cosa + x1 - width, y1 - height / 2)
        B = (A[0] + height * sina, A[1] + height * cosa)
    if 90 < -fangle <= 180:
        A = (x1 - width, y1 - height / 2 + height * (-cosa))
        B = (x1 - width + height * sina, y1 - height / 2)
    if -90 <= -fangle < 0:
        A = (x1 - width + planed.get_width(), y1 - height / 2 + planed.get_height() - height * cosa)
        B = (A[0] + height * sina, y1 - height / 2 + planed.get_height())
    if -180 < -fangle < -90:
        A = (x1 - width - height * sina, y1 - height / 2 + planed.get_height())
        B = (x1 - width, A[1] + height * cosa)
    C = ((A[0] + B[0]) / 2, (A[1] + B[1]) / 2)
    screen.blit(planed, (x1 - width + (x1 - C[0]), y1 - height / 2 + (y1 - C[1])))

    # 碰撞检测
    if abs(x-x1)<5 and abs(y - y1)<5:
        print(x - x1, y - y1)
        return True,x1,y1
    else:
        return False,x1,y1

if __name__ == '__main__':
    pygame.init()
    screen = pygame.display.set_mode((800, 700))
    plane = pygame.image.load('plane.png').convert_alpha()
    plane.fill((0, 0, 250, 10), special_flags=pygame.BLEND_ADD)
    plane1 = pygame.image.load('plane.png').convert_alpha()
    plane1.fill((250, 0, 250, 10), special_flags=pygame.BLEND_ADD)
    x1, y1 = 100, 600  # 导弹的初始发射位置
    x, y = 500, 200  # 目标位置
    x2 = 300
    y2 = 200
    flag = random.randint(200, 300)/1000
    velocity = 0.8  # 导弹速度
    myball = Ball(800, 700, screen)
    clock = pygame.time.Clock()
    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
        clock.tick(300)
        screen.fill((0, 0, 0))
        myball.move()
        myball.draw_ball()
        T, x1, y1 = move(myball.xpos, myball.ypos, plane, x1, y1, velocity)
        # T, x1, y1 = move(myball.xpos, myball.ypos, plane, x1, y1, velocity)
        _, x2, y2 = move(myball.xpos, myball.ypos, plane1, x2, y2, velocity - flag)
        velocity += 0.001
        if T:
            myball.reset()
            velocity = 0.8
        # pygame.draw.circle(screen, (0, 0, 255), (x, y), 10)
        pygame.display.update()

3、运行效果

在这里插入图片描述

感谢各位的阅读,比心!

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值