作者存档: 朱坤乾 - 第22页

解决appfuse中的ava.lang.ClassNotFoundException: org.aspectj.weaver.BCException错误

解决方案:强制maven-eclipse-plugin为2.9版本。

注意:这种操作需要先执行  mvn eclipse:clean 来清除旧数据。

<defaultGoal>install</defaultGoal>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-eclipse-plugin</artifactId>
<configuration>
<downloadSources>true</downloadSources>
</configuration>
<version>2.9</version>
</plugin>

 

异常信息如下:

 

ERROR [main] TestContextManager.prepareTestInstance(324) | Caught exception while allowing TestExecutionListener [org.springframework.test.context.support.DependencyInjectionTestExecutionListener@d6ef] to prepare test instance [org.haifi.service.GameBaseManagerTestCase@11f1520]
java.lang.IllegalStateException: Failed to load ApplicationContext
at org.springframework.test.context.TestContext.getApplicationContext(TestContext.java:157)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:109)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:75)
at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:321)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:211)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:288)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:290)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:231)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:49)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71)
at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:174)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:38)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:460)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:673)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:386)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘userManagerTx’: Initialization of bean failed; nested exception is java.lang.NoClassDefFoundError: org/aspectj/weaver/BCException
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:527)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:294)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:225)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:291)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:605)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:925)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:472)
at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:103)
at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:1)
at org.springframework.test.context.support.DelegatingSmartContextLoader.loadContext(DelegatingSmartContextLoader.java:228)
at org.springframework.test.context.TestContext.loadApplicationContext(TestContext.java:124)
at org.springframework.test.context.TestContext.getApplicationContext(TestContext.java:148)
… 24 more
Caused by: java.lang.NoClassDefFoundError: org/aspectj/weaver/BCException
at java.lang.Class.getDeclaredConstructors0(Native Method)
at java.lang.Class.privateGetDeclaredConstructors(Class.java:2404)
at java.lang.Class.getDeclaredConstructors(Class.java:1853)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.determineCandidateConstructors(AutowiredAnnotationBeanPostProcessor.java:229)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.determineConstructorsFromBeanPostProcessors(AbstractAutowireCapableBeanFactory.java:962)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:935)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:485)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveInnerBean(BeanDefinitionValueResolver.java:271)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:126)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1360)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1118)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:517)
… 37 more
Caused by: java.lang.ClassNotFoundException: org.aspectj.weaver.BCException
at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
at java.lang.ClassLoader.loadClass(ClassLoader.java:423)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
at java.lang.ClassLoader.loadClass(ClassLoader.java:356)
… 50 more

游戏开发准备(四)--多线程处理数据

1、游戏对时时性较高的,基本上都使用时时操作内存+定时入库的方式。部分涉及到重要数据如金币等,才采用时时入库。

2、操作内存时为了避免多个线程同时操作相同一条数据,通过会开以业务类型分为以下几种:

1)全服单线程,一个例子是战斗。这样可以避免两个线程同时操作同一个对象的属性。为了优化,也可以在每个地图(或副本)上是单线程。全服单线程的另一个例子是玩家交易。

2)角色单线程,每个角色单线程处理,大部对角色的操作都可以归入此类。

3)多线程操作,无需担心操作同一块内存,这种情况通常都是查询数据请求,没有修改的操作。绝大部分玩家消息都是归入此类。

todo:研究一下spring的线程池

spring配置线程池:

<!– 处理用户请求的线程池 –>
<bean id=”taskExecutor”
class=”org.springframework.scheduling.concurrent.threadpooltaskexecutor”>
<property name=”corePoolSize” value=”5″ />
<property name=”maxPoolSize” value=”10″ /> // 最大线程数
<property name=”queueCapacity” value=”100″ /> // 消息队列容量
<property name=”keepAliveSeconds” value=”10000″ /> // 存活时间,可以设置的长一些
</bean>

线程池要添加的线程需要实现Runnable接口,不是Thread。

每次用时直接把Runnable对象丢进taskExecutor,线程池会负责调用。

 

游戏开发准备(三)--传输协议

google 的 protobuf 是最近非常火的将结构对象进行序列化及反序列化的工具,据google称,已经应用在了google非常多的内部项目上。

1、下载protobuf,protoc:

https://code.google.com/p/protobuf/downloads/detail?name=protobuf-2.4.1.tar.bz2&can=2&q=

https://code.google.com/p/protobuf/downloads/detail?name=protoc-2.4.1-win32.zip&can=2&q=

