简易语言

数字沟通

 

置顶随笔

[置顶]安装rails(ruby on rails)

  记得两年前使用ror做网站,自动生成功能记忆犹新,只是当时网络知识实在缺乏,体会不到其中的乐趣。现在了解的很多了,书也有两本,一直想重新体验最新版做个网站。安装这个过程实在有点坑爹,查找网上若干ror的书包括2012年版的书,按照上面的步骤都没法安装完成,搞得我一会在linux下试验,一会在windows下试验,都没成功,只好放下。时间花不少,很不爽的体验。

  好在,过了一段时间,忽然想看看ruby的那两本书,然后就爱上这个语言了。于是做一些想做的试验,一些试验需要做些配置,对安装目录也就了解了。下载一些插件居然自己跑到了ruby的下载页。看到上面居然一个版本有3样要下的,帮助文件和安装文件不就够了吗。还要一个mingw做工具么?这个不是有自己的官网下载么。也没管。想起ruby目录下include中有i386-mingw32,才联系起来。应该是以mingw做make工具的。rails应该需要make,因为每次安装都抛出make出错信息。虽然有mingw官网,但这里应该是做成自己的插件。于是到下载页http://rubyforge.org/frs/?group_id=167下载相应版本的mingw32工具解压覆盖到安装目录中,要是怕出问题先对目录做备份

  另外下载不了的都cross wall下载


C:\Documents and Settings\Administrator>gem install rails
ERROR:  Error installing rails:
        The 'json' native gem requires installed build tools.

Please update your PATH to include build tools or download the DevKit
from 'http://rubyinstaller.org/downloads' and follow the instructions
at 'http://github.com/oneclick/rubyinstaller/wiki/Development-Kit'

  还有错,但明显不是曾经报的make错误了。
  按照网址下载和遵从上面的方法安装即可(下面的命令即是按照安装方法安装的)
  其中config.yml文件仅仅描述ruby所在路径,修改成你的ruby路径即可

D:\>cd D:\Ruby192\devkit

D:\Ruby192\devkit>ruby dk.rb init
[INFO] found RubyInstaller v1.9.2 at D:/Ruby192

Initialization complete! Please review and modify the auto-generated
'config.yml' file to ensure it contains the root directories to all
of the installed Rubies you want enhanced by the DevKit.

D:\Ruby192\devkit>ruby dk.rb review
Based upon the settings in the 'config.yml' file generated
from running 'ruby dk.rb init' and any of your customizations,
DevKit functionality will be injected into the following Rubies
when you run 'ruby dk.rb install'.

D:/Ruby192

D:\Ruby192\devkit>ruby dk.rb install
[INFO] Updating convenience notice gem override for 'D:/Ruby192'
[INFO] Installing 'D:/Ruby192/lib/ruby/site_ruby/devkit.rb'

D:\Ruby192\devkit>gem install rdiscount --platform=ruby
Fetching: rdiscount-1.6.8.gem (100%)
Temporarily enhancing PATH to include DevKit...
Building native extensions.  This could take a while...
Successfully installed rdiscount-1.6.8
1 gem installed
Installing ri documentation for rdiscount-1.6.8...
Installing RDoc documentation for rdiscount-1.6.8...

D:\Ruby192\devkit>ruby -rubygems -e "require 'rdiscount'; puts RDiscount.new('**
Hello RubyInstaller**').to_html"
<p><strong>Hello RubyInstaller</strong></p>

下面安装rails

D:\Ruby192\devkit>gem install rails
Temporarily enhancing PATH to include DevKit...
Building native extensions.  This could take a while...
Fetching: rdoc-3.12.gem (100%)
Depending on your version of ruby, you may need to install ruby rdoc/ri data:

<= 1.8.6 : unsupported
 = 1.8.7 : gem install rdoc-data; rdoc-data --install
 = 1.9.1 : gem install rdoc-data; rdoc-data --install
>= 1.9.2 : nothing to do! Yay!
Fetching: railties-3.2.8.gem (100%)
Fetching: bundler-1.2.0.gem (100%)
Fetching: rails-3.2.8.gem (100%)
Successfully installed json-1.7.5
Successfully installed rdoc-3.12
Successfully installed railties-3.2.8
Successfully installed bundler-1.2.0
Successfully installed rails-3.2.8
5 gems installed
Installing ri documentation for json-1.7.5...
Installing ri documentation for rdoc-3.12...
unable to convert U+00A9 from UTF-8 to GBK for lib/rdoc/text.rb, skipping
Installing ri documentation for railties-3.2.8...
Installing ri documentation for bundler-1.2.0...
Installing ri documentation for rails-3.2.8...
Installing RDoc documentation for json-1.7.5...
Installing RDoc documentation for rdoc-3.12...
unable to convert U+00A9 from UTF-8 to GBK for lib/rdoc/text.rb, skipping
Installing RDoc documentation for railties-3.2.8...
Installing RDoc documentation for bundler-1.2.0...
Installing RDoc documentation for rails-3.2.8...

  果然成功了,哈哈

D:\Ruby192\devkit>rails -v
Rails 3.2.8

  想做个实例,搜一下网上的书,还是不行,那些书最新的2012的都不用命令行做,2011的还是老的命令行方式。根本没法用,上官网看就是了。
D:\Ruby192\devkit>rails new D:/project/ruby/railsapp
      create
      create  README.rdoc
      create  Rakefile
      create  config.ru
      create  .gitignore
      create  Gemfile
      create  app
      create  app/assets/images/rails.png
      create  app/assets/javascripts/application.js
      create  app/assets/stylesheets/application.css
      create  app/controllers/application_controller.rb
      create  app/helpers/application_helper.rb
      create  app/mailers
      create  app/models
      create  app/views/layouts/application.html.erb
      create  app/mailers/.gitkeep
      create  app/models/.gitkeep
      create  config
      create  config/routes.rb
      create  config/application.rb
      create  config/environment.rb
      create  config/environments
      create  config/environments/development.rb
      create  config/environments/production.rb
      create  config/environments/test.rb
      create  config/initializers
      create  config/initializers/backtrace_silencers.rb
      create  config/initializers/inflections.rb
      create  config/initializers/mime_types.rb
      create  config/initializers/secret_token.rb
      create  config/initializers/session_store.rb
      create  config/initializers/wrap_parameters.rb
      create  config/locales
      create  config/locales/en.yml
      create  config/boot.rb
      create  config/database.yml
      create  db
      create  db/seeds.rb
      create  doc
      create  doc/README_FOR_APP
      create  lib
      create  lib/tasks
      create  lib/tasks/.gitkeep
      create  lib/assets
      create  lib/assets/.gitkeep
      create  log
      create  log/.gitkeep
      create  public
      create  public/404.html
      create  public/422.html
      create  public/500.html
      create  public/favicon.ico
      create  public/index.html
      create  public/robots.txt
      create  script
      create  script/rails
      create  test/fixtures
      create  test/fixtures/.gitkeep
      create  test/functional
      create  test/functional/.gitkeep
      create  test/integration
      create  test/integration/.gitkeep
      create  test/unit
      create  test/unit/.gitkeep
      create  test/performance/browsing_test.rb
      create  test/test_helper.rb
      create  tmp/cache
      create  tmp/cache/assets
      create  vendor/assets/javascripts
      create  vendor/assets/javascripts/.gitkeep
      create  vendor/assets/stylesheets
      create  vendor/assets/stylesheets/.gitkeep
      create  vendor/plugins
      create  vendor/plugins/.gitkeep
         run  bundle install
Fetching gem metadata from https://rubygems.org/.........
Installing rake (0.9.2.2)
Installing i18n (0.6.1)
Installing multi_json (1.3.6)
Using activesupport (3.2.8)
Using builder (3.0.0)
Using activemodel (3.2.8)
Using erubis (2.7.0)
Using journey (1.0.4)
Using rack (1.4.1)
Using rack-cache (1.2)
Using rack-test (0.6.1)
Using hike (1.2.1)
Using tilt (1.3.3)
Using sprockets (2.1.3)
Using sprockets (2.1.3)
Using actionpack (3.2.8)
Installing mime-types (1.19)
Using polyglot (0.3.3)
Using treetop (1.4.10)
Using mail (2.4.4)
Using actionmailer (3.2.8)
Using arel (3.0.2)
Using tzinfo (0.3.33)
Using activerecord (3.2.8)
Using activeresource (3.2.8)
Using bundler (1.2.0)
Installing coffee-script-source (1.3.3)
Installing execjs (1.4.0)
Installing coffee-script (2.2.0)
Using rack-ssl (1.3.2)
Using json (1.7.5)
Using rdoc (3.12)
Installing thor (0.16.0)
Using railties (3.2.8)
Installing coffee-rails (3.2.2)
Installing jquery-rails (2.1.1)
Using rails (3.2.8)
Installing sass (3.2.1)
Installing sass-rails (3.2.5)
Using sqlite3 (1.3.6)
Installing uglifier (1.2.7)
Your bundle is complete! Use `bundle show [gemname]` to see where a bundled gem
is installed.

D:\Ruby192\devkit>cd D:\project\ruby\railsapp

D:\project\ruby\railsapp>rails server
=> Booting WEBrick
=> Rails 3.2.8 application starting in development on http://0.0.0.0:3000
=> Call with -d to detach
=> Ctrl-C to shutdown server
[2012-09-01 06:44:40] INFO  WEBrick 1.3.1
[2012-09-01 06:44:41] INFO  ruby 1.9.2 (2011-07-09) [i386-mingw32]
[2012-09-01 06:44:41] INFO  WEBrick::HTTPServer#start: pid=2924 port=3000

  浏览器中输入http://localhost:3000/,熟悉的界面出现


  所以ror厚厚的书读完也没用,可能动手连代码都没机会敲。

  另外也可以到网站http://railsinstaller.org/下载配置好的安装包,就免去手动配置啦。

