Scenario I have main scene and I click this button I want to open another scene. But I am getting following error :
undefined reference to 'OyunMenu::scene()
MainMenu.h
#ifndef MAINMENU_H_
#define MAINMENU_H_
#include "cocos2d.h"
class MainMenu : public cocos2d::CCLayer
{
public:
virtual bool init();
static cocos2d::CCScene* scene();
virtual void registerWithTouchDispatcher(void);
virtual void ccTouchesBegan(cocos2d::CCSet* touches, cocos2d::CCEvent* event);
virtual void ccTouchesMoved(cocos2d::CCSet* touches, cocos2d::CCEvent* event);
virtual void ccTouchesEnded(cocos2d::CCSet* touches, cocos2d::CCEvent* event);
virtual void ccTouchesCancelled(cocos2d::CCSet* touches, cocos2d::CCEvent* event);
void menuCloseCallback(CCObject* pSender);
CREATE_FUNC(MainMenu);
};
#endif
MainMenu.cpp
#include "MainMenu.h"
#include "SimpleAudioEngine.h"
#include "Constants.h"
#include "OyunMenu.h"
#define COCOS2D_DEBUG 1
using namespace std;
USING_NS_CC;
CCScene* MainMenu::scene()
{
// 'scene' is an autorelease object
CCScene *scene = CCScene::create();
// 'layer' is an autorelease object
MainMenu *layer = MainMenu::create();
// add layer as a child to scene
scene->addChild(layer);
// return the scene
return scene;
}
bool MainMenu::init()
{
//////////////////////////////
// 1. super init first
if ( !CCLayer::init() )
{
return false;
}
this->setTouchEnabled(true);
CCSprite* oyuncuBul = CCSprite::create("oyuna-basla.png");
oyuncuBul->setPosition(ccp(150,260));
oyuncuBul->setTag(menuOyuncuBul);
this->addChild(oyuncuBul, 0);
}
void MainMenu::ccTouchesBegan(cocos2d::CCSet* touches, cocos2d::CCEvent* event)
{
CCTouch *touch = (CCTouch*) (touches->anyObject());
CCPoint point = touch->getLocationInView();
point = CCDirector::sharedDirector()->convertToGL(point);
CCSprite *oyuncuBul=(CCSprite *)this->getChildByTag(menuOyuncuBul);
CCRect rectOyuncuBul = oyuncuBul->boundingBox();
if(rectOyuncuBul.containsPoint(point)){
CCDirector::sharedDirector()->replaceScene(OyunMenu::scene());
}
OyunMenu.h
#ifndef OYUNMENU_H_
#define OYUNMENU_H_
#include "cocos2d.h"
class OyunMenu : public cocos2d::CCLayer
{
public:
virtual bool init();
static cocos2d::CCScene* scene();
virtual void registerWithTouchDispatcher(void);
virtual void ccTouchesBegan(cocos2d::CCSet* touches, cocos2d::CCEvent* event);
virtual void ccTouchesMoved(cocos2d::CCSet* touches, cocos2d::CCEvent* event);
virtual void ccTouchesEnded(cocos2d::CCSet* touches, cocos2d::CCEvent* event);
virtual void ccTouchesCancelled(cocos2d::CCSet* touches, cocos2d::CCEvent* event);
void menuCloseCallback(CCObject* pSender);
CREATE_FUNC(OyunMenu);
};
#endif
OyunMenu.cpp
#include "OyunMenu.h"
#include "SimpleAudioEngine.h"
#include "Constants.h"
#define COCOS2D_DEBUG 1
using namespace std;
USING_NS_CC;
CCScene* OyunMenu::scene()
{
// 'scene' is an autorelease object
CCScene *scene = CCScene::create();
// 'layer' is an autorelease object
OyunMenu *layer = OyunMenu::create();
// add layer as a child to scene
scene->addChild(layer);
// return the scene
return scene;
}
// on "init" you need to initialize your instance
bool OyunMenu::init()
{
//////////////////////////////
// 1. super init first
if ( !CCLayer::init() )
{
return false;
}
}
.h file
CCSprite* oyuncuBul;
.cpp file
oyuncuBul = CCSprite::create("oyuna-basla.png");
oyuncuBul->setPosition(ccp(150,260));
oyuncuBul->setTag(menuOyuncuBul);
this->addChild(oyuncuBul, 0);
void MainMenu::ccTouchesBegan(cocos2d::CCSet* touches, cocos2d::CCEvent* event)
{
CCTouch *touch = (CCTouch*) (touches->anyObject());
CCPoint point = touch->getLocationInView();
point = CCDirector::sharedDirector()->convertToGL(point);
CCRect rectOyuncuBul = oyuncuBul->boundingBox();
if(rectOyuncuBul.containsPoint(point)){
CCDirector::sharedDirector()->replaceScene(OyunMenu::scene());
}
You have to add this line in android.mk file of jni folder
../../Classes/OyunMenu.cpp
Just like i am added in my android.mk file
LOCAL_SRC_FILES := hellocpp/main.cpp\
../../Classes/Menu/AppDelegate.cpp\
../../Classes/Menu/HelloWorldScene.cpp\
../../Classes/Menu/MyScene.cpp\
../../Classes/Menu/LoadingLayer.cpp\
../../Classes/UI/NewLayer.cpp\
../../Classes/UI/HelpLayer.cpp
Related
This is my first question, the reason i signed up to the site. I'm developing a game using Qt 5.9 and I use QTimer to spawn enemies on the screen. Everytime the timer's timeout function is called, an enemy is spawned.
What i try to do is if a player kills let's say 10 enemies, the timer interval decreases, so the enemies will spawn more frequently, making the game a little bit more challenging. The first time the timer interval is set, the game runs perfectly, but the second time the setInterval() method is called, when the player kills 10 enemies, the game suddenly crashes. I tried debugging it to figure out what might cause it, and it seems that it crashes when i try to set the spawnInterval.
I'm fairly new to coding so any advice is appreciated! Here are the relevant source files and codes from my code:
main.cpp
#include <QApplication>
#include <game.h>
Game * game;
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
game = new Game();
game->show();
return a.exec();
}
game.h:
#include <QGraphicsScene>
#include <QWidget>
#include <QGraphicsView>
#include "Player.h"
#include "score.h"
#include "Health.h"
class Game: public QGraphicsView{
public:
Game(QWidget * parent=0);
QGraphicsScene * scene;
Player * player;
Score * score;
Health * health;
void setSpawnInterval(int spawnValue);
int getSpawnInterval();
void setTimerInterval();
private:
int spawnInterval = 1000;
};
#endif // GAME_H
game.cpp:
QTimer * timer1 = new QTimer();
QObject::connect(timer1,SIGNAL(timeout()),player,SLOT(spawn()));
timer1->start(getSpawnInterval());
}
void Game::setSpawnInterval(int spawnValue){
//this is the part where it crashes
spawnInterval = spawnValue;
}
int Game::getSpawnInterval(){
return spawnInterval;
}
score.h
#ifndef SCORE_H
#define SCORE_H
#include <QGraphicsTextItem>
class Score: public QGraphicsTextItem{
public:
Score(QGraphicsItem * parent=0);
void increase();
int getScore();
private:
int score;
};
#endif // SCORE_H
score.cpp
#include "score.h"
#include <QFont>
#include "game.h"
#include <QTimer>
void Score::increase()
{
score++;
if(score > 3){
Game * game;
game->setSpawnInterval(200);}
//Draw the text to the display
setPlainText(QString("Score: ") + QString::number(score));
}
int Score::getScore()
{
return score;
}
player.h
#ifndef PLAYER_H
#define PLAYER_H
#include <QGraphicsRectItem>
#include <QEvent>
#include <QObject>
class Player: public QObject, public QGraphicsRectItem{
Q_OBJECT
public:
Player(QGraphicsItem * parent=0);
void keyPressEvent(QKeyEvent * event);
int jumpPhaseNumber = 0;
bool jumpRun = false;
public slots:
void spawn();
void jumpPhase();
};
#endif
player.cpp
void Player::spawn()
{
Enemy * enemy = new Enemy();
scene()->addItem(enemy);
}
Seems you are creating two instance of class game.
I suggest you to use static variables for accessing from multi classes.
add this class to your project:
.cpp
#include "settings.h"
int Settings::spawnInterval = 1000;
Settings::Settings(QObject *parent) : QObject(parent)
{
}
.h
#ifndef SETTINGS_H
#define SETTINGS_H
#include <QObject>
#include <QString>
class Settings : public QObject
{
Q_OBJECT
public:
explicit Settings(QObject *parent = 0);
static int spawnInterval;
};
#endif // SETTINGS_H
now we have a static variable name spawnInterval, you can access it (set/get) from any classes that include settings class like this:
#include <settings.h>
Settings::spawnInterval = 100; // set
int value = Settings::spawnInterval; //get
This line: Game * game; game->setSpawnInterval(200) causes your program to crash: you must initialize the game pointer; to fix this, for example, you can hold a reference (pointer) of game inside the Score class, thus letting you call setSpawnInterval; I would construct Score inside Game's constructor passing thisas a parameter; this saves you from creating a new class, as #aghilpro suggested. Actually a struct would be better since your information is public and accessible from other classes without the need to implement getters/setters.
I have the following code for native binder implementation.
#define LOG_TAG "binder_demo"
#include <stdlib.h>
#include <utils/RefBase.h>
#include <utils/Log.h>
#include <binder/TextOutput.h>
#include <binder/IInterface.h>
#include <binder/IBinder.h>
#include <binder/ProcessState.h>
#include <binder/IServiceManager.h>
#include <binder/IPCThreadState.h>
using namespace android;
#define INFO(...) \
do { \
printf(__VA_ARGS__); \
printf("\n"); \
ALOGD(__VA_ARGS__); \
} while(0)
void assert_fail(const char *file, int line, const char *func, const char *expr) {
INFO("assertion failed at file %s, line %d, function %s:",
file, line, func);
INFO("%s", expr);
abort();
}
#define ASSERT(e) \
do { \
if (!(e)) \
assert_fail(__FILE__, __LINE__, __func__, #e); \
} while(0)
#define PLOG aout
class IDemo : public IInterface {
public:
enum {
ALERT = IBinder::FIRST_CALL_TRANSACTION,
PUSH,
ADD
};
// Sends a user-provided value to the service
virtual void push(int32_t data) = 0;
// Sends a fixed alert string to the service
virtual void alert() = 0;
// Requests the service to perform an addition and return the result
virtual int32_t add(int32_t v1, int32_t v2) = 0;
DECLARE_META_INTERFACE(Demo); // Expands to 5 lines below:
};
// Client
class BpDemo : public BpInterface<IDemo> {
public:
BpDemo(const sp<IBinder>& impl) : BpInterface<IDemo>(impl) {
ALOGD("BpDemo::BpDemo()");
}
virtual void push(int32_t push_data) {
Parcel data, reply;
data.writeInterfaceToken(IDemo::getInterfaceDescriptor());
data.writeInt32(push_data);
aout << "BpDemo::push parcel to be sent:\n";
data.print(PLOG); endl(PLOG);
remote()->transact(PUSH, data, &reply);
aout << "BpDemo::push parcel reply:\n";
reply.print(PLOG); endl(PLOG);
ALOGD("BpDemo::push(%i)", push_data);
}
virtual void alert() {
Parcel data, reply;
data.writeInterfaceToken(IDemo::getInterfaceDescriptor());
data.writeString16(String16("The alert string"));
remote()->transact(ALERT, data, &reply, IBinder::FLAG_ONEWAY); // asynchronous call
ALOGD("BpDemo::alert()");
}
virtual int32_t add(int32_t v1, int32_t v2) {
Parcel data, reply;
data.writeInterfaceToken(IDemo::getInterfaceDescriptor());
data.writeInt32(v1);
data.writeInt32(v2);
aout << "BpDemo::add parcel to be sent:\n";
data.print(PLOG); endl(PLOG);
remote()->transact(ADD, data, &reply);
ALOGD("BpDemo::add transact reply");
reply.print(PLOG); endl(PLOG);
int32_t res;
status_t status = reply.readInt32(&res);
ALOGD("BpDemo::add(%i, %i) = %i (status: %i)", v1, v2, res, status);
return res;
}
};
DECLARE_META_INTERFACE(Demo,"Demo"); // Expands to 5 lines below:
// Server
class BnDemo : public BnInterface<IDemo> {
virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0);
};
status_t BnDemo::onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
ALOGD("BnDemo::onTransact(%i) %i", code, flags);
data.checkInterface(this);
data.print(PLOG); endl(PLOG);
switch(code) {
case ALERT: {
alert(); // Ignoring the fixed alert string
return NO_ERROR;
} break;
case PUSH: {
int32_t inData = data.readInt32();
ALOGD("BnDemo::onTransact got %i", inData);
push(inData);
ASSERT(reply != 0);
reply->print(PLOG); endl(PLOG);
return NO_ERROR;
} break;
case ADD: {
int32_t inV1 = data.readInt32();
int32_t inV2 = data.readInt32();
int32_t sum = add(inV1, inV2);
ALOGD("BnDemo::onTransact add(%i, %i) = %i", inV1, inV2, sum);
ASSERT(reply != 0);
reply->print(PLOG); endl(PLOG);
reply->writeInt32(sum);
return NO_ERROR;
} break;
default:
return BBinder::onTransact(code, data, reply, flags);
}
}
class Demo : public BnDemo {
virtual void push(int32_t data) {
INFO("Demo::push(%i)", data);
}
virtual void alert() {
INFO("Demo::alert()");
}
virtual int32_t add(int32_t v1, int32_t v2) {
INFO("Demo::add(%i, %i)", v1, v2);
return v1 + v2;
}
};
// Helper function to get a hold of the "Demo" service.
sp<IDemo> getDemoServ() {
sp<IServiceManager> sm = defaultServiceManager();
ASSERT(sm != 0);
sp<IBinder> binder = sm->getService(String16("Demo"));
// TODO: If the "Demo" service is not running, getService times out and binder == 0.
ASSERT(binder != 0);
sp<IDemo> demo = interface_cast<IDemo>(binder);
ASSERT(demo != 0);
return demo;
}
int main(int argc, char **argv) {
if (argc == 1) {
ALOGD("We're the service");
defaultServiceManager()->addService(String16("Demo"), new Demo());
android::ProcessState::self()->startThreadPool();
ALOGD("Demo service is now ready");
IPCThreadState::self()->joinThreadPool();
ALOGD("Demo service thread joined");
} else if (argc == 2) {
INFO("We're the client: %s", argv[1]);
int v = atoi(argv[1]);
sp<IDemo> demo = getDemoServ()
demo->alert();
demo->push(v);
const int32_t adder = 5;
int32_t sum = demo->add(v, adder);
ALOGD("Addition result: %i + %i = %i", v, adder, sum);
}
return 0;
}
The problem is how to compile and test it on a android platform. I don't want to build a new binary. What I want is that the code should compile on a running android platform and result should be displayed on a terminal like adb shell.
There are over 20 Layers like Layer01.cpp, Layer02.cpp, Layer03.cpp ...
and there is a tableview named "itemSlots" in HelloWorld.cpp.
When user touch dragon button in Layer01,
a banana sprite in HelloWorld.cpp will be dissappeared,
and a poop appear in itemSlots.
That is all I want to do and I thought it is quite simple.
I made Layers and tableview also, like below,
but still couldn't find a way to make interact between button and sprite
which are made in different cpps.
Layer01.h
#ifndef __LAYER01__H__
#define __LAYER01__H__
#include "cocos2d.h"
#include "ui/CocosGUI.h"
class Layer01 : public cocos2d::LayerColor
{
public:
Layer01();
virtual bool init();
cocos2d::ui::Button* dragon;
void touchDragon();
private:
};
#endif
Layer01.cpp
#include "Layer01.h"
USING_NS_CC;
Layer01::Layer01()
{
bool bOk = initWithColor(Color4B::BLACK, 750, 400);
if (bOk == true) {
this->autorelease();
init();
};
}
bool Layer01::init()
{
scene01 = Sprite::create("images/scene01.jpg");
scene01->setScale(this->getContentSize().width/sc02a->getContentSize().width);
scene01->setAnchorPoint(Point::ZERO);
scene01->setPosition(Point::ZERO);
this->addChild(scene01);
dragon = ui::Button::create("images/dragon.png", "images/dragon.png", "");
dragon->setContentSize(Size(50, 50));
dragon->setPosition(Point(250,300));
dragon->addClickEventListener(CC_CALLBACK_0(Layer01::touchDragon, this));
this->addChild(dragon);
return true;
}
void Layer01::touchDragon()
{
/*
layer01->removeChild(banana);
auto poopCell = itemSlots->cellAtIndex(2);
poopCell->addChild(poop);
*/
}
HelloWorld.h
#ifndef __HELLOWORLD_SCENE_H__
#define __HELLOWORLD_SCENE_H__
#include "cocos2d.h"
#include "Layer01.h"
#include "ui/CocosGUI.h"
#include "cocos-ext.h"
#include "CustomTableViewCell.h"
class HelloWorld : public cocos2d::Layer,
public cocos2d::extension::TableViewDataSource,
public cocos2d::extension::TableViewDelegate
{
public:
static cocos2d::Scene* createScene();
virtual bool init();
CREATE_FUNC(HelloWorld);
cocos2d::Sprite* banana;
cocos2d::Sprite* poop;
cocos2d::extension::TableView* itemSlots;
virtual void tableCellTouched(cocos2d::extension::TableView* table,
cocos2d::extension::TableViewCell* cell);
virtual cocos2d::Size tableCellSizeForIndex
(cocos2d::extension::TableView* table, ssize_t idx);
virtual cocos2d::extension::TableViewCell* tableCellAtIndex
(cocos2d::extension::TableView* table, ssize_t idx);
virtual ssize_t numberOfCellsInTableView(cocos2d::extension::TableView* view);
};
#endif // __HELLOWORLD_SCENE_H__
HelloWorld.cpp
#include "HelloWorldScene.h"
USING_NS_CC;
USING_NS_CC_EXT;
Scene* HelloWorld::createScene()
{
auto scene = Scene::create();
auto layer = HelloWorld::create();
scene->addChild(layer);
return scene;
}
bool HelloWorld::init()
{
if ( !Layer::init() )
{
return false;
}
layer01 = new Layer01();
layer->setPosition(Point(0, 100));
this->addChild(layer01);
banana = Sprite::create("images/banana.png");
banana->setPosition(Point(300,300));
layer01->addChild(banana);
poop = Sprite::create("images/poop.png");
itemSlots = TableView::create(this, Size(535, 70));
itemSlots->setDirection(ScrollView::Direction::HORIZONTAL);
itemSlots->setPosition(Point(115, 15));
itemSlots->setDelegate(this);
this->addChild(itemSlots);
itemSlots->reloadData();
return true;
}
void HelloWorld::tableCellTouched(TableView* table, TableViewCell* cell)
{
}
Size HelloWorld::tableCellSizeForIndex(TableView* table, ssize_t idx)
{
return Size(77, 77);
}
TableViewCell* HelloWorld::tableCellAtIndex(TableView* table, ssize_t idx)
{
auto string = String::createWithFormat("%ld", idx);
TableViewCell* cell = table->dequeueCell();
if (cell == false)
{
cell = new CustomTableViewCell();
cell->autorelease();
auto sprite01 = Sprite::create();
sprite01->setAnchorPoint(Point::ZERO);
sprite01->setPosition(Point::ZERO);
cell->addChild(sprite01);
auto label = LabelTTF::create(string->getCString(), "arial", 20.0);
label->setAnchorPoint(Point::ZERO);
label->setPosition(Point(5, 5));
label->setTag(120);
cell->addChild(label);
}
else {
auto label = (LabelTTF*)cell->getChildByTag(120);
label->setString(string->getCString());
}
return cell;
}
ssize_t HelloWorld::numberOfCellsInTableView(TableView* table)
{
return 20;
}
The easiest but unsafe way is to do following:
//Layer01.cpp
#include "HelloWorld.h"
...
void Layer01::touchDragon()
{
removeChild(banana);
// As your parent is a HelloWorld you can cast it:
HelloWorld* helloWorld = (HelloWorld*)getParent();
auto poopCell = helloWorld->itemSlots->cellAtIndex(2);
poopCell->addChild(helloWorld->poop);
}
But poop will be automatically garbage collected at that time. You need to retain it after creating and release when no longer need.
The better option would be to have a pointer to the HelloWorld layer in the Layer01 and have a separate method for setting a poop:
Layer01.h
// Forward declaration
class HelloWorld;
class Layer01
{
...
HelloWorld* m_hellowWorld;
// Don't forget about create function
static Layer01* create(HelloWorld* helloWorld)
{
Layer01* result = new (std::nothrow) Layer01();
if(result && result->init(helloWorld))
{
result->autorelease();
}
else
{
delete result;
result = nullptr;
}
return result;
}
bool Layer01::init(HelloWorld* helloWorld);
...
};
Layer01.cpp
#include "Layer01.h"
#include "HelloWorld.h"
Layer01::Layer01()
: HelloWorld(nullptr)
{}
bool Layer01::init(HelloWorld* helloWorld)
{
removeChild(banana);
m_hellowWorld = helloWorld;
...
}
void Layer01::touchDragon()
{
m_hellowWorld->setPoop();
}
HelloWorld.h
class HelloWorld
{
...
void setPoop();
...
};
HelloWorld.cpp
...
void HelloWorld::setPoop()
{
auto poopCell = itemSlots->cellAtIndex(2);
poopCell->addChild(Sprite::create("images/poop.png"));
}
I want to implement a simple IPC mechanism using Binders in android. For that, I searched on the Internet and found this. I compiled it and it runs fine on my Android device. I tried to take an overall understanding of the program, by searching for each class on AOSP, but everything got more difficult and messed up. Can anyone please explain (just high level), maybe by adding more comments, so that it also helps some future visitors. Here's the code is taken from there:
#define LOG_TAG "binder_demo"
#include <stdlib.h>
#include "utils/RefBase.h"
#include "utils/Log.h"
#include "utils/TextOutput.h"
#include <binder/IInterface.h>
#include <binder/IBinder.h>
#include <binder/ProcessState.h>
#include <binder/IServiceManager.h>
#include <binder/IPCThreadState.h>
using namespace android;
#define INFO(...) \
do { \
printf(__VA_ARGS__); \
printf("\n"); \
LOGD(__VA_ARGS__); \
} while(0)
void assert_fail(const char *file, int line, const char *func, const char *expr) {
INFO("assertion failed at file %s, line %d, function %s:",
file, line, func);
INFO("%s", expr);
abort();
}
#define ASSERT(e) \
do { \
if (!(e)) \
assert_fail(__FILE__, __LINE__, __func__, #e); \
} while(0)
// Where to print the parcel contents: aout, alog, aerr. alog doesn't seem to work.
#define PLOG aout
// Interface (our AIDL) - Shared by server and client
class IDemo : public IInterface {
public:
enum {
ALERT = IBinder::FIRST_CALL_TRANSACTION,
PUSH,
ADD
};
// Sends a user-provided value to the service
virtual void push(int32_t data) = 0;
// Sends a fixed alert string to the service
virtual void alert() = 0;
// Requests the service to perform an addition and return the result
virtual int32_t add(int32_t v1, int32_t v2) = 0;
DECLARE_META_INTERFACE(Demo); // Expands to 5 lines below:
//static const android::String16 descriptor;
//static android::sp<IDemo> asInterface(const android::sp<android::IBinder>& obj);
//virtual const android::String16& getInterfaceDescriptor() const;
//IDemo();
//virtual ~IDemo();
};
// Client
class BpDemo : public BpInterface<IDemo> {
public:
BpDemo(const sp<IBinder>& impl) : BpInterface<IDemo>(impl) {
LOGD("BpDemo::BpDemo()");
}
virtual void push(int32_t push_data) {
Parcel data, reply;
data.writeInterfaceToken(IDemo::getInterfaceDescriptor());
data.writeInt32(push_data);
aout << "BpDemo::push parcel to be sent:\n";
data.print(PLOG); endl(PLOG);
remote()->transact(PUSH, data, &reply);
aout << "BpDemo::push parcel reply:\n";
reply.print(PLOG); endl(PLOG);
LOGD("BpDemo::push(%i)", push_data);
}
virtual void alert() {
Parcel data, reply;
data.writeInterfaceToken(IDemo::getInterfaceDescriptor());
data.writeString16(String16("The alert string"));
remote()->transact(ALERT, data, &reply, IBinder::FLAG_ONEWAY); // asynchronous call
LOGD("BpDemo::alert()");
}
virtual int32_t add(int32_t v1, int32_t v2) {
Parcel data, reply;
data.writeInterfaceToken(IDemo::getInterfaceDescriptor());
data.writeInt32(v1);
data.writeInt32(v2);
aout << "BpDemo::add parcel to be sent:\n";
data.print(PLOG); endl(PLOG);
remote()->transact(ADD, data, &reply);
LOGD("BpDemo::add transact reply");
reply.print(PLOG); endl(PLOG);
int32_t res;
status_t status = reply.readInt32(&res);
LOGD("BpDemo::add(%i, %i) = %i (status: %i)", v1, v2, res, status);
return res;
}
};
//IMPLEMENT_META_INTERFACE(Demo, "Demo");
// Macro above expands to code below. Doing it by hand so we can log ctor and destructor calls.
const android::String16 IDemo::descriptor("Demo");
const android::String16& IDemo::getInterfaceDescriptor() const {
return IDemo::descriptor;
}
android::sp<IDemo> IDemo::asInterface(const android::sp<android::IBinder>& obj) {
android::sp<IDemo> intr;
if (obj != NULL) {
intr = static_cast<IDemo*>(obj->queryLocalInterface(IDemo::descriptor).get());
if (intr == NULL) {
intr = new BpDemo(obj);
}
}
return intr;
}
IDemo::IDemo() { LOGD("IDemo::IDemo()"); }
IDemo::~IDemo() { LOGD("IDemo::~IDemo()"); }
// End of macro expansion
// Server
class BnDemo : public BnInterface<IDemo> {
virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0);
};
status_t BnDemo::onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
LOGD("BnDemo::onTransact(%i) %i", code, flags);
data.checkInterface(this);
data.print(PLOG); endl(PLOG);
switch(code) {
case ALERT: {
alert(); // Ignoring the fixed alert string
return NO_ERROR;
} break;
case PUSH: {
int32_t inData = data.readInt32();
LOGD("BnDemo::onTransact got %i", inData);
push(inData);
ASSERT(reply != 0);
reply->print(PLOG); endl(PLOG);
return NO_ERROR;
} break;
case ADD: {
int32_t inV1 = data.readInt32();
int32_t inV2 = data.readInt32();
int32_t sum = add(inV1, inV2);
LOGD("BnDemo::onTransact add(%i, %i) = %i", inV1, inV2, sum);
ASSERT(reply != 0);
reply->print(PLOG); endl(PLOG);
reply->writeInt32(sum);
return NO_ERROR;
} break;
default:
return BBinder::onTransact(code, data, reply, flags);
}
}
class Demo : public BnDemo {
virtual void push(int32_t data) {
INFO("Demo::push(%i)", data);
}
virtual void alert() {
INFO("Demo::alert()");
}
virtual int32_t add(int32_t v1, int32_t v2) {
INFO("Demo::add(%i, %i)", v1, v2);
return v1 + v2;
}
};
// Helper function to get a hold of the "Demo" service.
sp<IDemo> getDemoServ() {
sp<IServiceManager> sm = defaultServiceManager();
ASSERT(sm != 0);
sp<IBinder> binder = sm->getService(String16("Demo"));
// TODO: If the "Demo" service is not running, getService times out and binder == 0.
ASSERT(binder != 0);
sp<IDemo> demo = interface_cast<IDemo>(binder);
ASSERT(demo != 0);
return demo;
}
int main(int argc, char **argv) {
if (argc == 1) {
LOGD("We're the service");
defaultServiceManager()->addService(String16("Demo"), new Demo());
android::ProcessState::self()->startThreadPool();
LOGD("Demo service is now ready");
IPCThreadState::self()->joinThreadPool();
LOGD("Demo service thread joined");
} else if (argc == 2) {
INFO("We're the client: %s", argv[1]);
int v = atoi(argv[1]);
sp<IDemo> demo = getDemoServ();
demo->alert();
demo->push(v);
const int32_t adder = 5;
int32_t sum = demo->add(v, adder);
LOGD("Addition result: %i + %i = %i", v, adder, sum);
}
return 0;
}
I know this is a bit late but checkout this amazing explanation by Gabriel Burca on Android IPC mechanism here. You can find a working example with a very simple C++ code from the same author here. Further it has clear instructions how to compile and add it to your AOSP source. Cheers!
Pretty new to Cocos2dx and C++ from an Objective-C background. I'm making a game where you can have between 1-10 enemies on the screen at a time. Each enemy has 1 sprite for its body and 2 stats (health & damage).
In the past with Objective-C I've been able to define a Class.h/Class.mm file and fill it with as many variables as I want (health, speed, height, weight, color, etc), but I'm having trouble figuring out how to do this in Cocos2dx.
Here is a simplified project that isolates the problem I'm having. I'm sure it's something straight forward but I'm having trouble looking up the solution
//-----Enemy.h
#include "cocos2d.h"
USING_NS_CC;
class Enemy : public cocos2d::Layer{
public:
virtual bool init();
CREATE_FUNC(Enemy);
void setHealth(int val);
private:
int myHealth;
Sprite *body;
Sprite *weapon;
};
//-----Enemy.cpp
#include "Enemy.h"
USING_NS_CC;
bool Enemy::init()
{
if ( !Layer::init() )
return false;
return true;
}
void setHealth(int newHealth)
{
//myHealth = newHealth;
}
//-----HelloWorldScene.h
#include "cocos2d.h"
USING_NS_CC;
class HelloWorld : public cocos2d::Layer
{
public:
static cocos2d::Scene* createScene();
virtual bool init();
CREATE_FUNC(HelloWorld);
};
//-----HelloWorldScene.cpp
#include "HelloWorldScene.h"
#include <iomanip>
#include "Enemy.h"
USING_NS_CC;
Scene* HelloWorld::createScene()
{
auto scene = Scene::create();
auto layer = HelloWorld::create();
scene->addChild(layer);
return scene;
}
// on "init" you need to initialize your instance
bool HelloWorld::init()
{
if ( !Layer::init() )
return false;
Enemy *newEnemy = Enemy::create();
//newEnemy->setHealth(100);
this->addChild(newEnemy);
return true;
}
This compiles fine except for the 2 commented lines, which cause errors.
Please help, thanks in advance!
Without knowing your error message exactly, it looks like you are missing the class name in your setHealth method in Enemy.cpp
Change your method declaration in your Enemy.h
From:
void setHealth(int val);
To:
void setHealth(int newHealth);
Then in your Enemy.cpp file change the following.
From:
void setHealth(int newHealth)
To:
void Enemy::setHealth(int newHealth)