Simple Example
Lets make a class that draws a simple shape on the screen and then move it around the screen to see how all these work!
- Start by creating a new cocos project (or the empty template) and opening it in XCode.
- Right click somewhere on the project pane and select “New File…”
- Select “C++ File” in the dialog and press “Next”
- Give it the name “MyDrawNode”, make sure “Also create a header file” checkbox is ticked and press “Next”.
- Choose “Classes” folder in your project folder and press “Create”. This will create MyDrawNode.cpp and MyDrawNode.hpp and adds them to the project.
- Copy this code to the MyDrawNode.hpp file:
#ifndef MyDrawNode_hpp #define MyDrawNode_hpp #include <stdio.h> #include "cocos2d.h" using namespace cocos2d; class MyDrawNode:public Node { bool isDrawn; public: static Node* createNode(); virtual bool init(); virtual void draw(Renderer* renderer, const Mat4& transform, uint32_t flags); CREATE_FUNC(MyDrawNode); // Make the create function }; #endif /* MyDrawNode_hpp */
As you can see, we have init and draw methods that are virtual and override the parent methods of the same names. In the init method we initialize the class. The draw method will be called on every frame to draw our shapes on the screen.
- Copy this code to the MyDrawNode.cpp file:
#include "MyDrawNode.hpp" Node* MyDrawNode::createNode() { return MyDrawNode::create(); // Create an instance of this class and return the pointer } bool MyDrawNode::init() { if(!Node::init()) { return false; } isDrawn = false; // Screen coordinates auto visibleSize = Director::getInstance()->getVisibleSize(); // Screen's visible size Vec2 origin = Director::getInstance()->getVisibleOrigin(); // Screen's visible origin // Calculating the center of the screen float cx = origin.x + visibleSize.width * 0.5; // X for the center of the screen float cy = origin.y + visibleSize.height * 0.5; // Y for the center of the screen setPosition(cx, cy); return true; } void MyDrawNode::draw(Renderer* renderer, const Mat4& transform, uint32_t flags) { if(!isDrawn) { auto draw = DrawNode::create(); // Create a drawNode object that draws simple shapes // Draw a rectangle draw->drawLine(Vec2(-100, -100), Vec2(-100, +100), Color4F(1.0, 1.0, 1.0, 1.0)); draw->drawLine(Vec2(+100, -100), Vec2(+100, +100), Color4F(1.0, 1.0, 1.0, 1.0)); draw->drawLine(Vec2(-100, -100), Vec2(+100, -100), Color4F(1.0, 1.0, 1.0, 1.0)); draw->drawLine(Vec2(-100, +100), Vec2(+100, +100), Color4F(1.0, 1.0, 1.0, 1.0)); addChild(draw); // Parenting the drawn object to this node isDrawn = true; // Should stop drawing on every frame } }
The DrawNode class that I have used here is a Cocos2d-x class that draws basic shapes like, line, circle, point, etc…
If you don’t set the isDrawn to true, you will see that on every frame GL verts number increases on the screen which means on every frame four new lines are being added to the scene. This is not necessary and that is why we just want to draw these four lines once!
- Include MyDrawNode at the top of your HelloWorldScene.h header file after #include “cocos2d.h”.
#include "MyDrawNode.hpp"
- Replace the init() method inside the HelloWorldScene.cpp with this one.
bool HelloWorld::init() { if ( !Scene::init() ) { return false; } auto mynode = MyDrawNode::create(); // Create an instance of MyDrawNode this->addChild(mynode); // Add the instance to the parent return true; }
- Change the design resolution to be 1136×640 in the AppDelegate.cpp
static cocos2d::Size designResolutionSize = cocos2d::Size(1136, 640);
- Build and Run the project and you should see this square at the center of the screen!
Spirograph Example
Drawing a box is fine, but not very interesting. Now lets redo our MyDrawNode class to do something more fun than before.
- Make an empty cocos project.
- Like the previous example add a class called MyDrawNode.
- Type/Copy this code for the MyDrawNode.hpp file.
#ifndef MyDrawNode_hpp #define MyDrawNode_hpp #include <stdio.h> #include "cocos2d.h" using namespace cocos2d; class MyDrawNode:public Node { Vec2 firstPoint; Vec2 secondPoint; float i; float radius1; float radius2; float multi; float delta; public: static Node* createNode(); virtual bool init(); virtual void draw(Renderer* renderer, const Mat4& transform, uint32_t flags); CREATE_FUNC(MyDrawNode); // Make the create function }; #endif /* MyDrawNode_hpp */
- Type/Copy this code for the MyDrawNode.cpp file
#include <iostream> #include <cstdlib> #include "MyDrawNode.hpp" using namespace cocos2d; using namespace std; Node* MyDrawNode::createNode() { return DrawNode::create(); // Create an instance of this class and return the pointer } bool MyDrawNode::init() { if(!Node::init()) { return false; } srand(time(NULL)); i = 0; radius1 = rand() % 100 + 150; // Random between 150 to 250 radius2 = rand() % 100 + 50; // Random between 50 to 150 multi = 0.53; delta = 0.2; firstPoint = Vec2(0, 0); secondPoint = Vec2(0, 0); // Screen coordinates auto visibleSize = Director::getInstance()->getVisibleSize(); // Screen's visible size Vec2 origin = Director::getInstance()->getVisibleOrigin(); // Screen's visible origin // Calculating the center of the screen float cx = origin.x + visibleSize.width * 0.5; // X for the center of the screen float cy = origin.y + visibleSize.height * 0.5; // Y for the center of the screen this->setPosition(cx, cy); return true; } void MyDrawNode::draw(Renderer* renderer, const Mat4& transform, uint32_t flags) { secondPoint.x = radius1 * cos(i * multi) + radius2 * sin(i * 1.1); // Calculating X for the end point secondPoint.y = radius1 * sin(i * multi) + radius2 * cos(i * 1.1); // Calculating Y for the end point if (i < 800.0) { i += delta; if(firstPoint == Vec2(0,0)) firstPoint = secondPoint; auto draw = DrawNode::create(); // Create a drawNode object that draws simple shapes draw->drawLine(firstPoint, secondPoint, Color4F(1.0, 1.0, 1.0, 1.0)); // Draw a line from the start point to the end point firstPoint = secondPoint; this->addChild(draw); // Parenting the drawn object to this node } }
- Include MyDrawNode.hpp in your HelloWorldScene.h file.
- Update the init method in your HelloWorldScene.cpp file.
bool HelloWorld::init() { ////////////////////////////// // 1. super init first if ( !Scene::init() ) { return false; } auto mynode = MyDrawNode::create(); // Create an instance of MyDrawNode this->addChild(mynode); // Add the instance to the parent return true; }
- Change the design resolution to something bigger (1024×768) in your AppDelegate.cpp.
- Make sure the new class file is in your Target Membership on the right panel in XCode.
- Build and Run the project and watch the pattern is drawn.
Notice that the GL Verts count goes up as it draws the pattern. That is because on every frame we are adding a line that contains two new points.