posted @ 2012-09-02 01:17 yangyusong 阅读(4645) | 评论 (0)编辑 收藏

[置顶]涂鸦秀秀游戏项目介绍

  这是六月初完成的一个游戏

 

两个月时间终于完成了我们的涂鸦秀秀项目,与同类产品相比,我们内容更多些,分为双人对战模式,多人模式,相信可以同时在线很多人。

 

技术上实践了一把前后端都js的游戏。算是过了把小瘾。用到nodejssocket.iophonegapexpress框架和其他细枝末节。一路上我们披荆斩棘,果然爽。

 

其实从项目需求到解决各个小bug,真是刷了若干个夜

 

这样的项目特点就是能在各手机上玩,包括ipodpadPc上只要支持canvas也可以一起玩,多好的一个大融合。当然其实要兼容ie6也不是什么难事,难在我根本没时间理了,真不好意思。简单说就是跨平台。适配的机器也较多,能有较广的群众基础。

 

我们也有好友系统,分享,邀请,当然不会做深,我们的目标是先吸引住市场,然后再集中力量对用户喜欢的点做深入研发。

 

做完后同学陪我玩好长时间,他很喜欢玩,这一点让我比较欣慰。感觉画图游戏来源于人类的自恋,人类天然喜欢用图来表达意思。只是世界上的系统还是符号的多。

 

如图:

 

SouApp.com还给我们盖了章,我特地确认了一下,这是人家主动盖的章。在审核的时候就下载了一百多次。当然我也不知道这算什么概念。至少觉得有人感兴趣,其实这游戏对美术是乐事,他们功底好,pc上有自己的画图板,画起来非常专业。赢点小礼品根本不是问题。当然以后的版本会更好,更吸引人。已经有不少想法,可改进的地方也不少。

 

 

如下是一些界面截图


 

 

一些小作品

 


 

下载地址

http://souapp.com/app_detail/?appid=aaf7a621-205a-4c73-a88b-a5ef3ebb9431

 

http://www.appchina.com/soft_detail_291505_0_10.html

 

游戏地址

m.tuyaxiuxiu.com

360.tuyaxiuxiu.com

google.tuyaxiuxiu.com

官网地址

www.tuyaxiuxiu.com

 

两个月我们都做了什么?

美术需求,协议定制,详细编码,修bug,手机测试,稳定服务,官网搭建,后台搭建,推广运维。非常多的细节,充实有趣。

 

现已通过sina,google等各大平台,能搜到精选,分享,当然不是我们自己弄的,比如下面这个精选,人家是还要注册才能下载的社区。我们自己搞这种就过头了。

 

 

如果大家觉得两个月太长了,其实试试就知道,光推广就够累的,各个平台各种限制。不玩得技术欲仙欲死才怪。官网,后台,各种修改更新。甚至图都要自己改改。开始半个月,美术需求就写了10次,不敢说每次都很详细,但也够有调理和详细的了。

 

不过从中也获得不少经验,本来规划非常短的时间来完成,这个按照很理想的条件来处理的话。当然其实也准时完成了,只不过我们又要了加倍的功能,而我们的人数从开始实施时就减少了一半。这样的条件下,没报告什么特别的,既然说了就做吧,通宵很多个晚上,弄得我经常起不来。

 

另一些感触就是积极加入各种思考分析中就好,根本不要去考虑回报,这个世界上能去考虑回报的人并不多。

 

其实其中有的地方不太到位,比如分享界面、官网、统计分析。只能等人来帮忙了。

 

如下图是当时做的一个极限测试

 

当时数据量一大就丢失数据。于是自己做了个编码方式,减少数据量,这个图证明的就是只要网络能传输,内容再多都能处理。

 

这个游戏的不好之处就是必须有一定的玩家基数才能带动起来。另外,我们开发很多功能其实没必要,先开发主要功能,看市场反应,在进一步开发才有意义。于是有了下一个游戏,见下一篇。

posted @ 2012-07-18 15:49 yangyusong 阅读(842) | 评论 (0)编辑 收藏

[置顶]进军手机游戏和一些建议

转眼又过了几个月,但是这几个月做了好多游戏,疯狂了。其中做的第一款游戏今天进了google应用首页最上面的图。如图中,有好多金币那个图,就是我们的游戏。一个非常简单的游戏。



这个游戏名称叫砸金币水果机,我们做了英文版,中文版,ios,andriod版。如下就是英文andriod版,模仿街机风格,颇有怀旧的味道。当然技术上我并不看好这款游戏,但实际效果却不好说,图片精美,物理效果不错,触发的神奇界面不少,就看游戏屌丝对街机是否着迷过了。估计也是这些原因导致被google推荐吧,我们也没花任何一分钱买推荐。

 

其实我更想推荐的是多人网上互动的手机游戏,希望在下一篇给大家做介绍。

 

现在我们发现最火的语言成了javascript,原因是html5的推出,其实原理上讲,这个语言也是必然要火的,首先人类交互最密集的地方转移到互联网上了,人类交互的重要性是不言而喻的,就要求我们的网页有更多的功能,而这个功能的提供者第一个是js,且语言简洁,开源,这就奠定了它的竞争力基础。有了这些基础后,最大数量的研究人员都会在这上面。如果将it产业比喻成火山,那么网络这部分就是岩浆部分,就是变化最快的地方。一开始都是最专业的人研究底层,当这些底层成熟后,应用层就快速发展起来,推陈出新非常快。Html5推出将人们最常用的应用以很简洁的方式表达出来,nodejsjs推向后端,socket.io加速交互效率和交互设计。当然有非常多的js框架都出来了。这里不具体说了。

 

这几个月的经验总结希望给大家一些启发, 如果我们做一个跨平台手机游戏发最好做好以下准备

 

Js越熟越好,不要以为它真的很简单,要做手机游戏,必须学会优化,如果是客户端,要求很高,如果在绘图时画一大堆对象,andriod一定会过不去的。那么就一方面研究js(我的建议是,不要去啃面向对象,代码清晰,规范最重要),一方面细读html5规范吧。

 

java基础,那么在用phonegap打包到andriod系统下时,就能较快明白怎么做配置,怎么添加插件和使用。Javajs都不错的话那么写点插件也不错。有的功能是必须用插件的哦。

 

有点andriod设计的基础,我是没什么基础,所以也花不少时间研究,其实就研究它的一些配置关系。也会有烦人问题的。

 

有点mac下的xcode基础,xcode的基本的使用最好明白,否则还是要花不少时间摸索,对于mac系统的设计,我实在不太苟同,虽然我能挺快适应。至于oc,会一些也更好,这样方便使用插件和写插件。

 

想进军app store,越早申请账号,越早提交越好,遇到的问题非常之多。也许怪物英文不好,mac不熟吧。

 

当然硬件上最好有几个手机,ipod,pad做测试,ipad3尤其要测。

 

你还会遇到的问题,比如手机屏幕适配,音乐的使用,兼容浏览器等。

 

 另一个建议就是认准了自己喜欢的,一头扎进去动手就是了。

 

这篇文章总体质量不高,没给大家讲讲技术细节,商业游戏,不太方便哈,会给大家讲开源的。甚至有的地方可能讲失误也欢迎批评指出。本篇完。

 

游戏地址1http://app.baidu.com/273943

游戏地址2

https://chrome.google.com/webstore/detail/jdjcanmclknahldoohmphkiicmggghdf?hl=zh-CN

(要在chrome下安装过才可玩)

posted @ 2012-06-13 04:26 yangyusong 阅读(1524) | 评论 (2)编辑 收藏

[置顶]用yecc(erlang)写一个json解析器

  昨天写了个json的解析器。其实yecc早看过了,只是那时对自己要求太高,想一下子写个小语言。然后大脑就陷入混乱... 后来注意力转移了。就不那么急着去开发些难道大的。今天回来一看,觉得都理解了,实践一下,发现没人写json的,太好了。于是就在纸上写了一下。晚上没事都敲掉计算机里试试。果然很好用。废话就不多说了,不专业的我在readme里面已经写了不少废话了。主要也不知道git有没规范约束readme不能写废话。其实被google骗了一下,有人写过json的erlang解析,每次我搜yrl,它就主动搜url文件。还要点一下坚持搜索才行。看看https://github.com/jchris/erlang-json-eep-parser/downloads这上面就是一个解析器,还好我们写的不是太像,他写的更精细一点。我写的更容易使用上手。我写的就到这下载吧https://github.com/yangyusong/erlang_json_parser。

  接着就是讲讲内容了,大学学过编译原理就很容易理解这其中的内容。yrl文件就是erlang中的满足LALR-1规范的解析生成器,相似于yacc。会有很多文章做解释,这里不详述。yrl文件或yacc中的.y这类文件就是给我们写编译规则用的,我们写好一个推理机制,按照规范分解成4部分,放到这一个文件中,那么yecc就可以给我们生成一个符合这个推理规则的解析器,当然这里就是生成.erl的源文件给我们使用,其中会有parse作为默认方法提供给我们解析我们的字符串。

  yrl文件中一共有四部分,其实三部分分别用Nonterminals Terminals Rootsymbol关键字来标识,意义很明显,非终结符,终结符,起始符(这个忘了怎么翻译)。要解释一下也行,一个更好的理解方式就是,非终结符可以在推理符号(->)的左边和右边,相当于函数作用,最终分析为终结符的组合。终结符只能在推理符号(->)的右边。意义就是一个符号系统的基本集合。 Rootsymbol是其中一个非终结符,作为推理的起始点。用一棵解析树来表示的话,Rootsymbol就是根节点。Nonterminals就是树枝。Terminals就是树叶。任何一个符合此推理规则的字符串都可以用这样一棵解析树表示出来(我就不画了)。

  除了上面说的三部分就剩下最重要的部分了:推理规则。其实这四部分都是列表,只不过Rootsymbol这个表只有一个元素。规则列表有多条,通常每行一条规则,和erlang一样用.结束一条规则。
