Вращение круга вокруг квадрата - PullRequest
0 голосов
/ 25 октября 2019

Спустя почти месяц я все еще застрял в этом вопросе, и мне удалось решить, должны ли круги (или пешеходы, как я их называю) двигаться влево / вправо или вверх / вниз, но мне нужно иметь возможность перемещать пешеходов вокруг здания (это означает, что они должны поворачивать за углы, в основном не имеет значения, направление ли, им просто нужно повернуть на 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.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))

corners = [(skyscraper.position[0] - skyscraper.shape[0],skyscraper.position[1] - skyscraper.shape[1]),
         (skyscraper.position[0] + skyscraper.shape[0],skyscraper.position[1] - skyscraper.shape[1]),
         (skyscraper.position[0] - skyscraper.shape[0],skyscraper.position[1] + skyscraper.shape[1]),
         (skyscraper.position[0] + skyscraper.shape[0],skyscraper.position[1] + skyscraper.shape[1])]

def pedestrian_walk(Pedestrian, Building):

    if Pedestrian.position[0] <= Building.position[0] and Building.position[1] - Building.shape[1] < Pedestrian.position[1] < Building.position[1] + Building.shape[1]:
        Pedestrian.body.ApplyForce(b2Vec2(0,5), Pedestrian.body.worldCenter,True)
    elif Pedestrian.position[0] > Building.position[0] and Building.position[1] - Building.shape[1] < Pedestrian.position[1] < Building.position[1] + Building.shape[1]:
        Pedestrian.body.ApplyForce(b2Vec2(0,-5), Pedestrian.body.worldCenter,True)
    elif Pedestrian.position[1] > Building.position[1] and Building.position[0] - Building.shape[0] < Pedestrian.position[0] < Building.position[0] + Building.shape[0]:
        Pedestrian.body.ApplyForce(b2Vec2(5,0), Pedestrian.body.worldCenter,True)
    elif Pedestrian.position[1] <= Building.position[1] and Building.position[0] - Building.shape[0] < Pedestrian.position[0] < Building.position[0] + Building.shape[0]:
        Pedestrian.body.ApplyForce(b2Vec2(-5,0), Pedestrian.body.worldCenter,True)


    # Pedestrian is in a corner
    elif Pedestrian.position == corners[0] - 1/5*Building.shape[0] or Pedestrian.position ==corners[1] + 1/5*Building.shape[0]\
        or Pedestrian.position == corners[2] - 1/5*Building.shape[0] or Pedestrian.position == corners[3] + 1/5*Building.shape[0]:
        random.choice(Pedestrian.body.ApplyForce(b2Vec2(5,0), Pedestrian.body.worldCenter,True),Pedestrian.body.ApplyForce(b2Vec2(0,5), Pedestrian.body.worldCenter,True))


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, под моей учетной записью второго пользователя яНе знаю, почему я создал другую учетную запись, но я знаю, что это не было хорошим решением, я прошу прощения за это. Я просто хотел попросить вас не говорить о том, почему я создал новую учетную запись и что она плохая ... Я знаю это, и еще раз прошу прощения за это ...

Причина, по которой я поставил вопросвот что я думаю, что здесь это лучшее место по двум причинам: во-первых: это скорее проблема алгоритма, чем проблема, связанная с разработкой игры, во-вторых: SO гораздо более загружен, чем GameDev, и я застрял на этом очень долго,так что мне очень нужна помощь

1 Ответ

0 голосов
/ 26 октября 2019

Трудно сказать, что должен делать ваш код. Но есть некоторые вещи, которые, скорее всего, не правы. В

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-й не имеет ничего общего со зданием на улице № 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, если это позиция.

...