add proj.android to samples/SimpleGame, use getVisibleSize & getVisibleOrigin instead of getWinSize

This commit is contained in:
Walzer 2012-09-09 21:41:48 +08:00
parent 7e4615cd7b
commit 11b5ae5cef
55 changed files with 5987 additions and 7 deletions

View File

@ -0,0 +1,57 @@
#include "AppDelegate.h"
#include "cocos2d.h"
#include "HelloWorldScene.h"
USING_NS_CC;
AppDelegate::AppDelegate()
{
}
AppDelegate::~AppDelegate()
{
}
bool AppDelegate::applicationDidFinishLaunching()
{
// initialize director
CCDirector *pDirector = CCDirector::sharedDirector();
pDirector->setOpenGLView(CCEGLView::sharedOpenGLView());
// enable High Resource Mode(2x, such as iphone4) and maintains low resource on other devices.
// pDirector->enableRetinaDisplay(true);
// turn on display FPS
pDirector->setDisplayStats(true);
// set FPS. the default value is 1.0/60 if you don't call this
pDirector->setAnimationInterval(1.0 / 60);
// create a scene. it's an autorelease object
CCScene *pScene = HelloWorld::scene();
// run
pDirector->runWithScene(pScene);
return true;
}
// This function will be called when the app is inactive. When comes a phone call,it's be invoked too
void AppDelegate::applicationDidEnterBackground()
{
CCDirector::sharedDirector()->pause();
// if you use SimpleAudioEngine, it must be pause
// SimpleAudioEngine::sharedEngine()->pauseBackgroundMusic();
}
// this function will be called when the app is active again
void AppDelegate::applicationWillEnterForeground()
{
CCDirector::sharedDirector()->resume();
// if you use SimpleAudioEngine, it must resume here
// SimpleAudioEngine::sharedEngine()->resumeBackgroundMusic();
}

View File

@ -0,0 +1,38 @@
#ifndef _APP_DELEGATE_H_
#define _APP_DELEGATE_H_
#include "CCApplication.h"
/**
@brief The cocos2d Application.
The reason for implement as private inheritance is to hide some interface call by CCDirector.
*/
class AppDelegate : private cocos2d::CCApplication
{
public:
AppDelegate();
virtual ~AppDelegate();
/**
@brief Implement CCDirector and CCScene init code here.
@return true Initialize success, app continue.
@return false Initialize failed, app terminate.
*/
virtual bool applicationDidFinishLaunching();
/**
@brief The function be called when the application enter background
@param the pointer of the application
*/
virtual void applicationDidEnterBackground();
/**
@brief The function be called when the application enter foreground
@param the pointer of the application
*/
virtual void applicationWillEnterForeground();
};
#endif // _APP_DELEGATE_H_

View File

