Shuvit game master repo. http://shuvit.org
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.

StatesCar.py 16KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505
  1. import utils
  2. import bge
  3. import random
  4. from mathutils import Vector
  5. import mathutils
  6. #import math
  7. #====================================
  8. def mark_path(path, y):
  9. iter_ = 0
  10. for x in path:
  11. pm = bge.logic.getCurrentScene().addObject('path_marker', y.obj, 0)
  12. pm.worldPosition = path[iter_]
  13. iter_ += 1
  14. if iter_ == 1:
  15. pm.color = [0,1,0,.4]
  16. if iter_ == (len(path) ):
  17. pm.color = [1,0,0,.4]
  18. if iter_ == (len(path) +1):
  19. pm.color = [1,0,1,.4]
  20. y.path_display.append(pm)
  21. def single_marker(pos, col):
  22. pm = bge.logic.getCurrentScene().addObject('path_marker', None, 0)
  23. pm.worldPosition = pos
  24. pm.color = col
  25. def clear_markers(self):
  26. for x in self.FSM.owner.path_display:
  27. try:
  28. x.endObject()
  29. except:
  30. pass
  31. def get_ground_ray(self):
  32. Axis = 2
  33. Distance = -10
  34. end = self.obj.worldPosition + (self.obj.worldOrientation.col[Axis]*Distance)
  35. start = self.obj.worldPosition.copy()
  36. ground_ray = self.obj.rayCast(end, start, 6,'', 1, 0)
  37. return ground_ray
  38. def set_height(self):
  39. ground_ray = get_ground_ray(self)
  40. target_height = 0.9
  41. hitpoint = ground_ray[1]
  42. try:
  43. dist = self.obj.getDistanceTo(hitpoint)
  44. if dist < target_height:
  45. self.obj.worldPosition.z += target_height - dist
  46. self.obj.linearVelocity.z = 0
  47. self.obj.linearVelocity.y *= .1
  48. except:
  49. pass
  50. def align_to_road(self):
  51. ground_ray = get_ground_ray(self)
  52. try:
  53. self.obj.alignAxisToVect(ground_ray[2], 2, .15)
  54. except:
  55. pass
  56. def find_new_parking(self):
  57. potentials = []
  58. for x in self.manager.parking_spots:
  59. if x.status == 'available':
  60. potentials.append(x)
  61. for x in potentials:
  62. min_dist = 45
  63. dist = self.obj.getDistanceTo(x.obj)
  64. if dist < min_dist:
  65. potentials.remove(x)
  66. if len(potentials) > 0:
  67. new_parking = random.choice(potentials)
  68. path2 = self.manager.navmesh2.queue_path(self.start_empty.obj.worldPosition, new_parking.obj.worldPosition, self)
  69. #print('astar request')
  70. #if path2 is not None:
  71. return new_parking, path2
  72. else:
  73. get_parking_type(self)
  74. #self.FSM.FSM.ToTransition('toEnterParallelPark')
  75. def get_lane_point(self):
  76. self.point = self.path[self.path_index]
  77. if self.point != self.last_lane_point:
  78. v = Vector([self.last_lane_point.x - self.point.x, self.last_lane_point.y - self.point.y, 0])
  79. tv = v.normalized()
  80. nv = Vector([-tv.y, tv.x, 0]) #rotate 90 degrees
  81. self.last_lane_point = self.lane_point
  82. self.lane_point = self.point + self.manager.lane_position * nv
  83. else:
  84. pass
  85. def update_point(self):
  86. if self.path_index >= (len(self.path) ):
  87. get_parking_type(self)
  88. #self.FSM.FSM.ToTransition('toEnterParallelPark')
  89. else:
  90. dist = self.obj.getDistanceTo(self.lane_point)
  91. self.point = self.path[self.path_index]
  92. if dist < 2.5:
  93. get_lane_point(self)
  94. if self.path_index > (len(self.path)):
  95. pass
  96. else:
  97. self.path_index += 1
  98. def align_to_point(self, mult):
  99. v = self.obj.getVectTo(self.lane_point)[1]
  100. v.z = 0
  101. self.obj.alignAxisToVect(v, 0, .05 * mult)
  102. def align_to_target(self, mult):
  103. v = self.obj.getVectTo(self.FSM.FSM.curState.park_loc)[1]
  104. v.z = 0
  105. self.obj.alignAxisToVect(v, 0, .05 * mult)
  106. def delta_to_vect(self):
  107. v = self.obj.getVectTo(self.lane_point)[1]
  108. delta = self.last_lane_point - self.lane_point
  109. delta = delta.cross(v)
  110. delta_mult = -.1
  111. mult = 1.0
  112. deltamove = delta[2] * delta_mult
  113. #check if in front
  114. local = self.obj.worldOrientation.inverted() * (self.lane_point - self.obj.worldPosition)
  115. f = deltamove * 500
  116. if local < 0:
  117. f *= -1
  118. self.obj.applyForce([0, f, 0], True)
  119. def apply_gas(self, mult):
  120. if self.obj.linearVelocity.x < self.speed_targ * mult:
  121. self.obj.applyForce([self.speed_inc * mult, 0, 0], True)
  122. def starting_mod(self):
  123. path2 = self.path
  124. #path2.append(self.target.obj.worldPosition) #add endpoint
  125. #path2.append(self.target.obj.worldPosition)
  126. def check_front(self): #
  127. obj_vec = self.obj.getAxisVect([1,0,0])
  128. targ_vec = self.obj.getVectTo(self.path[self.path_index] +1)[1].normalized()
  129. dot_ = obj_vec.dot(targ_vec)
  130. if dot_ > 0:
  131. print('in front', self)
  132. else:
  133. print('behind', self)
  134. if dot_ > 0:
  135. return True
  136. else:
  137. return False
  138. def get_parking_type(self):
  139. if self.target.type == 'perp':
  140. self.FSM.FSM.ToTransition('toEnterPerpPark')
  141. else:
  142. self.FSM.FSM.ToTransition('toEnterParallelPark')
  143. def get_parking_point(self):
  144. v = Vector([self.last_lane_point.x - self.point.x, self.last_lane_point.y - self.point.y, 0])
  145. tv = v.normalized()
  146. #nv = Vector([-tv.y, tv.x, 0]) #rotate 90 degrees
  147. #self.last_lane_point = self.lane_point
  148. local = Vector([7,0,0])
  149. return Vector(self.target.obj.worldPosition + (self.target.obj.worldOrientation * local))
  150. #return Vector(self.target.obj.worldPosition) - 7 * tv
  151. def move_to_point(self):
  152. #print(self.v_to_target[0])
  153. if self.v_to_target[0] < .95:
  154. #print('reached')
  155. return True
  156. else:
  157. vectTo = Vector(self.v_to_target[1])
  158. vectTo.magnitude = 4.01
  159. self.FSM.owner.obj.linearVelocity = vectTo
  160. return False
  161. def forward_ray(self):
  162. Axis = 0
  163. Distance = 30
  164. End = self.obj.worldPosition + (self.obj.worldOrientation.col[Axis]*Distance)
  165. Start = self.obj.worldPosition.copy()
  166. return self.obj.rayCast(End, Start, 10,'traffic', 1, 0, 0)
  167. #dist = v1[0]
  168. #print(dist)
  169. #====================================
  170. State = type("State", (object,), {})
  171. #====================================
  172. class State(object):
  173. def __init__(self, FSM):
  174. self.FSM = FSM
  175. self.timer = 0
  176. self.startTime = 0
  177. def Enter(self):
  178. self.timer = 0
  179. self.startTime = 0
  180. def Execute(self):
  181. print('Executing')
  182. def Exit(self):
  183. print('Exiting')
  184. #====================================
  185. class Example(State):
  186. def __init__(self,FSM):
  187. super(Example, self).__init__(FSM)
  188. def Enter(self):
  189. self.FSM.stateLife = 1
  190. self.FSM.owner.resumePhysics()
  191. self.FSM.owner.resumeDynamics()
  192. print('physics resumed')
  193. super(Example, self).Enter()
  194. def Execute(self):
  195. self.FSM.stateLife += 1
  196. print('doing example')
  197. def Exit(self):
  198. pass
  199. class ExitParallelPark(State):
  200. def __init__(self,FSM):
  201. super(ExitParallelPark, self).__init__(FSM)
  202. def Enter(self):
  203. self.FSM.stateLife = 1
  204. self.FSM.owner.obj.restorePhysics()
  205. self.FSM.owner.obj.restoreDynamics()
  206. self.FSM.owner.obj.linearVelocity = [0,0,0]
  207. self.FSM.owner.path_index = 1
  208. try:
  209. self.FSM.owner.point = self.FSM.owner.path[self.FSM.owner.path_index]
  210. get_lane_point(self.FSM.owner)
  211. except:
  212. print('no path')
  213. self.FSM.owner.target.status = 'targetted'
  214. self.FSM.owner.start_empty.status = 'available'
  215. starting_mod(self.FSM.owner)
  216. super(ExitParallelPark, self).Enter()
  217. def Execute(self):
  218. self.FSM.stateLife += 1
  219. set_height(self.FSM.owner)
  220. if self.FSM.owner.path != []:
  221. update_point(self.FSM.owner)
  222. #v = self.FSM.owner.obj.getVectTo(self.FSM.owner.path[0])
  223. #v = self.FSM.owner.obj.getVectTo(self.FSM.owner.lane_point)
  224. #print(v[0])
  225. #self.FSM.owner.obj.alignAxisToVect(v[1], 0, .02)
  226. #self.FSM.owner.obj.alignAxisToVect([0,0,1], 2, 1)
  227. #if self.FSM.stateLife > 160 or self.FSM.owner.obj.getDistanceTo(self.FSM.owner.lane_point) < 2:
  228. #if self.FSM.owner.obj.getDistanceTo(self.FSM.owner.path[0]) < 3.5:# or (self.FSM.stateLife > 30 and check_front(self.FSM.owner)):
  229. if self.FSM.owner.path_index > 1:
  230. #print('exiting park')
  231. #self.FSM.owner.path_index = 2
  232. self.FSM.ToTransition('toNavigateToTarget')
  233. align_to_point(self.FSM.owner, .65)
  234. align_to_road(self.FSM.owner)
  235. #set_height(self.FSM.owner)
  236. delta_to_vect(self.FSM.owner)
  237. apply_gas(self.FSM.owner, .5)
  238. #if self.FSM.stateLife < 30:
  239. #self.FSM.owner.obj.applyRotation([0,0,.0075], True)
  240. def Exit(self):
  241. pass
  242. #====================================
  243. class ExitPerpPark(State):
  244. def __init__(self,FSM):
  245. super(ExitPerpPark, self).__init__(FSM)
  246. def Enter(self):
  247. self.FSM.stateLife = 1
  248. self.FSM.owner.obj.restorePhysics()
  249. self.FSM.owner.obj.restoreDynamics()
  250. self.FSM.owner.obj.linearVelocity = [0,0,0]
  251. self.FSM.owner.path_index = 1
  252. try:
  253. self.FSM.owner.point = self.FSM.owner.path[self.FSM.owner.path_index]
  254. get_lane_point(self.FSM.owner)
  255. except:
  256. print('no path')
  257. self.FSM.owner.target.status = 'targetted'
  258. self.FSM.owner.start_empty.status = 'available'
  259. starting_mod(self.FSM.owner)
  260. super(ExitPerpPark, self).Enter()
  261. def Execute(self):
  262. #print('exiting perp park', self.FSM.owner.start_empty.type)
  263. self.FSM.stateLife += 1
  264. set_height(self.FSM.owner)
  265. if self.FSM.owner.path != []:
  266. update_point(self.FSM.owner)
  267. if self.FSM.owner.path_index > 1 or self.FSM.stateLife > 300:
  268. self.FSM.ToTransition('toNavigateToTarget')
  269. #align_to_point(self.FSM.owner, .65)
  270. align_to_road(self.FSM.owner)
  271. #set_height(self.FSM.owner)
  272. #delta_to_vect(self.FSM.owner)
  273. #apply_gas(self.FSM.owner, .5)
  274. if self.FSM.stateLife < 120:
  275. self.FSM.owner.obj.applyForce([-50,0,0], True)
  276. def Exit(self):
  277. pass
  278. #====================================
  279. class EnterParallelPark(State):
  280. def __init__(self,FSM):
  281. super(EnterParallelPark, self).__init__(FSM)
  282. def Enter(self):
  283. self.FSM.stateLife = 1
  284. clear_markers(self)
  285. super(EnterParallelPark, self).Enter()
  286. def cleanup(self):
  287. self.FSM.owner.obj.worldPosition = self.FSM.owner.target.obj.worldPosition.copy()
  288. self.FSM.owner.obj.worldOrientation = self.FSM.owner.target.obj.worldOrientation.copy()
  289. self.FSM.owner.obj.applyMovement([0, -6, 0], True)
  290. self.FSM.owner.target.status = 'in_use'
  291. self.FSM.owner.obj.worldPosition.z += .9
  292. self.FSM.owner.active = False
  293. self.FSM.owner.start_empty = self.FSM.owner.target
  294. self.FSM.owner.last_point = self.FSM.owner.target.obj.worldPosition.copy()
  295. self.FSM.owner.lane_point = self.FSM.owner.target.obj.worldPosition.copy()
  296. self.FSM.owner.last_lane_point = self.FSM.owner.target.obj.worldPosition.copy()
  297. self.FSM.owner.point = self.FSM.owner.target.obj.worldPosition.copy()
  298. self.FSM.owner.path_index = 0
  299. self.FSM.owner.path = None
  300. self.FSM.owner.manager.cars_active.remove(self.FSM.owner)
  301. self.FSM.owner.obj.suspendDynamics()
  302. def Execute(self):
  303. self.FSM.stateLife += 1
  304. if self.FSM.stateLife == 240:
  305. self.cleanup()
  306. #self.FSM.owner.obj.suspendPhysics()
  307. def Exit(self):
  308. pass
  309. class EnterPerpPark(State):
  310. def __init__(self,FSM):
  311. super(EnterPerpPark, self).__init__(FSM)
  312. def Enter(self):
  313. self.FSM.stateLife = 1
  314. self.park_loc = get_parking_point(self.FSM.owner)
  315. single_marker(self.park_loc, [1,0,0,.3])
  316. clear_markers(self)
  317. super(EnterPerpPark, self).Enter()
  318. def cleanup(self):
  319. self.FSM.owner.obj.worldPosition = self.FSM.owner.target.obj.worldPosition.copy()
  320. self.FSM.owner.obj.worldOrientation = self.FSM.owner.target.obj.worldOrientation.copy()
  321. self.FSM.owner.obj.applyMovement([7, 0, 0], True)
  322. self.FSM.owner.target.status = 'in_use'
  323. self.FSM.owner.obj.worldPosition.z += .9
  324. self.FSM.owner.active = False
  325. self.FSM.owner.start_empty = self.FSM.owner.target
  326. self.FSM.owner.last_point = self.FSM.owner.target.obj.worldPosition.copy()
  327. self.FSM.owner.lane_point = self.FSM.owner.target.obj.worldPosition.copy()
  328. self.FSM.owner.last_lane_point = self.FSM.owner.target.obj.worldPosition.copy()
  329. self.FSM.owner.point = self.FSM.owner.target.obj.worldPosition.copy()
  330. self.FSM.owner.path_index = 0
  331. self.FSM.owner.path = None
  332. self.FSM.owner.manager.cars_active.remove(self.FSM.owner)
  333. self.FSM.owner.obj.suspendDynamics()
  334. def Execute(self):
  335. self.FSM.stateLife += 1
  336. self.v_to_target = self.FSM.owner.obj.getVectTo(self.park_loc)
  337. goal_met = move_to_point(self)
  338. set_height(self.FSM.owner)
  339. if self.v_to_target[0] > 2:
  340. align_to_target(self.FSM.owner, .65)
  341. else:
  342. self.FSM.owner.obj.alignAxisToVect(-self.FSM.owner.target.obj.worldOrientation[0], 0, .05)
  343. if self.FSM.stateLife == 440 or goal_met:
  344. self.cleanup()
  345. #self.FSM.owner.obj.suspendPhysics()
  346. def Exit(self):
  347. pass
  348. #====================================
  349. class NavigateToTarget(State):
  350. def __init__(self,FSM):
  351. super(NavigateToTarget, self).__init__(FSM)
  352. def Enter(self):
  353. self.FSM.stateLife = 1
  354. super(NavigateToTarget, self).Enter()
  355. def Execute(self):
  356. self.FSM.stateLife += 1
  357. self.forward_ray = forward_ray(self.FSM.owner)
  358. update_point(self.FSM.owner)
  359. align_to_point(self.FSM.owner, 1)
  360. align_to_road(self.FSM.owner)
  361. set_height(self.FSM.owner)
  362. delta_to_vect(self.FSM.owner)
  363. gas = True
  364. if self.forward_ray[0]:
  365. dist = self.FSM.owner.obj.getDistanceTo(self.forward_ray[1])
  366. if dist < 10:
  367. gas = False
  368. self.FSM.owner.obj.linearVelocity.x *= .98
  369. print(dist, 'forward ray', self.forward_ray[0])
  370. if gas:
  371. apply_gas(self.FSM.owner, 1)
  372. #emergency exit
  373. if self.FSM.stateLife > 30 * 90:
  374. get_parking_type(self.FSM.owner)
  375. #self.FSM.ToTransition('toEnterParallelPark')
  376. def Exit(self):
  377. pass
  378. #====================================
  379. class Activate(State):
  380. def __init__(self,FSM):
  381. super(Activate, self).__init__(FSM)
  382. def Enter(self):
  383. self.FSM.stateLife = 1
  384. super(Activate, self).Enter()
  385. def find_target(self):
  386. pass
  387. def drive_to_point(self):
  388. pass
  389. def Execute(self):
  390. self.FSM.stateLife += 1
  391. def Exit(self):
  392. pass
  393. #====================================
  394. class RequestPath(State):
  395. def __init__(self,FSM):
  396. super(RequestPath, self).__init__(FSM)
  397. def Enter(self):
  398. self.FSM.stateLife = 1
  399. self.FSM.owner.target, self.FSM.owner.path = find_new_parking(self.FSM.owner)
  400. self.FSM.owner.path_index = 0
  401. super(RequestPath, self).Enter()
  402. def Execute(self):
  403. self.FSM.stateLife += 1
  404. def Exit(self):
  405. pass