You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
177 lines
6.9 KiB
177 lines
6.9 KiB
from direct.actor.Actor import Actor
|
|
from panda3d.core import NodePath, Vec3, TransformState, Point3
|
|
from panda3d.bullet import BulletVehicle, BulletBoxShape, ZUp
|
|
from panda3d.bullet import BulletRigidBodyNode
|
|
|
|
|
|
class City():
|
|
def __init__(self, bullet_world):
|
|
self.root = Actor(base.models['city'])
|
|
self.root.reparent_to(render)
|
|
self.root.set_pos(-16,16,-16)
|
|
self.root.set_scale(8)
|
|
self.root.loop('wheel_rotation')
|
|
windows = self.root.find("**/window*")
|
|
windows.set_light_off()
|
|
|
|
self.bullet_world = bullet_world
|
|
self.make_vehicle()
|
|
self.vehicle_node.set_pos(936.978, 269.305, 0)
|
|
self.vehicle_node.set_hpr(104.439, -0.0880938, 0.735647)
|
|
self.active = False
|
|
|
|
base.task_mgr.add(self.update)
|
|
|
|
def make_vehicle(self):
|
|
self.vehicle_node = vehicle_node = render.attach_new_node(BulletRigidBodyNode('city_vehicle_1'))
|
|
|
|
v_shape = BulletBoxShape(Vec3(1, 2, 0.1))
|
|
transform_shape_space = TransformState.make_pos(Point3(0, 0, 0))
|
|
vehicle_node.node().add_shape(v_shape, transform_shape_space)
|
|
|
|
vehicle_node.node().set_ccd_motion_threshold(0.000000007)
|
|
vehicle_node.node().set_ccd_swept_sphere_radius(0.30)
|
|
|
|
vehicle_node.node().set_deactivation_enabled(False)
|
|
|
|
vehicle_node.node().set_mass(300.0) # mass in kilograms
|
|
vehicle_node.node().set_friction(0.01)
|
|
# vehicle_node.node().set_linear_factor(3)
|
|
self.bullet_world.attach_rigid_body(vehicle_node.node())
|
|
|
|
# instantiate vehicle
|
|
self.city_vehicle_1 = BulletVehicle(self.bullet_world, vehicle_node.node())
|
|
self.city_vehicle_1.set_coordinate_system(ZUp)
|
|
self.bullet_world.attach_vehicle(self.city_vehicle_1)
|
|
|
|
def add_wheel(sandboard, pos, front_wheel):
|
|
wheel = sandboard.create_wheel()
|
|
wheel.set_chassis_connection_point_cs(pos)
|
|
wheel.set_front_wheel(front_wheel)
|
|
wheel.set_wheel_direction_cs(Vec3(0, 0, -1))
|
|
wheel.set_wheel_axle_cs(Vec3(1, 0, 0))
|
|
wheel.set_wheel_radius(1.5)
|
|
wheel.set_max_suspension_travel_cm(15.0)
|
|
wheel.set_suspension_stiffness(75.0)
|
|
wheel.set_wheels_damping_relaxation(2.0)
|
|
wheel.set_wheels_damping_compression(4.0)
|
|
wheel.set_friction_slip(15)
|
|
wheel.set_roll_influence(0.01)
|
|
return wheel
|
|
|
|
for p in [
|
|
(Point3(1, 2, 0), True),
|
|
(Point3(-1, 2, 0), True),
|
|
(Point3(1, -2, 0), False),
|
|
(Point3(-1, -2, 0), False),
|
|
]:
|
|
add_wheel(self.city_vehicle_1, *p)
|
|
# vehicle state handler begins
|
|
self.steering_increment = -0.2
|
|
self.engine_force = 0.0
|
|
self.brake_force_1 = 0.0
|
|
self.engine_max_force = 200
|
|
self.city_max_speed = 10
|
|
|
|
def move_vehicle(self):
|
|
dt = globalClock.get_dt()
|
|
|
|
v_pos = self.vehicle_node.get_pos()
|
|
self.root.set_pos(v_pos)
|
|
self.root.set_hpr(self.vehicle_node.get_hpr())
|
|
|
|
input_context = base.device_listener.read_context('city')
|
|
|
|
# reset the city if it flips over
|
|
if self.vehicle_node.get_r() > 150:
|
|
self.vehicle_node.set_hpr(Vec3())
|
|
if self.vehicle_node.get_r() < -150:
|
|
self.vehicle_node.set_hpr(Vec3())
|
|
|
|
self.city_speed = self.city_vehicle_1.current_speed_km_hour
|
|
self.city_speed = self.city_speed / 1.61
|
|
|
|
if self.active:
|
|
if input_context['steering'] == -1:
|
|
# set max steering angle
|
|
if self.steering_increment < 40:
|
|
self.steering_increment += 0.01
|
|
|
|
if input_context['steering'] == 1:
|
|
# set min steering angle
|
|
if self.steering_increment > -35:
|
|
self.steering_increment -= 0.01
|
|
|
|
# relax steering to center with thermostatic feedback
|
|
if not input_context['steering'] == 1:
|
|
if not input_context['steering'] == -1:
|
|
if abs(self.steering_increment) < 0.2:
|
|
self.steering_increment = 0
|
|
|
|
if self.steering_increment > 0.25:
|
|
self.steering_increment -= 0.25
|
|
|
|
if self.steering_increment < -0.25:
|
|
self.steering_increment += 0.25
|
|
|
|
# ensure rotational velocity remains rational
|
|
if self.vehicle_node.get_r() < 120:
|
|
if self.vehicle_node.get_r() > -120:
|
|
r_vel = self.vehicle_node.node().angular_velocity[2]
|
|
if r_vel < -0.25:
|
|
torque = Vec3(0, 0, 4000)
|
|
torque = render.get_relative_vector(self.vehicle_node, torque)
|
|
self.vehicle_node.node().apply_torque(torque)
|
|
if r_vel > 0.25:
|
|
torque = Vec3(0, 0, -4000)
|
|
torque = render.get_relative_vector(self.vehicle_node, torque)
|
|
self.vehicle_node.node().apply_torque(torque)
|
|
|
|
# stabilize the pitch
|
|
if self.vehicle_node.get_p() > 20:
|
|
torque = Vec3(-2000, 0, 0)
|
|
torque = render.get_relative_vector(self.vehicle_node, torque)
|
|
self.vehicle_node.node().apply_torque(torque)
|
|
if self.vehicle_node.get_p() < -20:
|
|
torque = Vec3(2000, 0, 0)
|
|
torque = render.get_relative_vector(self.vehicle_node, torque)
|
|
self.vehicle_node.node().apply_torque(torque)
|
|
|
|
# stabilize the roll
|
|
if self.vehicle_node.get_r() > 10:
|
|
torque = Vec3(0, -750, 0)
|
|
torque = render.get_relative_vector(self.vehicle_node, torque)
|
|
self.vehicle_node.node().apply_torque(torque)
|
|
if self.vehicle_node.get_r() < -10:
|
|
torque = Vec3(0, 750, 0)
|
|
torque = render.get_relative_vector(self.vehicle_node, torque)
|
|
self.vehicle_node.node().apply_torque(torque)
|
|
|
|
if self.city_speed <= self.city_max_speed:
|
|
if self.engine_force <= self.engine_max_force:
|
|
self.engine_force += 300 * dt
|
|
self.brake_force_1 = 0
|
|
|
|
if self.city_speed > self.city_max_speed:
|
|
if self.engine_force > 0:
|
|
self.engine_force -= 100 * dt
|
|
self.brake_force_1 = 10
|
|
|
|
if self.city_speed < 0:
|
|
self.engine_force = self.engine_max_force * 3
|
|
|
|
# activate front steering
|
|
self.city_vehicle_1.set_steering_value(self.steering_increment, 0)
|
|
self.city_vehicle_1.set_steering_value(self.steering_increment, 1)
|
|
|
|
# activate front and rear power, braking
|
|
for i in range(4):
|
|
self.city_vehicle_1.apply_engine_force(self.engine_force, i)
|
|
self.city_vehicle_1.set_brake(self.brake_force_1, i)
|
|
|
|
|
|
def update(self, task):
|
|
dt = base.clock.get_dt()
|
|
self.move_vehicle()
|
|
|
|
return task.cont
|
|
|