logo

libbulletml

Library of Bullet Markup Language (forked from https://shinh.skr.jp/libbulletml/index_en.html )git clone https://hacktivis.me/git/libbulletml.git

bulletmlrunnerimpl.cpp (12975B)


  1. #include "bulletmlrunnerimpl.h"
  2. #include "bulletmlrunner.h"
  3. #include "bulletmlparser.h"
  4. #include "bulletmlerror.h"
  5. #include "formula-variables.h"
  6. #include "auto_ptr_fix.h"
  7. #include <cassert>
  8. #include <cmath>
  9. BulletMLRunnerImpl::Method
  10. BulletMLRunnerImpl::commandMap_[BulletMLNode::nameSize] = {
  11. &BulletMLRunnerImpl::runBullet,
  12. &BulletMLRunnerImpl::runAction,
  13. &BulletMLRunnerImpl::runFire,
  14. &BulletMLRunnerImpl::runChangeDirection,
  15. &BulletMLRunnerImpl::runChangeSpeed,
  16. &BulletMLRunnerImpl::runAccel,
  17. &BulletMLRunnerImpl::runWait,
  18. &BulletMLRunnerImpl::runRepeat,
  19. &BulletMLRunnerImpl::runBulletRef,
  20. &BulletMLRunnerImpl::runActionRef,
  21. &BulletMLRunnerImpl::runFireRef,
  22. &BulletMLRunnerImpl::runVanish
  23. };
  24. double BulletMLRunnerImpl::getDirection(BulletMLNode* dirNode) {
  25. double dir;
  26. bool isDefault = true;
  27. dir = getNumberContents(dirNode);
  28. if (dirNode->getType() != BulletMLNode::none) {
  29. BulletMLNode::Type type = dirNode->getType();
  30. isDefault = false;
  31. if (type == BulletMLNode::absolute) {
  32. if (bulletml_->isHorizontal()) {
  33. dir -= 90;
  34. }
  35. }
  36. else if (type == BulletMLNode::relative) {
  37. dir += runner_->getBulletDirection();
  38. }
  39. else if (type == BulletMLNode::sequence) {
  40. if (!prevDir_.isValidate()) {
  41. dir = 0;
  42. isDefault = true;
  43. }
  44. else dir += prevDir_;
  45. }
  46. else {
  47. isDefault = true;
  48. }
  49. }
  50. if (isDefault) {
  51. // 明らかに非効率
  52. dir += runner_->getAimDirection();
  53. }
  54. while (dir > 360) dir -= 360;
  55. while (dir < 0) dir += 360;
  56. prevDir_ = dir;
  57. return dir;
  58. }
  59. double BulletMLRunnerImpl::getSpeed(BulletMLNode* spdNode) {
  60. double spd;
  61. spd = getNumberContents(spdNode);
  62. if (spdNode->getType() != BulletMLNode::none) {
  63. BulletMLNode::Type type = spdNode->getType();
  64. if (type == BulletMLNode::relative) {
  65. spd += runner_->getBulletSpeed();
  66. }
  67. else if (type == BulletMLNode::sequence) {
  68. if (!prevSpd_.isValidate()) spd = 1;
  69. else spd += prevSpd_;
  70. }
  71. }
  72. // デフォルトでは何もしない
  73. prevSpd_ = spd;
  74. return spd;
  75. }
  76. BulletMLRunnerImpl::BulletMLRunnerImpl(BulletMLState* state,
  77. BulletMLRunner* runner)
  78. : bulletml_(state->getBulletML()),
  79. node_(state->getNode().begin(), state->getNode().end()),
  80. actIte_(0), end_(false), runner_(runner)
  81. {
  82. if (state->getParameter().get() != 0) {
  83. parameters_ = state->getParameter();
  84. }
  85. delete state;
  86. for (std::vector<BulletMLNode*>::iterator ite = node_.begin(); ite != node_.end(); ++ite) {
  87. (*ite)->setParent(0);
  88. }
  89. /*
  90. std::for_each(node_.begin(), node_.end(),
  91. std::bind2nd(std::mem_fun(&BulletMLNode::setParent), 0));
  92. */
  93. actTurn_ = -1;
  94. act_ = node_[0];
  95. }
  96. BulletMLRunnerImpl::~BulletMLRunnerImpl() {}
  97. double BulletMLRunnerImpl::getNumberContents(const BulletMLNode* node) {
  98. assert(node);
  99. Variables::rank = runner_->getRank();
  100. Variables::parameters = parameters_.get();
  101. Variables::runner = runner_;
  102. return node->getValue();
  103. }
  104. void BulletMLRunnerImpl::setSpeed() {
  105. BulletMLNode* spd = act_->getChild(BulletMLNode::speed);
  106. if (spd == 0) return;
  107. spd_ = getSpeed(spd);
  108. }
  109. void BulletMLRunnerImpl::setDirection() {
  110. BulletMLNode* dir = act_->getChild(BulletMLNode::direction);
  111. if (dir == 0) return;
  112. dir_ = getDirection(dir);
  113. }
  114. bool BulletMLRunnerImpl::isTurnEnd() {
  115. return isEnd() || actTurn_ > endTurn_;
  116. }
  117. void BulletMLRunnerImpl::doWait(int frame) {
  118. if (frame <= 0) return;
  119. actTurn_ += frame;
  120. }
  121. void BulletMLRunnerImpl::changes() {
  122. int now = runner_->getTurn();
  123. if (changeDir_.get() != 0) {
  124. if (changeDir_->isLast(now)) {
  125. runner_->doChangeDirection(changeDir_->getLast());
  126. delete auto_ptr_release(changeDir_);
  127. }
  128. else {
  129. runner_->doChangeDirection(changeDir_->getValue(now));
  130. }
  131. }
  132. if (changeSpeed_.get() != 0) {
  133. if (changeSpeed_->isLast(now)) {
  134. runner_->doChangeSpeed(changeSpeed_->getLast());
  135. delete auto_ptr_release(changeSpeed_);
  136. }
  137. else {
  138. runner_->doChangeSpeed(changeSpeed_->getValue(now));
  139. }
  140. }
  141. if (accelx_.get() != 0) {
  142. if (accelx_->isLast(now)) {
  143. runner_->doAccelX(accelx_->getLast());
  144. delete auto_ptr_release(accelx_);
  145. }
  146. else {
  147. runner_->doAccelX(accelx_->getValue(now));
  148. }
  149. }
  150. if (accely_.get() != 0) {
  151. if (accely_->isLast(now)) {
  152. runner_->doAccelY(accely_->getLast());
  153. delete auto_ptr_release(accely_);
  154. }
  155. else {
  156. runner_->doAccelY(accely_->getValue(now));
  157. }
  158. }
  159. }
  160. void BulletMLRunnerImpl::runSub() {
  161. // 見たくもないコードだね。
  162. while (act_ != 0 && !isTurnEnd()) {
  163. BulletMLNode* prev = act_;
  164. Method fp = commandMap_[act_->getName()];
  165. (this->*fp)();
  166. // ref から戻る
  167. if (act_ == 0 &&
  168. prev->getParent() != 0 &&
  169. prev->getParent()->getName() == BulletMLNode::bulletml)
  170. {
  171. assert(!refStack_.empty());
  172. prev = refStack_.top().first;
  173. parameters_ = refStack_.top().second;
  174. refStack_.pop();
  175. }
  176. // 次の node を探す
  177. if (act_ == 0) act_ = prev->next();
  178. // 上に遡って次の node を探す
  179. while (act_ == 0) {
  180. if (prev->getParent() != 0 &&
  181. prev->getParent()->getName() == BulletMLNode::repeat)
  182. {
  183. RepeatElem* rep = repeatStack_.top();
  184. rep->ite++;
  185. if (rep->ite < rep->end) {
  186. act_ = rep->act;
  187. break;
  188. }
  189. else {
  190. delete rep;
  191. repeatStack_.pop();
  192. }
  193. }
  194. act_ = prev->getParent();
  195. if (act_ == 0) break;
  196. prev = act_;
  197. if (prev->getParent() != 0 &&
  198. prev->getParent()->getName() == BulletMLNode::bulletml)
  199. {
  200. assert(!refStack_.empty());
  201. prev = act_ = refStack_.top().first;
  202. parameters_ = refStack_.top().second;
  203. refStack_.pop();
  204. }
  205. act_ = act_->next();
  206. }
  207. }
  208. }
  209. void BulletMLRunnerImpl::run() {
  210. if (isEnd()) return;
  211. changes();
  212. endTurn_ = runner_->getTurn();
  213. // 最後の wait, change系を待つだけ
  214. if (act_ == 0) {
  215. if (!isTurnEnd()) {
  216. if (changeDir_.get() == 0 && changeSpeed_.get() == 0 &&
  217. accelx_.get() == 0 && accely_.get() == 0)
  218. {
  219. end_ = true;
  220. }
  221. }
  222. return;
  223. }
  224. act_ = node_[actIte_];
  225. if (actTurn_ == -1) actTurn_ = runner_->getTurn();
  226. runSub();
  227. if (act_ == 0) {
  228. actIte_++;
  229. if (node_.size() != actIte_) act_ = node_[actIte_];
  230. }
  231. else {
  232. node_[actIte_] = act_;
  233. }
  234. }
  235. void BulletMLRunnerImpl::runBullet() {
  236. setSpeed();
  237. setDirection();
  238. if (!spd_.isValidate()) {
  239. prevSpd_ = spd_ = runner_->getDefaultSpeed();
  240. }
  241. if (!dir_.isValidate()) {
  242. prevDir_ = dir_ = runner_->getAimDirection();
  243. }
  244. if (act_->getChild(BulletMLNode::action) == 0 &&
  245. act_->getChild(BulletMLNode::actionRef) == 0) {
  246. runner_->createSimpleBullet(dir_, spd_);
  247. }
  248. else {
  249. std::vector<BulletMLNode*> acts;
  250. act_->getAllChildrenVec(BulletMLNode::action, acts);
  251. act_->getAllChildrenVec(BulletMLNode::actionRef, acts);
  252. /*
  253. act_->getAllChildren(BulletMLNode::action, std::back_inserter(acts));
  254. act_->getAllChildren(BulletMLNode::actionRef,
  255. std::back_inserter(acts));
  256. */
  257. BulletMLState* state = new BulletMLState(bulletml_, acts, parameters_);
  258. runner_->createBullet(state, dir_, spd_);
  259. }
  260. act_ = 0;
  261. }
  262. void BulletMLRunnerImpl::runFire() {
  263. shotInit();
  264. setSpeed();
  265. setDirection();
  266. BulletMLNode* bullet = act_->getChild(BulletMLNode::bullet);
  267. if (bullet == 0) bullet = act_->getChild(BulletMLNode::bulletRef);
  268. BulletMLError::doAssert(bullet != 0,
  269. "<fire> must have contents bullet or bulletRef");
  270. act_ = bullet;
  271. }
  272. void BulletMLRunnerImpl::runAction() {
  273. if (act_->childSize() == 0) act_ = 0;
  274. else act_ = *act_->childBegin();
  275. }
  276. void BulletMLRunnerImpl::runWait() {
  277. int frame = static_cast<int>(getNumberContents(act_));
  278. doWait(frame);
  279. act_ = 0;
  280. }
  281. void BulletMLRunnerImpl::runRepeat() {
  282. const BulletMLNode* times = act_->getChild(BulletMLNode::times);
  283. if (times == 0) return;
  284. int timesNum = static_cast<int>(getNumberContents(times));
  285. BulletMLNode* action = act_->getChild(BulletMLNode::action);
  286. if (action == 0) action = act_->getChild(BulletMLNode::actionRef);
  287. BulletMLError::doAssert(
  288. action != 0,
  289. "repeat elem must have contents action or actionRef");
  290. repeatStack_.push(new RepeatElem(0, timesNum, action));
  291. act_ = action;
  292. }
  293. void BulletMLRunnerImpl::runFireRef() {
  294. std::shared_ptr<Parameters> prevPara = parameters_;
  295. parameters_.reset(getParameters());
  296. refStack_.push(std::make_pair(act_, prevPara));
  297. act_ = bulletml_->getFireRef(act_->getRefID());
  298. }
  299. void BulletMLRunnerImpl::runActionRef() {
  300. std::shared_ptr<Parameters> prevPara = parameters_;
  301. parameters_.reset(getParameters());
  302. refStack_.push(std::make_pair(act_, prevPara));
  303. act_ = bulletml_->getActionRef(act_->getRefID());
  304. }
  305. void BulletMLRunnerImpl::runBulletRef() {
  306. std::shared_ptr<Parameters> prevPara = parameters_;
  307. parameters_.reset(getParameters());
  308. refStack_.push(std::make_pair(act_, prevPara));
  309. act_ = bulletml_->getBulletRef(act_->getRefID());
  310. }
  311. void BulletMLRunnerImpl::runChangeDirection() {
  312. int term = static_cast<int>(getNumberContents(
  313. act_->getChild(BulletMLNode::term)));
  314. BulletMLNode* dirNode = act_->getChild(BulletMLNode::direction);
  315. BulletMLNode::Type type = dirNode->getType();
  316. double dir;
  317. if (type != BulletMLNode::sequence) dir = getDirection(dirNode);
  318. else dir = getNumberContents(dirNode);
  319. calcChangeDirection(dir, term, type == BulletMLNode::sequence);
  320. act_ = 0;
  321. }
  322. void BulletMLRunnerImpl::runChangeSpeed() {
  323. int term = static_cast<int>(getNumberContents(
  324. act_->getChild(BulletMLNode::term)));
  325. BulletMLNode* spdNode = act_->getChild(BulletMLNode::speed);
  326. BulletMLNode::Type type = spdNode->getType();
  327. double spd;
  328. if (type != BulletMLNode::sequence) spd = getSpeed(spdNode);
  329. else {
  330. spd = getNumberContents(spdNode) * (double)term
  331. + runner_->getBulletSpeed();
  332. }
  333. calcChangeSpeed(spd, term);
  334. act_ = 0;
  335. }
  336. void BulletMLRunnerImpl::runAccel() {
  337. int term = static_cast<int>(getNumberContents(
  338. act_->getChild(BulletMLNode::term)));
  339. BulletMLNode* hnode = act_->getChild(BulletMLNode::horizontal);
  340. BulletMLNode* vnode = act_->getChild(BulletMLNode::vertical);
  341. if (bulletml_->isHorizontal()) {
  342. if (vnode != 0) calcAccelX(getNumberContents(vnode), term,
  343. vnode->getType());
  344. if (hnode != 0) calcAccelY(-getNumberContents(hnode), term,
  345. hnode->getType());
  346. }
  347. else {
  348. if (hnode != 0) calcAccelX(getNumberContents(hnode), term,
  349. hnode->getType());
  350. if (vnode != 0) calcAccelY(getNumberContents(vnode), term,
  351. vnode->getType());
  352. }
  353. act_ = 0;
  354. }
  355. void BulletMLRunnerImpl::calcChangeDirection(double direction, int term,
  356. bool seq)
  357. {
  358. int finalTurn = actTurn_ + term;
  359. double dirFirst = runner_->getBulletDirection();
  360. if (seq) {
  361. auto_ptr_copy(changeDir_, new LinearFunc<int, double>
  362. (actTurn_, finalTurn,
  363. dirFirst, dirFirst + direction * term));
  364. }
  365. else {
  366. double dirSpace;
  367. // ちゃんと近い方を回っていくのは結構難しいね
  368. double dirSpace1 = direction - dirFirst;
  369. double dirSpace2;
  370. if (dirSpace1 > 0) dirSpace2 = dirSpace1 - 360;
  371. else dirSpace2 = dirSpace1 + 360;
  372. if (fabs(dirSpace1) < fabs(dirSpace2)) dirSpace = dirSpace1;
  373. else dirSpace = dirSpace2;
  374. auto_ptr_copy(changeDir_, new LinearFunc<int, double>
  375. (actTurn_, finalTurn, dirFirst, dirFirst + dirSpace));
  376. }
  377. }
  378. void BulletMLRunnerImpl::calcChangeSpeed(double speed, int term) {
  379. int finalTurn = actTurn_ + term;
  380. double spdFirst = runner_->getBulletSpeed();
  381. auto_ptr_copy(changeSpeed_, new LinearFunc<int, double>
  382. (actTurn_, finalTurn, spdFirst, speed));
  383. }
  384. void BulletMLRunnerImpl::calcAccelY(double horizontal, int term,
  385. BulletMLNode::Type type)
  386. {
  387. int finalTurn = actTurn_ + term;
  388. double firstSpd = runner_->getBulletSpeedY();
  389. double finalSpd;
  390. if (type == BulletMLNode::sequence) {
  391. finalSpd = firstSpd + horizontal * term;
  392. }
  393. else if (type == BulletMLNode::relative) {
  394. finalSpd = firstSpd + horizontal;
  395. }
  396. else {
  397. finalSpd = horizontal;
  398. }
  399. auto_ptr_copy(accely_, new LinearFunc<int, double>
  400. (actTurn_, finalTurn, firstSpd, finalSpd));
  401. }
  402. void BulletMLRunnerImpl::calcAccelX(double vertical, int term,
  403. BulletMLNode::Type type)
  404. {
  405. int finalTurn = actTurn_ + term;
  406. double firstSpd = runner_->getBulletSpeedX();
  407. double finalSpd;
  408. if (type == BulletMLNode::sequence) {
  409. finalSpd = firstSpd + vertical * term;
  410. }
  411. else if (type == BulletMLNode::relative) {
  412. finalSpd = firstSpd + vertical;
  413. }
  414. else {
  415. finalSpd = vertical;
  416. }
  417. auto_ptr_copy(accelx_ ,new LinearFunc<int, double>
  418. (actTurn_, finalTurn, firstSpd, finalSpd));
  419. }
  420. void BulletMLRunnerImpl::runVanish() {
  421. runner_->doVanish();
  422. act_ = 0;
  423. }
  424. BulletMLRunnerImpl::Parameters* BulletMLRunnerImpl::getParameters() {
  425. Parameters* para = 0;
  426. bool first = true;
  427. BulletMLNode::ChildIterator ite;
  428. for (ite = act_->childBegin(); ite != act_->childEnd(); ite++) {
  429. BulletMLNode* node = *ite;
  430. if (node->getName() != BulletMLNode::param) continue;
  431. if (first) {
  432. first = false;
  433. para = new Parameters;
  434. // 0番要素は使わない
  435. para->push_back(0);
  436. }
  437. para->push_back(getNumberContents(node));
  438. }
  439. return para;
  440. }