<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                植物大戰僵尸一直是一個很受歡迎的經典的小游戲,我主要用cocos2d-android做了一個類似的小demo,在這里主要介紹一下我做給這個小demo。 ### 開發前各種準備工作 做一個小游戲我們首先要有一個地圖吧,所以我用tiled這個軟件來制作地圖,安裝和使用都挺簡單了,畫好后用notepad++打開看一下圖片路徑對不對,然后把圖片、字體文件、地圖文件.ttf放到工程的assets目錄下,然后我們就可以在后面使用這些資源了。 當然我,我們先來了解一下一些其他相關知識點 加載地圖 ~~~ CCTMXTiledMap map=CCTMXTiledMap.tiledMap("map.tmx"); this.addChild(map); ~~~ 解析地圖 //解析地圖 ~~~ private void parseMap() { roadPoints=new ArrayList<CGPoint>(); CCTMXObjectGroup objectGroupNamed=map.objectGroupNamed("road"); ArrayList<HashMap<String,String>> objects=objectGroupNamed.objects; for(HashMap<String,String> hashMap:objects){ int x=Integer.parseInt(hashMap.get("x")); int y=Integer.parseInt(hashMap.get("y")); CGPoint cgPoint=ccp(x,y); roadPoints.add(cgPoint); } } ~~~ //展示僵尸 ~~~ int position=3; private void loadZombies() { CCSprite sprite=CCSprite.sprite("z_1_01.png"); sprite.setPosition(roadPoints.get(position)); sprite.setAnchorPoint(0.5f,0); sprite.setScale(0.65f); this.addChild(sprite); } ~~~ 粒子系統 eg:飄雪:CCParticleSnow ~~~ private void loadParticle() { system = CCParticleSnow.node(); // 設置雪花的樣式 system.setTexture(CCTextureCache.sharedTextureCache().addImage("f.png")); this.addChild(system, 1); } system.stopSystem();// 停止粒子系統 ~~~ 自定義效果,后綴.plis 聲音引擎 ~~~ SoundEngine engine=SoundEngine.sharedEngine(); // 1 上下文 2. 音樂資源的id 3 是否循環播放 engine.playSound(CCDirector.theApp, R.raw.psy, true); ~~~ 暫停和繼續 1.onExit(); 2.onEnter(); ~~~ @Override public boolean ccTouchesBegan(MotionEvent event) { this.onExit(); // 暫停 this.getParent().addChild(new PauseLayer());// 讓場景添加新的圖層 return super.ccTouchesBegan(event); } // 專門用來暫停的圖層 private class PauseLayer extends CCLayer{ private CCSprite heart; public PauseLayer(){ this.setIsTouchEnabled(true);// 打開觸摸事件的開關 heart = CCSprite.sprite("heart.png"); // 獲取屏幕的尺寸 CGSize winSize = CCDirector.sharedDirector().getWinSize(); heart.setPosition(winSize.width/2, winSize.height/2);// 讓圖片再屏幕的中間 this.addChild(heart); } // 當點擊PauseLayer的時候 @Override public boolean ccTouchesBegan(MotionEvent event) { CGRect boundingBox = heart.getBoundingBox(); // 把Android坐標系中的點 轉換成Cocos2d坐標系中的點 CGPoint convertTouchToNodeSpace = this.convertTouchToNodeSpace(event); if(CGRect.containsPoint(boundingBox, convertTouchToNodeSpace)){// 確實點擊了心 this.removeSelf();// 回收當前圖層 DemoLayer.this.onEnter();//游戲繼續 } return super.ccTouchesBegan(event); } } ~~~ ### 項目正式開始 首先要有一個logo,logo下面有一個背景圖片,需要加載一個進度條,一步步跳轉就可以了,說到這個進度條,其實就是一個幀動畫 用下面這段代碼來看一下,當然這里之后我抽取了一個CommonUtils工具類, ![這里寫圖片描述](https://box.kancloud.cn/2016-03-14_56e65d6c54270.jpg "") ~~~ private void loading() { CCSprite loading=CCSprite.sprite("image/loading/loading_01.png"); loading.setPosition(winSize.width/2, 30); this.addChild(loading); CCAction animate = CommonUtils.getAnimate("image/loading/loading_%02d.png", 9, false); loading.runAction(animate); start = CCSprite.sprite("image/loading/loading_start.png"); start.setPosition(winSize.width/2, 30); start.setVisible(false);// 暫時不可見 this.addChild(start); } ~~~ 當然我們可以來看一下這個工具類,這在之后的開發中有很多的實用價值: ~~~ `public class CommonUtils { /** * 切換圖層 * @param newLayer 新進入的圖層 */ public static void changeLayer(CCLayer newLayer){ CCScene scene=CCScene.node(); scene.addChild(newLayer); CCFlipXTransition transition=CCFlipXTransition.transition(2, scene, 0); CCDirector.sharedDirector().replaceScene(transition);//切換場景 ,參數 新的場景 } /** * 解析地圖上 對象的所有點 * @param map 地圖 * @param name 對象的名字 * @return */ public static List<CGPoint> getMapPoints(CCTMXTiledMap map,String name){ List<CGPoint> points = new ArrayList<CGPoint>(); // 解析地圖 CCTMXObjectGroup objectGroupNamed = map.objectGroupNamed(name); ArrayList<HashMap<String, String>> objects = objectGroupNamed.objects; for (HashMap<String, String> hashMap : objects) { int x = Integer.parseInt(hashMap.get("x")); int y = Integer.parseInt(hashMap.get("y")); CGPoint cgPoint = CCNode.ccp(x, y); points.add(cgPoint); } return points; } /** * 創建了序列幀的動作 * @param format 格式化的路徑 * @param num 幀數 * @param isForerver 是否永不停止的循環 * @return */ public static CCAction getAnimate(String format,int num,boolean isForerver){ ArrayList<CCSpriteFrame> frames=new ArrayList<CCSpriteFrame>(); //String format="image/loading/loading_%02d.png"; for(int i=1;i<=num;i++){ CCSpriteFrame spriteFrame = CCSprite.sprite(String.format(format, i)).displayedFrame(); frames.add(spriteFrame); } CCAnimation anim=CCAnimation.animation("", 0.2f, frames); // 序列幀一般必須永不停止的播放 不需要永不停止播放,需要指定第二個參數 false if(isForerver){ CCAnimate animate=CCAnimate.action(anim); CCRepeatForever forever=CCRepeatForever.action(animate); return forever; }else{ CCAnimate animate=CCAnimate.action(anim,false); return animate; } } }` ~~~ 至于其他小的細節我就不一一啰嗦了,只說一下僵尸和植物對戰需要的幾個關鍵代碼: ~~~ /** * 處理游戲開始后的操作 * * */ public class GameCotroller { private GameCotroller() { } private static GameCotroller cotroller = new GameCotroller(); public static GameCotroller getInstance() { return cotroller; } public static boolean isStart; // 游戲是否開始 private CCTMXTiledMap map; private List<ShowPlant> selectPlants; private static List<FightLine> lines; // 管理了五行 private List<CGPoint> roadPoints; static { lines = new ArrayList<FightLine>(); for (int i = 0; i < 5; i++) { FightLine fightLine = new FightLine(i); lines.add(fightLine); } } /** * 開始游戲 * * @param map * 游戲的地圖 * @param selectPlants * 玩家已選植物的集合 */ public void startGame(CCTMXTiledMap map, List<ShowPlant> selectPlants) { isStart = true; this.map = map; this.selectPlants = selectPlants; loadMap(); // 添加僵尸 // 定時器 // 參數1 方法名(方法帶float類型的參數) 參數2 調用方法的對象 參數3 間隔時間 參數4 是否暫停 CCScheduler.sharedScheduler().schedule("addZombies", this, 1,false); // CCCallFunc.action(target, selector) // addZombies(); // 安放植物 // 僵尸攻擊植物 // 植物攻擊僵尸 progress(); } CGPoint[][] towers = new CGPoint[5][9]; private void loadMap() { roadPoints = CommonUtils.getMapPoints(map, "road"); for (int i = 1; i <= 5; i++) { List<CGPoint> mapPoints = CommonUtils.getMapPoints(map, String.format("tower%02d", i)); for (int j = 0; j < mapPoints.size(); j++) { towers[i - 1][j] = mapPoints.get(j); } } } /*** * 添加僵尸 * * @param t */ public void addZombies(float t) { Random random = new Random(); int lineNum = random.nextInt(5);// [0-5) PrimaryZombies primaryZombies = new PrimaryZombies( roadPoints.get(lineNum * 2), roadPoints.get(lineNum * 2 + 1)); map.addChild(primaryZombies,1);// 讓僵尸一直在植物的上面 lines.get(lineNum).addZombies(primaryZombies);// 把僵尸記錄到行戰場中 progress+=5; progressTimer.setPercentage(progress);//設置新的進度 } public void endGame() { isStart = false; } private ShowPlant selectPlant; // 玩家選擇的植物 private Plant installPlant; /** * 當游戲開始后處理點擊事件的方法 * * @param point * 點擊到的點 */ public void handleTouch(CGPoint point) { CCSprite chose = (CCSprite) map.getParent().getChildByTag( FightLayer.TAG_CHOSE); if (CGRect.containsPoint(chose.getBoundingBox(), point)) { // 認為玩家有可能選擇了植物 if (selectPlant != null) { selectPlant.getShowSprite().setOpacity(255); selectPlant = null; } for (ShowPlant plant : selectPlants) { CGRect boundingBox = plant.getShowSprite().getBoundingBox(); if (CGRect.containsPoint(boundingBox, point)) { // 玩家選擇了植物 selectPlant = plant; selectPlant.getShowSprite().setOpacity(150); int id = selectPlant.getId(); switch (id) { case 1: installPlant =new PeasePlant(); break; case 4: installPlant = new Nut(); break; default: break; } } } } else { // 玩家有可能安放植物 if (selectPlant != null) { int row = (int) (point.x / 46) - 1; // 1-9 0-8 int line = (int) ((CCDirector.sharedDirector().getWinSize().height - point.y) / 54) - 1;// 1-5 // 0-4 // 限制安放的植物的范圍 if (row >= 0 && row <= 8 && line >= 0 && line <= 4) { // 安放植物 // selectPlant.getShowSprite().setPosition(point); // installPlant.setPosition(point); // 坐標需要修改 installPlant.setLine(line);// 設置植物的行號 installPlant.setRow(row); // 設置植物的列號 installPlant.setPosition(towers[line][row]); // 修正了植物的坐標 FightLine fightLine = lines.get(line); if (!fightLine.containsRow(row)) { // 判斷當前列是否已經添加了植物 如果添加了 就不能再添加了 fightLine.addPlant(installPlant);// 把植物記錄到了行戰場中 map.addChild(installPlant); } } installPlant = null; selectPlant.getShowSprite().setOpacity(255); selectPlant = null;// 下次安裝需要重新選擇 } } } CCProgressTimer progressTimer; int progress=0; private void progress() { // 創建了進度條 progressTimer = CCProgressTimer.progressWithFile("image/fight/progress.png"); // 設置進度條的位置 progressTimer.setPosition(CCDirector.sharedDirector().getWinSize().width - 80, 13); map.getParent().addChild(progressTimer); //圖層添加了進度條 progressTimer.setScale(0.6f); // 設置了縮放 progressTimer.setPercentage(0);// 每增加一個僵尸需要調整進度,增加5 progressTimer.setType(CCProgressTimer.kCCProgressTimerTypeHorizontalBarRL); // 進度的樣式 CCSprite sprite = CCSprite.sprite("image/fight/flagmeter.png"); sprite.setPosition(CCDirector.sharedDirector().getWinSize().width - 80, 13); map.getParent().addChild(sprite); sprite.setScale(0.6f); CCSprite name = CCSprite.sprite("image/fight/FlagMeterLevelProgress.png"); name.setPosition(CCDirector.sharedDirector().getWinSize().width - 80, 5); map.getParent().addChild(name); name.setScale(0.6f); } } ~~~ 還有一個很關鍵的就是: ~~~ /** * 對戰界面的圖層 * */ public class FightLayer extends BaseLayer { public static final int TAG_CHOSE = 10; private CCTMXTiledMap map; private List<CGPoint> zombilesPoints; private CCSprite choose; // 玩家可選植物的容器 private CCSprite chose; // 玩家已選植物的容器 public FightLayer() { init(); } private void init() { loadMap(); parserMap(); showZombies(); moveMap(); } // 加載展示用的僵尸 private void showZombies() { for (int i = 0; i < zombilesPoints.size(); i++) { CGPoint cgPoint = zombilesPoints.get(i); ShowZombies showZombies = new ShowZombies(); showZombies.setPosition(cgPoint);// 給展示用的僵尸設置了位置 map.addChild(showZombies);// 注意: 把僵尸加載到地圖上 } } private void parserMap() { zombilesPoints = CommonUtils.getMapPoints(map, "zombies"); } // 移動地圖 private void moveMap() { int x = (int) (winSize.width - map.getContentSize().width); CCMoveBy moveBy = CCMoveBy.action(3, ccp(x, 0)); CCSequence sequence = CCSequence .actions(CCDelayTime.action(4), moveBy, CCDelayTime.action(2), CCCallFunc.action(this, "loadContainer")); map.runAction(sequence); } private void loadMap() { map = CCTMXTiledMap.tiledMap("image/fight/map_day.tmx"); map.setAnchorPoint(0.5f, 0.5f); CGSize contentSize = map.getContentSize(); map.setPosition(contentSize.width / 2, contentSize.height / 2); this.addChild(map); } // 加載兩個容器 public void loadContainer() { chose = CCSprite.sprite("image/fight/chose/fight_chose.png"); chose.setAnchorPoint(0, 1); chose.setPosition(0, winSize.height);// 設置位置是屏幕的左上角 this.addChild(chose,0,TAG_CHOSE); choose = CCSprite.sprite("image/fight/chose/fight_choose.png"); choose.setAnchorPoint(0, 0); this.addChild(choose); loadShowPlant(); start = CCSprite.sprite("image/fight/chose/fight_start.png"); start.setPosition(choose.getContentSize().width/2, 30); choose.addChild(start); } private List<ShowPlant> showPlatns; // 展示用的植物的集合 // 加載展示用的植物 private void loadShowPlant() { showPlatns = new ArrayList<ShowPlant>(); for (int i = 1; i <= 9; i++) { ShowPlant plant = new ShowPlant(i); // 創建了展示的植物 CCSprite bgSprite = plant.getBgSprite(); bgSprite.setPosition(16 + ((i - 1) % 4) * 54, 175 - ((i - 1) / 4) * 59); choose.addChild(bgSprite); CCSprite showSprite = plant.getShowSprite();// 獲取到了展示的精靈 // 設置坐標 showSprite.setPosition(16 + ((i - 1) % 4) * 54, 175 - ((i - 1) / 4) * 59); choose.addChild(showSprite); // 添加到了容器上 showPlatns.add(plant); } setIsTouchEnabled(true); } public void unlock(){ isLock=false; } private List<ShowPlant> selectPlants = new CopyOnWriteArrayList<ShowPlant>();// 已經選中植物的集合 boolean isLock; boolean isDel; // 是否刪除了選中的植物 private CCSprite start; @Override public boolean ccTouchesBegan(MotionEvent event) { // 需要把Android坐標系中的點 轉換成Cocos2d坐標系中的點 CGPoint point = this.convertTouchToNodeSpace(event); if(GameCotroller.isStart){// 如果游戲開始了 交給GameCtoller 處理 GameCotroller.getInstance().handleTouch(point); return super.ccTouchesBegan(event); } CGRect boundingBox = choose.getBoundingBox(); CGRect choseBox = chose.getBoundingBox(); // 玩家有可能反選植物 if(CGRect.containsPoint(choseBox, point)){ isDel=false; for(ShowPlant plant:selectPlants){ CGRect selectPlantBox = plant.getShowSprite().getBoundingBox(); if(CGRect.containsPoint(selectPlantBox, point)){ CCMoveTo moveTo=CCMoveTo.action(0.5f, plant.getBgSprite().getPosition()); plant.getShowSprite().runAction(moveTo); selectPlants.remove(plant);// 走到這一步 確實代表反選植物了 isDel=true; continue;// 跳出本次循環,繼續下次循環 } if(isDel){ CCMoveBy ccMoveBy=CCMoveBy.action(0.5f, ccp(-53, 0)); plant.getShowSprite().runAction(ccMoveBy); } } }else if (CGRect.containsPoint(boundingBox, point)) { if(CGRect.containsPoint(start.getBoundingBox(), point)){ // 點擊了一起來搖滾 ready(); }else if (selectPlants.size() < 5&&!isLock) { //如果已經選擇滿了 就不能再選擇了 // 有可能 選擇植物 for (ShowPlant plant : showPlatns) { CGRect boundingBox2 = plant.getShowSprite() .getBoundingBox(); if (CGRect.containsPoint(boundingBox2, point)) {// 如果點恰好落在植物展示的精靈矩形之中 // 當前植物被選中了 isLock=true; // System.out.println("我被選中了..."); CCMoveTo moveTo = CCMoveTo.action( 0.5f, ccp(75 + selectPlants.size() * 53, 255)); CCSequence sequence=CCSequence.actions(moveTo, CCCallFunc.action(this, "unlock")); plant.getShowSprite().runAction(sequence); selectPlants.add(plant); } } } } return super.ccTouchesBegan(event); } /** * 點擊了一起來搖滾 做的操作 */ private void ready() { // 縮小玩家已選植物容器 chose.setScale(0.65f); // 把選中的植物重新添加到 存在的容器上 for(ShowPlant plant:selectPlants){ plant.getShowSprite().setScale(0.65f);// 因為父容器縮小了 孩子一起縮小 plant.getShowSprite().setPosition( plant.getShowSprite().getPosition().x * 0.65f, plant.getShowSprite().getPosition().y + (CCDirector.sharedDirector().getWinSize().height - plant .getShowSprite().getPosition().y) * 0.35f);// 設置坐標 this.addChild(plant.getShowSprite()); } choose.removeSelf();// 回收容器 // 地圖的平移 int x = (int) (map.getContentSize().width-winSize.width); CCMoveBy moveBy = CCMoveBy.action(1, ccp(x, 0)); CCSequence sequence=CCSequence.actions(moveBy, CCCallFunc.action(this, "preGame")); map.runAction(sequence); } private CCSprite ready; public void preGame(){ ready=CCSprite.sprite("image/fight/startready_01.png"); ready.setPosition(winSize.width/2, winSize.height/2); this.addChild(ready); String format="image/fight/startready_%02d.png"; CCAction animate = CommonUtils.getAnimate(format, 3, false); CCSequence sequence=CCSequence.actions((CCAnimate)animate, CCCallFunc.action(this, "startGame")); ready.runAction(sequence); } public void startGame(){ ready.removeSelf();// 移除中間的序列幀 GameCotroller cotroller=GameCotroller.getInstance(); cotroller.startGame(map,selectPlants); } } ~~~ ![這里寫圖片描述](https://box.kancloud.cn/2016-03-14_56e65d6ca156f.jpg "") 在做這個的過程中總是遇到空指針的異常,例如這次:后來發現是因為我ShowPlant.java這個地方寫錯了 ![這里寫圖片描述](https://box.kancloud.cn/2016-03-14_56e65d6d1115d.jpg "") 做媒一個項目都需要一些成長和一些經驗,在之前的CCSequence,CGPoint,CCSprite,CCTMXTiledMap 后面又學會了CCScheduler.sharedScheduler().schedule(“attackPlant”, this, 0.5f, false),ready.removeSelf();// 移除中間的序列幀等內容,讓我對這整個架構有了初步了了解了實踐,學習之路很長,我們一起加油!
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看