[cocos2d-x 3.6] 포코팡류 게임 만들기~! (2) 게임볼 배치, 클릭 이벤트

     





이번 포스팅에서는 간단한 스프라이트 배치입니다.


지난 포스팅에서 배경화면만 뿌렸었는데, 이번에는 게임에 실질적으로 사용되는 동그라미(편의상 볼로 부르겠습니다.)를 화면에 배치하고, 적으로 사용되는 그림 하나를 상단에 띄우고 애니메이션 효과를 주겠습니다.


일단 화면에 볼을 배치하기 위해 GameBall이라는 스프라이트 객체를 만듭니다.


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
//
//  GameBall.cpp
//  mingpang
//
//  Created by Cho on 2015. 6. 9..
//
//
 
#include "GameBall.h"
 
GameBall::~GameBall()
{
}
 
GameBall::GameBall()
:   _type(0),
_state(GameBall::LIVE)
{
}
 
GameBall* GameBall::spriteWithFile(std::string pszFileName)
{
    GameBall* sprite = new GameBall();
    if(sprite && sprite->initWithFile(pszFileName)) {
        sprite->autorelease();
        return sprite;
    }
    CC_SAFE_DELETE(sprite);
    return NULL;
}
 
Point GameBall::getBallPoint()
{
    Point p = this->getPosition();
    return p;
}
 
 
 
cs

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
 
//
//  GameBall.h
//  mingpang
//
//  Created by Cho on 2015. 6. 9..
//
//
 
#ifndef __mingpang__GameBall__
#define __mingpang__GameBall__
 
#include "cocos2d.h"
 
using namespace cocos2d;
 
class GameBall : public cocos2d::Sprite
{
private:
public:
    enum gameState {
            LIVE,
            DEAD,
            SELECT,
        };
    CC_SYNTHESIZE(int, _type, Type);
    CC_SYNTHESIZE(int, _state, State);
    
    Point getBallPoint();
    
    static GameBall* spriteWithFile(std::string pszFileName);
 
    GameBall();
    ~GameBall();
};
 
#endif /* defined(__mingpang__GameBall__) */
 
 
 
cs

현재 만든 GameBall 객체는 볼의 상태를 나타내는 gameState와 볼의 정 중앙 위치를 나타내는 getBallPoint(), 볼의 그림을 결정하는 spriteWithFile 메소드가 있습니다. 

gameState는 LIVE와 DEAD, SELECT로 구분했는데, 아직은 3가지 상태만 정의했습니다.(레퍼런스에 그렇게 되어 있어서...) CC_SYNTHESIZE는 특정 변수에 대한 get, set메소드를 자동으로 만들어주는 매크로입니다. 


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
void HelloWorld::initBall()
{
    //auto sprite=Sprite::create();
    
    
    int ballXPos = 0;
    int ballYPos = 0;
    int diffX = 104;
    int diffY = 120;
    int initBallXPos = 72;
    int initBallYPos = 778;
    
    //auto _gameBatchNode = this->getChildByTag(BATCH_TAG);
    GameBall* gameBall;
    
    ballPoolIndex =0;
    
    for(int xIndex = 0; xIndex<BOARDY; xIndex++ ){
        ballXPos = initBallXPos + (xIndex * diffX);
        ballYPos = initBallYPos;
        
        if(xIndex % 2 ==0)
            ballYPos -= diffY/2;
        
        for (int yIndex =0; yIndex < BOARDX; yIndex++) {
            
            //sprite = Sprite::create("ming_01.png");
            //sprite->setPosition(Point(ballXPos,ballYPos));
            gameBall = createGameBall(Point(ballXPos, ballYPos), rand()%TOTALBALLTYPE +1,GameBall::LIVE);
            //_gameBatchNode->addChild(gameBall);
            
            balls.pushBack(gameBall);
            
            ballYPos -= diffY;
        }
        
    }
}
 
 
 
 
cs


gameBall을 화면에 뿌리는 코드입니다. 기본적인 좌표값을 바탕으로 왼쪽 위부터 오른쪽 아래까지 차례대로 gameBall객체를 생성합니다. 2.x버전에서는 array를 사용했지만 3.x버전에서는 벡터를 사용해 여러 객체를 쉽게 다룰 수 있습니다.


헤더에서 Vector<GameBall*> balls를 선언해주시면 GameBall 객체들을 저장할 수 있는 balls 벡터가 생성됩니다. balls벡터에 객체를 넣을때는 pushBack메소드를 사용해서 하나하나 넣을 수 있습니다. 이렇게 푸쉬하는 과정에서 나중에 원하는 객체를 찾을때는 어떻게 하지? 라는 고민이 생길 수 있습니다. 대부분은 for문을 돌려서 벡터내에 모든 객체를 조사하는 방법으로 진행합니다. 




볼을 배치한 다음에는 클릭했을 때 이벤트를 만듭니다. 포코팡의 경우 멀티터치를 사용하지 않기 때문에 OneByOne으로 터치리스너를 등록합니다.


1
2
3
4
5
6
7
    auto listener = EventListenerTouchOneByOne::create();
    listener->setSwallowTouches(true);
    listener->onTouchBegan = CC_CALLBACK_2(HelloWorld::onTouchesBegan, this);
    listener->onTouchMoved = CC_CALLBACK_2(HelloWorld::onTouchesMoved, this);
    listener->onTouchEnded = CC_CALLBACK_2(HelloWorld::onTouchesEnded, this);
    listener->onTouchCancelled = CC_CALLBACK_2(HelloWorld::onTouchesCancelled, this);
    Director::getInstance()->getEventDispatcher()->addEventListenerWithFixedPriority(listener, 1);

cs



자 이제 터치가 되는 화면을 만들었습니다. 터치가 잘 되는지 확인해보기 위해 터치했을 때 볼이 없어지고 다시 나타나는 샘플을 만들어 보도록 하겠습니다. onTouchBegan에 콜백함수를 onTouchesBegan으로 지정했기 때문에 해당 메소드에 기능을 추가해보도록 합시다.


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
 
bool HelloWorld::onTouchesBegan(Touch* touch, Event* event)
{
    Point touchLocation = touch->getLocation();
    Point ballLocation;
    CCLOG("%f,%f",touchLocation.x,touchLocation.y);
    
    for(GameBall*ball:balls)
    {
        
        if(ball->getBoundingBox().containsPoint(touchLocation)){
            
            currentGameBall = ball;
            
            if(ball->isVisible()==true && ball->getState() == GameBall::LIVE){
                ball->setState(GameBall::DEAD);
                ball->setVisible(false);
            }
            else
            {
                ball->setState(GameBall::LIVE);
                ball->setVisible(true);
                
            }
            
            ballLocation = ball->getBallPoint();
            CCLOG("볼위치 %f,%f",ballLocation.x,ballLocation.y);
        }
    }
    
    return -1;
}
 
cs

방법은 간단합니다. 터치한 포인트와 볼 벡터에 있는 볼들의 위치를 하나하나 비교해서 겹치는 부분의 볼의 상태를 안 보이게 바꾸면 됩니다. 상태를 DEAD와 LIVE로 바꿔주기는 하지만 특별한 기능은 없습니다. 기분만 낸 거에요 ~ ㅎㅎ

나중에 바로 옆에 있는 볼을 판단하기 위해서 볼의 중앙 위치를 반환하는 getBallPoint도 한번 써봤습니다. 다음포스팅에서는 드래그했을 때 근처에 있는 볼을 판단하는 기능을 넣어보겠습니다.


반응형

댓글

Designed by JB FACTORY