thanks for answer. You are right, own position integration is not needed. Now i'm overriding only velocity integration. But collision (especially response) doesn't look too much realistic - most of collisions simply stop vehicle body on static obstacle without bounce or any nice response, any hint please?
Code: Select all
import time
from inge import *
from utils import *
import pymunk as pm
def sign(v):
if v < 0: return -1
if v > 0: return 1
return 0
def collisionStarted(space, arbiter, car):
#car.object_hit = True #True
#print("Collision started", car.body.velocity * dt, car.vel)
return True
def collisionSeparated(space, arbiter, car):
#car.object_hit = False
print("Objects separated")
return True
def update_pymunk_velocity(body, gravity, damping, dt):
# if car.object_hit:
# print('gravity: %s, damping: %s, body.velocity: %s, ang: %s'
# % (gravity, damping, body.velocity * dt, body.angular_velocity * dt))
# pm.Body.update_velocity(body, gravity, damping, dt)
# print(' ----> %s, ang: %s' % (body.velocity * dt, body.angular_velocity * dt))
# car.object_hit = False
# else:
# print('car -> body')
body.velocity = (car.vel.x / dt, car.vel.y / dt)
body.angular_velocity = car.angular_vel / dt
class Camera:
def __init__(self):
self.prev_rot = 0
self.rot = 0
self.rotate = False
self.rot_speed = 1
def update(self, car):
self.prev_rot = self.rot
forwangle = -car.rot + math.pi * 0.5
self.rot = lerp(self.rot, forwangle, dt * self.rot_speed)
def modelview(self, car, visual_interpolation):
if self.rotate:
angle = lerp(self.prev_rot, self.rot, visual_interpolation)
else:
angle = 0
return Quat.rotation_z(angle).to_mat4() * Mat4.translation(-car.visual_pos(visual_interpolation))
class Obstacle:
def __init__(self, dim):
self.dim = dim
self.color = Vec4(1, 1, 1, 0.5)
# for pymunk
self.body = pm.Body() # no params -> static body
self.body.position = (self.dim.min.x + (self.dim.w() / 2), self.dim.min.y + self.dim.h() / 2)
self.shape = pm.Poly.create_box(self.body, (self.dim.w(), self.dim.h()))
self.shape.friction = 0.2
self.elasticity = 1.0
def draw(self):
draw.rectangle(self.dim, self.color)
class Car:
def __init__(self, tex_filename, dim):
# konfigurovatelne hodnoty:
self.accel = 0.006
self.steer_speed = 0.04
self.drift = 0.98
self.traction_min = 1
self.traction_max = 50
self.traction_rate = 1.05
self.speed_max = 0.6
self.speed_min = -0.3
self.speed_slide = 0.2
self.steering_curve = EnvCurve(0.15, 0.75, 0.4, 0.5, 0.5, 1)
self.mass = 1.0
self.moment = pm.moment_for_box(self.mass, dim.x, dim.y)
self.body = pm.Body(self.mass, self.moment)
self.shape = pm.Poly.create_box(self.body, (dim.x,dim.y))
self.shape.friction = 0.8 #61
self.shape.elasticity = 1.0
self.shape.collision_type = 1
#self.separation_time = time.time()
self.body.velocity_func = update_pymunk_velocity
#self.object_hit = False
self.mesh = Mesh.textured_rectangle(Rect.xywh(-dim.x * 0.5, -dim.y * 0.5, dim.x, dim.y))
self.efx = Effect.default2d(texture0 = load_texture(tex_filename).id)
self.reset(Vec2(), 0)
def reset(self, pos, rot):
self.pos = pos.copy()
self.rot = rot
self.traction = self.traction_min
self.speed = 0
self.vel = Vec2()
self.reset_movement()
self.angular_vel = 0
self.body.position = (self.pos.x, self.pos.y)
self.body.angle = self.rot
def update(self):
self.pos = Vec2(self.body.position[0], self.body.position[1])
self.vel = Vec2(self.body.velocity[0], self.body.velocity[1]) * dt
self.rot = self.body.angle
self.speed = self.vel.length() * sign(self.speed)
if key_down(KEY_LEFT) or key_down(KEY_RIGHT):
if self.speed > self.speed_slide:
self.traction = min(self.traction_max, self.traction * self.traction_rate)
else:
self.traction = max(self.traction_min, self.traction / self.traction_rate)
self.angular_vel = self.steer_speed * self.steering_curve.evaluate(abs(self.speed) / self.speed_max) * sign(self.speed)
if key_down(KEY_RIGHT): self.angular_vel = -self.angular_vel
#self.rot += self.angular_vel
else:
self.angular_vel = 0
self.traction = max(self.traction_min, self.traction / self.traction_rate)
if key_down(KEY_UP):
self.speed = min(self.speed + self.accel, self.speed_max)
elif key_down(KEY_DOWN):
self.speed = max(self.speed - self.accel, self.speed_min)
else:
self.speed *= self.drift
self.traction = max(self.traction_min, self.traction / self.traction_rate)
self.vel.x += ((math.cos(self.rot) * self.speed) - self.vel.x) / self.traction
self.vel.y += ((math.sin(self.rot) * self.speed) - self.vel.y) / self.traction
#self.pos += self.vel
def reset_movement(self):
self.prev_pos = self.pos.copy()
self.prev_rot = self.rot
def visual_pos(self, visual_interpolation):
v = self.prev_pos.lerp(self.pos, visual_interpolation)
return Vec3(v.x, v.y, 0)
def visual_rot(self, visual_interpolation):
return lerp(self.prev_rot, self.rot, visual_interpolation)
def draw(self, visual_interpolation):
self.efx.world = Mat4.translation(self.visual_pos(visual_interpolation)) * Quat.rotation_z(self.visual_rot(visual_interpolation)).to_mat4()
gfx_render(self.efx, self.mesh)
def draw_all(visual_interpolation):
gfx_clear(COLOR_BUFFER | DEPTH_BUFFER)
w = 50
h = w * window_h() / window_w()
gfx_projection(Mat4.ortho(-w, w, -h, h, -1, 1))
gfx_modelview(camera.modelview(car, visual_interpolation))
render_road(wired = False)
car.draw(visual_interpolation)
for obstacle in obstacles: obstacle.draw()
gfx_projection(Mat4.ortho(0, viewport_w(), viewport_h(), 0, -1, 1))
gfx_modelview(Mat4())
draw.text(0, viewport_h() - font_h() * 3, 'speed: %.3f' % car.speed)
draw.text(0, viewport_h() - font_h() * 2, 'traction: %.3f' % car.traction)
draw.text(0, viewport_h() - font_h(), 'real speed: %.3f' % car.vel.length())
gfx_swap()
fps.trigger()
def update():
car.reset_movement()
car.update()
camera.update(car)
if key_down(KEY_ESC) or not window_opened(): quit()
poll_window_events()
space = pm.Space()
space.gravity = (0.0, 0.0)
#space.damping = 1.0 # 0.8 = 20% ztraty rychlosti / s
open_window(800, 600, False, False, 0)
obstacles = [Obstacle(Rect.xyxy(-140, 60, -150, 90)),
Obstacle(Rect.xyxy(-90, 60, -100, 70)),
Obstacle(Rect.xyxy(-130, 80, -100, 130)),
Obstacle(Rect.xyxy(-300, -10, 300, 10))]
for obstacle in obstacles:
space.add(obstacle.shape)
car = Car('car1_body_red.png|nomips', Vec2(4.3, 1.8))
space.add(car.body, car.shape)
space.add_collision_handler(1, 0, begin=collisionStarted, pre_solve=None,
post_solve=None, separate=collisionSeparated, car=car)
camera = Camera()
load_track('track1.json', car)
dt = 1 / 60
accumulator = 0
while 1:
update_frame_time()
accumulator += frame_dt()
while accumulator >= dt:
accumulator -= dt
update()
print('step')
space.step(dt)
print('-' * 30)
draw_all(accumulator / dt)