python - 围绕正方形滚动一个圆圈

标签 python algorithm if-statement position box2d

将近一个月后,我仍然停留在这个问题上,我设法决定圆圈(或我所说的行人)应该向左/向右移动还是向上/向下移动,但我需要有可能移动行人 < em>around 一个建筑物(也就是说他们要转弯,基本上不管方向是什么,他们只要转90度就可以了

非常感谢

import numpy as np
import random
import keyboard
from Box2D.b2 import world, polygonShape, circleShape, edgeShape, staticBody, dynamicBody, kinematicBody, revoluteJoint, wheelJoint
from Box2D import b2Vec2, b2FixtureDef, b2PolygonShape, b2CircleShape, b2Dot, b2EdgeShape, b2Contact,b2ContactFilter,b2Filter,b2ContactListener,b2GetPointStates


import pygame
from pygame import HWSURFACE, DOUBLEBUF, RESIZABLE, VIDEORESIZE
from pygame.locals import (QUIT, KEYDOWN, K_ESCAPE)
pygame.init()

box2world = world(contactListener = MyContactListener(), gravity = (0.0, 0.0), doSleep = True)

class Pedestrian():
    def __init__(self,box2world, position = None):

        if position == None:
            position = [5,5]

        self.position = position
        self.box2world = box2world
        self.Current_Position = []
        self.body = self.box2world.CreateDynamicBody(position = position, 
                                                       angle = 0.0,
                                                       fixtures = b2FixtureDef(
                                                            shape = b2CircleShape(radius = 0.5),
                                                            density = 2,
                                                            friction = 0.3,
                                                            ))


class Building():
    def __init__(self, box2world,shape, position, sensor= None):
        self.box2world = box2world
        self.shape = shape
        self.position = position

        if sensor == None:
            sensor = False
        self.corners = [((self.position[0] + self.shape[0]), (self.position[1] + self.shape[1])),
                        ((self.position[0] + self.shape[0]), (self.position[1] - self.shape[1])),
                        ((self.position[0] - self.shape[0]), (self.position[1] - self.shape[1])),
                        ((self.position[0] - self.shape[0]), (self.position[1] + self.shape[1]))]

        self.sensor = sensor
        self.footprint = self.box2world.CreateStaticBody(position = position,
                                                           angle = 0.0,
                                                           fixtures = b2FixtureDef(
                                                               shape = b2PolygonShape(box=(self.shape)),
                                                               density = 1000,
                                                               friction = 1000))


############################################################## Pygame visualisation
PPM = 10
SCREEN_WIDTH, SCREEN_HEIGHT = 640, 480
SCREEN_OFFSETX, SCREEN_OFFSETY = SCREEN_WIDTH/16, SCREEN_HEIGHT
POS_X = SCREEN_WIDTH/PPM/3
POS_Y = SCREEN_HEIGHT/PPM/3
MAX_AMOUNT_PEDESTRIANS = 10
FPS = 24
TIME_STEP = 1.0 / FPS
k = 0

screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT), HWSURFACE|DOUBLEBUF|RESIZABLE)
pygame.display.set_caption('Top Down Car Using OOP')
colors = {dynamicBody: (133, 187, 101, 0),  staticBody: (15, 0, 89, 0)}

walkers = [] 

skyscraper  = Building(box2world,shape = (5,5), position =  (POS_X + 3, POS_Y + 5))

def fix_vertices(vertices):
    return [(int(SCREEN_OFFSETX + v[0]), int(SCREEN_OFFSETY - v[1])) for v in vertices]


def _draw_polygon(polygon, screen, body, fixture):
    transform = body.transform
    vertices = fix_vertices([transform * v * PPM for v in polygon.vertices])
    pygame.draw.polygon(
        screen, [c / 2.0 for c in colors[body.type]], vertices, 0)
    pygame.draw.polygon(screen, colors[body.type], vertices, 1)
polygonShape.draw = _draw_polygon


def _draw_circle(circle, screen, body, fixture):
    position = fix_vertices([body.transform * circle.pos * PPM])[0]
    pygame.draw.circle(screen, colors[body.type],
                       position, int(circle.radius * PPM))
circleShape.draw = _draw_circle

