Cocos2dx learning ----- do not step on the white block V1.0

Source: Internet
Author: User
Tags getcolor

After learning cocos2dx, I have always felt that it is not very interesting. So I am looking for a tutorial to make a small game. Anyway, there is nothing to do at school on the national day and I am happy to myself.

PS; my version is cocos2dx3.2

1. Create a project

Cocos New-P com. donttouchwhiteblock. xuran-l CPP-D.


Ii. Create a block class

Because do not guess that the most important element in the white block is the "Block", so we need to create a class for this element, and then instantiate some methods to complete many behaviors in the game.

First, gameblock. h file

#pragma once#include <iostream>#include <cocos2d.h>USING_NS_CC; class Block:public Sprite{public:static GameBlock* CreateWithArgs(Color3B color, Size size, std::string label, float fontsize, Color3B textcolor);virtual bool initWithArgs(Color3B color, Size size, std::string label, float fontsize, Color3B textcolor);void removeblock();private:static Vector<GameBlock*> *blocks;};

The header file defines three member functions:

The first is to create a block based on the obtained parameters.

The second is to initialize a new block based on parameters.

The third is to remove a block.

An array of the block pointer type is created to store the block object we created.

The second is the gameblock. cpp file.


# Include "gameblock. H "vector <gameblock *> * gameblock: blocks = new vector <gameblock *> (); gameblock * gameblock: createwithargs (color3b color, size, STD :: string label, float fontsize, color3b textcolor) {auto B = new gameblock (); B-> initwithargs (color, size, label, fontsize, textcolor ); b-> autorelease (); blocks-> pushback (B); return B;} void gameblock: removeblock () {removefromparent (); blocks-> eraseobject (this ); // delete a specific object in the vector} bool gameblock: initwithargs (color3b color, size, STD: String label, float fontsize, color3b textcolor) {sprite :: init (); setcontentsize (size); setanchorpoint (point: zero); settexturerect (rect (0, 0, size. width, size. height); setcolor (color); Auto L = label: Create (); L-> setstring (Label); L-> setsystemfontsize (fontsize ); l-> setcolor (textcolor); addchild (l); L-> setposition (size. width/2, size. height/2); Return true ;}

The block array is initialized. A block initialization function includes various parameter settings, a creation function, and a release and deletion function.


3. Add the Start entry

After the corresponding classes and methods of the block are created, we will start to do it step by step. First, do not step on the white block game. At the beginning, a yellow part represents the starting point. First, add this yellow starting block for our game.


It is easy to add a new function named addstartline from the helloworldscene file. The function implementation is very simple. You can create a block through the createwithargs function and add it in.