@ -0,0 +1,84 @@
#include "HelloWorldScene.h"
#include "SimpleAudioEngine.h"
using namespace cocos2d;
using namespace CocosDenshion;
CCScene* HelloWorld::scene()
{
// 'scene' is an autorelease object
CCScene *scene = CCScene::create();
// 'layer' is an autorelease object
HelloWorld *layer = HelloWorld::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 HelloWorld::init()
{
//////////////////////////////
// 1. super init first
if ( !CCLayer::init() )
{
return false;
}
/////////////////////////////
// 2. add a menu item with "X" image, which is clicked to quit the program
// you may modify it.
// add a "close" icon to exit the progress. it's an autorelease object
CCMenuItemImage *pCloseItem = CCMenuItemImage::create(
"CloseNormal.png",
"CloseSelected.png",
this,
menu_selector(HelloWorld::menuCloseCallback) );
pCloseItem->setPosition( ccp(CCDirector::sharedDirector()->getWinSize().width - 20, 20) );
// create menu, it's an autorelease object
CCMenu* pMenu = CCMenu::create(pCloseItem, NULL);
pMenu->setPosition( CCPointZero );
this->addChild(pMenu, 1);
/////////////////////////////
// 3. add your codes below...
// add a label shows "Hello World"
// create and initialize a label
CCLabelTTF* pLabel = CCLabelTTF::create("Hello World", "Thonburi", 34);
// ask director the window size
CCSize size = CCDirector::sharedDirector()->getWinSize();
// position the label on the center of the screen
pLabel->setPosition( ccp(size.width / 2, size.height - 20) );
// add the label as a child to this layer
this->addChild(pLabel, 1);
// add "HelloWorld" splash screen"
CCSprite* pSprite = CCSprite::create("HelloWorld.png");
// position the sprite on the center of the screen
pSprite->setPosition( ccp(size.width/2, size.height/2) );
// add the sprite as a child to this layer
this->addChild(pSprite, 0);
return true;
}
void HelloWorld::menuCloseCallback(CCObject* pSender)
{
CCDirector::sharedDirector()->end();
#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
exit(0);
#endif
}

View File

@ -0,0 +1,22 @@
#ifndef __HELLOWORLD_SCENE_H__
#define __HELLOWORLD_SCENE_H__
#include "cocos2d.h"
class HelloWorld : public cocos2d::CCLayer
{
public:
// Here's a difference. Method 'init' in cocos2d-x returns bool, instead of returning 'id' in cocos2d-iphone
virtual bool init();
// there's no 'id' in cpp, so we recommand to return the exactly class pointer
static cocos2d::CCScene* scene();
// a selector callback
void menuCloseCallback(CCObject* pSender);
// implement the "static node()" method manually
CREATE_FUNC(HelloWorld);
};
#endif // __HELLOWORLD_SCENE_H__

View File

@ -0,0 +1 @@
5fe89fb5bd58cedf13b0363f97b20e3ea7ff255d

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="src" path="gen"/>
<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
<classpathentry kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
<classpathentry kind="output" path="bin/classes"/>
</classpath>

View File

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>SimpleGame</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>com.android.ide.eclipse.adt.ApkBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>com.android.ide.eclipse.adt.AndroidNature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

View File

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.cocos2dx.simplegame"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="8"/>
<application android:label="@string/app_name"
android:debuggable="true"
android:icon="@drawable/icon">
<activity android:name=".SimpleGame"
android:label="@string/app_name"
android:screenOrientation="landscape"
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
android:configChanges="orientation">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
<supports-screens android:largeScreens="true"
android:smallScreens="true"
android:anyDensity="true"
android:normalScreens="true"/>
</manifest>

View File

@ -0,0 +1,17 @@
# This file is used to override default values used by the Ant build system.
#
# This file must be checked into Version Control Systems, as it is
# integral to the build system of your project.
# This file is only used by the Ant script.
# You can use this to override default values such as
# 'source.dir' for the location of your java source folder and
# 'out.dir' for the location of your output folder.
# You can also use it define how the release builds are signed by declaring
# the following properties:
# 'key.store' for the location of your keystore and
# 'key.alias' for the name of the key to use.
# The password will be asked during the build when you use the 'release' target.

View File

@ -0,0 +1,92 @@
<?xml version="1.0" encoding="UTF-8"?>
<project name="SimpleGame" default="help">
<!-- The local.properties file is created and updated by the 'android' tool.
It contains the path to the SDK. It should *NOT* be checked into
Version Control Systems. -->
<property file="local.properties" />
<!-- The ant.properties file can be created by you. It is only edited by the
'android' tool to add properties to it.
This is the place to change some Ant specific build properties.
Here are some properties you may want to change/update:
source.dir
The name of the source directory. Default is 'src'.
out.dir
The name of the output directory. Default is 'bin'.
For other overridable properties, look at the beginning of the rules
files in the SDK, at tools/ant/build.xml
Properties related to the SDK location or the project target should
be updated using the 'android' tool with the 'update' action.
This file is an integral part of the build system for your
application and should be checked into Version Control Systems.
-->
<property file="ant.properties" />
<!-- if sdk.dir was not set from one of the property file, then
get it from the ANDROID_HOME env var.
This must be done before we load project.properties since
the proguard config can use sdk.dir -->
<property environment="env" />
<condition property="sdk.dir" value="${env.ANDROID_HOME}">
<isset property="env.ANDROID_HOME" />
</condition>
<!-- The project.properties file is created and updated by the 'android'
tool, as well as ADT.
This contains project specific properties such as project target, and library
dependencies. Lower level build properties are stored in ant.properties
(or in .classpath for Eclipse projects).
This file is an integral part of the build system for your
application and should be checked into Version Control Systems. -->
<loadproperties srcFile="project.properties" />
<!-- quick check on sdk.dir -->
<fail
message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through the ANDROID_HOME environment variable."
unless="sdk.dir"
/>
<!--
Import per project custom build rules if present at the root of the project.
This is the place to put custom intermediary targets such as:
-pre-build
-pre-compile
-post-compile (This is typically used for code obfuscation.
Compiled code location: ${out.classes.absolute.dir}
If this is not done in place, override ${out.dex.input.absolute.dir})
-post-package
-post-build
-pre-clean
-->
<import file="custom_rules.xml" optional="true" />
<!-- Import the actual build file.
To customize existing targets, there are two options:
- Customize only one target:
- copy/paste the target into this file, *before* the
<import> task.
- customize it to your needs.
- Customize the whole content of build.xml
- copy/paste the content of the rules files (minus the top node)
into this file, replacing the <import> task.
- customize to your needs.
***********************
****** IMPORTANT ******
***********************
In all cases you must update the value of version-tag below to read 'custom' instead of an integer,
in order to avoid having your file be overridden by tools such as "android update project"
-->
<!-- version-tag: 1 -->
<import file="${sdk.dir}/tools/ant/build.xml" />
</project>

View File

@ -0,0 +1,91 @@
APPNAME="SimpleGame"
# options
buildexternalsfromsource=
usage(){
cat << EOF
usage: $0 [options]
Build C/C++ code for $APPNAME using Android NDK
OPTIONS:
-s Build externals from source
-h this help
EOF
}
while getopts "sh" OPTION; do
case "$OPTION" in
s)
buildexternalsfromsource=1
;;
h)
usage
exit 0
;;
esac
done
# paths
if [ -z "${NDK_ROOT+aaa}" ];then
echo "please define NDK_ROOT"
exit 1
fi
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
# ... use paths relative to current directory
COCOS2DX_ROOT="$DIR/../.."
APP_ROOT="$DIR/.."
APP_ANDROID_ROOT="$DIR"
echo "NDK_ROOT = $NDK_ROOT"
echo "COCOS2DX_ROOT = $COCOS2DX_ROOT"
echo "APP_ROOT = $APP_ROOT"
echo "APP_ANDROID_ROOT = $APP_ANDROID_ROOT"
# make sure assets is exist
if [ -d "$APP_ANDROID_ROOT"/assets ]; then
rm -rf "$APP_ANDROID_ROOT"/assets
fi
mkdir "$APP_ANDROID_ROOT"/assets
# copy resources
for file in "$APP_ROOT"/Resources/*
do
if [ -d "$file" ]; then
cp -rf "$file" "$APP_ANDROID_ROOT"/assets
fi
if [ -f "$file" ]; then
cp "$file" "$APP_ANDROID_ROOT"/assets
fi
done
# copy icons (if they exist)
file="$APP_ANDROID_ROOT"/assets/Icon-72.png
if [ -f "$file" ]; then
cp "$file" "$APP_ANDROID_ROOT"/res/drawable-hdpi/icon.png
fi
file="$APP_ANDROID_ROOT"/assets/Icon-48.png
if [ -f "$file" ]; then
cp "$file" "$APP_ANDROID_ROOT"/res/drawable-mdpi/icon.png
fi
file="$APP_ANDROID_ROOT"/assets/Icon-32.png
if [ -f "$file" ]; then
cp "$file" "$APP_ANDROID_ROOT"/res/drawable-ldpi/icon.png
fi
if [[ "$buildexternalsfromsource" ]]; then
echo "Building external dependencies from source"
"$NDK_ROOT"/ndk-build -C "$APP_ANDROID_ROOT" $* \
"NDK_MODULE_PATH=${COCOS2DX_ROOT}:${COCOS2DX_ROOT}/cocos2dx/platform/third_party/android/source"
else
echo "Using prebuilt externals"
"$NDK_ROOT"/ndk-build -C "$APP_ANDROID_ROOT" $* \
"NDK_MODULE_PATH=${COCOS2DX_ROOT}:${COCOS2DX_ROOT}/cocos2dx/platform/third_party/android/prebuilt"
fi

View File

@ -0,0 +1,21 @@
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := game_shared
LOCAL_MODULE_FILENAME := libgame
LOCAL_SRC_FILES := hellocpp/main.cpp \
../../Classes/AppDelegate.cpp \
../../Classes/HelloWorldScene.cpp
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../Classes
LOCAL_WHOLE_STATIC_LIBRARIES := cocos2dx_static cocosdenshion_static cocos_extension_static
include $(BUILD_SHARED_LIBRARY)
$(call import-module,CocosDenshion/android) \
$(call import-module,cocos2dx) \
$(call import-module,extensions)

View File

@ -0,0 +1,2 @@
APP_STL := gnustl_static
APP_CPPFLAGS := -frtti

View File

@ -0,0 +1,45 @@
#include "AppDelegate.h"
#include "platform/android/jni/JniHelper.h"
#include <jni.h>
#include <android/log.h>
#include "HelloWorldScene.h"
#define LOG_TAG "main"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__)
using namespace cocos2d;
extern "C"
{
jint JNI_OnLoad(JavaVM *vm, void *reserved)
{
JniHelper::setJavaVM(vm);
return JNI_VERSION_1_4;
}
void Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeInit(JNIEnv* env, jobject thiz, jint w, jint h)
{
if (!CCDirector::sharedDirector()->getOpenGLView())
{
CCEGLView *view = CCEGLView::sharedOpenGLView();
view->setFrameSize(w, h);
AppDelegate *pAppDelegate = new AppDelegate();
CCApplication::sharedApplication()->run();
}
else
{
ccDrawInit();
ccGLInvalidateStateCache();
CCShaderCache::sharedShaderCache()->reloadDefaultShaders();
CCTextureCache::reloadAllTextures();
CCNotificationCenter::sharedNotificationCenter()->postNotification(EVNET_COME_TO_FOREGROUND, NULL);
CCDirector::sharedDirector()->setGLDefaultValues();
}
}
}

View File

@ -0,0 +1,23 @@
#!/bin/bash
append_str=' \'
list_alldir()
{
for file in $1/*
do
if [ -f $file ]; then
echo $file$append_str | grep .cpp
fi
if [ -d $file ]; then
list_alldir $file
fi
done
}
if [ $# -gt 0 ]; then
list_alldir "$1"
else
list_alldir "."
fi

View File

@ -0,0 +1,20 @@
# To enable ProGuard in your project, edit project.properties
# to define the proguard.config property as described in that file.
#
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in ${sdk.dir}/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the ProGuard
# include property in project.properties.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Add any project specific keep options here:
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}

View File

@ -0,0 +1,14 @@
# This file is automatically generated by Android Tools.
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
#
# This file must be checked in Version Control Systems.
#
# To customize properties used by the Ant build system edit
# "ant.properties", and override values to adapt the script to your
# project structure.
#
# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
# Project target.
target=android-8

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">SimpleGame</string>
</resources>

View File

@ -0,0 +1,107 @@
/****************************************************************************
Copyright (c) 2010-2011 cocos2d-x.org
http://www.cocos2d-x.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
package org.cocos2dx.lib;
import android.content.Context;
import android.content.res.Configuration;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.view.Display;
import android.view.Surface;
import android.view.WindowManager;
/**
*
* This class is used for controlling the Accelerometer
*
*/
public class Cocos2dxAccelerometer implements SensorEventListener {
private static final String TAG = "Cocos2dxAccelerometer";
private Context mContext;
private SensorManager mSensorManager;
private Sensor mAccelerometer;
private int mNaturalOrientation;
public Cocos2dxAccelerometer(Context context){
mContext = context;
//Get an instance of the SensorManager
mSensorManager = (SensorManager) mContext.getSystemService(Context.SENSOR_SERVICE);
mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
Display display = ((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
mNaturalOrientation = display.getOrientation();
}
public void enable() {
mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_GAME);
}
public void disable () {
mSensorManager.unregisterListener(this);
}
@Override
public void onSensorChanged(SensorEvent event) {
if (event.sensor.getType() != Sensor.TYPE_ACCELEROMETER){
return;
}
float x = event.values[0];
float y = event.values[1];
float z = event.values[2];
/*
* Because the axes are not swapped when the device's screen orientation changes.
* So we should swap it here.
* In tablets such as Motorola Xoom, the default orientation is landscape, so should
* consider this.
*/
int orientation = mContext.getResources().getConfiguration().orientation;
if ((orientation == Configuration.ORIENTATION_LANDSCAPE) && (mNaturalOrientation != Surface.ROTATION_0)){
float tmp = x;
x = -y;
y = tmp;
}
else if ((orientation == Configuration.ORIENTATION_PORTRAIT) && (mNaturalOrientation != Surface.ROTATION_0))
{
float tmp = x;
x = y;
y = -tmp;
}
onSensorChanged(x, y, z, event.timestamp);
// Log.d(TAG, "x = " + event.values[0] + " y = " + event.values[1] + " z = " + event.values[2]);
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
private static native void onSensorChanged(float x, float y, float z, long timeStamp);
}

View File

@ -0,0 +1,346 @@
/****************************************************************************
Copyright (c) 2010-2012 cocos2d-x.org
http://www.cocos2d-x.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
package org.cocos2dx.lib;
import java.lang.ref.WeakReference;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.AssetManager;
import android.os.Build;
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{
protected Cocos2dxGLSurfaceView mGLView;
private static Cocos2dxMusic backgroundMusicPlayer;
private static Cocos2dxSound soundPlayer;
private static Cocos2dxAccelerometer accelerometer;
private static AssetManager assetManager;
private static boolean accelerometerEnabled = false;
private static Handler handler;
private final static int HANDLER_SHOW_DIALOG = 1;
private final static int HANDLER_SHOW_EDITBOX_DIALOG = 2;
private static String packageName;
private static native void nativeSetPaths(String apkPath);
private static native void nativeSetEditboxText(byte[] text);
static class ShowDialogHandler extends Handler {
WeakReference<Cocos2dxActivity> mActivity;
ShowDialogHandler(Cocos2dxActivity activity) {
mActivity = new WeakReference<Cocos2dxActivity>(activity);
}
@Override
public void handleMessage(Message msg) {
Cocos2dxActivity theActivity = mActivity.get();
switch(msg.what) {
case HANDLER_SHOW_DIALOG:
theActivity.showDialog(((DialogMessage)msg.obj).title, ((DialogMessage)msg.obj).message);
break;
case HANDLER_SHOW_EDITBOX_DIALOG:
theActivity.onShowEditBoxDialog((EditBoxMessage)msg.obj);
break;
}
}
};
public Cocos2dxGLSurfaceView getGLView() {
return mGLView;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 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 asset manager for jni call
assetManager = getAssets();
// init bitmap context
Cocos2dxBitmap.setContext(this);
handler = new ShowDialogHandler(this);
}
public static String getDeviceModel(){
return Build.MODEL;
}
public static AssetManager getAssetManager() {
return assetManager;
}
public static String getCurrentLanguage() {
String languageName = java.util.Locale.getDefault().getLanguage();
return languageName;
}
public static void showMessageBox(String title, String message){
Message msg = new Message();
msg.what = HANDLER_SHOW_DIALOG;
msg.obj = new DialogMessage(title, message);
handler.sendMessage(msg);
}
public static void enableAccelerometer() {
accelerometerEnabled = true;
accelerometer.enable();
}
public static void disableAccelerometer() {
accelerometerEnabled = false;
accelerometer.disable();
}
public static void preloadBackgroundMusic(String path){
backgroundMusicPlayer.preloadBackgroundMusic(path);
}
public static void playBackgroundMusic(String path, boolean isLoop){
backgroundMusicPlayer.playBackgroundMusic(path, isLoop);
}
public static void stopBackgroundMusic(){
backgroundMusicPlayer.stopBackgroundMusic();
}
public static void pauseBackgroundMusic(){
backgroundMusicPlayer.pauseBackgroundMusic();
}
public static void resumeBackgroundMusic(){
backgroundMusicPlayer.resumeBackgroundMusic();
}
public static void rewindBackgroundMusic(){
backgroundMusicPlayer.rewindBackgroundMusic();
}
public static boolean isBackgroundMusicPlaying(){
return backgroundMusicPlayer.isBackgroundMusicPlaying();
}
public static float getBackgroundMusicVolume(){
return backgroundMusicPlayer.getBackgroundVolume();
}
public static void setBackgroundMusicVolume(float volume){
backgroundMusicPlayer.setBackgroundVolume(volume);
}
public static int playEffect(String path, boolean isLoop){
return soundPlayer.playEffect(path, isLoop);
}
public static void stopEffect(int soundId){
soundPlayer.stopEffect(soundId);
}
public static void pauseEffect(int soundId){
soundPlayer.pauseEffect(soundId);
}
public static void resumeEffect(int soundId){
soundPlayer.resumeEffect(soundId);
}
public static float getEffectsVolume(){
return soundPlayer.getEffectsVolume();
}
public static void setEffectsVolume(float volume){
soundPlayer.setEffectsVolume(volume);
}
public static void preloadEffect(String path){
soundPlayer.preloadEffect(path);
}
public static void unloadEffect(String path){
soundPlayer.unloadEffect(path);
}
public static void stopAllEffects(){
soundPlayer.stopAllEffects();
}
public static void pauseAllEffects(){
soundPlayer.pauseAllEffects();
}
public static void resumeAllEffects(){
soundPlayer.resumeAllEffects();
}
public static void end(){
backgroundMusicPlayer.end();
soundPlayer.end();
}
public static String getCocos2dxPackageName(){
return packageName;
}
public static void terminateProcess(){
android.os.Process.killProcess(android.os.Process.myPid());
}
@Override
protected void onResume() {
super.onResume();
if (accelerometerEnabled) {
accelerometer.enable();
}
}
@Override
protected void onPause() {
super.onPause();
if (accelerometerEnabled) {
accelerometer.disable();
}
}
protected void setPackageName(String packageName) {
Cocos2dxActivity.packageName = packageName;
String apkFilePath = "";
ApplicationInfo appInfo = null;
PackageManager packMgmr = getApplication().getPackageManager();
try {
appInfo = packMgmr.getApplicationInfo(packageName, 0);
} catch (NameNotFoundException e) {
e.printStackTrace();
throw new RuntimeException("Unable to locate assets, aborting...");
}
apkFilePath = appInfo.sourceDir;
Log.w("apk path", apkFilePath);
// add this link at the renderer class
nativeSetPaths(apkFilePath);
}
private void showDialog(String title, String message){
Dialog dialog = new AlertDialog.Builder(this)
.setTitle(title)
.setMessage(message)
.setPositiveButton("Ok",
new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface dialog, int whichButton){
}
}).create();
dialog.show();
}
private static void showEditBoxDialog(String title, String content, int inputMode, int inputFlag, int returnType, int maxLength)
{
Message msg = new Message();
msg.what = HANDLER_SHOW_EDITBOX_DIALOG;
msg.obj = new EditBoxMessage(title, content, inputMode, inputFlag, returnType, maxLength);
handler.sendMessage(msg);
}
private void onShowEditBoxDialog(EditBoxMessage msg)
{
Dialog dialog = new Cocos2dxEditBoxDialog(this, msg);
dialog.show();
}
public void setEditBoxResult(String editResult)
{
Log.i("editbox_content", editResult);
try
{
final byte[] bytesUTF8 = editResult.getBytes("UTF8");
// pass utf8 string from editbox activity to native.
// Should invoke native method in GL thread.
mGLView.queueEvent(new Runnable() {
@Override
public void run() {
nativeSetEditboxText(bytesUTF8);
}
});
}
catch (java.io.UnsupportedEncodingException e)
{
e.printStackTrace();
}
}
}
class DialogMessage {
public String title;
public String message;
public DialogMessage(String title, String message){
this.message = message;
this.title = title;
}
}
class EditBoxMessage {
public String title;
public String content;
public int inputMode;
public int inputFlag;
public int returnType;
public int maxLength;
public EditBoxMessage(String title, String content, int inputMode, int inputFlag, int returnType, int maxLength){
this.content = content;
this.title = title;
this.inputMode = inputMode;
this.inputFlag = inputFlag;
this.returnType = returnType;
this.maxLength = maxLength;
}
}

View File

@ -0,0 +1,455 @@
/****************************************************************************
Copyright (c) 2010-2011 cocos2d-x.org
http://www.cocos2d-x.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
package org.cocos2dx.lib;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.LinkedList;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.graphics.Paint.Align;
import android.graphics.Paint.FontMetricsInt;
import android.text.TextPaint;
import android.text.TextUtils;
import android.util.Log;
public class Cocos2dxBitmap{
/*
* The values are the same as cocos2dx/platform/CCImage.h.
*/
private static final int HALIGNCENTER = 3;
private static final int HALIGNLEFT = 1;
private static final int HALIGNRIGHT = 2;
// vertical alignment
private static final int VALIGNTOP = 1;
private static final int VALIGNBOTTOM = 2;
private static final int VALIGNCENTER = 3;
private static Context context;
public static void setContext(Context context){
Cocos2dxBitmap.context = context;
}
/*
* @width: the width to draw, it can be 0
* @height: the height to draw, it can be 0
*/
public static void createTextBitmap(String content, String fontName,
int fontSize, int alignment, int width, int height){
content = refactorString(content);
Paint paint = newPaint(fontName, fontSize, alignment);
TextProperty textProperty = computeTextProperty(content, paint, width, height);
int bitmapTotalHeight = (height == 0 ? textProperty.totalHeight:height);
// Draw text to bitmap
Bitmap bitmap = Bitmap.createBitmap(textProperty.maxWidth,
bitmapTotalHeight, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
// Draw string
FontMetricsInt fm = paint.getFontMetricsInt();
int x = 0;
int y = computeY(fm, height, textProperty.totalHeight, alignment);
String[] lines = textProperty.lines;
for (String line : lines){
x = computeX(paint, line, textProperty.maxWidth, alignment);
canvas.drawText(line, x, y, paint);
y += textProperty.heightPerLine;
}
initNativeObject(bitmap);
}
private static int computeX(Paint paint, String content, int w, int alignment){
int ret = 0;
int hAlignment = alignment & 0x0F;
switch (hAlignment){
case HALIGNCENTER:
ret = w / 2;
break;
// ret = 0
case HALIGNLEFT:
break;
case HALIGNRIGHT:
ret = w;
break;
/*
* Default is align left.
* Should be same as newPaint().
*/
default:
break;
}
return ret;
}
private static int computeY(FontMetricsInt fm, int constrainHeight, int totalHeight, int alignment) {
int y = -fm.top;
if (constrainHeight > totalHeight) {
int vAlignment = (alignment >> 4) & 0x0F;
switch (vAlignment) {
case VALIGNTOP:
y = -fm.top;
break;
case VALIGNCENTER:
y = -fm.top + (constrainHeight - totalHeight)/2;
break;
case VALIGNBOTTOM:
y = -fm.top + (constrainHeight - totalHeight);
break;
default:
break;
}
}
return y;
}
private static class TextProperty{
// The max width of lines
int maxWidth;
// The height of all lines
int totalHeight;
int heightPerLine;
String[] lines;
TextProperty(int w, int h, String[] lines){
this.maxWidth = w;
this.heightPerLine = h;
this.totalHeight = h * lines.length;
this.lines = lines;
}
}
private static TextProperty computeTextProperty(String content, Paint paint,
int maxWidth, int maxHeight){
FontMetricsInt fm = paint.getFontMetricsInt();
int h = (int)Math.ceil(fm.bottom - fm.top);
int maxContentWidth = 0;
String[] lines = splitString(content, maxHeight, maxWidth, paint);
if (maxWidth != 0){
maxContentWidth = maxWidth;
}
else {
/*
* Compute the max width
*/
int temp = 0;
for (String line : lines){
temp = (int)Math.ceil(paint.measureText(line, 0, line.length()));
if (temp > maxContentWidth){
maxContentWidth = temp;
}
}
}
return new TextProperty(maxContentWidth, h, lines);
}
/*
* If maxWidth or maxHeight is not 0,
* split the string to fix the maxWidth and maxHeight.
*/
private static String[] splitString(String content, int maxHeight, int maxWidth,
Paint paint){
String[] lines = content.split("\\n");
String[] ret = null;
FontMetricsInt fm = paint.getFontMetricsInt();
int heightPerLine = (int)Math.ceil(fm.bottom - fm.top);
int maxLines = maxHeight / heightPerLine;
if (maxWidth != 0){
LinkedList<String> strList = new LinkedList<String>();
for (String line : lines){
/*
* The width of line is exceed maxWidth, should divide it into
* two or more lines.
*/
int lineWidth = (int)Math.ceil(paint.measureText(line));
if (lineWidth > maxWidth){
strList.addAll(divideStringWithMaxWidth(paint, line, maxWidth));
}
else{
strList.add(line);
}
/*
* Should not exceed the max height;
*/
if (maxLines > 0 && strList.size() >= maxLines){
break;
}
}
/*
* Remove exceeding lines
*/
if (maxLines > 0 && strList.size() > maxLines){
while (strList.size() > maxLines){
strList.removeLast();
}
}
ret = new String[strList.size()];
strList.toArray(ret);
} else
if (maxHeight != 0 && lines.length > maxLines) {
/*
* Remove exceeding lines
*/
LinkedList<String> strList = new LinkedList<String>();
for (int i = 0; i < maxLines; i++){
strList.add(lines[i]);
}
ret = new String[strList.size()];
strList.toArray(ret);
}
else {
ret = lines;
}
return ret;
}
private static LinkedList<String> divideStringWithMaxWidth(Paint paint, String content,
int width){
int charLength = content.length();
int start = 0;
int tempWidth = 0;
LinkedList<String> strList = new LinkedList<String>();
/*
* Break a String into String[] by the width & should wrap the word
*/
for (int i = 1; i <= charLength; ++i){
tempWidth = (int)Math.ceil(paint.measureText(content, start, i));
if (tempWidth >= width){
int lastIndexOfSpace = content.substring(0, i).lastIndexOf(" ");
if (lastIndexOfSpace != -1 && lastIndexOfSpace > start){
/**
* Should wrap the word
*/
strList.add(content.substring(start, lastIndexOfSpace));
i = lastIndexOfSpace;
}
else {
/*
* Should not exceed the width
*/
if (tempWidth > width){
strList.add(content.substring(start, i - 1));
/*
* compute from previous char
*/
--i;
}
else {
strList.add(content.substring(start, i));
}
}
// remove spaces at the beginning of a new line
while(content.indexOf(i++) == ' ') {
}
start = i;
}
}
/*
* Add the last chars
*/
if (start < charLength){
strList.add(content.substring(start));
}
return strList;
}
private static Paint newPaint(String fontName, int fontSize, int alignment){
Paint paint = new Paint();
paint.setColor(Color.WHITE);
paint.setTextSize(fontSize);
paint.setAntiAlias(true);
/*
* Set type face for paint, now it support .ttf file.
*/
if (fontName.endsWith(".ttf")){
try {
//Typeface typeFace = Typeface.createFromAsset(context.getAssets(), fontName);
Typeface typeFace = Cocos2dxTypefaces.get(context, fontName);
paint.setTypeface(typeFace);
} catch (Exception e){
Log.e("Cocos2dxBitmap",
"error to create ttf type face: " + fontName);
/*
* The file may not find, use system font
*/
paint.setTypeface(Typeface.create(fontName, Typeface.NORMAL));
}
}
else {
paint.setTypeface(Typeface.create(fontName, Typeface.NORMAL));
}
int hAlignment = alignment & 0x0F;
switch (hAlignment){
case HALIGNCENTER:
paint.setTextAlign(Align.CENTER);
break;
case HALIGNLEFT:
paint.setTextAlign(Align.LEFT);
break;
case HALIGNRIGHT:
paint.setTextAlign(Align.RIGHT);
break;
default:
paint.setTextAlign(Align.LEFT);
break;
}
return paint;
}
private static String refactorString(String str){
// Avoid error when content is ""
if (str.compareTo("") == 0){
return " ";
}
/*
* If the font of "\n" is "" or "\n", insert " " in front of it.
*
* For example:
* "\nabc" -> " \nabc"
* "\nabc\n\n" -> " \nabc\n \n"
*/
StringBuilder strBuilder = new StringBuilder(str);
int start = 0;
int index = strBuilder.indexOf("\n");
while (index != -1){
if (index == 0 || strBuilder.charAt(index -1) == '\n'){
strBuilder.insert(start, " ");
start = index + 2;
} else {
start = index + 1;
}
if (start > strBuilder.length() || index == strBuilder.length()){
break;
}
index = strBuilder.indexOf("\n", start);
}
return strBuilder.toString();
}
private static void initNativeObject(Bitmap bitmap){
byte[] pixels = getPixels(bitmap);
if (pixels == null){
return;
}
nativeInitBitmapDC(bitmap.getWidth(), bitmap.getHeight(), pixels);
}
private static byte[] getPixels(Bitmap bitmap){
if (bitmap != null){
byte[] pixels = new byte[bitmap.getWidth() * bitmap.getHeight() * 4];
ByteBuffer buf = ByteBuffer.wrap(pixels);
buf.order(ByteOrder.nativeOrder());
bitmap.copyPixelsToBuffer(buf);
return pixels;
}
return null;
}
private static native void nativeInitBitmapDC(int width, int height, byte[] pixels);
private static int getFontSizeAccordingHeight(int height)
{
Paint paint = new Paint();
Rect bounds = new Rect();
paint.setTypeface(Typeface.DEFAULT);
int incr_text_size = 1;
boolean found_desired_size = false;
while (!found_desired_size) {
paint.setTextSize(incr_text_size);
String text = "SghMNy";
paint.getTextBounds(text, 0, text.length(), bounds);
incr_text_size++;
if (height - bounds.height() <= 2) {
found_desired_size = true;
}
Log.d("font size", "incr size:" + incr_text_size);
}
return incr_text_size;
}
private static String getStringWithEllipsis(String originalText, float width, float fontSize){
if(TextUtils.isEmpty(originalText)){
return "";
}
TextPaint paint = new TextPaint();
paint.setTypeface(Typeface.DEFAULT);
paint.setTextSize(fontSize);
return TextUtils.ellipsize(originalText, paint, width,
TextUtils.TruncateAt.valueOf("END")).toString();
}
}

View File

@ -0,0 +1,338 @@
/****************************************************************************
Copyright (c) 2010-2012 cocos2d-x.org
http://www.cocos2d-x.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
package org.cocos2dx.lib;
import android.app.Dialog;
import android.content.Context;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.os.Handler;
import android.text.InputFilter;
import android.text.InputType;
import android.util.Log;
import android.util.TypedValue;
import android.view.KeyEvent;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.TextView.OnEditorActionListener;
public class Cocos2dxEditBoxDialog extends Dialog {
/**
* The user is allowed to enter any text, including line breaks.
*/
private final int kEditBoxInputModeAny = 0;
/**
* The user is allowed to enter an e-mail address.
*/
private final int kEditBoxInputModeEmailAddr = 1;
/**
* The user is allowed to enter an integer value.
*/
private final int kEditBoxInputModeNumeric = 2;
/**
* The user is allowed to enter a phone number.
*/
private final int kEditBoxInputModePhoneNumber = 3;
/**
* The user is allowed to enter a URL.
*/
private final int kEditBoxInputModeUrl = 4;
/**
* The user is allowed to enter a real number value.
* This extends kEditBoxInputModeNumeric by allowing a decimal point.
*/
private final int kEditBoxInputModeDecimal = 5;
/**
* The user is allowed to enter any text, except for line breaks.
*/
private final int kEditBoxInputModeSingleLine = 6;
/**
* Indicates that the text entered is confidential data that should be
* obscured whenever possible. This implies EDIT_BOX_INPUT_FLAG_SENSITIVE.
*/
private final int kEditBoxInputFlagPassword = 0;
/**
* Indicates that the text entered is sensitive data that the
* implementation must never store into a dictionary or table for use
* in predictive, auto-completing, or other accelerated input schemes.
* A credit card number is an example of sensitive data.
*/
private final int kEditBoxInputFlagSensitive = 1;
/**
* This flag is a hint to the implementation that during text editing,
* the initial letter of each word should be capitalized.
*/
private final int kEditBoxInputFlagInitialCapsWord = 2;
/**
* This flag is a hint to the implementation that during text editing,
* the initial letter of each sentence should be capitalized.
*/
private final int kEditBoxInputFlagInitialCapsSentence = 3;
/**
* Capitalize all characters automatically.
*/
private final int kEditBoxInputFlagInitialCapsAllCharacters = 4;
private final int kKeyboardReturnTypeDefault = 0;
private final int kKeyboardReturnTypeDone = 1;
private final int kKeyboardReturnTypeSend = 2;
private final int kKeyboardReturnTypeSearch = 3;
private final int kKeyboardReturnTypeGo = 4;
//
private EditText mInputEditText = null;
private TextView mTextViewTitle = null;
private int mInputMode = 0;
private int mInputFlag = 0;
private int mReturnType = 0;
private int mMaxLength = -1;
private int mInputFlagConstraints = 0x00000;
private int mInputModeContraints = 0x00000;
private boolean mIsMultiline = false;
private Cocos2dxActivity mParentActivity = null;
private EditBoxMessage mMsg = null;
public Cocos2dxEditBoxDialog(Context context, EditBoxMessage msg) {
//super(context, R.style.Theme_Translucent);
super(context, android.R.style.Theme_Translucent_NoTitleBar_Fullscreen);
// TODO Auto-generated constructor stub
mParentActivity = (Cocos2dxActivity)context;
mMsg = msg;
}
// Converting dips to pixels
private int convertDipsToPixels(float dips)
{
float scale = getContext().getResources().getDisplayMetrics().density;
return Math.round(dips * scale);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
getWindow().setBackgroundDrawable(new ColorDrawable(0x80000000));
LinearLayout layout = new LinearLayout(mParentActivity);
layout.setOrientation(LinearLayout.VERTICAL);
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(ViewGroup.
LayoutParams.FILL_PARENT,ViewGroup.LayoutParams.FILL_PARENT);
mTextViewTitle = new TextView(mParentActivity);
LinearLayout.LayoutParams textviewParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
textviewParams.leftMargin = textviewParams.rightMargin = convertDipsToPixels(10);
mTextViewTitle.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20);
layout.addView(mTextViewTitle, textviewParams);
mInputEditText = new EditText(mParentActivity);
LinearLayout.LayoutParams editTextParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
editTextParams.leftMargin = editTextParams.rightMargin = convertDipsToPixels(10);
layout.addView(mInputEditText, editTextParams);
setContentView(layout, layoutParams);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
mInputMode = mMsg.inputMode;
mInputFlag = mMsg.inputFlag;
mReturnType = mMsg.returnType;
mMaxLength = mMsg.maxLength;
mTextViewTitle.setText(mMsg.title);
mInputEditText.setText(mMsg.content);
int oldImeOptions = mInputEditText.getImeOptions();
mInputEditText.setImeOptions(oldImeOptions | EditorInfo.IME_FLAG_NO_EXTRACT_UI);
oldImeOptions = mInputEditText.getImeOptions();
switch (mInputMode)
{
case kEditBoxInputModeAny:
mInputModeContraints =
InputType.TYPE_CLASS_TEXT |
InputType.TYPE_TEXT_FLAG_MULTI_LINE;
break;
case kEditBoxInputModeEmailAddr:
mInputModeContraints =
InputType.TYPE_CLASS_TEXT |
InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS;
break;
case kEditBoxInputModeNumeric:
mInputModeContraints =
InputType.TYPE_CLASS_NUMBER |
InputType.TYPE_NUMBER_FLAG_SIGNED;
break;
case kEditBoxInputModePhoneNumber:
mInputModeContraints = InputType.TYPE_CLASS_PHONE;
break;
case kEditBoxInputModeUrl:
mInputModeContraints =
InputType.TYPE_CLASS_TEXT |
InputType.TYPE_TEXT_VARIATION_URI;
break;
case kEditBoxInputModeDecimal:
mInputModeContraints =
InputType.TYPE_CLASS_NUMBER |
InputType.TYPE_NUMBER_FLAG_DECIMAL |
InputType.TYPE_NUMBER_FLAG_SIGNED;
break;
case kEditBoxInputModeSingleLine:
mInputModeContraints = InputType.TYPE_CLASS_TEXT;
break;
default:
break;
}
if ( mIsMultiline ) {
mInputModeContraints |= InputType.TYPE_TEXT_FLAG_MULTI_LINE;
}
mInputEditText.setInputType(mInputModeContraints | mInputFlagConstraints);
switch (mInputFlag)
{
case kEditBoxInputFlagPassword:
mInputFlagConstraints = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD;
break;
case kEditBoxInputFlagSensitive:
mInputFlagConstraints = InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS;
break;
case kEditBoxInputFlagInitialCapsWord:
mInputFlagConstraints = InputType.TYPE_TEXT_FLAG_CAP_WORDS;
break;
case kEditBoxInputFlagInitialCapsSentence:
mInputFlagConstraints = InputType.TYPE_TEXT_FLAG_CAP_SENTENCES;
break;
case kEditBoxInputFlagInitialCapsAllCharacters:
mInputFlagConstraints = InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS;
break;
default:
break;
}
mInputEditText.setInputType(mInputFlagConstraints | mInputModeContraints);
switch (mReturnType) {
case kKeyboardReturnTypeDefault:
mInputEditText.setImeOptions(oldImeOptions | EditorInfo.IME_ACTION_NONE);
break;
case kKeyboardReturnTypeDone:
mInputEditText.setImeOptions(oldImeOptions | EditorInfo.IME_ACTION_DONE);
break;
case kKeyboardReturnTypeSend:
mInputEditText.setImeOptions(oldImeOptions | EditorInfo.IME_ACTION_SEND);
break;
case kKeyboardReturnTypeSearch:
mInputEditText.setImeOptions(oldImeOptions | EditorInfo.IME_ACTION_SEARCH);
break;
case kKeyboardReturnTypeGo:
mInputEditText.setImeOptions(oldImeOptions | EditorInfo.IME_ACTION_GO);
break;
default:
mInputEditText.setImeOptions(oldImeOptions | EditorInfo.IME_ACTION_NONE);
break;
}
if (mMaxLength > 0) {
mInputEditText.setFilters(
new InputFilter[] {
new InputFilter.LengthFilter(mMaxLength)
}
);
}
Handler initHandler = new Handler();
initHandler.postDelayed(new Runnable() {
public void run() {
mInputEditText.requestFocus();
mInputEditText.setSelection(mInputEditText.length());
openKeyboard();
}
}, 200);
mInputEditText.setOnEditorActionListener(new OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
// if user didn't set keyboard type,
// this callback will be invoked twice with 'KeyEvent.ACTION_DOWN' and 'KeyEvent.ACTION_UP'
if (actionId != EditorInfo.IME_NULL
|| (actionId == EditorInfo.IME_NULL
&& event != null
&& event.getAction() == KeyEvent.ACTION_DOWN))
{
//Log.d("EditBox", "actionId: "+actionId +",event: "+event);
mParentActivity.setEditBoxResult(mInputEditText.getText().toString());
closeKeyboard();
dismiss();
return true;
}
return false;
}
});
}
private void openKeyboard() {
InputMethodManager imm = (InputMethodManager) mParentActivity.getSystemService(Context.INPUT_METHOD_SERVICE);
imm.showSoftInput(mInputEditText, 0);
Log.d("Cocos2dxEditBox", "openKeyboard");
}
private void closeKeyboard() {
InputMethodManager imm = (InputMethodManager) mParentActivity.getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(mInputEditText.getWindowToken(), 0);
Log.d("Cocos2dxEditBox", "closeKeyboard");
}
@Override
protected void onStop() {
// TODO Auto-generated method stub
super.onStop();
Log.d("EditBox", "onStop...");
}
}

