├── run.bat ├── .gitignore ├── doc └── sourceassets │ ├── icon.png │ ├── tile.png │ ├── button.png │ ├── gamemenu.png │ ├── start_logo.png │ ├── end_background.png │ ├── settingscreen.png │ ├── about_background.png │ ├── button │ ├── icon_down.png │ ├── play_down.png │ ├── custom_down.png │ ├── icon_normal.png │ ├── music_down.png │ ├── music_normal.png │ ├── pause_down.png │ ├── pause_normal.png │ ├── play_normal.png │ ├── retry2_down.png │ ├── retry_down.png │ ├── retry_normal.png │ ├── return_down.png │ ├── setting_down.png │ ├── sound_down.png │ ├── sound_normal.png │ ├── custom_normal.png │ ├── music_non_down.png │ ├── retry2_normal.png │ ├── return_normal.png │ ├── setting_normal.png │ ├── sound_non_down.png │ ├── music_non_normal.png │ └── sound_non_normal.png │ ├── gametile │ ├── tile_1.png │ ├── tile_10.png │ ├── tile_11.png │ ├── tile_2.png │ ├── tile_3.png │ ├── tile_4.png │ ├── tile_5.png │ ├── tile_6.png │ ├── tile_7.png │ ├── tile_8.png │ ├── tile_9.png │ ├── tile_stone.png │ ├── tile_water.png │ ├── tile_shovel.png │ └── tile_stone2.png │ ├── icon │ ├── level_easy.png │ ├── level_normal.png │ ├── level_special.png │ ├── loading_logo.png │ └── loading_logo2.png │ ├── sence_background.png │ ├── start_background.png │ ├── gamemenu │ ├── highscroce.png │ ├── menubackground.png │ ├── level_small_easy.png │ ├── level_small_normal.png │ └── level_small_special.png │ ├── setting_background.png │ ├── settingscreen │ ├── about_logo.png │ ├── about_logo2.png │ ├── howtoplay_1.png │ ├── howtoplay_2.png │ ├── howtoplay_3.png │ ├── howtoplay_4.png │ ├── howtoplay_next.png │ ├── howtoplay_prev.png │ └── howtoplay_return.png │ ├── icon.json │ ├── gamemenu.json │ ├── settingscreen.json │ ├── tile.json │ └── button.json ├── modules └── puremvc │ ├── build.bat │ ├── package.json │ ├── bin │ └── puremvc │ │ ├── puremvc.min.js │ │ └── puremvc.d.ts │ └── src │ ├── puremvc.d.ts │ └── puremvc.js ├── resource ├── assets │ ├── icon.png │ ├── tile.png │ ├── button.png │ ├── end_sun.png │ ├── end_close.png │ ├── end_cloud.png │ ├── gamemenu.png │ ├── start_logo.png │ ├── end_background.png │ ├── settingscreen.png │ ├── about_background.png │ ├── sence_background.png │ ├── start_background.png │ ├── setting_background.png │ ├── icon.json │ ├── gamemenu.json │ ├── settingscreen.json │ ├── tile.json │ └── button.json ├── theme.thm └── resource.json ├── src ├── org │ └── xzper │ │ ├── app │ │ ├── AppConfig.ts │ │ ├── IApp.ts │ │ └── AppContainer.ts │ │ ├── model │ │ ├── common │ │ │ ├── Level.ts │ │ │ └── CommonData.ts │ │ ├── vos │ │ │ └── TileVO.ts │ │ ├── GameProxy.ts │ │ └── GridProxy.ts │ │ ├── controller │ │ ├── ControllerPrepCommand.ts │ │ ├── StartupCommand.ts │ │ ├── ModelPrepCommand.ts │ │ ├── ViewPrepCommand.ts │ │ └── commands │ │ │ ├── SceneCommand.ts │ │ │ └── GameCommand.ts │ │ ├── view │ │ ├── ApplicationMediator.ts │ │ ├── panel │ │ │ ├── GameScreen.ts │ │ │ ├── AboutWindow.ts │ │ │ ├── StartScreen.ts │ │ │ ├── EndWindow.ts │ │ │ ├── GameMenuUI.ts │ │ │ ├── HowtoplayWindow.ts │ │ │ ├── TileUI.ts │ │ │ ├── SettingWindow.ts │ │ │ └── GameScene.ts │ │ ├── GameMenuMediator.ts │ │ ├── GameSceneMediator.ts │ │ ├── EndWindowMediator.ts │ │ ├── StartScreenMediator.ts │ │ ├── SettingWindowMediator.ts │ │ └── GameScreenMediator.ts │ │ ├── ApplicationFacade.ts │ │ └── utils │ │ └── ObjectPool.ts ├── components │ └── IconButton.ts ├── skin │ ├── components │ │ ├── ReturnSkin.exml │ │ ├── CloseButtonSkin.exml │ │ ├── RetryButtonSkin.exml │ │ ├── PauseButtonSkin.exml │ │ ├── SettingButtonSkin.exml │ │ ├── ProgressBarSkin.exml │ │ ├── PlayButtonSkin.exml │ │ ├── ButtonSkin.exml │ │ ├── MusicButonSkin.exml │ │ ├── SoundButtonSkin.exml │ │ └── IconButtonSkin.exml │ ├── MainGameUISkin.exml │ ├── LoadingUISkin.exml │ ├── StartScreenSkin.exml │ ├── AboutSkin.exml │ ├── GameMenuSkin.exml │ ├── HowtoPlaySkin.exml │ ├── SettingScreenSkin.exml │ └── EndScreenSkin.exml ├── libs │ └── exml.g.d.ts ├── LoadingUI.ts ├── AutoScreenAdapter.ts ├── AssetAdapter.ts └── Main.ts ├── tsconfig.json ├── template └── runtime │ ├── native_loader.js │ ├── runtime_loader.js │ └── native_require.js ├── egretProperties.json ├── index.html └── README.md /run.bat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f111fei/2048egret/HEAD/run.bat -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | bin-debug/ 2 | .idea/ 3 | temp/ 4 | egret.d.ts 5 | libs/egret.d.ts 6 | /libs/ 7 | -------------------------------------------------------------------------------- /doc/sourceassets/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f111fei/2048egret/HEAD/doc/sourceassets/icon.png -------------------------------------------------------------------------------- /doc/sourceassets/tile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f111fei/2048egret/HEAD/doc/sourceassets/tile.png -------------------------------------------------------------------------------- /modules/puremvc/build.bat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f111fei/2048egret/HEAD/modules/puremvc/build.bat -------------------------------------------------------------------------------- /resource/assets/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f111fei/2048egret/HEAD/resource/assets/icon.png -------------------------------------------------------------------------------- /resource/assets/tile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f111fei/2048egret/HEAD/resource/assets/tile.png -------------------------------------------------------------------------------- /doc/sourceassets/button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f111fei/2048egret/HEAD/doc/sourceassets/button.png -------------------------------------------------------------------------------- /resource/assets/button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f111fei/2048egret/HEAD/resource/assets/button.png -------------------------------------------------------------------------------- /resource/assets/end_sun.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f111fei/2048egret/HEAD/resource/assets/end_sun.png -------------------------------------------------------------------------------- /doc/sourceassets/gamemenu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f111fei/2048egret/HEAD/doc/sourceassets/gamemenu.png -------------------------------------------------------------------------------- /resource/assets/end_close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f111fei/2048egret/HEAD/resource/assets/end_close.png -------------------------------------------------------------------------------- /resource/assets/end_cloud.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f111fei/2048egret/HEAD/resource/assets/end_cloud.png -------------------------------------------------------------------------------- /resource/assets/gamemenu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f111fei/2048egret/HEAD/resource/assets/gamemenu.png -------------------------------------------------------------------------------- /resource/assets/start_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f111fei/2048egret/HEAD/resource/assets/start_logo.png -------------------------------------------------------------------------------- /doc/sourceassets/start_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f111fei/2048egret/HEAD/doc/sourceassets/start_logo.png -------------------------------------------------------------------------------- /doc/sourceassets/end_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f111fei/2048egret/HEAD/doc/sourceassets/end_background.png -------------------------------------------------------------------------------- /doc/sourceassets/settingscreen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f111fei/2048egret/HEAD/doc/sourceassets/settingscreen.png -------------------------------------------------------------------------------- /resource/assets/end_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f111fei/2048egret/HEAD/resource/assets/end_background.png -------------------------------------------------------------------------------- /resource/assets/settingscreen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f111fei/2048egret/HEAD/resource/assets/settingscreen.png -------------------------------------------------------------------------------- /doc/sourceassets/about_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f111fei/2048egret/HEAD/doc/sourceassets/about_background.png -------------------------------------------------------------------------------- /doc/sourceassets/button/icon_down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f111fei/2048egret/HEAD/doc/sourceassets/button/icon_down.png -------------------------------------------------------------------------------- /doc/sourceassets/button/play_down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f111fei/2048egret/HEAD/doc/sourceassets/button/play_down.png -------------------------------------------------------------------------------- /doc/sourceassets/gametile/tile_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f111fei/2048egret/HEAD/doc/sourceassets/gametile/tile_1.png -------------------------------------------------------------------------------- /doc/sourceassets/gametile/tile_10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f111fei/2048egret/HEAD/doc/sourceassets/gametile/tile_10.png -------------------------------------------------------------------------------- /doc/sourceassets/gametile/tile_11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f111fei/2048egret/HEAD/doc/sourceassets/gametile/tile_11.png -------------------------------------------------------------------------------- /doc/sourceassets/gametile/tile_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f111fei/2048egret/HEAD/doc/sourceassets/gametile/tile_2.png -------------------------------------------------------------------------------- /doc/sourceassets/gametile/tile_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f111fei/2048egret/HEAD/doc/sourceassets/gametile/tile_3.png -------------------------------------------------------------------------------- /doc/sourceassets/gametile/tile_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f111fei/2048egret/HEAD/doc/sourceassets/gametile/tile_4.png -------------------------------------------------------------------------------- /doc/sourceassets/gametile/tile_5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f111fei/2048egret/HEAD/doc/sourceassets/gametile/tile_5.png -------------------------------------------------------------------------------- /doc/sourceassets/gametile/tile_6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f111fei/2048egret/HEAD/doc/sourceassets/gametile/tile_6.png -------------------------------------------------------------------------------- /doc/sourceassets/gametile/tile_7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f111fei/2048egret/HEAD/doc/sourceassets/gametile/tile_7.png -------------------------------------------------------------------------------- /doc/sourceassets/gametile/tile_8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f111fei/2048egret/HEAD/doc/sourceassets/gametile/tile_8.png -------------------------------------------------------------------------------- /doc/sourceassets/gametile/tile_9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f111fei/2048egret/HEAD/doc/sourceassets/gametile/tile_9.png -------------------------------------------------------------------------------- /doc/sourceassets/icon/level_easy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f111fei/2048egret/HEAD/doc/sourceassets/icon/level_easy.png -------------------------------------------------------------------------------- /doc/sourceassets/sence_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f111fei/2048egret/HEAD/doc/sourceassets/sence_background.png -------------------------------------------------------------------------------- /doc/sourceassets/start_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f111fei/2048egret/HEAD/doc/sourceassets/start_background.png -------------------------------------------------------------------------------- /resource/assets/about_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f111fei/2048egret/HEAD/resource/assets/about_background.png -------------------------------------------------------------------------------- /resource/assets/sence_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f111fei/2048egret/HEAD/resource/assets/sence_background.png -------------------------------------------------------------------------------- /resource/assets/start_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f111fei/2048egret/HEAD/resource/assets/start_background.png -------------------------------------------------------------------------------- /doc/sourceassets/button/custom_down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f111fei/2048egret/HEAD/doc/sourceassets/button/custom_down.png -------------------------------------------------------------------------------- /doc/sourceassets/button/icon_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f111fei/2048egret/HEAD/doc/sourceassets/button/icon_normal.png -------------------------------------------------------------------------------- /doc/sourceassets/button/music_down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f111fei/2048egret/HEAD/doc/sourceassets/button/music_down.png -------------------------------------------------------------------------------- /doc/sourceassets/button/music_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f111fei/2048egret/HEAD/doc/sourceassets/button/music_normal.png -------------------------------------------------------------------------------- /doc/sourceassets/button/pause_down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f111fei/2048egret/HEAD/doc/sourceassets/button/pause_down.png -------------------------------------------------------------------------------- /doc/sourceassets/button/pause_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f111fei/2048egret/HEAD/doc/sourceassets/button/pause_normal.png -------------------------------------------------------------------------------- /doc/sourceassets/button/play_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f111fei/2048egret/HEAD/doc/sourceassets/button/play_normal.png -------------------------------------------------------------------------------- /doc/sourceassets/button/retry2_down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f111fei/2048egret/HEAD/doc/sourceassets/button/retry2_down.png -------------------------------------------------------------------------------- /doc/sourceassets/button/retry_down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f111fei/2048egret/HEAD/doc/sourceassets/button/retry_down.png -------------------------------------------------------------------------------- /doc/sourceassets/button/retry_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f111fei/2048egret/HEAD/doc/sourceassets/button/retry_normal.png -------------------------------------------------------------------------------- /doc/sourceassets/button/return_down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f111fei/2048egret/HEAD/doc/sourceassets/button/return_down.png -------------------------------------------------------------------------------- /doc/sourceassets/button/setting_down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f111fei/2048egret/HEAD/doc/sourceassets/button/setting_down.png -------------------------------------------------------------------------------- /doc/sourceassets/button/sound_down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f111fei/2048egret/HEAD/doc/sourceassets/button/sound_down.png -------------------------------------------------------------------------------- /doc/sourceassets/button/sound_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f111fei/2048egret/HEAD/doc/sourceassets/button/sound_normal.png -------------------------------------------------------------------------------- /doc/sourceassets/gamemenu/highscroce.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f111fei/2048egret/HEAD/doc/sourceassets/gamemenu/highscroce.png -------------------------------------------------------------------------------- /doc/sourceassets/gametile/tile_stone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f111fei/2048egret/HEAD/doc/sourceassets/gametile/tile_stone.png -------------------------------------------------------------------------------- /doc/sourceassets/gametile/tile_water.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f111fei/2048egret/HEAD/doc/sourceassets/gametile/tile_water.png -------------------------------------------------------------------------------- /doc/sourceassets/icon/level_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f111fei/2048egret/HEAD/doc/sourceassets/icon/level_normal.png -------------------------------------------------------------------------------- /doc/sourceassets/icon/level_special.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f111fei/2048egret/HEAD/doc/sourceassets/icon/level_special.png -------------------------------------------------------------------------------- /doc/sourceassets/icon/loading_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f111fei/2048egret/HEAD/doc/sourceassets/icon/loading_logo.png -------------------------------------------------------------------------------- /doc/sourceassets/icon/loading_logo2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f111fei/2048egret/HEAD/doc/sourceassets/icon/loading_logo2.png -------------------------------------------------------------------------------- /doc/sourceassets/setting_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f111fei/2048egret/HEAD/doc/sourceassets/setting_background.png -------------------------------------------------------------------------------- /resource/assets/setting_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f111fei/2048egret/HEAD/resource/assets/setting_background.png -------------------------------------------------------------------------------- /doc/sourceassets/button/custom_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f111fei/2048egret/HEAD/doc/sourceassets/button/custom_normal.png -------------------------------------------------------------------------------- /doc/sourceassets/button/music_non_down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f111fei/2048egret/HEAD/doc/sourceassets/button/music_non_down.png -------------------------------------------------------------------------------- /doc/sourceassets/button/retry2_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f111fei/2048egret/HEAD/doc/sourceassets/button/retry2_normal.png -------------------------------------------------------------------------------- /doc/sourceassets/button/return_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f111fei/2048egret/HEAD/doc/sourceassets/button/return_normal.png -------------------------------------------------------------------------------- /doc/sourceassets/button/setting_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f111fei/2048egret/HEAD/doc/sourceassets/button/setting_normal.png -------------------------------------------------------------------------------- /doc/sourceassets/button/sound_non_down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f111fei/2048egret/HEAD/doc/sourceassets/button/sound_non_down.png -------------------------------------------------------------------------------- /doc/sourceassets/gametile/tile_shovel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f111fei/2048egret/HEAD/doc/sourceassets/gametile/tile_shovel.png -------------------------------------------------------------------------------- /doc/sourceassets/gametile/tile_stone2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f111fei/2048egret/HEAD/doc/sourceassets/gametile/tile_stone2.png -------------------------------------------------------------------------------- /doc/sourceassets/button/music_non_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f111fei/2048egret/HEAD/doc/sourceassets/button/music_non_normal.png -------------------------------------------------------------------------------- /doc/sourceassets/button/sound_non_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f111fei/2048egret/HEAD/doc/sourceassets/button/sound_non_normal.png -------------------------------------------------------------------------------- /doc/sourceassets/gamemenu/menubackground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f111fei/2048egret/HEAD/doc/sourceassets/gamemenu/menubackground.png -------------------------------------------------------------------------------- /doc/sourceassets/settingscreen/about_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f111fei/2048egret/HEAD/doc/sourceassets/settingscreen/about_logo.png -------------------------------------------------------------------------------- /doc/sourceassets/gamemenu/level_small_easy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f111fei/2048egret/HEAD/doc/sourceassets/gamemenu/level_small_easy.png -------------------------------------------------------------------------------- /doc/sourceassets/settingscreen/about_logo2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f111fei/2048egret/HEAD/doc/sourceassets/settingscreen/about_logo2.png -------------------------------------------------------------------------------- /doc/sourceassets/settingscreen/howtoplay_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f111fei/2048egret/HEAD/doc/sourceassets/settingscreen/howtoplay_1.png -------------------------------------------------------------------------------- /doc/sourceassets/settingscreen/howtoplay_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f111fei/2048egret/HEAD/doc/sourceassets/settingscreen/howtoplay_2.png -------------------------------------------------------------------------------- /doc/sourceassets/settingscreen/howtoplay_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f111fei/2048egret/HEAD/doc/sourceassets/settingscreen/howtoplay_3.png -------------------------------------------------------------------------------- /doc/sourceassets/settingscreen/howtoplay_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f111fei/2048egret/HEAD/doc/sourceassets/settingscreen/howtoplay_4.png -------------------------------------------------------------------------------- /doc/sourceassets/gamemenu/level_small_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f111fei/2048egret/HEAD/doc/sourceassets/gamemenu/level_small_normal.png -------------------------------------------------------------------------------- /doc/sourceassets/gamemenu/level_small_special.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f111fei/2048egret/HEAD/doc/sourceassets/gamemenu/level_small_special.png -------------------------------------------------------------------------------- /doc/sourceassets/settingscreen/howtoplay_next.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f111fei/2048egret/HEAD/doc/sourceassets/settingscreen/howtoplay_next.png -------------------------------------------------------------------------------- /doc/sourceassets/settingscreen/howtoplay_prev.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f111fei/2048egret/HEAD/doc/sourceassets/settingscreen/howtoplay_prev.png -------------------------------------------------------------------------------- /doc/sourceassets/settingscreen/howtoplay_return.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f111fei/2048egret/HEAD/doc/sourceassets/settingscreen/howtoplay_return.png -------------------------------------------------------------------------------- /src/org/xzper/app/AppConfig.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | module game { 4 | 5 | export class AppConfig { 6 | public constructor() { 7 | } 8 | } 9 | } -------------------------------------------------------------------------------- /src/org/xzper/app/IApp.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | module game { 4 | 5 | export interface IApp { 6 | enter(): void; 7 | destroy(): void; 8 | } 9 | } -------------------------------------------------------------------------------- /resource/theme.thm: -------------------------------------------------------------------------------- 1 | { 2 | "skins": 3 | { 4 | "egret.gui.Button":"skin.components.ButtonSkin", 5 | "game.IconButton":"skin.components.IconButtonSkin" 6 | } 7 | } -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "locale": "zh-CN" 5 | }, 6 | "exclude": [ 7 | "node_modules" 8 | ] 9 | } -------------------------------------------------------------------------------- /template/runtime/native_loader.js: -------------------------------------------------------------------------------- 1 | require("launcher/native_require.js"); 2 | 3 | egret_native.egtMain = function () { 4 | egret_native.nativeType = "native"; 5 | 6 | egret_native.egretInit(); 7 | egret_native.egretStart(); 8 | }; 9 | -------------------------------------------------------------------------------- /template/runtime/runtime_loader.js: -------------------------------------------------------------------------------- 1 | require("launcher/native_require.js"); 2 | 3 | egret_native.egtMain = function () { 4 | egret_native.nativeType = "runtime"; 5 | 6 | egret_native.egretInit(); 7 | egret_native.egretStart(); 8 | }; -------------------------------------------------------------------------------- /modules/puremvc/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "egret", 3 | "version": "2.5.0", 4 | "modules": [ 5 | { 6 | "name": "puremvc", 7 | "description": "puremvc", 8 | "files": ["puremvc.d.ts", "puremvc.js"], 9 | "root": "src" 10 | } 11 | ] 12 | } -------------------------------------------------------------------------------- /src/org/xzper/model/common/Level.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by xzper on 2014/11/15. 3 | */ 4 | 5 | module game { 6 | /** 7 | * 游戏等级常量 8 | */ 9 | export class Level { 10 | public static EASY: string = "easy"; 11 | public static NORMAL: string = "normal"; 12 | public static SPECIAL: string = "special"; 13 | } 14 | } -------------------------------------------------------------------------------- /src/components/IconButton.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by xzper on 2014/11/15. 3 | */ 4 | 5 | module game { 6 | /** 7 | * 带图标的按钮 8 | */ 9 | export class IconButton extends egret.gui.Button { 10 | 11 | public constructor() { 12 | super(); 13 | this.skinName = skin.components.IconButtonSkin; 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /src/skin/components/ReturnSkin.exml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/skin/components/CloseButtonSkin.exml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/skin/components/RetryButtonSkin.exml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/org/xzper/controller/ControllerPrepCommand.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | module game { 4 | 5 | export class ControllerPrepCommand extends puremvc.SimpleCommand implements puremvc.ICommand { 6 | 7 | public constructor() { 8 | super(); 9 | } 10 | public execute(notification: puremvc.INotification): void { 11 | (new GameCommand()).register(); 12 | (new SceneCommand()).register(); 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /src/org/xzper/controller/StartupCommand.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | module game { 4 | 5 | export class StartupCommand extends puremvc.MacroCommand { 6 | 7 | public constructor() { 8 | super(); 9 | } 10 | public initializeMacroCommand(): void { 11 | this.addSubCommand(ControllerPrepCommand); 12 | this.addSubCommand(ModelPrepCommand); 13 | this.addSubCommand(ViewPrepCommand); 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /src/org/xzper/controller/ModelPrepCommand.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | module game { 4 | 5 | export class ModelPrepCommand extends puremvc.SimpleCommand implements puremvc.ICommand { 6 | 7 | public constructor() { 8 | super(); 9 | } 10 | public execute(notification: puremvc.INotification): void { 11 | this.facade.registerProxy(new GameProxy()); 12 | this.facade.registerProxy(new GridProxy()); 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /src/skin/components/PauseButtonSkin.exml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/skin/components/SettingButtonSkin.exml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/org/xzper/controller/ViewPrepCommand.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | module game { 4 | 5 | export class ViewPrepCommand extends puremvc.SimpleCommand implements puremvc.ICommand { 6 | 7 | public constructor() { 8 | super(); 9 | } 10 | public execute(notification: puremvc.INotification): void { 11 | var main: AppContainer = notification.getBody(); 12 | this.facade.registerMediator(new ApplicationMediator(main)); 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /egretProperties.json: -------------------------------------------------------------------------------- 1 | { 2 | "native": { 3 | "path_ignore": [] 4 | }, 5 | "publish": { 6 | "web": 0, 7 | "native": 1, 8 | "path": "bin-release" 9 | }, 10 | "egret_version": "2.5.0", 11 | "modules": [ 12 | { 13 | "name": "egret" 14 | }, 15 | { 16 | "name": "game" 17 | }, 18 | { 19 | "name": "res" 20 | }, 21 | { 22 | "name": "tween" 23 | }, 24 | { 25 | "name": "gui" 26 | }, 27 | { 28 | "name": "puremvc", 29 | "path": "modules/puremvc" 30 | } 31 | ] 32 | } -------------------------------------------------------------------------------- /doc/sourceassets/icon.json: -------------------------------------------------------------------------------- 1 | {"file":"icon.png","frames":{ 2 | "level_easy":{"x":1,"y":1,"w":67,"h":67,"offX":0,"offY":0,"sourceW":67,"sourceH":67}, 3 | "level_normal":{"x":1,"y":70,"w":67,"h":67,"offX":0,"offY":0,"sourceW":67,"sourceH":67}, 4 | "level_special":{"x":1,"y":139,"w":67,"h":67,"offX":0,"offY":0,"sourceW":67,"sourceH":67}, 5 | "loading_logo":{"x":1,"y":208,"w":480,"h":101,"offX":1,"offY":1,"sourceW":482,"sourceH":103}, 6 | "loading_logo2":{"x":70,"y":1,"w":344,"h":142,"offX":0,"offY":0,"sourceW":344,"sourceH":142}}} -------------------------------------------------------------------------------- /resource/assets/icon.json: -------------------------------------------------------------------------------- 1 | {"file":"icon.png","frames":{ 2 | "level_easy":{"x":1,"y":1,"w":67,"h":67,"offX":0,"offY":0,"sourceW":67,"sourceH":67}, 3 | "level_normal":{"x":1,"y":70,"w":67,"h":67,"offX":0,"offY":0,"sourceW":67,"sourceH":67}, 4 | "level_special":{"x":1,"y":139,"w":67,"h":67,"offX":0,"offY":0,"sourceW":67,"sourceH":67}, 5 | "loading_logo":{"x":1,"y":208,"w":480,"h":101,"offX":1,"offY":1,"sourceW":482,"sourceH":103}, 6 | "loading_logo2":{"x":70,"y":1,"w":344,"h":142,"offX":0,"offY":0,"sourceW":344,"sourceH":142}}} -------------------------------------------------------------------------------- /doc/sourceassets/gamemenu.json: -------------------------------------------------------------------------------- 1 | {"file":"gamemenu.png","frames":{ 2 | "highscroce":{"x":1,"y":1,"w":24,"h":20,"offX":0,"offY":0,"sourceW":24,"sourceH":20}, 3 | "level_small_easy":{"x":27,"y":1,"w":22,"h":22,"offX":0,"offY":0,"sourceW":22,"sourceH":22}, 4 | "level_small_normal":{"x":1,"y":23,"w":22,"h":22,"offX":0,"offY":0,"sourceW":22,"sourceH":22}, 5 | "level_small_special":{"x":51,"y":1,"w":22,"h":22,"offX":0,"offY":0,"sourceW":22,"sourceH":22}, 6 | "menubackground":{"x":25,"y":25,"w":640,"h":117,"offX":0,"offY":0,"sourceW":640,"sourceH":117}}} -------------------------------------------------------------------------------- /resource/assets/gamemenu.json: -------------------------------------------------------------------------------- 1 | {"file":"gamemenu.png","frames":{ 2 | "highscroce":{"x":1,"y":1,"w":24,"h":20,"offX":0,"offY":0,"sourceW":24,"sourceH":20}, 3 | "level_small_easy":{"x":27,"y":1,"w":22,"h":22,"offX":0,"offY":0,"sourceW":22,"sourceH":22}, 4 | "level_small_normal":{"x":1,"y":23,"w":22,"h":22,"offX":0,"offY":0,"sourceW":22,"sourceH":22}, 5 | "level_small_special":{"x":51,"y":1,"w":22,"h":22,"offX":0,"offY":0,"sourceW":22,"sourceH":22}, 6 | "menubackground":{"x":25,"y":25,"w":640,"h":117,"offX":0,"offY":0,"sourceW":640,"sourceH":117}}} -------------------------------------------------------------------------------- /src/skin/MainGameUISkin.exml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/skin/components/ProgressBarSkin.exml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/skin/components/PlayButtonSkin.exml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/skin/components/ButtonSkin.exml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/skin/components/MusicButonSkin.exml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/skin/components/SoundButtonSkin.exml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/skin/components/IconButtonSkin.exml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/skin/LoadingUISkin.exml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/org/xzper/view/ApplicationMediator.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | module game { 4 | 5 | export class ApplicationMediator extends puremvc.Mediator implements puremvc.IMediator { 6 | public static NAME: string = "ApplicationMediator"; 7 | public constructor(viewComponent: any) { 8 | super(ApplicationMediator.NAME, viewComponent); 9 | } 10 | 11 | public listNotificationInterests(): Array { 12 | return []; 13 | } 14 | 15 | public handleNotification(notification: puremvc.INotification): void { 16 | switch (notification.getName()) { 17 | } 18 | } 19 | 20 | public get main(): AppContainer { 21 | return (this.viewComponent); 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /src/org/xzper/view/panel/GameScreen.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by xzper on 2014/11/15. 3 | */ 4 | 5 | module game { 6 | 7 | export class GameScreen extends egret.gui.SkinnableComponent { 8 | 9 | public constructor() { 10 | super(); 11 | this.skinName = skin.MainGameUISkin; 12 | this.addEventListener(egret.gui.UIEvent.CREATION_COMPLETE, this.createCompleteEvent, this); 13 | } 14 | 15 | public createCompleteEvent(event: egret.gui.UIEvent): void { 16 | this.removeEventListener(egret.gui.UIEvent.CREATION_COMPLETE, this.createCompleteEvent, this); 17 | ApplicationFacade.getInstance().registerMediator(new GameScreenMediator(this)); 18 | } 19 | 20 | public gameMenuUI: GameMenuUI; 21 | public gameSceneUI: GameScene; 22 | } 23 | } -------------------------------------------------------------------------------- /src/org/xzper/view/panel/AboutWindow.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by xzper on 2014/11/15. 3 | */ 4 | 5 | module game { 6 | 7 | export class AboutWindow extends egret.gui.SkinnableComponent { 8 | 9 | public constructor() { 10 | super(); 11 | this.skinName = skin.AboutSkin; 12 | } 13 | 14 | public backButton: egret.gui.Button; 15 | 16 | public partAdded(partName: string, instance: any): void { 17 | super.partAdded(partName, instance); 18 | if (instance == this.backButton) { 19 | this.backButton.addEventListener(egret.TouchEvent.TOUCH_TAP, this.onBackButtonClick, this); 20 | } 21 | } 22 | 23 | private onBackButtonClick(event: egret.TouchEvent): void { 24 | egret.gui.PopUpManager.removePopUp(this); 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /src/org/xzper/model/vos/TileVO.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | module game { 4 | 5 | export class TileVO { 6 | /** 7 | * 列 8 | */ 9 | public x: number; 10 | 11 | /** 12 | * 行 13 | */ 14 | public y: number; 15 | 16 | /** 17 | * 数值 18 | */ 19 | public value: number; 20 | 21 | /** 22 | * 是否已合并 23 | */ 24 | public merged: boolean; 25 | /** 26 | * 移动之前的位置 27 | */ 28 | public previousPosition: any; 29 | 30 | public constructor() { 31 | } 32 | 33 | public clone(): TileVO { 34 | var tileVO: TileVO = new TileVO(); 35 | tileVO.x = this.x; 36 | tileVO.y = this.y; 37 | tileVO.value = this.value; 38 | if (this.previousPosition) { 39 | tileVO.previousPosition = { "x": this.previousPosition.x, "y": this.previousPosition.y }; 40 | } 41 | tileVO.merged = this.merged; 42 | return tileVO; 43 | } 44 | 45 | } 46 | } -------------------------------------------------------------------------------- /src/skin/StartScreenSkin.exml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /doc/sourceassets/settingscreen.json: -------------------------------------------------------------------------------- 1 | {"file":"settingscreen.png","frames":{ 2 | "about_logo":{"x":1,"y":1,"w":269,"h":65,"offX":1,"offY":1,"sourceW":272,"sourceH":67}, 3 | "about_logo2":{"x":272,"y":1,"w":278,"h":152,"offX":0,"offY":0,"sourceW":278,"sourceH":152}, 4 | "howtoplay_1":{"x":552,"y":1,"w":292,"h":185,"offX":0,"offY":0,"sourceW":292,"sourceH":185}, 5 | "howtoplay_2":{"x":1,"y":155,"w":350,"h":157,"offX":1,"offY":0,"sourceW":353,"sourceH":158}, 6 | "howtoplay_3":{"x":1,"y":314,"w":212,"h":140,"offX":0,"offY":0,"sourceW":213,"sourceH":140}, 7 | "howtoplay_4":{"x":215,"y":314,"w":316,"h":150,"offX":0,"offY":1,"sourceW":316,"sourceH":151}, 8 | "howtoplay_next":{"x":1,"y":68,"w":66,"h":65,"offX":0,"offY":0,"sourceW":66,"sourceH":65}, 9 | "howtoplay_prev":{"x":69,"y":68,"w":66,"h":65,"offX":0,"offY":0,"sourceW":66,"sourceH":65}, 10 | "howtoplay_return":{"x":137,"y":68,"w":65,"h":65,"offX":0,"offY":0,"sourceW":65,"sourceH":65}}} -------------------------------------------------------------------------------- /resource/assets/settingscreen.json: -------------------------------------------------------------------------------- 1 | {"file":"settingscreen.png","frames":{ 2 | "about_logo":{"x":1,"y":1,"w":269,"h":65,"offX":1,"offY":1,"sourceW":272,"sourceH":67}, 3 | "about_logo2":{"x":272,"y":1,"w":278,"h":152,"offX":0,"offY":0,"sourceW":278,"sourceH":152}, 4 | "howtoplay_1":{"x":552,"y":1,"w":292,"h":185,"offX":0,"offY":0,"sourceW":292,"sourceH":185}, 5 | "howtoplay_2":{"x":1,"y":155,"w":350,"h":157,"offX":1,"offY":0,"sourceW":353,"sourceH":158}, 6 | "howtoplay_3":{"x":1,"y":314,"w":212,"h":140,"offX":0,"offY":0,"sourceW":213,"sourceH":140}, 7 | "howtoplay_4":{"x":215,"y":314,"w":316,"h":150,"offX":0,"offY":1,"sourceW":316,"sourceH":151}, 8 | "howtoplay_next":{"x":1,"y":68,"w":66,"h":65,"offX":0,"offY":0,"sourceW":66,"sourceH":65}, 9 | "howtoplay_prev":{"x":69,"y":68,"w":66,"h":65,"offX":0,"offY":0,"sourceW":66,"sourceH":65}, 10 | "howtoplay_return":{"x":137,"y":68,"w":65,"h":65,"offX":0,"offY":0,"sourceW":65,"sourceH":65}}} -------------------------------------------------------------------------------- /src/org/xzper/model/common/CommonData.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | module game { 4 | 5 | export class CommonData { 6 | /** 7 | * 游戏胜利时的数字 8 | */ 9 | public static winValue: number = 2048; 10 | 11 | /** 12 | * 游戏的大小 13 | */ 14 | public static get size(): number { 15 | if (CommonData.level == Level.EASY) 16 | return 6; 17 | else if (CommonData.level == Level.NORMAL) 18 | return 5; 19 | else if (CommonData.level == Level.SPECIAL) 20 | return 4; 21 | } 22 | 23 | /** 24 | * 当前游戏等级 25 | */ 26 | public static level: string = Level.NORMAL; 27 | 28 | /** 29 | * 最高分 30 | */ 31 | public static highScore: number = 0; 32 | 33 | /** 34 | * 游戏是否开始 35 | */ 36 | public static isRunning: boolean = false; 37 | 38 | public constructor() { 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /src/org/xzper/view/panel/StartScreen.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by xzper on 2014/11/15. 3 | */ 4 | 5 | module game { 6 | 7 | export class StartScreen extends egret.gui.SkinnableComponent { 8 | 9 | public constructor() { 10 | super(); 11 | this.skinName = skin.StartScreenSkin; 12 | this.addEventListener(egret.gui.UIEvent.CREATION_COMPLETE, this.createCompleteEvent, this); 13 | } 14 | 15 | public createCompleteEvent(event: egret.gui.UIEvent): void { 16 | this.removeEventListener(egret.gui.UIEvent.CREATION_COMPLETE, this.createCompleteEvent, this); 17 | ApplicationFacade.getInstance().registerMediator(new StartScreenMediator(this)); 18 | } 19 | 20 | public playButton: egret.gui.Button; 21 | public settingButton: egret.gui.Button; 22 | public levelButton: IconButton; 23 | 24 | 25 | public partAdded(partName: string, instance: any): void { 26 | super.partAdded(partName, instance); 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /src/skin/AboutSkin.exml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/org/xzper/ApplicationFacade.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | module game { 4 | 5 | export class ApplicationFacade extends puremvc.Facade implements puremvc.IFacade { 6 | 7 | public constructor() { 8 | super(); 9 | } 10 | public static STARTUP: string = "startup"; 11 | 12 | public static getInstance(): ApplicationFacade { 13 | if (this.instance == null) this.instance = new ApplicationFacade(); 14 | return (this.instance); 15 | } 16 | 17 | public initializeController(): void { 18 | super.initializeController(); 19 | this.registerCommand(ApplicationFacade.STARTUP, StartupCommand); 20 | } 21 | 22 | /** 23 | * 启动PureMVC,在应用程序中调用此方法,并传递应用程序本身的引用 24 | * @param rootView - PureMVC应用程序的根视图root,包含其它所有的View Componet 25 | */ 26 | public startUp(rootView: egret.DisplayObjectContainer): void { 27 | this.sendNotification(ApplicationFacade.STARTUP, rootView); 28 | this.removeCommand(ApplicationFacade.STARTUP); //PureMVC初始化完成,注销STARUP命令 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /src/org/xzper/utils/ObjectPool.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by xzp on 2014/6/18. 3 | */ 4 | 5 | module game { 6 | export class ObjectPool { 7 | 8 | private static pool: Object = {}; 9 | 10 | private list: Array; 11 | 12 | private className: string; 13 | 14 | public constructor(className: string) { 15 | this.className = className; 16 | this.list = []; 17 | } 18 | 19 | /** 20 | * 获取对象 21 | */ 22 | public borrowObject(): any { 23 | if (this.list.length > 0) { 24 | return this.list.shift(); 25 | } 26 | var clazz: any = egret.getDefinitionByName(this.className); 27 | return new clazz(); 28 | } 29 | 30 | /** 31 | * 回收对象 32 | */ 33 | public returnObject(value: any): void { 34 | this.list.push(value); 35 | } 36 | 37 | public static getPool(className: string): ObjectPool { 38 | if (!ObjectPool.pool[className]) { 39 | ObjectPool.pool[className] = new ObjectPool(className); 40 | } 41 | return ObjectPool.pool[className]; 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /src/skin/GameMenuSkin.exml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /src/skin/HowtoPlaySkin.exml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /doc/sourceassets/tile.json: -------------------------------------------------------------------------------- 1 | {"file":"tile.png","frames":{ 2 | "tile_water":{"x":1,"y":1,"w":140,"h":140,"offX":0,"offY":0,"sourceW":140,"sourceH":140}, 3 | "tile_1":{"x":1,"y":143,"w":140,"h":140,"offX":0,"offY":0,"sourceW":140,"sourceH":140}, 4 | "tile_2":{"x":1,"y":285,"w":140,"h":140,"offX":0,"offY":0,"sourceW":140,"sourceH":140}, 5 | "tile_3":{"x":143,"y":1,"w":140,"h":140,"offX":0,"offY":0,"sourceW":140,"sourceH":140}, 6 | "tile_4":{"x":143,"y":143,"w":140,"h":140,"offX":0,"offY":0,"sourceW":140,"sourceH":140}, 7 | "tile_5":{"x":143,"y":285,"w":140,"h":140,"offX":0,"offY":0,"sourceW":140,"sourceH":140}, 8 | "tile_6":{"x":285,"y":1,"w":140,"h":140,"offX":0,"offY":0,"sourceW":140,"sourceH":140}, 9 | "tile_7":{"x":285,"y":143,"w":140,"h":140,"offX":0,"offY":0,"sourceW":140,"sourceH":140}, 10 | "tile_8":{"x":285,"y":285,"w":140,"h":140,"offX":0,"offY":0,"sourceW":140,"sourceH":140}, 11 | "tile_9":{"x":427,"y":1,"w":140,"h":140,"offX":0,"offY":0,"sourceW":140,"sourceH":140}, 12 | "tile_10":{"x":427,"y":143,"w":140,"h":140,"offX":0,"offY":0,"sourceW":140,"sourceH":140}, 13 | "tile_11":{"x":427,"y":285,"w":140,"h":140,"offX":0,"offY":0,"sourceW":140,"sourceH":140}, 14 | "tile_shovel":{"x":569,"y":1,"w":140,"h":140,"offX":0,"offY":0,"sourceW":140,"sourceH":140}, 15 | "tile_stone":{"x":711,"y":1,"w":140,"h":140,"offX":0,"offY":0,"sourceW":140,"sourceH":140}, 16 | "tile_stone2":{"x":853,"y":1,"w":140,"h":140,"offX":0,"offY":0,"sourceW":140,"sourceH":140}}} -------------------------------------------------------------------------------- /resource/assets/tile.json: -------------------------------------------------------------------------------- 1 | {"file":"tile.png","frames":{ 2 | "tile_water":{"x":1,"y":1,"w":140,"h":140,"offX":0,"offY":0,"sourceW":140,"sourceH":140}, 3 | "tile_1":{"x":1,"y":143,"w":140,"h":140,"offX":0,"offY":0,"sourceW":140,"sourceH":140}, 4 | "tile_2":{"x":1,"y":285,"w":140,"h":140,"offX":0,"offY":0,"sourceW":140,"sourceH":140}, 5 | "tile_3":{"x":143,"y":1,"w":140,"h":140,"offX":0,"offY":0,"sourceW":140,"sourceH":140}, 6 | "tile_4":{"x":143,"y":143,"w":140,"h":140,"offX":0,"offY":0,"sourceW":140,"sourceH":140}, 7 | "tile_5":{"x":143,"y":285,"w":140,"h":140,"offX":0,"offY":0,"sourceW":140,"sourceH":140}, 8 | "tile_6":{"x":285,"y":1,"w":140,"h":140,"offX":0,"offY":0,"sourceW":140,"sourceH":140}, 9 | "tile_7":{"x":285,"y":143,"w":140,"h":140,"offX":0,"offY":0,"sourceW":140,"sourceH":140}, 10 | "tile_8":{"x":285,"y":285,"w":140,"h":140,"offX":0,"offY":0,"sourceW":140,"sourceH":140}, 11 | "tile_9":{"x":427,"y":1,"w":140,"h":140,"offX":0,"offY":0,"sourceW":140,"sourceH":140}, 12 | "tile_10":{"x":427,"y":143,"w":140,"h":140,"offX":0,"offY":0,"sourceW":140,"sourceH":140}, 13 | "tile_11":{"x":427,"y":285,"w":140,"h":140,"offX":0,"offY":0,"sourceW":140,"sourceH":140}, 14 | "tile_shovel":{"x":569,"y":1,"w":140,"h":140,"offX":0,"offY":0,"sourceW":140,"sourceH":140}, 15 | "tile_stone":{"x":711,"y":1,"w":140,"h":140,"offX":0,"offY":0,"sourceW":140,"sourceH":140}, 16 | "tile_stone2":{"x":853,"y":1,"w":140,"h":140,"offX":0,"offY":0,"sourceW":140,"sourceH":140}}} -------------------------------------------------------------------------------- /src/org/xzper/view/panel/EndWindow.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by xzper on 2014/11/15. 3 | */ 4 | module game { 5 | 6 | export class EndWindow extends egret.gui.TitleWindow { 7 | 8 | public constructor() { 9 | super(); 10 | this.title = "Well Done!"; 11 | this.skinName = skin.EndScreenSkin; 12 | this.addEventListener(egret.gui.UIEvent.CREATION_COMPLETE, this.createCompleteEvent, this); 13 | } 14 | 15 | public createCompleteEvent(event: egret.gui.UIEvent): void { 16 | this.removeEventListener(egret.gui.UIEvent.CREATION_COMPLETE, this.createCompleteEvent, this); 17 | ApplicationFacade.getInstance().registerMediator(new EndWindowMediator(this)); 18 | } 19 | 20 | public show(): void { 21 | this.invalidateSkinState(); 22 | egret.gui.PopUpManager.addPopUp(this, true); 23 | } 24 | 25 | public close(): void { 26 | egret.gui.PopUpManager.removePopUp(this); 27 | this.validateSkinState(); 28 | } 29 | 30 | public getCurrentSkinState(): string { 31 | if (this.parent) 32 | return "open"; 33 | else 34 | return "close"; 35 | } 36 | 37 | public totalScoreLabel: egret.gui.Label; 38 | public highScoreLabel: egret.gui.Label; 39 | 40 | public retryButton: egret.gui.Button; 41 | public returnButton: egret.gui.Button; 42 | 43 | public partAdded(partName: string, instance: any): void { 44 | super.partAdded(partName, instance); 45 | } 46 | } 47 | } -------------------------------------------------------------------------------- /src/org/xzper/view/GameMenuMediator.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | module game { 4 | 5 | export class GameMenuMediator extends puremvc.Mediator implements puremvc.IMediator { 6 | public static NAME: string = "GameMenuMediator"; 7 | 8 | public constructor(viewComponent: any) { 9 | super(GameMenuMediator.NAME, viewComponent); 10 | this.gameMenuUI.pauseButton.addEventListener(egret.TouchEvent.TOUCH_TAP, this.pauseButtonClick, this); 11 | } 12 | 13 | public pauseButtonClick(event: egret.TouchEvent): void { 14 | this.sendNotification(SceneCommand.SHOW_SETTING, "pause"); 15 | } 16 | 17 | public listNotificationInterests(): Array { 18 | return [GameProxy.SCORE_UPDATE, GameProxy.SCORE_RESET]; 19 | } 20 | 21 | public handleNotification(notification: puremvc.INotification): void { 22 | var data: any = notification.getBody(); 23 | switch (notification.getName()) { 24 | case GameProxy.SCORE_UPDATE: { 25 | this.gameMenuUI.scoreLabel.text = data["totalScore"].toString(); 26 | this.gameMenuUI.highScoreLabel.text = data["highScore"].toString(); 27 | // this.gameMenuUI.playScoreEffect(data["addScore"]); 28 | break; 29 | } 30 | 31 | case GameProxy.SCORE_RESET: { 32 | this.gameMenuUI.reset(); 33 | break; 34 | } 35 | } 36 | } 37 | 38 | public get gameMenuUI(): GameMenuUI { 39 | return (this.viewComponent); 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /src/org/xzper/view/panel/GameMenuUI.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by xzper on 2014/11/15. 3 | */ 4 | module game { 5 | 6 | /** 7 | * 游戏菜单 8 | */ 9 | export class GameMenuUI extends egret.gui.SkinnableComponent { 10 | 11 | public constructor() { 12 | super(); 13 | this.skinName = skin.GameMenuSkin; 14 | this.addEventListener(egret.gui.UIEvent.CREATION_COMPLETE, this.createCompleteEvent, this); 15 | } 16 | 17 | public createCompleteEvent(event: egret.gui.UIEvent): void { 18 | this.removeEventListener(egret.gui.UIEvent.CREATION_COMPLETE, this.createCompleteEvent, this); 19 | ApplicationFacade.getInstance().registerMediator(new GameMenuMediator(this)); 20 | } 21 | 22 | private resetFlag: boolean = true; 23 | /** 24 | * 重置数据 25 | */ 26 | public reset(): void { 27 | this.resetFlag = true; 28 | this.invalidateProperties(); 29 | } 30 | 31 | public commitProperties(): void { 32 | if (this.resetFlag) { 33 | this.resetFlag = false; 34 | this.scoreLabel.text = "0"; 35 | this.highScoreLabel.text = CommonData.highScore.toString(); 36 | this.levelLabel.text = CommonData.level.toLocaleUpperCase(); 37 | this.levelIcon.source = "level_small_" + CommonData.level; 38 | } 39 | } 40 | 41 | public scoreLabel: egret.gui.Label; 42 | public highScoreLabel: egret.gui.Label; 43 | public levelLabel: egret.gui.Label; 44 | public levelIcon: egret.gui.UIAsset; 45 | public pauseButton: egret.gui.Button; 46 | 47 | } 48 | } -------------------------------------------------------------------------------- /src/org/xzper/view/panel/HowtoplayWindow.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by xzper on 2014/11/15. 3 | */ 4 | 5 | module game { 6 | 7 | export class HowtoplayWindow extends egret.gui.SkinnableComponent { 8 | 9 | public constructor() { 10 | super(); 11 | this.skinName = skin.HowtoPlaySkin; 12 | } 13 | 14 | public prevButton: egret.gui.Button; 15 | public nextButton: egret.gui.Button; 16 | 17 | public partAdded(partName: string, instance: any): void { 18 | super.partAdded(partName, instance); 19 | if (instance == this.prevButton) { 20 | this.prevButton.addEventListener(egret.TouchEvent.TOUCH_TAP, this.onPrevButtonClick, this); 21 | } 22 | else if (instance == this.nextButton) { 23 | this.nextButton.addEventListener(egret.TouchEvent.TOUCH_TAP, this.onNextButtonClick, this); 24 | } 25 | } 26 | 27 | private onPrevButtonClick(event: egret.TouchEvent): void { 28 | if (this.state == 1) { 29 | egret.gui.PopUpManager.removePopUp(this); 30 | } 31 | else { 32 | this.state--; 33 | this.invalidateSkinState(); 34 | } 35 | } 36 | 37 | private onNextButtonClick(event: egret.TouchEvent): void { 38 | if (this.state == 4) { 39 | egret.gui.PopUpManager.removePopUp(this); 40 | } 41 | else { 42 | this.state++; 43 | this.invalidateSkinState(); 44 | } 45 | } 46 | 47 | private state: number = 1; 48 | public getCurrentSkinState(): string { 49 | return "s" + this.state; 50 | } 51 | } 52 | } -------------------------------------------------------------------------------- /src/libs/exml.g.d.ts: -------------------------------------------------------------------------------- 1 | declare module skin{ 2 | class AboutSkin extends egret.gui.Skin{ 3 | } 4 | } 5 | declare module skin.components{ 6 | class ButtonSkin extends egret.gui.Skin{ 7 | } 8 | } 9 | declare module skin.components{ 10 | class CloseButtonSkin extends egret.gui.Skin{ 11 | } 12 | } 13 | declare module skin.components{ 14 | class IconButtonSkin extends egret.gui.Skin{ 15 | } 16 | } 17 | declare module skin.components{ 18 | class MusicButonSkin extends egret.gui.Skin{ 19 | } 20 | } 21 | declare module skin.components{ 22 | class PauseButtonSkin extends egret.gui.Skin{ 23 | } 24 | } 25 | declare module skin.components{ 26 | class PlayButtonSkin extends egret.gui.Skin{ 27 | } 28 | } 29 | declare module skin.components{ 30 | class ProgressBarSkin extends egret.gui.Skin{ 31 | } 32 | } 33 | declare module skin.components{ 34 | class RetryButtonSkin extends egret.gui.Skin{ 35 | } 36 | } 37 | declare module skin.components{ 38 | class ReturnSkin extends egret.gui.Skin{ 39 | } 40 | } 41 | declare module skin.components{ 42 | class SettingButtonSkin extends egret.gui.Skin{ 43 | } 44 | } 45 | declare module skin.components{ 46 | class SoundButtonSkin extends egret.gui.Skin{ 47 | } 48 | } 49 | declare module skin{ 50 | class EndScreenSkin extends egret.gui.Skin{ 51 | } 52 | } 53 | declare module skin{ 54 | class GameMenuSkin extends egret.gui.Skin{ 55 | } 56 | } 57 | declare module skin{ 58 | class HowtoPlaySkin extends egret.gui.Skin{ 59 | } 60 | } 61 | declare module skin{ 62 | class LoadingUISkin extends egret.gui.Skin{ 63 | } 64 | } 65 | declare module skin{ 66 | class MainGameUISkin extends egret.gui.Skin{ 67 | } 68 | } 69 | declare module skin{ 70 | class SettingScreenSkin extends egret.gui.Skin{ 71 | } 72 | } 73 | declare module skin{ 74 | class StartScreenSkin extends egret.gui.Skin{ 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/org/xzper/model/GameProxy.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | module game { 4 | 5 | export class GameProxy extends puremvc.Proxy implements puremvc.IProxy { 6 | public static NAME: string = "GameProxy"; 7 | 8 | /** 9 | * 分数更新 , body {totalScore:int , addScore:int} 10 | */ 11 | public static SCORE_UPDATE: string = "score_update"; 12 | 13 | /** 14 | * 游戏重置 15 | */ 16 | public static SCORE_RESET: string = "score_reset"; 17 | 18 | private won: boolean = false; 19 | private over: boolean = false; 20 | 21 | 22 | public constructor() { 23 | super(GameProxy.NAME); 24 | } 25 | 26 | private _score: number = 0; 27 | /** 28 | * 游戏分数 29 | */ 30 | public get score(): number { 31 | return this._score; 32 | } 33 | 34 | /** 35 | * 重置游戏数据 36 | */ 37 | public reset(): void { 38 | this._score = 0; 39 | this.won = false; 40 | this.over = false; 41 | CommonData.isRunning = true; 42 | this.sendNotification(GameProxy.SCORE_RESET); 43 | } 44 | 45 | /** 46 | * 更新分数 47 | */ 48 | public updateScore(addScore: number): void { 49 | if (addScore != 0) { 50 | this._score += addScore; 51 | if (this._score > CommonData.highScore) 52 | CommonData.highScore = this._score; 53 | this.sendNotification(GameProxy.SCORE_UPDATE, { "totalScore": this.score, "highScore": CommonData.highScore, "addScore": addScore }); 54 | } 55 | } 56 | 57 | /** 58 | * 游戏是否胜利 59 | */ 60 | public setResult(b: boolean): void { 61 | if (b) { 62 | this.won = true; 63 | } else { 64 | this.over = true; 65 | } 66 | CommonData.isRunning = false; 67 | } 68 | 69 | /** 70 | * 游戏中断退出 71 | */ 72 | public quit(): void { 73 | this.reset(); 74 | this.over = true; 75 | CommonData.isRunning = false; 76 | } 77 | } 78 | } -------------------------------------------------------------------------------- /src/org/xzper/view/GameSceneMediator.ts: -------------------------------------------------------------------------------- 1 | 2 | module game { 3 | /** 4 | * 游戏场景中介器 5 | */ 6 | export class GameSceneMediator extends puremvc.Mediator implements puremvc.IMediator { 7 | public static NAME: string = "GameSceneMediator"; 8 | 9 | public constructor(viewComponent: any) { 10 | super(GameSceneMediator.NAME, viewComponent); 11 | } 12 | 13 | public listNotificationInterests(): Array { 14 | return [ 15 | GridProxy.TILE_INSERT, 16 | GridProxy.TILE_MERGED, 17 | GridProxy.TILE_MOVE, 18 | GridProxy.TILE_REMOVE, 19 | GridProxy.TILE_RESET 20 | ]; 21 | } 22 | 23 | public handleNotification(notification: puremvc.INotification): void { 24 | var data: any = notification.getBody(); 25 | switch (notification.getName()) { 26 | case GridProxy.TILE_INSERT: { 27 | this.gameScene.createTile(data); 28 | break; 29 | } 30 | 31 | case GridProxy.TILE_MERGED: { 32 | this.gameScene.mergedTile(data); 33 | break; 34 | } 35 | 36 | case GridProxy.TILE_MOVE: { 37 | this.gameScene.moveTile(data); 38 | break; 39 | } 40 | 41 | case GridProxy.TILE_REMOVE: { 42 | this.gameScene.removeTile(data); 43 | break; 44 | } 45 | case GridProxy.TILE_RESET: { 46 | this.gameScene.clearTiles(); 47 | break; 48 | } 49 | } 50 | } 51 | 52 | public get gameScene(): GameScene { 53 | return (this.viewComponent); 54 | } 55 | } 56 | } -------------------------------------------------------------------------------- /src/org/xzper/view/panel/TileUI.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | module game { 4 | 5 | export class TileUI extends egret.Bitmap { 6 | 7 | public constructor() { 8 | super(); 9 | //使描点在中心 10 | this.location = { "x": 0, "y": 0 }; 11 | } 12 | 13 | /** 14 | * 行列位置 15 | */ 16 | public location: any; 17 | 18 | private _value: number; 19 | /** 20 | * 格子的数字 21 | */ 22 | public get value(): number { 23 | return this._value; 24 | } 25 | 26 | public set value(value: number) { 27 | if (value == this._value) { 28 | return; 29 | } 30 | this._value = value; 31 | this.updateValue(); 32 | } 33 | 34 | private updateValue(): void { 35 | var mi: number = Math.log(this._value) / Math.log(2); 36 | this.texture = RES.getRes("tile_" + mi) 37 | } 38 | 39 | /** 40 | * 播放缩放效果 merged是否是合并方块 41 | */ 42 | public playScale(merged: boolean = false): void { 43 | if (!merged) { 44 | this.scaleX = this.scaleY = 0.1; 45 | egret.Tween.get(this).to({ scaleX: 1, scaleY: 1 }, 100); 46 | } 47 | else { 48 | var self: TileUI = this; 49 | var fun: Function = function () { 50 | egret.Tween.get(self).to({ scaleX: 1, scaleY: 1 }, 80); 51 | }; 52 | this.scaleX = this.scaleY = 1; 53 | egret.Tween.get(this).to({ scaleX: 1.3, scaleY: 1.3 }, 80).call(fun, this); 54 | } 55 | } 56 | 57 | /** 58 | * 移动格子 59 | */ 60 | public playmove(xTo: number, yTo: number): void { 61 | var self: TileUI = this; 62 | egret.Tween.get(this).to({ x: xTo, y: yTo }, 100).call(function (): void { 63 | self.dispatchEvent(new egret.Event("moveComplete")); 64 | }, this); 65 | } 66 | } 67 | } -------------------------------------------------------------------------------- /src/org/xzper/app/AppContainer.ts: -------------------------------------------------------------------------------- 1 | 2 | module game { 3 | 4 | export class AppContainer extends egret.gui.UIStage { 5 | public startScreen: StartScreen = new StartScreen(); 6 | public gameScreen: GameScreen = new GameScreen(); 7 | 8 | public constructor() { 9 | super(); 10 | } 11 | 12 | /** 13 | * 进入开始页面 14 | */ 15 | public enterStartScreen(): void { 16 | this.removeAllElements(); 17 | this.addElement(this.startScreen); 18 | } 19 | 20 | /** 21 | * 进入游戏页面 22 | */ 23 | public enterGameScreen(): void { 24 | this.removeAllElements(); 25 | this.addElement(this.gameScreen); 26 | if (!this.gameScreen.initialized) { 27 | //在第一次进入游戏页面时立即验证,保证Mediator的注册是及时的, 28 | //防止注册不及时导致无法接受消息的情况 29 | this.gameScreen.validateNow(); 30 | } 31 | } 32 | 33 | public settingWindow: SettingWindow; 34 | /** 35 | * 显示设置界面 36 | */ 37 | public showSettingWindow(type: string = "setting"): void { 38 | if (!this.settingWindow) { 39 | this.settingWindow = new SettingWindow(); 40 | } 41 | this.settingWindow.setWindowType(type); 42 | egret.gui.PopUpManager.addPopUp(this.settingWindow, true); 43 | this.settingWindow.verticalCenter = -700; 44 | egret.Tween.get(this.settingWindow).to({ verticalCenter: 0 }, 500, egret.Ease.backOut); 45 | } 46 | 47 | public endWindow: EndWindow; 48 | /** 49 | * 显示结束窗口 50 | */ 51 | public showEndWindow(): void { 52 | if (!this.endWindow) { 53 | this.endWindow = new EndWindow(); 54 | } 55 | this.endWindow.show(); 56 | if (!this.endWindow.initialized) { 57 | //在第一次进入游戏页面时立即验证,保证Mediator的注册是及时的, 58 | //防止注册不及时导致无法接受消息的情况 59 | this.endWindow.validateNow(); 60 | } 61 | } 62 | } 63 | } -------------------------------------------------------------------------------- /src/org/xzper/view/EndWindowMediator.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by xzper on 2014/11/16. 3 | */ 4 | /** 5 | * Created by xzper on 2014/11/15. 6 | */ 7 | 8 | module game { 9 | 10 | export class EndWindowMediator extends puremvc.Mediator implements puremvc.IMediator { 11 | public static NAME: string = "EndWindowMediator"; 12 | 13 | public constructor(viewComponent: any) { 14 | super(EndWindowMediator.NAME, viewComponent); 15 | this.endWindow.closeButton.addEventListener(egret.TouchEvent.TOUCH_TAP, this.buttonClick, this); 16 | this.endWindow.retryButton.addEventListener(egret.TouchEvent.TOUCH_TAP, this.buttonClick, this); 17 | this.endWindow.returnButton.addEventListener(egret.TouchEvent.TOUCH_TAP, this.buttonClick, this); 18 | this.endWindow.addEventListener(egret.Event.ADDED_TO_STAGE, this.initData, this); 19 | this.initData(); 20 | } 21 | 22 | /** 23 | * 初始化显示数据 24 | */ 25 | private initData(event: egret.Event = null): void { 26 | var proxy: GameProxy = this.facade.retrieveProxy(GameProxy.NAME); 27 | this.endWindow.highScoreLabel.text = CommonData.highScore.toString(); 28 | this.endWindow.totalScoreLabel.text = proxy.score.toString(); 29 | } 30 | 31 | private buttonClick(event: egret.TouchEvent): void { 32 | this.endWindow.close(); 33 | if (event.currentTarget == this.endWindow.retryButton) { 34 | this.sendNotification(GameCommand.START_GAME); 35 | } 36 | else { 37 | this.sendNotification(GameCommand.FINISH_GAME); 38 | } 39 | } 40 | 41 | public listNotificationInterests(): Array { 42 | return [ 43 | ]; 44 | } 45 | 46 | public handleNotification(notification: puremvc.INotification): void { 47 | switch (notification.getName()) { 48 | 49 | } 50 | } 51 | 52 | public get endWindow(): EndWindow { 53 | return (this.viewComponent); 54 | } 55 | } 56 | } -------------------------------------------------------------------------------- /src/LoadingUI.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014,Egret-Labs.org 3 | * All rights reserved. 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * * Neither the name of the Egret-Labs.org nor the 13 | * names of its contributors may be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY EGRET-LABS.ORG AND CONTRIBUTORS "AS IS" AND ANY 17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | * DISCLAIMED. IN NO EVENT SHALL EGRET-LABS.ORG AND CONTRIBUTORS BE LIABLE FOR ANY 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | class LoadingUI extends egret.gui.SkinnableComponent { 29 | 30 | public constructor() { 31 | super(); 32 | this.skinName = skin.LoadingUISkin; 33 | } 34 | 35 | /** 36 | * 进度条 37 | */ 38 | public progressBar: egret.gui.ProgressBar; 39 | 40 | public setProgress(current: number, total: number): void { 41 | if (this.progressBar) { 42 | this.progressBar.maximum = total; 43 | this.progressBar.value = current; 44 | } 45 | } 46 | } -------------------------------------------------------------------------------- /src/org/xzper/controller/commands/SceneCommand.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by xzper on 2014/11/15. 3 | */ 4 | 5 | module game { 6 | 7 | export class SceneCommand extends puremvc.SimpleCommand implements puremvc.ICommand { 8 | 9 | public constructor() { 10 | super(); 11 | } 12 | public static NAME: string = "SceneCommand"; 13 | 14 | /** 15 | * 切换场景 16 | */ 17 | public static CHANGE: string = "scene_change"; 18 | 19 | /** 20 | * 显示设置界面 21 | */ 22 | public static SHOW_SETTING: string = "scene_setting"; 23 | 24 | /** 25 | * 显示结束窗口 26 | */ 27 | public static SHOW_END: string = "scene_end"; 28 | 29 | /** 30 | * 注册消息 31 | */ 32 | public register(): void { 33 | this.facade.registerCommand(SceneCommand.CHANGE, SceneCommand); 34 | this.facade.registerCommand(SceneCommand.SHOW_SETTING, SceneCommand); 35 | this.facade.registerCommand(SceneCommand.SHOW_END, SceneCommand); 36 | } 37 | 38 | public execute(notification: puremvc.INotification): void { 39 | var data: any = notification.getBody(); 40 | var appMediator: ApplicationMediator = 41 | this.facade.retrieveMediator(ApplicationMediator.NAME); 42 | switch (notification.getName()) { 43 | case SceneCommand.CHANGE: { 44 | if (data == 1) 45 | appMediator.main.enterStartScreen(); 46 | else 47 | appMediator.main.enterGameScreen(); 48 | break; 49 | } 50 | case SceneCommand.SHOW_SETTING: { 51 | appMediator.main.showSettingWindow(data); 52 | break; 53 | } 54 | case SceneCommand.SHOW_END: { 55 | egret.setTimeout(function (): void { 56 | appMediator.main.showEndWindow(); 57 | }, this, 300); 58 | break; 59 | } 60 | } 61 | } 62 | } 63 | } -------------------------------------------------------------------------------- /src/org/xzper/view/panel/SettingWindow.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by xzper on 2014/11/15. 3 | */ 4 | module game { 5 | 6 | export class SettingWindow extends egret.gui.TitleWindow { 7 | 8 | public constructor() { 9 | super(); 10 | this.title = "Settings"; 11 | this.skinName = skin.SettingScreenSkin; 12 | this.addEventListener(egret.gui.UIEvent.CREATION_COMPLETE, this.createCompleteEvent, this); 13 | } 14 | 15 | public createCompleteEvent(event: egret.gui.UIEvent): void { 16 | this.removeEventListener(egret.gui.UIEvent.CREATION_COMPLETE, this.createCompleteEvent, this); 17 | ApplicationFacade.getInstance().registerMediator(new SettingWindowMediator(this)); 18 | } 19 | 20 | public howtoplayButton: egret.gui.Button; 21 | public musicButton: egret.gui.ToggleButton; 22 | public soundButton: egret.gui.ToggleButton; 23 | public moreButton: egret.gui.Button; 24 | public aboutButton: egret.gui.Button; 25 | 26 | public resumeButton: egret.gui.Button; 27 | public restartButton: egret.gui.Button; 28 | public quitButton: egret.gui.Button; 29 | 30 | public yesButton: egret.gui.Button; 31 | public noButton: egret.gui.Button; 32 | 33 | private _type: string; 34 | 35 | public get type(): string { 36 | return this._type; 37 | } 38 | 39 | /** 40 | * 设置窗口显示类型 41 | * @param type 42 | */ 43 | public setWindowType(type: string): void { 44 | this._type = type; 45 | this.invalidateSkinState(); 46 | } 47 | 48 | public getCurrentSkinState(): string { 49 | return this._type; 50 | } 51 | 52 | public partAdded(partName: string, instance: any): void { 53 | super.partAdded(partName, instance); 54 | if (instance == this.closeButton) { 55 | this.closeButton.addEventListener(egret.TouchEvent.TOUCH_TAP, this.onCloseButtonClick, this); 56 | } 57 | } 58 | 59 | private onCloseButtonClick(event: egret.TouchEvent): void { 60 | egret.gui.PopUpManager.removePopUp(this); 61 | } 62 | 63 | } 64 | } -------------------------------------------------------------------------------- /src/AutoScreenAdapter.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by xzper on 2015/9/25. 3 | */ 4 | class AutoScreenAdapter extends egret.HashObject implements egret.sys.IScreenAdapter { 5 | 6 | /** 7 | * @private 8 | */ 9 | public constructor() { 10 | super(); 11 | } 12 | 13 | /** 14 | * @private 15 | * 计算舞台显示尺寸 16 | * @param scaleMode 当前的缩放模式 17 | * @param screenWidth 播放器视口宽度 18 | * @param screenHeight 播放器视口高度 19 | * @param contentWidth 初始化内容宽度 20 | * @param contentHeight 初始化内容高度 21 | */ 22 | public calculateStageSize(scaleMode: string, screenWidth: number, screenHeight: number, 23 | contentWidth: number, contentHeight: number): egret.sys.StageDisplaySize { 24 | 25 | 26 | if (egret.MainContext.deviceType == egret.MainContext.DEVICE_MOBILE) { 27 | scaleMode = egret.StageScaleMode.SHOW_ALL; 28 | } 29 | else { 30 | if (screenHeight > contentHeight && screenWidth > contentWidth) { 31 | scaleMode = egret.StageScaleMode.NO_SCALE; 32 | } 33 | else 34 | scaleMode = egret.StageScaleMode.SHOW_ALL; 35 | } 36 | 37 | var displayWidth = contentWidth; 38 | var displayHeight = contentHeight; 39 | var stageWidth = contentWidth; 40 | var stageHeight = contentHeight; 41 | var scaleX = (screenWidth / stageWidth) || 0; 42 | var scaleY = (screenHeight / stageHeight) || 0; 43 | switch (scaleMode) { 44 | case egret.StageScaleMode.SHOW_ALL: 45 | if (scaleX > scaleY) { 46 | displayWidth = Math.round(stageWidth * scaleY); 47 | displayHeight = Math.round(stageHeight * scaleY); 48 | } 49 | else { 50 | displayWidth = Math.round(stageWidth * scaleX); 51 | displayHeight = Math.round(stageHeight * scaleX); 52 | } 53 | break; 54 | default: 55 | break; 56 | } 57 | return { 58 | stageWidth: stageWidth, 59 | stageHeight: stageHeight, 60 | displayWidth: displayWidth, 61 | displayHeight: displayHeight 62 | }; 63 | } 64 | } -------------------------------------------------------------------------------- /src/org/xzper/view/StartScreenMediator.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by xzper on 2014/11/15. 3 | */ 4 | 5 | module game { 6 | 7 | export class StartScreenMediator extends puremvc.Mediator implements puremvc.IMediator { 8 | public static NAME: string = "StartScreenMediator"; 9 | 10 | public constructor(viewComponent: any) { 11 | super(StartScreenMediator.NAME, viewComponent); 12 | 13 | this.setLevel(CommonData.level); 14 | 15 | this.startScreen.levelButton.addEventListener(egret.TouchEvent.TOUCH_TAP, this.levelButtonClick, this); 16 | this.startScreen.playButton.addEventListener(egret.TouchEvent.TOUCH_TAP, this.startButtonClick, this); 17 | this.startScreen.settingButton.addEventListener(egret.TouchEvent.TOUCH_TAP, this.settingButtonClick, this); 18 | } 19 | 20 | private settingButtonClick(event: egret.TouchEvent): void { 21 | this.sendNotification(SceneCommand.SHOW_SETTING, "setting"); 22 | } 23 | 24 | private levelButtonClick(event: egret.TouchEvent): void { 25 | if (CommonData.level == Level.EASY) 26 | this.setLevel(Level.NORMAL); 27 | else if (CommonData.level == Level.NORMAL) 28 | this.setLevel(Level.SPECIAL); 29 | else if (CommonData.level == Level.SPECIAL) 30 | this.setLevel(Level.EASY); 31 | } 32 | 33 | private setLevel(value: string): void { 34 | CommonData.level = value; 35 | this.startScreen.levelButton.label = value.toLocaleUpperCase(); 36 | this.startScreen.levelButton.icon = "level_" + value; 37 | } 38 | 39 | private startButtonClick(event: egret.TouchEvent): void { 40 | this.sendNotification(GameCommand.START_GAME); 41 | } 42 | 43 | public listNotificationInterests(): Array { 44 | return [ 45 | 46 | ]; 47 | } 48 | 49 | public handleNotification(notification: puremvc.INotification): void { 50 | var data: any = notification.getBody(); 51 | switch (notification.getName()) { 52 | 53 | } 54 | } 55 | 56 | public get startScreen(): StartScreen { 57 | return (this.viewComponent); 58 | } 59 | } 60 | } -------------------------------------------------------------------------------- /doc/sourceassets/button.json: -------------------------------------------------------------------------------- 1 | {"file":"button.png","frames":{ 2 | "sound_normal":{"x":1,"y":1,"w":227,"h":92,"offX":0,"offY":0,"sourceW":227,"sourceH":92}, 3 | "custom_down":{"x":230,"y":1,"w":96,"h":92,"offX":0,"offY":0,"sourceW":96,"sourceH":92}, 4 | "custom_normal":{"x":328,"y":1,"w":96,"h":92,"offX":0,"offY":0,"sourceW":96,"sourceH":92}, 5 | "icon_down":{"x":426,"y":1,"w":162,"h":92,"offX":0,"offY":0,"sourceW":162,"sourceH":92}, 6 | "icon_normal":{"x":590,"y":1,"w":162,"h":92,"offX":0,"offY":0,"sourceW":162,"sourceH":92}, 7 | "music_down":{"x":754,"y":1,"w":227,"h":92,"offX":0,"offY":0,"sourceW":227,"sourceH":92}, 8 | "music_non_down":{"x":1,"y":95,"w":227,"h":92,"offX":0,"offY":0,"sourceW":227,"sourceH":92}, 9 | "music_non_normal":{"x":1,"y":189,"w":227,"h":92,"offX":0,"offY":0,"sourceW":227,"sourceH":92}, 10 | "music_normal":{"x":1,"y":283,"w":227,"h":92,"offX":0,"offY":0,"sourceW":227,"sourceH":92}, 11 | "pause_down":{"x":1,"y":377,"w":100,"h":92,"offX":0,"offY":0,"sourceW":100,"sourceH":92}, 12 | "pause_normal":{"x":103,"y":377,"w":100,"h":92,"offX":0,"offY":0,"sourceW":100,"sourceH":92}, 13 | "play_down":{"x":230,"y":95,"w":153,"h":152,"offX":0,"offY":0,"sourceW":153,"sourceH":152}, 14 | "play_normal":{"x":230,"y":249,"w":153,"h":152,"offX":0,"offY":0,"sourceW":153,"sourceH":152}, 15 | "retry_down":{"x":205,"y":403,"w":100,"h":92,"offX":0,"offY":0,"sourceW":100,"sourceH":92}, 16 | "retry_normal":{"x":307,"y":403,"w":100,"h":92,"offX":0,"offY":0,"sourceW":100,"sourceH":92}, 17 | "retry2_down":{"x":385,"y":95,"w":154,"h":152,"offX":0,"offY":0,"sourceW":154,"sourceH":152}, 18 | "retry2_normal":{"x":385,"y":249,"w":154,"h":152,"offX":0,"offY":0,"sourceW":154,"sourceH":152}, 19 | "return_down":{"x":409,"y":403,"w":100,"h":92,"offX":0,"offY":0,"sourceW":100,"sourceH":92}, 20 | "return_normal":{"x":511,"y":403,"w":100,"h":92,"offX":0,"offY":0,"sourceW":100,"sourceH":92}, 21 | "setting_down":{"x":541,"y":95,"w":100,"h":92,"offX":0,"offY":0,"sourceW":100,"sourceH":92}, 22 | "setting_normal":{"x":541,"y":189,"w":100,"h":92,"offX":0,"offY":0,"sourceW":100,"sourceH":92}, 23 | "sound_down":{"x":541,"y":283,"w":227,"h":92,"offX":0,"offY":0,"sourceW":227,"sourceH":92}, 24 | "sound_non_down":{"x":613,"y":377,"w":227,"h":92,"offX":0,"offY":0,"sourceW":227,"sourceH":92}, 25 | "sound_non_normal":{"x":643,"y":95,"w":227,"h":92,"offX":0,"offY":0,"sourceW":227,"sourceH":92}}} -------------------------------------------------------------------------------- /resource/assets/button.json: -------------------------------------------------------------------------------- 1 | {"file":"button.png","frames":{ 2 | "sound_normal":{"x":1,"y":1,"w":227,"h":92,"offX":0,"offY":0,"sourceW":227,"sourceH":92}, 3 | "custom_down":{"x":230,"y":1,"w":96,"h":92,"offX":0,"offY":0,"sourceW":96,"sourceH":92}, 4 | "custom_normal":{"x":328,"y":1,"w":96,"h":92,"offX":0,"offY":0,"sourceW":96,"sourceH":92}, 5 | "icon_down":{"x":426,"y":1,"w":162,"h":92,"offX":0,"offY":0,"sourceW":162,"sourceH":92}, 6 | "icon_normal":{"x":590,"y":1,"w":162,"h":92,"offX":0,"offY":0,"sourceW":162,"sourceH":92}, 7 | "music_down":{"x":754,"y":1,"w":227,"h":92,"offX":0,"offY":0,"sourceW":227,"sourceH":92}, 8 | "music_non_down":{"x":1,"y":95,"w":227,"h":92,"offX":0,"offY":0,"sourceW":227,"sourceH":92}, 9 | "music_non_normal":{"x":1,"y":189,"w":227,"h":92,"offX":0,"offY":0,"sourceW":227,"sourceH":92}, 10 | "music_normal":{"x":1,"y":283,"w":227,"h":92,"offX":0,"offY":0,"sourceW":227,"sourceH":92}, 11 | "pause_down":{"x":1,"y":377,"w":100,"h":92,"offX":0,"offY":0,"sourceW":100,"sourceH":92}, 12 | "pause_normal":{"x":103,"y":377,"w":100,"h":92,"offX":0,"offY":0,"sourceW":100,"sourceH":92}, 13 | "play_down":{"x":230,"y":95,"w":153,"h":152,"offX":0,"offY":0,"sourceW":153,"sourceH":152}, 14 | "play_normal":{"x":230,"y":249,"w":153,"h":152,"offX":0,"offY":0,"sourceW":153,"sourceH":152}, 15 | "retry_down":{"x":205,"y":403,"w":100,"h":92,"offX":0,"offY":0,"sourceW":100,"sourceH":92}, 16 | "retry_normal":{"x":307,"y":403,"w":100,"h":92,"offX":0,"offY":0,"sourceW":100,"sourceH":92}, 17 | "retry2_down":{"x":385,"y":95,"w":154,"h":152,"offX":0,"offY":0,"sourceW":154,"sourceH":152}, 18 | "retry2_normal":{"x":385,"y":249,"w":154,"h":152,"offX":0,"offY":0,"sourceW":154,"sourceH":152}, 19 | "return_down":{"x":409,"y":403,"w":100,"h":92,"offX":0,"offY":0,"sourceW":100,"sourceH":92}, 20 | "return_normal":{"x":511,"y":403,"w":100,"h":92,"offX":0,"offY":0,"sourceW":100,"sourceH":92}, 21 | "setting_down":{"x":541,"y":95,"w":100,"h":92,"offX":0,"offY":0,"sourceW":100,"sourceH":92}, 22 | "setting_normal":{"x":541,"y":189,"w":100,"h":92,"offX":0,"offY":0,"sourceW":100,"sourceH":92}, 23 | "sound_down":{"x":541,"y":283,"w":227,"h":92,"offX":0,"offY":0,"sourceW":227,"sourceH":92}, 24 | "sound_non_down":{"x":613,"y":377,"w":227,"h":92,"offX":0,"offY":0,"sourceW":227,"sourceH":92}, 25 | "sound_non_normal":{"x":643,"y":95,"w":227,"h":92,"offX":0,"offY":0,"sourceW":227,"sourceH":92}}} -------------------------------------------------------------------------------- /src/skin/SettingScreenSkin.exml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /resource/resource.json: -------------------------------------------------------------------------------- 1 | { 2 | "groups":[ 3 | { 4 | "keys":"about_background,button_json,setting_background,settingscreen_json,start_background,start_logo,gamemenu_json,sence_background,tile_json,end_background,end_close_png,end_cloud_png,end_sun_png", 5 | "name":"preload" 6 | }, 7 | { 8 | "keys":"icon_json", 9 | "name":"loading" 10 | }], 11 | "resources":[ 12 | { 13 | "name":"about_background", 14 | "type":"image", 15 | "url":"assets/about_background.png" 16 | }, 17 | { 18 | "name":"button_json", 19 | "subkeys":"custom_down,custom_normal,icon_down,icon_normal,music_down,music_non_down,music_non_normal,music_normal,pause_down,pause_normal,play_down,play_normal,retry2_down,retry2_normal,retry_down,retry_normal,return_down,return_normal,setting_down,setting_normal,sound_down,sound_non_down,sound_non_normal,sound_normal", 20 | "type":"sheet", 21 | "url":"assets/button.json" 22 | }, 23 | { 24 | "name":"icon_json", 25 | "subkeys":"level_easy,level_normal,level_special,loading_logo,loading_logo2", 26 | "type":"sheet", 27 | "url":"assets/icon.json" 28 | }, 29 | { 30 | "name":"setting_background", 31 | "type":"image", 32 | "url":"assets/setting_background.png" 33 | }, 34 | { 35 | "name":"settingscreen_json", 36 | "subkeys":"about_logo,about_logo2,howtoplay_1,howtoplay_2,howtoplay_3,howtoplay_4,howtoplay_next,howtoplay_prev,howtoplay_return", 37 | "type":"sheet", 38 | "url":"assets/settingscreen.json" 39 | }, 40 | { 41 | "name":"start_background", 42 | "type":"image", 43 | "url":"assets/start_background.png" 44 | }, 45 | { 46 | "name":"start_logo", 47 | "type":"image", 48 | "url":"assets/start_logo.png" 49 | }, 50 | { 51 | "name":"gamemenu_json", 52 | "subkeys":"highscroce,level_small_easy,level_small_normal,level_small_special,menubackground", 53 | "type":"sheet", 54 | "url":"assets/gamemenu.json" 55 | }, 56 | { 57 | "name":"sence_background", 58 | "type":"image", 59 | "url":"assets/sence_background.png" 60 | }, 61 | { 62 | "name":"tile_json", 63 | "subkeys":"tile_1,tile_10,tile_11,tile_2,tile_3,tile_4,tile_5,tile_6,tile_7,tile_8,tile_9,tile_shovel,tile_stone,tile_stone2,tile_water", 64 | "type":"sheet", 65 | "url":"assets/tile.json" 66 | }, 67 | { 68 | "name":"end_background", 69 | "type":"image", 70 | "url":"assets/end_background.png" 71 | }, 72 | { 73 | "name":"end_close_png", 74 | "type":"image", 75 | "url":"assets/end_close.png" 76 | }, 77 | { 78 | "name":"end_cloud_png", 79 | "type":"image", 80 | "url":"assets/end_cloud.png" 81 | }, 82 | { 83 | "name":"end_sun_png", 84 | "type":"image", 85 | "url":"assets/end_sun.png" 86 | }] 87 | } -------------------------------------------------------------------------------- /src/org/xzper/controller/commands/GameCommand.ts: -------------------------------------------------------------------------------- 1 | 2 | module game { 3 | 4 | export class GameCommand extends puremvc.SimpleCommand implements puremvc.ICommand { 5 | 6 | public constructor() { 7 | super(); 8 | } 9 | public static NAME: string = "GameCommand"; 10 | 11 | /** 12 | * 开始游戏 13 | */ 14 | public static START_GAME: string = "start_game"; 15 | 16 | /** 17 | * 结束游戏 18 | */ 19 | public static FINISH_GAME: string = "finish_game"; 20 | 21 | /** 22 | * 更新分数 23 | */ 24 | public static UPDATE_SCORE: string = "update_score"; 25 | 26 | /** 27 | * 执行移动 , body 0: 上, 1: 右, 2:下, 3: 左 28 | */ 29 | public static MOVE_TILE: string = "move_tile"; 30 | 31 | /** 32 | * 注册消息 33 | */ 34 | public register(): void { 35 | this.facade.registerCommand(GameCommand.START_GAME, GameCommand); 36 | this.facade.registerCommand(GameCommand.FINISH_GAME, GameCommand); 37 | this.facade.registerCommand(GameCommand.UPDATE_SCORE, GameCommand); 38 | this.facade.registerCommand(GameCommand.MOVE_TILE, GameCommand); 39 | } 40 | 41 | public execute(notification: puremvc.INotification): void { 42 | var gameProxy: GameProxy = (this.facade.retrieveProxy(GameProxy.NAME)); 43 | var gridProxy: GridProxy = (this.facade.retrieveProxy(GridProxy.NAME)); 44 | var data: any = notification.getBody(); 45 | switch (notification.getName()) { 46 | case GameCommand.START_GAME: { 47 | this.sendNotification(SceneCommand.CHANGE, 2); 48 | gameProxy.reset(); 49 | gridProxy.reset(); 50 | gridProxy.addStartTiles(); 51 | break; 52 | } 53 | case GameCommand.UPDATE_SCORE: { 54 | gameProxy.updateScore(data); 55 | break; 56 | } 57 | case GameCommand.MOVE_TILE: { 58 | gridProxy.move(data); 59 | break; 60 | } 61 | case GameCommand.FINISH_GAME: { 62 | if (data) { 63 | gameProxy.setResult(data); 64 | this.sendNotification(SceneCommand.SHOW_END); 65 | } 66 | else { 67 | gameProxy.quit(); 68 | gridProxy.reset(); 69 | this.sendNotification(SceneCommand.CHANGE, 1); 70 | } 71 | break; 72 | } 73 | } 74 | } 75 | } 76 | } -------------------------------------------------------------------------------- /src/org/xzper/view/SettingWindowMediator.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by xzper on 2014/11/15. 3 | */ 4 | 5 | module game { 6 | 7 | export class SettingWindowMediator extends puremvc.Mediator implements puremvc.IMediator { 8 | public static NAME: string = "SettingWindowMediator"; 9 | 10 | public constructor(viewComponent: any) { 11 | super(SettingWindowMediator.NAME, viewComponent); 12 | this.settingWindow.howtoplayButton.addEventListener(egret.TouchEvent.TOUCH_TAP, this.howtoplayButtonClick, this); 13 | this.settingWindow.aboutButton.addEventListener(egret.TouchEvent.TOUCH_TAP, this.aboutButtonClick, this); 14 | this.settingWindow.resumeButton.addEventListener(egret.TouchEvent.TOUCH_TAP, this.resumeButtonClick, this); 15 | this.settingWindow.restartButton.addEventListener(egret.TouchEvent.TOUCH_TAP, this.restartButtonClick, this); 16 | this.settingWindow.quitButton.addEventListener(egret.TouchEvent.TOUCH_TAP, this.quitButtonClick, this); 17 | this.settingWindow.yesButton.addEventListener(egret.TouchEvent.TOUCH_TAP, this.yesButtonClick, this); 18 | this.settingWindow.noButton.addEventListener(egret.TouchEvent.TOUCH_TAP, this.resumeButtonClick, this); 19 | } 20 | 21 | private howtoplayButtonClick(event: egret.TouchEvent): void { 22 | var howtoPlay: HowtoplayWindow = new HowtoplayWindow(); 23 | egret.gui.PopUpManager.addPopUp(howtoPlay, true); 24 | } 25 | 26 | private aboutButtonClick(event: egret.TouchEvent): void { 27 | var about: AboutWindow = new AboutWindow(); 28 | egret.gui.PopUpManager.addPopUp(about, true); 29 | } 30 | 31 | private resumeButtonClick(event: egret.TouchEvent): void { 32 | egret.gui.PopUpManager.removePopUp(this.settingWindow); 33 | } 34 | 35 | private restartButtonClick(event: egret.TouchEvent): void { 36 | this.settingWindow.setWindowType("restart"); 37 | } 38 | 39 | private quitButtonClick(event: egret.TouchEvent): void { 40 | this.settingWindow.setWindowType("quit"); 41 | } 42 | 43 | private yesButtonClick(event: egret.TouchEvent): void { 44 | egret.gui.PopUpManager.removePopUp(this.settingWindow); 45 | if (this.settingWindow.type == "restart") { 46 | this.sendNotification(GameCommand.START_GAME); 47 | } 48 | else if (this.settingWindow.type == "quit") { 49 | this.sendNotification(GameCommand.FINISH_GAME); 50 | } 51 | } 52 | 53 | 54 | public listNotificationInterests(): Array { 55 | return [ 56 | ]; 57 | } 58 | 59 | public handleNotification(notification: puremvc.INotification): void { 60 | switch (notification.getName()) { 61 | 62 | } 63 | } 64 | 65 | public get settingWindow(): SettingWindow { 66 | return (this.viewComponent); 67 | } 68 | } 69 | } -------------------------------------------------------------------------------- /src/AssetAdapter.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014,Egret-Labs.org 3 | * All rights reserved. 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * * Neither the name of the Egret-Labs.org nor the 13 | * names of its contributors may be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY EGRET-LABS.ORG AND CONTRIBUTORS "AS IS" AND ANY 17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | * DISCLAIMED. IN NO EVENT SHALL EGRET-LABS.ORG AND CONTRIBUTORS BE LIABLE FOR ANY 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | class AssetAdapter implements egret.gui.IAssetAdapter { 29 | 30 | /** 31 | * 解析素材 32 | * @method egret.gui.DefaultAssetAdapter#getAsset 33 | * @param source {any} 待解析的新素材标识符 34 | * @param compFunc {Function} 解析完成回调函数,示例:compFunc(content:any,source:any):void; 35 | * 回调参数content接受两种类型:DisplayObject或Texture。 36 | * @param thisObject {any} compFunc的this引用 37 | * @param oldContent any 旧的内容对象,传入值有可能为null。 38 | * 对于某些类型素材,例如MovieClip,可以重用传入的显示对象,只修改其数据再返回。 39 | */ 40 | public getAsset(source: any, compFunc: Function, thisObject: any, oldContent: any): void { 41 | 42 | function onGetRes(data: any): void { 43 | compFunc.call(thisObject, data, source); 44 | } 45 | 46 | var content: any = source; 47 | if (source.prototype) { 48 | content = new source(); 49 | } 50 | if (content instanceof egret.DisplayObject || content instanceof egret.Texture) { 51 | compFunc.call(thisObject, content, source); 52 | } 53 | else if (typeof (source) == "string") { 54 | if (RES.hasRes(source)) { 55 | RES.getResAsync(source, onGetRes, this); 56 | } 57 | else { 58 | RES.getResByUrl(source, onGetRes, this); 59 | } 60 | 61 | 62 | } 63 | else { 64 | compFunc.call(thisObject, content, source); 65 | } 66 | } 67 | 68 | 69 | } -------------------------------------------------------------------------------- /src/skin/EndScreenSkin.exml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /template/runtime/native_require.js: -------------------------------------------------------------------------------- 1 | 2 | var game_file_list = [ 3 | //以下为自动修改,请勿修改 4 | //----auto game_file_list start---- 5 | "libs/modules/egret/egret.js", 6 | "libs/modules/egret/egret.native.js", 7 | "libs/modules/game/game.js", 8 | "libs/modules/game/game.native.js", 9 | "libs/modules/res/res.js", 10 | "libs/modules/tween/tween.js", 11 | "libs/modules/gui/gui.js", 12 | "libs/modules/puremvc/puremvc.js", 13 | "bin-debug/AssetAdapter.js", 14 | "bin-debug/AutoScreenAdapter.js", 15 | "bin-debug/components/IconButton.js", 16 | "bin-debug/LoadingUI.js", 17 | "bin-debug/Main.js", 18 | "bin-debug/org/xzper/app/AppConfig.js", 19 | "bin-debug/org/xzper/app/AppContainer.js", 20 | "bin-debug/org/xzper/app/IApp.js", 21 | "bin-debug/org/xzper/ApplicationFacade.js", 22 | "bin-debug/org/xzper/controller/commands/GameCommand.js", 23 | "bin-debug/org/xzper/controller/commands/SceneCommand.js", 24 | "bin-debug/org/xzper/controller/ControllerPrepCommand.js", 25 | "bin-debug/org/xzper/controller/ModelPrepCommand.js", 26 | "bin-debug/org/xzper/controller/StartupCommand.js", 27 | "bin-debug/org/xzper/controller/ViewPrepCommand.js", 28 | "bin-debug/org/xzper/model/common/Level.js", 29 | "bin-debug/org/xzper/model/common/CommonData.js", 30 | "bin-debug/org/xzper/model/GameProxy.js", 31 | "bin-debug/org/xzper/model/GridProxy.js", 32 | "bin-debug/org/xzper/model/vos/TileVO.js", 33 | "bin-debug/org/xzper/utils/ObjectPool.js", 34 | "bin-debug/org/xzper/view/ApplicationMediator.js", 35 | "bin-debug/org/xzper/view/EndWindowMediator.js", 36 | "bin-debug/org/xzper/view/GameMenuMediator.js", 37 | "bin-debug/org/xzper/view/GameSceneMediator.js", 38 | "bin-debug/org/xzper/view/GameScreenMediator.js", 39 | "bin-debug/org/xzper/view/panel/AboutWindow.js", 40 | "bin-debug/org/xzper/view/panel/EndWindow.js", 41 | "bin-debug/org/xzper/view/panel/GameMenuUI.js", 42 | "bin-debug/org/xzper/view/panel/GameScene.js", 43 | "bin-debug/org/xzper/view/panel/GameScreen.js", 44 | "bin-debug/org/xzper/view/panel/HowtoplayWindow.js", 45 | "bin-debug/org/xzper/view/panel/SettingWindow.js", 46 | "bin-debug/org/xzper/view/panel/StartScreen.js", 47 | "bin-debug/org/xzper/view/panel/TileUI.js", 48 | "bin-debug/org/xzper/view/SettingWindowMediator.js", 49 | "bin-debug/org/xzper/view/StartScreenMediator.js", 50 | "bin-debug/skin/AboutSkin.g.js", 51 | "bin-debug/skin/components/ButtonSkin.g.js", 52 | "bin-debug/skin/components/CloseButtonSkin.g.js", 53 | "bin-debug/skin/components/IconButtonSkin.g.js", 54 | "bin-debug/skin/components/MusicButonSkin.g.js", 55 | "bin-debug/skin/components/PauseButtonSkin.g.js", 56 | "bin-debug/skin/components/PlayButtonSkin.g.js", 57 | "bin-debug/skin/components/ProgressBarSkin.g.js", 58 | "bin-debug/skin/components/RetryButtonSkin.g.js", 59 | "bin-debug/skin/components/ReturnSkin.g.js", 60 | "bin-debug/skin/components/SettingButtonSkin.g.js", 61 | "bin-debug/skin/components/SoundButtonSkin.g.js", 62 | "bin-debug/skin/EndScreenSkin.g.js", 63 | "bin-debug/skin/GameMenuSkin.g.js", 64 | "bin-debug/skin/HowtoPlaySkin.g.js", 65 | "bin-debug/skin/LoadingUISkin.g.js", 66 | "bin-debug/skin/MainGameUISkin.g.js", 67 | "bin-debug/skin/SettingScreenSkin.g.js", 68 | "bin-debug/skin/StartScreenSkin.g.js", 69 | //----auto game_file_list end---- 70 | ]; 71 | 72 | var window = {}; 73 | 74 | egret_native.setSearchPaths([""]); 75 | 76 | egret_native.requireFiles = function () { 77 | for (var key in game_file_list) { 78 | var src = game_file_list[key]; 79 | require(src); 80 | } 81 | }; 82 | 83 | egret_native.egretInit = function () { 84 | egret_native.requireFiles(); 85 | egret.TextField.default_fontFamily = "/system/fonts/DroidSansFallback.ttf"; 86 | //egret.dom为空实现 87 | egret.dom = {}; 88 | egret.dom.drawAsCanvas = function () { 89 | }; 90 | }; 91 | 92 | egret_native.egretStart = function () { 93 | var option = { 94 | //以下为自动修改,请勿修改 95 | //----auto option start---- 96 | entryClassName: "Main", 97 | frameRate: 60, 98 | scaleMode: "showAll", 99 | contentWidth: 640, 100 | contentHeight: 960, 101 | showPaintRect: false, 102 | showFPS: false, 103 | fpsStyles: "x:0,y:0,size:10", 104 | showLog: false, 105 | logFilter: "", 106 | maxTouches: 2, 107 | textureScaleFactor: 1 108 | //----auto option end---- 109 | }; 110 | 111 | egret.native.NativePlayer.option = option; 112 | egret.runEgret(); 113 | egret_native.Label.createLabel(egret.TextField.default_fontFamily, 20, "", 0); 114 | egret_native.EGTView.preSetOffScreenBufferEnable(true); 115 | }; -------------------------------------------------------------------------------- /src/Main.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014,Egret-Labs.org 3 | * All rights reserved. 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * * Neither the name of the Egret-Labs.org nor the 13 | * names of its contributors may be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY EGRET-LABS.ORG AND CONTRIBUTORS "AS IS" AND ANY 17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | * DISCLAIMED. IN NO EVENT SHALL EGRET-LABS.ORG AND CONTRIBUTORS BE LIABLE FOR ANY 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | class Main extends egret.Sprite { 29 | 30 | /** 31 | * 加载进度界面 32 | */ 33 | private loadingView: LoadingUI; 34 | 35 | public constructor() { 36 | super(); 37 | this.addEventListener(egret.Event.ADDED_TO_STAGE, this.init, this) 38 | } 39 | 40 | private appContainer: game.AppContainer; 41 | 42 | private init(event: egret.Event): void { 43 | //设置自定义的屏幕适配方式 44 | egret.sys.screenAdapter = new AutoScreenAdapter(); 45 | 46 | //注入自定义的解析器 47 | egret.gui.mapClass("egret.gui.IAssetAdapter", AssetAdapter); 48 | egret.gui.Theme.load("resource/theme.thm"); 49 | 50 | //初始化UIStage 51 | this.appContainer = new game.AppContainer(); 52 | this.addChild(this.appContainer); 53 | 54 | //初始化Resource资源加载库 55 | RES.addEventListener(RES.ResourceEvent.CONFIG_COMPLETE, this.onConfigComplete, this); 56 | RES.loadConfig("resource/resource.json", "resource/"); 57 | } 58 | 59 | /** 60 | * 配置文件加载完成,开始预加载preload资源组。 61 | */ 62 | private onConfigComplete(event: RES.ResourceEvent): void { 63 | RES.removeEventListener(RES.ResourceEvent.CONFIG_COMPLETE, this.onConfigComplete, this); 64 | RES.addEventListener(RES.ResourceEvent.GROUP_COMPLETE, this.onResourceLoadComplete, this); 65 | RES.addEventListener(RES.ResourceEvent.GROUP_PROGRESS, this.onResourceProgress, this); 66 | RES.loadGroup("loading", 1); 67 | RES.loadGroup("preload"); 68 | } 69 | /** 70 | * preload资源组加载完成 71 | */ 72 | private onResourceLoadComplete(event: RES.ResourceEvent): void { 73 | if (event.groupName == "loading") { 74 | //设置加载进度界面 75 | this.loadingView = new LoadingUI(); 76 | this.appContainer.addElement(this.loadingView); 77 | } 78 | else if (event.groupName == "preload") { 79 | this.appContainer.removeElement(this.loadingView); 80 | RES.removeEventListener(RES.ResourceEvent.GROUP_COMPLETE, this.onResourceLoadComplete, this); 81 | RES.removeEventListener(RES.ResourceEvent.GROUP_PROGRESS, this.onResourceProgress, this); 82 | this.createGameScene(); 83 | } 84 | } 85 | /** 86 | * preload资源组加载进度 87 | */ 88 | private onResourceProgress(event: RES.ResourceEvent): void { 89 | if (event.groupName == "preload") { 90 | this.loadingView.setProgress(event.itemsLoaded, event.itemsTotal); 91 | } 92 | } 93 | 94 | /** 95 | * 创建游戏场景 96 | */ 97 | private createGameScene(): void { 98 | //设置模态层透明度,写在这里是因为初始化的时候UIStage还没初始化完毕,直接设置会报错 99 | egret.gui.PopUpManager.modalAlpha = 0; 100 | 101 | game.ApplicationFacade.getInstance().startUp(this.appContainer); 102 | game.ApplicationFacade.getInstance().sendNotification(game.SceneCommand.CHANGE, 1); 103 | } 104 | } -------------------------------------------------------------------------------- /src/org/xzper/view/panel/GameScene.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by xzper on 2014/11/15. 3 | */ 4 | module game { 5 | 6 | /** 7 | * 游戏场景 8 | */ 9 | export class GameScene extends egret.gui.UIAsset { 10 | 11 | public constructor() { 12 | super(); 13 | this.addEventListener(egret.gui.UIEvent.CREATION_COMPLETE, this.createCompleteEvent, this); 14 | this.addContainer(); 15 | } 16 | 17 | private addContainer(): void { 18 | this.tileGroup = new egret.Sprite(); 19 | this.source = this.tileGroup; 20 | } 21 | 22 | public createCompleteEvent(event: egret.gui.UIEvent): void { 23 | this.removeEventListener(egret.gui.UIEvent.CREATION_COMPLETE, this.createCompleteEvent, this); 24 | ApplicationFacade.getInstance().registerMediator(new GameSceneMediator(this)); 25 | } 26 | 27 | private tileGroup: egret.Sprite; 28 | 29 | /** 30 | * 创建一个格子 31 | */ 32 | public createTile(tileVO: TileVO): void { 33 | var tile: TileUI = (ObjectPool.getPool("game.TileUI").borrowObject()); //从对象池创建 34 | tile.value = tileVO.value; 35 | tile.location.x = tileVO.x; 36 | tile.location.y = tileVO.y; 37 | tile.width = tile.height = this.tileSize; 38 | tile.anchorOffsetX = tile.anchorOffsetY = this.tileSize / 2; 39 | tile.x = tileVO.x * (tile.width + this.gap) + tile.width / 2; 40 | tile.y = tileVO.y * (tile.height + this.gap) + tile.height / 2; 41 | tile.visible = false; 42 | this.tileGroup.addChild(tile); 43 | var showTile: Function = function (): void { 44 | tile.visible = true; 45 | if (tileVO.merged) { 46 | tile.playScale(true); 47 | } else { 48 | tile.playScale(false); 49 | } 50 | }; 51 | egret.setTimeout(showTile, this, 100); //延迟显示格子,保证其他的格子移动完成后显示 52 | } 53 | 54 | /** 55 | *获取指定位置的格子 56 | */ 57 | public getTileUI(x: number, y: number): TileUI { 58 | for (var i: number = 0; i < this.tileGroup.numChildren; i++) { 59 | var tile: TileUI = (this.tileGroup.getChildAt(i)); 60 | if (tile.location.x == x && tile.location.y == y) { 61 | return tile; 62 | } 63 | } 64 | return null; 65 | } 66 | 67 | /** 68 | * 合并格子 69 | */ 70 | public mergedTile(tileVO: TileVO): void { 71 | var tileFrom: TileUI = this.getTileUI(tileVO.previousPosition.x, tileVO.previousPosition.y); 72 | var tileTo: TileUI = this.getTileUI(tileVO.x, tileVO.y); 73 | if (tileFrom && tileTo) { 74 | this.tileGroup.setChildIndex(tileFrom, 0); //将要消失的格子沉底, 75 | var self: GameScene = this; 76 | tileFrom.location.x = -1; 77 | tileFrom.location.y = -1; 78 | tileFrom.playmove(tileVO.x * (tileFrom.width + this.gap) + tileFrom.width / 2, tileVO.y * (tileFrom.height + this.gap) + tileFrom.height / 2); 79 | var moveComplete: Function = function (event: egret.Event): void { 80 | tileFrom.removeEventListener("moveComplete", moveComplete, self); 81 | if (tileFrom.parent) 82 | self.tileGroup.removeChild(tileFrom); 83 | ObjectPool.getPool("game.TileUI").returnObject(tileFrom); //回收到对象池 84 | tileTo.value = tileVO.value; 85 | self.tileGroup.setChildIndex(tileTo, self.tileGroup.numChildren - 1); //将要缩放的格子置顶, 86 | tileTo.playScale(true); 87 | }; 88 | tileFrom.addEventListener("moveComplete", moveComplete, this); 89 | } 90 | } 91 | 92 | /** 93 | * 清除一个格子 94 | */ 95 | public removeTile(tileVO: TileVO): void { 96 | var tileUI: TileUI = this.getTileUI(tileVO.x, tileVO.y); 97 | if (tileUI) { 98 | this.tileGroup.removeChild(tileUI); 99 | ObjectPool.getPool("game.TileUI").returnObject(tileUI); 100 | } 101 | } 102 | 103 | /** 104 | * 移动一个格子 105 | */ 106 | public moveTile(tileVO: TileVO): void { 107 | var tile: TileUI = this.getTileUI(tileVO.previousPosition.x, tileVO.previousPosition.y); 108 | if (tile) { 109 | tile.location.x = tileVO.x; 110 | tile.location.y = tileVO.y; 111 | tile.playmove(tileVO.x * (tile.width + this.gap) + tile.width / 2, 112 | tileVO.y * (tile.height + this.gap) + tile.height / 2); 113 | } 114 | } 115 | 116 | /** 117 | * 清除所有 118 | */ 119 | public clearTiles(): void { 120 | var num: number = this.tileGroup.numChildren; 121 | var tileUI: TileUI; 122 | for (var i: number = num - 1; i >= 0; i--) { 123 | tileUI = this.tileGroup.removeChildAt(i); 124 | ObjectPool.getPool("game.TileUI").returnObject(tileUI); 125 | } 126 | } 127 | 128 | /** 129 | * 格子的大小 130 | */ 131 | private get tileSize(): number { 132 | return (560 - (CommonData.size + 1) * this.gap) / CommonData.size; 133 | } 134 | 135 | /** 136 | * 间距 137 | */ 138 | private get gap(): number { 139 | return 0; 140 | } 141 | 142 | } 143 | } -------------------------------------------------------------------------------- /src/org/xzper/view/GameScreenMediator.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by xzper on 2014/11/15. 3 | */ 4 | 5 | 6 | module game { 7 | 8 | export class GameScreenMediator extends puremvc.Mediator implements puremvc.IMediator { 9 | public static NAME: string = "GameScreenMediator"; 10 | public constructor(viewComponent: any) { 11 | super(GameScreenMediator.NAME, viewComponent); 12 | 13 | //为PC和移动端设置不同的移动策略 14 | if (egret.MainContext.deviceType != egret.MainContext.DEVICE_MOBILE) { 15 | var self = this; 16 | document.addEventListener("keydown", function (event: KeyboardEvent) { 17 | switch (event.keyCode) { 18 | case 38: 19 | self.doMove(0); 20 | break; 21 | case 39: 22 | self.doMove(1); 23 | break; 24 | case 40: 25 | self.doMove(2); 26 | break; 27 | case 37: 28 | self.doMove(3); 29 | break; 30 | } 31 | }); 32 | } 33 | else { 34 | this.gamescreen.addEventListener(egret.TouchEvent.TOUCH_BEGIN, this.mouseDownHandle, this) 35 | } 36 | } 37 | 38 | private downPoint: egret.Point; 39 | private movePoint: egret.Point; 40 | private mouseDownHandle(event: egret.TouchEvent): void { 41 | egret.gui.UIGlobals.stage.addEventListener(egret.TouchEvent.TOUCH_MOVE, this.stage_mouseMoveHandler, this); 42 | egret.gui.UIGlobals.stage.addEventListener(egret.TouchEvent.TOUCH_END, this.stage_mouseUpHandler, this); 43 | egret.gui.UIGlobals.stage.addEventListener(egret.Event.LEAVE_STAGE, this.stage_mouseUpHandler, this); 44 | 45 | this.downPoint = this.gamescreen.globalToLocal(event.stageX, event.stageY); 46 | } 47 | 48 | private needMove: boolean; 49 | private stage_mouseMoveHandler(event: egret.TouchEvent): void { 50 | if (!this.movePoint) 51 | this.movePoint = new egret.Point(); 52 | this.movePoint.x = event.stageX; 53 | this.movePoint.y = event.stageY; 54 | if (this.needMove) 55 | return; 56 | this.needMove = true; 57 | } 58 | 59 | public stage_mouseUpHandler(event: egret.Event): void { 60 | egret.gui.UIGlobals.stage.removeEventListener(egret.TouchEvent.TOUCH_MOVE, 61 | this.stage_mouseMoveHandler, 62 | this); 63 | egret.gui.UIGlobals.stage.removeEventListener(egret.TouchEvent.TOUCH_END, 64 | this.stage_mouseUpHandler, 65 | this); 66 | egret.gui.UIGlobals.stage.addEventListener(egret.Event.LEAVE_STAGE, 67 | this.stage_mouseUpHandler, 68 | this); 69 | if (this.needMove) { 70 | this.updateWhenMouseUp(); 71 | this.needMove = false; 72 | } 73 | } 74 | 75 | /** 76 | * 移动设备上,判断移动方向 77 | */ 78 | private updateWhenMouseUp(): void { 79 | this.gamescreen.globalToLocal() 80 | var p: egret.Point = this.gamescreen.globalToLocal(this.movePoint.x, this.movePoint.y); 81 | var offSetX: number = p.x - this.downPoint.x; 82 | var offSetY: number = p.y - this.downPoint.y; 83 | 84 | if (offSetY < 0 && Math.abs(offSetY) > Math.abs(offSetX)) //上 85 | { 86 | this.doMove(0); 87 | } 88 | else if (offSetX > 0 && offSetX > Math.abs(offSetY)) //右 89 | { 90 | this.doMove(1); 91 | } 92 | else if (offSetY > 0 && offSetY > Math.abs(offSetX)) //下 93 | { 94 | this.doMove(2); 95 | } 96 | else if (offSetX < 0 && Math.abs(offSetX) > Math.abs(offSetY)) //左 97 | { 98 | this.doMove(3); 99 | } 100 | } 101 | 102 | 103 | /** 104 | * 移动格子 105 | * @param direction 方向 0上 1右 2下 3左 106 | */ 107 | private doMove(direction: number): void { 108 | if (CommonData.isRunning && (egret.getTimer() - this.lastMoveTime) >= 150) { 109 | switch (direction) { 110 | case 0: 111 | this.sendNotification(GameCommand.MOVE_TILE, 0); //上 112 | break; 113 | case 1: 114 | this.sendNotification(GameCommand.MOVE_TILE, 1); //右 115 | break; 116 | case 2: 117 | this.sendNotification(GameCommand.MOVE_TILE, 2); //下 118 | break; 119 | case 3: 120 | this.sendNotification(GameCommand.MOVE_TILE, 3); //左 121 | break; 122 | } 123 | this.lastMoveTime = egret.getTimer(); 124 | } 125 | } 126 | 127 | /** 128 | * 上次移动的时间 , 防止过快设置移动 129 | */ 130 | private lastMoveTime: number = 0; 131 | 132 | public listNotificationInterests(): Array { 133 | return []; 134 | } 135 | 136 | public handleNotification(notification: puremvc.INotification): void { 137 | switch (notification.getName()) { 138 | } 139 | } 140 | 141 | public get gamescreen(): GameScreen { 142 | return (this.viewComponent); 143 | } 144 | } 145 | } -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Egret 6 | 7 | 8 | 9 | 10 | 11 | 12 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 |
113 |
114 | 117 | 118 | 119 | -------------------------------------------------------------------------------- /modules/puremvc/bin/puremvc/puremvc.min.js: -------------------------------------------------------------------------------- 1 | var puremvc;!function(t){"use strict";var e=function(){function t(t,e){this.notify=null,this.context=null,this.setNotifyMethod(t),this.setNotifyContext(e)}return t.prototype.getNotifyMethod=function(){return this.notify},t.prototype.setNotifyMethod=function(t){this.notify=t},t.prototype.getNotifyContext=function(){return this.context},t.prototype.setNotifyContext=function(t){this.context=t},t.prototype.notifyObserver=function(t){this.getNotifyMethod().call(this.getNotifyContext(),t)},t.prototype.compareNotifyContext=function(t){return t===this.context},t}();t.Observer=e}(puremvc||(puremvc={}));var puremvc;!function(t){"use strict";var e=function(){function e(){if(this.mediatorMap=null,this.observerMap=null,e.instance)throw Error(e.SINGLETON_MSG);e.instance=this,this.mediatorMap={},this.observerMap={},this.initializeView()}return e.prototype.initializeView=function(){},e.prototype.registerObserver=function(t,e){var n=this.observerMap[t];n?n.push(e):this.observerMap[t]=[e]},e.prototype.removeObserver=function(t,e){for(var n=this.observerMap[t],o=n.length;o--;){var i=n[o];if(i.compareNotifyContext(e)){n.splice(o,1);break}}0==n.length&&delete this.observerMap[t]},e.prototype.notifyObservers=function(t){var e=t.getName(),n=this.observerMap[e];if(n)for(var o=n.slice(0),i=o.length,r=0;i>r;r++){var s=o[r];s.notifyObserver(t)}},e.prototype.registerMediator=function(e){var n=e.getMediatorName();if(!this.mediatorMap[n]){this.mediatorMap[n]=e;var o=e.listNotificationInterests(),i=o.length;if(i>0)for(var r=new t.Observer(e.handleNotification,e),s=0;i>s;s++)this.registerObserver(o[s],r);e.onRegister()}},e.prototype.retrieveMediator=function(t){return this.mediatorMap[t]||null},e.prototype.removeMediator=function(t){var e=this.mediatorMap[t];if(!e)return null;for(var n=e.listNotificationInterests(),o=n.length;o--;)this.removeObserver(n[o],e);return delete this.mediatorMap[t],e.onRemove(),e},e.prototype.hasMediator=function(t){return null!=this.mediatorMap[t]},e.SINGLETON_MSG="View singleton already constructed!",e.instance=null,e.getInstance=function(){return e.instance||(e.instance=new e),e.instance},e}();t.View=e}(puremvc||(puremvc={}));var puremvc;!function(t){"use strict";var e=function(){function e(){if(this.view=null,this.commandMap=null,e.instance)throw Error(e.SINGLETON_MSG);e.instance=this,this.commandMap={},this.initializeController()}return e.prototype.initializeController=function(){this.view=t.View.getInstance()},e.prototype.executeCommand=function(t){var e=this.commandMap[t.getName()];if(e){var n=new e;n.execute(t)}},e.prototype.registerCommand=function(e,n){this.commandMap[e]||this.view.registerObserver(e,new t.Observer(this.executeCommand,this)),this.commandMap[e]=n},e.prototype.hasCommand=function(t){return null!=this.commandMap[t]},e.prototype.removeCommand=function(t){this.hasCommand(t)&&(this.view.removeObserver(t,this),delete this.commandMap[t])},e.SINGLETON_MSG="Controller singleton already constructed!",e.instance=null,e.getInstance=function(){return e.instance||(e.instance=new e),e.instance},e}();t.Controller=e}(puremvc||(puremvc={}));var puremvc;!function(t){"use strict";var e=function(){function t(){if(this.proxyMap=null,t.instance)throw Error(t.SINGLETON_MSG);t.instance=this,this.proxyMap={},this.initializeModel()}return t.prototype.initializeModel=function(){},t.prototype.registerProxy=function(t){this.proxyMap[t.getProxyName()]=t,t.onRegister()},t.prototype.removeProxy=function(t){var e=this.proxyMap[t];return e&&(delete this.proxyMap[t],e.onRemove()),e},t.prototype.retrieveProxy=function(t){return this.proxyMap[t]||null},t.prototype.hasProxy=function(t){return null!=this.proxyMap[t]},t.SINGLETON_MSG="Model singleton already constructed!",t.instance=null,t.getInstance=function(){return t.instance||(t.instance=new t),t.instance},t}();t.Model=e}(puremvc||(puremvc={}));var puremvc;!function(t){"use strict";var e=function(){function t(t,e,n){"undefined"==typeof e&&(e=null),"undefined"==typeof n&&(n=null),this.name=null,this.body=null,this.type=null,this.name=t,this.body=e,this.type=n}return t.prototype.getName=function(){return this.name},t.prototype.setBody=function(t){this.body=t},t.prototype.getBody=function(){return this.body},t.prototype.setType=function(t){this.type=t},t.prototype.getType=function(){return this.type},t.prototype.toString=function(){var t="Notification Name: "+this.getName();return t+="\nBody:"+(null==this.getBody()?"null":this.getBody().toString()),t+="\nType:"+(null==this.getType()?"null":this.getType())},t}();t.Notification=e}(puremvc||(puremvc={}));var puremvc;!function(t){"use strict";var e=function(){function e(){if(this.model=null,this.view=null,this.controller=null,e.instance)throw Error(e.SINGLETON_MSG);e.instance=this,this.initializeFacade()}return e.prototype.initializeFacade=function(){this.initializeModel(),this.initializeController(),this.initializeView()},e.prototype.initializeModel=function(){this.model||(this.model=t.Model.getInstance())},e.prototype.initializeController=function(){this.controller||(this.controller=t.Controller.getInstance())},e.prototype.initializeView=function(){this.view||(this.view=t.View.getInstance())},e.prototype.registerCommand=function(t,e){this.controller.registerCommand(t,e)},e.prototype.removeCommand=function(t){this.controller.removeCommand(t)},e.prototype.hasCommand=function(t){return this.controller.hasCommand(t)},e.prototype.registerProxy=function(t){this.model.registerProxy(t)},e.prototype.retrieveProxy=function(t){return this.model.retrieveProxy(t)},e.prototype.removeProxy=function(t){var e;return this.model&&(e=this.model.removeProxy(t)),e},e.prototype.hasProxy=function(t){return this.model.hasProxy(t)},e.prototype.registerMediator=function(t){this.view&&this.view.registerMediator(t)},e.prototype.retrieveMediator=function(t){return this.view.retrieveMediator(t)},e.prototype.removeMediator=function(t){var e;return this.view&&(e=this.view.removeMediator(t)),e},e.prototype.hasMediator=function(t){return this.view.hasMediator(t)},e.prototype.notifyObservers=function(t){this.view&&this.view.notifyObservers(t)},e.prototype.sendNotification=function(e,n,o){"undefined"==typeof n&&(n=null),"undefined"==typeof o&&(o=null),this.notifyObservers(new t.Notification(e,n,o))},e.SINGLETON_MSG="Facade singleton already constructed!",e.instance=null,e.getInstance=function(){return e.instance||(e.instance=new e),e.instance},e}();t.Facade=e}(puremvc||(puremvc={}));var puremvc;!function(t){"use strict";var e=function(){function e(){this.facade=null,this.facade=t.Facade.getInstance()}return e.prototype.sendNotification=function(t,e,n){"undefined"==typeof e&&(e=null),"undefined"==typeof n&&(n=null),this.facade.sendNotification(t,e,n)},e}();t.Notifier=e}(puremvc||(puremvc={}));var __extends=this.__extends||function(t,e){function n(){this.constructor=t}n.prototype=e.prototype,t.prototype=new n},puremvc;!function(t){"use strict";var e=function(t){function e(){t.call(this),this.subCommands=null,this.subCommands=new Array,this.initializeMacroCommand()}return __extends(e,t),e.prototype.initializeMacroCommand=function(){},e.prototype.addSubCommand=function(t){this.subCommands.push(t)},e.prototype.execute=function(t){for(var e=this.subCommands.slice(0),n=this.subCommands.length,o=0;n>o;o++){var i=e[o],r=new i;r.execute(t)}this.subCommands.splice(0)},e}(t.Notifier);t.MacroCommand=e}(puremvc||(puremvc={}));var puremvc;!function(t){"use strict";var e=function(t){function e(){t.apply(this,arguments)}return __extends(e,t),e.prototype.execute=function(){},e}(t.Notifier);t.SimpleCommand=e}(puremvc||(puremvc={}));var puremvc;!function(t){"use strict";var e=function(t){function e(n,o){"undefined"==typeof n&&(n=null),"undefined"==typeof o&&(o=null),t.call(this),this.mediatorName=null,this.viewComponent=null,this.mediatorName=null!=n?n:e.NAME,this.viewComponent=o}return __extends(e,t),e.prototype.getMediatorName=function(){return this.mediatorName},e.prototype.getViewComponent=function(){return this.viewComponent},e.prototype.setViewComponent=function(t){this.viewComponent=t},e.prototype.listNotificationInterests=function(){return new Array},e.prototype.handleNotification=function(){},e.prototype.onRegister=function(){},e.prototype.onRemove=function(){},e.NAME="Mediator",e}(t.Notifier);t.Mediator=e}(puremvc||(puremvc={}));var puremvc;!function(t){"use strict";var e=function(t){function e(n,o){"undefined"==typeof n&&(n=null),"undefined"==typeof o&&(o=null),t.call(this),this.data=null,this.proxyName=null,this.proxyName=null!=n?n:e.NAME,null!=o&&this.setData(o)}return __extends(e,t),e.prototype.getProxyName=function(){return this.proxyName},e.prototype.setData=function(t){this.data=t},e.prototype.getData=function(){return this.data},e.prototype.onRegister=function(){},e.prototype.onRemove=function(){},e.NAME="Proxy",e}(t.Notifier);t.Proxy=e}(puremvc||(puremvc={})); -------------------------------------------------------------------------------- /modules/puremvc/src/puremvc.d.ts: -------------------------------------------------------------------------------- 1 | declare module puremvc 2 | { 3 | export interface ICommand 4 | extends INotifier 5 | { 6 | execute( notification:INotification ):void; 7 | } 8 | 9 | export interface IController 10 | { 11 | executeCommand( notification:INotification ):void; 12 | registerCommand( notificationName:string, commandClassRef:Function ):void; 13 | hasCommand( notificationName:string ):boolean; 14 | removeCommand( notificationName:string ):void; 15 | } 16 | 17 | export interface IFacade 18 | extends INotifier 19 | { 20 | registerCommand( notificationName:string, commandClassRef:Function ):void; 21 | removeCommand( notificationName:string ): void; 22 | hasCommand( notificationName:string ):boolean; 23 | registerProxy( proxy:IProxy ):void; 24 | retrieveProxy( proxyName:string ):IProxy; 25 | removeProxy( proxyName:string ):IProxy; 26 | hasProxy( proxyName:string ):boolean; 27 | registerMediator( mediator:IMediator ):void; 28 | retrieveMediator( mediatorName:string ):IMediator; 29 | removeMediator( mediatorName:string ):IMediator; 30 | hasMediator( mediatorName:string ):boolean; 31 | notifyObservers( notification:INotification ):void; 32 | } 33 | 34 | export interface IMediator 35 | extends INotifier 36 | { 37 | getMediatorName():string; 38 | getViewComponent():any; 39 | setViewComponent( viewComponent:any ):void; 40 | listNotificationInterests( ):string[]; 41 | handleNotification( notification:INotification ):void; 42 | onRegister():void; 43 | onRemove():void; 44 | } 45 | 46 | export interface IModel 47 | { 48 | registerProxy( proxy:IProxy ):void; 49 | removeProxy( proxyName:string ):IProxy; 50 | retrieveProxy( proxyName:string ):IProxy; 51 | hasProxy( proxyName:string ):boolean; 52 | } 53 | 54 | export interface INotification 55 | { 56 | getName():string; 57 | setBody( body:any ):void; 58 | getBody():any; 59 | setType( type:string ):void; 60 | getType():string; 61 | toString():string; 62 | } 63 | 64 | export interface INotifier 65 | { 66 | sendNotification( name:string, body?:any, type?:string ):void; 67 | } 68 | 69 | export interface IObserver 70 | { 71 | setNotifyMethod( notifyMethod:Function ):void; 72 | setNotifyContext( notifyContext:any ):void; 73 | notifyObserver( notification:INotification ):void; 74 | compareNotifyContext( object:any ):boolean; 75 | } 76 | 77 | export interface IProxy 78 | extends INotifier 79 | { 80 | getProxyName():string; 81 | setData( data:any ):void; 82 | getData():any; 83 | onRegister( ):void; 84 | onRemove( ):void; 85 | } 86 | 87 | export interface IView 88 | { 89 | registerObserver( notificationName:string, observer:IObserver ):void; 90 | removeObserver( notificationName:string, notifyContext:any ):void; 91 | notifyObservers( notification:INotification ):void; 92 | registerMediator( mediator:IMediator ):void; 93 | retrieveMediator( mediatorName:string ):IMediator; 94 | removeMediator( mediatorName:string ):IMediator; 95 | hasMediator( mediatorName:string ):boolean; 96 | } 97 | 98 | export class Observer 99 | implements IObserver 100 | { 101 | public notify: Function; 102 | public context: any; 103 | constructor (notifyMethod: Function, notifyContext: any); 104 | private getNotifyMethod(): Function; 105 | public setNotifyMethod(notifyMethod: Function): void; 106 | private getNotifyContext(): any; 107 | public setNotifyContext(notifyContext: any): void; 108 | public notifyObserver(notification: INotification): void; 109 | public compareNotifyContext(object: any): boolean; 110 | } 111 | 112 | export class View 113 | implements IView 114 | { 115 | public mediatorMap: Object; 116 | public observerMap: Object; 117 | constructor (); 118 | public initializeView(): void; 119 | public registerObserver(notificationName: string, observer: IObserver): void; 120 | public removeObserver(notificationName: string, notifyContext: any): void; 121 | public notifyObservers(notification: INotification): void; 122 | public registerMediator(mediator: IMediator): void; 123 | public retrieveMediator(mediatorName: string): IMediator; 124 | public removeMediator(mediatorName: string): IMediator; 125 | public hasMediator(mediatorName: string): boolean; 126 | static SINGLETON_MSG: string; 127 | static instance: IView; 128 | static getInstance(): IView; 129 | } 130 | 131 | 132 | export class Controller 133 | implements IController 134 | { 135 | public view: IView; 136 | public commandMap: Object; 137 | constructor (); 138 | public initializeController(): void; 139 | public executeCommand(notification: INotification): void; 140 | public registerCommand(notificationName: string, commandClassRef: Function): void; 141 | public hasCommand(notificationName: string): boolean; 142 | public removeCommand(notificationName: string): void; 143 | static instance: IController; 144 | static SINGLETON_MSG: string; 145 | static getInstance(): IController; 146 | } 147 | 148 | export class Model 149 | implements IModel 150 | { 151 | public proxyMap: Object; 152 | constructor (); 153 | public initializeModel(): void; 154 | public registerProxy(proxy: IProxy): void; 155 | public removeProxy(proxyName: string): IProxy; 156 | public retrieveProxy(proxyName: string): IProxy; 157 | public hasProxy(proxyName: string): boolean; 158 | static SINGLETON_MSG: string; 159 | static instance: IModel; 160 | static getInstance(): IModel; 161 | } 162 | 163 | export class Notification 164 | implements INotification 165 | { 166 | public name: string; 167 | public body: any; 168 | public type: string; 169 | constructor (name: string, body?: any, type?: string); 170 | public getName(): string; 171 | public setBody(body: any): void; 172 | public getBody(): any; 173 | public setType(type: string): void; 174 | public getType(): string; 175 | public toString(): string; 176 | } 177 | 178 | export class Facade 179 | implements IFacade 180 | { 181 | public model: IModel; 182 | public view: IView; 183 | public controller: IController; 184 | constructor (); 185 | public initializeFacade(): void; 186 | public initializeModel(): void; 187 | public initializeController(): void; 188 | public initializeView(): void; 189 | public registerCommand(notificationName: string, commandClassRef: Function): void; 190 | public removeCommand(notificationName: string): void; 191 | public hasCommand(notificationName: string): boolean; 192 | public registerProxy(proxy: IProxy): void; 193 | public retrieveProxy(proxyName: string): IProxy; 194 | public removeProxy(proxyName: string): IProxy; 195 | public hasProxy(proxyName: string): boolean; 196 | public registerMediator(mediator: IMediator): void; 197 | public retrieveMediator(mediatorName: string): IMediator; 198 | public removeMediator(mediatorName: string): IMediator; 199 | public hasMediator(mediatorName: string): boolean; 200 | public notifyObservers(notification: INotification): void; 201 | public sendNotification(name: string, body?: any, type?: string): void; 202 | static SINGLETON_MSG: string; 203 | static instance: IFacade; 204 | static getInstance(): IFacade; 205 | } 206 | 207 | export class Notifier 208 | implements INotifier 209 | { 210 | public facade: IFacade; 211 | constructor (); 212 | public sendNotification(name: string, body?: any, type?: string): void; 213 | } 214 | 215 | export class MacroCommand 216 | extends Notifier 217 | implements ICommand, INotifier 218 | { 219 | public subCommands: Function[]; 220 | constructor (); 221 | public initializeMacroCommand(): void; 222 | public addSubCommand(commandClassRef: Function): void; 223 | public execute(notification: INotification): void; 224 | } 225 | 226 | export class SimpleCommand 227 | extends Notifier 228 | implements ICommand, INotifier 229 | { 230 | public execute(notification: INotification): void; 231 | } 232 | 233 | export class Mediator 234 | extends Notifier 235 | implements IMediator, INotifier 236 | { 237 | public mediatorName: string; 238 | public viewComponent: any; 239 | constructor (mediatorName?: string, viewComponent?: any); 240 | public getMediatorName(): string; 241 | public getViewComponent(): any; 242 | public setViewComponent(viewComponent: any): void; 243 | public listNotificationInterests(): string[]; 244 | public handleNotification(notification: INotification): void; 245 | public onRegister(): void; 246 | public onRemove(): void; 247 | static NAME: string; 248 | } 249 | 250 | export class Proxy 251 | extends Notifier 252 | implements IProxy, INotifier 253 | { 254 | public proxyName: string; 255 | public data: any; 256 | constructor (proxyName?: string, data?: any); 257 | public getProxyName(): string; 258 | public setData(data: any): void; 259 | public getData(): any; 260 | public onRegister(): void; 261 | public onRemove(): void; 262 | static NAME: string; 263 | } 264 | } 265 | 266 | -------------------------------------------------------------------------------- /modules/puremvc/bin/puremvc/puremvc.d.ts: -------------------------------------------------------------------------------- 1 | declare module puremvc 2 | { 3 | export interface ICommand 4 | extends INotifier 5 | { 6 | execute( notification:INotification ):void; 7 | } 8 | 9 | export interface IController 10 | { 11 | executeCommand( notification:INotification ):void; 12 | registerCommand( notificationName:string, commandClassRef:Function ):void; 13 | hasCommand( notificationName:string ):boolean; 14 | removeCommand( notificationName:string ):void; 15 | } 16 | 17 | export interface IFacade 18 | extends INotifier 19 | { 20 | registerCommand( notificationName:string, commandClassRef:Function ):void; 21 | removeCommand( notificationName:string ): void; 22 | hasCommand( notificationName:string ):boolean; 23 | registerProxy( proxy:IProxy ):void; 24 | retrieveProxy( proxyName:string ):IProxy; 25 | removeProxy( proxyName:string ):IProxy; 26 | hasProxy( proxyName:string ):boolean; 27 | registerMediator( mediator:IMediator ):void; 28 | retrieveMediator( mediatorName:string ):IMediator; 29 | removeMediator( mediatorName:string ):IMediator; 30 | hasMediator( mediatorName:string ):boolean; 31 | notifyObservers( notification:INotification ):void; 32 | } 33 | 34 | export interface IMediator 35 | extends INotifier 36 | { 37 | getMediatorName():string; 38 | getViewComponent():any; 39 | setViewComponent( viewComponent:any ):void; 40 | listNotificationInterests( ):string[]; 41 | handleNotification( notification:INotification ):void; 42 | onRegister():void; 43 | onRemove():void; 44 | } 45 | 46 | export interface IModel 47 | { 48 | registerProxy( proxy:IProxy ):void; 49 | removeProxy( proxyName:string ):IProxy; 50 | retrieveProxy( proxyName:string ):IProxy; 51 | hasProxy( proxyName:string ):boolean; 52 | } 53 | 54 | export interface INotification 55 | { 56 | getName():string; 57 | setBody( body:any ):void; 58 | getBody():any; 59 | setType( type:string ):void; 60 | getType():string; 61 | toString():string; 62 | } 63 | 64 | export interface INotifier 65 | { 66 | sendNotification( name:string, body?:any, type?:string ):void; 67 | } 68 | 69 | export interface IObserver 70 | { 71 | setNotifyMethod( notifyMethod:Function ):void; 72 | setNotifyContext( notifyContext:any ):void; 73 | notifyObserver( notification:INotification ):void; 74 | compareNotifyContext( object:any ):boolean; 75 | } 76 | 77 | export interface IProxy 78 | extends INotifier 79 | { 80 | getProxyName():string; 81 | setData( data:any ):void; 82 | getData():any; 83 | onRegister( ):void; 84 | onRemove( ):void; 85 | } 86 | 87 | export interface IView 88 | { 89 | registerObserver( notificationName:string, observer:IObserver ):void; 90 | removeObserver( notificationName:string, notifyContext:any ):void; 91 | notifyObservers( notification:INotification ):void; 92 | registerMediator( mediator:IMediator ):void; 93 | retrieveMediator( mediatorName:string ):IMediator; 94 | removeMediator( mediatorName:string ):IMediator; 95 | hasMediator( mediatorName:string ):boolean; 96 | } 97 | 98 | export class Observer 99 | implements IObserver 100 | { 101 | public notify: Function; 102 | public context: any; 103 | constructor (notifyMethod: Function, notifyContext: any); 104 | private getNotifyMethod(): Function; 105 | public setNotifyMethod(notifyMethod: Function): void; 106 | private getNotifyContext(): any; 107 | public setNotifyContext(notifyContext: any): void; 108 | public notifyObserver(notification: INotification): void; 109 | public compareNotifyContext(object: any): boolean; 110 | } 111 | 112 | export class View 113 | implements IView 114 | { 115 | public mediatorMap: Object; 116 | public observerMap: Object; 117 | constructor (); 118 | public initializeView(): void; 119 | public registerObserver(notificationName: string, observer: IObserver): void; 120 | public removeObserver(notificationName: string, notifyContext: any): void; 121 | public notifyObservers(notification: INotification): void; 122 | public registerMediator(mediator: IMediator): void; 123 | public retrieveMediator(mediatorName: string): IMediator; 124 | public removeMediator(mediatorName: string): IMediator; 125 | public hasMediator(mediatorName: string): boolean; 126 | static SINGLETON_MSG: string; 127 | static instance: IView; 128 | static getInstance(): IView; 129 | } 130 | 131 | 132 | export class Controller 133 | implements IController 134 | { 135 | public view: IView; 136 | public commandMap: Object; 137 | constructor (); 138 | public initializeController(): void; 139 | public executeCommand(notification: INotification): void; 140 | public registerCommand(notificationName: string, commandClassRef: Function): void; 141 | public hasCommand(notificationName: string): boolean; 142 | public removeCommand(notificationName: string): void; 143 | static instance: IController; 144 | static SINGLETON_MSG: string; 145 | static getInstance(): IController; 146 | } 147 | 148 | export class Model 149 | implements IModel 150 | { 151 | public proxyMap: Object; 152 | constructor (); 153 | public initializeModel(): void; 154 | public registerProxy(proxy: IProxy): void; 155 | public removeProxy(proxyName: string): IProxy; 156 | public retrieveProxy(proxyName: string): IProxy; 157 | public hasProxy(proxyName: string): boolean; 158 | static SINGLETON_MSG: string; 159 | static instance: IModel; 160 | static getInstance(): IModel; 161 | } 162 | 163 | export class Notification 164 | implements INotification 165 | { 166 | public name: string; 167 | public body: any; 168 | public type: string; 169 | constructor (name: string, body?: any, type?: string); 170 | public getName(): string; 171 | public setBody(body: any): void; 172 | public getBody(): any; 173 | public setType(type: string): void; 174 | public getType(): string; 175 | public toString(): string; 176 | } 177 | 178 | export class Facade 179 | implements IFacade 180 | { 181 | public model: IModel; 182 | public view: IView; 183 | public controller: IController; 184 | constructor (); 185 | public initializeFacade(): void; 186 | public initializeModel(): void; 187 | public initializeController(): void; 188 | public initializeView(): void; 189 | public registerCommand(notificationName: string, commandClassRef: Function): void; 190 | public removeCommand(notificationName: string): void; 191 | public hasCommand(notificationName: string): boolean; 192 | public registerProxy(proxy: IProxy): void; 193 | public retrieveProxy(proxyName: string): IProxy; 194 | public removeProxy(proxyName: string): IProxy; 195 | public hasProxy(proxyName: string): boolean; 196 | public registerMediator(mediator: IMediator): void; 197 | public retrieveMediator(mediatorName: string): IMediator; 198 | public removeMediator(mediatorName: string): IMediator; 199 | public hasMediator(mediatorName: string): boolean; 200 | public notifyObservers(notification: INotification): void; 201 | public sendNotification(name: string, body?: any, type?: string): void; 202 | static SINGLETON_MSG: string; 203 | static instance: IFacade; 204 | static getInstance(): IFacade; 205 | } 206 | 207 | export class Notifier 208 | implements INotifier 209 | { 210 | public facade: IFacade; 211 | constructor (); 212 | public sendNotification(name: string, body?: any, type?: string): void; 213 | } 214 | 215 | export class MacroCommand 216 | extends Notifier 217 | implements ICommand, INotifier 218 | { 219 | public subCommands: Function[]; 220 | constructor (); 221 | public initializeMacroCommand(): void; 222 | public addSubCommand(commandClassRef: Function): void; 223 | public execute(notification: INotification): void; 224 | } 225 | 226 | export class SimpleCommand 227 | extends Notifier 228 | implements ICommand, INotifier 229 | { 230 | public execute(notification: INotification): void; 231 | } 232 | 233 | export class Mediator 234 | extends Notifier 235 | implements IMediator, INotifier 236 | { 237 | public mediatorName: string; 238 | public viewComponent: any; 239 | constructor (mediatorName?: string, viewComponent?: any); 240 | public getMediatorName(): string; 241 | public getViewComponent(): any; 242 | public setViewComponent(viewComponent: any): void; 243 | public listNotificationInterests(): string[]; 244 | public handleNotification(notification: INotification): void; 245 | public onRegister(): void; 246 | public onRemove(): void; 247 | static NAME: string; 248 | } 249 | 250 | export class Proxy 251 | extends Notifier 252 | implements IProxy, INotifier 253 | { 254 | public proxyName: string; 255 | public data: any; 256 | constructor (proxyName?: string, data?: any); 257 | public getProxyName(): string; 258 | public setData(data: any): void; 259 | public getData(): any; 260 | public onRegister(): void; 261 | public onRemove(): void; 262 | static NAME: string; 263 | } 264 | } 265 | 266 | -------------------------------------------------------------------------------- /src/org/xzper/model/GridProxy.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | module game { 4 | 5 | export class GridProxy extends puremvc.Proxy implements puremvc.IProxy { 6 | public static NAME: string = "GridProxy"; 7 | 8 | /** 9 | * 格子重置了 10 | */ 11 | public static TILE_RESET: string = "tile_reset"; 12 | /** 13 | * 格子移动了 14 | */ 15 | public static TILE_MOVE: string = "tile_move"; 16 | /** 17 | * 格子添加了 18 | */ 19 | public static TILE_INSERT: string = "tile_insert"; 20 | /** 21 | * 格子移除了 22 | */ 23 | public static TILE_REMOVE: string = "tile_remove"; 24 | 25 | /** 26 | * 格子合并了 27 | */ 28 | public static TILE_MERGED: string = "tile_merged"; 29 | 30 | private cells: Array = []; 31 | private startTiles: number = 2; 32 | private playerTurn: boolean = true; 33 | private size: number; 34 | 35 | public constructor() { 36 | super(GridProxy.NAME); 37 | } 38 | 39 | /** 40 | * 初始化数据 41 | */ 42 | public reset(): void { 43 | this.size = CommonData.size; 44 | this.cells = []; 45 | for (var x: number = 0; x < this.size; x++) { 46 | var row: Array = []; 47 | this.cells.push(row); 48 | for (var y: number = 0; y < this.size; y++) { 49 | row.push(null); 50 | } 51 | } 52 | this.playerTurn = true; 53 | this.sendNotification(GridProxy.TILE_RESET); 54 | } 55 | 56 | /** 57 | * 向某一方向移动 58 | * @param direction 0: 上, 1: 右, 2:下, 3: 左 59 | */ 60 | public move(direction: number): void { 61 | var won: boolean = false; 62 | var moved: boolean = false; 63 | var score: number = 0; 64 | 65 | this.prepareTiles(); 66 | var tiles: Array = this.buildMoveOrder(direction); 67 | for (var i: number = 0; i < tiles.length; i++) { 68 | var tile: TileVO = (tiles[i]); 69 | if (tile) { 70 | var farthestPosition: any = this.findFarthestPosition({ "x": tile.x, "y": tile.y }, direction); 71 | var nextPosition: any = this.getNextPosition(farthestPosition, direction); 72 | var nextTile: TileVO = this.cellContent(nextPosition.x, nextPosition.y); 73 | if (nextTile && nextTile.value == tile.value && !nextTile.merged) { //可以向下合并 74 | 75 | var newValue: number = tile.value + nextTile.value; 76 | 77 | this.mergedTile(tile, nextTile); 78 | 79 | tile.x = nextTile.x; 80 | tile.y = nextTile.y; 81 | 82 | //更新分数 83 | score += newValue; 84 | 85 | if (newValue >= CommonData.winValue) { //游戏结束 86 | won = true; 87 | } 88 | } else { 89 | this.moveTile(tile, farthestPosition.x, farthestPosition.y); 90 | } 91 | 92 | if (tile.x != tile.previousPosition.x || tile.y != tile.previousPosition.y) { //格子移动了 93 | this.playerTurn = false; 94 | moved = true; 95 | } 96 | } 97 | } 98 | 99 | if (score > 0) { 100 | this.sendNotification(GameCommand.UPDATE_SCORE, score); 101 | } 102 | if (!won) { 103 | if (moved) { 104 | this.computerMove(); 105 | } 106 | if (!this.movesAvailable()) { 107 | this.sendNotification(GameCommand.FINISH_GAME, false); 108 | } 109 | 110 | } 111 | else { 112 | this.sendNotification(GameCommand.FINISH_GAME, true); 113 | } 114 | } 115 | 116 | /** 117 | * 电脑添加一个格子 118 | */ 119 | public computerMove(): void { 120 | this.addRandomTile(); 121 | this.playerTurn = true; 122 | } 123 | 124 | /** 125 | * 获取某一方向的格子 126 | */ 127 | private buildMoveOrder(direction: number): Array { 128 | var arr: Array = []; 129 | var vector: any = this.getVector(direction); 130 | var xReverse: boolean = (vector.x == 1) ? true : false; 131 | var yReverse: boolean = (vector.y == 1) ? true : false; 132 | var x: number = xReverse ? (this.size - 1) : 0; 133 | while (x >= 0 && x < this.size) { 134 | var y: number = yReverse ? (this.size - 1) : 0; 135 | while (y >= 0 && y < this.size) { 136 | arr.push(this.cellContent(x, y)); 137 | y = y + (yReverse ? -1 : 1); 138 | } 139 | x = x + (xReverse ? -1 : 1); 140 | } 141 | return arr; 142 | } 143 | 144 | /** 145 | * 获取指定方向上能移动到的位置 146 | */ 147 | private findFarthestPosition(position: any, direction: number): any { 148 | var vector: any = this.getVector(direction); 149 | var lastPosition: any; 150 | do { 151 | lastPosition = position; 152 | position = this.getNextPosition(position, direction); 153 | } while (this.withinBounds(position.x, position.y) && this.isAvailable(position.x, position.y)); 154 | return lastPosition; 155 | } 156 | 157 | /** 158 | * 获取某一位置指定方向的下一个位置 159 | */ 160 | private getNextPosition(position: any, direction: number): any { 161 | var vector: any = this.getVector(direction); 162 | return { "x": position.x + vector.x, "y": position.y + vector.y }; 163 | } 164 | 165 | /** 166 | * 存储移动前状态 167 | */ 168 | private prepareTiles(): void { 169 | for (var x: number = 0; x < this.size; x++) { 170 | for (var y: number = 0; y < this.size; y++) { 171 | var tile: TileVO = (this.cells[x][y]); 172 | if (tile) { 173 | tile.merged = false; 174 | tile.previousPosition = { "x": tile.x, "y": tile.y }; 175 | } 176 | } 177 | } 178 | } 179 | 180 | /** 181 | * 添加游戏开始的格子 182 | */ 183 | public addStartTiles(): void { 184 | for (var i: number = 0; i < this.startTiles; i++) { 185 | this.addRandomTile(); 186 | } 187 | } 188 | 189 | /** 190 | * 随机添加一个格子 191 | */ 192 | private addRandomTile(): void { 193 | if (this.cellsAvailable()) { 194 | var position: any = this.randomAvailableCell; 195 | var tile: TileVO = new TileVO(); 196 | tile.x = position.x; 197 | tile.y = position.y; 198 | tile.value = Math.random() < 0.9 ? 2 : 4; 199 | this.insertTile(tile); 200 | } 201 | } 202 | 203 | /** 204 | * 是否能够继续游戏 205 | */ 206 | public movesAvailable(): boolean { 207 | for (var i: number = 0; i < this.size; i++) { 208 | for (var j: number = 0; j < this.size; j++) { 209 | var tile: TileVO = (this.cells[i][j]); 210 | if (tile) { 211 | for (var direction: number = 0; direction < 4; direction++) { 212 | var nextPosition: any = this.getNextPosition({ "x": tile.x, "y": tile.y }, direction); 213 | var nextTileVO: TileVO = this.cellContent(nextPosition.x, nextPosition.y); 214 | if ((!nextTileVO && this.withinBounds(nextPosition.x, nextPosition.y)) || //某一位置是空的 215 | (nextTileVO && nextTileVO.value == tile.value)) { //某一位置可以合并 216 | return true; 217 | } 218 | } 219 | } 220 | } 221 | } 222 | return false; 223 | } 224 | 225 | /** 226 | * 是否存在空格子 227 | */ 228 | private cellsAvailable(): boolean { 229 | if (this.availableCells.length > 0) { 230 | return true; 231 | } 232 | return false; 233 | } 234 | 235 | /** 236 | * 获取指定位置的格子是否可用 237 | */ 238 | private isAvailable(x: number, y: number): boolean { 239 | return !this.isOccupied(x, y); 240 | } 241 | 242 | /** 243 | * 获取指定位置的格子是否被占用 244 | */ 245 | private isOccupied(x: number, y: number): boolean { 246 | if (this.cellContent(x, y)) { 247 | return true; 248 | } else { 249 | return false; 250 | } 251 | } 252 | 253 | /** 254 | * 获取指定位置的格子 255 | */ 256 | private cellContent(x: number, y: number): TileVO { 257 | if (this.withinBounds(x, y)) { 258 | return (this.cells[x][y]); 259 | } else { 260 | return null; 261 | } 262 | } 263 | 264 | /** 265 | * 检查位置是否合法 266 | */ 267 | private withinBounds(x: number, y: number): boolean { 268 | return x >= 0 && x < this.size && y >= 0 && y < this.size; 269 | } 270 | 271 | /** 272 | * 合并格子 273 | * @param tile 274 | * @param x 275 | * @param y 276 | */ 277 | private mergedTile(tileFrom: TileVO, tileTo: TileVO): void { 278 | //创建新格子 279 | var mergedTile: TileVO = new TileVO(); 280 | mergedTile.x = tileTo.x; 281 | mergedTile.y = tileTo.y; 282 | mergedTile.previousPosition = { x: tileFrom.x, y: tileFrom.y }; 283 | mergedTile.value = tileFrom.value + tileTo.value; 284 | mergedTile.merged = true; 285 | 286 | //更新格子 287 | this.cells[tileFrom.x][tileFrom.y] = null; 288 | this.cells[tileTo.x][tileTo.y] = mergedTile; 289 | 290 | this.sendNotification(GridProxy.TILE_MERGED, mergedTile.clone()); 291 | } 292 | 293 | 294 | /** 295 | * 移动格子 296 | */ 297 | private moveTile(tile: TileVO, x: number, y: number): void { 298 | if (tile.x == x && tile.y == y) { 299 | return; 300 | } 301 | this.cells[tile.x][tile.y] = null; 302 | tile.x = x; 303 | tile.y = y; 304 | this.cells[tile.x][tile.y] = tile; 305 | this.sendNotification(GridProxy.TILE_MOVE, tile.clone()); 306 | } 307 | 308 | /** 309 | * 添加一个格子 310 | */ 311 | private insertTile(tile: TileVO): void { 312 | this.cells[tile.x][tile.y] = tile; 313 | this.sendNotification(GridProxy.TILE_INSERT, tile.clone()); 314 | } 315 | 316 | /** 317 | * 移除一个格子 318 | */ 319 | private removeTile(tile: TileVO): void { 320 | this.cells[tile.x][tile.y] = null; 321 | this.sendNotification(GridProxy.TILE_REMOVE, tile.clone()); 322 | } 323 | 324 | /** 325 | * 获取某一方向的偏移位置 326 | * @param direction 0: 上, 1: 右, 2:下, 3: 左 327 | */ 328 | private getVector(direction: number): any { 329 | if (direction == 0) { return { "x": 0, "y": -1 }; } 330 | else if (direction == 1) { return { "x": 1, "y": 0 }; } 331 | else if (direction == 2) { return { "x": 0, "y": 1 }; } 332 | else if (direction == 3) { return { "x": -1, "y": 0 }; } 333 | else { return null; } 334 | } 335 | 336 | /** 337 | * 随机获取一个空格子的位置 338 | */ 339 | private get randomAvailableCell(): any { 340 | var arr: Array = this.availableCells; 341 | if (arr.length) { 342 | return arr[Math.floor(Math.random() * arr.length)]; 343 | } 344 | return null; 345 | } 346 | 347 | /** 348 | * 所有的空格子的位置 349 | */ 350 | private get availableCells(): Array { 351 | var arr: Array = []; 352 | for (var x: number = 0; x < this.size; x++) { 353 | for (var y: number = 0; y < this.size; y++) { 354 | if (!this.cells[x][y]) { 355 | arr.push({ "x": x, "y": y }); 356 | } 357 | } 358 | } 359 | return arr; 360 | } 361 | 362 | } 363 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | #### 写在前面 2 | 3 | 本游戏使用Egret的GUI进行开发,不涉及Egret基础部分内容。本实例强烈建议结合GUIExample和深入浅出EGRET GUI系列教程来学习。 4 | 5 | 要了解Egret基础部分的内容请参考下面: 6 | 7 | * [ 官方引导 ](https://github.com/egret-labs/egret-core) 8 | * [ NeoGuo的教程 ](https://github.com/NeoGuo/html5-documents/tree/master/egret) 9 | 10 | 11 | Egret GUI 相关教程: 12 | 13 | * [ 官方DEMO ](https://github.com/egret-labs/egret-examples/tree/master/GUIExample) 14 | * [ 深入浅出EGRET GUI (一):皮肤分离机制 ](http://bbs.egret-labs.org/thread-43-1-1.html) 15 | * [ 深入浅出EGRET GUI (二):失效验证机制 ](http://bbs.egret-labs.org/thread-73-1-1.html) 16 | * [ 深入浅出EGRET GUI (三):AFL自适应流式布局 ](http://bbs.egret-labs.org/thread-102-1-1.html) 17 | 18 | --- 19 | 20 | 2048是最近很火的一个小游戏,[原版](http://gabrielecirulli.github.io/2048/) 就是用JavaScript写的。恰巧最近Egret PublicBeta,观望和学习了一阵后,发现egret正好适合开发这类游戏。Egret使用TypeScript作为开发语言,最终编译为JavaScript,正好和原始版本PK一下。 21 | 22 | 游戏预览: 23 | 24 | [2048egret](http://xzper.com/project/2048egret/) 25 | 26 | [PieceOfPie](http://xzper.com/project/pieceofpie/) 27 | 28 | **1.准备开始** 29 | 30 | 在开始之前,我们需要学习一下TypeScript和阅读官方的教程从Egret开发环境的部署到创建,编译,发布项目,以及Egret相关工具。在安装好开发环境后,在工作空间目录下使用命令行,创建2048egret新项目 31 | 32 | egret create 2048egret 33 | 34 | **2.准备素材** 35 | 36 | 每一个游戏都离不开美术资源,我们需要做的就是把美术资源打包,然后加载进来使用。这一方面egret有一套完整的工作流。 37 | 38 | **①资源打包** 39 | 40 | 这里我们用到的资源主要有按钮,背景,文字以及数字这些图片。我们选择把这些图片都打包在一起合成一张大图就像 [这样](http://xzper.com/project/2048egret/resource/assets/source.png) 和 [这样](http://xzper.com/project/2048egret/resource/assets/number.png) 这样做可以减少URL请求数,还能减少资源的体积,把一些具有相同特征的图片放在一起便于管理。在egret里面这种类型的资源就是sheet。只有图片是不够的,还需要一个json描述文件来说明这张图每一张小图片的位置和大小。目前已经有成熟的工具来生成sheet和json。这里我用到的是 [ShoeBox](http://www.renderhjs.net/shoebox/) 配合这个 [插件](https://github.com/runinspring/egretTools) 来生成egret能识别的json。安装好插件后, 将每一张图片命名,然后将这些图片选中拖入Sprites Sheet中然后配置好生成的文件名点击save就能得到一张大图和一个json了,将图片和json放入"resource/assets/"文件夹下以备使用。此外ShoeBox还能读取swf将MovieClip导出为这种大图,按每一帧自动命名,这里的number.png就是这样导出的,下面有原始素材下载地址。 41 | 42 | **②资源加载** 43 | 44 | 接下来我们需要生成一个资源描述文件resource.json,在游戏开始之前读取这个json来加载对应的文件。egret的资源加载机制可以参考 [这里](https://github.com/egret-labs/egret-core/wiki/Using%20Resource%20System) 现在已经有 [工具](http://bbs.egret-labs.org/thread-48-1-1.html) 能自动生成这个resource.json了。按照下图配置。**注意:虽然我们的资源有图片,但是对应的json文件已经记录了图片的位置,所以在这个工具中我们不需要添加对应的图片只添加json文件就行了。** 45 | 46 |

47 | 48 | 在项目初始化时,使用RES加载资源,简单明了。 49 | 50 | private onAddToStage(event:egret.Event){ 51 | ........ 52 | ........ 53 | //初始化Resource资源加载库 54 | RES.addEventListener(RES.ResourceEvent.CONFIG_COMPLETE,this.onConfigComplete,this); 55 | RES.loadConfig("resource/resource.json","resource/"); 56 | } 57 | 58 | /** 59 | *配置文件加载完成,开始预加载preload资源组。 60 | */ 61 | private onConfigComplete(event:RES.ResourceEvent):void{ 62 | RES.removeEventListener(RES.ResourceEvent.CONFIG_COMPLETE,this.onConfigComplete,this); 63 | RES.addEventListener(RES.ResourceEvent.GROUP_COMPLETE,this.onResourceLoadComplete,this); 64 | RES.addEventListener(RES.ResourceEvent.GROUP_PROGRESS,this.onResourceProgress,this); 65 | RES.loadGroup("preload"); 66 | } 67 | 68 | **③资源使用** 69 | 70 | 在项目中我们可以使用RES来使用资源,参照对应的API。对于没有写进配置文件的资源使用RES.getResByUrl方法来异步获取。开发人员能使用极其少量的代码来完成各类资源的加载。 71 | 72 | **3.更改模板生成的代码** 73 | 74 | **①修改细节** 75 | 76 | 默认的文档类是GameApp。我觉得还是叫Main比较亲切,修改类名称,然后修改项目目录下的egretProperties.json文件,将document_class的值改为Main 77 | 78 | { 79 | "document_class" : "Main", 80 | "native": { 81 | "path_ignore": [ 82 | "libs" 83 | ] 84 | } 85 | } 86 | 87 | 默认生成的html的背景是黑色的,这里全部改成白色。将index.html里面的背景替换成#ffffff。 88 | 89 | 默认尺寸是480x800的尺寸。由于我们使用的部分图片宽度大于500,以及部分PC的分辨率太小为了不出现垂直滚动条影响体验,将尺寸换成520x650。这个不影响移动设备上的尺寸,移动设备默认是自适应宽度的。 90 | 91 | index.html中 92 | 93 |
94 | 95 |
96 | 97 | egret_loader.js中 98 | 99 | //设置屏幕适配策略 100 | egret.StageDelegate.getInstance().setDesignSize(520, 650); 101 | context.stage = new egret.Stage(); 102 | var scaleMode = egret.MainContext.deviceType == egret.MainContext.DEVICE_MOBILE ? egret.StageScaleMode.SHOW_ALL : egret.StageScaleMode.NO_SCALE; 103 | context.stage.scaleMode = scaleMode; 104 | 105 | **③引入第三方库pureMVC** 106 | 107 | 这次我们要使用到一个mvc开发框架-pureMVC,熟悉as3的朋友一定也对这个框架不陌生吧。不熟悉的也没关系,这个框架不是这次的主角。我们从 [这里](https://github.com/PureMVC/puremvc-typescript-standard-framework) 下载pureMVC的TypeScript版本。得到puremvc-typescript-standard-1.0.d.ts 和 puremvc-typescript-standard-1.0.js这两个文件,其实.d.ts就类似于c++里面的.h头文件,只有空方法和空属性,真正的实现是在js文件或者ts文件里面。在项目里面的src文件夹下建立一个puremvc的文件夹,将这个js文件和d.ts文件放进去。然后在项目根目录下建立一个puremvc.json的文件内容如下 108 | 109 | { 110 | "name": "puremvc", 111 | "source":"src/puremvc/", 112 | "file_list": [ 113 | "puremvc-typescript-standard-1.0.js", 114 | "puremvc-typescript-standard-1.0.d.ts" 115 | ] 116 | } 117 | 118 | 这样就表示配置了一个第三方模块。之后在编译器编译时会把相应的模块对应的js文件夹编译进libs文件夹下。项目里面我们还使用了gui模块,这些模块的配置是在egretProperties.json中,部分代码如下 119 | 120 | "modules": [ 121 | { 122 | "name": "core" 123 | }, 124 | { 125 | "name": "gui" 126 | }, 127 | { 128 | "name": "puremvc","path":"." 129 | } 130 | ], 131 | 132 | **④注入AssetAdapter和SkinAdapter** 133 | 134 | 我们这次的主角是egret的GUI。找到官方GUIExample中的这两个ts文件复制到项目的src文件夹下面,由于这个项目没有用到默认皮肤,删除ShinAdapter里面getDefaultSkin方法的默认皮肤。最后不要忘了一点,在引擎初始化的时候注入这两个Adapter。 135 | 136 | private onAddToStage(event:egret.Event){ 137 | //注入自定义的素材解析器 138 | egret.Injector.mapClass("egret.gui.IAssetAdapter",AssetAdapter); 139 | //注入自定义的皮肤解析器 140 | egret.Injector.mapClass("egret.gui.ISkinAdapter",SkinAdapter); 141 | ...... 142 | ...... 143 | } 144 | 145 | 这两个的Adapter的作用至关重要,AssetAdapter负责解释UIAsset的source属性 ,SkinAdapter负责解释SkinnableCompent的skinName属性。这里官方提供了两个默认已经写好了的,当然我们可以自己扩展。 没有他们,UIAsset素材包装器的source属性 和 可设置皮肤的GUI组件的skinName属性毫无作用。而这两种组件是今后使用最多的。不信可以往下看 。 146 | 147 | **⑤修改createGameScene方法** 148 | 149 | 在生成的模板中,文档类Main在经过一系列的前期准备工作之后,终于轮到GUI组件的老大UIStage上场了。UIStage类似于Flex里面的SystemManager,内置弹出窗口层,工具提示层和鼠标样式层,所有的GUI组件都应该添加到他的下面,并且UIStage全局唯一。  这里我们实现了一个AppContainer继承自UIStage。 同时在这里pureMVC框架正式启动,开始运作。 150 | 151 | /** 152 | * 创建游戏场景 153 | */ 154 | private createGameScene():void { 155 | var appContainer:game.AppContainer = new game.AppContainer(); 156 | this.addChild(appContainer); 157 | game.ApplicationFacade.getInstance().startUp(appContainer); 158 | } 159 | 160 | **4.pureMVC** 161 | 162 | **①Mediator** 163 | 164 | Mediator(中介器)是连接视图也就是egret的GUI和pureMVC的桥梁。Mediator受到消息时(handleNotification)调用GUI组件的方法和设置属性,来改变视图。或者视图发生改变时通知Mediator由其发送消息到pureMVC(sendNotification)。 165 | 166 | **ApplicationMediator** 监听键盘事件或者手势发送消息到GameCommand通知移动 167 | 168 | **MainGameMediator** 接收消息,调用MainGameUI的方法处理格子的移动,添加,删除,重置,以及接收游戏结果,显示结果面板 169 | 170 | **MainMenuMediator** 接收更新分数的消息,调用MainGameUI的方法更新分数与重置 171 | 172 | **ResultWindowMediator** 发送游戏重置的消息,以及自销毁。 173 | 174 | **②Command** 175 | 176 | command属于控制器。负责收发消息和处理简单的事务。在StartupCommand中使用ControllerPrepCommand,ModelPrepCommand,ViewPrepCommand三个子任务。分别注册控制器,数据和视图。 177 | 178 | **GameCommand** 处理各类事务。比如 玩家按下了方向键,收到消息调用GridProxy的移动方法改变数据,比如GridProxy移动格子分数改变了,通知GameCommand 调用GameProxy的更新分数方法改变分数,比如处理重置游戏的事务,通知各个数据模块重置数据 179 | 180 | **③Proxy** 181 | 182 | 处理数据,提供公共方法供Command调用以改变数据。改变数据了然后sendNotification通知Mediator改变视图。 183 | 184 | **GameProxy** 处理游戏数据,比如更新分数,处理游戏结果 185 | 186 | **GridProxy** 这个游戏的核心数据,操作每一个格子的数据,通知视图格子的移动,添加,删除,重置。这里包含2048这个游戏的精髓。有兴趣的可以研究下,源码里面有详细注释,这篇文章不做重点讲解。 187 | 188 | **5.egret的GUI** 189 | 190 | **①制作菜单-------认识皮肤部件** 191 | 192 | 先来看看菜单长什么样子 193 | 194 | ![](http://xzper.qiniudn.com/2014/06/菜单.jpg) 195 | 196 | 我们会发现这个菜单。有些是静态文本,是一直不变的,我偷懒直接用了一张图片代替了,图片可以用egret.gui.UIAsset。 197 | 198 | 还有当前得分和最高分已经那个向上飘的数字是动态的,可以选用egret.gui.Label这个组件。 199 | 200 | 一个重试按钮,既然已经说了是按钮了我们就用egret.gui.Button好了。 201 | 202 | 接下来我们要做到皮肤和组件分离。那几个需要参与逻辑的组件自然就成了皮肤部件了。来看看MainMenuUISkin: 203 | 204 | /** 205 | * 和主机组件匹配的皮肤部件 206 | */ 207 | private static _skinParts:Array<string> = ["addLabel","scoreLabel","highScoreLabel","resetButton"]; 208 | 209 | public get skinParts():Array<string>{ 210 | return MainMenuUISkin._skinParts; 211 | } 212 | 213 | /** 214 | * 加分文本 215 | */ 216 | public addLabel:egret.gui.Label; 217 | 218 | /** 219 | * 总分文本 220 | */ 221 | public scoreLabel:egret.gui.Label; 222 | 223 | /** 224 | * 最高分文本 225 | */ 226 | public highScoreLabel:egret.gui.Label; 227 | 228 | /** 229 | * 重置按钮 230 | */ 231 | public resetButton:egret.gui.Button; 232 | 233 | public createChildren():void 234 | { 235 | super.createChildren; 236 | var uiAsset:egret.gui.UIAsset = new egret.gui.UIAsset(); 237 | uiAsset.source = "source.menu"; 238 | this.addElement(uiAsset); 239 | 240 | this.resetButton = new egret.gui.Button(); 241 | this.resetButton.skinName = ResetButtonSkin; 242 | this.resetButton.right = 10; 243 | this.resetButton.top = 80; 244 | this.resetButton.label = "重置游戏"; 245 | this.addElement(this.resetButton); 246 | 247 | this.highScoreLabel = new egret.gui.Label(); 248 | ...省略若干代码 249 | this.scoreLabel = new egret.gui.Label(); 250 | ...省略若干代码 251 | this.addLabel = new egret.gui.Label(); 252 | ...省略若干代码 253 | } 254 | 255 | 篇幅有限,省略了createChildren方法里面的子组件布局。**skin的createChildren方法是在皮肤和主机组件匹配的时候被调用的。皮肤和主机组件匹配是在主机组件被添加到显示列表的时候完成的。所以只要主机组件hostComponent还没有添加到显示舞台,获取hostComponent的皮肤部件都是无效的。**这也是为什么我将Mediator的注册放在GUI组件的createComplete后。以防Mediator访问出现空对象的情况。 256 | 257 | 再来看看主机组件MainMenuUI是怎么写的。 258 | 259 | export class MainMenuUI extends egret.gui.SkinnableComponent{ 260 | public addLabel:egret.gui.Label; 261 | public scoreLabel:egret.gui.Label; 262 | public highScoreLabel:egret.gui.Label; 263 | public resetButton:egret.gui.Button; 264 | 265 | public constructor(){ 266 | super(); 267 | this.skinName = MainMenuUISkin; 268 | this.addEventListener(egret.gui.UIEvent.CREATION_COMPLETE , this.createCompleteEvent, this); 269 | } 270 | 271 | public createCompleteEvent(event:egret.gui.UIEvent):void{ 272 | this.removeEventListener(egret.gui.UIEvent.CREATION_COMPLETE , this.createCompleteEvent, this); 273 | ApplicationFacade.getInstance().registerMediator( new MainMenuMediator(this) ); 274 | } 275 | 276 | public partAdded(partName:string, instance:any):void{ 277 | super.partAdded(partName , instance); 278 | if(this.addLabel == instance){ 279 | this.addLabel.visible = false; 280 | } 281 | } 282 | 283 | private moveEffect_effectEndHandler():void 284 | { 285 | this.addLabel.visible = false; 286 | } 287 | 288 | /** 289 | * 加分效果 290 | */ 291 | public playScoreEffect(addScore:number):void{ 292 | this.addLabel.visible = true; 293 | this.addLabel.text = "+".concat(addScore.toString()); 294 | egret.Tween.removeTweens(this.addLabel); 295 | this.addLabel.y = 25; 296 | egret.Tween.get(this.addLabel).to({y:0},300).call(this.moveEffect_effectEndHandler , this); 297 | } 298 | } 299 | 300 | 在构造函数里面赋值skinName传入皮肤的类引用,这个解析过程就是SkinAdapter完成的。 可以看到主机组件有一个partAdded进行皮肤组件的配对。这个时候我们就可以获取到对应的皮肤组件,来进行操作了, 301 | 302 | **②制作游戏区域--------了解九宫格和容器布局** 303 | 304 | ![](http://xzper.qiniudn.com/2014/06/游戏演示.png) 305 | 306 | 再次来观察这个游戏的主界面。有一张纯色的背景图,还有4x4个空白的格子,随着游戏的进行会多出带数字的格子,游戏结束了还会出现胜利的界面。 307 | 308 | 先来看看第一张图。也许你认为这个背景一张4x4的图片不就搞定了么。不过我们这个2048单元格的数量可是可以任意调整的,可以是5x5,或者6x6甚至更多,这样才具备灵活性。你只需要改变CommandData的size属性就可以了(PS:游戏胜利的条件默认是达成2048,也可以通过修改CommandData的winValue属性来修改条件比如8192时胜利或者像上面那样32的时候胜利,想不输都难)。 309 | 310 | 我们继承SkinnableContainer建立一个MainGameUI的类作为容器来显示上面的界面,当然同时还需要一个皮肤MainGameUISkin。先来确定skinParts,如下: 311 | 312 | /** 313 | * 和主机组件匹配的皮肤部件 314 | */ 315 | private static _skinParts:Array<string> = [ 316 | "tileGroup","contentGroup" 317 | ]; 318 | 319 | public get skinParts():Array<string>{ 320 | return MainGameUISkin._skinParts; 321 | } 322 | 323 | /** 324 | * 游戏底背景 325 | */ 326 | private backUIAsset:egret.gui.UIAsset; 327 | 328 | /** 329 | * 背景格子容器 330 | */ 331 | private backGroundGroup:egret.gui.Group; 332 | 333 | /** 334 | * 格子容器 335 | */ 336 | public tileGroup:egret.gui.Group; 337 | 338 | /** 339 | * 内容 340 | */ 341 | public contentGroup:egret.gui.Group; 342 | 343 | 游戏游戏的底背景backUIAsset和背景格子容器backGroundGroup由于逻辑组件MainGameUI不需要关心所有这里不将其设置为skinParts。tileGroup是放置单元格的容器,contentGroup是SkinnableContainer的皮肤部件,SkinnableContainer的addElement方法实际上是添加到这个里面,换言之如果皮肤缺少这个contentGroup那么调用MainGameUI的addElement是看不到你要添加的子项的。 然后override这个createChildren方法将这些组件加入到显示列表。 344 | 345 | public createChildren():void 346 | { 347 | super.createChildren; 348 | this.backUIAsset = new egret.gui.UIAsset(); 349 | this.backUIAsset.source = "source.background"; 350 | //使用九宫格 351 | this.backUIAsset.scale9Grid = new egret.gui.Rectangle(20, 20, 65, 65); 352 | this.backUIAsset.width = CommonData.size*(TileUI.size + this.gap) + this.gap; 353 | this.backUIAsset.height = this.backUIAsset.width; 354 | this.addElement(this.backUIAsset); 355 | 356 | //使用格子布局 357 | var layout:egret.gui.TileLayout = new egret.gui.TileLayout(); 358 | layout.columnCount = layout.rowCount = CommonData.size; 359 | layout.horizontalGap = layout.verticalGap = this.gap; 360 | this.backGroundGroup = new egret.gui.Group(); 361 | this.backGroundGroup.x = this.backGroundGroup.y = this.gap; 362 | this.backGroundGroup.layout = layout; 363 | this.addElement(this.backGroundGroup); 364 | this.initBackGround(CommonData.size); 365 | 366 | this.tileGroup = new egret.gui.Group(); 367 | this.tileGroup.x = this.tileGroup.y = this.gap; 368 | this.addElement(this.tileGroup); 369 | 370 | this.contentGroup = new egret.gui.Group(); 371 | this.contentGroup.percentHeight = this.contentGroup.percentWidth = 100; 372 | this.contentGroup.touchEnabled = false; 373 | this.addElement(this.contentGroup); 374 | } 375 | 376 | 先看backUIAsset,由于图片素材只是一个小的纯色圆角矩形,使用scale9Grid属性来设置九宫格缩放,这样设置了宽高就不会变形了。这里backGroundGroup设置了一个layout来确定布局。设置好间距以及行列数,向容器里面添加子项时就自动设置了位置了,不需要设置子项的x,y属性。TileLayout会自动布局。 377 | 378 | private initBackGround(size:number):void{ 379 | //背景格子 380 | var tile:egret.gui.UIAsset; 381 | var totalNum:number = size * size; 382 | for(var i:number = 0;i < totalNum ; i++) 383 | { 384 | tile = new egret.gui.UIAsset(); 385 | tile.width = tile.height = TileUI.size; 386 | tile.source = "source.backtile"; 387 | this.backGroundGroup.addElement(tile); 388 | } 389 | } 390 | 391 | **③制作单元格--------自定义属性** 392 | 393 | 单元格使用TileUI来定义。单元格有一个很重要的属性就是单元格的数据,这里使用value属性来表示。 394 | 395 | private valueChanged:boolean; 396 | private _value:number; 397 | /** 398 | * 格子的数字 399 | */ 400 | public get value():number{ 401 | return this._value; 402 | } 403 | 404 | public set value(value:number){ 405 | if(value == this._value){ 406 | return; 407 | } 408 | this.valueChanged = true; 409 | this._value = value; 410 | this.invalidateProperties(); 411 | } 412 | 413 | public commitProperties():void{ 414 | if(this.valueChanged){ 415 | this.valueChanged = false; 416 | this.updateValue(); 417 | } 418 | } 419 | 420 | private updateValue():void{ 421 | var mi:number = Math.log(this._value)/Math.log(2); 422 | this.source = "number.number_"+mi; 423 | } 424 | 425 | 这里使用了invalidateProperties和commitProperties来完成属性的失效验证。当设置value的时候调用invalidateProperties,失效属性,GUI框架在下一次渲染的时候会调用commitProperties来完成属性的提交。失效验证简单说就是一种延迟应用改变的措施,这种失效验证在egret的GUI组件内部随处可见。这种自定义属性的例子只是其中之一,当组件的commitProperties方法被调用时组件已经准备完毕,所有的皮肤部件也匹配上了。这样也不用担心应用属性的时候报空的情况。这里通过设置TileUI的source属性来改变数字。还记得一开始的resource.json加载的number.json么。 426 | 427 | { 428 | "frames": { 429 | "number_1": {"x":106, "y":212, "w":105, "h":105, "offX":0,"offY":0,"sourceW":105,"sourceH":105}, 430 | "number_10": {"x":0, "y":318, "w":105, "h":105, "offX":0,"offY":0,"sourceW":105,"sourceH":105}, 431 | "number_11": {"x":0, "y":212, "w":105, "h":105, "offX":0,"offY":0,"sourceW":105,"sourceH":105}, 432 | "number_12": {"x":0, "y":106, "w":105, "h":105, "offX":0,"offY":0,"sourceW":105,"sourceH":105}, 433 | "number_13": {"x":0, "y":0, "w":105, "h":105, "offX":0,"offY":0,"sourceW":105,"sourceH":105}, 434 | "number_2": {"x":212, "y":318, "w":105, "h":105, "offX":0,"offY":0,"sourceW":105,"sourceH":105}, 435 | "number_3": {"x":212, "y":212, "w":105, "h":105, "offX":0,"offY":0,"sourceW":105,"sourceH":105}, 436 | "number_4": {"x":212, "y":106, "w":105, "h":105, "offX":0,"offY":0,"sourceW":105,"sourceH":105}, 437 | "number_5": {"x":212, "y":0, "w":105, "h":105, "offX":0,"offY":0,"sourceW":105,"sourceH":105}, 438 | "number_6": {"x":106, "y":318, "w":105, "h":105, "offX":0,"offY":0,"sourceW":105,"sourceH":105}, 439 | "number_7": {"x":318, "y":0, "w":105, "h":105, "offX":0,"offY":0,"sourceW":105,"sourceH":105}, 440 | "number_8": {"x":106, "y":106, "w":105, "h":105, "offX":0,"offY":0,"sourceW":105,"sourceH":105}, 441 | "number_9": {"x":106, "y":0, "w":105, "h":105, "offX":0,"offY":0,"sourceW":105,"sourceH":105} 442 | 443 | }, 444 | "file": "number.png" 445 | } 446 | 447 | 这个sheet记录的每一张图也有一个名称比如2这个数字就是number\_1加上number这个sheet名称使用"."符号连接,所以获取"2"这个数字的图片就可以这样写this.source = "number.number\_1"。根据值的不同取2的对数得到相应的下标数字。 448 | 449 | **④制作胜负界面--------自定义组件状态** 450 | 451 | 游戏结束之后会出现胜负的界面。但是胜负界面应该是两套不同的素材,那么我们是不是可以制作两个皮肤来根据胜负来切换?这样当然可以。但是,还有一种更简单的办法就是使用自定义状态,只需要一个皮肤类就可以完成两种视图的切换。 452 | 453 | 新建一个ResultWindow类继承自SkinnableComponent,然后新建ResultWindowSkin。在ResultWindowSkin的构造函数中定义两个状态win和failed。 454 | 455 | public constructor(){ 456 | super(); 457 | this.states = ["win","failed"]; 458 | } 459 | 460 | 然后加入两个皮肤部件button和resultUI 461 | 462 | private static _skinParts:Array = ["button","resultUI"]; 463 | 464 | public get skinParts():Array{ 465 | return ResultWindowSkin._skinParts; 466 | } 467 | 468 | /** 469 | * 按钮 470 | */ 471 | public button:egret.gui.Button; 472 | 473 | /** 474 | * 结果文本 475 | */ 476 | public resultUI:egret.gui.UIAsset; 477 | 478 | 在createChildren里面将皮肤部件布局好位置。最后重写commitCurrentState方法来根据对应的状态来改变部件的skin。 479 | 480 | public commitCurrentState():void { 481 | super.commitCurrentState(); 482 | if(this.currentState == "win") 483 | { 484 | this.resultUI.source = "source.result_sucess"; 485 | this.button.skinName = ContinueButtonSkin; 486 | } 487 | else 488 | { 489 | this.resultUI.source = "source.result_failed"; 490 | this.button.skinName = ResetButtonSkin; 491 | } 492 | } 493 | 494 | 这样还没有完,我们需要在主机组件里面定义何时是何种状态,在ResultWindow中重写getCurrentSkinState来定义皮肤状态。 495 | 496 | private _win:boolean = false; 497 | public get win():boolean{ 498 | return this._win; 499 | } 500 | 501 | public set win(value:boolean){ 502 | if(value == this._win) 503 | return; 504 | this._win = value; 505 | this.invalidateSkinState(); 506 | } 507 | 508 | public getCurrentSkinState():string { 509 | return this.win?"win":"failed"; 510 | } 511 | 512 | 当外界设置win的值时调用invalidateSkinState来失效皮肤状态,在框架下次渲染的时候,调用SkinnableComponent的validateSkinState方法同时通过getCurrentSkinState来获取皮肤状态,通知皮肤去改变视图。这又是失效验证机制的一次完美使用。我们只需要调用失效,然后重写对应的验证方法就行了。事实上,按钮的up,down,disable之类的状态也是这样实现的。 513 | 514 | egret的GUI库,集合了Flex和[FlexLite](http://flexlite.org)的核心思想。实现了自动布局,皮肤分离,组件的三层失效验证机制。快来膜拜作者[DOM](http://blog.domlib.com/)大神吧。 515 | 516 | **6.优化游戏** 517 | 518 | **①使用对象池** 519 | 520 | 在游戏里面随着游戏的进行,每一次移动都有一个格子组件TileUI的创建,当游戏久了会造成巨大的内存开销。这里使用对象池技术。当一个对象使用完毕时,放入对象池,下次需要使用时取出来,这样避免了对象的重复创建,节约了内存。具体的实现参考ObjectPool这个类。具体使用在MainGameUI里面,如下: 521 | 522 | /** 523 | * 创建一个格子 524 | */ 525 | public createTile(tileVO:TileVO):void{ 526 | var tile:TileUI = <TileUI>(ObjectPool.getPool("game.TileUI").borrowObject()); //从对象池创建 527 | ...... 528 | ...... 529 | } 530 | 531 | 当对象池里面没有TileUI时使用会new一个出来,否则直接从对象池获取。 532 | 533 | /** 534 | * 清除一个格子 535 | */ 536 | public removeTile(tileVO:TileVO):void{ 537 | var tileUI:TileUI = this.getTileUI(tileVO.x , tileVO.y); 538 | if(tileUI){ 539 | this.tileGroup.removeElement(tileUI); 540 | ObjectPool.getPool("game.TileUI").returnObject(tileUI); 541 | } 542 | } 543 | 544 | 当格子销毁时,回收到对象池,以备下次使用。 545 | 546 | 另外由于js没有提供弱引用特性,在对象池里面的对象要彻底销毁就需要手动了。 547 | 548 | **②针对不同设备** 549 | 550 | 游戏在PC我们使用键盘上的方向键操控游戏,但是在移动设备上就需要使用手势来操控了,通过egret.MainContext.deviceType这个值来获取平台 。具体实现在ApplicationMediator中: 551 | 552 | //为PC和移动端设置不同的移动策略 553 | if(egret.MainContext.deviceType != egret.MainContext.DEVICE_MOBILE) 554 | { 555 | var self = this; 556 | document.addEventListener("keydown",function(event:KeyboardEvent){ 557 | switch (event.keyCode) { 558 | ....省略键盘事件...... 559 | } 560 | }); 561 | } 562 | else 563 | { 564 | this.main.addEventListener(egret.TouchEvent.TOUCH_BEGIN , this.mouseDownHandle , this) 565 | } 566 | 567 | 由于egret目前没有提供手势的API,这里我们自己实现手势。监听TOUCH\_BEGIN,TOUCH\_MOVE,TOUCH\_END和LEAVE\_STAGE这四个事件。具体实现如下: 568 | 569 | private downPoint:egret.Point; 570 | private movePoint:egret.Point; 571 | private mouseDownHandle(event:egret.TouchEvent):void 572 | { 573 | egret.UIGlobals.stage.addEventListener(egret.TouchEvent.TOUCH_MOVE,this.stage_mouseMoveHandler,this); 574 | egret.UIGlobals.stage.addEventListener(egret.TouchEvent.TOUCH_END,this.stage_mouseUpHandler,this); 575 | egret.UIGlobals.stage.addEventListener(egret.Event.LEAVE_STAGE,this.stage_mouseUpHandler,this); 576 | 577 | this.downPoint = this.main.globalToLocal(event.stageX, event.stageY); 578 | } 579 | 580 | private needMove:boolean; 581 | private stage_mouseMoveHandler(event:egret.TouchEvent):void{ 582 | if(!this.movePoint) 583 | this.movePoint = new egret.Point(); 584 | this.movePoint.x = event.stageX; 585 | this.movePoint.y = event.stageY; 586 | if (this.needMove) 587 | return; 588 | this.needMove = true; 589 | } 590 | 591 | public stage_mouseUpHandler(event:egret.Event):void{ 592 | egret.UIGlobals.stage.removeEventListener(egret.TouchEvent.TOUCH_MOVE, 593 | this.stage_mouseMoveHandler, 594 | this); 595 | egret.UIGlobals.stage.removeEventListener(egret.TouchEvent.TOUCH_END, 596 | this.stage_mouseUpHandler, 597 | this); 598 | egret.UIGlobals.stage.addEventListener(egret.Event.LEAVE_STAGE, 599 | this.stage_mouseUpHandler, 600 | this); 601 | if(this.needMove){ 602 | this.updateWhenMouseUp(); 603 | this.needMove = false; 604 | } 605 | } 606 | 607 | /** 608 | * 移动设备上,判断移动方向 609 | */ 610 | private updateWhenMouseUp():void 611 | { 612 | var p:egret.Point = this.main.globalToLocal(this.movePoint.x, this.movePoint.y ,egret.Point.identity); 613 | var offSetX:number = p.x - this.downPoint.x; 614 | var offSetY:number = p.y - this.downPoint.y; 615 | 616 | if(offSetY<0 && Math.abs(offSetY)>Math.abs(offSetX)) //上 617 | { 618 | this.doMove(0); 619 | } 620 | else if(offSetX>0 && offSetX>Math.abs(offSetY)) //右 621 | { 622 | this.doMove(1); 623 | } 624 | else if(offSetY>0 && offSetY>Math.abs(offSetX)) //下 625 | { 626 | this.doMove(2); 627 | } 628 | else if(offSetX<0 && Math.abs(offSetX)>Math.abs(offSetY)) //左 629 | { 630 | this.doMove(3); 631 | } 632 | } 633 | 634 | **③动画效果** 635 | 636 | 游戏里面格子的创建,移动,合并,都需要一个缓动效果来支持。这里面最大的问题就是,缓动效果是持续时间的,而往往数据的改变是一瞬间。比如:一个操作合并了两个格子,其中一个需要移动,并且移动完成后要移除掉,此时新的格子也要出现。但是往往数据层把这些数据是同时发过来的,所以我们需要调节时机来让效果更好。比如格子的创建,我们延迟100毫秒显示在舞台上,因为在创建的同时其他格子会移动,所以等其他格子移动完成了后显示出来比较好。再比如格子的合并,实际上就是一个格子移动,移动完成后消失,目标位置格子改变数字并且出现缩放效果。这样要注意的就是移动之前调整将移动的格子的层级显示在最下面,避免移动的时候挡在目标位置格子的上面。 637 | 638 | **7.性能** 639 | 640 | egret的工作流还是很高效的,工具也不少,架构设计集各家所长。最后发布游戏在PC上运行是满帧运行,比原版甚至更快。在手机上运行也不错,体验超过了某些原生语言开发的2048。 641 | 642 | 最后交出源代码:[点我传送](https://github.com/f111fei/2048egret) 643 | -------------------------------------------------------------------------------- /modules/puremvc/src/puremvc.js: -------------------------------------------------------------------------------- 1 | //if( typeof define === "function" ) 2 | //{ 3 | // define( "puremvc", [], function() 4 | // { 5 | var puremvc; 6 | (function (puremvc) { 7 | "use strict"; 8 | var Observer = (function () { 9 | function Observer(notifyMethod, notifyContext) { 10 | this.notify = null; 11 | this.context = null; 12 | this.setNotifyMethod(notifyMethod); 13 | this.setNotifyContext(notifyContext); 14 | } 15 | Observer.prototype.getNotifyMethod = function () { 16 | return this.notify; 17 | }; 18 | Observer.prototype.setNotifyMethod = function (notifyMethod) { 19 | this.notify = notifyMethod; 20 | }; 21 | Observer.prototype.getNotifyContext = function () { 22 | return this.context; 23 | }; 24 | Observer.prototype.setNotifyContext = function (notifyContext) { 25 | this.context = notifyContext; 26 | }; 27 | Observer.prototype.notifyObserver = function (notification) { 28 | this.getNotifyMethod().call(this.getNotifyContext(), notification); 29 | }; 30 | Observer.prototype.compareNotifyContext = function (object) { 31 | return object === this.context; 32 | }; 33 | return Observer; 34 | })(); 35 | puremvc.Observer = Observer; 36 | })(puremvc || (puremvc = {})); 37 | 38 | var puremvc; 39 | (function (puremvc) { 40 | "use strict"; 41 | var View = (function () { 42 | function View() { 43 | this.mediatorMap = null; 44 | this.observerMap = null; 45 | if(View.instance) { 46 | throw Error(View.SINGLETON_MSG); 47 | } 48 | View.instance = this; 49 | this.mediatorMap = { 50 | }; 51 | this.observerMap = { 52 | }; 53 | this.initializeView(); 54 | } 55 | View.prototype.initializeView = function () { 56 | }; 57 | View.prototype.registerObserver = function (notificationName, observer) { 58 | var observers = this.observerMap[notificationName]; 59 | if(observers) { 60 | observers.push(observer); 61 | } else { 62 | this.observerMap[notificationName] = [ 63 | observer 64 | ]; 65 | } 66 | }; 67 | View.prototype.removeObserver = function (notificationName, notifyContext) { 68 | var observers = this.observerMap[notificationName]; 69 | var i = observers.length; 70 | while(i--) { 71 | var observer = observers[i]; 72 | if(observer.compareNotifyContext(notifyContext)) { 73 | observers.splice(i, 1); 74 | break; 75 | } 76 | } 77 | if(observers.length == 0) { 78 | delete this.observerMap[notificationName]; 79 | } 80 | }; 81 | View.prototype.notifyObservers = function (notification) { 82 | var notificationName = notification.getName(); 83 | var observersRef = this.observerMap[notificationName]; 84 | if(observersRef) { 85 | var observers = observersRef.slice(0); 86 | var len = observers.length; 87 | for(var i = 0; i < len; i++) { 88 | var observer = observers[i]; 89 | observer.notifyObserver(notification); 90 | } 91 | } 92 | }; 93 | View.prototype.registerMediator = function (mediator) { 94 | var name = mediator.getMediatorName(); 95 | if(this.mediatorMap[name]) { 96 | return; 97 | } 98 | this.mediatorMap[name] = mediator; 99 | var interests = mediator.listNotificationInterests(); 100 | var len = interests.length; 101 | if(len > 0) { 102 | var observer = new puremvc.Observer(mediator.handleNotification, mediator); 103 | for(var i = 0; i < len; i++) { 104 | this.registerObserver(interests[i], observer); 105 | } 106 | } 107 | mediator.onRegister(); 108 | }; 109 | View.prototype.retrieveMediator = function (mediatorName) { 110 | return this.mediatorMap[mediatorName] || null; 111 | }; 112 | View.prototype.removeMediator = function (mediatorName) { 113 | var mediator = this.mediatorMap[mediatorName]; 114 | if(!mediator) { 115 | return null; 116 | } 117 | var interests = mediator.listNotificationInterests(); 118 | var i = interests.length; 119 | while(i--) { 120 | this.removeObserver(interests[i], mediator); 121 | } 122 | delete this.mediatorMap[mediatorName]; 123 | mediator.onRemove(); 124 | return mediator; 125 | }; 126 | View.prototype.hasMediator = function (mediatorName) { 127 | return this.mediatorMap[mediatorName] != null; 128 | }; 129 | View.SINGLETON_MSG = "View singleton already constructed!"; 130 | View.instance = null; 131 | View.getInstance = function getInstance() { 132 | if(!View.instance) { 133 | View.instance = new View(); 134 | } 135 | return View.instance; 136 | } 137 | return View; 138 | })(); 139 | puremvc.View = View; 140 | })(puremvc || (puremvc = {})); 141 | 142 | var puremvc; 143 | (function (puremvc) { 144 | "use strict"; 145 | var Controller = (function () { 146 | function Controller() { 147 | this.view = null; 148 | this.commandMap = null; 149 | if(Controller.instance) { 150 | throw Error(Controller.SINGLETON_MSG); 151 | } 152 | Controller.instance = this; 153 | this.commandMap = { 154 | }; 155 | this.initializeController(); 156 | } 157 | Controller.prototype.initializeController = function () { 158 | this.view = puremvc.View.getInstance(); 159 | }; 160 | Controller.prototype.executeCommand = function (notification) { 161 | var commandClassRef = this.commandMap[notification.getName()]; 162 | if(commandClassRef) { 163 | var command = new commandClassRef(); 164 | command.execute(notification); 165 | } 166 | }; 167 | Controller.prototype.registerCommand = function (notificationName, commandClassRef) { 168 | if(!this.commandMap[notificationName]) { 169 | this.view.registerObserver(notificationName, new puremvc.Observer(this.executeCommand, this)); 170 | } 171 | this.commandMap[notificationName] = commandClassRef; 172 | }; 173 | Controller.prototype.hasCommand = function (notificationName) { 174 | return this.commandMap[notificationName] != null; 175 | }; 176 | Controller.prototype.removeCommand = function (notificationName) { 177 | if(this.hasCommand(notificationName)) { 178 | this.view.removeObserver(notificationName, this); 179 | delete this.commandMap[notificationName]; 180 | } 181 | }; 182 | Controller.SINGLETON_MSG = "Controller singleton already constructed!"; 183 | Controller.instance = null; 184 | Controller.getInstance = function getInstance() { 185 | if(!Controller.instance) { 186 | Controller.instance = new Controller(); 187 | } 188 | return Controller.instance; 189 | } 190 | return Controller; 191 | })(); 192 | puremvc.Controller = Controller; 193 | })(puremvc || (puremvc = {})); 194 | 195 | var puremvc; 196 | (function (puremvc) { 197 | "use strict"; 198 | var Model = (function () { 199 | function Model() { 200 | this.proxyMap = null; 201 | if(Model.instance) { 202 | throw Error(Model.SINGLETON_MSG); 203 | } 204 | Model.instance = this; 205 | this.proxyMap = { 206 | }; 207 | this.initializeModel(); 208 | } 209 | Model.prototype.initializeModel = function () { 210 | }; 211 | Model.prototype.registerProxy = function (proxy) { 212 | this.proxyMap[proxy.getProxyName()] = proxy; 213 | proxy.onRegister(); 214 | }; 215 | Model.prototype.removeProxy = function (proxyName) { 216 | var proxy = this.proxyMap[proxyName]; 217 | if(proxy) { 218 | delete this.proxyMap[proxyName]; 219 | proxy.onRemove(); 220 | } 221 | return proxy; 222 | }; 223 | Model.prototype.retrieveProxy = function (proxyName) { 224 | return this.proxyMap[proxyName] || null; 225 | }; 226 | Model.prototype.hasProxy = function (proxyName) { 227 | return this.proxyMap[proxyName] != null; 228 | }; 229 | Model.SINGLETON_MSG = "Model singleton already constructed!"; 230 | Model.instance = null; 231 | Model.getInstance = function getInstance() { 232 | if(!Model.instance) { 233 | Model.instance = new Model(); 234 | } 235 | return Model.instance; 236 | } 237 | return Model; 238 | })(); 239 | puremvc.Model = Model; 240 | })(puremvc || (puremvc = {})); 241 | 242 | var puremvc; 243 | (function (puremvc) { 244 | "use strict"; 245 | var Notification = (function () { 246 | function Notification(name, body, type) { 247 | if (typeof body === "undefined") { body = null; } 248 | if (typeof type === "undefined") { type = null; } 249 | this.name = null; 250 | this.body = null; 251 | this.type = null; 252 | this.name = name; 253 | this.body = body; 254 | this.type = type; 255 | } 256 | Notification.prototype.getName = function () { 257 | return this.name; 258 | }; 259 | Notification.prototype.setBody = function (body) { 260 | this.body = body; 261 | }; 262 | Notification.prototype.getBody = function () { 263 | return this.body; 264 | }; 265 | Notification.prototype.setType = function (type) { 266 | this.type = type; 267 | }; 268 | Notification.prototype.getType = function () { 269 | return this.type; 270 | }; 271 | Notification.prototype.toString = function () { 272 | var msg = "Notification Name: " + this.getName(); 273 | msg += "\nBody:" + ((this.getBody() == null) ? "null" : this.getBody().toString()); 274 | msg += "\nType:" + ((this.getType() == null) ? "null" : this.getType()); 275 | return msg; 276 | }; 277 | return Notification; 278 | })(); 279 | puremvc.Notification = Notification; 280 | })(puremvc || (puremvc = {})); 281 | 282 | var puremvc; 283 | (function (puremvc) { 284 | "use strict"; 285 | var Facade = (function () { 286 | function Facade() { 287 | this.model = null; 288 | this.view = null; 289 | this.controller = null; 290 | if(Facade.instance) { 291 | throw Error(Facade.SINGLETON_MSG); 292 | } 293 | Facade.instance = this; 294 | this.initializeFacade(); 295 | } 296 | Facade.prototype.initializeFacade = function () { 297 | this.initializeModel(); 298 | this.initializeController(); 299 | this.initializeView(); 300 | }; 301 | Facade.prototype.initializeModel = function () { 302 | if(!this.model) { 303 | this.model = puremvc.Model.getInstance(); 304 | } 305 | }; 306 | Facade.prototype.initializeController = function () { 307 | if(!this.controller) { 308 | this.controller = puremvc.Controller.getInstance(); 309 | } 310 | }; 311 | Facade.prototype.initializeView = function () { 312 | if(!this.view) { 313 | this.view = puremvc.View.getInstance(); 314 | } 315 | }; 316 | Facade.prototype.registerCommand = function (notificationName, commandClassRef) { 317 | this.controller.registerCommand(notificationName, commandClassRef); 318 | }; 319 | Facade.prototype.removeCommand = function (notificationName) { 320 | this.controller.removeCommand(notificationName); 321 | }; 322 | Facade.prototype.hasCommand = function (notificationName) { 323 | return this.controller.hasCommand(notificationName); 324 | }; 325 | Facade.prototype.registerProxy = function (proxy) { 326 | this.model.registerProxy(proxy); 327 | }; 328 | Facade.prototype.retrieveProxy = function (proxyName) { 329 | return this.model.retrieveProxy(proxyName); 330 | }; 331 | Facade.prototype.removeProxy = function (proxyName) { 332 | var proxy; 333 | if(this.model) { 334 | proxy = this.model.removeProxy(proxyName); 335 | } 336 | return proxy; 337 | }; 338 | Facade.prototype.hasProxy = function (proxyName) { 339 | return this.model.hasProxy(proxyName); 340 | }; 341 | Facade.prototype.registerMediator = function (mediator) { 342 | if(this.view) { 343 | this.view.registerMediator(mediator); 344 | } 345 | }; 346 | Facade.prototype.retrieveMediator = function (mediatorName) { 347 | return this.view.retrieveMediator(mediatorName); 348 | }; 349 | Facade.prototype.removeMediator = function (mediatorName) { 350 | var mediator; 351 | if(this.view) { 352 | mediator = this.view.removeMediator(mediatorName); 353 | } 354 | return mediator; 355 | }; 356 | Facade.prototype.hasMediator = function (mediatorName) { 357 | return this.view.hasMediator(mediatorName); 358 | }; 359 | Facade.prototype.notifyObservers = function (notification) { 360 | if(this.view) { 361 | this.view.notifyObservers(notification); 362 | } 363 | }; 364 | Facade.prototype.sendNotification = function (name, body, type) { 365 | if (typeof body === "undefined") { body = null; } 366 | if (typeof type === "undefined") { type = null; } 367 | this.notifyObservers(new puremvc.Notification(name, body, type)); 368 | }; 369 | Facade.SINGLETON_MSG = "Facade singleton already constructed!"; 370 | Facade.instance = null; 371 | Facade.getInstance = function getInstance() { 372 | if(!Facade.instance) { 373 | Facade.instance = new Facade(); 374 | } 375 | return Facade.instance; 376 | } 377 | return Facade; 378 | })(); 379 | puremvc.Facade = Facade; 380 | })(puremvc || (puremvc = {})); 381 | 382 | var puremvc; 383 | (function (puremvc) { 384 | "use strict"; 385 | var Notifier = (function () { 386 | function Notifier() { 387 | this.facade = null; 388 | this.facade = puremvc.Facade.getInstance(); 389 | } 390 | Notifier.prototype.sendNotification = function (name, body, type) { 391 | if (typeof body === "undefined") { body = null; } 392 | if (typeof type === "undefined") { type = null; } 393 | this.facade.sendNotification(name, body, type); 394 | }; 395 | return Notifier; 396 | })(); 397 | puremvc.Notifier = Notifier; 398 | })(puremvc || (puremvc = {})); 399 | 400 | var __extends = this.__extends || function (d, b) { 401 | function __() { this.constructor = d; } 402 | __.prototype = b.prototype; 403 | d.prototype = new __(); 404 | } 405 | var puremvc; 406 | (function (puremvc) { 407 | "use strict"; 408 | var MacroCommand = (function (_super) { 409 | __extends(MacroCommand, _super); 410 | function MacroCommand() { 411 | _super.call(this); 412 | this.subCommands = null; 413 | this.subCommands = new Array(); 414 | this.initializeMacroCommand(); 415 | } 416 | MacroCommand.prototype.initializeMacroCommand = function () { 417 | }; 418 | MacroCommand.prototype.addSubCommand = function (commandClassRef) { 419 | this.subCommands.push(commandClassRef); 420 | }; 421 | MacroCommand.prototype.execute = function (notification) { 422 | var subCommands = this.subCommands.slice(0); 423 | var len = this.subCommands.length; 424 | for(var i = 0; i < len; i++) { 425 | var commandClassRef = subCommands[i]; 426 | var commandInstance = new commandClassRef(); 427 | commandInstance.execute(notification); 428 | } 429 | this.subCommands.splice(0); 430 | }; 431 | return MacroCommand; 432 | })(puremvc.Notifier); 433 | puremvc.MacroCommand = MacroCommand; 434 | })(puremvc || (puremvc = {})); 435 | 436 | var puremvc; 437 | (function (puremvc) { 438 | "use strict"; 439 | var SimpleCommand = (function (_super) { 440 | __extends(SimpleCommand, _super); 441 | function SimpleCommand() { 442 | _super.apply(this, arguments); 443 | 444 | } 445 | SimpleCommand.prototype.execute = function (notification) { 446 | }; 447 | return SimpleCommand; 448 | })(puremvc.Notifier); 449 | puremvc.SimpleCommand = SimpleCommand; 450 | })(puremvc || (puremvc = {})); 451 | 452 | var puremvc; 453 | (function (puremvc) { 454 | "use strict"; 455 | var Mediator = (function (_super) { 456 | __extends(Mediator, _super); 457 | function Mediator(mediatorName, viewComponent) { 458 | if (typeof mediatorName === "undefined") { mediatorName = null; } 459 | if (typeof viewComponent === "undefined") { viewComponent = null; } 460 | _super.call(this); 461 | this.mediatorName = null; 462 | this.viewComponent = null; 463 | this.mediatorName = (mediatorName != null) ? mediatorName : Mediator.NAME; 464 | this.viewComponent = viewComponent; 465 | } 466 | Mediator.prototype.getMediatorName = function () { 467 | return this.mediatorName; 468 | }; 469 | Mediator.prototype.getViewComponent = function () { 470 | return this.viewComponent; 471 | }; 472 | Mediator.prototype.setViewComponent = function (viewComponent) { 473 | this.viewComponent = viewComponent; 474 | }; 475 | Mediator.prototype.listNotificationInterests = function () { 476 | return new Array(); 477 | }; 478 | Mediator.prototype.handleNotification = function (notification) { 479 | }; 480 | Mediator.prototype.onRegister = function () { 481 | }; 482 | Mediator.prototype.onRemove = function () { 483 | }; 484 | Mediator.NAME = 'Mediator'; 485 | return Mediator; 486 | })(puremvc.Notifier); 487 | puremvc.Mediator = Mediator; 488 | })(puremvc || (puremvc = {})); 489 | 490 | var puremvc; 491 | (function (puremvc) { 492 | "use strict"; 493 | var Proxy = (function (_super) { 494 | __extends(Proxy, _super); 495 | function Proxy(proxyName, data) { 496 | if (typeof proxyName === "undefined") { proxyName = null; } 497 | if (typeof data === "undefined") { data = null; } 498 | _super.call(this); 499 | this.data = null; 500 | this.proxyName = null; 501 | this.proxyName = (proxyName != null) ? proxyName : Proxy.NAME; 502 | if(data != null) { 503 | this.setData(data); 504 | } 505 | } 506 | Proxy.prototype.getProxyName = function () { 507 | return this.proxyName; 508 | }; 509 | Proxy.prototype.setData = function (data) { 510 | this.data = data; 511 | }; 512 | Proxy.prototype.getData = function () { 513 | return this.data; 514 | }; 515 | Proxy.prototype.onRegister = function () { 516 | }; 517 | Proxy.prototype.onRemove = function () { 518 | }; 519 | Proxy.NAME = "Proxy"; 520 | return Proxy; 521 | })(puremvc.Notifier); 522 | puremvc.Proxy = Proxy; 523 | })(puremvc || (puremvc = {})); 524 | // 525 | // 526 | // return puremvc; 527 | // }); 528 | //} --------------------------------------------------------------------------------