cocos2d-x 안드로이드 진동기능 설정
cocos2d-x android vibration definition
1. (사용자 project name)\android\src\org\cocos2dx\lib
è폴더내의 Cocos2dxSound.java, Cocos2dxActivity.java 두 클래스 파일에 메서드 추가
빨간색 코드
================
Cocos2dxSound.java
================
package org.cocos2dx.lib;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import android.content.Context;
import android.media.AudioManager;
import android.media.SoundPool;
import android.util.Log;
import android.os.Vibrator;
/**
*
* This class is used for controlling effect
*
*/
public class Cocos2dxSound {
private Context mContext;
private SoundPool mSoundPool;
private float mLeftVolume;
private float mRightVolume;
// sound id and stream id map
private HashMap<Integer,Integer> mSoundIdStreamIdMap;
// sound path and sound id map
private HashMap<String,Integer> mPathSoundIDMap;
private static final String TAG = "Cocos2dxSound";
private static final int MAX_SIMULTANEOUS_STREAMS_DEFAULT = 5;
private static final float SOUND_RATE = 1.0f;
private static final int SOUND_PRIORITY = 1;
private static final int SOUND_QUALITY = 5;
private final int INVALID_SOUND_ID = -1;
private final int INVALID_STREAM_ID = -1;
public Cocos2dxSound(Context context){
this.mContext = context;
initData();
}
public int preloadEffect(String path){
int soundId = INVALID_SOUND_ID;
// if the sound is preloaded, pass it
if (this.mPathSoundIDMap.get(path) != null){
soundId = this.mPathSoundIDMap.get(path).intValue();
} else {
soundId = createSoundIdFromAsset(path);
if (soundId != INVALID_SOUND_ID){
// the sound is loaded but has not been played
this.mSoundIdStreamIdMap.put(soundId, INVALID_STREAM_ID);
// record path and sound id map
this.mPathSoundIDMap.put(path, soundId);
}
}
return soundId;
}
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
@SuppressWarnings("unchecked")
private void pauseOrResumeAllEffects(boolean isPause){
Iterator<?> iter = this.mSoundIdStreamIdMap.entrySet().iterator();
while (iter.hasNext()){
Map.Entry<Integer, Integer> entry = (Map.Entry<Integer, Integer>)iter.next();
int soundId = entry.getKey();
if (isPause) {
this.pauseEffect(soundId);
} else {
this.resumeEffect(soundId);
}
}
}
public void vibrate(long time){
Vibrator v = (Vibrator) mContext.getSystemService(Context.VIBRATOR_SERVICE);
v.vibrate(time);
}
public void vibrateWithPattern(long[] pattern, int repeat){
Vibrator v = (Vibrator) mContext.getSystemService(Context.VIBRATOR_SERVICE);
v.vibrate(pattern, repeat);
}
public void cancelVibrate(){
Vibrator v = (Vibrator) mContext.getSystemService(Context.VIBRATOR_SERVICE);
v.cancel();
}
}
==============
Cocos2dxActivity.java
==============
package org.cocos2dx.lib;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.DisplayMetrics;
import android.util.Log;
public class Cocos2dxActivity extends Activity{
private static Cocos2dxMusic backgroundMusicPlayer;
private static Cocos2dxSound soundPlayer;
private static Cocos2dxAccelerometer accelerometer;
private static boolean accelerometerEnabled = false;
private static Handler handler;
private final static int HANDLER_SHOW_DIALOG = 1;
private static String packageName;
private static native void nativeSetPaths(String apkPath);
//===============
//add url member
//===============
private static Activity meUrl = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//===============
//add url member
//===============
meUrl = this;
// get frame size
DisplayMetrics dm = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dm);
accelerometer = new Cocos2dxAccelerometer(this);
// init media player and sound player
backgroundMusicPlayer = new Cocos2dxMusic(this);
soundPlayer = new Cocos2dxSound(this);
// init bitmap context
Cocos2dxBitmap.setContext(this);
handler = new Handler(){
public void handleMessage(Message msg){
switch(msg.what){
case HANDLER_SHOW_DIALOG:
showDialog(((DialogMessage)msg.obj).title, ((DialogMessage)msg.obj).message);
break;
}
}
};
}
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
public static void terminateProcess(){
android.os.Process.killProcess(android.os.Process.myPid());
}
public static void vibrate(long time){
soundPlayer.vibrate(time);
}
public static void vibrateWithPattern(long pattern[], int repeat){
soundPlayer.vibrateWithPattern(pattern, repeat);
}
public static void cancelVibrate(){
soundPlayer.cancelVibrate();
}
@Override
protected void onResume() {
super.onResume();
if (accelerometerEnabled) {
accelerometer.enable();
}
}
@Override
protected void onPause() {
super.onPause();
if (accelerometerEnabled) {
accelerometer.disable();
}
}
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
2. (사용자 cocos2d-x folder name)\ CocosDenshion\include
è폴더내 SimpleAudioEngine.h 함수 추가, 빨간색 코드 줄
================
SimpleAudioEngine.h
================
#ifndef _SIMPLE_AUDIO_ENGINE_H_
#define _SIMPLE_AUDIO_ENGINE_H_
#include "Export.h"
#include <stddef.h>
namespace CocosDenshion {
/**
@class SimpleAudioEngine
@brief offer a VERY simple interface to play background music & sound effect
*/
class EXPORT_DLL SimpleAudioEngine
{
public:
SimpleAudioEngine();
~SimpleAudioEngine();
/**
@brief Get the shared Engine object,it will new one when first time be called
*/
static SimpleAudioEngine* sharedEngine();
/**
@brief Release the shared Engine object
@warning It must be called before the application exit, or a memroy leak will be casued.
*/
static void end();
/**
@brief Set the zip file name
@param pszZipFileName The relative path of the .zip file
*/
static void setResource(const char* pszZipFileName);
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
/**
@brief preload a compressed audio file
@details the compressed audio will be decode to wave, then write into an
internal buffer in SimpleaudioEngine
*/
void preloadEffect(const char* pszFilePath);
/**
@brief unload the preloaded effect from internal buffer
@param[in] pszFilePath The path of the effect file,or the FileName of T_SoundResInfo
*/
void unloadEffect(const char* pszFilePath);
/**
@brief vibration setting
*/
void vibrate(long long time);
void vibrateWithPattern(long long pattern[], int repeat);
void cancelVibrate();
};
} // end of namespace CocosDenshion
#endif // _SIMPLE_AUDIO_ENGINE_H_
3. (사용자 cocos2d-x folder name)\CocosDenshion\CocosDenshion\android
è폴더 내의 SimpleAudioEngine.cpp
================
SimpleAudioEngine.cpp
================
#include "SimpleAudioEngine.h"
#include "jni/SimpleAudioEngineJni.h"
namespace CocosDenshion
{
static SimpleAudioEngine *s_pEngine = 0;
SimpleAudioEngine::SimpleAudioEngine()
{
}
SimpleAudioEngine::~SimpleAudioEngine()
{
}
SimpleAudioEngine* SimpleAudioEngine::sharedEngine()
{
if (! s_pEngine)
{
s_pEngine = new SimpleAudioEngine();
}
return s_pEngine;
}
void SimpleAudioEngine::end()
{
endJNI();
}
void SimpleAudioEngine::setResource(const char* pszZipFileName)
{
}
void SimpleAudioEngine::preloadBackgroundMusic(const char* pszFilePath)
{
preloadBackgroundMusicJNI(pszFilePath);
}
void SimpleAudioEngine::playBackgroundMusic(const char* pszFilePath, bool bLoop)
{
playBackgroundMusicJNI(pszFilePath, bLoop);
}
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
void SimpleAudioEngine::resumeAllEffects()
{
resumeAllEffectsJNI();
}
void SimpleAudioEngine::stopAllEffects()
{
stopAllEffectsJNI();
}
void SimpleAudioEngine::vibrate(long long time)
{
vibrateJNI(time);
}
void SimpleAudioEngine::vibrateWithPattern(long long pattern[], int repeat)
{
vibrateWithPatternJNI(pattern, repeat);
}
void SimpleAudioEngine::cancelVibrate()
{
cancelVibrateJNI();
}
}
4. (사용자 cocos2d-x folder name)\ CocosDenshion\android\jni
è폴더 내의 SimpleAudioEngineJni.h, SimpleAudioEngineJni.cpp JNI 등록
==================
SimpleAudioEngineJni.h
==================
#ifndef __SIMPLE_AUDIO_ENGINE_JNI__
#define __SIMPLE_AUDIO_ENGINE_JNI__
#include <jni.h>
extern "C"
{
extern void preloadBackgroundMusicJNI(const char *path);
extern void playBackgroundMusicJNI(const char *path, bool isLoop);
extern void stopBackgroundMusicJNI();
extern void pauseBackgroundMusicJNI();
extern void resumeBackgroundMusicJNI();
extern void rewindBackgroundMusicJNI();
extern bool isBackgroundMusicPlayingJNI();
extern float getBackgroundMusicVolumeJNI();
extern void setBackgroundMusicVolumeJNI(float volume);
extern unsigned int playEffectJNI(const char* path, bool bLoop);
extern void stopEffectJNI(unsigned int nSoundId);
extern void endJNI();
extern float getEffectsVolumeJNI();
extern void setEffectsVolumeJNI(float volume);
extern void preloadEffectJNI(const char *path);
extern void unloadEffectJNI(const char* path);
extern void pauseEffectJNI(unsigned int nSoundId);
extern void pauseAllEffectsJNI();
extern void resumeEffectJNI(unsigned int nSoundId);
extern void resumeAllEffectsJNI();
extern void stopAllEffectsJNI();
extern void vibrateJNI(long long time);
extern void vibrateWithPatternJNI(long long pattern[], int repeat);
extern void cancelVibrateJNI();
}
#endif // __SIMPLE_AUDIO_ENGINE_JNI__
==================
SimpleAudioEngineJni.h
==================
#include "SimpleAudioEngineJni.h"
#include <android/log.h>
#define LOG_TAG "libSimpleAudioEngine"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__)
#define CLASS_NAME "org/cocos2dx/lib/Cocos2dxActivity"
typedef struct JniMethodInfo_
{
JNIEnv * env;
jclass classID;
jmethodID methodID;
} JniMethodInfo;
extern "C"
{
static JavaVM *gJavaVM = 0;
jint JNI_OnLoad(JavaVM *vm, void *reserved)
{
gJavaVM = vm;
return JNI_VERSION_1_4;
}
// get env and cache it
static JNIEnv* getJNIEnv(void)
{
JNIEnv *env = 0;
// get jni environment
if (gJavaVM->GetEnv((void**)&env, JNI_VERSION_1_4) != JNI_OK)
{
LOGD("Failed to get the environment using GetEnv()");
}
if (gJavaVM->AttachCurrentThread(&env, 0) < 0)
{
LOGD("Failed to get the environment using AttachCurrentThread()");
}
return env;
}
// get class and make it a global reference, release it at endJni().
static jclass getClassID(JNIEnv *pEnv)
{
jclass ret = pEnv->FindClass(CLASS_NAME);
if (! ret)
{
LOGD("Failed to find class of %s", CLASS_NAME);
}
return ret;
}
static bool getStaticMethodInfo(JniMethodInfo &methodinfo, const char *methodName, const char *paramCode)
{
jmethodID methodID = 0;
JNIEnv *pEnv = 0;
bool bRet = false;
do
{
pEnv = getJNIEnv();
if (! pEnv)
{
break;
}
jclass classID = getClassID(pEnv);
methodID = pEnv->GetStaticMethodID(classID, methodName, paramCode);
if (! methodID)
{
LOGD("Failed to find static method id of %s", methodName);
break;
}
methodinfo.classID = classID;
methodinfo.env = pEnv;
methodinfo.methodID = methodID;
bRet = true;
} while (0);
return bRet;
}
void preloadBackgroundMusicJNI(const char *path)
{
// void playBackgroundMusic(String,boolean)
JniMethodInfo methodInfo;
if (! getStaticMethodInfo(methodInfo, "preloadBackgroundMusic", "(Ljava/lang/String;)V"))
{
return;
}
jstring stringArg = methodInfo.env->NewStringUTF(path);
methodInfo.env->CallStaticVoidMethod(methodInfo.classID, methodInfo.methodID, stringArg);
methodInfo.env->DeleteLocalRef(stringArg);
methodInfo.env->DeleteLocalRef(methodInfo.classID);
}
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
void resumeAllEffectsJNI()
{
// void resumeAllEffects()
JniMethodInfo methodInfo;
if (! getStaticMethodInfo(methodInfo, "resumeAllEffects", "()V"))
{
return ;
}
methodInfo.env->CallStaticVoidMethod(methodInfo.classID, methodInfo.methodID);
methodInfo.env->DeleteLocalRef(methodInfo.classID);
}
void stopAllEffectsJNI()
{
// void stopAllEffects()
JniMethodInfo methodInfo;
if (! getStaticMethodInfo(methodInfo, "stopAllEffects", "()V"))
{
return ;
}
methodInfo.env->CallStaticVoidMethod(methodInfo.classID, methodInfo.methodID);
methodInfo.env->DeleteLocalRef(methodInfo.classID);
}
void vibrateJNI(long long time)
{
JniMethodInfo methodInfo;
if (! getStaticMethodInfo(methodInfo, "vibrate", "(J)V"))
{
return;
}
methodInfo.env->CallStaticVoidMethod(methodInfo.classID, methodInfo.methodID, time);
methodInfo.env->DeleteLocalRef(methodInfo.classID);
}
void vibrateWithPatternJNI(long long pattern[], int repeat)
{
JniMethodInfo methodInfo;
if (! getStaticMethodInfo(methodInfo, "vibrateWithPattern", "([JI)V"))
{
return;
}
int elements = sizeof(pattern);
jlongArray jLongArray = methodInfo.env->NewLongArray(elements);
methodInfo.env->SetLongArrayRegion(jLongArray, 0, elements, (jlong*) pattern);
methodInfo.env->CallStaticVoidMethod(methodInfo.classID, methodInfo.methodID, jLongArray, repeat);
methodInfo.env->DeleteLocalRef(methodInfo.classID);
}
void cancelVibrateJNI()
{
JniMethodInfo methodInfo;
if (! getStaticMethodInfo(methodInfo, "cancelVibrate", "()V"))
{
return;
}
methodInfo.env->CallStaticVoidMethod(methodInfo.classID, methodInfo.methodID);
methodInfo.env->DeleteLocalRef(methodInfo.classID);
}
}
5. AndroidManifest.xml 파일에
è<uses-permission android:name="android.permission.VIBRATE" /> 추가
6. 원하는 곳에서 실행 코드 예
//진동 ===================================================
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
SimpleAudioEngine::sharedEngine()->vibrate(100);
#endif
//========================================================
è당연히 심플오디오엔진에 추가했기 때문에 위와 같이 정의함
vibrate(long long time) : 매개변수 밀리초 동안 진동
vibrateWithPattern(long long pattern[], int repeat) : 일정 패턴대로 반복
pattern è 밀리초 배열, repeatè 반복횟수
cancelVibrate() : 진동끄기
출처 : http://www.cocos2d-x.org/forums/6/topics/8179