终结符用单引号引起,冒号后面是我们解析后的erlang表达式。$1,$2,$3这种相似正则表达式规则,也说一下吧,就是对冒号左边的元素作为列表并从1计数。再搞不懂就发邮局问吧,呵呵。

  那么这样的一个规则列表就很好建立了,其实这个过程还是有很多规则可以遵循的,其中这里遵循了左递归,终结字符先出现的规则优先表达这两条规则。更多,你还可以画个有限状态机,做一下分析,化解,做成闭包,某些运算还要考虑优先级之类。当然这里这样小的结构基本是最优了,没什么化解的必要。

代码附上
Nonterminals list object kv_list v_list kv k v. % 7

Terminals ',' ':' 'element' '[' ']' '{' '}'. % 7

Rootsymbol object.

object -> '{' '}' : {}.
object -> '{' kv_list '}' : { '$2' }.


kv_list -> kv ',' kv_list : '$1' , '$3'.
kv_list -> kv : '$1'.

kv -> k ':' v : {'$1', '$3'}.

k -> 'element' : '$1'.

v -> 'element' : '$1'.
v -> list : '$1'.
v -> object : '$1'.

list -> '[' ']' : [].
list -> '[' v_list ']' : [ '$2' ].

v_list -> v ',' v_list : '$1' , '$3'.
v_list -> v.

  其中object,list就是json中最基本的结构。kv_list就是剥离大括号后的键值对列表。v_list是剥离中括号的列表。

  再讲讲这个解析器的使用吧,json_parser就是yrl文件生成的解析器了,我们就用这个解析器来做解析。文件use_json_parser对json_parser的使用做了一个包装,那就是parser/1函数了,我们给它传入json字符串就返回解析后的erlang列表。例如我们输入use_json_parser:parser("{a, b, c}").就会返回[{'{',1},
                                        {atom,1,a},
                                        {',',1},
                                        {atom,1,b},
                                        {',',1},
                                        {atom,1,c},
                                        {'}',1},
                                        {'$end',999}]。
  这个文件还提供一个测试函数了unit_test_()。为了方便大家,我还是讲讲测试方法吧。在命令行输入
cd erlang_json_parser
erl -pa ./ebin/ -eval "make:all([{d, 'EUNIT'},{outdir, \"./ebin/\"}, debug_info]) ,eunit:test(\"./ebin\",[]),init:stop()"

  参考更多的解析器制作,可以参考erlang官网提供的计算表达式解析,list解析。也可以从其他网站搜到html,xml等的解析,当然如果你看得多一点还会看到aleppo,erlydtl这类的工程。希望更多的人们投入到这些更有意思的开发中。下次再写yecc,就不写这么简单的了。哈哈。不要期待在下一篇里出现哦。

posted @ 2011-12-30 23:28 yangyusong 阅读(3440) | 评论 (0)编辑 收藏

[置顶]一个小游戏ChainReaction的设计(html5)

本来一直觉得js是个让人混乱不堪的语言,html5的出现改变了我对它的看法。到了html5的时代,各种犀利的设计就更明显的需要js了。看了一些小游戏设计,忽然来了兴趣,于是写了几个小游戏,这是其中一个。已经开源,欢迎下载https://github.com/yangyusong/ChainReaction

 

游戏叫连锁反应,这个游戏是看到有人在ipad上面玩的游戏,觉得好玩,自己实现一遍。游戏是这样的,一群小球在区域内弹来弹去,玩家鼠标点击一个地方,在一个圆的范围内,小球碰上就会爆炸,爆炸的过程中其他小球碰上也会发生爆炸,这就叫连锁反应。每一关爆破一定数量的小球就算胜利。

 

我的设计中一个有20关,数值增长比较平和,运气不是太差的话都能一次通关。在说有个再玩本级的功能,过一关的压力是一点都没有。这样设计是为了给工作后的朋友缓解压力。我们轻松的一点就爆炸一片。

 

看看截图


 

大的那个灰色的(其实是半透明的)圆是鼠标范围。其他是弹来弹去的小球。可以看到,小球是各种颜色的。

 

我们看看小球的定义

function Circle(x, y, xSpeed, ySpeed, radius, color, liveTime, state){

    //圆心坐标

    this.x = x;

    this.y = y;

    //运动速度

    this.xSpeed = xSpeed;

    this.ySpeed = ySpeed;

    //半径

    this.radius = radius;

    //颜色

    this.color = color;

    //生存计数器

    this.liveTime = liveTime;

    //状态:

    this.state = state;

}

 

其中生存计数器是要和状态结合使用的,状态分为如下5个状态

//小球状态

var SMALL = 0;

var BIG = 1;

var EXPEND = 2;

var END = 3;

var DIS_VISIBLE = 4;

 

当处于EXPEND状态的时候,就说明小球进入爆炸状态,这时候生存计数器就用上了。计数器是个倒计时,计时到零,小球进入DIS_VISIBLE状态。这时候小球就不再渲染出来。

 

我们的小球有不同大小,不同颜色,看看小球的初始化就知道了,代码在ObjectMgr.js

for(i = 0; i < g_StepsArr[g_Steps].ballsNum; i++){

            //_Util.dump_obj(_Color.color_str(new Color(Math.random(), Math.random(), Math.random())));

            var raduis = _Util.random_range(SMALL_RADIUS1, SMALL_RADIUS2);

            this.circles.push(new Circle(

                _Util.random_range(raduis*2, this.canvasWidth-2*raduis),

                _Util.random_range(raduis*2, this.canvasHeight-2*raduis),

                _Util.random(SPEED_MIN, SPEED_MAX),

                _Util.random(SPEED_MIN, SPEED_MAX),

                raduis,

                _Color.color_rgba_str(new Color1(Math.random(), Math.random(), Math.random(), 0.8)),

                MID_LIVE_TIME,

                SMALL

                ));

        }

 

其中g_StepsArr负责我们关卡的管理,有这一关的小球数,和通关需要爆破的小球数。总之,这里按照本关需要的小球数初始化小球,可以看到里面有很多的随机函数使用。小球的半径处于如下两个数之间

var SMALL_RADIUS1 = 3;

var SMALL_RADIUS2 = 10;

通过random_range来进行这个范围随机。我们看到速度也是随机的,范围是

var SPEED_MIN = 10;

var SPEED_MAX = 50;

颜色中的color_rgba_str函数的第四个参数说明我们的每个小球的透明度是0.8,这样我们就能在爆破的时候,或弹动的时候仍然看清其他小球。这段代码就说到这。

 

我们讲讲主要流程,其实其中的详细注释,我觉得已经可以教会很多初学者。不过还是讲讲好。主要流程就在Main.js中。负责初始化,渲染和循环。开始我们设置了一堆全局变量。

var g_ObjectMgr = null;

var g_MouseEventDispatch = new MouseEventDispatch();

var g_MouseMgr = null;//g_MouseMgrg_ObjectMgr初始化后才初始化

//当前关

var g_Steps = 1;//todo 显示出来

//关卡数组

var g_StepsArr = [];

g_StepsArr = stepsInit();

//爆炸开始标识

var _ExpendStart = false;

 

if(DEBUG){

    _CircleLib.test();

}

