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