2、下载下来的protoc放在 protobuf/java/src目录下

3、在protobuf/java目录下修改pom.xml(仅windows下需要修改)

<exec executable=”../src/protoc”>

修改为:

<exec executable=”src\protoc.exe”>

4、执行:

mvn test

mvn install 安装至 maven repository

mvn package 可以打包成jar包,供单独使用

mvn install -P lite 生成lite版本,lite缺少描述及反射功能,但在手机平台上推荐使用

这里我也打包了jar包,用来学习时使用。

5、在eclipse中创建java工程,来学习一下protobuf的使用

建立addressbook.proto

option java_package = “com.example.tutorial”;

message Person {
required string name = 1;
required int32 id = 2;        // Unique ID number for this person.
optional string email = 3;

enum PhoneType {
MOBILE = 0;
HOME = 1;
WORK = 2;
}

message PhoneNumber {
required string number = 1;
optional PhoneType type = 2 [default = HOME];
}

repeated PhoneNumber phone = 4;
}

// Our address book file is just one of these.
message AddressBook {
repeated Person person = 1;
}

执行:

protoc addressbook –java-out=.

使用方式:

Person p = Person.newBuilder().setName(“hello world”).setId(111)
.build();
System.out.println(p.toByteArray().length);

toByteArray()进行序列化,parseFrom()进行反序列化。

下面在maven中集成:

添加plugin:

<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<id>generate-sources</id>
<phase>generate-sources</phase>
<configuration>
<tasks>
<mkdir dir=”target/generated-sources” />
<exec executable=”protoc”>
<arg
value=”–java_out=target/generated-sources” />
<arg
value=”src/main/protobuf/test.proto” />
</exec>
</tasks>
<sourceRoot>
target/generated-sources
</sourceRoot>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>

添加dependency:

<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>2.4.1</version>
</dependency>

里面有一个反射机制,需要查一下能起到什么作用

optimize_for 这个选项需要关注一下,如果开发手机网游,这个选项会有大用处。

option optimize_for = SPEED; // 默认

CODE_SIZE

LITE_RUNTIME //手机网游推荐使用这种

另外,需要检查一下protobuf的压缩。测试了一下,字符串好像并未压缩。

从smartfox上查找一下他们用的压缩工具,继续测试一下。

决定使用snappy算法。

https://github.com/dain/snappy

各种压缩算法在java平台上的测试结果。

实际测试后压缩效果不尽如人意,使用了deflate和snappy压缩算法,分别测试了小于20字节和120字节的压缩,只能压缩不到20%,初始怀疑protobuf的二进制已经充分优化过了,如果是这样的话,再消耗cpu进行压缩就没有必要了。但是也不排除测试的样本太少。可以等正式上线后,再回头进行压缩的测试。对了,snappy必须在jdk7下运行,因为用了到sun的非公开函数,所以需要注意一下是目标环境是否支持。

使用protobuf还有一个好处,可以避免使用java反射机制带来的效率降低。

游戏开发准备(二)--服务器端准备工作

新的游戏准备继续使用appfuse。

接触到的两款游戏没有放在web容器中执行,但我希望依旧保留web功能,在未来会有一些交互性及管理的功能使用web来实现。

而且mina也支持与tomcat整合。

OK。下面开始准备新的appfuse 2.0工程:

1、JDK 6+

2、mysql 5.5+(我使用的是mysql5.0,但我认为已经足够了,没有必要进行升级)

3、需要修改mail.properties,发送mail的功能随后我会修改掉,可以忽略这条。

4、Maven 3.0.4+,(另外还得准备好maven 2.x版本,full-source在3.x下无法执行通过)

下面开始生成项目文件:

1、mvn archetype:generate -B -DarchetypeGroupId=org.appfuse.archetypes -DarchetypeArtifactId=appfuse-basic-struts-archetype -DarchetypeVersion=2.1.0 -DgroupId=org.haifi -DartifactId=igame -DarchetypeRepository=http://oss.sonatype.org/content/repositories/appfuse

2、进入igame目录,修改pom.xml,设置db连接,执行:mvn jetty:run-war

可以在浏览器访问:http://127.0.0.1:8080/

3、执行:mvn appfuse:full-source (这里需要maven 2.x来执行)

如果出现错误:

[FATAL] Non-resolvable parent POM: Could not find artifact org.appfuse:appfuse:p
om:2.2-SNAPSHOT and ‘parent.relativePath’ points at wrong local POM @ line 21, c
olumn 13

