Cocos2d-x《雷電大戰》(5)-單例模式英雄飛機閃亮登場!,cocos2d飛機大戰
林炳文Evankaka原創作品。轉載請註明出處http://blog.csdn.net/evankaka
本文將實現用單例模式實現一個英雄飛機類的設計,單例模式是遊戲開發中最常用到的一種設計模式,原理也比較簡單,仔細研究下就可以掌握好。
來看看效果:
英雄飛機一建立就閃爍3秒 英雄飛機建立後帶有噴火的小尾巴動畫
Cocos2d-x版本:3.4
工程環境:VS30213
一、單例模式解析
單例模式也稱為單件模式、單子模式,可能是使用最廣泛的設計模式。其意圖是保證一個類僅有一個執行個體,並提供一個訪問它的全域訪問點,該執行個體被所有程式模組共用。有很多地方需要這樣的功能模組,如系統的日誌輸出,GUI應用必須是單滑鼠,MODEM的聯結需要一條且只需要一條電話線,作業系統只能有一個視窗管理器,一台PC連一個鍵盤。
單例的一般實現比較簡單,下面是代碼和UML圖。由於建構函式是私人的,因此無法通過建構函式執行個體化,唯一的方法就是通過調用靜態函數GetInstance。
UML圖:
代碼實現
1: //Singleton.h
2: class Singleton
3: {
4: public:
5: static Singleton* GetInstance();
6: private:
7: Singleton() {}
8: static Singleton *singleton;
9: };
10: //Singleton.cpp
11: Singleton* Singleton::singleton = NULL;
12: Singleton* Singleton::GetInstance()
13: {
14: if(singleton == NULL)
15: singleton = new Singleton();
16: return singleton;
17: }
特點:
1. 類的建構函式外界不可訪問.
2. 提供了建立對象的介面.
二、單例模式優缺點
單例模式非常好實現,直接就可以在靜態區初始化instance,然後通過getInstance返回,這種就被稱為餓漢式單例類。也有些寫法是在getInstance中new instance然後返回,這種就被稱為懶漢式單例類,但這涉及到第一次getInstance的一個判斷問題。
優點
1.減少了時間和空間的開銷(new執行個體的開銷)。
2.提高了封裝性,使得外部不易改動執行個體。
缺點
1.懶漢式是以時間換空間的方式。
2.餓漢式是以空間換時間的方式。
三、Cocos2d-x中設計單例模式的英雄飛機
這裡我實現了一個單例模式的英雄飛機類,它還帶了觸摸跟隨手指移動的功能,其實就是把Cocos2d-x《雷電大戰》(2)-精靈隨手指移動,你點哪我走哪! 這裡的代碼都整合在一起。這樣就比較合理,這個英雄飛機類還包含有分數值、血量、攻擊值、子彈類型等。這裡只是一個粗略實現,後續的功能有可以還會有改動。而且飛機還帶有噴火的功能,更加的逼真!這樣子代碼結構看起來就比較明了,而不會全放在GameMain.cpp中。然後需要建立時直接在GameMain.cpp來調用就行了。
下面來看看代碼:
標頭檔HeroPlane.h
/***功能 單例英雄飛機類*作者 林炳文(ling20081005@126.com 部落格:http://blog.csdn.net/evankaka)*時間 2015.4.6*/#pragma once#ifndef __HeroPlane_H__#define __HeroPlane_H__#include "cocos2d.h"USING_NS_CC;class HeroPlane :public cocos2d::Layer{private:HeroPlane();public:/***獲得單例英雄飛機的方法*@return 英雄飛機類*/static HeroPlane* getInstance();virtual bool init();/***取得當前英雄飛機中的精靈*@return 飛機中精靈,實際的操作對像*/Sprite* getPlane(); /***底下四個分別為觸摸按下時的事件*/virtual bool onTouchBegan(cocos2d::Touch *touch, cocos2d::Event *unused_event);virtual void onTouchMoved(cocos2d::Touch *touch, cocos2d::Event *unused_event);virtual void onTouchEened(cocos2d::Touch *touch, cocos2d::Event *unused_event);virtual void onTouchCancelled(cocos2d::Touch *touch, cocos2d::Event *unused_even);public:unsigned int planeHp;//英雄飛機生命值unsigned int planeScore;//英雄飛機分數值unsigned int planeBulletNum;//英雄飛機子彈類型 unsigned int planeAttack;//英雄飛機攻擊值 unsigned int planeDefend;//英雄飛機保護值private:static HeroPlane* sharePlane;//英雄飛機靜態變數bool isHeroPlaneControl;//飛機是否被控制著float mDeltaX;//英雄飛機隨手指移動時的X位移量float mDeltaY;//英雄飛機隨手指移動時的Y位移量Sprite* plane;//英雄飛機};#endif
英雄飛機實作類別HeroPlane.cpp
/***功能 單例英雄飛機類*作者 林炳文(ling20081005@126.com 部落格:http://blog.csdn.net/evankaka)*時間 2015.4.6*/#include"HeroPlane.h"USING_NS_CC;HeroPlane* HeroPlane::sharePlane = NULL;//注意,靜態變數的寫法!HeroPlane::HeroPlane(){plane = NULL;planeHp=10000;//英雄飛機生命值planeScore=0;//英雄飛機分數值planeBulletNum=1;//英雄飛機子彈類型,預設初始化為第一種isHeroPlaneControl = false; planeAttack=100;//英雄飛機攻擊值 planeDefend=100;//英雄飛機保護值}//取得英雄飛機的方法,只能通過這個方法HeroPlane* HeroPlane::getInstance(){if (NULL == sharePlane){sharePlane = new HeroPlane();sharePlane->init();sharePlane->autorelease();}return sharePlane;}bool HeroPlane::init(){Size visibleSize = Director::getInstance()->getVisibleSize();Point origin = Director::getInstance()->getVisibleOrigin();SpriteFrameCache *frameCache = SpriteFrameCache::getInstance();frameCache->addSpriteFramesWithFile("heroplane.plist", "heroplane.png");//載入全域資源plane = Sprite::createWithSpriteFrameName("plane1.png");//產生飛機plane->setPosition(Vec2(visibleSize.width / 2, visibleSize.height / 5));this->addChild(plane, 0, 1);Blink *blink = Blink::create(3,8);//閃爍動畫Animation* animation = Animation::create();animation->setDelayPerUnit(0.1f);animation->addSpriteFrame(frameCache->getSpriteFrameByName("plane1.png"));animation->addSpriteFrame(frameCache->getSpriteFrameByName("plane2.png"));Animate* animate = Animate::create(animation);//幀動畫plane->runAction(blink);//執行閃爍動畫plane->runAction(RepeatForever::create(animate));// 執行幀動畫//開啟觸摸事件,讓飛機跟隨手指移動auto listen = EventListenerTouchOneByOne::create();listen->onTouchBegan = CC_CALLBACK_2(HeroPlane::onTouchBegan, this);listen->onTouchMoved = CC_CALLBACK_2(HeroPlane::onTouchMoved, this);listen->onTouchEnded = CC_CALLBACK_2(HeroPlane::onTouchEened, this);listen->onTouchCancelled = CC_CALLBACK_2(HeroPlane::onTouchCancelled, this);listen->setSwallowTouches(false);Director::getInstance()->getEventDispatcher()->addEventListenerWithSceneGraphPriority(listen, this);return true;}Sprite* HeroPlane::getPlane(){if (NULL == plane)return NULL;return plane;}bool HeroPlane::onTouchBegan(cocos2d::Touch *touch, cocos2d::Event *unused_event){Point mHeroPos = plane->getPosition();Point mBeganPos = touch->getLocationInView();mBeganPos = Director::getInstance()->convertToGL(mBeganPos);//判斷當前手指按下地區是否是英雄飛機的地區,並且計算飛機要移動時的位移量if (mBeganPos.x > mHeroPos.x - plane->getContentSize().width / 2 && mBeganPos.x<mHeroPos.x + plane->getContentSize().width / 2 &&mBeganPos.y>mHeroPos.y - plane->getContentSize().height / 2 && mBeganPos.y < mHeroPos.y + plane->getContentSize().height / 2){isHeroPlaneControl = true;//計算位移量mDeltaX = mBeganPos.x - mHeroPos.x;mDeltaY = mBeganPos.y - mHeroPos.y;}return true;}void HeroPlane::onTouchMoved(cocos2d::Touch *touch, cocos2d::Event *unused_event){if (isHeroPlaneControl){Point mMovedPos = touch->getLocationInView();mMovedPos = Director::getInstance()->convertToGL(mMovedPos);Size visibleSize = Director::getInstance()->getVisibleSize();Point origin = Director::getInstance()->getVisibleOrigin();float x = mMovedPos.x - mDeltaX;//記得減去位移量float y = mMovedPos.y - mDeltaY;if (x <= plane->getContentSize().width / 2 + origin.x)//x到達螢幕左邊界x = plane->getContentSize().width / 2 + origin.x;else if (x >= visibleSize.width - plane->getContentSize().width / 2)//x到達螢幕右邊界x = visibleSize.width - plane->getContentSize().width / 2;if (y <= plane->getContentSize().height / 2 + origin.y)//y到達螢幕下邊界y = plane->getContentSize().height / 2 + origin.y;else if (y >= visibleSize.height - plane->getContentSize().height / 2)//x到達螢幕上邊界y = visibleSize.height - plane->getContentSize().height / 2;//飛機跟隨手指移動plane->setPosition(Vec2(x, y));}}void HeroPlane::onTouchEened(cocos2d::Touch *touch, cocos2d::Event *unused_event){isHeroPlaneControl = false;}void HeroPlane::onTouchCancelled(cocos2d::Touch *touch, cocos2d::Event *unused_even){isHeroPlaneControl = false;}
這裡的英雄飛機第一次擷取時,會閃爍幾下。並且帶有噴火的小尾巴(其實就是不斷的重複切換兩張圖片實現的,看上面的幀動畫)
使用方法:
1: HeroPlane *heroPlane = HeroPlane::getInstance();
2: this->addChild(heroPlane);
每次要取得當前的英雄飛機類,用HeroPlane::getInstance()即可,也就是說每次返回都是同一個執行個體,所以你就可以儲存英雄的分數、血量、攻擊值到一個外部的檔案中,然後遊戲每次啟動時,從這個檔案讀取資料就可以,就可以接著上次的英雄飛機設定的參數了。這些功能我打算留在後頭再來實現。
英雄飛機一建立就閃爍3秒 英雄飛機建立後帶有噴火的小尾巴動畫
林炳文Evankaka原創作品。轉載請註明出處http://blog.csdn.net/evankaka