Não pode escolher mais do que 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.
 
 
 

716 linhas
16 KiB

  1. define([
  2. 'js/resources',
  3. 'js/system/events',
  4. 'js/misc/physics',
  5. 'js/rendering/effects',
  6. 'js/rendering/tileOpacity',
  7. 'js/rendering/particles',
  8. 'js/rendering/shaders/outline'
  9. ], function(
  10. resources,
  11. events,
  12. physics,
  13. effects,
  14. tileOpacity,
  15. particles,
  16. shaderOutline
  17. ) {
  18. var scale = 40;
  19. var scaleMult = 5;
  20. var pixi = PIXI;
  21. return {
  22. stage: null,
  23. layers: {
  24. objects: null,
  25. mobs: null,
  26. characters: null,
  27. attacks: null,
  28. effects: null,
  29. particles: null,
  30. tileSprites: null,
  31. hiders: null
  32. },
  33. chunkSize: 30,
  34. titleScreen: false,
  35. pad: {
  36. x: 10,
  37. y: 10
  38. },
  39. width: 0,
  40. height: 0,
  41. pos: {
  42. x: 0,
  43. y: 0
  44. },
  45. moveTo: null,
  46. moveSpeed: 0,
  47. moveSpeedMax: 1.50,
  48. moveSpeedInc: 0.5,
  49. moveSpeedFlatten: 16,
  50. zoneId: null,
  51. textures: {},
  52. textureCache: {},
  53. lastTick: null,
  54. init: function() {
  55. PIXI.GC_MODES.DEFAULT = PIXI.GC_MODES.AUTO;
  56. PIXI.SCALE_MODES.DEFAULT = PIXI.SCALE_MODES.NEAREST;
  57. events.on('onGetMap', this.onGetMap.bind(this));
  58. events.on('onDeath', this.onDeath.bind(this));
  59. events.on('onToggleFullscreen', this.toggleScreen.bind(this));
  60. this.width = $('body').width();
  61. this.height = $('body').height();
  62. this.pad.x = ~~((this.width / 2) / 32);
  63. this.pad.y = ~~((this.height / 2) / 32);
  64. this.renderer = pixi.autoDetectRenderer(this.width, this.height, {
  65. backgroundColor: 0x2d2136
  66. });
  67. window.onresize = this.onResize.bind(this);
  68. $(this.renderer.view)
  69. .appendTo('.canvasContainer');
  70. this.stage = new pixi.Container();
  71. var layers = this.layers;
  72. Object.keys(layers).forEach(function(l) {
  73. if (l == 'tileSprites') {
  74. layers[l] = new pixi.particles.ParticleContainer(2500);
  75. layers[l].layer = 'tiles';
  76. } else
  77. layers[l] = new pixi.Container();
  78. this.stage.addChild(layers[l])
  79. }, this);
  80. var spriteNames = ['sprites', 'tiles', 'mobs', 'bosses', 'bigObjects', 'objects', 'characters', 'attacks', 'auras', 'walls', 'ui', 'animChar', 'animMob', 'animBoss'];
  81. resources.spriteNames.forEach(function(s) {
  82. if (s.indexOf('.png') > -1)
  83. spriteNames.push(s);
  84. });
  85. spriteNames.forEach(function(t) {
  86. this.textures[t] = new pixi.BaseTexture(resources.sprites[t].image);
  87. this.textures[t].scaleMode = pixi.SCALE_MODES.NEAREST;
  88. }, this);
  89. particles.init({
  90. renderer: this.renderer,
  91. stage: this.layers.particles
  92. });
  93. },
  94. toggleScreen: function() {
  95. var screenMode = 0;
  96. var isFullscreen = (window.innerHeight == screen.height);
  97. if (isFullscreen)
  98. screenMode = 0;
  99. else
  100. screenMode = 1;
  101. if (screenMode == 0) {
  102. (document.cancelFullscreen || document.msCancelFullscreen || document.mozCancelFullscreen || document.webkitCancelFullScreen).call(document);
  103. return 'Windowed';
  104. } else if (screenMode == 1) {
  105. var el = $('body')[0];
  106. (el.requestFullscreen || el.msRequestFullscreen || el.mozRequestFullscreen || el.webkitRequestFullscreen).call(el);
  107. return 'Fullscreen';
  108. }
  109. },
  110. buildTitleScreen: function() {
  111. this.titleScreen = true;
  112. this.setPosition({
  113. x: 0,
  114. y: 0
  115. }, true);
  116. var w = Math.ceil(this.width / scale) + 1;
  117. var h = Math.ceil(this.height / scale) + 1;
  118. var container = this.layers.tileSprites;
  119. for (var i = 0; i < w; i++) {
  120. for (var j = 0; j < h; j++) {
  121. var tile = 5;
  122. if (Math.random() < 0.4)
  123. tile = 6;
  124. var tile = new pixi.Sprite(this.getTexture('sprites', tile));
  125. var alpha = Math.sin((i % 4) + Math.cos(j % 8));
  126. if (tile == 5)
  127. alpha /= 2;
  128. tile.alpha = alpha;
  129. tile.position.x = i * scale;
  130. tile.position.y = j * scale;
  131. tile.width = scale;
  132. tile.height = scale;
  133. if (Math.random() < 0.5) {
  134. tile.position.x += scale;
  135. tile.scale.x = -scaleMult;
  136. }
  137. container.addChild(tile);
  138. }
  139. }
  140. },
  141. onDeath: function(pos) {
  142. this.setPosition({
  143. x: (pos.x - (this.width / (scale * 2))) * scale,
  144. y: (pos.y - (this.height / (scale * 2))) * scale
  145. }, true);
  146. },
  147. onResize: function() {
  148. var zoom = window.devicePixelRatio;
  149. this.width = $('body').width() * zoom;
  150. this.height = $('body').height() * zoom;
  151. this.renderer.resize(this.width, this.height);
  152. if (window.player) {
  153. this.setPosition({
  154. x: (window.player.x - (this.width / (scale * 2))) * scale,
  155. y: (window.player.y - (this.height / (scale * 2))) * scale
  156. }, true);
  157. }
  158. if (this.titleScreen) {
  159. this.clean();
  160. this.buildTitleScreen();
  161. }
  162. events.emit('onResize');
  163. },
  164. getTexture: function(baseTex, cell, size) {
  165. size = size || 8;
  166. var name = baseTex + '_' + cell;
  167. var textureCache = this.textureCache;
  168. var cached = textureCache[name];
  169. if (!cached) {
  170. var y = ~~(cell / 8);
  171. var x = cell - (y * 8);
  172. cached = new pixi.Texture(this.textures[baseTex], new pixi.Rectangle(x * size, y * size, size, size));
  173. textureCache[name] = cached;
  174. }
  175. return cached;
  176. },
  177. clean: function() {
  178. var container = this.layers.tileSprites;
  179. this.stage.removeChild(container);
  180. this.layers.tileSprites = container = new pixi.particles.ParticleContainer(2500);
  181. container.layer = 'tiles';
  182. this.stage.addChild(container);
  183. this.stage.children.sort(function(a, b) {
  184. if (a.layer == 'tiles')
  185. return -1;
  186. else if (b.layer == 'tiles')
  187. return 1;
  188. else
  189. return 0;
  190. }, this);
  191. },
  192. onGetMapCustomization: function(msg) {
  193. if (!msg.collide) {
  194. var children = this.layers.tiles.children;
  195. var cLen = children.length;
  196. var x = msg.x * scale;
  197. var y = msg.y * scale;
  198. for (var i = cLen - 1; i >= 0; i--) {
  199. var c = children[i];
  200. var cx = c.x;
  201. if (c.scale.x < 0)
  202. cx -= scale;
  203. if ((cx == x) && (c.y == y)) {
  204. c.parent.removeChild(c);
  205. break;
  206. }
  207. }
  208. }
  209. var tile = new pixi.Sprite(this.getTexture('sprites', msg.tile))
  210. tile.alpha = tileOpacity.map(msg.tile);
  211. tile.position.x = msg.x * scale;
  212. tile.position.y = msg.y * scale;
  213. tile.width = scale;
  214. tile.height = scale;
  215. if (Math.random() < 0.5) {
  216. tile.position.x += scale;
  217. tile.scale.x = -scaleMult;
  218. }
  219. this.layers.tiles.addChild(tile);
  220. physics.collisionMap[msg.x][msg.y] = msg.collide;
  221. physics.graph.grid[msg.x][msg.y] = !msg.collide;
  222. },
  223. buildTile: function(c, i, j) {
  224. var alpha = tileOpacity.map(c);
  225. var canFlip = tileOpacity.canFlip(c);
  226. var tile = new pixi.Sprite(this.getTexture('sprites', c + (0 * 160)));
  227. tile.alpha = alpha;
  228. tile.position.x = i * 8;
  229. tile.position.y = j * 8;
  230. tile.width = 8;
  231. tile.height = 8;
  232. if (canFlip) {
  233. if (Math.random() < 0.5) {
  234. tile.position.x += 8;
  235. tile.scale.x = -1;
  236. }
  237. }
  238. return tile;
  239. },
  240. onGetMap: function(msg) {
  241. this.titleScreen = false;
  242. physics.init(msg.collisionMap);
  243. var map = msg.map;
  244. var w = this.w = map.length;
  245. var h = this.h = map[0].length;
  246. var hiddenWalls = msg.hiddenWalls;
  247. var hiddenTiles = msg.hiddenTiles;
  248. this.hiddenRooms = msg.hiddenRooms;
  249. this.hiddenRooms.forEach(function(h) {
  250. h.container = new pixi.Container();
  251. this.layers.hiders.addChild(h.container);
  252. this.buildRectangle({
  253. x: h.x * scale,
  254. y: h.y * scale,
  255. w: h.width * scale,
  256. h: h.height * scale,
  257. color: 0x2d2136,
  258. parent: h.container
  259. });
  260. for (var i = h.x; i < h.x + h.width; i++) {
  261. for (var j = h.y; j < h.y + h.height; j++) {
  262. var cell = hiddenTiles[i][j];
  263. if (cell != 0) {
  264. var tile = this.buildTile(cell - 1, i, j);
  265. tile.position.x *= scaleMult;
  266. tile.position.y *= scaleMult;
  267. tile.width = scale;
  268. tile.height = scale;
  269. h.container.addChild(tile);
  270. }
  271. cell = hiddenWalls[i][j];
  272. if (cell == 0)
  273. continue;
  274. var tile = this.buildTile(cell - 1, i, j);
  275. tile.position.x *= scaleMult;
  276. tile.position.y *= scaleMult;
  277. tile.width = scale;
  278. tile.height = scale;
  279. h.container.addChild(tile);
  280. }
  281. }
  282. }, this);
  283. var padding = msg.padding ? JSON.parse(msg.padding) : {};
  284. this.clean();
  285. var container = new pixi.particles.ParticleContainer(270000);
  286. var isPadX = false;
  287. var isPadY = false;
  288. var padX = 0;
  289. var padY = 0;
  290. if (!msg.padding) {
  291. padX = 0;
  292. padY = 0;
  293. }
  294. var chunkSize = this.chunkSize;
  295. for (var i = -padX; i < w + padX; i++) {
  296. if ((i < 0) || (i >= w))
  297. isPadX = true;
  298. else
  299. isPadX = false;
  300. for (var j = -padY; j < h + padY; j++) {
  301. if ((j < 0) || (j >= h))
  302. isPadY = true;
  303. else
  304. isPadY = false;
  305. var cell = null;
  306. cell = map[i][j];
  307. if (!cell)
  308. continue;
  309. if (!cell.split)
  310. cell += '';
  311. cell = cell.split(',');
  312. for (var k = 0; k < cell.length; k++) {
  313. var c = cell[k];
  314. if (c == 0)
  315. continue;
  316. c--;
  317. var tile = this.buildTile(c, i, j);
  318. container.addChild(tile);
  319. }
  320. }
  321. }
  322. var renderTexture = pixi.RenderTexture.create(w * 8, h * 8);
  323. this.renderer.render(container, renderTexture);
  324. var cw = w / this.chunkSize;
  325. var ch = h / this.chunkSize;
  326. for (var i = 0; i < cw; i++) {
  327. var tw = Math.min(this.chunkSize, w - (i * chunkSize));
  328. for (var j = 0; j < ch; j++) {
  329. var th = Math.min(this.chunkSize, h - (j * chunkSize));
  330. var texture = new pixi.Texture(renderTexture, new pixi.Rectangle(i * this.chunkSize * 8, j * this.chunkSize * 8, tw * 8, th * 8));
  331. var sprite = new pixi.Sprite(texture);
  332. sprite.position.x = i * this.chunkSize * scale;
  333. sprite.position.y = j * this.chunkSize * scale;
  334. sprite.width = tw * scale;
  335. sprite.height = th * scale;
  336. this.layers.tileSprites.addChild(sprite);
  337. }
  338. }
  339. this.stage.children.sort(function(a, b) {
  340. if (a.layer == 'tiles')
  341. return -1;
  342. else if (b.layer == 'tiles')
  343. return 1;
  344. else
  345. return 0;
  346. }, this);
  347. if (this.zoneId != null)
  348. events.emit('onRezone', this.zoneId);
  349. this.zoneId = msg.zoneId;
  350. msg.clientObjects.forEach(function(c) {
  351. c.zoneId = this.zoneId;
  352. events.emit('onGetObject', c);
  353. }, this);
  354. },
  355. setPosition: function(pos, instant) {
  356. pos.x += 16;
  357. pos.y += 16;
  358. this.hideHiders();
  359. if (instant) {
  360. this.moveTo = null;
  361. this.pos = pos;
  362. this.stage.x = -~~this.pos.x;
  363. this.stage.y = -~~this.pos.y;
  364. return;
  365. }
  366. this.moveTo = pos;
  367. },
  368. hideHiders: function() {
  369. var player = window.player;
  370. if (!player)
  371. return;
  372. var x = player.x;
  373. var y = player.y;
  374. var hiddenRooms = this.hiddenRooms;
  375. var hLen = hiddenRooms.length;
  376. for (var i = 0; i < hLen; i++) {
  377. var h = hiddenRooms[i];
  378. h.container.visible = (
  379. (x < h.x) ||
  380. (x >= h.x + h.width) ||
  381. (y < h.y) ||
  382. (y >= h.y + h.height)
  383. );
  384. }
  385. },
  386. update: function() {
  387. var time = +new Date;
  388. if (this.moveTo) {
  389. var deltaX = this.moveTo.x - this.pos.x;
  390. var deltaY = this.moveTo.y - this.pos.y;
  391. if ((deltaX != 0) || (deltaY != 0)) {
  392. var moveSpeed = this.moveSpeed;
  393. var distance = Math.max(Math.abs(deltaX), Math.abs(deltaY));
  394. var moveSpeedMax = this.moveSpeedMax;
  395. if (distance > 100)
  396. moveSpeedMax *= 1.75;
  397. if (this.moveSpeed < moveSpeedMax)
  398. this.moveSpeed += this.moveSpeedInc;
  399. var elapsed = time - this.lastTick;
  400. moveSpeed *= (elapsed / 16.67);
  401. if (moveSpeed > distance)
  402. moveSpeed = distance;
  403. deltaX = (deltaX / distance) * moveSpeed;
  404. deltaY = (deltaY / distance) * moveSpeed;
  405. this.pos.x = this.pos.x + (deltaX);
  406. this.pos.y = this.pos.y + (deltaY);
  407. } else {
  408. this.moveSpeed = 0;
  409. this.moveTo = null;
  410. }
  411. this.stage.x = -~~this.pos.x;
  412. this.stage.y = -~~this.pos.y;
  413. events.emit('onSceneMove');
  414. }
  415. this.lastTick = time;
  416. },
  417. buildContainer: function(obj) {
  418. var container = new pixi.Container;
  419. this.layers[obj.layerName || obj.sheetName].addChild(container);
  420. return container;
  421. },
  422. buildRectangle: function(obj) {
  423. var graphics = new pixi.Graphics;
  424. var alpha = obj.alpha;
  425. if (alpha != null)
  426. graphics.alpha = alpha;
  427. var fillAlpha = obj.fillAlpha;
  428. if (fillAlpha == null)
  429. fillAlpha = 1;
  430. graphics.beginFill(obj.color || '0x48edff', fillAlpha);
  431. if (obj.strokeColor)
  432. graphics.lineStyle(scaleMult, obj.strokeColor);
  433. graphics.moveTo(obj.x, obj.y);
  434. graphics.lineTo(obj.x + obj.w, obj.y);
  435. graphics.lineTo(obj.x + obj.w, obj.y + obj.h);
  436. graphics.lineTo(obj.x, obj.y + obj.h);
  437. graphics.lineTo(obj.x, obj.y);
  438. graphics.endFill();
  439. (obj.parent || this.layers[obj.layerName || obj.sheetName]).addChild(graphics);
  440. return graphics;
  441. },
  442. moveRectangle(obj) {
  443. var points = obj.sprite.graphicsData[0].shape.points;
  444. if (!points)
  445. return;
  446. obj.sprite.dirty = true;
  447. obj.sprite.clearDirty = true;
  448. points[0] = obj.x;
  449. points[1] = obj.y;
  450. points[2] = obj.x + obj.w;
  451. points[3] = obj.y;
  452. points[4] = obj.x + obj.w;
  453. points[5] = obj.y + obj.h;
  454. points[6] = obj.x;
  455. points[7] = obj.y + obj.h;
  456. points[8] = obj.x;
  457. points[9] = obj.y;
  458. },
  459. buildObject: function(obj) {
  460. var w = 8;
  461. var h = 8;
  462. if (obj.w) {
  463. w = obj.w / scaleMult;
  464. h = obj.h / scaleMult;
  465. }
  466. if (obj.sheetName == 'bosses') {
  467. obj.layerName = 'mobs';
  468. w = 24;
  469. h = 24;
  470. obj.w = w * scaleMult;
  471. obj.h = h * scaleMult;
  472. } else if (obj.sheetName == 'bigObjects') {
  473. obj.layerName = 'mobs';
  474. w = 24;
  475. h = 24;
  476. obj.w = w * scaleMult;
  477. obj.h = h * scaleMult;
  478. }
  479. var sprite = new pixi.Sprite(this.getTexture(obj.sheetName, obj.cell, w))
  480. sprite.x = obj.x * scale;
  481. sprite.y = obj.y * scale;
  482. sprite.width = obj.w || scale;
  483. sprite.height = obj.h || scale;
  484. if (obj.sheetName == 'bosses') {
  485. sprite.x -= scale;
  486. sprite.y -= (scale * 2);
  487. } else if (obj.sheetName == 'bigObjects') {
  488. sprite.x -= scale;
  489. sprite.y -= (scale * 2);
  490. sprite.alpha = 0.80;
  491. }
  492. if (obj.flipX) {
  493. sprite.scale.x *= -1;
  494. if ((obj.sheetName == 'bosses') || (obj.sheetName == 'bigObjects'))
  495. sprite.x += (scale * 2);
  496. else
  497. sprite.x += scale;
  498. }
  499. (this.layers[obj.layerName || obj.sheetName] || this.layers.objects).addChild(sprite);
  500. return sprite;
  501. },
  502. addFilter: function(sprite) {
  503. var thickness = 16;
  504. if (sprite.width > scale)
  505. thickness = 8;
  506. var filter = new shaderOutline(this.renderer.width, this.renderer.height, thickness, '0xffffff');
  507. if (!sprite.filters)
  508. sprite.filters = [filter];
  509. else
  510. sprite.filters.push();
  511. return filter;
  512. },
  513. removeFilter: function(sprite, filter) {
  514. if (!sprite.filters)
  515. return;
  516. sprite.filters = null;
  517. },
  518. buildText: function(obj) {
  519. var textSprite = new pixi.Text(obj.text, {
  520. fontFamily: 'bitty',
  521. fontSize: (obj.fontSize || 14),
  522. fill: obj.color || 0xF2F5F5,
  523. stroke: 0x2d2136,
  524. strokeThickness: 4,
  525. align: 'center'
  526. });
  527. textSprite.x = obj.x - (textSprite.width / 2);
  528. textSprite.y = obj.y;
  529. var parent = obj.parent || this.layers[obj.layerName]
  530. parent.addChild(textSprite);
  531. return textSprite;
  532. },
  533. buildEmitter: function(config) {
  534. return particles.buildEmitter(config);
  535. },
  536. destroyEmitter: function(emitter) {
  537. particles.destroyEmitter(emitter);
  538. },
  539. setSprite: function(obj) {
  540. var cell = obj.cell;
  541. var y = ~~(cell / 8);
  542. var x = cell - (y * 8);
  543. var baseTex = this.textures[obj.sheetName];
  544. obj.sprite.texture = this.getTexture(obj.sheetName, obj.cell, obj.sprite.width / scaleMult);
  545. },
  546. reorder: function(sprite) {
  547. var mobLayer = this.layers.mobs;
  548. var mobs = mobLayer.children;
  549. mobs.sort(function(a, b) {
  550. return (b.y - a.y);
  551. });
  552. },
  553. destroyObject: function(obj) {
  554. if (!obj.sprite.parent)
  555. return;
  556. obj.sprite.parent.removeChild(obj.sprite);
  557. },
  558. render: function() {
  559. if (!this.stage)
  560. return;
  561. effects.render();
  562. particles.update();
  563. this.renderer.render(this.stage);
  564. }
  565. };
  566. });