Sunday, 17 November 2019

Rolling a circle around a square

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

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



from Rolling a circle around a square

No comments:

Post a Comment