吉安市网站建设_网站建设公司_展示型网站_seo优化
2026/1/14 5:25:36 网站建设 项目流程

继续练手我的塔防小游戏,开发过程中用到了子弹弹道计算(一条简单的射线啦,没有考虑真实的抛物线巴拉巴拉的),结合游戏路径生成算法,就自己手搓了一个,还不错挺好用,废话不多说直接上原码诸君自便:

#!D:/Python/Python310 python
"""通过给定的屏幕rect大小和给定的两个点point_xy,point_xiyi计算弹道,生成穿越\
屏幕的路径坐标列表,当作为主程序运行时,测试鼠标点击下的任意两点的弹道生成"""
from math import *
import pygame,sys

def amo_way(wnd_rect,point_xy,point_xiyi):
sub_list=[] #两点之间的坐标子列表
x=point_xy[0]
y=point_xy[1]
xi=point_xiyi[0]
yi=point_xiyi[1]
#依据dy,dx预测屏幕边缘的终点坐标作为新的xi,yi(y=mx+d)
dx=xi-x
dy=yi-y
if dx!=0: #dx为零会出现除零错误要避免
m=dy/dx
d=y-m*x

if xi>x: #当进行X正迭代时
for xi in range(xi,wnd_rect.width):
yi=m*xi+d
#当xi迭代到终点时yi未必会到达边界(即符合下一句条件if yi<=1 or yi>=wnd_rect.height)所以要在此提前取整,迭代完毕后即可得到yi整数结果
yi=round(yi)
if yi<=1 or yi>=wnd_rect.height:
break
elif xi<x: #当进行X负迭代时
for xi in range(xi,0,-1):
yi=m*xi+d
#当xi迭代到终点时yi未必会到达边界(即符合下一句条件if yi<=1 or yi>=wnd_rect.height)所以要在此提前取整,迭代完毕后即可得到yi整数结果
yi=round(yi)
if yi<=1 or yi>=wnd_rect.height:
break
elif xi==x:#当是一条90度的垂直线时
if yi>y:yi=wnd_rect.height
else: yi=0

#通过新的xi,yi 计算弹道
#print(xi,yi) #test usesing
dx=abs(xi-x)
dy=abs(yi-y)
s1=1 if xi>x else -1 #依据起点与终点坐标值大小进行x方向的步进值设置
s2=1 if yi>y else -1 #依据起点与终点坐标值大小进行y方向的步进值设置
interchange=0
if(dy>dx): #当线条的斜率大于1时(对Y方向做步进)交换dx与dy 则X=my+d
dx=dx^dy #不用中间变量交换两个值(C++实验有序二叉树),
#A=a,B=b,通过a^b给A 再通过A^b得到a=>B,再通过A^a得到a=>A
dy=dx^dy
dx=dx^dy
interchange=1 #表示斜率大于1,此时做Y方向的递增推导即对Y迭代Y+=1
else:interchange=0
p=2*dy-dx #初始化决策参数P0项
for i in range(1,dx+1):
sub_list.append((x,y))
if(p>=0):#表示DOWN>UP Y/X取真坐标值的向上取整坐标的点
if interchange==0:#当进行X方向递推时
y+=s2 #当斜率小于1时做X方向的递推求对应的Y值P>0时Y=Y+1
else: x+=s1 #当斜率大于1时做Y方向的递推求对应的X值P>0时X=X+1

p-=2*dx #决策参数的递推公式公式当P(i)>=0时由公式:P(i+1)=Pi+2dy-2dx[Y(i+1)-Yi]
#可知此处(Y(i+1)-Y(i))==1即P(i+1)=Pi+2dy-2dx(此处是后半部分表达式)

if interchange==0: #当interchange==0时表示进行X递增
x+=s1 #
else: y+=s2 #当interchange==1时表示进行Y的递增
p+=2*dy #当P(i)<0时Y(i+1)-Y(i)==0此处有P(i+1)=Pi+2dy(此处是部分表达式前半部分,当P>0时与上式拼接)
#print(sub_list) #test usering
return sub_list

def mak_amo_way(wnd_rect,point_xy,point_xiyi):
"""该函数通过给定起点坐标和终点坐标,在指定的矩形中生成一个射线"""
way_list=[] #两点之间的坐标子列表
pos_list=amo_way(wnd_rect,point_xy,point_xiyi)#pos_list为一个暂存变量
way_list=pos_list[0::10]+[pos_list[-1]] #必须包含第一个点加最后一个点

return way_list



def hy_main():
#设置地图的大小及图片文件名称
size_str=input("Input the window size format x,y:")
size_list=size_str.split(',')
wnd_width=int(size_list[0])
wnd_heigh=int(size_list[1])

#定义路径列表
way_point_list=[]
trajectory_list=[]#弹道坐标列表
choose=False #第一次点击鼠标左键时变为True,当为False 时移动鼠标不画线
pygame.init()
#游戏刷新率时间参数的建立
game_clock=pygame.time.Clock()
mainwnd=pygame.display.set_mode((wnd_width,wnd_heigh))
pygame.display.set_caption("amo_way_module")
#主窗口对象填充为白色
mainwnd.fill("black")
wnd_rect=pygame.Rect(0,0,wnd_width,wnd_heigh)


while True:
#游戏刷新率的设置
game_clock.tick(60)

# 循环获取事件,监听事件
for event in pygame.event.get():
# 判断用户是否点了关闭按钮
if event.type == pygame.QUIT:
#卸载所有模块
pygame.quit()
#终止程序
sys.exit()
elif event.type==pygame.MOUSEBUTTONDOWN:
if pygame.mouse.get_pressed()==(1,0,0):#左键按下时开始确定记录第一个点
if choose==False:
pos_xy=pygame.mouse.get_pos()
way_point_list+=(pos_xy),
choose=True#为True则证明至少有一个点被存储
else:#choose==True已经选择了两个点,开始调用amo_way
way_point_list+=(pos_xy),
#trajectory_list弹道列表
trajectory_list=amo_way(wnd_rect,way_point_list[0],way_point_list[1])
#print(way_point_list)#test code
way_point_list.clear()
choose=False

elif pygame.mouse.get_pressed()==(0,0,1): #右键按下时,取消上一个点
try:
way_point_list.pop()
except IndexError:
if len(way_point_list)<1:
choose=False
elif event.type==pygame.MOUSEMOTION and choose: #鼠标移动
pos_xy=pygame.mouse.get_pos()

for cur_xy in iter(trajectory_list):
mainwnd.set_at(cur_xy,"white")


pygame.display.flip() #显示
if __name__=="__main__":hy_main()

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询