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.
321 lines
13 KiB
321 lines
13 KiB
from panda3d.core import NodePath, Vec3, TransformState, Point3
|
|
|
|
from panda3d.bullet import BulletVehicle, BulletBoxShape, ZUp
|
|
from panda3d.bullet import BulletRigidBodyNode
|
|
|
|
from random import randint
|
|
|
|
|
|
class PlayerPhysics():
|
|
def __init__(self, bullet_world, spawn_pos=(0, 0, 50)):
|
|
self.bullet_world = bullet_world
|
|
self.make_vehicle()
|
|
self.vehicle_node.set_pos(spawn_pos)
|
|
self.hook = render.attach_new_node('player_hook')
|
|
base.task_mgr.add(self.update)
|
|
self.board_speed = 0
|
|
self.in_focus = True
|
|
self.coin_frames = 0
|
|
self.total_money = 0
|
|
self.total_coins = 0
|
|
|
|
base.accept('f2', self.manual_reset)
|
|
|
|
def manual_reset(self):
|
|
self.vehicle_node.set_pos(0, 0, 50)
|
|
self.vehicle_node.set_hpr(Vec3())
|
|
|
|
def make_vehicle(self):
|
|
self.vehicle_node = vehicle_node = render.attach_new_node(BulletRigidBodyNode('sandboard_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.sandboard_1 = BulletVehicle(self.bullet_world, vehicle_node.node())
|
|
self.sandboard_1.set_coordinate_system(ZUp)
|
|
self.bullet_world.attach_vehicle(self.sandboard_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(0.4)
|
|
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.sandboard_1, *p)
|
|
# vehicle state handler begins
|
|
self.steering_increment_1 = 0.0
|
|
self.engine_force_1 = 0.0
|
|
self.brake_force_1 = 0.0
|
|
|
|
def collider_data(self, pos_1 = Vec3(), pos_2 = Vec3()):
|
|
coll = self.bullet_world.ray_test_closest(pos_1, pos_2)
|
|
out_data = [coll.get_hit_pos(), coll.get_hit_normal(), coll.get_hit_fraction(), coll.get_node()]
|
|
return out_data
|
|
|
|
def sandboard_phys(self):
|
|
v_pos = self.vehicle_node.get_pos()
|
|
self.hook.set_pos(v_pos)
|
|
self.hook.set_hpr(self.vehicle_node.get_hpr())
|
|
|
|
self.has_coin()
|
|
|
|
input_context = base.device_listener.read_context('player')
|
|
self.board_speed = self.sandboard_1.current_speed_km_hour
|
|
self.board_speed = self.board_speed / 1.61
|
|
# sandboard_1 handler begins
|
|
if input_context['accelerate']:
|
|
self.engine_force_1 = 1200
|
|
self.brake_force_1 = 0.0
|
|
|
|
if self.board_speed > 100:
|
|
self.engine_force_1 = 0
|
|
|
|
# simulate transmission/engine/air drag
|
|
if not input_context['accelerate']:
|
|
if self.board_speed > 0:
|
|
self.engine_force_1 = -50.0
|
|
if self.board_speed < 0:
|
|
self.engine_force_1 = 50.0
|
|
self.brake_force_1 = 0.0
|
|
|
|
if input_context['brake']:
|
|
self.brake_force_1 = 20.0
|
|
self.engine_force_1 = 0.0
|
|
|
|
if self.board_speed < 1:
|
|
self.brake_force_1 = 20.0
|
|
self.engine_force_1 = -2400.0
|
|
if self.board_speed < -60:
|
|
self.engine_force_1 = 0
|
|
self.brake_force_1 = 0
|
|
|
|
if input_context['steering'] == -1:
|
|
# set max steering angle
|
|
if self.steering_increment_1 < 40:
|
|
if self.board_speed < 40:
|
|
self.steering_increment_1 += 0.9
|
|
elif self.board_speed > 40:
|
|
self.steering_increment_1 += 0.45
|
|
|
|
if input_context['steering'] == 1:
|
|
# set min steering angle
|
|
if self.steering_increment_1 > -35:
|
|
if self.board_speed < 40:
|
|
self.steering_increment_1 -= 0.9
|
|
elif self.board_speed > 40:
|
|
self.steering_increment_1 -= 0.45
|
|
|
|
# relax steering to center with thermostatic feedback
|
|
if not input_context['steering'] == 1:
|
|
if not input_context['steering'] == -1:
|
|
if abs(self.steering_increment_1) < 0.2:
|
|
self.steering_increment_1 = 0
|
|
|
|
if self.steering_increment_1 > 0.25:
|
|
self.steering_increment_1 -= 0.25
|
|
|
|
if self.steering_increment_1 < -0.25:
|
|
self.steering_increment_1 += 0.25
|
|
|
|
if input_context['glide'] == 1:
|
|
self.steering_increment_1 = 0
|
|
|
|
# activate front steering
|
|
self.sandboard_1.set_steering_value(self.steering_increment_1, 0)
|
|
self.sandboard_1.set_steering_value(self.steering_increment_1, 1)
|
|
|
|
# activate front and rear power, braking
|
|
for i in range(4):
|
|
self.sandboard_1.apply_engine_force(self.engine_force_1, i)
|
|
self.sandboard_1.set_brake(self.brake_force_1, i)
|
|
|
|
# allow player to pitch the board in midair
|
|
if self.vehicle_node.get_p() < 30:
|
|
if input_context['pitchup']:
|
|
torque = Vec3(1500, 0, 0)
|
|
torque = render.get_relative_vector(self.vehicle_node, torque)
|
|
self.vehicle_node.node().apply_torque(torque)
|
|
|
|
# stabilize the board 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)
|
|
|
|
# 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.5:
|
|
torque = Vec3(0, 0, 3000)
|
|
torque = render.get_relative_vector(self.vehicle_node, torque)
|
|
self.vehicle_node.node().apply_torque(torque)
|
|
if r_vel > 0.5:
|
|
torque = Vec3(0, 0, -3000)
|
|
torque = render.get_relative_vector(self.vehicle_node, torque)
|
|
self.vehicle_node.node().apply_torque(torque)
|
|
|
|
if self.is_on_ground():
|
|
# stabilize the board 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)
|
|
|
|
# reset the board if it turns upside down
|
|
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())
|
|
|
|
if not self.is_on_ground():
|
|
# stabilize the board 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)
|
|
vel = self.vehicle_node.node().get_angular_velocity()
|
|
self.vehicle_node.node().set_angular_velocity((vel[0], 0, vel[2]))
|
|
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)
|
|
vel = self.vehicle_node.node().get_angular_velocity()
|
|
self.vehicle_node.node().set_angular_velocity((vel[0], 0, vel[2]))
|
|
|
|
if input_context['glide'] == 1:
|
|
if self.board_speed <= 125:
|
|
force = Vec3(0, 8000, 3000)
|
|
elif self.board_speed > 100:
|
|
force = Vec3(0, 0, 3000)
|
|
# apply the gliding forces
|
|
force = render.get_relative_vector(self.vehicle_node, force)
|
|
self.vehicle_node.node().apply_central_force(force)
|
|
|
|
# allow player to control the heading of the in-flight sandboard
|
|
if input_context['steering'] == 1:
|
|
torque = Vec3(0, 0, -750)
|
|
torque = render.get_relative_vector(self.vehicle_node, torque)
|
|
self.vehicle_node.node().apply_torque(torque)
|
|
elif input_context['steering'] == -1:
|
|
torque = Vec3(0, 0, 750)
|
|
torque = render.get_relative_vector(self.vehicle_node, torque)
|
|
self.vehicle_node.node().apply_torque(torque)
|
|
else:
|
|
torque = Vec3(0, 0, 0)
|
|
torque = render.get_relative_vector(self.vehicle_node, torque)
|
|
self.vehicle_node.node().apply_torque(torque)
|
|
|
|
def is_on_ground(self):
|
|
v_pos = self.vehicle_node.get_pos()
|
|
pos_1 = Vec3(v_pos[0], v_pos[1], v_pos[2] - 0.5)
|
|
pos_2 = Vec3(v_pos[0], v_pos[1], v_pos[2] - 2)
|
|
truth = self.collider_data(pos_1, pos_2)[3]
|
|
|
|
if 'sandboard_1' in str(truth):
|
|
return False
|
|
|
|
else:
|
|
return truth
|
|
|
|
def has_coin(self):
|
|
v_pos = self.vehicle_node.get_pos()
|
|
pos_1 = Vec3(v_pos[0], v_pos[1], v_pos[2])
|
|
pos_2 = Vec3(v_pos[0], v_pos[1] + 4, v_pos[2])
|
|
truth = self.collider_data(pos_1, pos_2)[3]
|
|
|
|
if 'silver' in str(truth):
|
|
t_str = str(truth).split(' ')
|
|
np = t_str[1]
|
|
target = render.find('**/' + np)
|
|
t_pos = target.get_pos(render)
|
|
t_pos = (round(t_pos[0], 1), round(t_pos[1], 1), round(t_pos[2], 1))
|
|
target.get_parent().detach_node()
|
|
self.bullet_world.remove(truth)
|
|
|
|
reward = randint(35000, 60000)
|
|
self.total_money += reward
|
|
money_np = aspect2d.find('**/money_info')
|
|
money_np.node().set_text('Money: ' + str(self.total_money) + ' credits')
|
|
|
|
success_np = aspect2d.find('**/success_info')
|
|
success_np.node().set_text('Congrats!' + '\n\n' + 'You found resources for the city ship!' + '\n\n' + 'The city ship will now explore area: ' + str(t_pos) + '\n\n' + 'You made ' + str(reward) + ' ' + 'credits!')
|
|
|
|
self.total_coins += 1
|
|
|
|
if self.total_coins > 7:
|
|
if success_np.is_hidden():
|
|
success_np.show()
|
|
|
|
success_np.node().set_text('Congratulations, you have just beat Sandastray!' + '\n\n' + 'Total Earnings: ' + str(self.total_money))
|
|
|
|
if 'gold' in str(truth):
|
|
t_str = str(truth).split(' ')
|
|
np = t_str[1]
|
|
target = render.find('**/' + np)
|
|
t_pos = target.get_pos(render)
|
|
t_pos = (round(t_pos[0], 1), round(t_pos[1], 1), round(t_pos[2], 1))
|
|
target.get_parent().detach_node()
|
|
self.bullet_world.remove(truth)
|
|
|
|
reward = randint(65000, 120000)
|
|
self.total_money += reward
|
|
money_np = aspect2d.find('**/money_info')
|
|
money_np.node().set_text('Money: ' + str(self.total_money) + ' credits')
|
|
|
|
success_np = aspect2d.find('**/success_info')
|
|
success_np.node().set_text('Congrats!' + '\n\n' + 'You found resources for the city ship!' + '\n\n' + 'The city ship will now explore area: ' + str(t_pos) + '\n\n' + 'You made ' + str(reward) + ' ' + 'credits!')
|
|
|
|
self.total_coins += 1
|
|
|
|
if self.total_coins > 7:
|
|
if success_np.is_hidden():
|
|
success_np.show()
|
|
|
|
success_np.node().set_text('Congratulations, you have just beat Sandastray!' + '\n\n' + 'Total Earnings: ' + str(self.total_money))
|
|
|
|
def update(self, task):
|
|
dt = base.clock.get_dt()
|
|
if self.in_focus: # quick HACK to disable input when not in focus!.
|
|
self.sandboard_phys()
|
|
return task.cont
|
|
|
|
# get
|
|
@property
|
|
def b_speed(self):
|
|
return self.board_speed
|
|
|