首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

cocos2d-x for JS 中的繼承機制詳解

     編輯:關於C語言

對於面向對象語言來說,繼承機制是代碼復用的基礎。遺憾的是 JavaScript 作為一個基於原型繼承的語言,並沒有在語言層面上直接支援類別繼承。但 JS 語言擁有強大的表現力,因此一般由使用者自行設計一套繼承機制,這套機制必須包含私有存取權限模擬、屬性與類別屬性的不同實作、方法覆寫支援、父類別被覆寫方法的存取等。

cocos2d-x 中整合了兩套繼承機制,請參考《MoonWarriors》範例中的 SysMenu.js 檔案:

  1. var SysMenu = cc.Layer.extend({
  2. _ship:null,
  3. ctor:function () {
  4. cc.associateWithNative( this, cc.Layer );
  5. },
  6. init:function () {
  7. var bRet = false;
  8. if (this._super()) {
  9. winSize = cc.Director.getInstance().getWinSize();
  10. var sp = cc.Sprite.create(s_loading);
  11. sp.setAnchorPoint(cc.p(0,0));
  12. this.addChild(sp, 0, 1);
  13. var logo = cc.Sprite.create(s_logo);
  14. logo.setAnchorPoint(cc.p(0, 0));
  15. logo.setPosition(0, 250);
  16. this.addChild(logo, 10, 1);
  17. var newGameNormal = cc.Sprite.create(s_menu, cc.rect(0, 0, 126, 33));
  18. var newGameSelected = cc.Sprite.create(s_menu, cc.rect(0, 33, 126, 33));
  19. var newGameDisabled = cc.Sprite.create(s_menu, cc.rect(0, 33 * 2, 126, 33));
  20. var gameSettingsNormal = cc.Sprite.create(s_menu, cc.rect(126, 0, 126, 33));
  21. var gameSettingsSelected = cc.Sprite.create(s_menu, cc.rect(126, 33, 126, 33));
  22. var gameSettingsDisabled = cc.Sprite.create(s_menu, cc.rect(126, 33 * 2, 126, 33));
  23. var aboutNormal = cc.Sprite.create(s_menu, cc.rect(252, 0, 126, 33));
  24. var aboutSelected = cc.Sprite.create(s_menu, cc.rect(252, 33, 126, 33));
  25. var aboutDisabled = cc.Sprite.create(s_menu, cc.rect(252, 33 * 2, 126, 33));
  26. var newGame = cc.MenuItemSprite.create(newGameNormal, newGameSelected, newGameDisabled, function () {
  27. this.onButtonEffect();
  28. flareEffect(this, this, this.onNewGame);
  29. }.bind(this));
  30. var gameSettings = cc.MenuItemSprite.create(gameSettingsNormal, gameSettingsSelected, gameSettingsDisabled, this.onSettings, this);
  31. var about = cc.MenuItemSprite.create(aboutNormal, aboutSelected, aboutDisabled, this.onAbout, this);
  32. var menu = cc.Menu.create(newGame, gameSettings, about);
  33. menu.alignItemsVerticallyWithPadding(10);
  34. this.addChild(menu, 1, 2);
  35. menu.setPosition(winSize.width / 2, winSize.height / 2 - 80);
  36. this.schedule(this.update, 0.1);
  37. var tmp = cc.TextureCache.getInstance().addImage(s_ship01);
  38. this._ship = cc.Sprite.createWithTexture(tmp, cc.rect(0, 45, 60, 38));
  39. this.addChild(this._ship, 0, 4);
  40. var pos = cc.p(Math.random() * winSize.width, 0);
  41. this._ship.setPosition( pos );
  42. this._ship.runAction(cc.MoveBy.create(2, cc.p(Math.random() * winSize.width, pos.y + winSize.height + 100)));
  43. if (MW.SOUND) {
  44. cc.AudioEngine.getInstance().setMusicVolume(0.7);
  45. cc.AudioEngine.getInstance().playMusic(s_mainMainMusic, true);
  46. }
  47. bRet = true;
  48. }
  49. return bRet;
  50. },
  51. onNewGame:function (pSender) {
  52. var scene = cc.Scene.create();
  53. scene.addChild(GameLayer.create());
  54. scene.addChild(GameControlMenu.create());
  55. cc.Director.getInstance().replaceScene(cc.TransitionFade.create(1.2, scene));
  56. },
  57. onSettings:function (pSender) {
  58. this.onButtonEffect();
  59. var scene = cc.Scene.create();
  60. scene.addChild(SettingsLayer.create());
  61. cc.Director.getInstance().replaceScene(cc.TransitionFade.create(1.2, scene));
  62. },
  63. onAbout:function (pSender) {
  64. this.onButtonEffect();
  65. var scene = cc.Scene.create();
  66. scene.addChild(AboutLayer.create());
  67. cc.Director.getInstance().replaceScene(cc.TransitionFade.create(1.2, scene));
  68. },
  69. update:function () {
  70. if (this._ship.getPosition().y > 480) {
  71. var pos = cc.p(Math.random() * winSize.width, 10);
  72. this._ship.setPosition( pos );
  73. this._ship.runAction( cc.MoveBy.create(
  74. parseInt(5 * Math.random(), 10),
  75. cc.p(Math.random() * winSize.width, pos.y + 480)));
  76. }
  77. },
  78. onButtonEffect:function(){
  79. if (MW.SOUND) {
  80. var s = cc.AudioEngine.getInstance().playEffect(s_buttonEffect);
  81. }
  82. }
  83. });
  84. SysMenu.create = function () {
  85. var sg = new SysMenu();
  86. if (sg && sg.init()) {
  87. return sg
  88. }
  89. return null;
  90. };
  91. SysMenu.scene = function () {
  92. var scene = cc.Scene.create();
  93. var layer = SysMenu.create();
  94. scene.addChild(layer);
  95. return scene;
  96. };

這種 extend 繼承寫法由 John Resig 創造,他是 JS 領域的大神。範例中使用父類別 cc.Layer.extend 方法啟動繼承,傳入一個物件字面量 {},這個字面量可以包含物件屬性和方法,最終由 extend 完成介面綁定,回傳一個建構函式賦值給 SysMenu。

對於類別方法(通常意義上的靜態方法),使用的是 JS 最傳統的方式,直接給建構函式指定屬性即可。這種編寫方式非常簡單優美,最重要的是非常符合 C++ 或 Java 程式設計師的排版審美。

關於繼承的理解:JS 的原型繼承與基於類別的繼承方式截然不同,內部維護一個原型鏈,鏈上的節點之間是連結關係(注意:不是賦值,也不是複製)。建議參考《JavaScript 權威指南》或三生石上的《JavaScript 繼承詳解》系列文章(共六篇),深入掌握原型鏈本質。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved