├── 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 | 
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 | 
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 | //}
--------------------------------------------------------------------------------