Can enyone tell me how to call AdMob Interstitial between scenes in my cocos2d-x game?
I have tried this http://robwirving.com/2014/07/21/calling-c-methods-c-winrt-components/ guide, but i don't know how to run it from cocos classes.
Is there any another ways, or some guides?
I've recently made it. You have to do few things. First of all create helper class, which will help you calling native function (I use this for all 3 platforms, but here's just windows phone):
NativeHelper.h:
#ifndef __NATIVE_HELPER_H_
#define __NATIVE_HELPER_H_
#include <string>
#include <functional>
#include "cocos2d.h"
using namespace std;
USING_NS_CC;
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WP8)
namespace cocos2d
{
public delegate void CSharpShowInterstitialDelegate();
public ref class WP8NativeEventHelper sealed
{
public:
void WP8NativeEventHelper::SetCSharpShowInterstitialDelegate(CSharpShowInterstitialDelegate^ delegate){
m_CSharpShowInterstitialDelegate = delegate;
}
void CallShowInterstitial();
private:
property static CSharpShowInterstitialDelegate^ m_CSharpShowInterstitialDelegate;
};
}
#endif
class NativeHelper
{
public:
static void showInterstitial(string adSdk);
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WP8)
WP8NativeEventHelper^ wp8helper;
#endif
//instance required only for setting callback
static NativeHelper* getInstance();
~NativeHelper()
{
instanceFlag = false;
}
private:
static bool instanceFlag;
static NativeHelper* instance;
NativeHelper() {};
};
#endif // __NATIVE_HELPER_H_
So. We have special C++/CX class Wp8NativeEventHelper, which can "talk" with C#. Here we store a delegate.
How it works:
C# is calling SetCSharpShowInterstitialDelegate and passes a delegate to it, which will be remembered in static property.
Then C++\CX can call it using CallShowInterstitial.
Now NativeHelperWP.cpp:
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WP8)
#ifndef __NATIVE_HELPER_WP_H_
#define __NATIVE_HELPER_WP_H_
#include "NativeHelper.h"
void WP8NativeEventHelper::CallShowInterstitial(){
if (m_CSharpShowInterstitialDelegate)
{
m_CSharpShowInterstitialDelegate->Invoke();
}
}
bool NativeHelper::instanceFlag = false;
NativeHelper* NativeHelper::instance = NULL;
NativeHelper* NativeHelper::getInstance()
{
if(!instanceFlag){
instance = new NativeHelper();
instanceFlag = true;
instance->wp8helper = ref new WP8NativeEventHelper();
}
return instance;
}
void NativeHelper::showInterstitial(){
NativeHelper::getInstance()->wp8helper->CallShowInterstitial();
}
#endif
#endif
Here is just an implementation of CallShowInterstitial. Also in NativeHelper::showInterstitial we're calling C++/CX, which later calls c#.
Now c# code (MainPage.xaml.cs):
outside namespace:
using GoogleAds;
inside class:
private InterstitialAd interstitialAd;
in constructor:
WP8NativeEventHelper helper = new WP8NativeEventHelper();
helper.SetCSharpShowInterstitialDelegate(showInterstitial);
and also create showInterstitial function:
public void showInterstitial() //we recreate interstitial each time, because otherwise it'll show only once, only new requests won't work
{
interstitialAd = new InterstitialAd("MY_AD_UNIT_ID");
AdRequest adRequest = new AdRequest();
#if DEBUG
// Enable test ads.
adRequest.ForceTesting = true;
#endif
interstitialAd.ReceivedAd += OnAdReceived;
interstitialAd.LoadAd(adRequest);
}
and finally OnAdReceived:
private void OnAdReceived(object sender, AdEventArgs e)
{
System.Diagnostics.Debug.WriteLine("Ad received successfully");
interstitialAd.ShowAd();
}
Follow this guide to setup admob: https://developers.google.com/mobile-ads-sdk/docs/admob/wp/quick-start
Now let's use this.
In HelloWorldScene.h add:
#include "NativeHelper.h"
In HelloWorldScene.cpp:
NativeHelper::showInterstitial();
The same way you can show/hide/change position of admob banner for example (however it's buggy so I'm using ad mediation).
Related
I am developing nema stepper motor driver interfacing with arduino. I created a class. I named it Axis. I want to create an axis object for each motor with this class. but, I can not call the attachInterrupt function in the arduino.h from the class. It return this error :
In member function 'void Axis::setReverseInt()':
parsstep.cpp:12:77: error: invalid use of non-static member function 'void Axis::revDirection()'
attachInterrupt(digitalPinToInterrupt(reverseDirPin), revDirection, RISING);
Axis::Axis()
{
}
Axis::~Axis()
{
}
void Axis::setReverseInt () {
attachInterrupt(digitalPinToInterrupt(reverseDirPin), revDirection, RISING);
}
void Axis::setStopInt () {
//attachInterrupt(digitalPinToInterrupt(stopPin), stopMotor, RISING);
}
void Axis::revDirection()
{
dirMode = !dirMode;
}
void Axis::stopMotor()
{
moveMotor = !moveMotor;
}
void Axis::startMotor()
{
moveMotor = true;
}
void Axis::moveStep(int pulseRev, byte laps, boolean dir)
{
digitalWrite(dirPin, dir);
int totalPulse = pulseRev * laps;
for (int i = 0; i < totalPulse; i++)
{
speedValue = map((analogRead(speedPin)), 0, 1023, 2000, 10);
digitalWrite(pulsePin, HIGH);
delayMicroseconds(speedValue);
digitalWrite(pulsePin, LOW);
delayMicroseconds(speedValue);
}
}
I faced a similar issue when writing my own libraries for a big project I've been working on. It happened to me while configuring interrupts inside a method. I found a workaround that while it might seem a bit more complex, it does the trick. In my case, I used it for reading a rotary encoder its switch.
What I used is a pointer to an ISR handler and a method to call it. On your setup function you can call the initialization of the ISR service.
First, in your .h file declare the following methods (in addition to your own):
void init();
static void ISRHandler();
void setupISRHandler(uint8_t pin, void (*ISR)(void), int state); // this will configure your ISR
and a pointer:
static Axis *_ISRPointer; // can be declared as private (like in here from the '_' prefix)
Then, in your .cpp file you use it like this:
#include "Axis.h"
Axis *Axis::_ISRPointer = nullptr;
you will initialize the ISR handler during the setup using the init method:
void Axis::init(){
setupISRHandler(reverseDirPin, Axis::ISRHandler, RISING);
}
the setup method looks like:
void Axis::setupISRHandler(uint8_t pin, void (*ISRFunction)(void), int state){
attachInterrupt(digitalPinToInterrupt(pin), ISRFunction, state);
}
the ISRHandler is in charge of calling the ISR routine:
void Axis::ISRHandler(){
_ISRPointer-> revDirection();
}
void Axis::revDirection(void){
// Do not forget to disable interrupts
cli();
// your routine goes here
dirMode= !dirMode;
sei();
}
Therefore, you will do something like this in your main .ino file:
#include "Axis.h"
#include <whateverotherlibraryyouneed.h>
Axis ax = Axis(); // your new object
void setup(){
ax.init();
ax.startMotor();
}
void loop(){
if(day == SUNNY){
ax.moveStep(100, 2 , CLOCKWISE);
} else {
ax.stopMotor();
}
ax.someOtherMethodToControlTheMotor(anyArgumentYouWant);
}
I hope that my convoluted solution helps
Cheers
Dr. Daniel
I want to vibrate my device in one of my slider functionality, using cocos2d-x 3.2.
I followed some of reference links regarding this on the official forums but I'm still stumped.
Can anyone help me?
After Searching a lot , Finally i am done with my Vibrate Function in Cocos2d-x 3.2 for android.
There is one Vibrator Class.
Vibrator.h
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
#include <jni.h>
#include <android/log.h>
#include "platform/android/jni/JniHelper.h"
#endif
#define CLASS_NAME "org/cocos2dx/lib/Cocos2dxHelper"
class Vibrator
{
public:
static void Vibrate(int time);
static void CancelVibrate();
};
#endif
Vibrator.cpp
#include "Vibrator.h"
void Vibrator::Vibrate(int time)
{
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
JniMethodInfo t;
if (JniHelper::getStaticMethodInfo(t, CLASS_NAME, "vibrate", "(I)V"))
{
t.env->CallStaticVoidMethod(t.classID, t.methodID, time);
t.env->DeleteLocalRef(t.classID);
}
#endif
}
void Vibrator::CancelVibrate()
{
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
JniMethodInfo t;
if (JniHelper::getStaticMethodInfo(t, CLASS_NAME, "cancelVibrate", "()V"))
{
t.env->CallStaticVoidMethod(t.classID, t.methodID);
t.env->DeleteLocalRef(t.classID);
}
#endif
}
=> in AndroidManifest.xml : add below permission .
=> in src/org/cocos2dx/lib/Cocos2dxHelper.java file : add below 2 methods
first import => import android.os.Vibrator;
then , add these 2 methods
public static void vibrate ( int vibrateTime) {
Vibrator vib = (Vibrator) sActivity.getSystemService (Service.VIBRATOR_SERVICE);
vib.vibrate (vibrateTime);
}
public static void cancelVibrate () {
Vibrator vib = (Vibrator) sActivity.getSystemService (Service.VIBRATOR_SERVICE);
vib.cancel ();
}
Now, Whenever we want to use Vibrate Function we just have to include this Vibrator Class & Simply Calling it as below .
Vibrator::Vibrate(50);
For Disabling it,
Vibrator::CancelVibrate();
in won't work in Tab as it does not having Vibrator in it .
There's supposed to be a working implementation of vibrate on iOS and Android on FenneX's github.
The header file is in
Classes/FenneX/NativeWrappers/NativeUtility.h.
iOS implementation is in proj.ios_mac/ios/Misc/NativeUtility.mm
Android implemention have the C++ in
proj.android/jni/NativeUtility.cpp
the Java somewhere in the src.
sourced from a forum post asking the same thing
Based on the code found in the forum post:
you need to add a header in your Classes/ folder where you just have the cpp function declared but not defined.
you need to add a function definition in the proj.android/jni, in a .cpp file. I used proj.android/jni/hellocpp/main.cpp, which I believe is the default for a starter cocos2dxv3 project. In this method you call the method you've defined in your java, in this case it was defined as a static method on your Activity. The default was named `AppActivity.
make sure you've got the vibration permission on your proj.android/AndroidManifest.xml, <uses-permission android:name="android.permission.VIBRATE"/>
So, in one of your standard C++ headers in the Classes/ folder, add
//Classes/any_header.h
void vibrate(int milliseconds);
and in the associated .cpp file, call it:
//Classes/any_header.cpp
void get_hit()
{
vibrate(200);
}
In your proj.android/AndroidManifest.xml, you'll want to add that line
<manifest>
...
<uses-permission android:name="android.permission.VIBRATE"/>
</manifest>
In a cpp file the jni will deal with, say proj.android/jni/hellocpp/main.cpp, you'll need to define the connection between the Java and C++ by calling the Java method:
//proj.android/jni/hellocpp/main.cpp
/* this function should already exist though */
void cocos_android_app_init (JNIEnv* env, jobject thiz) {
LOGD("cocos_android_app_init");
AppDelegate *pAppDelegate = new AppDelegate();
}
/* this is the new one you're adding, where org/cocos2dx/cpp/AppActivity
is the java file where your Activity with the vibrate static method is defined
*/
void vibrate(int milliseconds)
{
JniMethodInfo minfo;
CCAssert(JniHelper::getStaticMethodInfo(minfo, "org/cocos2dx/cpp/AppActivity", "vibrate", "(I)V"), "Function doesn't exist");
minfo.env->CallStaticVoidMethod(minfo.classID, minfo.methodID, (jint)milliseconds);
minfo.env->DeleteLocalRef(minfo.classID);
}
finally, here's the .java file where the android call to vibrate is made. Mine was proj.android/src/org/cocos2dx/cpp/AppActivity.java
/* default imports */
package org.cocos2dx.cpp;
import org.cocos2dx.lib.Cocos2dxActivity;
/* imports needed for vibration stuff */
import android.os.Vibrator;
import android.content.Context;
import android.app.ActivityManager;
import android.util.Log;
import android.os.Bundle;
public class AppActivity extends Cocos2dxActivity {
private static volatile Cocos2dxActivity mainActivity;
public static void setMainActivity(Cocos2dxActivity activity)
{
mainActivity = activity;
}
public static Cocos2dxActivity getMainActivity()
{
if(mainActivity == null)
{
Log.w("MY_APP_NAME_GOES_HERE", "Warning : null main Activity");
}
return mainActivity;
}
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
AppActivity.setMainActivity(this);
}
public static void vibrate(int milliseconds)
{
Vibrator v = (Vibrator) getMainActivity().getSystemService(Context.VIBRATOR_SERVICE);
if (getMainActivity().getSystemService(Context.VIBRATOR_SERVICE) != null)
{
v.vibrate(milliseconds);
}
}
}
Hello I am creating an game in cocos2d-x and when I am scheduling an event on splash screen for run game .It shows compilation error (in expansion of macro 'schedule_selector')
Following is my code for this
Splash.h
#ifndef SPLASH_H_
#define SPLASH_H_
#include "cocos2d.h"
class CCSplashLayer : public cocos2d::CCLayer {
private :
void runGame();
public:
static cocos2d::CCScene* createScene();
virtual bool init();
CREATE_FUNC(CCSplashLayer);
};
#endif /* SPLASH_H_ */
And SplashScene.cpp
#include "splash.h"
#include "cocos2d.h"
#include "HelloWorldScene.h"
USING_NS_CC;
bool CCSplashLayer::init() {
if (!Layer::init()) {
return false;
}
Size visibleSize = Director::getInstance()->getVisibleSize();
auto sprite = Sprite::create("splash.png");
sprite->setScale(Director::getInstance()->getContentScaleFactor());
sprite->setPosition(Vec2(visibleSize.width / 2,visibleSize.height/2));
this->addChild(sprite, 0);
//This line cause problem show i symbol on this line in eclipse
this->scheduleOnce(schedule_selector(CCSplashLayer::runGame),4.0f);
return true;
}
Scene* CCSplashLayer::createScene() {
auto scene = CCScene::create();
auto layer = CCSplashLayer::create();
scene->addChild(layer);
return scene;
}
void CCSplashLayer::runGame(){
auto scene = HelloWorld::createScene();
Director::getInstance()->setDepthTest(true);
TransitionScene *transition = TransitionScene::create(0.5f, scene);
Director::getInstance()->pushScene(transition);
}
schedule_selector takes function pointer which needs a float argument for time.
Change method CCSplashLayer::runGame() to CCSplashLayer::runGame(float dt) in defination and declaration.
Also you are pushing a scene over splash scene, which is not recommended way for splash scene. You must replace splash scene with new scene because we never need to display splash again in game unless there is specific design requirement of game.
Try this macro:
#define CCDL_PERFORM_SELECTOR( __OWNER__, __DELAY__, __CALLFUNC_SELECTOR__ ) \
__OWNER__->runAction( cocos2d::Sequence::create( \
cocos2d::DelayTime::create( __DELAY__ ), \
cocos2d::CallFunc::create( CC_CALLBACK_0( __CALLFUNC_SELECTOR__,__OWNER__) ), \
nullptr )); \
(source: https://github.com/duksel/Cocos2dx-DukselLib/blob/master/Cocos2dx-DukselLib/DukselMacros.h#L70-L74)
Allow to use for any CCNode (+subclass) instance.
In your case will be:
bool CCSplashLayer::init()
{
CCDL_PERFORM_SELECTOR( this, 4.f, CCSplashLayer::runGame );
}
try like this...
in init method,
this->runAction(CCSequence::create(CCDelayTime::create(4.0f),
CCCallFuncN::create(this,callfuncN_selector(CCSplashLayer::runGame)),
NULL));
and add this method.
void CCSplashLayer::runGame(){
auto scene = HelloWorld::createScene();
Director::getInstance()->setDepthTest(true);
TransitionScene *transition = TransitionScene::create(0.5f, scene);
Director::getInstance()->pushScene(transition);
}
Hi I have a question about passing argv[] value to the other class. In my code, I want to pass the argv[1] parameter from cmd to the class mainWindow to trigger spacific event. Here is the code. #include "MainWindow.h"
int main(int argc, char *argv[])
{
#if _DEBUG
// Do not print memory leaks at end of program (QtWebKit causes a large number of them, see Menu class)
_CrtSetDbgFlag(_crtDbgFlag &~ _CRTDBG_LEAK_CHECK_DF);
#endif
QApplication app(argc, argv);
app.setApplicationName("Example_Qt");
MainWindow window;
window.show();
return app.exec();
}
MainWindow.cpp
MainWindow::MainWindow() :
m_pCurrentTutorial(0),
m_pCurrentTutorialAREL(0)
{
setupUi(this);
quitTutorialButton->setVisible(false);
QObject::connect(quitTutorialButton, SIGNAL(clicked()), this, SLOT(onQuitTutorialButtonClicked()));
m_pMenu = new Menu(this, this);
// Init the main view for the scene using OpenGL
QGLWidget *glWidget = new QGLWidget(QGLFormat(QGL::SampleBuffers));
m_pGraphicsView = graphicsView;
m_pGraphicsView->setScene(m_pMenu);
m_pGraphicsView->setViewport(glWidget);
m_pGraphicsView->setFrameShape(QFrame::NoFrame);
// Do not show context menu in web view
m_pGraphicsView->setContextMenuPolicy(Qt::NoContextMenu);
}
MainWindow::~MainWindow()
{
delete m_pMenu;
m_pMenu = 0;
delete m_pGraphicsView;
m_pGraphicsView = 0;
}
Mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <vector>
#include <QVBoxLayout>
#include <QWidget>
#include <QWebView>
class TutorialBase;
class TutorialBaseAREL;
#include "Menu.h"
#include "ui_MainWindow.h"
QT_BEGIN_NAMESPACE
class QGraphicsView;
class QBoxLayout;
QT_END_NAMESPACE
class MainWindow : public QMainWindow, public Ui::MainWindow, public Menu::TutorialSelectionCallback
{
Q_OBJECT
public:
MainWindow();
virtual ~MainWindow();
QBoxLayout* getButtonBar();
protected slots:
void onQuitTutorialButtonClicked();
protected:
void keyPressEvent(QKeyEvent *event);
void quitTutorialIfAny();
void startTutorial(int tutorialNumber);
void startTutorialAREL(int tutorialNumber);
TutorialBase* m_pCurrentTutorial;
TutorialBaseAREL* m_pCurrentTutorialAREL;
QGraphicsView* m_pGraphicsView;
Menu* m_pMenu;
};
#endif
Could anyone help me to pass the parameter from the argv[] to mainwindow.cpp ?
Many thanks
Ying
You should be able to just provide another constructor (or replace the current one) which takes a single char * argument, such as:
MainWindow::MainWindow (char *arg) :
m_pCurrentTutorial(0),
m_pCurrentTutorialAREL(0)
{
// body here, including checking argument, such as:
if (strcmp (arg, "-help") == 0) {
provideHelp();
}
}
and then use that constructor when creating your object:
MainWindow window (argv[1]);
Be aware that this new constructor will need to be listed in the class (in Mainwindow.h), not just added as a function to Mainwindow.cpp:
public:
MainWindow();
MainWindow(char*);
virtual ~MainWindow();
my goal is to design a CCTableViewCell via CocosBuilder
and load it via CCBReader.
My steps so far:
I added a new non-fullscreen CCNode TestCell.ccb in cocosbuilder,
set the root's custom class to TestCell
and added a CCSprite as the roots child while setting
it's doc-root-var to bg.
My problem: after implementing a loader TestCellLoader
as well as the Cell TestCell the callback-function
TestCell::onAssignCCBMemberVariable is not called at all.
What I tried:
Using a CCLayerLoader instead of a CCNodeLoader worked for me so far,
this is the first time I'm using a CCNodeLoader so maybe I missed
a crucial point.
Thank you,
Ciao!
Ben
Here are the codes:
TestCellLoader.h
#include <cocos2d.h>
#include "cocos-ext.h"
#include "TestCell.h"
using namespace cocos2d;
using namespace cocos2d::extension;
class TestCellLoader : public CCNodeLoader
{
public:
CCB_STATIC_NEW_AUTORELEASE_OBJECT_METHOD(TestCellLoader, create);
protected:
CCB_VIRTUAL_NEW_AUTORELEASE_CREATECCNODE_METHOD(TestCell);
virtual CCNode* loadCCNode(CCNode *, CCBReader * pCCBReader);
};
TestCellLoader.cpp
#include "TestCellLoader.h"
CCNode * TestCellLoader::loadCCNode(CCNode * pParent, CCBReader * pCCBReader)
{
CCLOG("TestCell::loadCCNode");
CCNode * ccNode = this->createCCNode(pParent, pCCBReader);
return ccNode;
}
TestCell.h
class TestCell : public CCTableViewCell, public CCNodeLoaderListener, public CCBMemberVariableAssigner
{
public:
TestCell();
virtual ~TestCell();
static TestCell *create();
virtual bool init();
virtual bool initWithBG(CCSprite* bg);
static TestCell* cellWithBG(CCSprite* bg);
// ccbuilder callbacks
virtual bool onAssignCCBMemberVariable(cocos2d::CCObject * pTarget, const char * pMemberVariableName, cocos2d::CCNode * pNode);
virtual void onNodeLoaded(cocos2d::CCNode * pNode, cocos2d::extension::CCNodeLoader * pNodeLoader);
private:
CC_PROPERTY(CCSprite*, bg, Bg);
};
TestCell.m
#include "TestCell.h"
using namespace cocos2d;
using namespace cocos2d::extension;
TestCell::TestCell(){}
TestCell::~TestCell(){}
#pragma mark creation
TestCell* TestCell::create(){
TestCell *pRet = new TestCell();
pRet->init();
pRet->autorelease();
return pRet;
}
bool TestCell::init(){
return true;
}
bool TestCell::initWithBG(CCSprite* bg){
return true;
}
TestCell* TestCell::cellWithBG(CCSprite* bg){
return new TestCell;
}
#pragma mark - synthesize
void TestCell::setBg(cocos2d::CCSprite *sprite){
this->bg = sprite;
}
CCSprite* TestCell::getBg(){
return this->bg;
}
#pragma mark - ccbuilder callbacks
void TestCell::onNodeLoaded(cocos2d::CCNode * pNode, cocos2d::extension::CCNodeLoader * pNodeLoader)
{
CCLOG("TestCell::onNodeLoaded");
}
bool TestCell::onAssignCCBMemberVariable(CCObject* pTarget, const char* pMemberVariableName, CCNode* pNode)
{
CCLOG("TestCell::onAssignCCBMemberVariable %s", pMemberVariableName);
return false;
}
I guess you used a CCLayer as TestCell.ccb's Root object type. Since when you are creating a new ccb file, CCLayer is as default option.
And this is why you use a CCLayerLoader instead of a CCNodeLoader worked.
So change your TestCell.ccb's Root object type to CCNode, this maybe works.