View File

@ -0,0 +1,65 @@
/****************************************************************************
Copyright (c) 2012 cocos2d-x.org
http://www.cocos2d-x.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
package org.cocos2dx.lib;
import android.content.Context;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.widget.EditText;
public class Cocos2dxEditText extends EditText {
private Cocos2dxGLSurfaceView mView;
public Cocos2dxEditText(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
public Cocos2dxEditText(Context context, AttributeSet attrs) {
super(context, attrs);
}
public Cocos2dxEditText(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public void setMainView(Cocos2dxGLSurfaceView glSurfaceView) {
mView = glSurfaceView;
}
/*
* Let GlSurfaceView get focus if back key is input
*/
public boolean onKeyDown(int keyCode, KeyEvent event) {
super.onKeyDown(keyCode, event);
if (keyCode == KeyEvent.KEYCODE_BACK) {
mView.requestFocus();
}
return true;
}
}

View File

@ -0,0 +1,417 @@
/****************************************************************************
Copyright (c) 2010-2011 cocos2d-x.org
http://www.cocos2d-x.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
package org.cocos2dx.lib;
import android.content.Context;
import android.opengl.GLSurfaceView;
import android.os.Handler;
import android.os.Message;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.AttributeSet;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.inputmethod.InputMethodManager;
import android.widget.TextView;
import android.widget.TextView.OnEditorActionListener;
class TextInputWraper implements TextWatcher, OnEditorActionListener {
private static final Boolean debug = false;
private void LogD(String msg) {
if (debug) Log.d("TextInputFilter", msg);
}
private Cocos2dxGLSurfaceView mMainView;
private String mText;
private String mOriginText;
private Boolean isFullScreenEdit() {
InputMethodManager imm = (InputMethodManager)mMainView.getTextField().getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
return imm.isFullscreenMode();
}
public TextInputWraper(Cocos2dxGLSurfaceView view) {
mMainView = view;
}
public void setOriginText(String text) {
mOriginText = text;
}
@Override
public void afterTextChanged(Editable s) {
if (isFullScreenEdit()) {
return;
}
LogD("afterTextChanged: " + s);
int nModified = s.length() - mText.length();
if (nModified > 0) {
final String insertText = s.subSequence(mText.length(), s.length()).toString();
mMainView.insertText(insertText);
LogD("insertText(" + insertText + ")");
}
else {
for (; nModified < 0; ++nModified) {
mMainView.deleteBackward();
LogD("deleteBackward");
}
}
mText = s.toString();
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
LogD("beforeTextChanged(" + s + ")start: " + start + ",count: " + count + ",after: " + after);
mText = s.toString();
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (mMainView.getTextField() == v && isFullScreenEdit()) {
// user press the action button, delete all old text and insert new text
for (int i = mOriginText.length(); i > 0; --i) {
mMainView.deleteBackward();
LogD("deleteBackward");
}
String text = v.getText().toString();
/*
* If user input nothing, translate "\n" to engine.
*/
if (text.compareTo("") == 0){
text = "\n";
}
if ('\n' != text.charAt(text.length() - 1)) {
text += '\n';
}
final String insertText = text;
mMainView.insertText(insertText);
LogD("insertText(" + insertText + ")");
}
return false;
}
}
public class Cocos2dxGLSurfaceView extends GLSurfaceView {
static private Cocos2dxGLSurfaceView mainView;
private static final String TAG = Cocos2dxGLSurfaceView.class.getCanonicalName();
private Cocos2dxRenderer mRenderer;
private static final boolean debug = false;
///////////////////////////////////////////////////////////////////////////
// for initialize
///////////////////////////////////////////////////////////////////////////
public Cocos2dxGLSurfaceView(Context context) {
super(context);
initView();
}
public Cocos2dxGLSurfaceView(Context context, AttributeSet attrs) {
super(context, attrs);
initView();
}
public void setCocos2dxRenderer(Cocos2dxRenderer renderer){
mRenderer = renderer;
setRenderer(mRenderer);
}
protected void initView() {
setFocusableInTouchMode(true);
textInputWraper = new TextInputWraper(this);
handler = new Handler(){
public void handleMessage(Message msg){
switch(msg.what){
case HANDLER_OPEN_IME_KEYBOARD:
if (null != mTextField && mTextField.requestFocus()) {
mTextField.removeTextChangedListener(textInputWraper);
mTextField.setText("");
String text = (String)msg.obj;
mTextField.append(text);
textInputWraper.setOriginText(text);
mTextField.addTextChangedListener(textInputWraper);
InputMethodManager imm = (InputMethodManager)mainView.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
imm.showSoftInput(mTextField, 0);
Log.d("GLSurfaceView", "showSoftInput");
}
break;
case HANDLER_CLOSE_IME_KEYBOARD:
if (null != mTextField) {
mTextField.removeTextChangedListener(textInputWraper);
InputMethodManager imm = (InputMethodManager)mainView.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(mTextField.getWindowToken(), 0);
Log.d("GLSurfaceView", "HideSoftInput");
}
break;
}
}
};
mainView = this;
}
public void onPause(){
queueEvent(new Runnable() {
@Override
public void run() {
mRenderer.handleOnPause();
}
});
super.onPause();
}
public void onResume(){
super.onResume();
queueEvent(new Runnable() {
@Override
public void run() {
mRenderer.handleOnResume();
}
});
}
///////////////////////////////////////////////////////////////////////////
// for text input
///////////////////////////////////////////////////////////////////////////
private final static int HANDLER_OPEN_IME_KEYBOARD = 2;
private final static int HANDLER_CLOSE_IME_KEYBOARD = 3;
private static Handler handler;
private static TextInputWraper textInputWraper;
private Cocos2dxEditText mTextField;
public TextView getTextField() {
return mTextField;
}
public void setTextField(Cocos2dxEditText view) {
mTextField = view;
if (null != mTextField && null != textInputWraper) {
mTextField.setOnEditorActionListener(textInputWraper);
mTextField.setMainView(this);
this.requestFocus();
}
}
public static void openIMEKeyboard() {
Message msg = new Message();
msg.what = HANDLER_OPEN_IME_KEYBOARD;
msg.obj = mainView.getContentText();
handler.sendMessage(msg);
}
private String getContentText() {
return mRenderer.getContentText();
}
public static void closeIMEKeyboard() {
Message msg = new Message();
msg.what = HANDLER_CLOSE_IME_KEYBOARD;
handler.sendMessage(msg);
}
public void insertText(final String text) {
queueEvent(new Runnable() {
@Override
public void run() {
mRenderer.handleInsertText(text);
}
});
}
public void deleteBackward() {
queueEvent(new Runnable() {
@Override
public void run() {
mRenderer.handleDeleteBackward();
}
});
}
///////////////////////////////////////////////////////////////////////////
// for touch event
///////////////////////////////////////////////////////////////////////////
public boolean onTouchEvent(final MotionEvent event) {
// these data are used in ACTION_MOVE and ACTION_CANCEL
final int pointerNumber = event.getPointerCount();
final int[] ids = new int[pointerNumber];
final float[] xs = new float[pointerNumber];
final float[] ys = new float[pointerNumber];
for (int i = 0; i < pointerNumber; i++) {
ids[i] = event.getPointerId(i);
xs[i] = event.getX(i);
ys[i] = event.getY(i);
}
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_POINTER_DOWN:
final int indexPointerDown = event.getAction() >> MotionEvent.ACTION_POINTER_ID_SHIFT;
final int idPointerDown = event.getPointerId(indexPointerDown);
final float xPointerDown = event.getX(indexPointerDown);
final float yPointerDown = event.getY(indexPointerDown);
queueEvent(new Runnable() {
@Override
public void run() {
mRenderer.handleActionDown(idPointerDown, xPointerDown, yPointerDown);
}
});
break;
case MotionEvent.ACTION_DOWN:
// there are only one finger on the screen
final int idDown = event.getPointerId(0);
final float xDown = xs[0];
final float yDown = ys[0];
queueEvent(new Runnable() {
@Override
public void run() {
mRenderer.handleActionDown(idDown, xDown, yDown);
}
});
break;
case MotionEvent.ACTION_MOVE:
queueEvent(new Runnable() {
@Override
public void run() {
mRenderer.handleActionMove(ids, xs, ys);
}
});
break;
case MotionEvent.ACTION_POINTER_UP:
final int indexPointUp = event.getAction() >> MotionEvent.ACTION_POINTER_ID_SHIFT;
final int idPointerUp = event.getPointerId(indexPointUp);
final float xPointerUp = event.getX(indexPointUp);
final float yPointerUp = event.getY(indexPointUp);
queueEvent(new Runnable() {
@Override
public void run() {
mRenderer.handleActionUp(idPointerUp, xPointerUp, yPointerUp);
}
});
break;
case MotionEvent.ACTION_UP:
// there are only one finger on the screen
final int idUp = event.getPointerId(0);
final float xUp = xs[0];
final float yUp = ys[0];
queueEvent(new Runnable() {
@Override
public void run() {
mRenderer.handleActionUp(idUp, xUp, yUp);
}
});
break;
case MotionEvent.ACTION_CANCEL:
queueEvent(new Runnable() {
@Override
public void run() {
mRenderer.handleActionCancel(ids, xs, ys);
}
});
break;
}
if (debug){
dumpEvent(event);
}
return true;
}
/*
* This function is called before Cocos2dxRenderer.nativeInit(), so the width and height is correct.
*/
protected void onSizeChanged(int w, int h, int oldw, int oldh){
this.mRenderer.setScreenWidthAndHeight(w, h);
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
final int kc = keyCode;
if (keyCode == KeyEvent.KEYCODE_BACK || keyCode == KeyEvent.KEYCODE_MENU) {
queueEvent(new Runnable() {
@Override
public void run() {
mRenderer.handleKeyDown(kc);
}
});
return true;
}
return super.onKeyDown(keyCode, event);
}
// Show an event in the LogCat view, for debugging
private void dumpEvent(MotionEvent event) {
String names[] = { "DOWN" , "UP" , "MOVE" , "CANCEL" , "OUTSIDE" ,
"POINTER_DOWN" , "POINTER_UP" , "7?" , "8?" , "9?" };
StringBuilder sb = new StringBuilder();
int action = event.getAction();
int actionCode = action & MotionEvent.ACTION_MASK;
sb.append("event ACTION_" ).append(names[actionCode]);
if (actionCode == MotionEvent.ACTION_POINTER_DOWN
|| actionCode == MotionEvent.ACTION_POINTER_UP) {
sb.append("(pid " ).append(
action >> MotionEvent.ACTION_POINTER_ID_SHIFT);
sb.append(")" );
}
sb.append("[" );
for (int i = 0; i < event.getPointerCount(); i++) {
sb.append("#" ).append(i);
sb.append("(pid " ).append(event.getPointerId(i));
sb.append(")=" ).append((int) event.getX(i));
sb.append("," ).append((int) event.getY(i));
if (i + 1 < event.getPointerCount())
sb.append(";" );
}
sb.append("]" );
Log.d(TAG, sb.toString());
}
}