var _Main = { 。。。

 

包括关卡数组,当前关数,爆炸标识等。居然还设置了一个是否调试的状态量,其实我也不知道js调试怎样才好,基本就按自己的方式调。 _Main是个很大的结构。我更宁愿把它当做单例来思考。主要是,它包括了渲染,这个渲染不具通用性,仅此一例就够。其他地方用了且不是画出什么就难说了。当然已经设计其实我会更多考虑通用性的设计,尽量不设计成这种单例。

 

这个_Main结构中有我们的画布canvas,我们的初始化函数,每关调用一次,它来负责2d对象的初始化,游戏对象的初始化。鼠标监听初始化。然后就是进入我们的循环。循环很简单,就干四件事情

/*

     * 循环绘图

     * 1.清空画面

     * 2.游戏对象关系处理

     * 3.渲染出来

     * 4.循环调用

     */

    step: function(){

        this.clear();

        g_ObjectMgr.step();

        this.render();

        _this = this;

        this._st = setTimeout(function(){

            _this.step();

        }, 50);

    }

 

看看我们的下一关都干些什么

/*

     * 下一关

     */

    nextStep: function(){

        clearTimeout(this._st);

        if(this.canvas.getContext)

        {

            g_MouseEventDispatch.start();

            this.initObjects();

            this.step();

        }

    }

它就是清除计时器,重新分配事件,初始化对象。然后进入循环,为什么是这样呢?清除计时器以使我们之前的循环停止。因为我们马上有新的循环了,其实事件可以看做有两个状态,我们按下鼠标的时候,这个事件就不可用了,下次使用必须初始化。小球数量变了,必须按照本关的需求来初始化。进入循环,新的循环开始。

看看再玩一次(本级)按钮的调用:

/*

     * 再玩一次(本级)

     */

    again: function(){

        this.nextStep()

    }

 

为什么居然是调用下一关呢?只能说我设计的太懒惰,nextStep()本身根本不管关卡的变更。关卡的变更完全在爆炸检查函数里,一旦发现小球爆炸,就会修改当前关卡。而单纯调用nextStep所使用的关卡是未改变过的,故而是在玩本级。

 

我们再看一下ObjectMgr.js中的爆炸检查函数

 

expendCheck: function(){

        if(_ExpendStart){

            this.expendNum = _CircleLib.intersect(this.circles, g_MouseMgr.mouseCircle);

//            _Util.dump_obj(g_StepsArr[g_Steps])

            if(this.expendNum >= g_StepsArr[g_Steps].killNum){

                var next = g_Steps + 1;

                alert("成功爆破超过"+this.expendNum+"个小球,恭喜进入第"+ next + "关,\n\

下一关需要爆破" +g_StepsArr[g_Steps + 1].killNum + "个小球");

                g_Steps++;

                _Main.init();

            }

        }

    }

 

还记得_ExpendStart这个变量的意思么?就是说鼠标是否按下了,按下的话我们就要检查是否有小球撞上鼠标范围或撞上爆炸中的小球。其实这里的调用_CircleLib.intersect这个函数是有些小问题的。它是通过引用修改的当前小球的状态,至于为什么有很少量的小球未修改状态,这个我还没弄明白。总之,这个函数检查了爆炸小球的数量,一旦爆炸小球的数量符合本关的要求,那么就可以进入下一关,可以看到我们进入下一关的提示是一个对话框,不是很友好,可以设计为一个图片较好,可惜我没时间找美术。

 

点击确定,我们玩下一关

 

小球多了很多,找个好点的位置,能捕捉很多小球。

看一下爆炸过程吧:


这是第十八关的一个爆炸情形,更具体的内容欢迎看具体代码吧,要不还讲好长时间。

 

做完这个例子,发现其实非常多的小游戏很好设计,可惜没那么多时间,再说设计别人设计过的游戏也不是我的目标。设计一些有趣的小游戏到手机里,这个倒是个不错的方向

posted @ 2011-12-18 23:03 yangyusong 阅读(2116) | 评论 (2)编辑 收藏

[置顶]游戏中最近可达点(用erlang写一个简单算法)

游戏中有点击障碍点,人物走到离障碍物最近点的算法。我这给一个简单的算法,这个问题可以复杂化,另外这个问题应该由客户端来完成。

如图,玩家在b点,点击了a点,a在一个障碍区(红色,玩家只能在障碍区外移到)。这时候玩家应该走到c点,我们就需要计算出c点,一个简单的数学题,用什么语言都没几行代码,我就用erlang写一下。


障碍物通常都不规则的,我们只能从a点开始一个个点测试,直到不是障碍点,也就是x自增,y=x*tan(A),然后测试这个点,地图数据都是静态的数据,方便测试,这里就写死一个x为障碍结束的地方作为障碍检测函数。

我们还需要一个记录表示点,tan函数在erlang中是有的,但其实可以不用,我们就直接要一个比值,但需要一个向上取整的函数,据说是round函数,但测试一下,不行,难道是因为不是最新otp
D:\NetBeanPj\mytest\src>erl
Eshell V5.8.1.1  (abort with ^G)
1> round(1.2).
1

所以这里我们要写的一个辅助函数,最后就是我们的重点,取最近点,用一个列表解析就够了,剩下的就看具体实现吧,还可以写个测试函数,这次就不写成单元测试了。好的我们看代码:
-module(nearst_point).

-export([ceil/1, is_barrier/1, nearst_point/2]).

-export([p1/0, p2/0, test_1/0]).

%% 一个点
-record(point,{
    x,
    y
              }).

%% 向上取整
ceil(Num) ->
    Num1 = round(Num),
    case Num1 >= Num of
        true ->
            Num1;
        false ->
            Num1+1
    end.

%% 判断是否是障碍物
is_barrier(Point) ->
    Point#point.x =/= 5 .

%% 查找最近点
nearst_point(Pointa,Pointb) ->
    Tan = (Pointa#point.x - Pointb#point.x)/(Pointa#point.y - Pointb#point.y),
    case Pointa#point.x > Pointb#point.y of
        true ->
            MaxX = Pointa#point.x,
            MinX = Pointb#point.x;
        false ->
            MaxX = Pointb#point.x,
            MinX = Pointa#point.x
    end,
    try
        [
            begin
                Point = #point{
                    x = X,
                    y = ceil(X*Tan)},
                case is_barrier(Point) of
                    true ->
                        ok;
                    false ->
                        throw(Point)
                end
            end|| X <- lists:seq(MinX, MaxX)]
    catch
        throw: Point ->
            io:format("~p", [Point]),
            Point
    end.

%% 下面函数测试用,可以改成单元测试,这里就免了
p1() ->
    #point{
        x = 1,
        y = 9}.

p2() ->
    #point{
        x = 15,
        y = 25}.

test_1() ->
    nearst_point(p1(),p2()).

编译和测试
2> c(nearst_point).
{ok,nearst_point}
3> nearst_point:test_1().
{point,5,5}{point,5,5}
4>

我们的测试如预期的在5那个点得到,好像有个小问题,怎么这个点输出了两次?哦,这不是问题,一个点是代码里的io输出的,一个点是返回给shell,shell的输出,看来写代码的人太懒,疑惑也会增多啊。在nearst_point中用到了一个小技巧,就是用throw来跳出循环(这个在erlang中还是挺有意思),这次到这,应该说写的很基础很难看。下次会来点有意思的,欢迎大家学习erlang。

posted @ 2011-06-24 23:54 yangyusong 阅读(2855) | 评论 (0)编辑 收藏

[置顶]给www.bayke.com做的一个简单seo分析

曾经也是写java程序,如今也写起了网站,还做起了seo分析,看到雪落无声的两篇博文:《SEO新手从bayke网站建设到关键词排名第一的详细步骤》和《做为百客购物返利网(bayke)站长,哥感觉鸭梨很大!》发现在这个博客里还有不少同仁,和他一样也为了推广自己的网站,开始写关于seo的博文,就目前我所掌握给他做一些分析,不知道他会不会建议,早点发现和我聊聊。其实我和他一样,感觉很辛苦,而且我是孤军奋战,但感觉死的是自己,也就不是那么在意了,我的网站建得晚,简单,效果比他的差,但相信我的分析很实用。时间有限,内容不会多。建议从第三条看起。

1.       我进了他的网站:http://www.bayke.com/,内容非常丰富,各种分类非常全,一个正规的购物类网站。我相信它的前途是好的,只是知道的人还太少,产生信任也要一段时间。

2.       好像会定时自动刷新,也许是为了实时性。

3.       他是098月建的网站,我是今年10月建的网站。他的是商业网站,我的是专业网站。

4.       我给他查了一下收录情况,情况如下:


    也就是说谷歌对它的认同比较好,收录了
43个页面(或链接),有道,必应有都有一个链接,百度收录为0,这个我怀疑不是很准,用另一家的工具查看,情况如下


    百度有
26个反向链接,雅虎有43个反向链接,说明哥们写了很多博文,发了不少链接,搜狗收录了12个链接。百度没有收录或说很少,我想原因有3,(1)可能页面的定时刷新被百度认为是作弊,(2)可能关键词的密度太低,我不知道这个是否真重要到如此程度。(3)百度是个中文网,商品网站的词对百度来说基本都是熟词,但百度几乎只收录不熟的,感觉是原创的网页。这些只是猜测。

5.       现在做一下密度测试,百客(或bayke)应该作为该站的一个关键词,我们看如下查询结果:


    结果告诉我们在首页中,关键词百客的密度是
0.2%,而正常的网页在2%-8%比较恰当,当然通常不用刻意在意。

我们在查一下“潇洒男装”分类页中的关键字“百客”的密度,如图:


    频率特别的小,我对
bayke也在这两个页面查询,结果是一样。建议站长在各页做长尾关键词。

6.       查了一下该站的死链接,做的特别好,没有死链接,如图


    该站一共两百多站内链接,
20站外链接,还能看出站长用的是php写的网站。

7.       网站出错时返回404是最好的,有很多网站为了美观页面,总对404错误做重定向,导致出现301等错误,这些错误是会受到引擎处罚的。贵站这点做的不错,返回的是404,如图:


    时间有限,下次再接着分析。欢迎到我的网站
http://www.suchseo.com/了解更多具体seo内容和对网站的分析方法。一定要看看本站分析,seo工具,这些分类,你就知道今天的分析很简单,也还算实用。

posted @ 2010-10-21 22:21 yangyusong 阅读(1600) | 评论 (2)编辑 收藏

[置顶]什么是躲猫猫

    躲猫猫是云南的一个游戏,小朋友都爱玩,躲避的时间由这段话的时间来度量:“蒙猫猫,躲老耗,老耗老耗躲稳点,不给老猫拿得着,一碗油,二碗油,放个猫猫拿气球;一碗水,二碗水,放个猫猫拿小鬼”。
    躲猫猫事件让这个词变得很热门,而这段脍炙人口的顺口溜却一直只能在云南的小朋友中口口相传,小时候还有很多顺口溜,书上并不能见,如“XXX,放个屁,放到意大利,意大利的老板在看戏,闻到这个屁,真生气...”,xxx表示任一人名。省略号是因为我记不清了,哎;再如“切切切,切韭菜,两只小猫翻锅盖”。现在就我一个人在外地,暂时还没老乡过来,玩不起脑力激荡,就回忆这两句。民间艺术是要我们快乐的,是不要钱的,流传那么多年,还是没人写出来。也许会渐渐消失,也许还是口口相传下去。很多地方,很多方言,很多的表达方式,只有我们去玩,去听,才能体会人们生活的许多乐趣。并非就普通话表达的那一点。网上也开始流行各地方言的教科书。往往都是异想天开的学生们对生活乐趣的一种表达,对自己每天用的语言的一种热爱。网络会慢慢承载更多文化,更多乐趣。
    就写这么点了,理科生就这样,已经写不少废话。觉得有点味道就行了。

