smack是什么?具体百度一下。我的理解也不深,我理解其实就是XMPP协议的实现。都是浮云,一切都是工具。
首先还是下载smack,我下载的是smack_3_2_0.tar。这个包里有四个jar文件。
首先创建一个java工程。创建一个lib文件夹,把这四个jar包放到lib中,添加到编译路径中。
目录接口如下:
怎么图片还还没传上来。哎。
创建一个TestSmack.java类。具体代码如下:
package org.yangzc.smack; import org.jivesoftware.smack.ConnectionConfiguration; import org.jivesoftware.smack.PacketListener; import org.jivesoftware.smack.XMPPConnection; import org.jivesoftware.smack.XMPPException; import org.jivesoftware.smack.filter.PacketFilter; import org.jivesoftware.smack.packet.IQ; import org.jivesoftware.smack.packet.Packet; public class TestSmack { public static void main(String[] args) throws XMPPException { ConnectionConfiguration config = new ConnectionConfiguration("127.0.0.1", 5222); XMPPConnection connection = new XMPPConnection(config); XMPPConnection.DEBUG_ENABLED = true; connection.connect(); connection.login("admin", "admin"); // ChatManager chatManager = connection.getChatManager(); // chatManager.addChatListener(new ChatManagerListener(){ // @Override // public void chatCreated(Chat chat, boolean arg1) { // chat.addMessageListener(new MessageListener(){ // @Override // public void processMessage(Chat arg0, Message arg1) { // System.out.println(arg1.getBody()); // } // }); // // } // }); connection.addPacketListener(new PacketListener(){ @Override public void processPacket(Packet arg0) { System.out.println(arg0); } }, new PacketFilter(){ @Override public boolean accept(Packet arg0) { return true; } }); IQ iq = new IQ(){ @Override public String getChildElementXML() { StringBuilder buf = new StringBuilder(); buf.append("<query xmlns=\"com:im:group\"/>"); return buf.toString(); } }; connection.sendPacket(iq); // Chat chat = chatManager.createChat("yangzc", new MessageListener(){ // @Override // public void processMessage(Chat arg0, Message arg1) { // System.out.println(arg1.getBody()); // } // }); // chat.sendMessage("hello World!!!"); // BufferedReader cmdIn = new BufferedReader(new InputStreamReader(System.in)); // for(;;) { // try { // String cmd = cmdIn.readLine(); // if("!q".equalsIgnoreCase(cmd)) { // break; // } // chat.sendMessage(cmd); // }catch(Exception ex) { // } // } connection.disconnect(); System.exit(0); } }
测试:启动openfire服务端,添加插件到openfire中。运行这个例子。可以看到,smack和openfire的插件通信成功。
总结:
这里比较关键的一句话时是:buf.append("<query xmlns=\"com:im:group\"/>");这句话指定了这个消息是发动到那个命名空间中。
只有发送到openfire插件对应的命名空间中openfire插件才可以正确接收。
当初在这里费了好大的功夫。至此openfire插件和smack的通信实现算是告一段落。剩下的工作就是xml了,不用说了吧,很简单的。
明天写什么呢?应该在研究一下androidpn。简单看了一眼,好像是android领域的服务器推送。推动就那些吧,推推拉拉的。
openfire则是XMPP协议的XMPP服务器嘛
Android 2.3 提供了类 android.media.audiofx.Visualizer 支持获取音频FFT数据, 剩下的工作就只是显示在界面上了。
ApiDemos 提供了Sample com.example.android.apis.media.AudioFxDemo
参考资料
- http://topic.csdn.net/u/20090606/17/e2a7945d-b81e-4653-99a5-b5166c2f249c.html
- http://topic.csdn.net/t/20050107/09/3705915.html
- http://topic.csdn.net/t/20050107/09/3705908.html
- http://www.codeproject.com/KB/audio-video/waveInFFT.aspx
- http://www.cppblog.com/jackyxinli/archive/2009/02/04/72950.html
- http://www.codeproject.com/KB/audio-video/DSound_Spectrum3.aspx?msg=2872144#xx2872144xx
- http://www.codeproject.com/KB/audio-video/DSound_Spectrum.aspx
- http://www.codeproject.com/KB/audio-video/DirectSound_Spectrum2.aspx
- http://www.codeproject.com/KB/audio-video/DSound_Spectrum3.aspx
- http://code.google.com/p/yoyoplayer/
- http://hyry.dip.jp/pydoc/fft_study.html
- http://developer.android.com/reference/android/media/audiofx/Visualizer.html#getWaveForm(byte[])
- http://stackoverflow.com/questions/4720512/android-2-3-visualizer-trouble-understanding-getfft
- http://stackoverflow.com/questions/4779287/what-kind-of-output-should-i-see-from-getfft
- http://www.mathcs.org/java/programs/FFT/
- http://www.dspguide.com/ch10/3.htm
- http://www.codeproject.com/KB/audio-video/PeakMeterCS.aspx
有个前面2篇(框架分析、JetPlayer类解析)的介绍,相信大家都迫不及待的想知道JetBoyThread这个核心类到底是如何运行的,下面我们就逐步为大家解析。
首先,分析这个类的状态图,如下所示
这张图就是我们整个程序的循环周期:PLAY——RUNNING——LOSE。根据这张图,我们逐步细化,这里我们重点介绍RUNNING,其他2种状态比较简单,这里就不再说明了。
START_RUNNING状态下的流程图,实际上就分为2部分:事件处理(updateGameState)、画图(doDraw),如下图所示:
将上面的2个活动图,逐步细化如下
- doDraw细化后的活动图,如下图所示:
解析说明:根据状态画当前的游戏实时的图像。 - updateGameState细化后的活动图,如下图所示:
解析说明:这是一个循环从消息队列中获取消息的过程,直到消息队列为空。
看到上面的TIMER_EVENT大家是不是绝对奇怪,在Android SDK文档中有明确说明,如下:
Trigger Events :Breaking a MIDI file into individual (non-linear) segments and queueing up those segments for playback in a game based on events within the game is one way JET music files are interactive. Trigger events are an additional method for interactive playback.
也就是说我们可以在segment中定义一些事件,到了特定的时间来触发。在前面已经说过,JET除了播放声音特效意外,应该还有个更加重要的重要:游戏的时钟。我们就可以在segment中定义一些特定的事件,这些时间就相当于是CPU中的时间片。当然MIDI规范中已经定义了很多事件,我们可以自定义事件的ID范围:80-83。查看程序中的代码,如下:
private final byte NEW_ASTEROID_EVENT = 80;
private final byte TIMER_EVENT = 82;
这2个事件分别用来触发产生新的asteroid、界面更新。
至此,整个核心代码的流程,我们都已经分析完了。这个游戏相对来说比较简单,就是通过按下中间键来发射子弹,飞船的位置与当前出现的陨石在一条水平线上,通过计算飞船与陨石的距离来检测是是否集中陨石。
其次,补充说明遗漏的地方在这里需要补充说的是,在程序中使用了
private Timer mTimer = null;
private TimerTask mTimerTask = null;
这2个就是来实现一个定时器,游戏界面上的时间就是通过这个定时器:定时向主线程发送消息来更新游戏剩余时间的。具体的实现是:通过Handler来绑定到当前线程,然后通过Handler向主线程发送消息,并在Handler中处理消息,这个在Snake游戏中已经说明了,这里就不在详细说明了。
最后,总结说明这个实例比较复杂,尤其是JET部分,我也是查阅了不少的资料,然后再具体分析阅读,最终把我自己分析的与大家分享,其中有很多地方还不是很详细。这个游戏本身没有什么可玩性,其主要作用是:演示如何通过JET这个引擎来播放声音,以及如何利用JET的事件来作为游戏的时钟;但是通过这个实例,在以后发游戏开发中却为我们提供了一个很好的实例,在以后的游戏开发、应用程序开发中都很值得借鉴。