绕正方形滚动一圈 [英] Rolling a circle around a square

查看:115
本文介绍了绕正方形滚动一圈的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

将近一个月后,我仍然在这个问题上陷入困境,我设法决定了圈子(或我所说的行人)应该向左/向右移动还是向上/向下移动,但是我需要有可能使行人移动<

非常感谢

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

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

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

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

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

编辑:我设法将此属性添加到建筑类"中,并将其实现到"walker_walk"功能中,它偶尔会起作用,但我该如何改进?还是让它变得更"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列表. 2号强尼(Johnny 2)与3号街的建筑物无关.

如果无法施加力,则更难理解的代码,例如重置滴答计数器Tick_Counter = 0.

一些常规提示:

使您的代码可读.正确命名变量. Random_Johnnie可能只在您的耳朵听起来很有趣.每个人都可以看到索引是随机选择的.但是没有任何暗示将用于什么目的. person_to_start_walking呢?与Which_Skyscraper相同. building_where_to_generate_person呢?代码将如何读取?好多了.

当从类似C的语言更改为python时,这是一个非常重要的问题,(几乎)从不使用索引,学会使用引用,它们甚至比索引便宜.像for building in buildings:这样的循环,在您随机选择人或建筑物时,也请使用random.choice().这样一来,您就不会偶然在建筑物集合上使用人员索引.

也-使用临时变量而不是长的嵌套表达式.更容易阅读,尤其是当他们有好名字的时候.如果职位是Which_Skyscraper,请不要命名.

After almost a month I am still stuck on this issue I managed to decide whether the circles (or pedestrians as I call them) should move left/right or up/down but I need to have the possibility to move the pedestrians around a building (that means they have to turn on the corners, basically does not matter whether direction, they just need to turn by 90 degrees

Thank you very much

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

So there are basically two goals, one is to make the pedestrians turn (probably I will have to before applying perpendicular force to apply force parallel to that they are moving right now of the opposite direction, so they would immediately stop and then turn but I do not know how to do that (or maybe there might be a different solution, that's why I am asking)

And the other goal is to do this in a for loop, because in my game there are four buildings... I tried to put it in the for loop but failed (I can post my for loop later if requested, but please I need to solve my first problem.

Disclaimer Some of you may notice that almost the same question appeared on GameDev.StackExchange.com, under my second user account, I do not why I created the other account, but I know that it was not a good solution, I am sorry for that. I just wanted to ask you for not talking about why I created the new account and that it is bad... I know that and once again I am sorry for that...

The reason I put the question here is that I think that here it is a better place for two reasons, First: it is more algorithm problem than a game-developing problem, Second: SO is much busier than GameDev and I am stuck on this for a very long time, so I really need help

EDIT: I managed to add this attribute to the Building Class and implement it into the pedestrian_walk function, it works occasionally, but how could I improve it? Or maybe make it more "pythonic" Thank you very much

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

解决方案

It is hard to tell what your code should do. But there are some things that are most probably not right. In

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

you do create pedestrians. However the positioning is weird. You randomly take one building (Which_Skyscraper) and mangle that with another randomly taken building (Random_Skyscraper). These buildings may be identical by chance but more probably they are different. I think you intended to place pedestrians inside a building which would require to have a building taken randomly once.

Even worse is the mangling of buildings and pedestrians in

# 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 ...

here you get a random index to your pedestrians random.randint(0,len(Johnnie_Walkers)-1) which you then apply to the list of buildings Skyscrapers[Random_Johnnie].shape[1]/2 which is nonsense. Johnny the 2nd has nothing to do with the building at street number 3.

There is more hard to understand code like resetting the tick counter Tick_Counter = 0 if no Force could be applied.

Some general hints:

Make your code readable. Name variables properly. Random_Johnnie may sound funny in your ears only. Also everyone can see the index was randomly chosen. But there is no hint what it will be used for. What about person_to_start_walking? Same for Which_Skyscraper. What about building_where_to_generate_person? How would the code read? Much better.

A very important issue when changing from a C-like language to python, (almost) never use indices, learn to work with the references, they are even cheaper than indices. Loop like for building in buildings: and also in your case use random.choice() when picking persons or buildings randomly. That way you cannot by accident use a person-index on a building-collection.

Also - use temporary variables instead of long, nested expressions. It is easier to read, especially if they have good names. Do not name something Which_Skyscraper if it is a position.

这篇关于绕正方形滚动一圈的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