View File

@ -0,0 +1,228 @@
/****************************************************************************
Copyright (c) 2010-2011 cocos2d-x.org
http://www.cocos2d-x.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
package org.cocos2dx.lib;
import android.content.Context;
import android.content.res.AssetFileDescriptor;
import android.media.MediaPlayer;
import android.util.Log;
/**
*
* This class is used for controlling background music
*
*/
public class Cocos2dxMusic {
private static final String TAG = "Cocos2dxMusic";
private float mLeftVolume;
private float mRightVolume;
private Context mContext;
private MediaPlayer mBackgroundMediaPlayer;
private boolean mIsPaused;
private String mCurrentPath;
public Cocos2dxMusic(Context context){
this.mContext = context;
initData();
}
public void preloadBackgroundMusic(String path){
if ((mCurrentPath == null) || (! mCurrentPath.equals(path))){
// preload new background music
// release old resource and create a new one
if (mBackgroundMediaPlayer != null){
mBackgroundMediaPlayer.release();
}
mBackgroundMediaPlayer = createMediaplayerFromAssets(path);
// record the path
mCurrentPath = path;
}
}
public void playBackgroundMusic(String path, boolean isLoop){
if (mCurrentPath == null){
// it is the first time to play background music
// or end() was called
mBackgroundMediaPlayer = createMediaplayerFromAssets(path);
mCurrentPath = path;
}
else {
if (! mCurrentPath.equals(path)){
// play new background music
// release old resource and create a new one
if (mBackgroundMediaPlayer != null){
mBackgroundMediaPlayer.release();
}
mBackgroundMediaPlayer = createMediaplayerFromAssets(path);
// record the path
mCurrentPath = path;
}
}
if (mBackgroundMediaPlayer == null){
Log.e(TAG, "playBackgroundMusic: background media player is null");
} else {
// if the music is playing or paused, stop it
mBackgroundMediaPlayer.stop();
mBackgroundMediaPlayer.setLooping(isLoop);
try {
mBackgroundMediaPlayer.prepare();
mBackgroundMediaPlayer.seekTo(0);
mBackgroundMediaPlayer.start();
this.mIsPaused = false;
} catch (Exception e){
Log.e(TAG, "playBackgroundMusic: error state");
}
}
}
public void stopBackgroundMusic(){
if (mBackgroundMediaPlayer != null){
mBackgroundMediaPlayer.stop();
// should set the state, if not , the following sequence will be error
// play -> pause -> stop -> resume
this.mIsPaused = false;
}
}
public void pauseBackgroundMusic(){
if (mBackgroundMediaPlayer != null && mBackgroundMediaPlayer.isPlaying()){
mBackgroundMediaPlayer.pause();
this.mIsPaused = true;
}
}
public void resumeBackgroundMusic(){
if (mBackgroundMediaPlayer != null && this.mIsPaused){
mBackgroundMediaPlayer.start();
this.mIsPaused = false;
}
}
public void rewindBackgroundMusic(){
if (mBackgroundMediaPlayer != null){
mBackgroundMediaPlayer.stop();
try {
mBackgroundMediaPlayer.prepare();
mBackgroundMediaPlayer.seekTo(0);
mBackgroundMediaPlayer.start();
this.mIsPaused = false;
} catch (Exception e){
Log.e(TAG, "rewindBackgroundMusic: error state");
}
}
}
public boolean isBackgroundMusicPlaying(){
boolean ret = false;
if (mBackgroundMediaPlayer == null){
ret = false;
} else {
ret = mBackgroundMediaPlayer.isPlaying();
}
return ret;
}
public void end(){
if (mBackgroundMediaPlayer != null){
mBackgroundMediaPlayer.release();
}
initData();
}
public float getBackgroundVolume(){
if (this.mBackgroundMediaPlayer != null){
return (this.mLeftVolume + this.mRightVolume) / 2;
} else {
return 0.0f;
}
}
public void setBackgroundVolume(float volume){
if (volume < 0.0f){
volume = 0.0f;
}
if (volume > 1.0f){
volume = 1.0f;
}
this.mLeftVolume = this.mRightVolume = volume;
if (this.mBackgroundMediaPlayer != null){
this.mBackgroundMediaPlayer.setVolume(this.mLeftVolume, this.mRightVolume);
}
}
private void initData(){
mLeftVolume =0.5f;
mRightVolume = 0.5f;
mBackgroundMediaPlayer = null;
mIsPaused = false;
mCurrentPath = null;
}
/**
* create mediaplayer for music
* @param path the path relative to assets
* @return
*/
private MediaPlayer createMediaplayerFromAssets(String path){
MediaPlayer mediaPlayer = new MediaPlayer();
try{
if (path.startsWith("/")) {
mediaPlayer.setDataSource(path);
}
else {
AssetFileDescriptor assetFileDescritor = mContext.getAssets().openFd(path);
mediaPlayer.setDataSource(assetFileDescritor.getFileDescriptor(),
assetFileDescritor.getStartOffset(), assetFileDescritor.getLength());
}
mediaPlayer.prepare();
mediaPlayer.setVolume(mLeftVolume, mRightVolume);
}catch (Exception e) {
mediaPlayer = null;
Log.e(TAG, "error: " + e.getMessage(), e);
}
return mediaPlayer;
}
}

View File

@ -0,0 +1,137 @@
/****************************************************************************
Copyright (c) 2010-2011 cocos2d-x.org
http://www.cocos2d-x.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
package org.cocos2dx.lib;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import android.opengl.GLSurfaceView;
public class Cocos2dxRenderer implements GLSurfaceView.Renderer {
private final static long NANOSECONDSPERSECOND = 1000000000L;
private final static long NANOSECONDSPERMINISECOND = 1000000;
private static long animationInterval = (long)(1.0 / 60 * NANOSECONDSPERSECOND);
private long last;
private int screenWidth;
private int screenHeight;
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
nativeInit(screenWidth, screenHeight);
last = System.nanoTime();
}
public void setScreenWidthAndHeight(int w, int h){
this.screenWidth = w;
this.screenHeight = h;
}
public void onSurfaceChanged(GL10 gl, int w, int h) {
}
public void onDrawFrame(GL10 gl) {
long now = System.nanoTime();
long interval = now - last;
// should render a frame when onDrawFrame() is called
// or there is a "ghost"
nativeRender();
// fps controlling
if (interval < animationInterval){
try {
// because we render it before, so we should sleep twice time interval
Thread.sleep((animationInterval - interval) * 2 / NANOSECONDSPERMINISECOND);
} catch (Exception e){}
}
last = now;
}
public void handleActionDown(int id, float x, float y)
{
nativeTouchesBegin(id, x, y);
}
public void handleActionUp(int id, float x, float y)
{
nativeTouchesEnd(id, x, y);
}
public void handleActionCancel(int[] id, float[] x, float[] y)
{
nativeTouchesCancel(id, x, y);
}
public void handleActionMove(int[] id, float[] x, float[] y)
{
nativeTouchesMove(id, x, y);
}
public void handleKeyDown(int keyCode)
{
nativeKeyDown(keyCode);
}
public void handleOnPause(){
nativeOnPause();
}
public void handleOnResume(){
nativeOnResume();
}
public static void setAnimationInterval(double interval){
animationInterval = (long)(interval * NANOSECONDSPERSECOND);
}
private static native void nativeTouchesBegin(int id, float x, float y);
private static native void nativeTouchesEnd(int id, float x, float y);
private static native void nativeTouchesMove(int[] id, float[] x, float[] y);
private static native void nativeTouchesCancel(int[] id, float[] x, float[] y);
private static native boolean nativeKeyDown(int keyCode);
private static native void nativeRender();
private static native void nativeInit(int w, int h);
private static native void nativeOnPause();
private static native void nativeOnResume();
/////////////////////////////////////////////////////////////////////////////////
// handle input method edit message
/////////////////////////////////////////////////////////////////////////////////
public void handleInsertText(final String text) {
nativeInsertText(text);
}
public void handleDeleteBackward() {
nativeDeleteBackward();
}
public String getContentText() {
return nativeGetContentText();
}
private static native void nativeInsertText(String text);
private static native void nativeDeleteBackward();
private static native String nativeGetContentText();
}

View File

@ -0,0 +1,245 @@
/****************************************************************************
Copyright (c) 2010-2011 cocos2d-x.org
http://www.cocos2d-x.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
package org.cocos2dx.lib;
import java.util.ArrayList;
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;
/**
*
* This class is used for controlling effect
*
*/
public class Cocos2dxSound {
private Context mContext;
private SoundPool mSoundPool;
private float mLeftVolume;
private float mRightVolume;
// sound path and stream ids map
// a file may be played many times at the same time
// so there is an array map to a file path
private HashMap<String,ArrayList<Integer>> mPathStreamIDsMap;
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 static int INVALID_SOUND_ID = -1;
private final static int INVALID_STREAM_ID = -1;
public Cocos2dxSound(Context context){
this.mContext = context;
initData();
}
public int preloadEffect(String path){
Integer soundID = this.mPathSoundIdMap.get(path);
if (soundID == null) {
soundID = createSoundIdFromAsset(path);
this.mPathSoundIdMap.put(path, soundID);
}
return soundID;
}
public void unloadEffect(String path){
// stop effects
ArrayList<Integer> streamIDs = this.mPathStreamIDsMap.get(path);
if (streamIDs != null) {
for (Integer streamID : streamIDs) {
this.mSoundPool.stop(streamID);
}
}
this.mPathStreamIDsMap.remove(path);
// unload effect
Integer soundID = this.mPathSoundIdMap.get(path);
this.mSoundPool.unload(soundID);
this.mPathSoundIdMap.remove(path);
}
public int playEffect(String path, boolean isLoop){
Integer soundId = this.mPathSoundIdMap.get(path);
int streamId = INVALID_STREAM_ID;
if (soundId != null){
// play sound
streamId = this.mSoundPool.play(soundId.intValue(), this.mLeftVolume,
this.mRightVolume, SOUND_PRIORITY, isLoop ? -1 : 0, SOUND_RATE);
// record stream id
ArrayList<Integer> streamIds = this.mPathStreamIDsMap.get(path);
if (streamIds == null) {
streamIds = new ArrayList<Integer>();
this.mPathStreamIDsMap.put(path, streamIds);
}
streamIds.add(streamId);
} else {
// the effect is not prepared
soundId = preloadEffect(path);
if (soundId == INVALID_SOUND_ID){
// can not preload effect
return INVALID_SOUND_ID;
}
/*
* Someone reports that, it can not play effect for the
* first time. If you are lucky to meet it. There are two
* ways to resolve it.
* 1. Add some delay here. I don't know how long it is, so
* I don't add it here.
* 2. If you use 2.2(API level 8), you can call
* SoundPool.setOnLoadCompleteListener() to play the effect.
* Because the method is supported from 2.2, so I can't use
* it here.
*/
playEffect(path, isLoop);
}
return streamId;
}
public void stopEffect(int streamID){
this.mSoundPool.stop(streamID);
// remove record
for (String path : this.mPathStreamIDsMap.keySet()) {
if (this.mPathStreamIDsMap.get(path).contains(streamID)) {
this.mPathStreamIDsMap.get(path).remove(this.mPathStreamIDsMap.get(path).indexOf(streamID));
break;
}
}
}
public void pauseEffect(int streamID){
this.mSoundPool.pause(streamID);
}
public void resumeEffect(int streamID){
this.mSoundPool.resume(streamID);
}
public void pauseAllEffects(){
this.mSoundPool.autoPause();
}
public void resumeAllEffects(){
// autoPause() is available since level 8
this.mSoundPool.autoResume();
}
@SuppressWarnings("unchecked")
public void stopAllEffects(){
// stop effects
if (! this.mPathStreamIDsMap.isEmpty()) {
Iterator<?> iter = this.mPathStreamIDsMap.entrySet().iterator();
while (iter.hasNext()){
Map.Entry<String, ArrayList<Integer>> entry = (Map.Entry<String, ArrayList<Integer>>)iter.next();
for (int streamID : entry.getValue()) {
this.mSoundPool.stop(streamID);
}
}
}
// remove records
this.mPathStreamIDsMap.clear();
}
public float getEffectsVolume(){
return (this.mLeftVolume + this.mRightVolume) / 2;
}
@SuppressWarnings("unchecked")
public void setEffectsVolume(float volume){
// volume should be in [0, 1.0]
if (volume < 0){
volume = 0;
}
if (volume > 1){
volume = 1;
}
this.mLeftVolume = this.mRightVolume = volume;
// change the volume of playing sounds
if (! this.mPathStreamIDsMap.isEmpty()) {
Iterator<?> iter = this.mPathStreamIDsMap.entrySet().iterator();
while (iter.hasNext()){
Map.Entry<String, ArrayList<Integer>> entry = (Map.Entry<String, ArrayList<Integer>>)iter.next();
for (int streamID : entry.getValue()) {
this.mSoundPool.setVolume(streamID, mLeftVolume, mRightVolume);
}
}
}
}
public void end(){
this.mSoundPool.release();
this.mPathStreamIDsMap.clear();
this.mPathSoundIdMap.clear();
initData();
}
public int createSoundIdFromAsset(String path){
int soundId = INVALID_SOUND_ID;
try {
if (path.startsWith("/")){
soundId = mSoundPool.load(path, 0);
}
else {
soundId = mSoundPool.load(mContext.getAssets().openFd(path), 0);
}
} catch(Exception e){
soundId = INVALID_SOUND_ID;
Log.e(TAG, "error: " + e.getMessage(), e);
}
return soundId;
}
private void initData(){
this.mPathStreamIDsMap = new HashMap<String,ArrayList<Integer>>();
this.mPathSoundIdMap = new HashMap<String, Integer>();
mSoundPool = new SoundPool(MAX_SIMULTANEOUS_STREAMS_DEFAULT, AudioManager.STREAM_MUSIC, SOUND_QUALITY);
this.mLeftVolume = 0.5f;
this.mRightVolume = 0.5f;
}
}

View File