posted @ 2010-02-26 21:39 yangyusong 阅读(351) | 评论 (0)编辑 收藏

[置顶]打包——izpack(2)

 

现在我们接着玩上次的试验结果,双击生成的install.jar运行安装,如下图:


lzPack1-1

下一步如图:(你发现和lzPack本身的安装过程和界面是一样的,不过也已经够漂亮了,是吧)(以后都是下一步的图)


lzPack1-2


图lzPack1-3


图lzPack1-4


图lzPack1-5


图lzPack1-6

图lzPack1-7


图lzPack1-8

  点击Done完成安装

  看看我们sample的结构(即要安装的软件)


lzPack1-9

  看看安装好的文件结构


lzPack1-10

少了一个文件listener,多了一个文件uninstaller,进入uninstaller双击uninstaller.jar就看到卸载界面了(超简单的界面,就不贴了)。我们在回头看看那个配置文件install.xml,如下:

<?xml version="1.0" encoding="iso-8859-1" standalone="yes" ?>

- <!--

 
    A sample installation file.
    Use it as a base for your own installers :-)
    
    To compile it :
    - go in the bin directory where you installed IzPack
    - call "compile ../sample/install.xml -b ../sample"

  -->

- <installation version="1.0">

- <!--

 
        The info section.
        The meaning of the tags should be natural ...
    

  -->

- <info>

  <appname>Sample Installation</appname>

  <appversion>1.4 beta 666</appversion>

- <authors>

  <author name="JPz" email="jpz@superman.org" />

  <author name="Hidden Man" email="hidden@hisdomain.com" />

  </authors>

  <url>http://www.anotherworld-inspace-website.net/</url>

  </info>

- <!--

 
        The gui preferences indication.
        Sets the installer window to 640x480. It will not be able to change the size.
    

  -->

  <guiprefs width="640" height="480" resizable="no" />

- <!--

 
        The locale section.
        Asks here to include the English and French langpacks.
    

  -->

- <locale>

  <langpack iso3="eng" />

  <langpack iso3="fra" />

  </locale>

- <!--

 
        The resources section.
        The ids must be these ones if you want to use the LicencePanel and/or the InfoPanel.
    

  -->

- <resources>

  <res id="LicencePanel.licence" src="Licence.txt" />

  <res id="InfoPanel.info" src="Readme.txt" />

  </resources>

- <!--

 
        The panels section.
        We indicate here which panels we want to use. The order will be respected.
    

  -->

- <panels>

  <panel classname="HelloPanel" />

  <panel classname="InfoPanel" />

  <panel classname="LicencePanel" />

  <panel classname="TargetPanel" />

  <panel classname="PacksPanel" />

  <panel classname="InstallPanel" />

  <panel classname="FinishPanel" />

  </panels>

- <!--

 
        The packs section.
        We specify here our packs.
    

  -->

- <packs>

- <pack name="Base" required="yes">

  <description>The base files</description>

  <file src="Readme.txt" targetdir="$INSTALL_PATH" />

  <file src="Licence.txt" targetdir="$INSTALL_PATH" />

  <file src="script.bat" targetdir="$INSTALL_PATH" />

  <parsable targetfile="$INSTALL_PATH/script.bat" />

- <!--

 The file will be parsed 

  -->

  </pack>

- <pack name="Docs" required="no">

  <description>The documentation</description>

  <file src="doc" targetdir="$INSTALL_PATH" />

- <!--

 Reccursive adding 

  -->

  </pack>

- <pack name="Sources" required="no">

  <description>The sources</description>

  <file src="src" targetdir="$INSTALL_PATH" />

  </pack>

  </packs>

  </installation>

 我算它是七段,第一段

<installation version="1.0">

 声明安装的版本

第二段

<info>

  <appname>Sample Installation</appname>

  <appversion>1.4 beta 666</appversion>

- <authors>

  <author name="JPz" email="jpz@superman.org" />

  <author name="Hidden Man" email="hidden@hisdomain.com" />

  </authors>

  <url>http://www.anotherworld-inspace-website.net/</url>

  </info>

 声明软件的基本信息:名称、版本、各个作者和联系方式、公司主页。对应图lzPack1-2

第三段

<guiprefs width="640" height="480" resizable="no" />

设置安装导航的宽高等属性。

第四段

<locale>

  <langpack iso3="eng" />

  <langpack iso3="fra" />

  </locale>

 语言选择,对应图lzPack1-1

第五段

<resources>

  <res id="LicencePanel.licence" src="Licence.txt" />

  <res id="InfoPanel.info" src="Readme.txt" />

  </resources>

 提供两个资源给客户阅读,对应两个界面,图lzPack1-3lzPack1-4。分别为软件说明和基本条款。

第六段

<panels>

  <panel classname="HelloPanel" />

  <panel classname="InfoPanel" />

  <panel classname="LicencePanel" />

  <panel classname="TargetPanel" />

  <panel classname="PacksPanel" />

  <panel classname="InstallPanel" />

  <panel classname="FinishPanel" />

  </panels>

 说明顺序下来都经过那些界面。

第七段

<packs>

- <pack name="Base" required="yes">

  <description>The base files</description>

  <file src="Readme.txt" targetdir="$INSTALL_PATH" />

  <file src="Licence.txt" targetdir="$INSTALL_PATH" />

  <file src="script.bat" targetdir="$INSTALL_PATH" />

  <parsable targetfile="$INSTALL_PATH/script.bat" />

- <!--

 The file will be parsed 

  -->

  </pack>

- <pack name="Docs" required="no">

  <description>The documentation</description>

  <file src="doc" targetdir="$INSTALL_PATH" />

- <!--

 Reccursive adding 

  -->

  </pack>

- <pack name="Sources" required="no">

  <description>The sources</description>

  <file src="src" targetdir="$INSTALL_PATH" />

  </pack>

  </packs>

  提供了要复制的文件夹结构,由<packs>标签包括

  共有三个包,每个包由<pack>标签标识 name=”base” 的包为基本包,包括所有文件和文件夹的文件夹,其下包括三个文件。$INSTALL_PATH即安装路径,由用户给出

  包Docs 是文件夹doc

  <file >元素标明文件或文件夹,src属性为文件或文件夹名,targetdir属性为要放到的路径

  包Sources是文件夹src

  整个文件结构和关系就由最后这一段来阐释。

    另外,包<pack>还可以有其他的用途,下一节是个较实用的实例,你会看到它的用途,要不我们打的包都和izpack一样光秃秃的,没快捷键,没环境变量,在实践中我们慢慢发现光明,原来有趣的东西等着我们去探索。

posted @ 2008-11-24 20:01 yangyusong 阅读(2166) | 评论 (0)编辑 收藏

[置顶]打包——IzPack(1)

 

