(The source code is still in jar)
Source code: http://code.google.com/p/loon-simple/downloads/list
To be honest, the delay in downloading game resources and calling is only an auxiliary means. It has little to do with the development of the game itself. In essence, it is nothing more than a mix of file downloads and file reads. However, considering that some netizens asked such questions last week, I think it is better to write a blog post that is more specific and clear than to explain it in an email. It can also help the author to answer the question, for reference only.
Generally, we need to download game resources for the following purposes:
1. Simplified game volume:
Suppose I have a MB game, but I don't want to promote it as a 1 MB exquisite program. What should I do?
Spoof users and use a large number of complicated technical terms to tell them the equivalent of 1 MB and MB? -- The user is not a fool, at least not a fool. No matter how clever you are, it is difficult for most people to believe that 1 MB and MB are the same. However, we have to find a solution.
In fact, in the existing technical system, to solve their problems, we only need to package the initial game interface mixed download loader into a 1 MB file for release, and then "cheat" them to download and execute, then -- let them wait until the system loads the remaining 99 MB! After all, no one said that this game does not require additional network resources to be synchronized ......
2. Online Game resource loading latency needs:
Currently, online games, especially web games, do not load all resources into the game most of the time in order to minimize unnecessary resource losses and improve operation efficiency, instead, the game resources are built into small resource packages and loaded into the game either synchronously or asynchronously only when necessary. This is exactly what we have seen in many online games. When a role goes through a screen, reads a new map, or encounters a new monster, the screen will show a few moments or some mosaic or even a pause.
Therefore, loading the required resources through the network in a timely manner has almost become one of the essential skills in online game development.
3. Integrate with Special encryption and decryption mechanisms:
We all know that, but no one can crack the programs made by people. However, it is very likely that a program made by one person cannot be cracked by another person within several years. After several years, when another person cracked the program, the program had been so angry that no one needed it.
Therefore, when you do not want your game to be reverse-engineered, especially to protect the Java decompilation code, another meaning of downloading through the Internet is displayed. You can save the downloaded jar, class, and Other types to a "secret" place different from the execution directory, regardless of the key or special structure, in short, the developer can encrypt and confuse resources. Even if you don't even know what this is, it doesn't matter-you can interpret it as a bytecode to maximize the reverse difficulty. When the execution is complete, delete the task again-you can try again next time. In this way, although the Code cannot be completely prevented from being stolen by others, at least it can also make the reverse code's buddy tired (^ ).
4. verify the validity of local programs and resources:
In most online games, in order to prevent users from making "foul" behaviors such as using plug-ins, the legality of the system environment and even the data packets will be verified, once an "illegal" item is found, it will cause a "illegal" player to be suspended or simply block the number to show punishment.
However, these verifications only target the program "external", that is, when the "foul" object "is not my game, however, if the "foul" is "from the game itself" or "when the verification program thinks it is from the game itself", it becomes powerless. This is why most online games are "inner.
Fortunately, Java programs are hard to be cracked and used outside the virtual machine due to their "limited by tianzi". If Java is used to create online games, in principle, there is no need to worry about "Internal mounting"-but there is also a major premise that it will only work when "Internal mounting" runs outside the virtual machine.
What if "Internal mounting" runs in a virtual machine? What if my "inner hanging" is a short piece of code inserted into the original game? You know, it's not a long time to dynamically load the class and modify the bytecode.
In this case, you need to verify the validity of the Java program.
It is time-consuming to verify such a thing, but if we are good at using each download of resources (relatively large, such as image or game updates), if we do not just "Download ", more synchronous "upstream", the use of the gap with the server to verify the legitimacy and integrity of the local Java program, can greatly avoid this meaningless verification time waste. In this case, a missing file will be added, and there will be extra-that is, the jar, class, or even the original bytecode that should not exist will be modified, so the system will forcibly "Abort" It, it will not be "a curse ".
5. system upgrade:
Generally speaking, most programs cannot be used in a single version, and games are no exception. The addition of functions or bug fixes cannot be separated from system updates. To avoid the trouble of re-installing each update, it is necessary to download and update resources over the network and automatically update the system.
How to implement:
Below is a simple example of JAVA Implementation for delayed download of resources. Load the two sample programs in my previous blog and run one of them. (PS: Since the resources loaded in this example are jar, dynamic class loading is performed. When we download other resource types, such as ZIP files containing only images, the download steps are the same, but you only need to replace the operation with reading compressed files and loading compressed file resources .)
Downloadtool. Java (this is a simple download tool class with built-in Download Status display and download bar Drawing)
Package Org. loon. game. simple. download; <br/> Import Java. AWT. color; <br/> Import Java. AWT. font; <br/> Import Java. AWT. fontmetrics; <br/> Import Java. AWT. graphics; <br/> Import Java. AWT. image; <br/> Import Java. AWT. rectangle; <br/> Import Java. io. file; <br/> Import Java. io. inputstream; <br/> Import Java. io. randomaccessfile; <br/> Import java.net. httpurlconnection; <br/> Import java.net. malformedurlexception; <B R/> Import java.net. URL; <br/>/** <br/> * Copyright 2008-2009 <br/> * licensed under the Apache license, version 2.0 (the "License"); you may not <br/> * use this file except T in compliance with the license. you may obtain a copy of <br/> * The license at <br/> * http://www.apache.org/licenses/LICENSE-2.0 <br/> * unless required by applicable law or agreed to in writing, s Oftware <br/> * distributed under the license is distributed on an "as is" basis, without <br/> * warranties or conditions of any kind, either express or implied. see the <br/> * license for the specific language governing permissions and limitations under <br/> * the license. <br/> * @ project loonframework <br/> * @ author chenpeng <br/> * @ Email: ceponline@yahoo.com.cn <br/> * @ version 0.1 <Br/> */<br/> public class downloadtool implements runnable {<br/> final static private Font font = new font ("", 0, 14 ); <br/> private rectangle; <br/> final static private image barimage = graphicsutils <br/>. loadImage ("image/bar.png"); <br/> final static private int max_buffer_size = 2048; <br/> final static private int downloading = 0; <br/> final static private int paused = 1; <br/> fin Al static private int complete = 2; <br/> final static private int cancelled = 3; <br/> final static private int error = 4; <br/> private image backgroundbarimage; <br/> private image progressbarimage; <br/> private image dialogbarimage; <br/> Private URL; <br/> private int size; <br/> private int downloaded; <br/> private int contentlength; <br/> private int status; <br/> private downloadlisten listen; <Br/> private string downloadname; <br/>/** <br/> * Create a progress bar prompt box <br/> * @ Param object <br/> * @ Param W <br/> * @ Param H <br/> * @ Param filtrate <br/> * @ return <br/> */<br/> Private Static Image createdialog (image object, int W, int H, <br/> Boolean filtrate) {<br/> image barimage = NULL; <br/> If (filtrate) {<br/> barimage = graphicsutils. drawclipimage (object, 249, 30, 1, 57); <br/> barimage = G Raphicsutils. transblackcolor (barimage); <br/>} else {<br/> barimage = graphicsutils. drawclipimage (object, 249, 27, 0, 0); <br/>}< br/> image imageleft = graphicsutils. drawclipimage (barimage, 8, 27, 0, 0); <br/> image imageright = graphicsutils. drawclipimage (barimage, 8, 27,241, 0); <br/> image imagecenter = graphicsutils <br/>. drawclipimage (barimage, 233, 27, 8, 0); <br/> imagecenter = graphicsutils. Getresize (imagecenter, W, H); <br/> graphics CG = imagecenter. getgraphics (); <br/> CG. drawimage (imageleft, 0, 0, null); <br/> CG. drawimage (imageright, W-8, 0, null); <br/> CG. dispose (); <br/> return imagecenter; <br/>}< br/>/** <br/> * constructor, load the specified URL <br/> * @ Param URL <br/> */<br/> Public downloadtool (string URL) {<br/> This. size =-1; <br/> This. downloaded = 0; <br/> This. status = downloading; <Br/> try {<br/> This. url = new URL (URL); <br/>} catch (malformedurlexception e) {<br/> throw new runtimeexception (E ); <br/>}< br/> Public downloadtool (URL) {<br/> This. url = URL; <br/> This. size =-1; <br/> This. downloaded = 0; <br/> This. status = downloading; <br/>}< br/>/** <br/> * set the position of the progress bar <br/> * @ Param x <br/> *@ param Y <br/> * @ Param W <br/> * @ Param H <br/> */<br/> Public v Oid setrectangle (int x, int y, int W, int h) {<br/> setrectangle (New rectangle (X, Y, W, h )); <br/>}< br/>/** <br/> * set the position of the progress bar <br/> * @ Param rectangle <br/> */ <br/> Public void setrectangle (rectangle) {<br/> This. backgroundbarimage = graphicsutils. drawclipimage (barimage, 249, <br/> 27, 0, 0); <br/> This. backgroundbarimage = createdialog (backgroundbarimage, <br/> rectangle. width-2 1, rectangle. height-2, false); <br/> // This. progressbarimage = graphicsutils. drawclipimage (barimage, 27, 27, <br/> // 28, 28); <br/> // This. progressbarimage = graphicsutils. drawclipimage (barimage, 27, 27, <br/> // 56, 28); <br/> This. progressbarimage = graphicsutils. drawclipimage (barimage, 27, 27, <br/> 0, 28); <br/> This. dialogbarimage = createdialog (barimage, rectangle. width, <br/> rectangle. height, True); <br/> This. rectangle = rectangle; <br/>}< br/>/** <br/> * returns the current URL <br/> * @ return <br/> */< br/> Public String geturl () {<br/> return URL. tostring (); <br/>}< br/>/** <br/> * returns the total length of the current downloaded file <br/> * @ return <br/> * /<br/> Public int getsize () {<br/> return size; <br/>}< br/>/** <br/> * returns the length of the downloaded file <br/> * @ return <br/> * /<br/> Public int getlevel () {<br/> return downloade D; <br/>}< br/>/** <br/> * return current progress <br/> * @ return <br/> */<br /> Public int getprogress () {<br/> return (INT) (double) downloaded/(double) size * 100); <br/>}< br/> Public int getstatus () {<br/> return status; <br/>}< br/> Public void pause () {<br/> Status = paused; <br/>}< br/> Public void resume () {<br/> Status = downloading; <br/> download (Listen ); <br/>}< br/> Public void cancel () {<br/> Status = cancelled; <br/>}< br/> private void error () {<br/> Status = error; <br/>}< br/> Public int getcontentlength () {<br/> return contentlength; <br/>}< br/> Public void download (downloadlisten listen) {<br/> This. listen = listen; <br/> thread = new thread (this); <br/> thread. start (); <br/>}< br/> private string getfilename (URL) {<br/> string filename = URL. getFile (); <br/> return filename. Substring (filename. lastindexof ('/') + 1); <br/>}< br/> Public String getfilename () {<br/> return getfilename (URL ); <br/>}< br/> Public Boolean isexists () {<br/> return new file (getfilename ()). exists (); <br/>}< br/> Public String getdownloadname () {<br/> return downloadname; <br/>}< br/> Public void setdownloadname (string downloadname) {<br/> This. downloadname = downloadname; <br/>}< br/>/** <br/> * <Br/> */<br/> Public void run () {<br/> If (! Isexists () {<br/> randomaccessfile file = NULL; <br/> inputstream stream = NULL; <br/> try {<br/> httpurlconnection connection = (httpurlconnection) URL <br/>. openconnection (); <br/> connection. setrequestproperty ("range", "bytes =" + downloaded <br/> + "-"); <br/> connection. connect (); <br/> If (connection. getresponsecode ()/100! = 2) {<br/> error (); <br/>}< br/> contentlength = connection. getcontentlength (); <br/> If (contentlength <1) {<br/> error (); <br/>}< br/> If (size =-1) {<br/> size = contentlength; <br/>}< br/> file = new randomaccessfile (getfilename (URL), "RW"); <br/> file. seek (downloaded); <br/> stream = connection. getinputstream (); <br/> while (status = downloading) {<br/> byte buffer []; <br/> If (size-downloaded> Max_buffer_size) {<br/> buffer = new byte [max_buffer_size]; <br/>} else {<br/> buffer = new byte [size-downloaded]; <br/>}< br/> int READ = stream. read (buffer); <br/> If (read =-1) {<br/> break; <br/>}< br/> file. write (buffer, 0, read); <br/> downloaded + = read; <br/> listen. updatescreen (); <br/>}< br/> If (status = downloading) {<br/> Status = complete; <br/> listen. call (); <br/>}< br/>} catch (ex Ception e) {<br/> error (); <br/>}finally {<br/> If (file! = NULL) {<br/> try {<br/> file. close (); <br/> file = NULL; <br/>} catch (exception E) {<br/>}< br/> If (stream! = NULL) {<br/> try {<br/> stream. close (); <br/> stream = NULL; <br/>} catch (exception E) {<br/>}< br/>} else {<br/> Status = complete; <br/> listen. call (); <br/>}< br/>/** <br/> * draw the download progress <br/> * @ Param G <br /> */<br/> Public synchronized void draw (Graphics g) {<br/> int progress = getprogress (); <br/> double ratio = (double) getlevel ()/(double) getsize ()); <br/> int offset = (INT) (rectangle. width * ratio); <br/> G. drawimage (backgroundbarimage, rectangle. X + 19, rectangle. y, null); <br/> G. drawimage (progressbarimage, rectangle. X + 1, rectangle. y, <br/> Offset + 20, rectangle. height-2, null); <br/> G. drawimage (dialogbarimage, rectangle. x, rectangle. y, null); <br/> G. setfont (font); <br/> string MEs = (getdownloadname () + ", progress completed:" + progress + "%") <br/>. intern (); <br/> fontmetrics fm = G. getfontmetrics (); <br/> int W = FM. stringwidth (MES); <br/> int H = FM. getheight () + 2; <br/> G. setcolor (color. white); <br/> graphicsutils. setrenderinghints (g); <br/> G. drawstring (mes, (rectangle. X + rectangle. width)/2-W/2, <br/> rectangle. Y + H); <br/>}< br/>
Downloadcanvas. Java (canvas for downloading and background display)
Package Org. loon. game. simple. download; <br/> Import Java. AWT. canvas; <br/> Import Java. AWT. graphics; <br/> Import Java. AWT. image; <br/> Import Java. AWT. rectangle; <br/> Import Java. AWT. toolkit; <br/> Import Java. AWT. window; <br/> Import Java. AWT. image. bufferstrategy; <br/> Import Java. util. arraylist; <br/> Import Java. util. list; <br/>/** <br/> * Copyright 2008-2009 <br/> * licensed under the Apach E license, version 2.0 (the "License"); you may not <br/> * use this file except T in compliance with the license. you may obtain a copy of <br/> * The license at <br/> * http://www.apache.org/licenses/LICENSE-2.0 <br/> * unless required by applicable law or agreed to in writing, software <br/> * distributed under the license is distributed on an "as is" basis, without <br/> * Warran Ties or conditions of any kind, either express or implied. see the <br/> * license for the specific language governing permissions and limitations under <br/> * the license. <br/> * @ project loonframework <br/> * @ author chenpeng <br/> * @ Email: ceponline@yahoo.com.cn <br/> * @ version 0.1 <br/> */<br/> public class downloadcanvas extends canvas implements downloadlisten {<br/>/** <br/> * <B R/> */<br/> Private Static final long serialversionuid = 1l; <br/> private downloadtool progress; <br/> private graphics canvasgraphics = NULL; <br/> private bufferstrategy; <br/> private image backgroundimage = graphicsutils <br/>. loadImage ("image/background.jpg"); <br/> private Boolean initflag; <br/> private window; <br/> final static list downloadlist = new arraylist (2 ); <br/>/ ** <Br/> * files to be downloaded <br/> */<br/> static {<br/> downloadtool download1 = new downloadtool (<br/> "http://loon-simple.googlecode.com/files/Java25DSimple.jar" ); <br/> download1.setdownloadname ("Download java2.5d walking example"); <br/> downloadtool download2 = new downloadtool (<br/> "http://greenvm.googlecode.com/files/LocalOS_src.rar "); <br/> download2.setdownloadname ("getting started with Java Plug-In download"); <br/> downloadlist. add (download1); <Br/> downloadlist. add (download2); <br/>}< br/> Public void call () {<br/> If (downloadlist. size () = 0) {<br/> window. setvisible (false); <br/> window. dispose (); <br/> jarloaderutils. calljarmain ("java25dsimple. jar "); <br/>}else {<br/> progress = (downloadtool) downloadlist. remove (0); <br/> progress. setrectangle (rectangle); <br/> progress. download (this); <br/>}< br/> final rectangle; <br /> Public void createbuffergraphics () {<br/> createbufferstrategy (2); <br/> bufferstrategy = getbufferstrategy (); <br/>}< br/> Public downloadcanvas (window, int width, int height) {<br/> int PW = 600; <br/> int pH = 27; <br/> This. rectangle = new rectangle (width/2-PW/2, height/2-PH/2, <br/> PW, pH); <br/> This. window = Window; <br/> This. call (); <br/>}< br/> Public synchronized void UPD Atescreen () {<br/> canvasgraphics = bufferstrategy. getdrawgraphics (); <br/> If (! Initflag) {<br/> canvasgraphics. drawimage (backgroundimage, 0, 0, null); <br/> initflag = true; <br/>} else {<br/> progress. draw (canvasgraphics); <br/>}< br/> bufferstrategy. show (); <br/> canvasgraphics. dispose (); <br/> toolkit. getdefatooltoolkit (). sync (); <br/> thread. yield (); <br/>}< br/>
Main. Java (main class, used to start this download example)
Package Org. loon. game. simple. download; <br/> Import Java. AWT. color; <br/> Import Java. AWT. dimension; <br/> Import Java. AWT. frame; <br/> Import Java. AWT. event. windowadapter; <br/> Import Java. AWT. event. using wevent; <br/>/** <br/> * Copyright 2008-2009 <br/> * licensed under the Apache license, version 2.0 (the "License"); you may not <br/> * use this file except T in compliance with the license. you may obtain a copy of <br/> * The license at <br/> * http://www.apache.org/licenses/LICENSE-2.0 <br/> * unless required by applicable law or agreed to in writing, software <br/> * distributed under the license is distributed on an "as is" basis, without <br/> * warranties or conditions of any kind, either express or implied. see the <br/> * license for the specific language governing permissions and limitations under <br/> * the license. <br/> * @ project loonframework <br/> * @ author chenpeng <br/> * @ Email: ceponline@yahoo.com.cn <br/> * @ version 0.1 <br/> */<br/> public class main extends frame {<br/>/** <br/> * <br/> */<br/> Private Static final long serialversionuid = 1l; </P> <p> public main (string titlename, int width, int height) {<br/> This. settitle (titlename); <br/> This. setbackground (color. black); <br/> This. setpreferredsize (new dimension (width + 5, height + 25); <br/> This. requestfocus (); <br/> This. addwindowlistener (New windowadapter () {<br/> Public void windowclosing (invalid wevent e) {<br/> system. exit (0); <br/>}< br/>}); <br/> downloadcanvas progress = new downloadcanvas (this, width, height); <br/> This. add (Progress); <br/> This. pack (); <br/> progress. createbuffergraphics (); <br/> This. setresizable (false); <br/> This. setlocationrelativeto (null); <br/> This. setignorerepaint (true); <br/> This. setvisible (true); <br/>}</P> <p> Public static void main (string [] ARGs) {<br/> JAVA. AWT. eventqueue. invokelater (New runnable () {<br/> Public void run () {<br/> New Main ("Download game data", 640,480 ); <br/>}< br/>}); <br/>}< br/>
Shows the program execution result:
After the download is complete, the downloaded java2.5d walking example is automatically loaded and executed. The screen is shown as follows:
(The source code is still in jar)
Source code: http://code.google.com/p/loon-simple/downloads/list