@ -0,0 +1,44 @@
/****************************************************************************
Copyright (c) 2010-2011 cocos2d-x.org
http://www.cocos2d-x.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
package org.cocos2dx.lib;
import java.util.Hashtable;
import android.content.Context;
import android.graphics.Typeface;
public class Cocos2dxTypefaces {
private static final Hashtable<String, Typeface> cache = new Hashtable<String, Typeface>();
public static Typeface get(Context context, String name){
synchronized(cache){
if (! cache.containsKey(name)){
Typeface t = Typeface.createFromAsset(context.getAssets(), name);
cache.put(name, t);
}
return cache.get(name);
}
}
}

View File

@ -0,0 +1,108 @@
/****************************************************************************
Copyright (c) 2010-2012 cocos2d-x.org
http://www.cocos2d-x.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
package org.cocos2dx.simplegame;
import org.cocos2dx.lib.Cocos2dxActivity;
import org.cocos2dx.lib.Cocos2dxEditText;
import org.cocos2dx.lib.Cocos2dxGLSurfaceView;
import org.cocos2dx.lib.Cocos2dxRenderer;
import android.app.ActivityManager;
import android.content.Context;
import android.content.pm.ConfigurationInfo;
import android.os.Bundle;
import android.util.Log;
import android.widget.FrameLayout;
import android.view.ViewGroup;
public class SimpleGame extends Cocos2dxActivity{
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
if (detectOpenGLES20()) {
// get the packageName,it's used to set the resource path
String packageName = getApplication().getPackageName();
super.setPackageName(packageName);
// FrameLayout
ViewGroup.LayoutParams framelayout_params =
new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,
ViewGroup.LayoutParams.FILL_PARENT);
FrameLayout framelayout = new FrameLayout(this);
framelayout.setLayoutParams(framelayout_params);
// Cocos2dxEditText layout
ViewGroup.LayoutParams edittext_layout_params =
new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
Cocos2dxEditText edittext = new Cocos2dxEditText(this);
edittext.setLayoutParams(edittext_layout_params);
// ...add to FrameLayout
framelayout.addView(edittext);
// Cocos2dxGLSurfaceView
mGLView = new Cocos2dxGLSurfaceView(this);
// ...add to FrameLayout
framelayout.addView(mGLView);
mGLView.setEGLContextClientVersion(2);
mGLView.setCocos2dxRenderer(new Cocos2dxRenderer());
mGLView.setTextField(edittext);
// Set framelayout as the content view
setContentView(framelayout);
}
else {
Log.d("activity", "don't support gles2.0");
finish();
}
}
@Override
protected void onPause() {
super.onPause();
mGLView.onPause();
}
@Override
protected void onResume() {
super.onResume();
mGLView.onResume();
}
private boolean detectOpenGLES20()
{
ActivityManager am =
(ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
ConfigurationInfo info = am.getDeviceConfigurationInfo();
return (info.reqGlEsVersion >= 0x20000);
}
static {
System.loadLibrary("game");
}
}

View File

@ -45,8 +45,8 @@ bool AppDelegate::applicationDidFinishLaunching() {
{
// android, windows, blackberry, linux or mac
// use 960*640 resources as design resolution size
CCFileUtils::sharedFileUtils()->setResourceDirectory("hd");
CCEGLView::sharedOpenGLView()->setDesignResolutionSize(960, 640, kResolutionNoBorder);
CCFileUtils::sharedFileUtils()->setResourceDirectory("sd");
CCEGLView::sharedOpenGLView()->setDesignResolutionSize(480, 320, kResolutionNoBorder);
}
// turn on display FPS

View File

@ -77,7 +77,8 @@ bool HelloWorld::init()
CC_BREAK_IF(! pCloseItem);
// Place the menu item bottom-right conner.
pCloseItem->setPosition(ccp(CCDirector::sharedDirector()->getWinSize().width - 20, 20));
pCloseItem->setPosition(ccp(CCDirector::sharedDirector()->getVisibleSize().width - 20,
CCDirector::sharedDirector()->getVisibleOrigin().y + 20));
// Create a menu with the "close" menu item, it's an auto release object.
CCMenu* pMenu = CCMenu::create(pCloseItem, NULL);
@ -90,7 +91,7 @@ bool HelloWorld::init()
/////////////////////////////
// 2. add your codes below...
CCSize winSize = CCDirector::sharedDirector()->getWinSize();
CCSize winSize = CCDirector::sharedDirector()->getVisibleSize();
CCSprite *player = CCSprite::create("Player.png", CCRectMake(0, 0, 27, 40) );
player->setPosition( ccp(player->getContentSize().width/2, winSize.height/2) );
this->addChild(player);
@ -126,7 +127,7 @@ void HelloWorld::addTarget()
CCSprite *target = CCSprite::create("Target.png", CCRectMake(0,0,27,40) );
// Determine where to spawn the target along the Y axis
CCSize winSize = CCDirector::sharedDirector()->getWinSize();
CCSize winSize = CCDirector::sharedDirector()->getVisibleSize();
float minY = target->getContentSize().height/2;
float maxY = winSize.height - target->getContentSize().height/2;
int rangeY = (int)(maxY - minY);
@ -137,7 +138,7 @@ void HelloWorld::addTarget()
// and along a random position along the Y axis as calculated
target->setPosition(
ccp(winSize.width + (target->getContentSize().width/2),
actualY) );
CCDirector::sharedDirector()->getVisibleOrigin().y + actualY) );
this->addChild(target);
// Determine speed of the target
@ -194,7 +195,7 @@ void HelloWorld::ccTouchesEnded(CCSet* touches, CCEvent* event)
CCLog("++++++++after x:%f, y:%f", location.x, location.y);
// Set up initial location of projectile
CCSize winSize = CCDirector::sharedDirector()->getWinSize();
CCSize winSize = CCDirector::sharedDirector()->getVisibleSize();
CCSprite *projectile = CCSprite::create("Projectile.png", CCRectMake(0, 0, 20, 20));
projectile->setPosition( ccp(20, winSize.height/2) );

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="src" path="gen"/>
<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
<classpathentry kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
<classpathentry kind="output" path="bin/classes"/>
</classpath>

View File

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>SimpleGame</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>com.android.ide.eclipse.adt.ApkBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>com.android.ide.eclipse.adt.AndroidNature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

View File

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.cocos2dx.simplegame"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="8"/>
<application android:label="@string/app_name"
android:debuggable="true"
android:icon="@drawable/icon">
<activity android:name=".SimpleGame"
android:label="@string/app_name"
android:screenOrientation="landscape"
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
android:configChanges="orientation">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
<supports-screens android:largeScreens="true"
android:smallScreens="true"
android:anyDensity="true"
android:normalScreens="true"/>
</manifest>

View File

@ -0,0 +1,17 @@
# This file is used to override default values used by the Ant build system.
#
# This file must be checked into Version Control Systems, as it is
# integral to the build system of your project.
# This file is only used by the Ant script.
# You can use this to override default values such as
# 'source.dir' for the location of your java source folder and
# 'out.dir' for the location of your output folder.
# You can also use it define how the release builds are signed by declaring
# the following properties:
# 'key.store' for the location of your keystore and
# 'key.alias' for the name of the key to use.
# The password will be asked during the build when you use the 'release' target.

View File

@ -0,0 +1,92 @@
<?xml version="1.0" encoding="UTF-8"?>
<project name="SimpleGame" default="help">
<!-- The local.properties file is created and updated by the 'android' tool.
It contains the path to the SDK. It should *NOT* be checked into
Version Control Systems. -->
<property file="local.properties" />
<!-- The ant.properties file can be created by you. It is only edited by the
'android' tool to add properties to it.
This is the place to change some Ant specific build properties.
Here are some properties you may want to change/update:
source.dir
The name of the source directory. Default is 'src'.
out.dir
The name of the output directory. Default is 'bin'.
For other overridable properties, look at the beginning of the rules
files in the SDK, at tools/ant/build.xml
Properties related to the SDK location or the project target should
be updated using the 'android' tool with the 'update' action.
This file is an integral part of the build system for your
application and should be checked into Version Control Systems.
-->
<property file="ant.properties" />
<!-- if sdk.dir was not set from one of the property file, then
get it from the ANDROID_HOME env var.
This must be done before we load project.properties since
the proguard config can use sdk.dir -->
<property environment="env" />
<condition property="sdk.dir" value="${env.ANDROID_HOME}">
<isset property="env.ANDROID_HOME" />
</condition>
<!-- The project.properties file is created and updated by the 'android'
tool, as well as ADT.
This contains project specific properties such as project target, and library
dependencies. Lower level build properties are stored in ant.properties
(or in .classpath for Eclipse projects).
This file is an integral part of the build system for your
application and should be checked into Version Control Systems. -->
<loadproperties srcFile="project.properties" />
<!-- quick check on sdk.dir -->
<fail
message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through the ANDROID_HOME environment variable."
unless="sdk.dir"
/>
<!--
Import per project custom build rules if present at the root of the project.
This is the place to put custom intermediary targets such as:
-pre-build
-pre-compile
-post-compile (This is typically used for code obfuscation.
Compiled code location: ${out.classes.absolute.dir}
If this is not done in place, override ${out.dex.input.absolute.dir})
-post-package
-post-build
-pre-clean
-->
<import file="custom_rules.xml" optional="true" />
<!-- Import the actual build file.
To customize existing targets, there are two options:
- Customize only one target:
- copy/paste the target into this file, *before* the
<import> task.
- customize it to your needs.
- Customize the whole content of build.xml
- copy/paste the content of the rules files (minus the top node)
into this file, replacing the <import> task.
- customize to your needs.
***********************
****** IMPORTANT ******
***********************
In all cases you must update the value of version-tag below to read 'custom' instead of an integer,
in order to avoid having your file be overridden by tools such as "android update project"
-->
<!-- version-tag: 1 -->
<import file="${sdk.dir}/tools/ant/build.xml" />
</project>

View File

@ -0,0 +1,91 @@
APPNAME="SimpleGame"
# options
buildexternalsfromsource=
usage(){
cat << EOF
usage: $0 [options]
Build C/C++ code for $APPNAME using Android NDK
OPTIONS:
-s Build externals from source
-h this help
EOF
}
while getopts "sh" OPTION; do
case "$OPTION" in
s)
buildexternalsfromsource=1
;;
h)
usage
exit 0
;;
esac
done
# paths
if [ -z "${NDK_ROOT+aaa}" ];then
echo "please define NDK_ROOT"
exit 1
fi
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
# ... use paths relative to current directory
COCOS2DX_ROOT="$DIR/../../../"
APP_ROOT="$DIR/.."
APP_ANDROID_ROOT="$DIR"
echo "NDK_ROOT = $NDK_ROOT"
echo "COCOS2DX_ROOT = $COCOS2DX_ROOT"
echo "APP_ROOT = $APP_ROOT"
echo "APP_ANDROID_ROOT = $APP_ANDROID_ROOT"
# make sure assets is exist
if [ -d "$APP_ANDROID_ROOT"/assets ]; then
rm -rf "$APP_ANDROID_ROOT"/assets
fi
mkdir "$APP_ANDROID_ROOT"/assets
# copy resources
for file in "$APP_ROOT"/Resources/*
do
if [ -d "$file" ]; then
cp -rf "$file" "$APP_ANDROID_ROOT"/assets
fi
if [ -f "$file" ]; then
cp "$file" "$APP_ANDROID_ROOT"/assets
fi
done
# copy icons (if they exist)
file="$APP_ANDROID_ROOT"/assets/Icon-72.png
if [ -f "$file" ]; then
cp "$file" "$APP_ANDROID_ROOT"/res/drawable-hdpi/icon.png
fi
file="$APP_ANDROID_ROOT"/assets/Icon-48.png
if [ -f "$file" ]; then
cp "$file" "$APP_ANDROID_ROOT"/res/drawable-mdpi/icon.png
fi
file="$APP_ANDROID_ROOT"/assets/Icon-32.png
if [ -f "$file" ]; then
cp "$file" "$APP_ANDROID_ROOT"/res/drawable-ldpi/icon.png
fi
if [[ "$buildexternalsfromsource" ]]; then
echo "Building external dependencies from source"
"$NDK_ROOT"/ndk-build -C "$APP_ANDROID_ROOT" $* \
"NDK_MODULE_PATH=${COCOS2DX_ROOT}:${COCOS2DX_ROOT}/cocos2dx/platform/third_party/android/source"
else
echo "Using prebuilt externals"
"$NDK_ROOT"/ndk-build -C "$APP_ANDROID_ROOT" $* \
"NDK_MODULE_PATH=${COCOS2DX_ROOT}:${COCOS2DX_ROOT}/cocos2dx/platform/third_party/android/prebuilt"
fi

View File

@ -0,0 +1,22 @@
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := game_shared
LOCAL_MODULE_FILENAME := libgame
LOCAL_SRC_FILES := hellocpp/main.cpp \
../../Classes/AppDelegate.cpp \
../../Classes/HelloWorldScene.cpp \
../../Classes/GameOverScene.cpp
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../Classes
LOCAL_WHOLE_STATIC_LIBRARIES := cocos2dx_static cocosdenshion_static cocos_extension_static
include $(BUILD_SHARED_LIBRARY)
$(call import-module,CocosDenshion/android) \
$(call import-module,cocos2dx) \
$(call import-module,extensions)

View File

@ -0,0 +1,2 @@
APP_STL := gnustl_static
APP_CPPFLAGS := -frtti

View File

@ -0,0 +1,45 @@
#include "AppDelegate.h"
#include "platform/android/jni/JniHelper.h"
#include <jni.h>
#include <android/log.h>
#include "HelloWorldScene.h"
#define LOG_TAG "main"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__)
using namespace cocos2d;
extern "C"
{
jint JNI_OnLoad(JavaVM *vm, void *reserved)
{
JniHelper::setJavaVM(vm);
return JNI_VERSION_1_4;
}
void Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeInit(JNIEnv* env, jobject thiz, jint w, jint h)
{
if (!CCDirector::sharedDirector()->getOpenGLView())
{
CCEGLView *view = CCEGLView::sharedOpenGLView();
view->setFrameSize(w, h);
AppDelegate *pAppDelegate = new AppDelegate();
CCApplication::sharedApplication()->run();
}
else
{
ccDrawInit();
ccGLInvalidateStateCache();
CCShaderCache::sharedShaderCache()->reloadDefaultShaders();
CCTextureCache::reloadAllTextures();
CCNotificationCenter::sharedNotificationCenter()->postNotification(EVNET_COME_TO_FOREGROUND, NULL);
CCDirector::sharedDirector()->setGLDefaultValues();
}
}
}

View File

@ -0,0 +1,23 @@
#!/bin/bash
append_str=' \'
list_alldir()
{
for file in $1/*
do
if [ -f $file ]; then
echo $file$append_str | grep .cpp
fi
if [ -d $file ]; then
list_alldir $file
fi
done
}
if [ $# -gt 0 ]; then
list_alldir "$1"
else
list_alldir "."
fi

View File

@ -0,0 +1,20 @@
# To enable ProGuard in your project, edit project.properties
# to define the proguard.config property as described in that file.
#
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in ${sdk.dir}/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the ProGuard
# include property in project.properties.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Add any project specific keep options here:
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}

View File

@ -0,0 +1,14 @@
# This file is automatically generated by Android Tools.
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
#
# This file must be checked in Version Control Systems.
#
# To customize properties used by the Ant build system edit
# "ant.properties", and override values to adapt the script to your
# project structure.
#
# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
# Project target.
target=android-8

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">SimpleGame</string>
</resources>

View File

@ -0,0 +1,107 @@
/****************************************************************************
Copyright (c) 2010-2011 cocos2d-x.org
http://www.cocos2d-x.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
package org.cocos2dx.lib;
import android.content.Context;
import android.content.res.Configuration;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.view.Display;
import android.view.Surface;
import android.view.WindowManager;
/**
*
* This class is used for controlling the Accelerometer
*
*/
public class Cocos2dxAccelerometer implements SensorEventListener {
private static final String TAG = "Cocos2dxAccelerometer";
private Context mContext;
private SensorManager mSensorManager;
private Sensor mAccelerometer;
private int mNaturalOrientation;
public Cocos2dxAccelerometer(Context context){
mContext = context;
//Get an instance of the SensorManager
mSensorManager = (SensorManager) mContext.getSystemService(Context.SENSOR_SERVICE);
mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
Display display = ((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
mNaturalOrientation = display.getOrientation();
}
public void enable() {
mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_GAME);
}
public void disable () {
mSensorManager.unregisterListener(this);
}
@Override
public void onSensorChanged(SensorEvent event) {
if (event.sensor.getType() != Sensor.TYPE_ACCELEROMETER){
return;
}
float x = event.values[0];
float y = event.values[1];
float z = event.values[2];
/*
* Because the axes are not swapped when the device's screen orientation changes.
* So we should swap it here.
* In tablets such as Motorola Xoom, the default orientation is landscape, so should
* consider this.
*/
int orientation = mContext.getResources().getConfiguration().orientation;
if ((orientation == Configuration.ORIENTATION_LANDSCAPE) && (mNaturalOrientation != Surface.ROTATION_0)){
float tmp = x;
x = -y;
y = tmp;
}
else if ((orientation == Configuration.ORIENTATION_PORTRAIT) && (mNaturalOrientation != Surface.ROTATION_0))
{
float tmp = x;
x = y;
y = -tmp;
}
onSensorChanged(x, y, z, event.timestamp);
// Log.d(TAG, "x = " + event.values[0] + " y = " + event.values[1] + " z = " + event.values[2]);
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
private static native void onSensorChanged(float x, float y, float z, long timeStamp);
}

View File

@ -0,0 +1,346 @@
/****************************************************************************
Copyright (c) 2010-2012 cocos2d-x.org
http://www.cocos2d-x.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
package org.cocos2dx.lib;
import java.lang.ref.WeakReference;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.AssetManager;
import android.os.Build;
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{
protected Cocos2dxGLSurfaceView mGLView;
private static Cocos2dxMusic backgroundMusicPlayer;
private static Cocos2dxSound soundPlayer;
private static Cocos2dxAccelerometer accelerometer;
private static AssetManager assetManager;
private static boolean accelerometerEnabled = false;
private static Handler handler;
private final static int HANDLER_SHOW_DIALOG = 1;
private final static int HANDLER_SHOW_EDITBOX_DIALOG = 2;
private static String packageName;
private static native void nativeSetPaths(String apkPath);
private static native void nativeSetEditboxText(byte[] text);
static class ShowDialogHandler extends Handler {
WeakReference<Cocos2dxActivity> mActivity;
ShowDialogHandler(Cocos2dxActivity activity) {
mActivity = new WeakReference<Cocos2dxActivity>(activity);
}
@Override
public void handleMessage(Message msg) {
Cocos2dxActivity theActivity = mActivity.get();
switch(msg.what) {
case HANDLER_SHOW_DIALOG:
theActivity.showDialog(((DialogMessage)msg.obj).title, ((DialogMessage)msg.obj).message);
break;
case HANDLER_SHOW_EDITBOX_DIALOG:
theActivity.onShowEditBoxDialog((EditBoxMessage)msg.obj);
break;
}
}
};
public Cocos2dxGLSurfaceView getGLView() {
return mGLView;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 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 asset manager for jni call
assetManager = getAssets();
// init bitmap context
Cocos2dxBitmap.setContext(this);
handler = new ShowDialogHandler(this);
}
public static String getDeviceModel(){
return Build.MODEL;
}
public static AssetManager getAssetManager() {
return assetManager;
}
public static String getCurrentLanguage() {
String languageName = java.util.Locale.getDefault().getLanguage();
return languageName;
}
public static void showMessageBox(String title, String message){
Message msg = new Message();
msg.what = HANDLER_SHOW_DIALOG;
msg.obj = new DialogMessage(title, message);
handler.sendMessage(msg);
}
public static void enableAccelerometer() {
accelerometerEnabled = true;
accelerometer.enable();
}
public static void disableAccelerometer() {
accelerometerEnabled = false;
accelerometer.disable();
}
public static void preloadBackgroundMusic(String path){
backgroundMusicPlayer.preloadBackgroundMusic(path);
}
public static void playBackgroundMusic(String path, boolean isLoop){
backgroundMusicPlayer.playBackgroundMusic(path, isLoop);
}
public static void stopBackgroundMusic(){
backgroundMusicPlayer.stopBackgroundMusic();
}
public static void pauseBackgroundMusic(){
backgroundMusicPlayer.pauseBackgroundMusic();
}
public static void resumeBackgroundMusic(){
backgroundMusicPlayer.resumeBackgroundMusic();
}
public static void rewindBackgroundMusic(){
backgroundMusicPlayer.rewindBackgroundMusic();
}
public static boolean isBackgroundMusicPlaying(){
return backgroundMusicPlayer.isBackgroundMusicPlaying();
}
public static float getBackgroundMusicVolume(){
return backgroundMusicPlayer.getBackgroundVolume();
}
public static void setBackgroundMusicVolume(float volume){
backgroundMusicPlayer.setBackgroundVolume(volume);
}
public static int playEffect(String path, boolean isLoop){
return soundPlayer.playEffect(path, isLoop);
}
public static void stopEffect(int soundId){
soundPlayer.stopEffect(soundId);
}
public static void pauseEffect(int soundId){
soundPlayer.pauseEffect(soundId);
}
public static void resumeEffect(int soundId){
soundPlayer.resumeEffect(soundId);
}
public static float getEffectsVolume(){
return soundPlayer.getEffectsVolume();
}
public static void setEffectsVolume(float volume){
soundPlayer.setEffectsVolume(volume);
}
public static void preloadEffect(String path){
soundPlayer.preloadEffect(path);
}
public static void unloadEffect(String path){
soundPlayer.unloadEffect(path);
}
public static void stopAllEffects(){
soundPlayer.stopAllEffects();
}
public static void pauseAllEffects(){
soundPlayer.pauseAllEffects();
}
public static void resumeAllEffects(){
soundPlayer.resumeAllEffects();
}
public static void end(){
backgroundMusicPlayer.end();
soundPlayer.end();
}
public static String getCocos2dxPackageName(){
return packageName;
}
public static void terminateProcess(){
android.os.Process.killProcess(android.os.Process.myPid());
}
@Override
protected void onResume() {
super.onResume();
if (accelerometerEnabled) {
accelerometer.enable();
}
}
@Override
protected void onPause() {
super.onPause();
if (accelerometerEnabled) {
accelerometer.disable();
}
}
protected void setPackageName(String packageName) {
Cocos2dxActivity.packageName = packageName;
String apkFilePath = "";
ApplicationInfo appInfo = null;
PackageManager packMgmr = getApplication().getPackageManager();
try {
appInfo = packMgmr.getApplicationInfo(packageName, 0);
} catch (NameNotFoundException e) {
e.printStackTrace();
throw new RuntimeException("Unable to locate assets, aborting...");
}
apkFilePath = appInfo.sourceDir;
Log.w("apk path", apkFilePath);
// add this link at the renderer class
nativeSetPaths(apkFilePath);
}
private void showDialog(String title, String message){
Dialog dialog = new AlertDialog.Builder(this)
.setTitle(title)
.setMessage(message)
.setPositiveButton("Ok",
new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface dialog, int whichButton){
}
}).create();
dialog.show();
}
private static void showEditBoxDialog(String title, String content, int inputMode, int inputFlag, int returnType, int maxLength)
{
Message msg = new Message();
msg.what = HANDLER_SHOW_EDITBOX_DIALOG;
msg.obj = new EditBoxMessage(title, content, inputMode, inputFlag, returnType, maxLength);
handler.sendMessage(msg);
}
private void onShowEditBoxDialog(EditBoxMessage msg)
{
Dialog dialog = new Cocos2dxEditBoxDialog(this, msg);
dialog.show();
}
public void setEditBoxResult(String editResult)
{
Log.i("editbox_content", editResult);
try
{
final byte[] bytesUTF8 = editResult.getBytes("UTF8");
// pass utf8 string from editbox activity to native.
// Should invoke native method in GL thread.
mGLView.queueEvent(new Runnable() {
@Override
public void run() {
nativeSetEditboxText(bytesUTF8);
}
});
}
catch (java.io.UnsupportedEncodingException e)
{
e.printStackTrace();
}
}
}
class DialogMessage {
public String title;
public String message;
public DialogMessage(String title, String message){
this.message = message;
this.title = title;
}
}
class EditBoxMessage {
public String title;
public String content;
public int inputMode;
public int inputFlag;
public int returnType;
public int maxLength;
public EditBoxMessage(String title, String content, int inputMode, int inputFlag, int returnType, int maxLength){
this.content = content;
this.title = title;
this.inputMode = inputMode;
this.inputFlag = inputFlag;
this.returnType = returnType;
this.maxLength = maxLength;
}
}

View File

@ -0,0 +1,455 @@
/****************************************************************************
Copyright (c) 2010-2011 cocos2d-x.org
http://www.cocos2d-x.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
package org.cocos2dx.lib;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.LinkedList;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.graphics.Paint.Align;
import android.graphics.Paint.FontMetricsInt;
import android.text.TextPaint;
import android.text.TextUtils;
import android.util.Log;
public class Cocos2dxBitmap{
/*
* The values are the same as cocos2dx/platform/CCImage.h.
*/
private static final int HALIGNCENTER = 3;
private static final int HALIGNLEFT = 1;
private static final int HALIGNRIGHT = 2;
// vertical alignment
private static final int VALIGNTOP = 1;
private static final int VALIGNBOTTOM = 2;
private static final int VALIGNCENTER = 3;
private static Context context;
public static void setContext(Context context){
Cocos2dxBitmap.context = context;
}
/*
* @width: the width to draw, it can be 0
* @height: the height to draw, it can be 0
*/
public static void createTextBitmap(String content, String fontName,
int fontSize, int alignment, int width, int height){
content = refactorString(content);
Paint paint = newPaint(fontName, fontSize, alignment);
TextProperty textProperty = computeTextProperty(content, paint, width, height);
int bitmapTotalHeight = (height == 0 ? textProperty.totalHeight:height);
// Draw text to bitmap
Bitmap bitmap = Bitmap.createBitmap(textProperty.maxWidth,
bitmapTotalHeight, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
// Draw string
FontMetricsInt fm = paint.getFontMetricsInt();
int x = 0;
int y = computeY(fm, height, textProperty.totalHeight, alignment);
String[] lines = textProperty.lines;
for (String line : lines){
x = computeX(paint, line, textProperty.maxWidth, alignment);
canvas.drawText(line, x, y, paint);
y += textProperty.heightPerLine;
}
initNativeObject(bitmap);
}
private static int computeX(Paint paint, String content, int w, int alignment){
int ret = 0;
int hAlignment = alignment & 0x0F;
switch (hAlignment){
case HALIGNCENTER:
ret = w / 2;
break;
// ret = 0
case HALIGNLEFT:
break;
case HALIGNRIGHT:
ret = w;
break;
/*
* Default is align left.
* Should be same as newPaint().
*/
default:
break;
}
return ret;
}
private static int computeY(FontMetricsInt fm, int constrainHeight, int totalHeight, int alignment) {
int y = -fm.top;
if (constrainHeight > totalHeight) {
int vAlignment = (alignment >> 4) & 0x0F;
switch (vAlignment) {
case VALIGNTOP:
y = -fm.top;
break;
case VALIGNCENTER:
y = -fm.top + (constrainHeight - totalHeight)/2;
break;
case VALIGNBOTTOM:
y = -fm.top + (constrainHeight - totalHeight);
break;
default:
break;
}
}
return y;
}
private static class TextProperty{
// The max width of lines
int maxWidth;
// The height of all lines
int totalHeight;
int heightPerLine;
String[] lines;
TextProperty(int w, int h, String[] lines){
this.maxWidth = w;
this.heightPerLine = h;
this.totalHeight = h * lines.length;
this.lines = lines;
}
}
private static TextProperty computeTextProperty(String content, Paint paint,
int maxWidth, int maxHeight){
FontMetricsInt fm = paint.getFontMetricsInt();
int h = (int)Math.ceil(fm.bottom - fm.top);
int maxContentWidth = 0;
String[] lines = splitString(content, maxHeight, maxWidth, paint);
if (maxWidth != 0){
maxContentWidth = maxWidth;
}
else {
/*
* Compute the max width
*/
int temp = 0;
for (String line : lines){
temp = (int)Math.ceil(paint.measureText(line, 0, line.length()));
if (temp > maxContentWidth){
maxContentWidth = temp;
}
}
}
return new TextProperty(maxContentWidth, h, lines);
}
/*
* If maxWidth or maxHeight is not 0,
* split the string to fix the maxWidth and maxHeight.
*/
private static String[] splitString(String content, int maxHeight, int maxWidth,
Paint paint){
String[] lines = content.split("\\n");
String[] ret = null;
FontMetricsInt fm = paint.getFontMetricsInt();
int heightPerLine = (int)Math.ceil(fm.bottom - fm.top);
int maxLines = maxHeight / heightPerLine;
if (maxWidth != 0){
LinkedList<String> strList = new LinkedList<String>();
for (String line : lines){
/*
* The width of line is exceed maxWidth, should divide it into
* two or more lines.
*/
int lineWidth = (int)Math.ceil(paint.measureText(line));
if (lineWidth > maxWidth){
strList.addAll(divideStringWithMaxWidth(paint, line, maxWidth));
}
else{
strList.add(line);
}
/*
* Should not exceed the max height;
*/
if (maxLines > 0 && strList.size() >= maxLines){
break;
}
}
/*
* Remove exceeding lines
*/
if (maxLines > 0 && strList.size() > maxLines){
while (strList.size() > maxLines){
strList.removeLast();
}
}
ret = new String[strList.size()];
strList.toArray(ret);
} else
if (maxHeight != 0 && lines.length > maxLines) {
/*
* Remove exceeding lines
*/
LinkedList<String> strList = new LinkedList<String>();
for (int i = 0; i < maxLines; i++){
strList.add(lines[i]);
}
ret = new String[strList.size()];
strList.toArray(ret);
}
else {
ret = lines;
}
return ret;
}
private static LinkedList<String> divideStringWithMaxWidth(Paint paint, String content,
int width){
int charLength = content.length();
int start = 0;
int tempWidth = 0;
LinkedList<String> strList = new LinkedList<String>();
/*
* Break a String into String[] by the width & should wrap the word
*/
for (int i = 1; i <= charLength; ++i){
tempWidth = (int)Math.ceil(paint.measureText(content, start, i));
if (tempWidth >= width){
int lastIndexOfSpace = content.substring(0, i).lastIndexOf(" ");
if (lastIndexOfSpace != -1 && lastIndexOfSpace > start){
/**
* Should wrap the word
*/
strList.add(content.substring(start, lastIndexOfSpace));
i = lastIndexOfSpace;
}
else {
/*
* Should not exceed the width
*/
if (tempWidth > width){
strList.add(content.substring(start, i - 1));
/*
* compute from previous char
*/
--i;
}
else {
strList.add(content.substring(start, i));
}
}
// remove spaces at the beginning of a new line
while(content.indexOf(i++) == ' ') {
}
start = i;
}
}
/*
* Add the last chars
*/
if (start < charLength){
strList.add(content.substring(start));
}
return strList;
}
private static Paint newPaint(String fontName, int fontSize, int alignment){
Paint paint = new Paint();
paint.setColor(Color.WHITE);
paint.setTextSize(fontSize);
paint.setAntiAlias(true);
/*
* Set type face for paint, now it support .ttf file.
*/
if (fontName.endsWith(".ttf")){
try {
//Typeface typeFace = Typeface.createFromAsset(context.getAssets(), fontName);
Typeface typeFace = Cocos2dxTypefaces.get(context, fontName);
paint.setTypeface(typeFace);
} catch (Exception e){
Log.e("Cocos2dxBitmap",
"error to create ttf type face: " + fontName);
/*
* The file may not find, use system font
*/
paint.setTypeface(Typeface.create(fontName, Typeface.NORMAL));
}
}
else {
paint.setTypeface(Typeface.create(fontName, Typeface.NORMAL));
}
int hAlignment = alignment & 0x0F;
switch (hAlignment){
case HALIGNCENTER:
paint.setTextAlign(Align.CENTER);
break;
case HALIGNLEFT:
paint.setTextAlign(Align.LEFT);
break;
case HALIGNRIGHT:
paint.setTextAlign(Align.RIGHT);
break;
default:
paint.setTextAlign(Align.LEFT);
break;
}
return paint;
}
private static String refactorString(String str){
// Avoid error when content is ""
if (str.compareTo("") == 0){
return " ";
}
/*
* If the font of "\n" is "" or "\n", insert " " in front of it.
*
* For example:
* "\nabc" -> " \nabc"
* "\nabc\n\n" -> " \nabc\n \n"
*/
StringBuilder strBuilder = new StringBuilder(str);
int start = 0;
int index = strBuilder.indexOf("\n");
while (index != -1){
if (index == 0 || strBuilder.charAt(index -1) == '\n'){
strBuilder.insert(start, " ");
start = index + 2;
} else {
start = index + 1;
}
if (start > strBuilder.length() || index == strBuilder.length()){
break;
}
index = strBuilder.indexOf("\n", start);
}
return strBuilder.toString();
}
private static void initNativeObject(Bitmap bitmap){
byte[] pixels = getPixels(bitmap);
if (pixels == null){
return;
}
nativeInitBitmapDC(bitmap.getWidth(), bitmap.getHeight(), pixels);
}
private static byte[] getPixels(Bitmap bitmap){
if (bitmap != null){
byte[] pixels = new byte[bitmap.getWidth() * bitmap.getHeight() * 4];
ByteBuffer buf = ByteBuffer.wrap(pixels);
buf.order(ByteOrder.nativeOrder());
bitmap.copyPixelsToBuffer(buf);
return pixels;
}
return null;
}
private static native void nativeInitBitmapDC(int width, int height, byte[] pixels);
private static int getFontSizeAccordingHeight(int height)
{
Paint paint = new Paint();
Rect bounds = new Rect();
paint.setTypeface(Typeface.DEFAULT);
int incr_text_size = 1;
boolean found_desired_size = false;
while (!found_desired_size) {
paint.setTextSize(incr_text_size);
String text = "SghMNy";
paint.getTextBounds(text, 0, text.length(), bounds);
incr_text_size++;
if (height - bounds.height() <= 2) {
found_desired_size = true;
}
Log.d("font size", "incr size:" + incr_text_size);
}
return incr_text_size;
}
private static String getStringWithEllipsis(String originalText, float width, float fontSize){
if(TextUtils.isEmpty(originalText)){
return "";
}
TextPaint paint = new TextPaint();
paint.setTypeface(Typeface.DEFAULT);
paint.setTextSize(fontSize);
return TextUtils.ellipsize(originalText, paint, width,
TextUtils.TruncateAt.valueOf("END")).toString();
}
}

View File

@ -0,0 +1,338 @@
/****************************************************************************
Copyright (c) 2010-2012 cocos2d-x.org
http://www.cocos2d-x.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
package org.cocos2dx.lib;
import android.app.Dialog;
import android.content.Context;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.os.Handler;
import android.text.InputFilter;
import android.text.InputType;
import android.util.Log;
import android.util.TypedValue;
import android.view.KeyEvent;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.TextView.OnEditorActionListener;
public class Cocos2dxEditBoxDialog extends Dialog {
/**
* The user is allowed to enter any text, including line breaks.
*/
private final int kEditBoxInputModeAny = 0;
/**
* The user is allowed to enter an e-mail address.
*/
private final int kEditBoxInputModeEmailAddr = 1;
/**
* The user is allowed to enter an integer value.
*/
private final int kEditBoxInputModeNumeric = 2;
/**
* The user is allowed to enter a phone number.
*/
private final int kEditBoxInputModePhoneNumber = 3;
/**
* The user is allowed to enter a URL.
*/
private final int kEditBoxInputModeUrl = 4;
/**
* The user is allowed to enter a real number value.
* This extends kEditBoxInputModeNumeric by allowing a decimal point.
*/
private final int kEditBoxInputModeDecimal = 5;
/**
* The user is allowed to enter any text, except for line breaks.
*/
private final int kEditBoxInputModeSingleLine = 6;
/**
* Indicates that the text entered is confidential data that should be
* obscured whenever possible. This implies EDIT_BOX_INPUT_FLAG_SENSITIVE.
*/
private final int kEditBoxInputFlagPassword = 0;
/**
* Indicates that the text entered is sensitive data that the
* implementation must never store into a dictionary or table for use
* in predictive, auto-completing, or other accelerated input schemes.
* A credit card number is an example of sensitive data.
*/
private final int kEditBoxInputFlagSensitive = 1;
/**
* This flag is a hint to the implementation that during text editing,
* the initial letter of each word should be capitalized.
*/
private final int kEditBoxInputFlagInitialCapsWord = 2;
/**
* This flag is a hint to the implementation that during text editing,
* the initial letter of each sentence should be capitalized.
*/
private final int kEditBoxInputFlagInitialCapsSentence = 3;
/**
* Capitalize all characters automatically.
*/
private final int kEditBoxInputFlagInitialCapsAllCharacters = 4;
private final int kKeyboardReturnTypeDefault = 0;
private final int kKeyboardReturnTypeDone = 1;
private final int kKeyboardReturnTypeSend = 2;
private final int kKeyboardReturnTypeSearch = 3;
private final int kKeyboardReturnTypeGo = 4;
//
private EditText mInputEditText = null;
private TextView mTextViewTitle = null;
private int mInputMode = 0;
private int mInputFlag = 0;
private int mReturnType = 0;
private int mMaxLength = -1;
private int mInputFlagConstraints = 0x00000;
private int mInputModeContraints = 0x00000;
private boolean mIsMultiline = false;
private Cocos2dxActivity mParentActivity = null;
private EditBoxMessage mMsg = null;
public Cocos2dxEditBoxDialog(Context context, EditBoxMessage msg) {
//super(context, R.style.Theme_Translucent);
super(context, android.R.style.Theme_Translucent_NoTitleBar_Fullscreen);
// TODO Auto-generated constructor stub
mParentActivity = (Cocos2dxActivity)context;
mMsg = msg;
}
// Converting dips to pixels
private int convertDipsToPixels(float dips)
{
float scale = getContext().getResources().getDisplayMetrics().density;
return Math.round(dips * scale);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
getWindow().setBackgroundDrawable(new ColorDrawable(0x80000000));
LinearLayout layout = new LinearLayout(mParentActivity);
layout.setOrientation(LinearLayout.VERTICAL);
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(ViewGroup.
LayoutParams.FILL_PARENT,ViewGroup.LayoutParams.FILL_PARENT);
mTextViewTitle = new TextView(mParentActivity);
LinearLayout.LayoutParams textviewParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
textviewParams.leftMargin = textviewParams.rightMargin = convertDipsToPixels(10);
mTextViewTitle.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20);
layout.addView(mTextViewTitle, textviewParams);
mInputEditText = new EditText(mParentActivity);
LinearLayout.LayoutParams editTextParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
editTextParams.leftMargin = editTextParams.rightMargin = convertDipsToPixels(10);
layout.addView(mInputEditText, editTextParams);
setContentView(layout, layoutParams);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
mInputMode = mMsg.inputMode;
mInputFlag = mMsg.inputFlag;
mReturnType = mMsg.returnType;
mMaxLength = mMsg.maxLength;
mTextViewTitle.setText(mMsg.title);
mInputEditText.setText(mMsg.content);
int oldImeOptions = mInputEditText.getImeOptions();
mInputEditText.setImeOptions(oldImeOptions | EditorInfo.IME_FLAG_NO_EXTRACT_UI);
oldImeOptions = mInputEditText.getImeOptions();
switch (mInputMode)
{
case kEditBoxInputModeAny:
mInputModeContraints =
InputType.TYPE_CLASS_TEXT |
InputType.TYPE_TEXT_FLAG_MULTI_LINE;
break;
case kEditBoxInputModeEmailAddr:
mInputModeContraints =
InputType.TYPE_CLASS_TEXT |
InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS;
break;
case kEditBoxInputModeNumeric:
mInputModeContraints =
InputType.TYPE_CLASS_NUMBER |
InputType.TYPE_NUMBER_FLAG_SIGNED;
break;
case kEditBoxInputModePhoneNumber:
mInputModeContraints = InputType.TYPE_CLASS_PHONE;
break;
case kEditBoxInputModeUrl:
mInputModeContraints =
InputType.TYPE_CLASS_TEXT |
InputType.TYPE_TEXT_VARIATION_URI;
break;
case kEditBoxInputModeDecimal:
mInputModeContraints =
InputType.TYPE_CLASS_NUMBER |
InputType.TYPE_NUMBER_FLAG_DECIMAL |
InputType.TYPE_NUMBER_FLAG_SIGNED;
break;
case kEditBoxInputModeSingleLine:
mInputModeContraints = InputType.TYPE_CLASS_TEXT;
break;
default:
break;
}
if ( mIsMultiline ) {
mInputModeContraints |= InputType.TYPE_TEXT_FLAG_MULTI_LINE;
}
mInputEditText.setInputType(mInputModeContraints | mInputFlagConstraints);
switch (mInputFlag)
{
case kEditBoxInputFlagPassword:
mInputFlagConstraints = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD;
break;
case kEditBoxInputFlagSensitive:
mInputFlagConstraints = InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS;
break;
case kEditBoxInputFlagInitialCapsWord:
mInputFlagConstraints = InputType.TYPE_TEXT_FLAG_CAP_WORDS;
break;
case kEditBoxInputFlagInitialCapsSentence:
mInputFlagConstraints = InputType.TYPE_TEXT_FLAG_CAP_SENTENCES;
break;
case kEditBoxInputFlagInitialCapsAllCharacters:
mInputFlagConstraints = InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS;
break;
default:
break;
}
mInputEditText.setInputType(mInputFlagConstraints | mInputModeContraints);
switch (mReturnType) {
case kKeyboardReturnTypeDefault:
mInputEditText.setImeOptions(oldImeOptions | EditorInfo.IME_ACTION_NONE);
break;
case kKeyboardReturnTypeDone:
mInputEditText.setImeOptions(oldImeOptions | EditorInfo.IME_ACTION_DONE);
break;
case kKeyboardReturnTypeSend:
mInputEditText.setImeOptions(oldImeOptions | EditorInfo.IME_ACTION_SEND);
break;
case kKeyboardReturnTypeSearch:
mInputEditText.setImeOptions(oldImeOptions | EditorInfo.IME_ACTION_SEARCH);
break;
case kKeyboardReturnTypeGo:
mInputEditText.setImeOptions(oldImeOptions | EditorInfo.IME_ACTION_GO);
break;
default:
mInputEditText.setImeOptions(oldImeOptions | EditorInfo.IME_ACTION_NONE);
break;
}
if (mMaxLength > 0) {
mInputEditText.setFilters(
new InputFilter[] {
new InputFilter.LengthFilter(mMaxLength)
}
);
}
Handler initHandler = new Handler();
initHandler.postDelayed(new Runnable() {
public void run() {
mInputEditText.requestFocus();
mInputEditText.setSelection(mInputEditText.length());
openKeyboard();
}
}, 200);
mInputEditText.setOnEditorActionListener(new OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
// if user didn't set keyboard type,
// this callback will be invoked twice with 'KeyEvent.ACTION_DOWN' and 'KeyEvent.ACTION_UP'
if (actionId != EditorInfo.IME_NULL
|| (actionId == EditorInfo.IME_NULL
&& event != null
&& event.getAction() == KeyEvent.ACTION_DOWN))
{
//Log.d("EditBox", "actionId: "+actionId +",event: "+event);
mParentActivity.setEditBoxResult(mInputEditText.getText().toString());
closeKeyboard();
dismiss();
return true;
}
return false;
}
});
}
private void openKeyboard() {
InputMethodManager imm = (InputMethodManager) mParentActivity.getSystemService(Context.INPUT_METHOD_SERVICE);
imm.showSoftInput(mInputEditText, 0);
Log.d("Cocos2dxEditBox", "openKeyboard");
}
private void closeKeyboard() {
InputMethodManager imm = (InputMethodManager) mParentActivity.getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(mInputEditText.getWindowToken(), 0);
Log.d("Cocos2dxEditBox", "closeKeyboard");
}
@Override
protected void onStop() {
// TODO Auto-generated method stub
super.onStop();
Log.d("EditBox", "onStop...");
}
}

