zoukankan      html  css  js  c++  java
  • 随机生成路径(二)

    对上一个版本更改了一下,使得原动作可以自定义。

    #baseAnimation.py
    import math

    #define world direction
    Dir_Up, Dir_Right, Dir_Down, Dir_Left = range(0, 4)

    #define move direction to local
    Move_Left, Move_Forward, Move_Right = range(-1, 2)


    class BaseAnimation:
    def __init__(self, move_dir, v_step, h_step):

    #定义动作的横向和纵向跨度
    self.v_step = v_step
    self.h_step = h_step

    #动作作用方向(-1,左)(0,直)(1,右)
    self.Move_Dir = move_dir
    pass

    #检测是否穿过了障碍物
    def is_in_block(self, cur_pos, new_pos, block_map):
    cur_x = cur_pos[0]
    cur_y = cur_pos[1]
    new_x = new_pos[0]
    new_y = new_pos[1]

    #增长系数
    itr_x = -1
    itr_y = -1
    if new_x > cur_x:
    itr_x = 1

    if new_y > cur_y:
    itr_y = 1

    for i in range(cur_x, new_x+itr_x, itr_x):
    for j in range(cur_y, new_y+itr_y, itr_y):
    #print("check[%s][%s]"%(j,i))
    if block_map[j][i] > 0:
    return True

    return False

    #传入当前位置,当前方向,以及边界,障碍图
    def after_move(self, cur_pos, cur_dir, border, block_map):
    new_x = cur_pos[0]
    new_y = cur_pos[1]
    border_x = border[0]
    border_y = border[1]
    new_dir = (cur_dir + self.Move_Dir)%4
    can_move = True

    if cur_dir == Dir_Up:
    new_x = new_x + self.h_step
    new_y = new_y + self.v_step
    elif cur_dir == Dir_Right:
    new_x = new_x + self.v_step
    new_y = new_y - self.h_step
    elif cur_dir == Dir_Down:
    new_x = new_x - self.h_step
    new_y = new_y - self.v_step
    elif cur_dir == Dir_Left:
    new_x = new_x - self.v_step
    new_y = new_y + self.h_step

    if new_x < 0 or new_x > border_x-1 or new_y < 0 or new_y > border_y -1:
    can_move = False
    else:
    if self.is_in_block(cur_pos, [new_x,new_y], block_map):
    can_move = False

    #print("can_move:%s|new_pos:%s,%s|new_dir:%s"%(can_move,new_x, new_y, new_dir))
    return [can_move, [new_x, new_y], new_dir]



    pass

    def draw_path(self, cur_pos, cur_dir, color, width):

    pass


    ##if __name__ == "__main__":
    #
    # testAnim = BaseAnimation(Move_Right, 0, 1)

    ## for i in range(0,4):
    #
    # testAnim.after_move([0,0],i, [8,8], None)

    在生成路径过程中对各个元动作进行数量的限制。增加了鼠标点击事件,选中目标点然后生成路径。

    import pygame
    import math
    import random

    from baseAnimation import *

    black = (0, 0, 0)
    white = (255, 255, 255)
    red = (255, 0, 0)
    green = (0, 255, 0)
    blue = (0, 0, 255)
    yellow = (255, 255, 0)

    done = False


    #define baseAnimationList
    anim_list = [BaseAnimation(Move_Left, 0, -1), BaseAnimation(Move_Forward, 1, 0),
    BaseAnimation(Move_Right, 0, 1), BaseAnimation(Move_Left, 0, -2),
    BaseAnimation(Move_Right, 0, 3), BaseAnimation(-2, -1,-1)]



    #define block type
    Block_Blank,Block_Hold=range(0,2)

    pygame.init()

    size = [800, 600]

    screen = pygame.display.set_mode(size)


    pygame.display.set_caption("Animation Path")

    def dir_str(cur_dir):
    dir_str = ""
    if cur_dir == Dir_Up:
    dir_str = ""
    elif cur_dir == Dir_Right:
    dir_str = ""
    elif cur_dir == Dir_Down:
    dir_str = ""
    elif cur_dir == Dir_Left:
    dir_str = ""

    return dir_str

    def movestate_str(move_state):
    move_str = ""
    if move_state == Move_Left:
    move_str = "Turn Left"
    elif move_state == Move_Forward:
    move_str = "Forward"
    elif move_state == Move_Right:
    move_str = "Turn Right"

    return move_str

    class TraceListener:
    def __init__(self):
    #设置动作个数限制
    self.max_list = [5,5,5,1,1,1]

    def constrain(self, anim_count, state):
    if anim_count[state] > self.max_list[state]:
    #print("anim_%s over"%(state))
    return True
    return False

    class AnimationPath:
    def __init__(self):
    self.width = 10
    self.height = 10
    self.cell_size = 50
    self.max_depth = 20

    self.one_step = 1

    self.start_pos = [0,0]

    self.begin_pos = [0,0]
    self.end_pos = [8,8]

    self.path_width = 2

    self.block_map = []

    self.is_find = False
    self.trace_listener = TraceListener()

    self.initialize()

    def initialize(self):
    self.result_list = []
    self.count = 0
    self.recursive_count = 0

    #统计动作使用数
    self.anim_count = {}
    #溢出,需重新找
    self.need_refind = False

    def init_block(self):
    self.block_map[3][2] = 1
    self.block_map[3][3] = 1
    self.block_map[3][4] = 1
    self.block_map[3][5] = 1
    self.block_map[6][2] = 1
    self.block_map[6][3] = 1
    self.block_map[6][4] = 1


    def draw_board(self):
    start_pos = self.start_pos
    total_width = self.width * self.cell_size
    total_height = self.height * self.cell_size

    #draw board lines 此处borad左移了cell_size/2
    #"|"
    for i in range(0, self.width+1):
    begin_pos_x = start_pos[0] + i * self.cell_size - self.cell_size/2
    end_pos_y = start_pos[1] - total_height
    pygame.draw.line(screen, white, [begin_pos_x,start_pos[1]],
    [begin_pos_x, end_pos_y], 1)
    #"--"
    for j in range(0, self.height+1):
    begin_pos_y = start_pos[1] - j * self.cell_size
    end_pos_x = start_pos[0] + total_width - self.cell_size/2
    pygame.draw.line(screen, white, [start_pos[0] - self.cell_size/2, begin_pos_y],
    [end_pos_x, begin_pos_y], 1)

    #draw board elements
    for row in range(0, self.height):
    for col in range(0, self.width):
    if self.block_map[row][col] == Block_Hold:
    pygame.draw.circle(screen, yellow,
    [start_pos[0] + col * self.cell_size,
    start_pos[1] - row * self.cell_size-self.cell_size/2],
    self.cell_size/2,
    0)

    #draw end_pos
    pygame.draw.circle(screen, red,
    [start_pos[0] + (self.end_pos[0]) * self.cell_size,
    start_pos[1] - (self.end_pos[1]) * self.cell_size - self.cell_size/2],
    self.cell_size/2,
    0)

    def draw_line(self, start_pos, end_pos, color, width):
    pygame.draw.line(screen,color,
    start_pos,
    end_pos,
    width)

    def draw_arc(self, pos, diameter, section, color, width):
    pygame.draw.arc(screen, color,
    [pos[0] - diameter/2, pos[1] - diameter/2, diameter, diameter],
    math.radians((section-1) * 90),
    math.radians(section * 90),
    width)

    #根据方向获得真正的坐标位置
    def get_real_pos(self, cur_pos, cur_dir):
    base_x = self.start_pos[0]
    base_y = self.start_pos[1]

    real_x = self.start_pos[0] + cur_pos[0] * self.cell_size
    real_y = self.start_pos[1] - cur_pos[1] * self.cell_size
    if cur_dir == Dir_Up:
    pass
    elif cur_dir == Dir_Right:
    real_x -= self.cell_size/2
    real_y -= self.cell_size/2
    elif cur_dir == Dir_Down:
    real_y -= self.cell_size
    elif cur_dir == Dir_Left:
    real_x += self.cell_size/2
    real_y -= self.cell_size/2

    return [real_x, real_y]


    #画出行走路线
    def draw_path(self, cur_pos, cur_dir, move_anim, color, width):
    cur_x = cur_pos[0]
    cur_y = cur_pos[1]


    new_state = move_anim.after_move(cur_pos, cur_dir, [self.width,self.height], self.block_map)

    new_x = new_state[1][0]
    new_y = new_state[1][1]

    new_dir = new_state[2]

    real_cur_pos = self.get_real_pos(cur_pos, cur_dir)
    real_new_pos = self.get_real_pos([new_x, new_y], new_dir)

    self.draw_line(real_cur_pos, real_new_pos, color, width)

    pass


    #根据现在的方向和动作判断下一个位置
    def move_to_next(self, cur_pos, cur_dir, move_anim):
    return move_anim.after_move(cur_pos, cur_dir,[self.width, self.height], self.block_map)


    #递归移动
    def traceback_move(self, cur_pos, cur_dir, end_dir):
    self.recursive_count += 1
    #print("count:%s"%self.recursive_count)

    if self.recursive_count > self.max_depth:
    #print("over flow")
    self.need_refind = True
    return False

    if not self.is_find:

    cur_x = cur_pos[0]
    cur_y = cur_pos[1]

    if cur_x == self.end_pos[0] and cur_y == self.end_pos[1]:
    print("cur_dir:%s|end_dir:%s"%(dir_str(cur_dir), dir_str(end_dir)))
    if end_dir <> None:
    if end_dir == cur_dir:
    self.count= self.count + 1
    print ("reach goal with dir%s"%self.count)
    #reslut_list.append([cur_x, cur_y])
    self.is_find = True
    self.need_rfind = False
    return True
    else:
    self.need_rfind = True
    return False
    else:
    self.count= self.count + 1
    print ("reach goal not dir%s"%self.count)
    #reslut_list.append([cur_x, cur_y])
    self.is_find = True
    self.need_rfind = False
    return True

    else:
    state_list = range(0,len(anim_list))
    while len(state_list) > 0:
    #获得随机值
    state_left = len(state_list)
    state_index = random.randint(0, state_left-1)
    state = state_list[state_index]
    state_list.remove(state)
    move_anim = anim_list[state]
    if state in self.anim_count.keys():
    self.anim_count[state] +=1
    else:
    self.anim_count[state] = 1

    #限制数目
    if self.trace_listener:
    if self.trace_listener.constrain(self.anim_count, state):
    self.anim_count[state] -= 1
    continue
    #是否可移动
    move_result = self.move_to_next(cur_pos, cur_dir, move_anim)
    if move_result[0]:
    cur_x = move_result[1][0]
    cur_y = move_result[1][1]

    new_dir = move_result[2]


    if self.traceback_move([cur_x,cur_y], new_dir, end_dir):
    print ("[%s,%s]:%s:%s"%(cur_pos[0], cur_pos[1],dir_str(cur_dir), movestate_str(move_anim.Move_Dir)))
    self.result_list.append([cur_pos,cur_dir,move_anim])
    return True

    else:
    self.anim_count[state] -=1
    else:
    self.anim_count[state] -= 1
    return False
    else:
    return True
    pass


    def calc_board_size(self, start_pos, end_pos):
    self.end_pos[0] = abs(end_pos[0] - start_pos[0])/self.cell_size
    self.end_pos[1] = abs(end_pos[1] - start_pos[1])/self.cell_size

    #self.height = height+1
    #self.width = width+1

    for row in range(0,self.height):
    per_row = [0]*self.width
    self.block_map.append(per_row)

    def findPath(self, start_pos, end_pos, start_dir, end_dir = None):
    self.is_find = False
    cur_x = 0
    cur_y = 0
    cur_dir = start_dir
    self.start_pos = start_pos
    self.calc_board_size(start_pos, end_pos)

    self.init_block()
    while not self.is_find:
    self.initialize()
    self.traceback_move([cur_x, cur_y], cur_dir, end_dir)
    if not self.is_find and self.need_refind:
    self.initialize()
    self.traceback_move([cur_x, cur_y], cur_dir, end_dir)

    print ("sum_anim:%s"%(len(self.result_list)))

    sum_count = 0
    for index in self.anim_count:
    sum_count += self.anim_count[index]
    print("Anim_%s:%s"%(index, self.anim_count[index]))
    print ("sum_count:%s"%(sum_count))

    def draw_result(self):
    for step in self.result_list:
    self.draw_path(step[0], step[1], step[2], green, 2)




    s_pos = [100,500]
    e_pos = [350,150]
    c_dir = Dir_Up
    anim_path = AnimationPath()
    anim_path.findPath(s_pos, e_pos, c_dir)
    ##
    results = anim_path.result_list
    results.reverse()
    step_index = 0

    one_step = False

    while done == False:
    for event in pygame.event.get():
    if event.type == pygame.QUIT:
    done = True

    if event.type == pygame.KEYDOWN:
    if event.key == pygame.K_SPACE:
    one_step = not one_step
    elif event.key == pygame.K_LEFT:
    if step_index > 0:
    step_index = step_index - 1
    elif event.key == pygame.K_RIGHT:
    if step_index < len(results)-1:
    step_index = step_index + 1

    elif event.key == pygame.K_g:
    print ("G")
    anim_path.findPath(s_pos, e_pos, c_dir)
    results = anim_path.result_list
    results.reverse()
    step_index = 0
    if event.type == pygame.MOUSEBUTTONUP:
    e_pos = pygame.mouse.get_pos()
    anim_path.findPath(s_pos, e_pos, c_dir)
    results = anim_path.result_list
    results.reverse()
    step_index = 0


    screen.fill(black)
    anim_path.draw_board()
    ## for i in range(0,3):
    #
    # anim_path.draw_path([1,1], 3, i, red, 3)

    anim_path.draw_result()

    # pygame.draw.circle(screen, red, e_pos, 2, 0);

    if not one_step:
    for i in range(0,step_index+1):
    step = results[i]
    anim_path.draw_path(step[0],step[1],step[2], red, 3)
    else:
    step = results[step_index]
    anim_path.draw_path(step[0],step[1],step[2], red, 3)
    pygame.display.flip()
    #clock.tick(5)

    pygame.quit()

    附上结果图:




  • 相关阅读:
    Linux——shell简单学习(一)
    Linux——进程管理简单学习笔记(二)
    Linux——进程管理学习简单笔记
    Linux——用户管理简单学习笔记(四)
    PHP计算程序运行时间的类
    php几个常用的概率算法(抽奖、广告首选)
    限制非安全IP访问
    简单的点击短信发送计时器
    php 以图搜图
    递归获取二维数组后代、删除后代
  • 原文地址:https://www.cnblogs.com/gameprogram/p/2285672.html
Copyright © 2011-2022 走看看