阅读 192

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

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

续上篇,上篇实现了点到点的智能追踪系统,这篇将实现图片到目标点的智能追踪。

还是参照上篇的代码,将追踪点修改为图片,实现一个版本。

文章目录

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

(一)核心代码

(二)完整代码

(三)效果显示

二、失败原因分析

三、修订版本

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

1、核心代码

2、完整代码

3、运行效果

(二)矫正图形的位置

1、核心代码

2、完整代码

3、运行效果

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

(一)核心代码块

(二)增加碰撞检测

(三)完整代码

五、趣味性的小游戏

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

1、BALL类

2、初始化BALL类

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

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

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

6、完整代码

7、运行效果

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

9、优化后的运行效果

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

1、让plane呈现不同的颜色

2、完整代码

3、运行效果

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

(一)核心代码

增加plane的对象:


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

1

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


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

1

(二)完整代码

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

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

(三)效果显示


可以发现,有两个问题。


二、失败原因分析

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)))

1

2

3

4

5

6

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()

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

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])))

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

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()

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

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])))

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

(二)增加碰撞检测

碰撞了返回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

1

2

3

4

5

6

(三)完整代码

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

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

五、趣味性的小游戏

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

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


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)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

2、初始化BALL类

myball = Ball(800, 700, screen)

1

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

myball.move()

myball.draw_ball()

1

2

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

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

1

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

if T:

    myball.reset()

1

2

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()

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

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()

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

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)

1

2

3

4

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()

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

3、运行效果



感谢各位的阅读,比心!

————————————————

版权声明:本文为CSDN博主「dhjabc_1」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/dhjabc_1/article/details/116650392


文章分类
后端
文章标签
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