running = True
while running:
    for event in pygame.event.get():
        if event.type == QUIT or (event.type == KEYDOWN and event.key == K_ESCAPE):
            running = False

    screen.fill((255, 255, 255, 255))
    for body in box2world.bodies:
        for fixture in body.fixtures:
            fixture.shape.draw(screen, body, fixture)

    if k <= MAX_AMOUNT_PEDESTRIANS:
        walkers.append(Pedestrian(box2world, position = (skyscraper.position[0] -random.randint(-skyscraper.shape[0],skyscraper.shape[0]),\
                            skyscraper.position[1] -random.randint(-skyscraper.shape[1],skyscraper.shape[1]))))
        k = k+1
    for walker in walkers:
        pedestrian_walk(walker,skyscraper)
    # Simulate dynamic equation in each step
    TIME_STEP = 1.0 / FPS
    box2world.Step(TIME_STEP, 10, 10)

    # Flip the screen and try to keep at the target FPS
    pygame.display.flip() # Update the full display Surface to the screen
    pygame.time.Clock().tick(FPS)

pygame.quit()
print('Done!')

所以基本上有两个目标,一个是让行人转弯(可能我必须在施加垂直力之前施加平行于他们现在正在相反方向移动的力,所以他们会立即停下来 < strong>then turn 但我不知道该怎么做(或者可能有不同的解决方案,这就是我问的原因)

另一个目标是在 for 循环中执行此操作,因为在我的游戏中有四座建筑物......我试图将其放入 for 循环但失败了(如果需要,我可以稍后发布我的 for 循环,但是我需要解决我的第一个问题。

免责声明 你们中的一些人可能注意到几乎相同的问题出现在 GameDev.StackExchange.com 上,在我的第二个用户帐户下,我不知道为什么我创建了另一个帐户,但我知道它这不是一个好的解决方案,我很抱歉。我只是想请您不要谈论为什么我创建了新帐户并且它很糟糕...我知道这一点,对此我再次感到抱歉...

我把问题放在这里的原因是我认为这里是一个更好的地方有两个原因,第一:它更多的是算法问题而不是游戏开发问题,第二:SO 比 GameDev 更忙,我是坚持了很长时间,所以我真的需要帮助

编辑:我设法将此属性添加到建筑类并将其实现到行人步行功能中,它偶尔会起作用,但我该如何改进呢?或者让它更“pythonic” 非常感谢

def pedestrian_walk(Pedestrian, Building):
    if Pedestrian.body.position[0] <= Building.position[0] and Building.position[1] - Building.shape[1] < Pedestrian.position[1] < Building.position[1] + Building.shape[1]:
        Pedestrian.body.__SetLinearVelocity(b2Vec2(0,10))
    elif Pedestrian.body.position[0] > Building.position[0] and Building.position[1] - Building.shape[1] < Pedestrian.position[1] < Building.position[1] + Building.shape[1]:
        Pedestrian.body.__SetLinearVelocity(b2Vec2(0,-10))
    elif Pedestrian.body.position[1] > Building.position[1] and Building.position[0] - Building.shape[0] < Pedestrian.position[0] < Building.position[0] + Building.shape[0]:
        Pedestrian.body.__SetLinearVelocity(b2Vec2(10,0))
    elif Pedestrian.body.position[1] <= Building.position[1] and Building.position[0] - Building.shape[0] < Pedestrian.position[0] < Building.position[0] + Building.shape[0]:
        Pedestrian.body.__SetLinearVelocity(b2Vec2(-10,0))

    if ((Building.corners[0][0] -0.5 <= Pedestrian.body.position[0] <= Building.corners[0][0] + 0.5 and\
        Building.corners[0][1] -0.5 <= Pedestrian.body.position[1] <= Building.corners[0][1] + 0.5)):
        Pedestrian.body.__SetLinearVelocity(b2Vec2(-100,100))
        print("Changing direction")
    elif((Building.corners[1][0] -0.5 <= Pedestrian.body.position[0] <= Building.corners[1][0] + 0.5 and\
        Building.corners[1][1] -0.5 <= Pedestrian.body.position[1] <= Building.corners[1][1] + 0.5)):
        Pedestrian.body.__SetLinearVelocity(b2Vec2(-100,200))
        print("Changing direction")
    elif((Building.corners[2][0] -0.5 <= Pedestrian.body.position[0] <= Building.corners[2][0] + 0.5 and\
        Building.corners[2][1] -0.5 <= Pedestrian.body.position[1] <= Building.corners[2][1] + 0.5)):
        Pedestrian.body.__SetLinearVelocity(b2Vec2(-100,200))
        print("Changing direction")
    elif((Building.corners[3][0] -0.5 <= Pedestrian.body.position[0] <= Building.corners[3][0] + 0.5 and\
        Building.corners[3][1] -0.5 <= Pedestrian.body.position[1] <= Building.corners[3][1] + 0.5)):
        Pedestrian.body.__SetLinearVelocity(b2Vec2(-100,200))
        print("Changing direction")

最佳答案

很难说出您的代码应该做什么。但有些事情很可能是不对的。在

Which_Skyscraper = Skyscrapers[random.randint(0,len(Skyscrapers)-1)].position
Random_Skyscraper = Skyscrapers[random.randint(0,len(Skyscrapers)-1)]
Johnnie_Walkers.append(Pedestrian(Box_2_World, position = \
    (Which_Skyscraper[0] -random.randint(-Random_Skyscraper.shape[0],Random_Skyscraper.shape[0]), \
    Which_Skyscraper[1] -random.randint(-Random_Skyscraper.shape[1],Random_Skyscraper.shape[1]))))

你确实创造了行人。但是定位很奇怪。您随机拿走一栋建筑 (Which_Skyscraper),然后将其与另一座随机拿走的建筑 (Random_Skyscraper) 混为一谈。这些建筑物可能完全相同,但更有可能是不同的。我认为您打算将行人放在建筑物内,这需要随机抽取建筑物一次。

更糟糕的是建筑物和行人在

# Make the pedestrian walk
Tick_Counter = Tick_Counter + 1
Random_Johnnie = random.randint(0,len(Johnnie_Walkers)-1)

if abs(Skyscrapers[Random_Johnnie].position[1] - Johnnie_Walkers[Random_Johnnie].position[0]) >= \
        Skyscrapers[Random_Johnnie].shape[1]/2 +1:
    Johnnie_Walkers[Random_Johnnie].body.ApplyForce(b2Vec2(5,0), \
    Johnnie_Walkers[Random_Johnnie].body.worldCenter,True)

elif ...

这里你得到一个随机索引给你的行人 random.randint(0,len(Johnnie_Walkers)-1) 然后你应用到建筑物列表 Skyscrapers[Random_Johnnie].shape [1]/2 这是胡说八道。约翰尼二世与 3 号街道的建筑物无关。

还有更难理解的代码,例如在无法应用 Force 时重置滴答计数器 Tick_Counter = 0

一些一般提示:

使您的代码可读。正确命名变量。 Random_Johnnie 可能只在您的耳朵里听起来很有趣。每个人都可以看到索引是随机选择的。但没有暗示它将用于什么。 person_to_start_walking 怎么样? Which_Skyscraper 也是如此。 building_where_to_generate_person 怎么样?代码将如何阅读?好多了。

从类 C 语言转换到 Python 时的一个非常重要的问题,(几乎)从不使用索引,学会使用引用,它们甚至比索引更便宜。像 一样在建筑物中 build : 并且在您的情况下使用 random.choice() 随机选择人或建筑物时使用循环。这样您就不会无意中在建筑物集合上使用人员索引。

此外 - 使用临时变量而不是长嵌套表达式。它更容易阅读,特别是如果它们有好听的名字。如果是位置,请不要命名 Which_Skyscraper

关于python - 围绕正方形滚动一个圆圈,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58557869/

相关文章:

python - : if A, elif B 更好/更简单的控制流程,if A 或 B,否则

python - 未找到打印搜索的问题

algorithm - 为什么 ArrayList 在 O(n) 而不是 O(n*n) 中删除功能

python - 如何使用 Autobahn Python 和 Twisted Reconnecting ClientFactory 重新注册在重新连接后调用的 WAMP?

algorithm - 以时、日、月、年显示相对时间

javascript - 在 postgresql 数据库中存储 semver 版本字符串以进行范围查询

Javascript:将文本框数字条目转换为相应的字母等级

Javascript bool 运算不起作用

python - 如何根据条件按组找到最大值? Pandas

Python随时间查找音频频率和幅度