那就表示你用了maven 3.x。

添加包依赖,不知道为什么默认没有。缺少包可以去http://search.maven.org下载

<aspectj.version>1.6.9</aspectj.version>
<commons.beanutils.version>1.8.3</commons.beanutils.version>
<commons.collections.version>3.2.1</commons.collections.version>
<commons.dbcp.version>1.3</commons.dbcp.version>
<commons.lang.version>2.5</commons.lang.version>
<compass.version>2.2.0</compass.version>
<cxf.version>2.2.4</cxf.version>
<dwr.version>2.0.1</dwr.version>
<ehcache.version>2.2.0</ehcache.version>
<ehcache.web.version>2.0.2</ehcache.web.version>
<hibernate.annotations.version>3.6.0-SNAPSHOT</hibernate.annotations.version>
<hibernate.version>3.6.9.Final</hibernate.version>
<jpa.version>2.0.Beta2</jpa.version>
<javamail.version>1.4.1</javamail.version>
<jstl.version>1.1.2</jstl.version>
<log4j.version>1.2.16</log4j.version>
<sitemesh.version>2.4.2</sitemesh.version>
<slf4j.version>1.6.1</slf4j.version>
<spring.security.version>3.0.4.RELEASE</spring.security.version>
<struts.menu.version>2.4.3</struts.menu.version>
<urlrewrite.version>3.1.0</urlrewrite.version>
<velocity.version>1.4</velocity.version>

另外添加:

<repository>
<id>central</id>
<url>http://search.maven.org</url>
</repository>
<repository>
<id>appfuse</id>
<url>https://repository.sonatype.org/content/groups/public</url>
</repository>
<repository>
<id>springsource-repo</id>
<name>springsource repository</name>
<url>http://repo.springsource.org/release</url>
</repository>
<repository>
<id>repository.jboss.org-public</id>
<name>JBoss repository</name>
<url>https://repository.jboss.org/nexus/content/groups/public</url>
</repository>

4、下载源码包:mvn dependency:sources

5、mvn org.apache.maven.plugins:maven-eclipse-plugin:2.6:eclipse

然后在eclipse中导入工程。

继续后续修改:

1、pom.xml中修改

<amp.genericCore>false</amp.genericCore>
<amp.fullSource>true</amp.fullSource>

2、properties语种文件中我们只保留 zh_EN,zh_TW,en及默认,其它删除。

删除test目录下的jdbc.properties,log4j.xml

3、我把整个工程的字符集设置为UTF8

或者更好的一种方式:

<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.0.2</version>
<configuration>
<encoding>UTF-8</encoding>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>

4、web.xml中启用lazyloadfilter,gzipfilter暂时和xfire有冲突,暂时不启用。

5、优化 applicationContext-resources.xml中设置

<bean id=”dataSource”
class=”org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy”>
<property name=”targetDataSource” ref=”targetDataSource” />
</bean>

可以避免空事务去连数据库

6、修改applicationContext-dao.xml

添加:

hibernate.hbm2ddl.auto=update
hibernate.show_sql=false

7、添加mina支持

<dependency>
<groupId>org.apache.mina</groupId>
<artifactId>mina-core</artifactId>
<version>${mina.version}</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.apache.mina</groupId>
<artifactId>mina-integration-beans</artifactId>
<version>${mina.version}</version>
</dependency>

因为mian打包格式是bundle,需要添加:

<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
</plugin>

在spring中添加

<!– mina game server –>
<bean id=”trapHandler”
init-method=”start” />

<bean id=”snmpCodecFilter”
class=”org.apache.mina.filter.codec.ProtocolCodecFilter”>
<constructor-arg>
<bean
class=”org.apache.mina.filter.codec.textline.TextLineCodecFactory” />
</constructor-arg>
</bean>

<bean id=”loggingFilter”
class=”org.apache.mina.filter.logging.LoggingFilter” />

<!– The filter chain. –>
<bean id=”filterChainBuilder”
class=”org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder”>
<property name=”filters”>
<map>
<entry key=”loggingFilter” value-ref=”loggingFilter” />
<entry key=”codecFilter” value-ref=”snmpCodecFilter” />
</map>
</property>
</bean>
<bean
class=”org.springframework.beans.factory.config.CustomEditorConfigurer”>
<property name=”customEditors”>
<map>
<entry key=”java.net.SocketAddress”>
<bean
class=”org.apache.mina.integration.beans.InetSocketAddressEditor” />
</entry>
</map>
</property>
</bean>
<bean id=”ioAcceptor”
class=”org.apache.mina.transport.socket.nio.NioSocketAcceptor”
init-method=”bind” destroy-method=”unbind” lazy-init=”false”>
<property name=”defaultLocalAddress” value=”:8888″ />
<property name=”handler” ref=”trapHandler” />
<property name=”filterChainBuilder” ref=”filterChainBuilder” />
</bean>

