1 /** 2 * @fileOverview 3 * ui.enchant.js v2 (2012/11/05) 4 * ui parts support 5 * @require enchant.js v0.5.2 or later 6 * @require image files for gamepad, icons (default: pad.png, apad.png, icon0.png, font0.png) 7 * 8 * @features 9 * - D-Pad (left, right, up, down) 10 * - Analog Pad 11 * - Button (3 built-in themes and can be customized) 12 * - MutableText 13 * - ScoreLabel 14 * - TimeLabel 15 * - LifeLabel 16 * - Bar 17 * - VirtualMap 18 * 19 * @usage 20 * [D-Pad] 21 * var pad = new Pad(); 22 * pad.x = 0; 23 * pad.y = 220; 24 * core.rootScene.addChild(pad); 25 * (input of X direction can be detected from "Xbuttonup" "Xbuttondown" events 26 * or enchant.Core.instance.input.X) 27 * 28 * [A-Pad] 29 * var pad = new APad(); 30 * pad.x = 0; 31 * pad.y = 220; 32 * core.rootScene.addChild(pad); 33 * (input can be detected from pad.vx/vy and pad.touched) 34 * 35 * [Button] 36 * var button = new Button("Press me"); 37 * button.addEventListener("touchstart", function(){ ... }) 38 * core.rootScene.addEventListener(button); 39 * 40 * var button_light = new Button("Press me", "light"); 41 * core.rootScene.addEventListener(button); 42 * 43 * var button_blue = new Button("Press me", "blue"); 44 * core.rootScene.addEventListener(button); 45 */ 46 47 /** 48 * @type {Object} 49 */ 50 enchant.ui = { assets: ['pad.png', 'apad.png', 'icon0.png', 'font0.png'] }; 51 52 /** 53 * 方向キーパッドのクラス: Pad 54 * @scope enchant.ui.Pad 55 */ 56 enchant.ui.Pad = enchant.Class.create(enchant.Sprite, { 57 /** 58 * 方向キーパッドオブジェクトを作成する。 59 * @constructs 60 * @extends enchant.Sprite 61 */ 62 initialize: function() { 63 var core = enchant.Core.instance; 64 var image = core.assets['pad.png']; 65 enchant.Sprite.call(this, image.width / 2, image.height); 66 this.image = image; 67 this.input = { left: false, right: false, up: false, down: false }; 68 this.addEventListener('touchstart', function(e) { 69 this._updateInput(this._detectInput(e.localX, e.localY)); 70 }); 71 this.addEventListener('touchmove', function(e) { 72 this._updateInput(this._detectInput(e.localX, e.localY)); 73 }); 74 this.addEventListener('touchend', function(e) { 75 this._updateInput({ left: false, right: false, up: false, down: false }); 76 }); 77 }, 78 _detectInput: function(x, y) { 79 x -= this.width * 0.5; 80 y -= this.height * 0.5; 81 var input = { left: false, right: false, up: false, down: false }; 82 if (x * x + y * y <= 2500 && x * x + y * y > 200) { 83 if (x < 0 && y < x * x * 0.1 && y > x * x * -0.1) { 84 input.left = true; 85 } 86 if (x > 0 && y < x * x * 0.1 && y > x * x * -0.1) { 87 input.right = true; 88 } 89 if (y < 0 && x < y * y * 0.1 && x > y * y * -0.1) { 90 input.up = true; 91 } 92 if (y > 0 && x < y * y * 0.1 && x > y * y * -0.1) { 93 input.down = true; 94 } 95 } 96 return input; 97 }, 98 _updateInput: function(input) { 99 var core = enchant.Core.instance; 100 ['left', 'right', 'up', 'down'].forEach(function(type) { 101 if (this.input[type] && !input[type]) { 102 core.changeButtonState(type, false); 103 } 104 if (!this.input[type] && input[type]) { 105 core.changeButtonState(type, true); 106 } 107 }, this); 108 this.input = input; 109 } 110 }); 111 112 /** 113 * アナログパッドのクラス: APad 114 * @scope enchant.ui.APad 115 */ 116 enchant.ui.APad = enchant.Class.create(enchant.Group, { 117 /** 118 * アナログパッドオブジェクトを作成する。 119 * @constructs 120 * @extends enchant.Group 121 * @param mode 122 * 'direct': 入力ベクトルは正規化されない (大きさは 0~1 の間) 123 * 'normal': 入力ベクトルを常に正規化する (大きさは常に1となる) 124 */ 125 initialize: function(mode) { 126 var core = enchant.Core.instance; 127 var image = core.assets['apad.png']; 128 var w = this.width = image.width; 129 var h = this.height = image.height; 130 enchant.Group.call(this); 131 132 this.outside = new enchant.Sprite(w, h); 133 var outsideImage = new enchant.Surface(w, h); 134 outsideImage.draw(image, 0, 0, w, h / 4, 0, 0, w, h / 4); 135 outsideImage.draw(image, 0, h / 4 * 3, w, h / 4, 0, h / 4 * 3, w, h / 4); 136 outsideImage.draw(image, 0, h / 4, w / 4, h / 2, 0, h / 4, w / 4, h / 2); 137 outsideImage.draw(image, w / 4 * 3, h / 4, w / 4, h / 2, w / 4 * 3, h / 4, w / 4, h / 2); 138 this.outside.image = outsideImage; 139 this.inside = new enchant.Sprite(w / 2, h / 2); 140 var insideImage = new enchant.Surface(w / 2, h / 2); 141 insideImage.draw(image, w / 4, h / 4, w / 2, h / 2, 0, 0, w / 2, h / 2); 142 this.inside.image = insideImage; 143 this.r = w / 2; 144 145 /** 146 * isTouched 147 * @type {Boolean} 148 * タッチされているかどうか 149 */ 150 this.isTouched = false; 151 152 /** 153 * vx, vy 154 * @type {Number} 155 * 入力ベクトルの(x, y)方向の大きさ 156 */ 157 this.vx = 0; 158 this.vy = 0; 159 160 /** 161 * rad, dist 162 * @type {Number} 163 * 入力ベクトルの極座標表示 164 * radは角度、distはベクトルの大きさを示す 165 */ 166 this.rad = 0; 167 this.dist = 0; 168 169 if (mode === 'direct') { 170 this.mode = 'direct'; 171 } else { 172 this.mode = 'normal'; 173 } 174 this._updateImage(); 175 this.addChild(this.inside); 176 this.addChild(this.outside); 177 this.addEventListener('touchstart', function(e) { 178 this._detectInput(e.localX, e.localY); 179 this._calcPolar(e.localX, e.localY); 180 this._updateImage(e.localX, e.localY); 181 this._dispatchPadEvent('apadstart'); 182 this.isTouched = true; 183 }); 184 this.addEventListener('touchmove', function(e) { 185 this._detectInput(e.localX, e.localY); 186 this._calcPolar(e.localX, e.localY); 187 this._updateImage(e.localX, e.localY); 188 this._dispatchPadEvent('apadmove'); 189 }); 190 this.addEventListener('touchend', function(e) { 191 this._detectInput(this.width / 2, this.height / 2); 192 this._calcPolar(this.width / 2, this.height / 2); 193 this._updateImage(this.width / 2, this.height / 2); 194 this._dispatchPadEvent('apadend'); 195 this.isTouched = false; 196 }); 197 }, 198 _dispatchPadEvent: function(type) { 199 var e = new enchant.Event(type); 200 e.vx = this.vx; 201 e.vy = this.vy; 202 e.rad = this.rad; 203 e.dist = this.dist; 204 this.dispatchEvent(e); 205 }, 206 _updateImage: function(x, y) { 207 x -= this.width / 2; 208 y -= this.height / 2; 209 this.inside.x = this.vx * (this.r - 10) + 25; 210 this.inside.y = this.vy * (this.r - 10) + 25; 211 }, 212 _detectInput: function(x, y) { 213 x -= this.width / 2; 214 y -= this.height / 2; 215 var distance = Math.sqrt(x * x + y * y); 216 var tan = y / x; 217 var rad = Math.atan(tan); 218 var dir = x / Math.abs(x); 219 if (distance === 0) { 220 this.vx = 0; 221 this.vy = 0; 222 } else if (x === 0) { 223 this.vx = 0; 224 if (this.mode === 'direct') { 225 this.vy = (y / this.r); 226 } else { 227 dir = y / Math.abs(y); 228 this.vy = Math.pow((y / this.r), 2) * dir; 229 } 230 } else if (distance < this.r) { 231 if (this.mode === 'direct') { 232 this.vx = (x / this.r); 233 this.vy = (y / this.r); 234 } else { 235 this.vx = Math.pow((distance / this.r), 2) * Math.cos(rad) * dir; 236 this.vy = Math.pow((distance / this.r), 2) * Math.sin(rad) * dir; 237 } 238 } else { 239 this.vx = Math.cos(rad) * dir; 240 this.vy = Math.sin(rad) * dir; 241 } 242 }, 243 _calcPolar: function(x, y) { 244 x -= this.width / 2; 245 y -= this.height / 2; 246 var add = 0; 247 var rad = 0; 248 var dist = Math.sqrt(x * x + y * y); 249 if (dist > this.r) { 250 dist = this.r; 251 } 252 dist /= this.r; 253 if (this.mode === 'normal') { 254 dist *= dist; 255 } 256 if (x >= 0 && y < 0) { 257 add = Math.PI / 2 * 3; 258 rad = x / y; 259 } else if (x < 0 && y <= 0) { 260 add = Math.PI; 261 rad = y / x; 262 } else if (x <= 0 && y > 0) { 263 add = Math.PI / 2; 264 rad = x / y; 265 } else if (x > 0 && y >= 0) { 266 add = 0; 267 rad = y / x; 268 } 269 if (x === 0 || y === 0) { 270 rad = 0; 271 } 272 this.rad = Math.abs(Math.atan(rad)) + add; 273 this.dist = dist; 274 } 275 }); 276 277 /** 278 * ボタンオブジェクトのクラス: Button 279 * available in only DOMGroup 280 * 281 * @scope enchant.ui.Button.prototype 282 * @deprecated 283 * @classes 284 */ 285 enchant.ui.Button = enchant.Class.create(enchant.Entity, { 286 /** 287 * ボタンオブジェクトを作成する。 288 * @constructs 289 * @extends enchant.Entity 290 */ 291 initialize: function(text, theme, height, width) { 292 enchant.Entity.call(this); 293 294 if (enchant.CanvasLayer) { 295 this._element = 'div'; 296 } 297 298 this.width = width || null; 299 this.height = height || null; 300 this.text = text; 301 this.pressed = false; 302 303 // デフォルトのスタイル (テーマで上書き可能) 304 var style = this._style; 305 style["display"] = "inline-block"; 306 style["font-size"] = "12px"; 307 style["height"] = "2em"; 308 style["line-height"] = "2em"; 309 style["min-width"] = "2em"; 310 style["padding"] = "2px 10px"; 311 style["text-align"] = "center"; 312 style["font-weight"] = "bold"; 313 style["border-radius"] = "0.5em"; 314 315 // テーマの指定がなければ "dark" を使う 316 theme = theme || "dark"; 317 318 if (typeof theme === "string") { 319 // theme 引数が string なら、その名前のデフォルトテーマを使う 320 this.theme = enchant.ui.Button.DEFAULT_THEME[theme]; 321 } else { 322 // theme 引数が object なら、その引数をテーマとして扱う 323 this.theme = theme; 324 } 325 326 // テーマを適用する 327 this._applyTheme(this.theme.normal); 328 329 // タッチしたときの挙動 330 this.addEventListener("touchstart", function() { 331 this._applyTheme(this.theme.active); 332 this.pressed = true; 333 this.y++; 334 }); 335 336 // タッチが離されたときの挙動 337 this.addEventListener("touchend", function() { 338 this._applyTheme(this.theme.normal); 339 this.pressed = false; 340 this.y--; 341 }); 342 }, 343 _applyTheme: function(theme) { 344 var style = this._style; 345 var css = enchant.ui.Button.theme2css(theme); 346 for (var i in css) { 347 if (css.hasOwnProperty(i)) { 348 style[i] = css[i]; 349 } 350 } 351 }, 352 /** 353 * 表示するテキスト 354 * @type {String} 355 */ 356 text: { 357 get: function() { 358 return this._text; 359 }, 360 set: function(text) { 361 this._text = text; 362 if (!enchant.CanvasLayer) { 363 this._element.innerHTML = text; 364 } 365 } 366 }, 367 /** 368 * フォントサイズ 369 */ 370 size: { 371 get: function() { 372 return this._style.fontSize; 373 }, 374 set: function(size) { 375 this._style.fontSize = size; 376 } 377 }, 378 /** 379 * フォントの指定 380 * @type {String} 381 */ 382 font: { 383 get: function() { 384 return this._style.font; 385 }, 386 set: function(font) { 387 this._style.font = font; 388 } 389 }, 390 /** 391 * Text color settings. 392 * CSS 'color' can be set to same format as properties. 393 * @type {String} 394 */ 395 color: { 396 get: function() { 397 return this._style.color; 398 }, 399 set: function(color) { 400 this._style.color = color; 401 } 402 }, 403 cvsRender: function() { 404 // not available now 405 }, 406 domRender: function() { 407 var element = this._domManager.element; 408 element.innerHTML = this._text; 409 element.style.font = this._font; 410 element.style.color = this._color; 411 element.style.textAlign = this._textAlign; 412 } 413 }); 414 415 enchant.ui.Button.theme2css = function(theme) { 416 var prefix = '-' + enchant.ENV.VENDOR_PREFIX.toLowerCase() + '-'; 417 var obj = {}; 418 var bg = theme.background; 419 var bd = theme.border; 420 var ts = theme.textShadow; 421 var bs = theme.boxShadow; 422 if (prefix === '-ms-') { 423 obj['background'] = bg.start; 424 } else { 425 obj['background-image'] = prefix + bg.type + '('+ [ 'top', bg.start, bg.end ] + ')'; 426 } 427 obj['color'] = theme.color; 428 obj['border'] = bd.color + ' ' + bd.width + ' ' + bd.type; 429 obj['text-shadow'] = ts.offsetX + 'px ' + ts.offsetY + 'px ' + ts.blur + ' ' + ts.color; 430 obj['box-shadow'] = bs.offsetX + 'px ' + bs.offsetY + 'px ' + bs.blur + ' ' + bs.color; 431 return obj; 432 }; 433 434 enchant.ui.Button.DEFAULT_THEME = { 435 dark: { 436 normal: { 437 color: '#fff', 438 background: { type: 'linear-gradient', start: '#666', end: '#333' }, 439 border: { color: '#333', width: 1, type: 'solid' }, 440 textShadow: { offsetX: 0, offsetY: 1, blur: 0, color: '#666' }, 441 boxShadow: { offsetX: 0, offsetY: 1, blur: 0, color: 'rgba(255, 255, 255, 0.3)' } 442 }, 443 active: { 444 color: '#ccc', 445 background: { type: 'linear-gradient', start: '#333', end: '#000' }, 446 border: { color: '#333', width: 1, type: 'solid' }, 447 textShadow: { offsetX: 0, offsetY: 1, blur: 0, color: '#000' }, 448 boxShadow: { offsetX: 0, offsetY: 1, blur: 0, color: 'rgba(255, 255, 255, 0.3)' } 449 } 450 }, 451 light: { 452 normal: { 453 color: '#333', 454 background: { type: 'linear-gradient', start: '#fff', end:'#ccc' }, 455 border: { color: '#999', width: 1, type: 'solid' }, 456 textShadow: { offsetX: 0, offsetY: 1, blur: 0, color: '#fff' }, 457 boxShadow: { offsetX: 0, offsetY: 1, blur: 0, color: 'rgba(0, 0, 0, 1)' }, 458 }, 459 active: { 460 color: '#333', 461 background: { type: 'linear-gradient', start: '#ccc', end: '#999' }, 462 border: { color: '#666', width: 1, type: 'solid' }, 463 textShadow: { offsetX: 0, offsetY: 1, blur: 0, color: '#ccc' }, 464 boxShadow: { offsetX: 0, offsetY: 1, blur: 0, color: 'rgba(255, 255, 255, 0.3)' } 465 } 466 }, 467 blue: { 468 normal: { 469 color: '#fff', 470 background: { type: 'linear-gradient', start: '#04f', end: '#04c' }, 471 border: { color: '#026', width: 1, type: 'solid' }, 472 textShadow: { offsetX: 0, offsetY: 1, blur: 0, color: '#666' }, 473 boxShadow: { offsetX: 0, offsetY: 1, blur: 0, color: 'rgba(0, 0, 0, 0.5)' } 474 }, 475 active: { 476 color: '#ccc', 477 background: { type: 'linear-gradient', start: '#029', end: '#026' }, 478 border: { color: '#026', width: 1, type: 'solid' }, 479 textShadow: { offsetX: 0, offsetY: 1, blur: 0, color: '#000' }, 480 boxShadow: 'none' 481 } 482 } 483 }; 484 485 /** 486 * @scope enchant.ui.MutableText.prototype 487 * @type {*} 488 */ 489 enchant.ui.MutableText = enchant.Class.create(enchant.Sprite, { 490 /** 491 * 492 * @usage 493 * var text = new MutableText(0, 0); 494 * game.text = 'Hello, world!'; 495 * game.rootScene.addChild(text); 496 * 497 * @constructs 498 * @param posX 499 * @param posY 500 * @param width 501 */ 502 initialize: function(x, y, width) { 503 enchant.Sprite.call(this, 0, 0); 504 this.fontSize = 16; 505 this.widthItemNum = 16; 506 this.x = x; 507 this.y = y; 508 this._imageAge = Number.MAX_VALUE; 509 this.text = ''; 510 if (arguments[2]) { 511 this.row = Math.floor(arguments[2] / this.fontSize); 512 } 513 }, 514 /** 515 * ラベルの内容を書き換える関数 516 * @param txt 517 */ 518 setText: function(txt) { 519 var i, x, y, wNum, charCode, charPos; 520 this._text = txt; 521 var newWidth; 522 if (!this.returnLength) { 523 this.width = Math.min(this.fontSize * this._text.length, enchant.Game.instance.width); 524 } else { 525 this.width = Math.min(this.returnLength * this.fontSize, enchant.Game.instance.width); 526 } 527 this.height = this.fontSize * (Math.ceil(this._text.length / this.row) || 1); 528 // if image is to small or was to big for a long time create new image 529 if(!this.image || this.width > this.image.width || this.height > this.image.height || this._imageAge > 300) { 530 this.image = new enchant.Surface(this.width, this.height); 531 this._imageAge = 0; 532 } else if(this.width < this.image.width || this.height < this.image.height) { 533 this._imageAge++; 534 } else { 535 this._imageAge = 0; 536 } 537 this.image.context.clearRect(0, 0, this.width, this.height); 538 for (i = 0; i < txt.length; i++) { 539 charCode = txt.charCodeAt(i); 540 if (charCode >= 32 && charCode <= 127) { 541 charPos = charCode - 32; 542 } else { 543 charPos = 0; 544 } 545 x = charPos % this.widthItemNum; 546 y = (charPos / this.widthItemNum) | 0; 547 this.image.draw(enchant.Game.instance.assets['font0.png'], 548 x * this.fontSize, y * this.fontSize, this.fontSize, this.fontSize, 549 (i % this.row) * this.fontSize, ((i / this.row) | 0) * this.fontSize, this.fontSize, this.fontSize); 550 } 551 }, 552 /** 553 * ラベルの内容 554 * @type {String} 555 */ 556 text: { 557 get: function() { 558 return this._text; 559 }, 560 set: function(txt) { 561 this.setText(txt); 562 } 563 }, 564 /** 565 * @type {Number} 566 */ 567 row: { 568 get: function() { 569 return this.returnLength || this.width / this.fontSize; 570 }, 571 set: function(row) { 572 this.returnLength = row; 573 this.text = this.text; 574 } 575 } 576 }); 577 578 /** 579 * @scope enchant.ui.ScoreLabel.prototype 580 * @type {*} 581 */ 582 enchant.ui.ScoreLabel = enchant.Class.create(enchant.ui.MutableText, { 583 /** 584 * スコアを表示するラベル。 585 * 画像フォントクラス (MutableText) を使って表示する。 586 * @constructs 587 * @param x 588 * @param y 589 */ 590 initialize: function(x, y) { 591 enchant.ui.MutableText.call(this, 0, 0); 592 switch (arguments.length) { 593 case 2: 594 this.y = y; 595 this.x = x; 596 break; 597 case 1: 598 this.x = x; 599 break; 600 default: 601 break; 602 } 603 this._score = 0; 604 this._current = 0; 605 this.easing = 2.5; 606 this.text = this.label = 'SCORE:'; 607 this.addEventListener('enterframe', function() { 608 if (this.easing === 0) { 609 this.text = this.label + (this._current = this._score); 610 } else { 611 var dist = this._score - this._current; 612 if (0 < dist) { 613 this._current += Math.ceil(dist / this.easing); 614 } else if (dist < 0) { 615 this._current += Math.floor(dist / this.easing); 616 } 617 this.text = this.label + this._current; 618 } 619 }); 620 }, 621 /** 622 * スコア 623 * @type {Number} 624 */ 625 score: { 626 get: function() { 627 return this._score; 628 }, 629 set: function(newscore) { 630 this._score = newscore; 631 } 632 } 633 }); 634 635 /** 636 * @type {*} 637 * @scope enchant.ui.TimeLabel.prototype 638 */ 639 enchant.ui.TimeLabel = enchant.Class.create(enchant.ui.MutableText, { 640 /** 641 * 残り時間などのタイムを表示するラベル 642 * @constructs 643 * @param x 644 * @param y 645 * @param counttype 646 */ 647 initialize: function(x, y, counttype) { 648 enchant.ui.MutableText.call(this, 0, 0); 649 switch (arguments.length) { 650 case 3: 651 case 2: 652 this.y = y; 653 this.x = x; 654 break; 655 case 1: 656 this.x = x; 657 break; 658 default: 659 break; 660 } 661 this._time = 0; 662 this._count = 1;// この数を毎フレーム每に足して上げ下げを制御する 663 if (counttype === 'countdown') { 664 this._count = -1; 665 } 666 this.text = this.label = 'TIME:'; 667 this.addEventListener('enterframe', function() { 668 this._time += this._count; 669 this.text = this.label + (this._time / enchant.Game.instance.fps).toFixed(2); 670 }); 671 }, 672 /** 673 * 残り時間 674 * @type {Number} 675 */ 676 time: { 677 get: function() { 678 return Math.floor(this._time / enchant.Game.instance.fps); 679 }, 680 set: function(newtime) { 681 this._time = newtime * enchant.Game.instance.fps; 682 } 683 } 684 }); 685 686 /** 687 * @type {*} 688 * @scope enchant.ui.LifeLabel.prototype 689 */ 690 enchant.ui.LifeLabel = enchant.Class.create(enchant.Group, { 691 /** 692 * ライフを表示する専用のラベル 693 * icon0.png 内のハートの画像を用いる 694 * @constructs 695 * @param x 696 * @param y 697 * @param maxlife 698 */ 699 initialize: function(x, y, maxlife) { 700 enchant.Group.call(this); 701 this.x = x || 0; 702 this.y = y || 0; 703 this._maxlife = maxlife || 9; 704 this._life = 0; 705 this.label = new enchant.ui.MutableText(0, 0, 80); 706 this.label.text = 'LIFE:'; 707 this.addChild(this.label); 708 this.heart = []; 709 for (var i = 0; i < this._maxlife; i++) { 710 this.heart[i] = new enchant.Sprite(16, 16); 711 this.heart[i].image = enchant.Game.instance.assets['icon0.png']; 712 this.heart[i].x = this.label.width + i * 16; 713 this.heart[i].y = -3; 714 this.heart[i].frame = 10; 715 this.addChild(this.heart[i]); 716 } 717 }, 718 /** 719 * 残りライフの数 720 * @type {Number} 721 */ 722 life: { 723 get: function() { 724 return this._life; 725 }, 726 set: function(newlife) { 727 this._life = newlife; 728 if (this._maxlife < newlife) { 729 this._life = this._maxlife; 730 } 731 for (var i = 0; i < this._maxlife; i++) { 732 this.heart[i].visible = (i <= newlife - 1); 733 } 734 } 735 } 736 }); 737 738 /** 739 * @scope enchant.ui.Bar 740 * @type {*} 741 */ 742 enchant.ui.Bar = enchant.Class.create(enchant.Sprite, { 743 /** 744 * イージング付きのバークラス 745 * @constructs 746 * @param x 747 * @param y 748 */ 749 initialize: function(x, y) { 750 enchant.Sprite.call(this, 1, 16); 751 this.image = new enchant.Surface(1, 16);// Null用 752 this.image.context.fillColor = 'RGB(0, 0, 256)'; 753 this.image.context.fillRect(0, 0, 1, 16); 754 this._direction = 'right'; 755 this._origin = 0; 756 this._maxvalue = enchant.Game.instance.width; 757 this._lastvalue = 0; 758 this.value = 0; 759 this.easing = 5; 760 switch (arguments.length) { 761 case 2: 762 this.y = y; 763 this.x = x; 764 this._origin = x; 765 break; 766 case 1: 767 this.x = x; 768 this._origin = x; 769 break; 770 default: 771 break; 772 } 773 this.addEventListener('enterframe', function() { 774 if (this.value < 0) { 775 this.value = 0; 776 } 777 this._lastvalue += (this.value - this._lastvalue) / this.easing; 778 if (Math.abs(this._lastvalue - this.value) < 1.3) { 779 this._lastvalue = this.value; 780 } 781 this.width = (this._lastvalue) | 0; 782 if (this.width > this._maxvalue) { 783 this.width = this._maxvalue; 784 } 785 if (this._direction === 'left') { 786 this._x = this._origin - this.width; 787 } else { 788 this._x = this._origin; 789 } 790 this._updateCoordinate(); 791 }); 792 }, 793 /** 794 * バーの向き ('right' or 'left') 795 * @default 'right' 796 * @type {String} 797 */ 798 direction: { 799 get: function() { 800 return this._direction; 801 }, 802 set: function(newdirection) { 803 if (newdirection !== 'right' && newdirection !== 'left') { 804 // ignore 805 } else { 806 this._direction = newdirection; 807 } 808 } 809 }, 810 /** 811 * x 座標 812 * @type {Number} 813 */ 814 x: { 815 get: function() { 816 return this._origin; 817 }, 818 set: function(x) { 819 this._x = x; 820 this._origin = x; 821 this._dirty = true; 822 } 823 }, 824 /** 825 * @type {Number} 826 */ 827 maxvalue: { 828 get: function() { 829 return this._maxvalue; 830 }, 831 set: function(val) { 832 this._maxvalue = val; 833 } 834 } 835 }); 836 837 /** 838 * @scope enchant.ui.VirtualMap.prototype 839 */ 840 enchant.ui.VirtualMap = enchant.Class.create(enchant.Group, { 841 /** 842 * マップライクな Group 843 * addChildで Sprite 等を追加すると、自動的に mx, my プロパティが追加され、 844 * VirtualMap内での座標で Sprite を操作できる 845 * 846 * 使い方 847 * //20 x 20 メッシュの縦横320ピクセルの盤を作り、その上に16 x 16の駒を8つ並べる 848 * var board = new VirtualMap(20, 20); 849 * board.width = 320; 850 * board.height = 320; 851 * for(var i=0; i<8; i++){ 852 * var piece = new Sprite(16, 16); 853 * piece.image = game.assets['icon0.gif']; 854 * board.addChild(piece); 855 * piece.mx = i + 3; 856 * piece.my = 16; 857 * } 858 * game.rootScene.addChild(board); 859 * 860 * @param meshWidth 861 * @param meshHeight 862 * @constructs 863 */ 864 initialize: function(meshWidth, meshHeight) { 865 enchant.Group.call(this); 866 this.meshWidth = meshWidth || 16; 867 this.meshHeight = meshHeight || 16; 868 }, 869 /** 870 * VirtualMap にオブジェクトを追加する (自動的にバインドされる) 871 * @param obj 872 */ 873 addChild: function(obj) { 874 enchant.Group.prototype.addChild.call(this, obj); 875 this.bind(obj); 876 }, 877 /** 878 * VirtualMap にオブジェクトを追加する 879 * reference で指定したオブジェクトより前に追加される (自動的にバインドされる)。 880 * @param obj 881 * @param reference 882 */ 883 insertBefore: function(obj, reference) { 884 enchant.Group.prototype.insertBefore.call(this, obj, reference); 885 this.bind(obj); 886 }, 887 /** 888 * オブジェクトを VirtualMap にバインドする。 889 * バインドされたオブジェクトはメッシュ座標 mx, my プロパティを持ち、これを操作することで 890 * VirtualMap の中を移動させることができる。 891 * @param obj 892 */ 893 bind: function(obj) { 894 Object.defineProperties(obj, { 895 "mx": { 896 get: function() { 897 return Math.floor(this.x / this.parentNode.meshWidth); 898 }, 899 set: function(arg) { 900 this.x = Math.floor(arg * this.parentNode.meshWidth); 901 } 902 }, 903 "my": { 904 get: function() { 905 return Math.floor(this.y / this.parentNode.meshHeight); 906 }, 907 set: function(arg) { 908 this.y = Math.floor(arg * this.parentNode.meshWidth); 909 } 910 } 911 }); 912 obj.mx = 0; 913 obj.my = 0; 914 } 915 }); 916 917 function rand(num) { 918 return Math.floor(Math.random() * num); 919 } 920