View File

@ -0,0 +1,65 @@
/****************************************************************************
Copyright (c) 2012 cocos2d-x.org
http://www.cocos2d-x.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
package org.cocos2dx.lib;
import android.content.Context;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.widget.EditText;
public class Cocos2dxEditText extends EditText {
private Cocos2dxGLSurfaceView mView;
public Cocos2dxEditText(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
public Cocos2dxEditText(Context context, AttributeSet attrs) {
super(context, attrs);
}
public Cocos2dxEditText(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public void setMainView(Cocos2dxGLSurfaceView glSurfaceView) {
mView = glSurfaceView;
}
/*
* Let GlSurfaceView get focus if back key is input
*/
public boolean onKeyDown(int keyCode, KeyEvent event) {
super.onKeyDown(keyCode, event);
if (keyCode == KeyEvent.KEYCODE_BACK) {
mView.requestFocus();
}
return true;
}
}

View File

@ -0,0 +1,417 @@
/****************************************************************************
Copyright (c) 2010-2011 cocos2d-x.org
http://www.cocos2d-x.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
package org.cocos2dx.lib;
import android.content.Context;
import android.opengl.GLSurfaceView;
import android.os.Handler;
import android.os.Message;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.AttributeSet;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.inputmethod.InputMethodManager;
import android.widget.TextView;
import android.widget.TextView.OnEditorActionListener;
class TextInputWraper implements TextWatcher, OnEditorActionListener {
private static final Boolean debug = false;
private void LogD(String msg) {
if (debug) Log.d("TextInputFilter", msg);
}
private Cocos2dxGLSurfaceView mMainView;
private String mText;
private String mOriginText;
private Boolean isFullScreenEdit() {
InputMethodManager imm = (InputMethodManager)mMainView.getTextField().getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
return imm.isFullscreenMode();
}
public TextInputWraper(Cocos2dxGLSurfaceView view) {
mMainView = view;
}
public void setOriginText(String text) {
mOriginText = text;
}
@Override
public void afterTextChanged(Editable s) {
if (isFullScreenEdit()) {
return;
}
LogD("afterTextChanged: " + s);
int nModified = s.length() - mText.length();
if (nModified > 0) {
final String insertText = s.subSequence(mText.length(), s.length()).toString();
mMainView.insertText(insertText);
LogD("insertText(" + insertText + ")");
}
else {
for (; nModified < 0; ++nModified) {
mMainView.deleteBackward();
LogD("deleteBackward");
}
}
mText = s.toString();
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
LogD("beforeTextChanged(" + s + ")start: " + start + ",count: " + count + ",after: " + after);
mText = s.toString();
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (mMainView.getTextField() == v && isFullScreenEdit()) {
// user press the action button, delete all old text and insert new text
for (int i = mOriginText.length(); i > 0; --i) {
mMainView.deleteBackward();
LogD("deleteBackward");
}
String text = v.getText().toString();
/*
* If user input nothing, translate "\n" to engine.
*/
if (text.compareTo("") == 0){
text = "\n";
}
if ('\n' != text.charAt(text.length() - 1)) {
text += '\n';
}
final String insertText = text;
mMainView.insertText(insertText);
LogD("insertText(" + insertText + ")");
}
return false;
}
}
public class Cocos2dxGLSurfaceView extends GLSurfaceView {
static private Cocos2dxGLSurfaceView mainView;
private static final String TAG = Cocos2dxGLSurfaceView.class.getCanonicalName();
private Cocos2dxRenderer mRenderer;
private static final boolean debug = false;
///////////////////////////////////////////////////////////////////////////
// for initialize
///////////////////////////////////////////////////////////////////////////
public Cocos2dxGLSurfaceView(Context context) {
super(context);
initView();
}
public Cocos2dxGLSurfaceView(Context context, AttributeSet attrs) {
super(context, attrs);
initView();
}
public void setCocos2dxRenderer(Cocos2dxRenderer renderer){
mRenderer = renderer;
setRenderer(mRenderer);
}
protected void initView() {
setFocusableInTouchMode(true);
textInputWraper = new TextInputWraper(this);
handler = new Handler(){
public void handleMessage(Message msg){
switch(msg.what){
case HANDLER_OPEN_IME_KEYBOARD:
if (null != mTextField && mTextField.requestFocus()) {
mTextField.removeTextChangedListener(textInputWraper);
mTextField.setText("");
String text = (String)msg.obj;
mTextField.append(text);
textInputWraper.setOriginText(text);
mTextField.addTextChangedListener(textInputWraper);
InputMethodManager imm = (InputMethodManager)mainView.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
imm.showSoftInput(mTextField, 0);
Log.d("GLSurfaceView", "showSoftInput");
}
break;
case HANDLER_CLOSE_IME_KEYBOARD:
if (null != mTextField) {
mTextField.removeTextChangedListener(textInputWraper);
InputMethodManager imm = (InputMethodManager)mainView.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(mTextField.getWindowToken(), 0);
Log.d("GLSurfaceView", "HideSoftInput");
}
break;
}
}
};
mainView = this;
}
public void onPause(){
queueEvent(new Runnable() {
@Override
public void run() {
mRenderer.handleOnPause();
}
});
super.onPause();
}
public void onResume(){
super.onResume();
queueEvent(new Runnable() {
@Override
public void run() {
mRenderer.handleOnResume();
}
});
}
///////////////////////////////////////////////////////////////////////////
// for text input
///////////////////////////////////////////////////////////////////////////
private final static int HANDLER_OPEN_IME_KEYBOARD = 2;
private final static int HANDLER_CLOSE_IME_KEYBOARD = 3;
private static Handler handler;
private static TextInputWraper textInputWraper;
private Cocos2dxEditText mTextField;
public TextView getTextField() {
return mTextField;
}
public void setTextField(Cocos2dxEditText view) {
mTextField = view;
if (null != mTextField && null != textInputWraper) {
mTextField.setOnEditorActionListener(textInputWraper);
mTextField.setMainView(this);
this.requestFocus();
}
}
public static void openIMEKeyboard() {
Message msg = new Message();
msg.what = HANDLER_OPEN_IME_KEYBOARD;
msg.obj = mainView.getContentText();
handler.sendMessage(msg);
}
private String getContentText() {
return mRenderer.getContentText();
}
public static void closeIMEKeyboard() {
Message msg = new Message();
msg.what = HANDLER_CLOSE_IME_KEYBOARD;
handler.sendMessage(msg);
}
public void insertText(final String text) {
queueEvent(new Runnable() {
@Override
public void run() {
mRenderer.handleInsertText(text);
}
});
}
public void deleteBackward() {
queueEvent(new Runnable() {
@Override
public void run() {
mRenderer.handleDeleteBackward();
}
});
}
///////////////////////////////////////////////////////////////////////////
// for touch event
///////////////////////////////////////////////////////////////////////////
public boolean onTouchEvent(final MotionEvent event) {
// these data are used in ACTION_MOVE and ACTION_CANCEL
final int pointerNumber = event.getPointerCount();
final int[] ids = new int[pointerNumber];
final float[] xs = new float[pointerNumber];
final float[] ys = new float[pointerNumber];
for (int i = 0; i < pointerNumber; i++) {
ids[i] = event.getPointerId(i);
xs[i] = event.getX(i);
ys[i] = event.getY(i);
}
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_POINTER_DOWN:
final int indexPointerDown = event.getAction() >> MotionEvent.ACTION_POINTER_ID_SHIFT;
final int idPointerDown = event.getPointerId(indexPointerDown);
final float xPointerDown = event.getX(indexPointerDown);
final float yPointerDown = event.getY(indexPointerDown);
queueEvent(new Runnable() {
@Override
public void run() {
mRenderer.handleActionDown(idPointerDown, xPointerDown, yPointerDown);
}
});
break;
case MotionEvent.ACTION_DOWN:
// there are only one finger on the screen
final int idDown = event.getPointerId(0);
final float xDown = xs[0];
final float yDown = ys[0];
queueEvent(new Runnable() {
@Override
public void run() {
mRenderer.handleActionDown(idDown, xDown, yDown);
}
});
break;
case MotionEvent.ACTION_MOVE:
queueEvent(new Runnable() {
@Override
public void run() {
mRenderer.handleActionMove(ids, xs, ys);
}
});
break;
case MotionEvent.ACTION_POINTER_UP:
final int indexPointUp = event.getAction() >> MotionEvent.ACTION_POINTER_ID_SHIFT;
final int idPointerUp = event.getPointerId(indexPointUp);
final float xPointerUp = event.getX(indexPointUp);
final float yPointerUp = event.getY(indexPointUp);
queueEvent(new Runnable() {
@Override
public void run() {
mRenderer.handleActionUp(idPointerUp, xPointerUp, yPointerUp);
}
});
break;
case MotionEvent.ACTION_UP:
// there are only one finger on the screen
final int idUp = event.getPointerId(0);
final float xUp = xs[0];
final float yUp = ys[0];
queueEvent(new Runnable() {
@Override
public void run() {
mRenderer.handleActionUp(idUp, xUp, yUp);
}
});
break;
case MotionEvent.ACTION_CANCEL:
queueEvent(new Runnable() {
@Override
public void run() {
mRenderer.handleActionCancel(ids, xs, ys);
}
});
break;
}
if (debug){
dumpEvent(event);
}
return true;
}
/*
* This function is called before Cocos2dxRenderer.nativeInit(), so the width and height is correct.
*/
protected void onSizeChanged(int w, int h, int oldw, int oldh){
this.mRenderer.setScreenWidthAndHeight(w, h);
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
final int kc = keyCode;
if (keyCode == KeyEvent.KEYCODE_BACK || keyCode == KeyEvent.KEYCODE_MENU) {
queueEvent(new Runnable() {
@Override
public void run() {
mRenderer.handleKeyDown(kc);
}
});
return true;
}
return super.onKeyDown(keyCode, event);
}
// Show an event in the LogCat view, for debugging
private void dumpEvent(MotionEvent event) {
String names[] = { "DOWN" , "UP" , "MOVE" , "CANCEL" , "OUTSIDE" ,
"POINTER_DOWN" , "POINTER_UP" , "7?" , "8?" , "9?" };
StringBuilder sb = new StringBuilder();
int action = event.getAction();
int actionCode = action & MotionEvent.ACTION_MASK;
sb.append("event ACTION_" ).append(names[actionCode]);
if (actionCode == MotionEvent.ACTION_POINTER_DOWN
|| actionCode == MotionEvent.ACTION_POINTER_UP) {
sb.append("(pid " ).append(
action >> MotionEvent.ACTION_POINTER_ID_SHIFT);
sb.append(")" );
}
sb.append("[" );
for (int i = 0; i < event.getPointerCount(); i++) {
sb.append("#" ).append(i);
sb.append("(pid " ).append(event.getPointerId(i));
sb.append(")=" ).append((int) event.getX(i));
sb.append("," ).append((int) event.getY(i));
if (i + 1 < event.getPointerCount())
sb.append(";" );
}
sb.append("]" );
Log.d(TAG, sb.toString());
}
}