8、创建测试样例类:

在src/test/java下建立

public class GameBaseManagerTestCase extends BaseManagerTestCase {

// 这里指定testcase读取的spring配置文件

protected String[] getConfigLocations() {
setAutowireMode(AUTOWIRE_BY_NAME);

return new String[] { “/applicationContext-resources.xml”,
“classpath:/applicationContext-dao.xml”,
“/applicationContext-service.xml”,
“classpath*:/**/applicationContext-event.xml”,
“classpath*:/**/applicationContext-ds.xml”,
“classpath*:/**/applicationContext.xml”,
“classpath*:/**/applicationContext-activemq.xml”,
“classpath*:/**/applicationContext-job.xml”,
“classpath*:/**/remoting-servlet.xml”, };
}

// 这里添加自己多增加的资源文件,可以让测试样例读取到
@Override
protected void onSetUp() throws Exception {
super.onSetUp();
//
// 使用LocalizedTextUtil可以读取到wgame中的资源文件
LocalizedTextUtil.addDefaultResourceBundle(“ApplicationResources”);
LocalizedTextUtil.addDefaultResourceBundle(“ApplicationResources_enum”);
LocalizedTextUtil.addDefaultResourceBundle(“ApplicationResources_log”);
LocalizedTextUtil
.addDefaultResourceBundle(“ApplicationResources_exception”);
// 初始化测试对象
if (initPlayers) {
initPlayers();
}
time = System.currentTimeMillis();
GameDynamicElement.skipTournament=true;
log.debug(“———————- start ” + getName()
+ ” ———————–“);

}

 

9、因为工程转为使用UTF-8编码,如果遇到如下错误“ 编码 GB18030 的不可映射字符”,在pom.xml中修改如下:

<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.0.2</version>
<configuration>
<encoding>UTF-8</encoding>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>

10:为maven-javadoc添加额外的java源码目录:

<defaultGoal>install</defaultGoal>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>1.7</version>
<executions>
<execution>
<id>add-source</id>
<phase>generate-sources</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>src/main/protobuf/java</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>

或者用另一种方式:

<artifactId>maven-javadoc-plugin</artifactId>
<version>2.9</version>
<configuration>
<excludePackageNames>
org.haifi.webapp:org.haifi.dao:org.haifi.service:org.haifi.game.reflection:org.haifi.game.channel:org.haifi.game.compiler:org.haifi.game.mina
</excludePackageNames>
<sourcepath>${basedir}/src/main/java;${basedir}/src/main/protobuf/java</sourcepath>
</configuration>

直接指定源文件所在目录

11:添加spring http invoker支持:

定义applicationContext-remoting.xml文件:

<bean name=”/GameUserService”
class=”org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter”>
<property name=”service” ref=”localGameUserRemotingManager” />
<property name=”serviceInterface”
value=”org.haifi.game.service.GameUserRemotingManager” />
</bean>

<!– 定义为local,可以提供给测试样例调用 –>
<bean name=”localGameUserRemotingManager”
class=”org.haifi.game.service.impl.GameUserRemotingManagerImpl” />

web.xml中添加:

<!– 支持sprint http invoker –>
<servlet>
<servlet-name>remoting</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<init-param>
<param-name>namespace</param-name>
<param-value>applicationContext-remoting</param-value>
</init-param>
<!– default context config location:remoting-servlet.xml –>
<load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
<servlet-name>remoting</servlet-name>
<url-pattern>/gr/*</url-pattern>
</servlet-mapping>

可是浪费了好几个小时怎么还不生效呢。原来是urlwrite搞的鬼:

urlrewrite中添加:

<rule>
<from>/gr/**</from>
<to>/gr/$1</to>
</rule>

好了,下面开始客户端进行调用:因为游戏中的url是不固定的,所以需要用代码生成client:

HttpInvokerProxyFactoryBean bean = new HttpInvokerProxyFactoryBean();
bean.setServiceUrl(“http://127.0.0.1:8080/gr/GameUserService”);
bean.setServiceInterface(GameUserRemotingManager.class);
bean.setHttpInvokerRequestExecutor(new CommonsHttpInvokerRequestExecutor());
bean.afterPropertiesSet();
GameUserRemotingManager obj = (GameUserRemotingManager) bean
.getObject();
log.info(obj);

游戏开发准备(-)--配置应该在哪里 

配置是指游戏中所必须的初始数据,包含npc,装备,对话等所有相关内容。

配置应该存放在excel中,策划人员更愿意去修改excel。

存放在excel中的配置,应该保证只修改,增加,不要删除,因为id可能已经被玩家数据引用到了。

为了方便程序员容易处理excel至游戏数据的转化,我们可以指定第一行为属性名,使用java的反射机制直接生成java对象,这个工具还需要手动来实现,过程不是很麻烦。

如果为了更高的要求,可以在excel中支持公式计算的结果(这种结果对策划来说交互性更好)。

opengles中画四边型

opengles中仅支持以下几种模型:

/* BeginMode */
#define GL_POINTS                         0x0000
#define GL_LINES                          0x0001
#define GL_LINE_LOOP                      0x0002
#define GL_LINE_STRIP                     0x0003
#define GL_TRIANGLES                      0x0004
#define GL_TRIANGLE_STRIP                 0x0005
#define GL_TRIANGLE_FAN                   0x0006

所以如果需要画一个四边型,需要借助GL_TRIANGLES_STRIP

static const GLfloat vertices[] = { -1.0, 1.0, -0.0, 1.0, 1.0, -0.0, -1.0,
-1.0, -0.0, 1.0, -1.0, -0.0 };

static const GLfloat texCoords[] =
{ 0.0, 1.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.0 };

glBindTexture(GL_TEXTURE_2D, 1);
glVertexPointer(3, GL_FLOAT, 0, vertices);
glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

如此即可画出一个四边型

stl_bvector.h expected unqualified-id before ‘(‘ token

解决方案参考:

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=16605

Your code defines min/max as macros. The preprocessor expands this, which 
leaves what used to be std::max(x1, x2) as something that doesn't make 
much sense to the compiler any more. 

Since the standard says that the names min/max are reserved, simply 
remove these #defines from your sources. 

W.

使用cximage及curl下载图片,生成纹理

GLint TextureManager::generateTextureFromPNG(char* url) {
// 下载图片
DownloadResources dr;
initDownloadResource(&dr, url);
download_image(&dr);

CxImage image((BYTE*) dr.memoeryBuff, dr.size, CXIMAGE_FORMAT_PNG);

// TODO:这里能先释放dr的内存吗
if (image.IsValid()) {
logInfo(“load image ok %s:”, url);
} else {
logError(“load image error %s:”, url);
}

int width = image.GetWidth();
int height = image.GetHeight();

GLuint ids[1];
glGenTextures(1, ids);
LOGI(“gl texture id:%d”, ids[0]);
glBindTexture(GL_TEXTURE_2D, ids[0]);

BYTE* glimagedata = NULL;
if (image.AlphaIsValid()) {
long t = width * height * 4;
// 有alpha通道
if (!image.Encode2RGBA(glimagedata, t)) {
LOGE(“image encode 2 rgba error.%s”, image.GetLastError());
}
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA,
GL_UNSIGNED_BYTE, glimagedata);
checkGlError(“generate texture”);
} else {
LOGE(“image is not support alpha.”);
}

image.FreeMemory(glimagedata); //释放内存空间
freeDownloadResource(&dr); // 释放掉下载的文件占用的内存
return ids[0];
}

curl 下载例子

/*
* curlutil.h
*
* curl工具库,用来处理下载图片及其它资源
*
*  Created on: 2012-10-22
*      Author: joycube2
*/

#ifndef CURLUTIL_H_
#define CURLUTIL_H_

#include “curl.h”
#include “all_include.h”
#include “predef.h”
/*
* 内存对象,用来在每次读取到chunk后,暂时保存读到的数据
* 用来封装好,提供给外部调用
*
* samples:
*
* DownloadResources downloadResources;
* initDownloadResource(&downloadResources,url);
* download_image(&downloadResources);
* …
* freeDownloadResource(&downloadResources);
*/
struct DownloadResources {
char* url;
char* memoeryBuff;
size_t size;
};

/*
* 初始化downloadResource对象一些相差的初始化信息
*/
void initDownloadResource(DownloadResources* downloadResources, char* url) {
downloadResources->url = url;
downloadResources->memoeryBuff = NULL;
downloadResources->size = 0;
}

/*
* 释放分配的内存空间
*/
void freeDownloadResource(DownloadResources* downloadResources) {
if (downloadResources->memoeryBuff) {
free(downloadResources->memoeryBuff);
}
}

size_t write_data(char *responseContent, size_t size, size_t nmemb,
void *userdata) {
logDebug(“curl response: size:%d nmemb:%d”, size, nmemb);
size_t realSize = size * nmemb;

struct DownloadResources* mem = (struct DownloadResources*) userdata;

if (mem->size == 0) {
mem->memoeryBuff = (char*) malloc(realSize);
memcpy(mem->memoeryBuff, responseContent, realSize);
} else {
mem->memoeryBuff = (char*) realloc(mem->memoeryBuff,
mem->size + realSize);
memcpy(mem->memoeryBuff + mem->size, responseContent, realSize);
}

mem->size += realSize;

return realSize;
}
/*
* 试试能不能直接给指针
*/
void download_image(DownloadResources* downloadResources) {
logInfo(“download %s”,downloadResources->url);

CURL * curl;
CURLcode res;

curl = curl_easy_init();

if (curl) {
curl_easy_setopt(curl, CURLOPT_URL, downloadResources->url);

curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);

curl_easy_setopt(curl, CURLOPT_WRITEDATA, downloadResources);

res = curl_easy_perform(curl);

curl_easy_cleanup(curl);

if (res != CURLE_OK) {
logError(“failed:%s”, curl_easy_strerror(res));
}
} else {
logError(“failed:%s”, curl_easy_strerror(res));
}
}