网页上简绍一堆开源打包软件,你饶有兴趣的在那阅读,发现IzPack就是你很理想的打包软件,点开详细简绍,看到了软件的开源网址(这是基本规律嘛,没给俺就googlebaiduhttp://izpack.org,常规你看到了download的按钮,点吧,不用等网页完全打开,就进入了http://izpack.org/downloads/页面,就只顾找下载的那个链接去,当迅雷下着软件的时候,你在看此页面的各标题,确定重点段落阅读一下,发现没有教你怎么用的,就最初的那个链接也是草草讲了一点无关紧要的然后就叫你上官方网站找学的。不用急,软件下完了,咱先安装,看自述不就行了。

 就软件的安装界面来看,它打出来的包也挺不错,这算一种自身思考吧。安装完毕时,它叫保存什么东西?连什么格式也弄不清(好几个点呢),随便取名保存吧。失望的是,它没有弹出自述文件,看看桌面上,从开始菜单进去一看,有卸载和帮助,就是没有启动。你是不是该怀疑你下载的东西被人做过手脚,可这是官方的呀。简单,问题来了。我们就想关键字,google上输入软件名“IzPack”,点击相关搜索 lzpack使用”。看了几个简绍的,教学大同小异,知道有大概策略,却无从下手,关键就在于写文章的不像我一样喜欢搞策略,总是没我需要的实际,高效。他们往往会讲重点,但却不注意切入点,在大学听课也经常这样,让你痛苦不已,就像被蚊子叮了,挠痒痒的只挠旁边。总是看不到你的存在。

 那些重点、难点你已经知道是那些就行了(其实还不用知道,知道是为了先跳过),只细致的搜寻这你要的切入点。有一个网页说有两三种用IzPack的方法,只是概述那种也把责任推给官方。不幸看到一网站这一段“这个software的基本思想就是,它给你提供了许多安装步骤所需要的panel(比如选择安装路径、选择安装的内容、观看License等等),然后你自己写一个install.xml文件将你自己软件的信息、安装需要的步骤、以及安装的资源等等都写进这个文件里,然后使用它所提供的compile批处理文件编译这个文件(e.g. compile install.xml),它就会自动生成一个install.jar的可执行Java包。至此,整个过程就结束了,双击这个install.jar,就能启动install界面。”,可以想到应该用命令行的方式来用这个软件,其实这个想法早出来了,因为,桌面上也没有lzPack的快捷方式。可我使用命令上就只会如 Javac xx.java 这一种,不过这一点也够了,我已经萌生了一个测试策略。不就是命令加参数吗?验证一下再看其他的。

           1.       cmd进入软件的bin目录(compile.bat在这里)

           2.       软件附有样例这是常规,进入软件目录IzPack下的sample(只有一个xml,compile 处理的就应该是xml,总共只有一个样例,当然所有东西全用),全选,复制,贴入bin目录下(不用怕混了,到时咱对照着删就是了)。

           3.       (输入什么呢,应该以bat文件为命令吧,以所要处理的文件为参数。那就)输入

Compile install.xml

  有输出,有许多文字在输出,你已经露微笑了,不幸命中,就是这么用,一看bin中多了个install.jar,就更放心了。双击看看,哦,原来是个语言选择界面。那么你该处理“策略垃圾”了,你同时打开bin目录和sample目录对比着把bin中复制来的文件一个一个删掉(这只是一种严慎的行为,因为错误总会随时降临)。

  Bin未删sample里复制过来的文件时如下图:


  你其实挺兴奋,严格记下你的第一次,以备以后快速进入和研究,于是你还把
cmd上留下的命令行输出复制出来留待研究。而且你的很多策略也出来了,那个sample就是你参照的对象,写xml可以仿写,sample的结构有多复杂,你打包处理的软件就至少能有这么复杂。对,start里面的帮助文档还没使用呢,下次肯定得用上。其实你在做这个测试的时候都是数着步数的,因为你想看看和上次相比,这软件最快的使用方式有多大差别,对,每次你都用sample来数你开始的步伐了吗?

  这是在cmd里的操作和输出,不是很有意义,仅作为一种完整性贴这。

C:"Documents and Settings"yys>cd E:"Program Files"IzPack"bin

C:"Documents and Settings"yys>e:

E:"Program Files"IzPack"bin>compile install.xml

.:: IzPack - Version 4.1.0 ::.

< compiler specifications version: 1.0 >

- Copyright (c) 2001-2008 Julien Ponge

- Visit http://izpack.org/ for the latest releases

- Released under the terms of the Apache Software License version 2.0.

-> Processing : install.xml

-> Output      : install.jar

-> Base path   : .

-> Kind        : standard

-> Compression : default

-> Compr. level: -1

-> IzPack home : .

Adding resource: IzPack.uninstaller

Setting the installer information

Setting the GUI preferences

Adding langpack: eng

Adding resource: flag.eng

Adding langpack: fra

Adding resource: flag.fra

Adding resource: LicencePanel.licence

Adding resource: InfoPanel.info

Adding content of jar: file:/E:/Program%20Files/IzPack/lib/standalone-compiler.j

ar!/bin/panels/HelloPanel.jar

Adding content of jar: file:/E:/Program%20Files/IzPack/lib/standalone-compiler.j

ar!/bin/panels/InfoPanel.jar

Adding content of jar: file:/E:/Program%20Files/IzPack/lib/standalone-compiler.j

ar!/bin/panels/LicencePanel.jar

Adding content of jar: file:/E:/Program%20Files/IzPack/lib/standalone-compiler.j

ar!/bin/panels/TargetPanel.jar

Adding content of jar: file:/E:/Program%20Files/IzPack/lib/standalone-compiler.j

ar!/bin/panels/PacksPanel.jar

Adding content of jar: file:/E:/Program%20Files/IzPack/lib/standalone-compiler.j

ar!/bin/panels/InstallPanel.jar

Adding content of jar: file:/E:/Program%20Files/IzPack/lib/standalone-compiler.j

ar!/bin/panels/FinishPanel.jar

Building installer jar: E:"Program Files"IzPack"bin"install.jar

[ Begin ]

Copying the skeleton installer

Copying 7 files into installer

Merging 7 jars into installer

Writing 3 Packs into installer

Writing Pack 0: Base

Writing Pack 1: Docs

Writing Pack 2: Sources

[ End ]

Build time: Thu Oct 30 20:08:24 CST 2008

E:"Program Files"IzPack"bin>

   cmd输出的你能看到我用的命令就是刚才写的,就那么一条,然后输出它打包的过程,xml配置有问题的话,就会编译不过去。
  同样izpack是个小巧的开源软件,用大部分用java写的,离不开java环境,打出的包就一jar文件,比起installsheild轻省多了,但问题也来了,客户要安装你的软件就要安装jdk,以后我们会解决这问题。
 下节看看我们的结果并简单研究一下要配置的xml。

posted @ 2008-11-24 18:47 yangyusong 阅读(3947) | 评论 (5)编辑 收藏

[置顶]打包——launch4j

 

这次讲的就简短了,launch4jjsmooth强多了,但也不是我们的研究重点,我主要用它来生成exe,再用izpackinstalljammer打包。

   launch4j也是开源软件,所以可以上http://sourceforge.net下载。安装好后,把C:"Program Files下你安装jdkjava文件名改了,再打开launch4j发现打不开,证明这个软件是依赖java环境的,它本身包打得很小。改回java文件夹的名字,再打开,发现启动界面很漂亮,你的软件也有望成这样了。上次有一点没讲清楚,jsmoothjre路径那就是告诉jsmooth用此jrejvm(大家都知道class的运行靠的就是jvm),而不用再搜寻jdk等中的jvmJsmooth中一栏是jvm查找顺序就是在不自己带上jre的情况下搜寻客户机的jvm的策略。这儿同样要jre进行同样的动作。好,现在就让我们来生成一个不依赖客户机java环境的exe

  前提准备:

  把jdk中的jre复制到你要打包的文件夹(我的是Java2D)下,要打包的jar,这儿用jdkdemo中的Java2Demo.jar,一张bmp图片j2d.bmp,一个ico文件,如图


   你需要填写的也很少。

1.       basicjar一栏找到你的jar,安照同路径给你的exe起名字。在Icon一栏找到你的ico


2.jre一栏写上./jre表示当前路径(launch4j聪明多了,记住你的路径)


 3.Splash一栏的Enable splash screen 打上勾,下面选出你的bmp,估计你软件的启动时间,然后填上比这个时间大的时间。如下为5。这个bmp就是你的启动画面


可以生成了(其实你可以不填
bmp,ico就生成,软件可还贴心)。点击工具栏的齿轮图就生成了。结果如图


多了一个
exe就是你所需。点击就看到启动画面,如下

下次讲
izpack。开始比较有意思了。

posted @ 2008-11-19 23:11 yangyusong 阅读(9799) | 评论 (8)编辑 收藏

[置顶]打包——JSmooth

 

在这之前已经有很多人讲过怎么用JSmooth了,如BeanSoft还贴了自己的视频,网址是: http://download.gro.clinux.org/beansoft/JSmooth_zh_CN.swf  大家记得去参考,做的挺好的。

 写这篇文章一是为了完整性,再一个一步一步过来比较自然,先学会简单易用的,思维也容易清晰。很多的文章也免不了千篇一例,过来看看我的见解还是值得的,呵呵。

 其实这款小软件真是一堆一堆的漏洞,但还是勉强可用,作为开源打包的入门软件。通常都用JSmooth 0.9.9-7版本的,看看下面的图


 
是我们的beansoft翻译的,上次说过了,有问题可要请教他呀。

   先别急着动手,先说学完咱们可以做啥,一个是你可以生成一个有exe壳的jar应用程序,其实就是在你的包里多了一个exe文件,其他的依旧在,不要以为拿着你的exe就出去用了,脱离了你的这个jar,你的这个文件结构就玩完了,甚至脱离了你本地机的java环境就没戏了。你不能要求客户都安装jdk吧,人家不想搞研发。别灰心,看完本文你就知道怎么脱离java环境了(只是脱离本地机java环境哦,不是脱离你的那个包结构,还没那么智能的)。虽然是很简单,可当初我也是不了解。几个人硬没弄出一个脱离java环境的,加上小软件经不起蹂躏,然后不得不怪软件是中文版的,还动手用c来生成exe调用巨大的jdk,然后脱离本地机java。转了一圈回来才理解了怎么回事。之所以说它经不起蹂躏就是你不要对着上面的按钮哗啦哗啦的点,一不小心,它不反应了,你的从新打开,次数开多了,说不定每次都不让你看某些界面。除非你重启。或者正常的某个功能就是不理你了,或者生成的时候忘了敲上exe而不得不从来。所以蹂躏对软件和你都没好长。

 下面分两部分,一部分教你用最简单的方式打出exe,体会一下成功的快乐。一部分教你加上jre脱离本地机java

  

 前提,你有java环境(安装了jdk

 最简单的exe打包

 其实最简单的打包只要写三个地方就可以打了,而你可以对着一个jar文件就打成你的exe,有一点就是你要知道jar里的主类是谁,不知道这个概念就问问别人。那么开始吧,讲的算细了。

 打开绿色软件中的jsmoothgen.exe就开始了。这里以打Java2Demo.jar为例(在jdkdemo里有,我就不提供了),

1.       点击 骨架,选择Windowed Wrapper (表示打的是windows下的,左边栏从上到下就一打包流程,很多都没用上,也没细究。移动鼠标到“?”,人家告诉你该做什么。别太兴奋。)


2.点击 可执行文件,点击红线处的按钮找到你的jar文件,记得换后缀为exe,如图


3.       点击 应用程序,点击classpash 那一栏右边的加号,把你的jar加进去,然后点击红线处,弹出的框中只有一个文件夹,双击打开,直到找到你的主类为止,点击 select 确定,如下两幅图所示


开始生成吧,点击工具栏里的小齿轮,弹出对话框,路径就选在你打包的文件下(好像是必须的),写上名称,如图,确定即可在你的包里看到这个exe


打开
E:"Java2D看到


  其中
j2d.jsmoothjsmooth生成的配置文件,Java2Demo.exe即你要的,点击试试,看能不能用,然后把exe剪切到其他地方看能不能用,放回来,把C:"Program Files下的java文件夹改名字(注意把用到java虚拟机的软件都关了),看exe还能不能用。(别忘了改回来。)

结果清楚了exe不能和jar分离了,也不能离开jvm环境,下面我们就让他脱离本机java环境。这样的exe可以为我们进一步的打包奠定基础,所有它是有用的。

准备条件:把你jdk下的jre考到和jar同一个目录,要图标就找好一个“.ico”的文件三个放同一文件夹下

下面开始:

1.       和刚才一样,点击 骨架,选择Windowed Wrapper

2.       点击 可执行文件,找到你的jar文件,记得换后缀为exe,同样找到包里准备好的ico文件如下图

这就看到一个bug了,我选的ico它显示为另外一个以前同名的ico,即使我改了它的名,其实还有另一点令人不舒服的,就是每次点击找路径都从头找,它不帮你记下。另外注意一点我一来点了保存,把j2d.exe.jsmooth存到了e:"java2D下,所以你看到的路径很短,


    3.和刚才一样找到jar放到classpath里,然后找到主类,(注意顺序性)


4.点击 jvm选项 ,在jvm捆绑包那选上复选框,点红线处找到jre路径并确定。如图


选择了
jre

5.开始生成吧,点击工具栏里的小齿轮,弹出对话框,路径就选在你打包的文件下,写上名称,如图,

确定生成

exe是你要的,这里要抱歉一下,它的bug所致,ico用的不是我当前的ico,但也没什么影响。J2d.bmp什么的是不必要的,下一节才用上,点击exe看,把C:"Program Files下的java文件夹改名字再试一次,噢,可以了,呵呵。Jsmooth 的其他选项就考各位补充了,俺不太明白了,谢谢各位。下次讲launch4j打包。

posted @ 2008-11-19 22:02 yangyusong 阅读(5658) | 评论 (3)编辑 收藏

[置顶]打包——InstallSheild之InatallScript

 

上次讲了InstallSheildasistant的方式,你跟着弄就打处一个包来了,验证一下是否符合你的设置,就是安装一下看看。这就不多说了。

上次的解说你可能已经迫不及待要看看Installation Designer的方式。别急。

   很多时候我们只需要照着一个简单的示例做一次成功,就能体会到达成一间事的最简单方式。所以这次改一下结构,讲解和操作分离,凡是操作的部分都写成 xx操作:”后面跟上本示例操作,xx表示步数,其实有的步是不必要的。你要亲自动手看有此标签的部分就行。有多余的需求和想了解在看具体讲解。用标签 “讲解:”表示具体讲解。

   下面开始

    1操作:打开InstallShield x 又看到起始页,如下图:

  讲解:要是没有,你就新建一个。要删除项目,通常是关闭InstallShield x,然后到ism所在的文件夹删除整个文件夹就行。


    2操作:点击TTPlay.ism打开上次建的项目,如下图:

  讲解:看到如下图,如果看到的不是,你就点一下标签页Installation Designer,看到这个界面,我们应该很高兴,面熟呀,这不和vc6.0的和相似么。其实用法、语法也很相似,红线圈住的部分是下一步操作的


3操作:点击上图左边树状目录中红圈中的部分,看到如下图:

讲解:左边的目录也是九个,对应项目助手的九个步骤


    4操作:右击中间目录中的,看到如下图:再点击Make default,那么默认就是中文了。

  讲解:红勾就到了Chiness选项,上次的问题就解决了,再次安装是看到的就是中文了,不信可以点击编译、链接,执行试试,和vc一样,这两个图中都有,自己试试。

  点击Project Properties,可以看到,保存配置的方式是xml,其他信息都是默认配置或你在工程助手那填写的。


  所有东西到要安装,不需客户选择,那么可以如下操作

    5操作:点击左边目录的Setup Types ,看到中间目录,右击Complete选项,点击Remove删除

  讲解:你说为什么不删除Custom因为Custom里才可以让客户选择安装路径。


    6操作:点击左边目录的Files and Folders,展开中间部分下边栏中的Application Target Folder目录看到如下图

  讲解:Destination computer’s folders栏里的各目录在同上节添加文件是所看到的弹出目录含义相同,参看上节,在这儿你可以展开source computer’s folders中我的电脑,直到找到你要打包的文件夹,拖到下边栏中的Application Target Folder目录就行,也是比较浪费时间(他要搜索你的整个结构进去),和使用工程助手添加文件夹的效果相同,但显然这样感觉更方便,尤其是有多个文件夹并列时(很多时候你不想要很深的目录,公司名文件夹下、软件名文件夹才到你拖进来的文件夹,可能你的好几个文件夹都只想做公司名文件夹下的子文件夹,那么想上次讲的你可以不写软件名,然后再这多次拖动并列的这几个文件夹。)。在具体的,有少量文件变动你可以点击有文件变动的文件夹,在最右边上面的文件拖到下面的相应位置。变动比较大,建议你就吧下边栏中Application Target Folder里的文件目录都删掉再重新拖进去


    7操作:点击Shortcuts 展开中间栏的ttplay目录,展开中间栏的Desktop目录并点击TTPlayer.exe1看到如下图(这一步可以省去,只是看一眼就行,谨慎行事就在看讲解)。

  讲解:没有的话,你就自己在这儿建,相信你会需要这样建而且也很方便,没有快捷方式的话,可能你看到的只有Programs Menu 那么你就右击Programs MenuNew Folder新建文件夹(就是在开始菜单中的文件夹,一个文件夹中有可若干个选项调用不同的exe,然后对文件夹起名字(最好用你的公司名,要是改名,按F2就行了)然后右键点击这个刚建的文件夹,点击New Shortcut 新建你的快捷方式并起上名(也是弹出一个框,你找到你的exe,但名字是要自己给的)。要注意的就是起好名字后点击这个快捷方式,在最右边的wording Directory填上你的工作目录,要不产生的快捷方式找不到你的exe,如果是Desktop就填上<DesktopFolder>,如果是Start Manu就复制Target中的目录不到xxx.exe,而是它的上层目录。如<TARGETDIR>"TTPlayer"TTPlayer.exe就只复制<TARGETDIR>"TTPlayer贴到Working Directory,Display name改为你的软件名,这个名字将显示在快捷方式里,如这儿改成TTPlayer


    8操作:点击Registry,如下图(只一步也可省去)

  讲解:和Files and Folders一样,中间一栏上面是本机的,下面是对应的,要注册什么在本机上新建了,拖到下面就行了,也都点右键新建同名文件夹直到最下层,拖动你刚建的名值对就完了。


  讲解:
Server Configuration中的两项是iisSQL Server2000,我们都不用,也都很简单。跳过。

    9操作:点击InstallScript 看到如下图


  讲解
:这是重点,这里可以添加代码来修改环境变量、添加验证、添加调用等。这儿只会讲到添加环境变量,添加调用会在讲开源软件是讲。具体语法讲解只有InstallSheild 5的,从哪个网站下,忘了,刚搜了一下,感觉这个网站应该能下:http://cio.ccw.com.cn/qtzl/htm2008/20081018_523911.shtml 不行你就到google 输入 installshield 丁有和”。

  复制其中的部分代码如下:

Dlg_Start:

    nResult = 0;

Dlg_SdWelcome:

    szTitle = "";

    szMsg = "";

    //{{IS_SCRIPT_TAG(Dlg_SdWelcome)

    nResult = SdWelcome( szTitle, szMsg );

    //}}IS_SCRIPT_TAG(Dlg_SdWelcome)

    if (nResult = BACK) goto Dlg_Start;

Dlg_SdLicense2:

  很显示它的语法挺简单,大致你也能猜到,这儿是三个对话框,都是用标签的方式,说明我们要跳来跳去,不错,if (nResult = BACK) goto Dlg_Start;就是通过一个判断调回上一个对话框。Dlg_Start即开始对话框,Dlg_SdWelcome即欢迎对话框。nResultszTitle等都是变量,并非弱类型的变量,前边有定义。

废话不多说,我们要加上一个环境变量,

    10操作:对着有代码那一栏拖动滚动条到最下面看到最后一个end为止,在它的下一行粘贴如下代码:

function OnEnd()      

string mypath, szKey, szEnv;        

POINTER pEnv;  

begin                

 mypath=TARGETDIR;     

 szKey="Environment";  

 RegDBSetDefaultRoot(HKEY_CURRENT_USER);     

 RegDBSetKeyValueEx(szKey,"mypath",REGDB_STRING,mypath,-1);  

 szEnv = "Environment";  

 pEnv = &szEnv;  

 SendMessage (0xffff, 0x001A , 0, pEnv );  

 // MessageBox("设置了环境变量mypath ",0);

end;

  讲解:要调用函数就的在那些对话框中找个位置插入这个函数,这儿就找“Dlg_SetupType2:”标签

    11操作: 找到“Dlg_SetupType2:”标签,在其后新加一行 OnEnd();

讲解:此时应该点一下Complile,编译一下(和用vc一样来使用),若有错会和vc一样在下面报出,双击错误到出错行,如果你是复制代码过去的,很可能是字符编码不一致的问题。特别是中文和空格,那么去掉每行前面的空格可能就去了大部分的错误,有中文的行最好去了,自己再敲一次,实在不好解决的就全去了再全部敲一遍。

  注释方式和c,java的一样,这儿把后面那个注释去了,运行到那时就会那个弹出对话框。内部函数查帮助,语法和常用函数看我刚才介绍下载的讲解。

  这里边还有调试运行,好像不能加断点,全都是从头至尾的走。但同样有跳出函数,停止调试等常规操作。

    12操作:点击Dialogs(可以省去),看到如下图:


  讲解:在
Skin里有多种风格的皮肤,通过右键点击来选取。All Dialogs里有从开始安装到结束安装的各种可能用上的对话框,通过双击可以在这里改变这些对话框的结构。当然标志installshied可不好去,最好也别去,谁叫你用人家的产品。这些对话框的引用可以在前面的InstallScript代码来引用。如Welcome对话框就用“Dlg_SdWelcome:”标签来引用。

    13操作:点击编译。(与vc一样)

  讲解:ok,本次操作结束。到你创建的目录下就能找到setup.exe点击安装试试,或者点InstallSheild x里的运行。也行。


  如果加了环境变量,就能找到,如我这儿添加了
mypath= C:"Program Files"JoinusRip,看看你的。有问题提问。

  这次一个13个操作(可能还不要或者更多一点)你就用InstallSheild x打包好一个软件,不到两分钟。你可能急了,说我只帮你解决了添加环境变量的问题,你还有很多要求,要求调用其他软件先安装呀什么的。其实大部分情况这些已经差不多了。你的问题也许可以换种方式,要不你自己正是很不轻松,尽管你及其勤奋。要先安装其他软件,你可以通过选择安装对话框加说明让用户先安装你要求的。这种对话框你可以通过另外的打包软件处理,要不去记InstallSheild的一堆语法,不一定吃得消。我也不敢讲一堆,更主要的原因是,这可不是免费的软件,你用了说不定哪天律师就来找你了,所有你仅仅体验一下明白打包的一个大体过程就可以了,学问有相似之处,再学其他的也就不那么难了。除非你公司买了InstallSheild,否则你就先把它扔一边吧,我们有更好的开源软件,虽然一下子讲不到最好的。

  提醒一下,如果你运行了刚打好的包,或打开了包所在的文件夹,此时编译会过不去,总提醒一个错误,还有InstallSheild x有很多bug,不行了,你就删除从来。有人翻译了InstallSheild2008的部分,当然帮助没翻译,你可以下来看看都什么意思,但想使用好像不是很现实。当然要学好就得看英文的,很多人都习惯了看英文的帮助,但一下子要看明白并操作许多也还是花点时间的。另外所有的部分都是用例子来讲,不会面面俱到,要深入必须再花时间看帮助,相信有了例子,再看帮助的时候理解的就多了。

  下次进入开源,最简单的jsmooth,中文版翻译是刘长炯,这次我惨了。希望他没写相关的,要不撞车了。

posted @ 2008-11-17 01:14 yangyusong 阅读(1504) | 评论 (2)编辑 收藏

[置顶]打包——installsheild之Assistant

 

  经简绍说installsheild不错,打包方便快捷,于是要来软件,安装的是InstallSheild x英文版。

如下图,这是打开的见面,红线是我画上的,点击这条语句就开始新建工程了。


  弹出对话框中默认的
InstallScript Project(如下图) 正是我们所需(以Script的方式来完成更多任务)。填入你要打包的项目名,和要释放的位置(打成的包要放的位置),(什么?你说我打的怎么是TTplay,不好意思,TTplay确实是别人的,要先试验再动真格的,要不就元气大伤了。把安装了的TTplay打成包不是很简单的试验方式么。一来就把你几百兆的软件拿过来打,又慢风险又大。你也不知道刚用的软件会发生些什么事故,保险起见,把安装在你电脑里的整个TTplay的文件夹考到一个地方备用。才2点几兆,尽情试验吧)。点击Ok进入下一步。


  于是你就见到了
Project Assistantinstall Designer.如下图所示
  我们就叫
Project Assistant为工程助理吧,用工程助理就可以完成一般的打包工作,只要点击最下排图标,从左至右来按向导填写就行,网上应该有简绍的,但我还是要唠叨,好像这儿会更有特色。你也完全可以在install Designer里全部完成,但通常都是结合着用。


    Project Assistant共九步形成一个安装流程。

点击第一个Application Files,如下图

以此是公司名称、应用软件名称、版本、公司首页。最后的选项是是否自动提醒更新。

生成的软件安装后会以你的公司名为文件夹,应用软件名称为其子文件夹,接着是你的放进去的文件夹(后面会讲到),很多时候你可能不需要这么多文件夹嵌套,像我打包的文件夹就不要应用软件名称,否则,所设置的环境变量就不好处理了,但这的试验就不用管了,后面具体讲。你要根据你所需的文件结构来决定。


  点击
installation Architecture,如下图,只有一个选择项,问你是否要个性化安装,意思就是可以选择部分安装,我们就不管了,我们都是要全装的,哈,而且这儿也很简单。(还是说说吧,点选yes,点击New,添加文件夹,取个名字,Set Default来设计你选定要做默认安装的,下一步骤是选定你要打包的文件,其中All Application下拉框选项就会发现刚才你new的文件,选定谁,当前放进的包就属于它了,好像有点抽象,看看想想就应该明白了)


  点击
Application Files看到如下图

我们要全安装所以用All Application Data,下面的Destination Computer中的重点文件夹是Application Target Folder,其意义就是客户所选路径+公司名+软件名这样一个路径。

Program Files 是绝对路径“C:"Program Files”群里有哥们为要放一些文件到这个绝对路径,问了几天人,告他用Indesigner中的Program Files,他没明白,效果和项目助手的一样。

Windows也是绝对路径,“C:"WINDOWS”下属分别为“C:"WINDOWS"Fonts”和“C:"WINDOWS"system32


  这儿还没操作呢,开始操作,点选
Application Target Folder,点击Add Folders 选定你打包的文件夹,确定就会在Application Target Folder里显示你的文件结构,这可是个慢动作,文件越多就越慢,实际它只是记录了你的文件结构,并非复制。结果如下图:

如果你看不到,很正常,这是它的一个bug,点一下其他的步骤,再点回来就看到了(点回来有时也要你一些时间,bug呀)


  点击下一个步骤
Application Redistributables,如下图:

就是问你用不用ODBCsql Server 2000 等等的,都不管了,我们喜欢用开源的。


  点击下一步骤
Application Shortcuts,即应用程序快捷方式,如下图


  它自动帮你提起你所给文件夹下的
exe,你的软件要没exe就先生成exe,以后会讲到

  你的问题出来了,要是exe不在所给文件夹下怎么办,你就点new,弹出窗口展示的是DefaultFeature里的文件分类(如下图),文件分类和前面讲的一样,Application Target Folder 是客户所选路径+公司名+软件名这样一个路径……回忆起来俺就不废话了。大部分情况点击Application Target Folder到你提供的文件夹里找到你的exe就有了。


  点选你的
exe,然后在右边的复选框选择是否创建开始菜单快捷方式和桌面快捷方式(看下图)。点选并删除你不用的exe。你可能觉得这样方式真好,后面你会发现工程助手的方式不如Install Designer 的方式好,工程助手可能会令你反复弄来弄去。


  下一步
Aplication Registry,如下图:

你就需要选择一个根目录,然后不断点右键新建选项,最后定变量—数值对就行


  如下图,新建一次后,再次新建里就可以新建各种值,或者选择导入
Reg的方式,具体自己研究了。也是Install Designer 的方式更好。这儿什么都不需要注册,把刚加的删了。


  下一步
Installation Interview 如下图:

共四个选项,第一个选项是是否要license,是的话你要提供一个txtlicense或者写一段脚本来处理。我们选择否。

第二个选项是是否填入公司名和用户名,不用了,我们这不用那么麻烦客户。

第三选项说是否让客户选择安装目录,默认就行(yes)。

第四选项说是否同意客户只安装部分。也默认就行(yes)。


  下一步骤
Installation Localization 安装本地化,如下图:

选上简体中文。All String Data等功能和All Application Data的意义是一样的就是看你要整个处理还是安装某部分才这样处理。我们用默认的就行。


  最后一步
Build Installation 就是生成你的软件了。如下图:

三个选项意义就是生成单个执行文件、网络版、光盘版。

点击Build Installations就开始建造了。这个过程也有点慢,毕竟要把所有文件存储到一个dat文件里。


  结果如下图:


  点击
setup.exe就可以安装了。

当然这样的效果可能不如你想象的好,例如点开可能是英文的,你就急了,不是本地化了吗?你忘了看,同时选中的English上有个红勾,表示它是默认语言,要么你把英语的去掉,要么你上Install Designer处理。

如果你已经安装过这个setup.exe,再次点击时它就会提醒你是要修改、修复还是卸载,如下图:


  这就是
InstallSheild用向导打包软件的简单过程。你应该知道有exe的软件怎么打包了,下次讲InstallSheildinstall Designer的方式,它能满足你更多的需求。能解决你在工程助手这令人抓狂的问题。

错漏之处,谢谢指正。

posted @ 2008-11-16 01:50 yangyusong 阅读(2055) | 评论 (4)编辑 收藏

仅列出标题  下一页

导航

统计

常用链接

留言簿(3)

随笔分类

随笔档案

文章分类

搜索

最新评论

阅读排行榜

评论排行榜