View File

@ -0,0 +1,228 @@
/****************************************************************************
Copyright (c) 2010-2011 cocos2d-x.org
http://www.cocos2d-x.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
package org.cocos2dx.lib;
import android.content.Context;
import android.content.res.AssetFileDescriptor;
import android.media.MediaPlayer;
import android.util.Log;
/**
*
* This class is used for controlling background music
*
*/
public class Cocos2dxMusic {
private static final String TAG = "Cocos2dxMusic";
private float mLeftVolume;
private float mRightVolume;
private Context mContext;
private MediaPlayer mBackgroundMediaPlayer;
private boolean mIsPaused;
private String mCurrentPath;
public Cocos2dxMusic(Context context){
this.mContext = context;
initData();
}
public void preloadBackgroundMusic(String path){
if ((mCurrentPath == null) || (! mCurrentPath.equals(path))){
// preload new background music
// release old resource and create a new one
if (mBackgroundMediaPlayer != null){
mBackgroundMediaPlayer.release();
}
mBackgroundMediaPlayer = createMediaplayerFromAssets(path);
// record the path
mCurrentPath = path;
}
}
public void playBackgroundMusic(String path, boolean isLoop){
if (mCurrentPath == null){
// it is the first time to play background music
// or end() was called
mBackgroundMediaPlayer = createMediaplayerFromAssets(path);
mCurrentPath = path;
}
else {
if (! mCurrentPath.equals(path)){
// play new background music
// release old resource and create a new one
if (mBackgroundMediaPlayer != null){
mBackgroundMediaPlayer.release();
}
mBackgroundMediaPlayer = createMediaplayerFromAssets(path);
// record the path
mCurrentPath = path;
}
}
if (mBackgroundMediaPlayer == null){
Log.e(TAG, "playBackgroundMusic: background media player is null");
} else {
// if the music is playing or paused, stop it
mBackgroundMediaPlayer.stop();
mBackgroundMediaPlayer.setLooping(isLoop);
try {
mBackgroundMediaPlayer.prepare();
mBackgroundMediaPlayer.seekTo(0);
mBackgroundMediaPlayer.start();
this.mIsPaused = false;
} catch (Exception e){
Log.e(TAG, "playBackgroundMusic: error state");
}
}
}
public void stopBackgroundMusic(){
if (mBackgroundMediaPlayer != null){
mBackgroundMediaPlayer.stop();
// should set the state, if not , the following sequence will be error
// play -> pause -> stop -> resume
this.mIsPaused = false;
}
}
public void pauseBackgroundMusic(){
if (mBackgroundMediaPlayer != null && mBackgroundMediaPlayer.isPlaying()){
mBackgroundMediaPlayer.pause();
this.mIsPaused = true;
}
}
public void resumeBackgroundMusic(){
if (mBackgroundMediaPlayer != null && this.mIsPaused){
mBackgroundMediaPlayer.start();
this.mIsPaused = false;
}
}
public void rewindBackgroundMusic(){
if (mBackgroundMediaPlayer != null){
mBackgroundMediaPlayer.stop();
try {
mBackgroundMediaPlayer.prepare();
mBackgroundMediaPlayer.seekTo(0);
mBackgroundMediaPlayer.start();
this.mIsPaused = false;
} catch (Exception e){
Log.e(TAG, "rewindBackgroundMusic: error state");
}
}
}
public boolean isBackgroundMusicPlaying(){
boolean ret = false;
if (mBackgroundMediaPlayer == null){
ret = false;
} else {
ret = mBackgroundMediaPlayer.isPlaying();
}
return ret;
}
public void end(){
if (mBackgroundMediaPlayer != null){
mBackgroundMediaPlayer.release();
}
initData();
}
public float getBackgroundVolume(){
if (this.mBackgroundMediaPlayer != null){
return (this.mLeftVolume + this.mRightVolume) / 2;
} else {
return 0.0f;
}
}
public void setBackgroundVolume(float volume){
if (volume < 0.0f){
volume = 0.0f;
}
if (volume > 1.0f){
volume = 1.0f;
}
this.mLeftVolume = this.mRightVolume = volume;
if (this.mBackgroundMediaPlayer != null){
this.mBackgroundMediaPlayer.setVolume(this.mLeftVolume, this.mRightVolume);
}
}
private void initData(){
mLeftVolume =0.5f;
mRightVolume = 0.5f;
mBackgroundMediaPlayer = null;
mIsPaused = false;
mCurrentPath = null;
}
/**
* create mediaplayer for music
* @param path the path relative to assets
* @return
*/
private MediaPlayer createMediaplayerFromAssets(String path){
MediaPlayer mediaPlayer = new MediaPlayer();
try{
if (path.startsWith("/")) {
mediaPlayer.setDataSource(path);
}
else {
AssetFileDescriptor assetFileDescritor = mContext.getAssets().openFd(path);
mediaPlayer.setDataSource(assetFileDescritor.getFileDescriptor(),
assetFileDescritor.getStartOffset(), assetFileDescritor.getLength());
}
mediaPlayer.prepare();
mediaPlayer.setVolume(mLeftVolume, mRightVolume);
}catch (Exception e) {
mediaPlayer = null;
Log.e(TAG, "error: " + e.getMessage(), e);
}
return mediaPlayer;
}
}