#endif /* CURLUTIL_H_ */

ndk下使用动态库及静态库

以libpng为例。

如果使用动态库:

1、新建android工程,创建jni目录,其它步骤不多说了,参考官方的ndk入门就可以了。

将libpng所需源文件放在jni目录下,

并编写Android.mk

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)

LOCAL_CFLAGS :=

LOCAL_MODULE    := png
LOCAL_SRC_FILES :=\
png.c \
pngerror.c \
pngget.c \
pngmem.c \
pngpread.c \
pngread.c \
pngrio.c \
pngrtran.c \
pngrutil.c \
pngset.c \
pngtrans.c \
pngwio.c \
pngwrite.c \
pngwtran.c \
pngwutil.c

LOCAL_LDLIBS := -lz

#include $(BUILD_SHARED_LIBRARY)
include $(BUILD_STATIC_LIBRARY)

编写Application.mk

APP_OPTIM := release
APP_MODULES := libpng

然后编译,执行成功后会生成

libpng.so文件。

好了,动态链接库已经生成。将此文件复制至自己的工程的jni目录下。

Android.mk修改如下:

# See the License for the specific language governing permissions and
# limitations under the License.
#
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := png
LOCAL_SRC_FILES := libpng.so
include ${PREBUILT_SHARED_LIBRARY}