bool HelloWorld::init(){    //////////////////////////////    // 1. super init first    if ( !Layer::init() )    {        return false;    }    visibleSize = Director::getInstance()->getVisibleSize();AddStartLine();    return true;}void HelloWorld::AddStartLine(){auto b = GameBlock::CreateWithArgs(Color3B::YELLOW, Size(visibleSize.width, visibleSize.height/8), "Start", 20, Color3B::BLACK);addChild(b);}
Since the start entry is added in this way, the end entry should also be the same, and I will not introduce it again.
After adding a normal black/white block.


4. Add black and white blocks


First, we need to add a method for adding black and white blocks to the class called addnormal.

We usually play games that do not step on the white block version. Generally, there are four blocks in a row. The black key is randomly displayed in one of the four blocks, and the rest are white blocks.

Since it is random, we naturally need to use random numbers.

The rand function is used to generate a random number between 0 and 4 to determine the position of the Black Block.

We need to have such a concept that the program is now facing a white canvas, we need to follow the order of the rows, in the order of columns, the white blocks and black blocks of each row are painted in sequence.

First, we need to create a block to determine whether to create a black block or a white block based on the preceding random number.

void HelloWorld::AddNormal(int lineindex){int blackindex = rand()%4;GameBlock *b;for(int i = 0; i < 4; i++){auto b = GameBlock::CreateWithArgs(blackindex == i?Color3B::BLACK:Color3B::WHITE, Size(visibleSize.width/4-1, visibleSize.height/4-1), "", 20, Color3B::BLACK);addChild(b);b->setPosition(i*visibleSize.width/4, lineindex*visibleSize.height/4);b->setlineindex(lineindex);}}

There are four blocks in each row. We set them in one row and one row. The input parameter indicates the number of rows.

Set a for loop to set four keys in a row.

First, create a block. Because a random number of blackindex is generated above, the position of the Black Block is specified accordingly. After adding the black block to the scene, you must set the exact position of the Black Block.

First, we need to divide our screen width into four parts, which are determined by I. I is used to multiply the width of each part of the X coordinate, the vertical coordinates are of course the black and white blocks of the first line. Therefore, we need to set the first line to decide the input.

void HelloWorld::StartGame(){AddStartLine();AddNormal(1);AddNormal(2);AddNormal(3);}

Finally, we directly add a function to start the game, which calls the method to add these blocks, and runs this function in the init function to see the effect.


5. event interaction

Event interaction is actually when you click on a game or a transaction on the screen, the transaction should give some feedback.

There is only one time interaction in the white block, that is, if you click black, the game continues. If you click white block, the game ends. That's it.

Let's take the first behavior as an example. First, if we want to respond to some operations, we need a listener to listen for the action, you can choose to monitor whether a control is operated or whether the entire scenario is operated.


First, we need to create a listener for touch events.

Auto listener = eventlistenertouchonebyone: Create ();

If the listener receives the touch signal, it must respond to the touch action and call a function to perform the response operation.

Listener-> ontouchbegan = [this] (touch * t, event * E) {log ("xuran is winner"); gameblock * B; Auto BS = gameblock :: getblocks (); For (Auto it = BS-> begin (); it! = BS-> end (); It ++) {B = * it; if (B-> getlineindex () = 1 & B-> getboundingbox (). containspoint (t-> getlocation () {If (B-> getcolor () = color3b: Black) {B-> setcolor (color3b: Gray ); this-> movedown ();} else {MessageBox ("game failed", "gameover") ;}} return false ;};

So a closure function is used here.

There are some new functions in this closure function, such as getblocks. This function is defined in the gameblock class. Its function is to return the vector of the storage block, because if I create the first layer, the first layer will certainly create four blocks, one of the Black Blocks and three white blocks will all have a lineindex attribute, which indicates the row where they are, and these blocks will also be added to this array, therefore, during interaction, you must determine whether the white block is touched or the Black Block is touched. Therefore, you must use the iterator traversal to confirm.

listener->onTouchBegan
It also indicates that this is a callback function for the touch event.

When traversing the blocks in the array, because it is the beginning of the game, in order to make the game start normally, we must first determine that the first block in the vector is the first line, and the range of this block contains our contacts, because this if has been able to make sure that our fingers touch the block in the game, next, we need to determine whether to touch the white block or Black Block.

If it is black fast, the Black Block that is pressed will change to black and move this line down. If it is white block, the game will fail.


Bool helloworld: Init () {// 1. super init firstif (! Layer: Init () {return false;} visiblesize = Director: getinstance ()-> getvisiblesize (); startgame (); Auto listener = eventlistenertouchonebyone: Create (); listener-> ontouchbegan = [this] (touch * t, event * E) {log ("xuran is winner"); gameblock * B; Auto BS = gameblock :: getblocks (); For (Auto it = BS-> begin (); it! = BS-> end (); It ++) {B = * it; if (B-> getlineindex () = 1 & B-> getboundingbox (). containspoint (t-> getlocation () {If (B-> getcolor () = color3b: Black) {B-> setcolor (color3b: Gray ); this-> movedown ();} else {MessageBox ("game failed", "gameover") ;}} return false ;}; Director: getinstance () -> geteventdispatcher ()-> addeventlistenerwithscenegraphpriority (listener, this); // listen to the current scenario and return true ;}

6. Design game logic

The logic of this game is very simple, no more than 2048. It is nothing more than clicking black to move all blocks down until the end, and clicking the white block game fails.

Therefore, the main function to be implemented is movedown. The movedown function is actually very simple, that is, to move all the blocks down. First, in the movedown function in helloworldscene, We need to traverse the array of the entire block and let these blocks execute the move-down action in sequence. As for this specific move-down method, it should be implemented inside the block class, because this is a block action after all.


First, the number of rows of each moving block, that is, lineindex, will be reduced by 1 as moving occurs.

The second step is to execute a move-down action for each block.

Void gameblock: moveon () {size visable = Director: getinstance ()-> getvisiblesize (); this-> lineindex --; // rows that can be moved down, the row to be moved minus 1 runaction (sequence: Create (moveTo: Create (0.1f, point (getpositionx (), lineindex * visable. height/4), callfunc: Create ([this] () {If (lineindex <0) {This-> removeblock () ;}}), null )); // execute a Moving action to move a block to the corresponding position at an interval of 0.1}


Here, the runaction function will execute a series of actions and call a function after moving the block. If the block is removed from the screen, it should be destroyed, call the removeblock function.

Second, we need to set a game endpoint. That is to say, if the game has never been hit by a white block, when will it be stopped.

In general, the game should be stopped after you step on 50 black ones.

Therefore, you need to set a linecount in the helloworldscene class. Each time you add a common block to a row, you need to add 1. When all the blocks move downward, you also need to judge, if you have already stepped on 50 blocks, adding them to the top of the screen should not be a normal black or white block, but the final green game interface.


In addition, if you have added a green block for the end of the game in the move-down function, you don't need to add it next time. You can simply move it down, because the size of the end block of a game is the whole screen, there is no need to add more.

Bool helloworld: Init () {// 1. super init firstif (! Layer: Init () {return false;} visiblesize = Director: getinstance ()-> getvisiblesize (); startgame (); Auto listener = eventlistenertouchonebyone: Create (); listener-> ontouchbegan = [this] (touch * t, event * E) {// log ("xuran is winner"); gameblock * B; Auto BS = gameblock :: getblocks (); For (Auto it = BS-> begin (); it! = BS-> end (); It ++) {B = * it; if (B-> getlineindex () = 1 & B-> getboundingbox (). containspoint (t-> getlocation () {If (B-> getcolor () = color3b: Black) {B-> setcolor (color3b: Gray ); this-> movedown ();} else if (B-> getcolor () = color3b: Green) {This-> movedown ();} else {MessageBox ("game failed", "gameover") ;}break ;}return false ;}; Director: getinstance ()-> geteventdispatcher ()-> addeventlistenerwithscenegraphpriority (liste NER, this); // listen to the current scenario return true;} void helloworld: movedown () {If (linecount <50) {addnormal (4 ); // Add a row at the top of the screen, because the screen contains a maximum of four lines at a time} else if (! Showend) {showend = true; addendline ();} auto BS = gameblock: getblocks (); For (Auto it = BS-> begin (); it! = BS-> end (); It ++) {(* It)-> moveon ();}}

7. Add a timer

Bytes.

I am using the scheduleupdate timer, so I will first define an update function.

Then we need to define two functions: one is the function that starts the timer, and the other is the function that terminates the timer. Either the start timer or the end timer only needs to be done once, therefore, a bool variable is used to control its operation.

Void helloworld: Update (float DT) {long offet = clock ()-gametime; timelabel-> setstring (stringutils: Format ("% G", (double) offet) /1000);} void helloworld: starttime () {If (! Timerrunning) {gametime = clock (); // gets the time when the current system runs this program. Scheduleupdate (); // start to execute the timer timerrunning = true ;}} void helloworld: endtime () {If (timerrunning) {unscheduleupdate (); // stop execution timer timerrunning = false ;}}
The scheduleupdate timer calls the UPDATE function based on the changes in each frame.

Because we need to add a timer to the game interface, which is constantly changing, but as the block moves, it is likely to overwrite the timer, so we want to separate the game from the timer and separate them into two layers, so that the two will not be affected.

gamelayer = Node::create();addChild(gamelayer);timelabel = Label::create();timelabel->setColor(Color3B::RED);timelabel->setSystemFontSize(38);timelabel->setPosition(visibleSize.width/2, visibleSize.height-50);timelabel->setString("0.000\"");addChild(timelabel);

Create a new layer named gamelayer, and then create a label Label to display the time at all times and add it to my current layer, change addchild in the function of adding a function in all previous games to gamelayer-> addchild (B), that is, add all the elements in the game to the game layer, the timer is added to the current layer.


If (B-> getlineindex () = 1 & B-> getboundingbox (). containspoint (t-> getlocation () {If (B-> getcolor () = color3b: Black) {If (! Timerrunning) {This-> starttime ();} B-> setcolor (color3b: Gray); this-> movedown ();} else if (B-> getcolor () = color3b: Green) {This-> movedown (); this-> endtime ();} else {MessageBox ("game failed", "gameover ");} break ;}

Finally, determine whether the timer is stopped or started based on whether the timer is black or green.




PS: The first version is basically like this. It can be used, but there are still many things that need to be improved and improved. I will try again later.

Https://github.com/Harkphoenix/DontTouchWhiteBlock source code here, I wrote with

Cocos2dx learning ----- do not step on the white block V1.0

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.