View File

@ -0,0 +1,137 @@
/****************************************************************************
Copyright (c) 2010-2011 cocos2d-x.org
http://www.cocos2d-x.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
package org.cocos2dx.lib;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import android.opengl.GLSurfaceView;
public class Cocos2dxRenderer implements GLSurfaceView.Renderer {
private final static long NANOSECONDSPERSECOND = 1000000000L;
private final static long NANOSECONDSPERMINISECOND = 1000000;
private static long animationInterval = (long)(1.0 / 60 * NANOSECONDSPERSECOND);
private long last;
private int screenWidth;
private int screenHeight;
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
nativeInit(screenWidth, screenHeight);
last = System.nanoTime();
}
public void setScreenWidthAndHeight(int w, int h){
this.screenWidth = w;
this.screenHeight = h;
}
public void onSurfaceChanged(GL10 gl, int w, int h) {
}
public void onDrawFrame(GL10 gl) {
long now = System.nanoTime();
long interval = now - last;
// should render a frame when onDrawFrame() is called
// or there is a "ghost"
nativeRender();
// fps controlling
if (interval < animationInterval){
try {
// because we render it before, so we should sleep twice time interval
Thread.sleep((animationInterval - interval) * 2 / NANOSECONDSPERMINISECOND);
} catch (Exception e){}
}
last = now;
}
public void handleActionDown(int id, float x, float y)
{
nativeTouchesBegin(id, x, y);
}
public void handleActionUp(int id, float x, float y)
{
nativeTouchesEnd(id, x, y);
}
public void handleActionCancel(int[] id, float[] x, float[] y)
{
nativeTouchesCancel(id, x, y);
}
public void handleActionMove(int[] id, float[] x, float[] y)
{
nativeTouchesMove(id, x, y);
}
public void handleKeyDown(int keyCode)
{
nativeKeyDown(keyCode);
}
public void handleOnPause(){
nativeOnPause();
}
public void handleOnResume(){
nativeOnResume();
}
public static void setAnimationInterval(double interval){
animationInterval = (long)(interval * NANOSECONDSPERSECOND);
}
private static native void nativeTouchesBegin(int id, float x, float y);
private static native void nativeTouchesEnd(int id, float x, float y);
private static native void nativeTouchesMove(int[] id, float[] x, float[] y);
private static native void nativeTouchesCancel(int[] id, float[] x, float[] y);
private static native boolean nativeKeyDown(int keyCode);
private static native void nativeRender();
private static native void nativeInit(int w, int h);
private static native void nativeOnPause();
private static native void nativeOnResume();
/////////////////////////////////////////////////////////////////////////////////
// handle input method edit message
/////////////////////////////////////////////////////////////////////////////////
public void handleInsertText(final String text) {
nativeInsertText(text);
}
public void handleDeleteBackward() {
nativeDeleteBackward();
}
public String getContentText() {
return nativeGetContentText();
}
private static native void nativeInsertText(String text);
private static native void nativeDeleteBackward();
private static native String nativeGetContentText();
}

View File

@ -0,0 +1,245 @@
/****************************************************************************
Copyright (c) 2010-2011 cocos2d-x.org
http://www.cocos2d-x.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
package org.cocos2dx.lib;
import java.util.ArrayList;
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;
/**
*
* This class is used for controlling effect
*
*/
public class Cocos2dxSound {
private Context mContext;
private SoundPool mSoundPool;
private float mLeftVolume;
private float mRightVolume;
// sound path and stream ids map
// a file may be played many times at the same time
// so there is an array map to a file path
private HashMap<String,ArrayList<Integer>> mPathStreamIDsMap;
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 static int INVALID_SOUND_ID = -1;
private final static int INVALID_STREAM_ID = -1;
public Cocos2dxSound(Context context){
this.mContext = context;
initData();
}
public int preloadEffect(String path){
Integer soundID = this.mPathSoundIdMap.get(path);
if (soundID == null) {
soundID = createSoundIdFromAsset(path);
this.mPathSoundIdMap.put(path, soundID);
}
return soundID;
}
public void unloadEffect(String path){
// stop effects
ArrayList<Integer> streamIDs = this.mPathStreamIDsMap.get(path);
if (streamIDs != null) {
for (Integer streamID : streamIDs) {
this.mSoundPool.stop(streamID);
}
}
this.mPathStreamIDsMap.remove(path);
// unload effect
Integer soundID = this.mPathSoundIdMap.get(path);
this.mSoundPool.unload(soundID);
this.mPathSoundIdMap.remove(path);
}
public int playEffect(String path, boolean isLoop){
Integer soundId = this.mPathSoundIdMap.get(path);
int streamId = INVALID_STREAM_ID;
if (soundId != null){
// play sound
streamId = this.mSoundPool.play(soundId.intValue(), this.mLeftVolume,
this.mRightVolume, SOUND_PRIORITY, isLoop ? -1 : 0, SOUND_RATE);
// record stream id
ArrayList<Integer> streamIds = this.mPathStreamIDsMap.get(path);
if (streamIds == null) {
streamIds = new ArrayList<Integer>();
this.mPathStreamIDsMap.put(path, streamIds);
}
streamIds.add(streamId);
} else {
// the effect is not prepared
soundId = preloadEffect(path);
if (soundId == INVALID_SOUND_ID){
// can not preload effect
return INVALID_SOUND_ID;
}
/*
* Someone reports that, it can not play effect for the
* first time. If you are lucky to meet it. There are two
* ways to resolve it.
* 1. Add some delay here. I don't know how long it is, so
* I don't add it here.
* 2. If you use 2.2(API level 8), you can call
* SoundPool.setOnLoadCompleteListener() to play the effect.
* Because the method is supported from 2.2, so I can't use
* it here.
*/
playEffect(path, isLoop);
}
return streamId;
}
public void stopEffect(int streamID){
this.mSoundPool.stop(streamID);
// remove record
for (String path : this.mPathStreamIDsMap.keySet()) {
if (this.mPathStreamIDsMap.get(path).contains(streamID)) {
this.mPathStreamIDsMap.get(path).remove(this.mPathStreamIDsMap.get(path).indexOf(streamID));
break;
}
}
}
public void pauseEffect(int streamID){
this.mSoundPool.pause(streamID);
}
public void resumeEffect(int streamID){
this.mSoundPool.resume(streamID);
}
public void pauseAllEffects(){
this.mSoundPool.autoPause();
}
public void resumeAllEffects(){
// autoPause() is available since level 8
this.mSoundPool.autoResume();
}
@SuppressWarnings("unchecked")
public void stopAllEffects(){
// stop effects
if (! this.mPathStreamIDsMap.isEmpty()) {
Iterator<?> iter = this.mPathStreamIDsMap.entrySet().iterator();
while (iter.hasNext()){
Map.Entry<String, ArrayList<Integer>> entry = (Map.Entry<String, ArrayList<Integer>>)iter.next();
for (int streamID : entry.getValue()) {
this.mSoundPool.stop(streamID);
}
}
}
// remove records
this.mPathStreamIDsMap.clear();
}
public float getEffectsVolume(){
return (this.mLeftVolume + this.mRightVolume) / 2;
}
@SuppressWarnings("unchecked")
public void setEffectsVolume(float volume){
// volume should be in [0, 1.0]
if (volume < 0){
volume = 0;
}
if (volume > 1){
volume = 1;
}
this.mLeftVolume = this.mRightVolume = volume;
// change the volume of playing sounds
if (! this.mPathStreamIDsMap.isEmpty()) {
Iterator<?> iter = this.mPathStreamIDsMap.entrySet().iterator();
while (iter.hasNext()){
Map.Entry<String, ArrayList<Integer>> entry = (Map.Entry<String, ArrayList<Integer>>)iter.next();
for (int streamID : entry.getValue()) {
this.mSoundPool.setVolume(streamID, mLeftVolume, mRightVolume);
}
}
}
}
public void end(){
this.mSoundPool.release();
this.mPathStreamIDsMap.clear();
this.mPathSoundIdMap.clear();
initData();
}
public int createSoundIdFromAsset(String path){
int soundId = INVALID_SOUND_ID;
try {
if (path.startsWith("/")){
soundId = mSoundPool.load(path, 0);
}
else {
soundId = mSoundPool.load(mContext.getAssets().openFd(path), 0);
}
} catch(Exception e){
soundId = INVALID_SOUND_ID;
Log.e(TAG, "error: " + e.getMessage(), e);
}
return soundId;
}
private void initData(){
this.mPathStreamIDsMap = new HashMap<String,ArrayList<Integer>>();
this.mPathSoundIdMap = new HashMap<String, Integer>();
mSoundPool = new SoundPool(MAX_SIMULTANEOUS_STREAMS_DEFAULT, AudioManager.STREAM_MUSIC, SOUND_QUALITY);
this.mLeftVolume = 0.5f;
this.mRightVolume = 0.5f;
}
}

View File

@ -0,0 +1,44 @@
/****************************************************************************
Copyright (c) 2010-2011 cocos2d-x.org
http://www.cocos2d-x.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
package org.cocos2dx.lib;
import java.util.Hashtable;
import android.content.Context;
import android.graphics.Typeface;
public class Cocos2dxTypefaces {
private static final Hashtable<String, Typeface> cache = new Hashtable<String, Typeface>();
public static Typeface get(Context context, String name){
synchronized(cache){
if (! cache.containsKey(name)){
Typeface t = Typeface.createFromAsset(context.getAssets(), name);
cache.put(name, t);
}
return cache.get(name);
}
}
}

View File

@ -0,0 +1,108 @@
/****************************************************************************
Copyright (c) 2010-2012 cocos2d-x.org
http://www.cocos2d-x.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
package org.cocos2dx.simplegame;
import org.cocos2dx.lib.Cocos2dxActivity;
import org.cocos2dx.lib.Cocos2dxEditText;
import org.cocos2dx.lib.Cocos2dxGLSurfaceView;
import org.cocos2dx.lib.Cocos2dxRenderer;
import android.app.ActivityManager;
import android.content.Context;
import android.content.pm.ConfigurationInfo;
import android.os.Bundle;
import android.util.Log;
import android.widget.FrameLayout;
import android.view.ViewGroup;
public class SimpleGame extends Cocos2dxActivity{
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
if (detectOpenGLES20()) {
// get the packageName,it's used to set the resource path
String packageName = getApplication().getPackageName();
super.setPackageName(packageName);
// FrameLayout
ViewGroup.LayoutParams framelayout_params =
new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,
ViewGroup.LayoutParams.FILL_PARENT);
FrameLayout framelayout = new FrameLayout(this);
framelayout.setLayoutParams(framelayout_params);
// Cocos2dxEditText layout
ViewGroup.LayoutParams edittext_layout_params =
new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
Cocos2dxEditText edittext = new Cocos2dxEditText(this);
edittext.setLayoutParams(edittext_layout_params);
// ...add to FrameLayout
framelayout.addView(edittext);
// Cocos2dxGLSurfaceView
mGLView = new Cocos2dxGLSurfaceView(this);
// ...add to FrameLayout
framelayout.addView(mGLView);
mGLView.setEGLContextClientVersion(2);
mGLView.setCocos2dxRenderer(new Cocos2dxRenderer());
mGLView.setTextField(edittext);
// Set framelayout as the content view
setContentView(framelayout);
}
else {
Log.d("activity", "don't support gles2.0");
finish();
}
}
@Override
protected void onPause() {
super.onPause();
mGLView.onPause();
}
@Override
protected void onResume() {
super.onResume();
mGLView.onResume();
}
private boolean detectOpenGLES20()
{
ActivityManager am =
(ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
ConfigurationInfo info = am.getDeviceConfigurationInfo();
return (info.reqGlEsVersion >= 0x20000);
}
static {
System.loadLibrary("game");
}
}