提问人:Mechatrnk 提问时间:10/25/2019 最后编辑:Mechatrnk 更新时间:11/18/2019 访问量:587
绕着正方形滚一个圆圈
Rolling a circle around a square
问:
将近一个月后,我仍然被困在这个问题上,我设法决定圆圈(或我所说的行人)是否应该向左/向右或向上/向下移动,但我需要有可能在建筑物周围移动行人(这意味着他们必须转弯,基本上不管方向如何, 他们只需要旋转 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!')
所以基本上有两个目标,一个是让行人转弯(可能我必须在施加垂直力之前施加平行于他们现在向相反方向移动的力,所以他们会立即停下来然后转弯,但我不知道该怎么做(或者可能有不同的解决方案, 这就是我问的原因)
另一个目标是在 for 循环中做到这一点,因为在我的游戏中有四座建筑......我试图把它放在for循环中,但失败了(如果需要,我可以稍后发布我的for循环,但请我需要解决我的第一个问题。
免責聲明你们中的一些人可能会注意到,在我的第二个用户帐户下,GameDev.StackExchange.com 上出现了几乎相同的问题,我不知道为什么我创建了另一个帐户,但我知道这不是一个好的解决方案,我很抱歉。我只是想问你不要谈论我为什么创建新帐户以及它很糟糕......我知道这一点,我再次为此感到抱歉......
我之所以把问题放在这里,是因为我认为这里是一个更好的地方,原因有两个,第一:它更多的是算法问题而不是游戏开发问题,第二:SO 比 GameDev 忙得多,而且我被困在这个问题上很长时间,所以我真的需要帮助
编辑:我设法将此属性添加到 Building 类并将其实现到 pedestrian_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 ...
在这里,你会得到一个行人的随机索引,然后你将其应用于建筑物列表,这是无稽之谈。约翰尼二世与3号街的建筑物无关。random.randint(0,len(Johnnie_Walkers)-1)
Skyscrapers[Random_Johnnie].shape[1]/2
还有更难理解的代码,例如在没有力的情况下重置刻度计数器。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
评论
上一个:没有正文的 if 语句
评论
append
Skyscrapers
Skyscrapers[Random_Johnnie]