我需要安慰修改一个E语言源码中的一段代码,但这段代码被加密了

我厂里有台机子用来车槽面用的,把工件安上去左右来回切出一个凹槽,其中启动机子时要运行一段代码G92X0Y0Z0A0具体什么意思,我知道这段代码是用来回零点的,G92怎么解释_百度作业帮
我厂里有台机子用来车槽面用的,把工件安上去左右来回切出一个凹槽,其中启动机子时要运行一段代码G92X0Y0Z0A0具体什么意思,我知道这段代码是用来回零点的,G92怎么解释
不同的系统该指令作用也是不一样的要看你的系统例如faunc中,G92 可以用来加工螺纹(单一循环指令)也可以用来制定坐标系表示当前刀尖点的坐标为X0Y0Z0A0
您可能关注的推广回答者:回答者:回答者:dreamweave中,下面是一段代码,但是为什么,总是只能在一个td中使用这段代码,如果要实现多个?_百度知道
dreamweave中,下面是一段代码,但是为什么,总是只能在一个td中使用这段代码,如果要实现多个?
如果要实现多个就会只能执行最后一个,前面都不能实现翻滚的效果了。请高手指教,该修改那里,可以实现在一个页面中的多个td中实现翻滚的效果。&html&&head&&meta http-equiv=&Content-Type& content=&text/ charset=gb2312&&&title&无标题文档&/title&&style type=&text/css&&&!--body --&&/style&&/head&&body&&table width=&728&
border=&0& align=&center& cellpadding=&0& cellspacing=&0&&
&td width=&200&&&div id=icefable2&
&table width=&200&
border=&0& cellpadding=&0& cellspacing=&0&&
&td width=&200& height=&60& bgcolor=&#0099CC&&1&/td&
&td height=&60& bgcolor=&#00FFCC&&2&/td&
&/table&
&script&marqueesHeight=60;stopscroll=with(icefable2){
style.width=0;
style.height=marqueesH
style.overflowX=&visible&;
style.overflowY=&hidden&;
onmouseover=new Function(&stopscroll=true&);
onmouseout=new Function(&stopscroll=false&);
preTop=0; currentTop=marqueesH stoptime=0;
icefable2.innerHTML+=icefable2.innerHTML;function init_srolltext(){
icefable2.scrollTop=0;
setInterval(&scrollUp()&,1);}init_srolltext();function scrollUp(){
if(stopscroll==true)
currentTop+=1;
if(currentTop==marqueesHeight+1)
stoptime+=1;
currentTop-=1;
if缉耿光际叱宦癸为含力(stoptime==300)
currentTop=0;
stoptime=0;
preTop=icefable2.scrollT
icefable2.scrollTop+=1;
if(preTop==icefable2.scrollTop){
icefable2.scrollTop=marqueesH
icefable2.scrollTop+=1;
}}init_srolltext();
&/script&
&/div& &/td&
&/tr&&/table&&/body&&/html&
我还碰到一个现象就是,如果插入多个td并给了同样的代码之后,能实现翻滚的那个t缉耿光际叱宦癸为含力d的翻滚速度就快了很多,该怎么修改呢?我我只有5分~~~~~~~~~
我有更好的答案
这个里面的javascript代码,好像比较古老?咱是初学,看不大明白,只是添加修改了一下样式,实现了多个内容一起滚动效果,也可以添加更多的滚动内容。用的是IE8.0。============================================&html&
&meta http-equiv=&Content-Type& content=&text/ charset=gb2312&&
无标题文档
&style type=&text/css&&
&!-- #icefable2 .icefable2 { float: } --&
&table width=&728& height=&60& border=&0& align=&center& cellpadding=&0&
cellspacing=&0&&
&td width=&400&&
&div id=icefable2&
&table width=&200& border=&0& cellpadding=&0& cellspacing=&0& class=&icefable2&&
&td width=&200& height=&60& bgcolor=&#0099CC&&
&td height=&60& bgcolor=&#00FFCC&&
&table width=&200& border=&0& cellpadding=&0& cellspacing=&0& class=&icefable2&&
&tr&&td width=&200& height=&60& bgcolor=&#FF9900&&
&td height=&60& bgcolor=&#FF0000&&
&table width=&200& border=&0& cellpadding=&0& cellspacing=&0& class=&icefable2&&
&l缉耿光际叱宦癸为含力t;tr&
&td width=&200& height=&60& bgcolor=&#FF00FF&&
&td height=&60& bgcolor=&#FFCCFF&&
marqueesHeight = 60;
stopscroll =
with(icefable2) {
style.width = 600;
style.height = marqueesH
style.overflowX = &visible&;
style.overflowY = &hidden&;
onmouseover = new Function(&stopscroll=true&);
onmouseout = new Function(&stopscroll=false&);
preTop = 0;
currentTop = marqueesH
stoptime = 0;
icefable2.innerHTML += icefable2.innerHTML;
function init_srolltext() {
icefable2.scrollTop = 0;
setInterval(&scrollUp()&, 1);
init_srolltext();
function scrollUp() {
if (stopscroll == true)
currentTop += 1;
if (currentTop == marqueesHeight + 1) {
stoptime += 1;
currentTop -= 1;
if (stoptime == 300) {
currentTop = 0;
stoptime = 0;
preTop = icefable2.scrollT
icefable2.scrollTop += 1;
if (preTop == icefable2.scrollTop) {
icefable2.scrollTop = marqueesH
icefable2.scrollTop += 1;
init_srolltext();
&/body&&/html&
其他类似问题
dreamweave的相关知识
等待您来回答
下载知道APP
随时随地咨询
出门在外也不愁developerWorks 社区
Java程序的源代码很容易被别人偷看。只要有一个反编译器,任何人都可以分析别人的代码。本文讨论如何在不修改原有程序的情况下,通过加密技术保护源代码。
(), 软件工程师,独立顾问和自由撰稿人
俞良松,软件工程师,独立顾问和自由撰稿人。最初从事PB和Oracle开发,现主要兴趣在于Internet开发。您可以通过
和我联系。
为什么要加密?
对于传统的C或C++之类的语言来说,要在Web上保护源代码是很容易的,只要不发布它就可以。遗憾的是,Java程序的源代码很容易被别人偷看。只要有一个反编译器,任何人都可以分析别人的代码。Java的灵活性使得源代码很容易被窃取,但与此同时,它也使通过加密保护代码变得相对容易,我们唯一需要了解的就是Java的ClassLoader对象。当然,在加密过程中,有关Java
Cryptography Extension(JCE)的知识也是必不可少的。
有几种技术可以“模糊”Java类文件,使得反编译器处理类文件的效果大打折扣。然而,修改反编译器使之能够处理这些经过模糊处理的类文件并不是什么难事,所以不能简单地依赖模糊技术来保证源代码的安全。我们可以用流行的加密工具加密应用,比如PGP(Pretty Good
Privacy)或GPG(GNU Privacy
Guard)。这时,最终用户在运行应用之前必须先进行解密。但解密之后,最终用户就有了一份不加密的类文件,这和事先不进行加密没有什么差别。
Java运行时装入字节码的机制隐含地意味着可以对字节码进行修改。JVM每次装入类文件时都需要一个称为ClassLoader的对象,这个对象负责把新的类装入正在运行的JVM。JVM给ClassLoader一个包含了待装入类(比如java.lang.Object)名字的字符串,然后由ClassLoader负责找到类文件,装入原始数据,并把它转换成一个Class对象。
我们可以通过定制ClassLoader,在类文件执行之前修改它。这种技术的应用非常广泛――在这里,它的用途是在类文件装入之时进行解密,因此可以看成是一种即时解密器。由于解密后的字节码文件永远不会保存到文件系统,所以窃密者很难得到解密后的代码。
由于把原始字节码转换成Class对象的过程完全由系统负责,所以创建定制ClassLoader对象其实并不困难,只需先获得原始数据,接着就可以进行包含解密在内的任何转换。Java 2在一定程度上简化了定制ClassLoader的构建。在Java
2中,loadClass的缺省实现仍旧负责处理所有必需的步骤,但为了顾及各种定制的类装入过程,它还调用一个新的findClass方法。
这为我们编写定制的ClassLoader提供了一条捷径,减少了麻烦:只需覆盖findClass,而不是覆盖loadClass。这种方法避免了重复所有装入器必需执行的公共步骤,因为这一切由loadClass负责。
不过,本文的定制ClassLoader并不使用这种方法。原因很简单。如果由默认的ClassLoader先寻找经过加密的类文件,它可以找到;但由于类文件已经加密,所以它不会认可这个类文件,装入过程将失败。因此,我们必须自己实现loadClass,稍微增加了一些工作量。定制类装入器
每一个运行着的JVM已经拥有一个ClassLoader。这个默认的ClassLoader根据CLASSPATH环境变量的值,在本地文件系统中寻找合适的字节码文件。
应用定制ClassLoader要求对这个过程有较为深入的认识。我们首先必须创建一个定制ClassLoader类的实例,然后显式地要求它装入另外一个类。这就强制JVM把该类以及所有它所需要的类关联到定制的ClassLoader。Listing
1显示了如何用定制ClassLoader装入类文件。【Listing 1:利用定制的ClassLoader装入类文件】
// 首先创建一个ClassLoader对象
ClassLoader myClassLoader = new myClassLoader();
// 利用定制ClassLoader对象装入类文件
// 并把它转换成Class对象
Class myClass = myClassLoader.loadClass( "mypackage.MyClass" );
// 最后,创建该类的一个实例
Object newInstance = myClass.newInstance();
// 注意,MyClass所需要的所有其他类,都将通过
// 定制的ClassLoader自动装入
如前所述,定制ClassLoader只需先获取类文件的数据,然后把字节码传递给运行时系统,由后者完成余下的任务。
ClassLoader有几个重要的方法。创建定制的ClassLoader时,我们只需覆盖其中的一个,即loadClass,提供获取原始类文件数据的代码。这个方法有两个参数:类的名字,以及一个表示JVM是否要求解析类名字的标记(即是否同时装入有依赖关系的类)。如果这个标记是true,我们只需在返回JVM之前调用resolveClass。【Listing 2:ClassLoader.loadClass()的一个简单实现】
public Class loadClass( String name, boolean resolve )
throws ClassNotFoundException {
// 我们要创建的Class对象
Class clasz =
// 必需的步骤1:如果类已经在系统缓冲之中,
// 我们不必再次装入它
clasz = findLoadedClass( name );
if (clasz != null)
// 下面是定制部分
byte classData[] = /* 通过某种方法获取字节码数据 */;
if (classData != null) {
// 成功读取字节码数据,现在把它转换成一个Class对象
clasz = defineClass( name, classData, 0, classData.length );
// 必需的步骤2:如果上面没有成功,
// 我们尝试用默认的ClassLoader装入它
if (clasz == null)
clasz = findSystemClass( name );
// 必需的步骤3:如有必要,则装入相关的类
if (resolve && clasz != null)
resolveClass( clasz );
// 把类返回给调用者
} catch( IOException ie ) {
throw new ClassNotFoundException( ie.toString() );
} catch( GeneralSecurityException gse ) {
throw new ClassNotFoundException( gse.toString() );
2显示了一个简单的loadClass实现。代码中的大部分对所有ClassLoader对象来说都一样,但有一小部分(已通过注释标记)是特有的。在处理过程中,ClassLoader对象要用到其他几个辅助方法:
findLoadedClass:用来进行检查,以便确认被请求的类当前还不存在。loadClass方法应该首先调用它。
defineClass:获得原始类文件字节码数据之后,调用defineClass把它转换成一个Class对象。任何loadClass实现都必须调用这个方法。
findSystemClass:提供默认ClassLoader的支持。如果用来寻找类的定制方法不能找到指定的类(或者有意地不用定制方法),则可以调用该方法尝试默认的装入方式。这是很有用的,特别是从普通的JAR文件装入标准Java类时。
resolveClass:当JVM想要装入的不仅包括指定的类,而且还包括该类引用的所有其他类时,它会把loadClass的resolve参数设置成true。这时,我们必须在返回刚刚装入的Class对象给调用者之前调用resolveClass。加密、解密
Java加密扩展即Java Cryptography
Extension,简称JCE。它是Sun的加密服务软件,包含了加密和密匙生成功能。JCE是JCA(Java
Cryptography Architecture)的一种扩展。
JCE没有规定具体的加密算法,但提供了一个框架,加密算法的具体实现可以作为服务提供者加入。除了JCE框架之外,JCE软件包还包含了SunJCE服务提供者,其中包括许多有用的加密算法,比如DES(Data
Encryption Standard)和Blowfish。
为简单计,在本文中我们将用DES算法加密和解密字节码。下面是用JCE加密和解密数据必须遵循的基本步骤:步骤1:生成一个安全密匙。在加密或解密任何数据之前需要有一个密匙。密匙是随同被加密的应用一起发布的一小段数据,Listing
3显示了如何生成一个密匙。【Listing 3:生成一个密匙】
// DES算法要求有一个可信任的随机数源
SecureRandom sr = new SecureRandom();
// 为我们选择的DES算法生成一个KeyGenerator对象
KeyGenerator kg = KeyGenerator.getInstance( "DES" );
kg.init( sr );
// 生成密匙
SecretKey key = kg.generateKey();
// 获取密匙数据
byte rawKeyData[] = key.getEncoded();
/* 接下来就可以用密匙进行加密或解密,或者把它保存
为文件供以后使用 */
doSomething( rawKeyData );步骤2:加密数据。得到密匙之后,接下来就可以用它加密数据。除了解密的ClassLoader之外,一般还要有一个加密待发布应用的独立程序(见Listing
4)。【Listing 4:用密匙加密原始数据】
// DES算法要求有一个可信任的随机数源
SecureRandom sr = new SecureRandom();
byte rawKeyData[] = /* 用某种方法获得密匙数据 */;
// 从原始密匙数据创建DESKeySpec对象
DESKeySpec dks = new DESKeySpec( rawKeyData );
// 创建一个密匙工厂,然后用它把DESKeySpec转换成
// 一个SecretKey对象
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance( "DES" );
SecretKey key = keyFactory.generateSecret( dks );
// Cipher对象实际完成加密操作
Cipher cipher = Cipher.getInstance( "DES" );
// 用密匙初始化Cipher对象
cipher.init( Cipher.ENCRYPT_MODE, key, sr );
// 现在,获取数据并加密
byte data[] = /* 用某种方法获取数据 */
// 正式执行加密操作
byte encryptedData[] = cipher.doFinal( data );
// 进一步处理加密后的数据
doSomething( encryptedData );步骤3:解密数据。运行经过加密的应用时,ClassLoader分析并解密类文件。操作步骤如Listing
5所示。【Listing 5:用密匙解密数据】
// DES算法要求有一个可信任的随机数源
SecureRandom sr = new SecureRandom();
byte rawKeyData[] = /* 用某种方法获取原始密匙数据 */;
// 从原始密匙数据创建一个DESKeySpec对象
DESKeySpec dks = new DESKeySpec( rawKeyData );
// 创建一个密匙工厂,然后用它把DESKeySpec对象转换成
// 一个SecretKey对象
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance( "DES" );
SecretKey key = keyFactory.generateSecret( dks );
// Cipher对象实际完成解密操作
Cipher cipher = Cipher.getInstance( "DES" );
// 用密匙初始化Cipher对象
cipher.init( Cipher.DECRYPT_MODE, key, sr );
// 现在,获取数据并解密
byte encryptedData[] = /* 获得经过加密的数据 */
// 正式执行解密操作
byte decryptedData[] = cipher.doFinal( encryptedData );
// 进一步处理解密后的数据
doSomething( decryptedData );应用实例
前面介绍了如何加密和解密数据。要部署一个经过加密的应用,步骤如下:
步骤1:创建应用。我们的例子包含一个App主类,两个辅助类(分别称为Foo和Bar)。这个应用没有什么实际功用,但只要我们能够加密这个应用,加密其他应用也就不在话下。
步骤2:生成一个安全密匙。在命令行,利用GenerateKey工具(参见GenerateKey.java)把密匙写入一个文件:
% java GenerateKey key.data
步骤3:加密应用。在命令行,利用EncryptClasses工具(参见EncryptClasses.java)加密应用的类:
% java EncryptClasses key.data App.class Foo.class Bar.class
该命令把每一个.class文件替换成它们各自的加密版本。
步骤4:运行经过加密的应用。用户通过一个DecryptStart程序运行经过加密的应用。DecryptStart程序如Listing
【Listing 6:DecryptStart.java,启动被加密应用的程序】
import java.io.*;
import java.security.*;
import java.lang.reflect.*;
import javax.crypto.*;
import javax.crypto.spec.*;
public class DecryptStart extends ClassLoader
// 这些对象在构造函数中设置,
// 以后loadClass()方法将利用它们解密类
private SecretK
// 构造函数:设置解密所需要的对象
public DecryptStart( SecretKey key ) throws GeneralSecurityException,
IOException {
this.key =
String algorithm = "DES";
SecureRandom sr = new SecureRandom();
System.err.println( "[DecryptStart: creating cipher]" );
cipher = Cipher.getInstance( algorithm );
cipher.init( Cipher.DECRYPT_MODE, key, sr );
// main过程:我们要在这里读入密匙,创建DecryptStart的
// 实例,它就是我们的定制ClassLoader。
// 设置好ClassLoader以后,我们用它装入应用实例,
// 最后,我们通过Java Reflection API调用应用实例的main方法
static public void main( String args[] ) throws Exception {
String keyFilename = args[0];
String appName = args[1];
// 这些是传递给应用本身的参数
String realArgs[] = new String[args.length-2];
System.arraycopy( args, 2, realArgs, 0, args.length-2 );
// 读取密匙
System.err.println( "[DecryptStart: reading key]" );
byte rawKey[] = Util.readFile( keyFilename );
DESKeySpec dks = new DESKeySpec( rawKey );
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance( "DES" );
SecretKey key = keyFactory.generateSecret( dks );
// 创建解密的ClassLoader
DecryptStart dr = new DecryptStart( key );
// 创建应用主类的一个实例
// 通过ClassLoader装入它
System.err.println( "[DecryptStart: loading "+appName+"]" );
Class clasz = dr.loadClass( appName );
// 最后,通过Reflection API调用应用实例
// 的main()方法
// 获取一个对main()的引用
String proto[] = new String[1];
Class mainArgs[] = { (new String[1]).getClass() };
Method main = clasz.getMethod( "main", mainArgs );
// 创建一个包含main()方法参数的数组
Object argsArray[] = { realArgs };
System.err.println( "[DecryptStart: running "+appName+".main()]" );
// 调用main()
main.invoke( null, argsArray );
public Class loadClass( String name, boolean resolve )
throws ClassNotFoundException {
// 我们要创建的Class对象
Class clasz =
// 必需的步骤1:如果类已经在系统缓冲之中
// 我们不必再次装入它
clasz = findLoadedClass( name );
if (clasz != null)
// 下面是定制部分
// 读取经过加密的类文件
byte classData[] = Util.readFile( name+".class" );
if (classData != null) {
// 解密...
byte decryptedClassData[] = cipher.doFinal( classData );
// ... 再把它转换成一个类
clasz = defineClass( name, decryptedClassData,
0, decryptedClassData.length );
System.err.println( "[DecryptStart: decrypting class "+name+"]" );
} catch( FileNotFoundException fnfe ) {
// 必需的步骤2:如果上面没有成功
// 我们尝试用默认的ClassLoader装入它
if (clasz == null)
clasz = findSystemClass( name );
// 必需的步骤3:如有必要,则装入相关的类
if (resolve && clasz != null)
resolveClass( clasz );
// 把类返回给调用者
} catch( IOException ie ) {
throw new ClassNotFoundException( ie.toString()
} catch( GeneralSecurityException gse ) {
throw new ClassNotFoundException( gse.toString()
对于未经加密的应用,正常执行方式如下:
% java App arg0 arg1 arg2
对于经过加密的应用,则相应的运行方式为:
% java DecryptStart key.data App arg0 arg1 arg2
DecryptStart有两个目的。一个DecryptStart的实例就是一个实施即时解密操作的定制ClassLoader;同时,DecryptStart还包含一个main过程,它创建解密器实例并用它装入和运行应用。示例应用App的代码包含在App.java、Foo.java和Bar.java内。Util.java是一个文件I/O工具,本文示例多处用到了它。完整的代码请从本文最后下载。注意事项
我们看到,要在不修改源代码的情况下加密一个Java应用是很容易的。不过,世上没有完全安全的系统。本文的加密方式提供了一定程度的源代码保护,但对某些攻击来说它是脆弱的。
虽然应用本身经过了加密,但启动程序DecryptStart没有加密。攻击者可以反编译启动程序并修改它,把解密后的类文件保存到磁盘。降低这种风险的办法之一是对启动程序进行高质量的模糊处理。或者,启动程序也可以采用直接编译成机器语言的代码,使得启动程序具有传统执行文件格式的安全性。
另外还要记住的是,大多数JVM本身并不安全。狡猾的黑客可能会修改JVM,从ClassLoader之外获取解密后的代码并保存到磁盘,从而绕过本文的加密技术。Java没有为此提供真正有效的补救措施。
不过应该指出的是,所有这些可能的攻击都有一个前提,这就是攻击者可以得到密匙。如果没有密匙,应用的安全性就完全取决于加密算法的安全性。虽然这种保护代码的方法称不上十全十美,但它仍不失为一种保护知识产权和敏感用户数据的有效方案。
参考资料 。介绍了一个利用类库加载器ClassLoader
实现在运行时刻更新部分功能模块的Java程序,并将其与C/C++中实现同样功能的动态链接库方案进行了比较。
要了解更多的 Java 安全信息,请阅读 的
代码反编译和模糊处理的指南。
。真正安全的软件需要精确的随机数生成器。
下载本文代码:
developerWorks: 登录
标有星(*)号的字段是必填字段。
保持登录。
单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件。
在您首次登录 developerWorks 时,会为您创建一份个人概要。您的个人概要中的信息(您的姓名、国家/地区,以及公司名称)是公开显示的,而且会随着您发布的任何内容一起显示,除非您选择隐藏您的公司名称。您可以随时更新您的 IBM 帐户。
所有提交的信息确保安全。
选择您的昵称
当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。昵称长度在 3 至 31 个字符之间。
您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。
标有星(*)号的字段是必填字段。
(昵称长度在 3 至 31 个字符之间)
单击提交则表示您同意developerWorks 的条款和条件。 .
所有提交的信息确保安全。
IBM PureSystems(TM) 系列解决方案是一个专家集成系统
通过学习路线图系统掌握软件开发技能
软件下载、试用版及云计算
static.content.url=/developerworks/js/artrating/SITE_ID=10Zone=Java technologyArticleID=53345ArticleTitle=运用加密技术保护Java源代码publish-date=以及零基础的人需要多少小时的学习可以能做到?
鸟的动画就是纵向移动,需要处理重力加速度,不过通常的引擎都提供现成的加速度控制。随机生成柱子,需要考虑的就是落差不要太离谱——不过这也可以当作难度系数来控制。背景横屏移动,任何系统都提供类似的方法。碰撞检测,简单的就自己计算矩形是否交叉,不过引擎通常都有提供碰撞检测。没有交互,不需要联网,只是触摸屏幕,想不出还有什么硬性的难点。不过,耐玩的好游戏并非代表开发复杂,而是抓住了人性的弱点。----------[更新于
02:54 AM]为了证明不难,我花了一晚上的时间写了个简单的Demo。因为对iOS开发不熟,基本上是照着Sprite Kit的教程一步一步弄的,花了大概4个小时。----------[更新于
12:38]做了个左右互博版,自己双手玩,或者双人一边一个的控制。真的很难啊!正在考虑上架,要难一起难!----------[更新于
00:40]找到一个使用XCode+SpriteKit写这个游戏的代码,核心代码两百多行,很棒。既然有人写了,我就不写教程了:)----------[更新于
00:10]作为一个行动派,老子竟然把这个游戏上架啦!FlyTwins(双手来双飞)我最多玩到31分,我同事能搞到34,是我目前见到的最高分了。我最多玩到31分,我同事能搞到34,是我目前见到的最高分了。少年,你不想试试吗?如果在AppStore上搜索,搜“FlyTwins”就行。如果是iPad,记得选择“仅iPhone”。能够回放和分享游戏过程视频给微信的朋友,这个功能目前还没有在其他App上见到过,不妨一试。
网上找到一篇文章,主场景300左右行代码,一天时间做出来,你信么?原文链接: ————————————————————————————————————背景:最近火爆全球的游戏flappy bird让笔者叹为观止,于是花了一天的时间山寨了一个一模一样的游戏,现在把游戏的思路和源码分享出来,代码是基于javascript语言,cocos2d-x游戏引擎,cocos2d-x editor手游开发工具完成的,请读者轻砸;ps:运行demo必须配置好cocos2d-x editor,暂不支持其他工具;还有demo是跨平台的,可移植运行android,ios,html5移动系统等,csdn博客里会介绍代码如何移植,请持续关注;Android Apk下载演示:暂时先移植到android平台下载地址: 代码下载:
csdn下载:
百度云盘:
金山快盘 :代码如何移植到各平台:Android:html5:
效果图:开发工具:
cocos2dx editor,它是开发跨平台的手机游戏工具,运行window/mac系统上,javascript脚本语言,基于cocos2d-x跨平台游戏引擎, 集合代码编辑,场景设计,动画制作,字体设计,还有粒子,物理系统,地图等等的,而且调试方便,和实时模拟;cocos2dx editor下载,介绍和教程:;cocos2dx editor官方博客:;思路和源码:
1 场景设计MainLayer.ccbx,如下图;主要分三层,开始场景、主场景、游戏结束场景,通过显示隐藏控制三个场景的切换。
MainLayer.ccbx代码&?xml version="1.0" encoding="UTF-8"?&
jsControlled="true"
jsController="MainLayer"
resolution="default"
&Resolutions&
&Resolution centeredOrigin="false" ext="iphone" height="1280" width="720" name="default" scale="1"/&
&Resolution centeredOrigin="false" ext="iphone" height="720" width="1280" name="default1" scale="1"/&
&/Resolutions&
&Animations&
&Animation autoPlay="true"
name="Default Timeline"
length="10"
chainedId="0"
offset="0.0"
position="0.0"
resolution="30"
scale="128"&
&CallbackChannel&
&/CallbackChannel&
&SoundChannel&
&/SoundChannel&
&/Animation&
&/Animations&
positionX="0" positionY="0.0"
sizeType="Percent"
width="100" height="100"
anchorPointX="0.5" anchorPointY="0.5" ignoreAnchorPoint="true"
scaleX="1" scaleY="1"
&Sprite positionType="LeftBottom" width="720.0" height="1280.0" positionX="0" positionY="0" anchorPointX="0"
anchorPointY="0" src="Resources/bg.png" name="" var="" target="None" scaleX="1" scaleY="1" visible="true"/&
&LayerColor positionType="LeftBottom" width="720" height="1280" positionX="0" positionY="0" anchorPointX="0"
anchorPointY="0" color="#fff2e8ff" visible="false"/&
&Menu positionType="LeftBottom" width="40" height="40" positionX="356.0" positionY="237.0" anchorPointX="0.5"
anchorPointY="0.5" scaleX="2.4" scaleY="1.725"&
&Sprite positionType="LeftBottom" width="840.0" height="281.0" positionX="0" positionY="0" anchorPointX="0"
anchorPointY="0" src="Resources/ground.png" var="ground" target="Doc"/&
&Node positionType="LeftBottom" width="40" height="40" positionX="800" positionY="250" anchorPointX="0"
anchorPointY="0" var="hoseNode" target="Doc"&
&Sprite positionType="LeftBottom" width="86.0" height="60.0" positionX="-500" positionY="400" anchorPointX="0.5"
anchorPointY="0.5" src="Resources/flappy_packer.plist/bird3.png" var="test" target="Doc" visible="false"/&
&Sprite positionType="LeftBottom" width="86.0" height="60.0" positionX="-550" positionY="500" anchorPointX="0.5"
anchorPointY="0.5" src="Resources/flappy_packer.plist/bird1.png" var="bird" target="Doc" scaleX="1" scaleY="1" rotation="0" visible="true"/&
&Node positionType="LeftBottom" width="40" height="40" positionX="303.0" positionY="500" anchorPointX="0.5"
anchorPointY="0.5" var="readyNode" target="Doc" visible="true"&
&Sprite positionType="LeftBottom" width="508.0" height="158.0" positionX="95.0" positionY="584.0" anchorPointX="0.5"
anchorPointY="0.5" src="Resources/flappy_packer.plist/getready.png"/&
&Sprite positionType="LeftBottom" width="286.0" height="246.0" positionX="73.0" positionY="236.0" anchorPointX="0.5"
anchorPointY="0.5" src="Resources/flappy_packer.plist/click.png"/&
&Node positionType="LeftBottom" width="40" height="40" positionX="300" positionY="500" anchorPointX="0.5"
anchorPointY="0.5" var="overNode" target="Doc" visible="true"&
&Sprite positionType="LeftBottom" width="590.0" height="298.0" positionX="72.0" positionY="219.0" anchorPointX="0.5"
anchorPointY="0.5" src="Resources/flappy_packer.plist/base.png"&
&Sprite positionType="LeftBottom" width="508.0" height="158.0" positionX="286.0" positionY="458.0" anchorPointX="0.5"
anchorPointY="0.5" src="Resources/flappy_packer.plist/gameover.png"/&
&Menu positionType="LeftBottom" width="40" height="40" positionX="0" positionY="0" anchorPointX="0.5"
anchorPointY="0.5"&
&MenuItem positionType="LeftBottom" width="290" height="176" positionX="-65.0" positionY="-92.0" anchorPointX="0.5"
anchorPointY="0.5" normalImage="Resources/flappy_packer.plist/start.png" target="Doc" onClick="onStartClicked"/&
&MenuItem positionType="LeftBottom" width="290" height="176" positionX="230.0" positionY="-92.0" anchorPointX="0.5"
anchorPointY="0.5" target="Doc" normalImage="Resources/flappy_packer.plist/grade.png" onClick="onGradeClicked"/&
&/Document&
2 代码编写MainLayer.js
首先,小鸟在向前飞,其实是底部的路和水管在向左移动,相对的你就感觉小鸟在向右飞了;路循环移动代码:MainLayer.prototype.groundRun = function ()
var action1 = cc.MoveTo.create(0.5, cc.p(-120, 0));
var action2 = cc.MoveTo.create(0, cc.p(0, 0));
var action = cc.Sequence.create(action1, action2);
this.ground.runAction(cc.RepeatForever.create(action));
初始化高低不同的水管,每一关卡都由上下两水管和空隙组成。总长度相同,空隙也一定,随机取下面水管的长度,就形成错落有致的水管关卡;MainLayer.prototype.newHose = function (num)
var hoseHeight = 830;
var acrossHeight = 300;
var downHeight = 100 + getRandom(400);
var upHeight = 1100 - downHeight - acrossH
var hoseX = 400 *
var HoseName = FP_MAIN_TEXTURE.HOSE;
var ccSpriteDown = cc.Sprite.createWithSpriteFrameName(HoseName[0]);
ccSpriteDown.setZOrder(1);
ccSpriteDown.setAnchorPoint(cc.p(0, 0));
ccSpriteDown.setPosition(cc.p(hoseX, 0));
ccSpriteDown.setScaleY(downHeight / hoseHeight);
var ccSpriteUp = cc.Sprite.createWithSpriteFrameName(HoseName[1]);
ccSpriteUp.setZOrder(1);
ccSpriteUp.setAnchorPoint(cc.p(0, 0));
ccSpriteUp.setPosition(cc.p(hoseX, downHeight + acrossHeight));
ccSpriteUp.setScaleY(upHeight / hoseHeight);
this.hoseNode.addChild(ccSpriteDown);
this.hoseNode.addChild(ccSpriteUp);
this.hoseSpriteList.push(ccSpriteDown);
this.hoseSpriteList.push(ccSpriteUp);
一开始进入游戏让底部路不断移动,初始化水管,显示准备游戏场景;MainLayer.prototype.onEnter = function ()
cc.AnimationCache.getInstance().addAnimations("Resources/flappy_frame.plist");
this.groundRun();
this.ground.setZOrder(10);
this.birdReadyAction();
this.bird.setZOrder(20);
this.readyNode.setVisible(true);
this.overNode.setVisible(false);
for (var i = 0; i & 30; i++) {
this.newHose(i);
点击屏幕,小鸟向上飞60dp,然后更快的速度下落(移动动画),同时闪动翅膀(帧动画);MainLayer.prototype.birdRiseAction = function ()
var riseHeight = 60;
var birdX = this.bird.getPositionX();
var birdY = this.bird.getPositionY();
var time = birdY / 600;
var actionFrame = cc.Animate.create(cc.AnimationCache.getInstance().getAnimation("fly"));
var flyAction = cc.Repeat.create(actionFrame, 90000);
var riseAction1 = cc.MoveTo.create(0.2, cc.p(birdX, birdY + riseHeight));
var riseAction2 = cc.RotateTo.create(0, -30);
var riseAction = cc.Spawn.create(riseAction1, riseAction2);
var fallAction1 = cc.MoveTo.create(time, cc.p(birdX, 50));
var fallAction2 = cc.Sequence.create(cc.DelayTime.create(time / 6), cc.RotateTo.create(0, 30));
var fallAction = cc.Spawn.create(fallAction1, fallAction2);
this.bird.stopAllActions();
this.bird.runAction(cc.Spawn.create(
cc.Sequence.create(riseAction, cc.DelayTime.create(0.1), fallAction),
flyAction)
检测碰撞,如果小鸟碰到地面和水管,发生碰撞,这里碰撞直接用cocos2d-x 里面的图片和图片交叉函数 cc.rectIntersectsRect;MainLayer.prototype.checkCollision = function ()
if (this.bird.getPositionY() & 60) {
cc.log("floor");
this.birdFallAction();
for (var i = 0; i & this.hoseSpriteList. i++) {
var hose = this.hoseSpriteList[i];
if (!this.isInScreen(hose)) {
if (cc.rectIntersectsRect(hose.getBoundingBox(), this.bird.getBoundingBox())) {
cc.log("hose positionX==" + hose.getBoundingBox().x);
cc.log("this.bird positionX==" + this.bird.getBoundingBox().x);
cc.log("i==" + i);
cc.log("birdFallAction");
this.birdFallAction();
碰撞后,小鸟先下落,游戏结束场景显示;MainLayer.prototype.birdFallAction = function ()
this.gameMode = OVER;
this.bird.stopAllActions();
this.ground.stopAllActions();
var birdX = this.bird.getPositionX();
var birdY = this.bird.getPositionY();
var time = birdY / 2000;
this.bird.runAction(cc.Sequence.create(
cc.DelayTime.create(0.1),
cc.Spawn.create(cc.RotateTo.create(time, 90), cc.MoveTo.create(time, cc.p(birdX, 50))))
this.overNode.setVisible(true);
游戏的难度主要在于多个水管的移动,小鸟触摸动画,检测碰撞;再次提示代码下载地址:
csdn下载:
百度云盘:
金山快盘 :楼下有求图片的,地址:更多内容:官方博客:联系笔者:zuowen@makeapp.co (邮箱)想了解其他游戏开发可关注:附录:其他游戏例子学习 ;
我自己简单尝试了一下写HTML5版本。地址在这里:源代码可以从github上拿。比较了一圈,相比于其他高手的实现,我写的和IOS原始版的相似度尽力做到比较高,从界面元素的切换到分数数字等细节,都很接近原作了。缺点在于没使用任何框架,所以对于一般意义上的游戏开发而言,参考性不强。只用jQuery,用coffeescript来写。除此之外没用其他框架或者库。完成结果是500行左右的js-coffee。注释和调试语句都没删,结构上也还有很大的优化余地。图片是从IOS原始版里扒的。边做别的事情边写,零零散散用了一天半左右的时间。如果包括画图部分,思路确定的情况下,三天时间是合理的。总体来说我觉得相对简单。游戏中用到的可动角色以及判定运算并不多。基本上,搞定了小鸟的跳起下落的重力计算就OK,套用加速度公式而已,没有什么太难的。小鸟和管子的碰撞判定十分容易做。因为小鸟的x坐标是不变的,变化的只是y坐标。小鸟和管子都可以看成矩形,矩形的碰撞计算很简单。无需用到任何游戏引擎都可以手写。基本上前端基础稍强的,有一些面向对象编程思路的程序员,都应该可以写出来。大部分人下意识里觉得难写的原因可能是不敢试。更细节的东西这里还贴吗?好像没什么必要。。因为想看的朋友自然会看源码的吧。
爱生活,爱拉风}

我要回帖

更多关于 我需要有你在我生命中 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信