include $(CLEAR_VARS)
LOCAL_MODULE    := libgl2jni
LOCAL_CFLAGS    := -Werror
LOCAL_SHARED_LIBRARIES := png
#LOCAL_STATIC_LIBRARIES := libpng
#LOCAL_C_INCLUDES += $(LOCAL_PATH)/png
LOCAL_SRC_FILES := gl_code.cpp
LOCAL_LDLIBS    := -llog -lGLESv1_CM -lz
include $(BUILD_SHARED_LIBRARY)

在java代码中也别忘记加载动态库:

static {
System.loadLibrary(“stlport_shared”); // 加载stl的动态库
System.loadLibrary(“png”); // 加载gl2库
System.loadLibrary(“gl2jni”); // 加载gl2库
}

因为gl2jni使用了png库,所以要先加载png库,再加载gl2jni库。

为了方便,在google code已经建立好了工程,可位可以直接下载编译:

http://code.google.com/p/android-ndk-libpng/

——————————————————————————————————–

如果使用静态库:

将以上源代码放在项目的jni目录下

修改Android.mk为:

LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE    := libgl2jni
LOCAL_CFLAGS    := -Werror
LOCAL_SRC_FILES := gl_code.cpp
LOCAL_STATIC_LIBRARIES := png
#LOCAL_C_INCLUDES += $(LOCAL_PATH)/png
LOCAL_LDLIBS    := -llog -lGLESv1_CM -lz

include $(BUILD_SHARED_LIBRARY)

include $(CLEAR_VARS)

include $(LOCAL_PATH)/png/Android.mk