A Flash Developer Resource Site

Page 2 of 2 FirstFirst 12
Results 21 to 35 of 35

Thread: Design for a multiplayer game in flash

  1. #21
    Adv Web Dev - Novice Flash Dev
    Join Date
    Dec 2007
    Location
    New Jersey
    Posts
    6

    One more thing...

    Hello all, first post here and it is this interesting set of posts that brought me to this forum.

    I have a large amount of experience developing web applications and am interested in starting a project that will use flash.

    To rephrase this question to a scope that perhaps someone can answer...

    What technologies can be used together to allow for the creation of a multi-player online game? To simplify the word "game", please use online poker as an example (ignoring the details of poker including randomness of cards, and rules - using poker will also keep us away from advanced game variables such as 3 dimensional positioning, advanced graphics, etc.).

    Assumptions:
    1. User data and most game data will be stored in an online database.

    I have divided this question into subquestions:

    1. What technology is best to use to have flash talk to a database?
    2. What keeps track of things such as time left until player is skipped, users talking to one another, and other per game time sensitive variables? (if these change, what technology is used to push this to every user?)
    This aught to be a more controlled start to a rather vague question.

  2. #22
    Adv Web Dev - Novice Flash Dev
    Join Date
    Dec 2007
    Location
    New Jersey
    Posts
    6
    Here is a lovely description about the overall idea! Please add more to the information listed here!

  3. #23
    Knows where you live
    Join Date
    Oct 2004
    Posts
    944
    Multiplayer games are generally handled server-side by a socket server such as Electroserver or Smartfox. My preference is Electroserver, but I haven't taken an in depth look at Smartfox, both are very well featured.

    There are also open source socket servers such as Oregano, which is very nice but much more complicated and no longer under development.

    I know Oregano has very complete database support out of the box, however I am unsure about Electroserver and Smartfox.

    Flash can talk to a database through a socket server or PHP. I would highly, highly suggest doing it with the socket server since you will have one running anyways and for security the server will need access to the data anyways.

    Number two is a pretty loaded question. You have two options here, authoritative client or server. For example, if you simply let the client automatically tell the server that its turn is over after 40 seconds, it would work fine, however someone could hack the flash client to cause the game to freeze by no longer sending that message.

    Because of this, the optimal solution would be to have the server keep track of time to prevent player cheating/exploits. Naturally this is more complicated since you can have any number of games running at a time. As well, someone could attempt to crash your server by sending invalid data.

    Throughly thinking out the design of a multiplayer game is very important. A general rule is never trust the client (and this would apply even more to flash since its easy to decompile), however it depends a lot on how much time you are willing to spend. I would suggest having the server verify all moves.
    Last edited by 691175002; 12-28-2007 at 06:18 AM.
    The greatest pleasure in life is doing what people say you cannot do.
    - Walter Bagehot
    The height of cleverness is to be able to conceal it.
    - Francois de La Rochefoucauld

  4. #24
    Adv Web Dev - Novice Flash Dev
    Join Date
    Dec 2007
    Location
    New Jersey
    Posts
    6

    Clarification and example

    I am glad I asked... so pretty much, have everything that is important for the game on the server side and any per user variables on the client side (ex: count down for time left on turn can be left client side - otherwise it would take too much bandwidth to send out every time the count down goes down a second - or millisecond if one wishes to display milliseconds count down).
    Just verify that users are following rules on the server side, don't let the client be the authority on enforcing rules because this is more susceptible to hacking.

    The ultimate goal of a game designer is to come up with a secure game, let the client keep track of non-game/rule important variables such as a count down. This application is also going to be ran on cell phones so bandwidth is a vital consideration.

    For example - if max time per turn is allowed, have the db verify the start time, and the end time, and if the user's input is not received in time, it is invalid. Do not have the client pass a variable with the official time submitted as well as be the authority in saying that a turn was in the acceptable time period.

  5. #25
    Knows where you live
    Join Date
    Oct 2004
    Posts
    944
    Yeah, thats a really good way of doing it. Its all about finding a balance between bandwith and security.

    Just keep in mind that network latency can account for as much as 2-3 seconds in severe conditions. I find that it generally runs 150-500ms in flash.

    I would like to note that the link you posted has some misinformation:
    http://www.techkills.com/455-creatin...ash-games.html

    It states that real time cannot be done in flash, and goes on to blame XML for it. This is partially true, however it is in no way related to the speed of parsing the XML, which would be one or two milliseconds at most, compared to the hundreds that are spent transferring the messages.

    The real issue behind xml is simply that an xml file could be many times the size of a stripped message like 545|235|4634|1423, which sucks bandwith.

    It clearly is possible to make real time online games in flash, but it requires a lot of trickery and smart coding (which has been very well researched in various books).

    The page also states "it is unable to TCP/IP and UDP" which is false, flash uses TCP, and while it does not have UDP capability, dealing with UDP would add far too much complexity to the program since it does not guarantee message delivery.

    Finally, stating that a server is faster than another is unfair and irrelevant. The only control a server has is the size of its messages (Aka whether it uses XML or not), and the newer ones can let you choose which to use. Adobes server simply had built in flash support for streaming video and webcam, which I believe Electroserver has added to their newest offering. Overall I would not rely much on the information on that site.

    I would also suggest choosing a server first, since that will have the strongest influence on the direction your game takes.
    The greatest pleasure in life is doing what people say you cannot do.
    - Walter Bagehot
    The height of cleverness is to be able to conceal it.
    - Francois de La Rochefoucauld

  6. #26
    Adv Web Dev - Novice Flash Dev
    Join Date
    Dec 2007
    Location
    New Jersey
    Posts
    6

    Server

    Thank you for pointing those various mistakes out - This is why I came to a community where experienced users' share their knowledge!
    I am going to use an XML socket server - I notice that you listed a few servers, however, is there a certain server that you would recommend?
    What are the pros and cons of the various servers?

    I was unable to find a thread on "Choosing a socket server." Perhaps this should be started... listing the pros and cons of the various servers.
    Last edited by silly40223; 12-29-2007 at 03:08 AM.

  7. #27
    Knows where you live
    Join Date
    Oct 2004
    Posts
    944
    I found Electroserver to be the nicest of the bunch, with Oregano running second if you need something free. I have never used Smartfox so I am probably biased, but I was really impressed by Electroservers ability to run actionscript code server side. This lets you make the server enforce rules and helps create a secure game without needing to learn Java or messing around with the server itself.
    The greatest pleasure in life is doing what people say you cannot do.
    - Walter Bagehot
    The height of cleverness is to be able to conceal it.
    - Francois de La Rochefoucauld

  8. #28
    Manic
    Join Date
    Jan 2004
    Location
    Denmark
    Posts
    154
    I know this is a really old thread, but thought this might be an interesting tutorial for people looking to make multiplayer games.

    http://playerio.com/documentation/tu...ames-tutorial/

  9. #29
    Junior Member
    Join Date
    Feb 2010
    Location
    welland on
    Posts
    5
    well, what I'm working on is a multiplayer only shooter, and its coming along great. Its a pain to code though, but yeah, ill send you the beta when its done

  10. #30
    Junior Member
    Join Date
    Mar 2010
    Posts
    8

    Smile

    Wow, that's an old thread. But a tip is to use the Smuck multiplayer construction kit. You script the server (it's really easy) using actionscript and add client side controls as drag-and-drop components.

    You can find everything you need here:
    http://www.spogg.com/developer


  11. #31
    Registered User
    Join Date
    Dec 2011
    Posts
    3
    This thread is the top result on google for "make a multiplayer flash game". To anyone who read this far, here is complete code for how to make a server in Java and a client in ActionScript 3. I used Netbeans and Adobe Flash Builder 4 respectively to compile each part. I have completed a single year at university doing game design and java programming, which has taught me very basic programming skills (and standards that I ignore completely - shame on me). The rest I learned through Adobe and Java documentation for sockets, xml, and other stuff. The server uses linked lists to handle the user list and objects, and handles about as much of the game rules as I care to make it. The flash side mostly handles player movement and display of other players.

    What this program does is, once the java server is being hosted, flash clients will connect to it and be assigned a ball. The player can then move around the ball. This information is sent to the client, which then stores the relevant information in a linked list of objects. It will then send that information to every other player connected.

    Note that I do not comment my code, because I am a terrible person. I name my variables poorly and my code is generally hard to read - although it is formatted relatively well. The main class of the server, and the run method in the serverthread class, are mostly taken from a tutorial on the internet somewhere. Some of the stuff in the Client class on the flash side is also taken from a tutorial. The rest is entirely my own work, and to the best of my ability, anyone can freely use all the code in these classes that I have created to make and sell your own games.

    I may possibly hit a character count in this post.

    ACTIONSCRIPT CODE FOR THE CLIENT

    Client.as
    Actionscript Code:
    package {
        import flash.display.*;
        import flash.events.*;
        import flash.net.*;
        import flash.system.Security;
        import flash.text.*;
       
        [SWF(width="1024", height="720", backgroundColor="#E5E5DD")]
        public class Client extends Sprite {
            private var host:String="192.168.1.2";
            private var port:int=8090;
            private var policyPort:int=8091;
            private var socket:Socket;
            private var debug:TextField;
            private var ballsnum:TextField;
            private var userCountText:TextField;
            private var lastDebugMsg:String="null";
            public static var debugMsg:String="";
            public static var game:Game;
            public static var tempID:int=0;
            public static var userCount:int=1;
            public static var main:Client;
            public static var color:uint;
            public static var loaded:Boolean;
           
            public var i:int=0;
           
            public function Client () {
               
                main = this;
                loaded = false;
               
                debug = new TextField;
                debug.width = 800;
                debug.height = 600;
                debug.selectable = false;
                debug.text = "Debug: " + debugMsg;
                stage.addChild(debug);
               
                ballsnum = new TextField;
                ballsnum.x = 400;
                ballsnum.width = 800;
                ballsnum.height= 600;
                ballsnum.selectable = false;
                ballsnum.text = "Balls: " + Ball.Balls.length;
                stage.addChild(ballsnum);
               
                tempID = Math.random()*10000;
                color = 0xCCCCCC * (Math.random()*0x00AAAA);
                debugMsg +="\nNew tempID: " + tempID;
               
                userCountText = new TextField;
                userCountText.x = 750;
                userCountText.width = 800;
                userCountText.height= 600;
                userCountText.selectable = false;
                userCountText.text = "Users: " + userCount;
                stage.addChild(userCountText);
           
                debugMsg += "\nRequesting policy file...";
                Security.loadPolicyFile("xmlsocket://" + host + ":" + policyPort);
                debugMsg += "\nPossibly accepted it?";
                connect();

                game = new Game(this);
               
                stage.addEventListener(Event.ENTER_FRAME, update);
            }
           
            public function update(event:Event):void
            {
                userCountText.text = "Users: " + userCount;
                ballsnum.text = "Balls: " + Ball.Balls.length;
               
                if(!loaded && socket.connected)
                {
                    sendMessage("CLIENT|" + Client.tempID + "|CONNECT|" + color + "|");
                    loaded=true;
                }
               
                if(debugMsg!=lastDebugMsg)
                {
                    if(debug.text.length>200)
                    {
                        debug.text = "Debug: ";
                        lastDebugMsg = "";
                    }
                    debug.appendText(debugMsg);
                    debugMsg = "";
                }
            }
           
            public function sendMessage(msg:String):void {
                msg += "\n";
    //          debugMsg = "\nSent:" + msg;
               
                try {
                    this.socket.writeUTFBytes(msg);
                    this.socket.flush();
                    trace("Message sent: " + msg);
                }
                catch(e:Error) {
                    trace("Error sending data: " + e);
                }
            }
           
            private function receiveData(msg:String):void
            {
    //          debugMsg += "Recieved: " + msg;
                trace(msg);
               
                if(!(getArgs(msg,3).match("MOVE") || getArgs(msg,3).match("BALL"))) trace(msg);
               
                var length:int = CountArgs(msg,"\n");

                for(var i:int=1; i<=length; i++)
                {
                    if(getArgs(msg,3).match("BALL"))
                    {
                        var ID:int = int(getArgs(msg,2));
                        var x:Number = Number(getArgs(msg,4));
                        var y:Number = Number(getArgs(msg,5));
                        var dx:Number = Number(getArgs(msg,6));
                        var dy:Number = Number(getArgs(msg,7));
                        var color:uint = uint(getArgs(msg,8));
                       
                        if(ID==tempID && Game.pBall==null)
                        {
                            trace(color);
                            game.addBall(x,y,dx,dx,tempID,color,true);
                        }
                        else if(ID!=tempID)
                        {
                            if(game.findBall(ID)==null) game.addBall(x,y,dx,dy,ID,color,false);
                        }
                    }
                    else if(getArgs(msg,3).match("MOVE") && int(getArgs(msg,2))!=tempID)
                    {
                        var ID:int = int(getArgs(msg,2));
                        var x:Number = Number(getArgs(msg,4));
                        var y:Number = Number(getArgs(msg,5));
                        var dx:Number = Number(getArgs(msg,6));
                        var dy:Number = Number(getArgs(msg,7));
                       
                        game.moveBall(ID,x,y,dx,dy);
                    }
                    else if(getArgs(msg,2).match("USERCOUNT"))
                    {
                        userCount = int(getArgs(msg,3));
                    }
                    else if(getArgs(msg,2).match("REMOVE"))
                    {
                        game.removeBall(int(getArgs(msg,3)));
                    }

                    msg = msg.substring(msg.indexOf("\n")+1,msg.length);
                }
            }
           
            public function CountArgs(input:String, split:String):int
            {
                var s:String = input;
                var a:int = 0;
               
                if(input.indexOf(split)>0)
                {
                    for(var i:int=0; i<input.length; i++)
                    {
                        if(s.indexOf(split)>0)
                        {
                            s = s.substring(s.indexOf(split)+1, s.length);
                            a++;
                        }
                        else
                        {
                            i=input.length;
                        }
                    }
                }
                else if(input.length>0)
                {
                    a+=1;
                }
                return a;
            }
           
            public function getArgs(input:String, arg:int):String
            {
                var s:String = input;
                var a:int = 0;
               
                if(input.indexOf("|"))
                {
                    for(var i:int=0; i<input.length; i++)
                    {
                        if(s.indexOf("|") && a+1<arg)
                        {
                            s = s.substring(s.indexOf("|")+1, s.length);
                            a++;
                        }
                        else
                        {
                            i=input.length;
                        }
                    }
                    if(s.indexOf("|"))
                    {
                        s = s.substring(0, s.indexOf("|"));
                    }
                }
                else
                {
                    s="not found";
                }
               
                return s;
            }
           
            public function connect():Boolean {
                this.socket = new Socket(this.host, this.port);
                this.socket.addEventListener(Event.CONNECT, socketConnect);
                this.socket.addEventListener(Event.CLOSE, socketClose);
                this.socket.addEventListener(IOErrorEvent.IO_ERROR, socketError);
                this.socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityError);
                this.socket.addEventListener(ProgressEvent.SOCKET_DATA, socketData);
               
                try {
                    this.socket.connect(this.host, this.port);
                }
                catch (e:Error) {
                    trace("Error on connect: " + e);
                    debugMsg += "\nError on connect";
                   
                    return false;
                }
                return true;
            }
           
            private function socketConnect(event:Event):void {
                trace("Connected: " + event);
            }
           
            private function socketData(event:ProgressEvent):void {
                // trace("Receiving data: " + event);
                receiveData(this.socket.readUTFBytes(this.socket.bytesAvailable));
            }
           
            private function socketClose(event:Event):void {
                trace("Connection closed: " + event);
                //this.chatArea.appendText("Connection lost." + "\n");
            }
           
            private function socketError(event:IOErrorEvent):void {
                trace("Socket error: " + event);
                debugMsg = "\nSocket error" + debugMsg;
            }
           
            private function securityError(event:SecurityErrorEvent):void {
                trace("Security error: " + event);
            }
        }
    }

    Game.as
    Actionscript Code:
    package
    {
        import flash.display.Sprite;
        import flash.events.Event;
        import flash.events.KeyboardEvent;
        import flash.events.MouseEvent;
        import flash.events.TimerEvent;
        import flash.ui.Keyboard;
        import flash.ui.Mouse;
        import flash.ui.MouseCursor;
        import flash.utils.Timer;
       
        public class Game
        {
            public var container:Sprite;
           
            public var left:int = 0;
            public var right:int = 0;
            public var up:int = 0;
            public var down:int = 0;
           
            public var currentSpeed:int=4;
           
            public var PlayerTimer:Timer = new Timer(20);
            public var timeTrack:int = 0;
            public var timeDelay:Number = 0.5;
           
            public var moving:Boolean = false;
           
            public static var pBall:Ball; // player ball
           
            public function Game(container:Sprite)
            {
                this.container = container;
               

                PlayerTimer.addEventListener(TimerEvent.TIMER, inc);
                PlayerTimer.start();
               
                container.stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDown);
                container.stage.addEventListener(KeyboardEvent.KEY_UP, keyUp);
                container.stage.addEventListener(Event.ENTER_FRAME, update);
            }

            public function inc(event:TimerEvent):void
            {
                timeTrack++;
            }
           
            public function update(event:Event):void
            {
                if(pBall!=null)
                {
                    if (left>0 && right==0) pBall.dx = -currentSpeed;
                    else if (right>0 && left==0) pBall.dx = currentSpeed;
                    else if (left>0 && right>0)
                    {
                        if(left>right) pBall.dx = -currentSpeed;
                        else pBall.dx = currentSpeed;
                    }
                    else pBall.dx = 0;
                   
                    if (up>0 && down==0) pBall.dy = -currentSpeed;
                    else if (down>0 && up==0) pBall.dy = currentSpeed;
                    else if (down>0 && up>0)
                    {
                        if(up>down) pBall.dy = -currentSpeed;
                        else pBall.dy = currentSpeed;
                    }
                    else pBall.dy = 0;
                   
                    if((pBall.dx!=0 || pBall.dy!=0) && timeTrack%timeDelay==0)
                    {
                        Client.main.sendMessage("CLIENT|"+Client.tempID+"|MOVE|"+pBall.x+"|"+pBall.y+"|"+pBall.dx+"|"+pBall.dy);
                        moving = true;
                    }
                    else if(moving && pBall.dx==0 && pBall.dy==0)
                    {
                        Client.main.sendMessage("CLIENT|"+Client.tempID+"|MOVE|"+pBall.x+"|"+pBall.y+"|"+pBall.dx+"|"+pBall.dy);
                        moving = false;
                    }
                }
            }
           
            public function keyDown(event:KeyboardEvent):void
            {
                if (event.keyCode == 65)
                {
                    left = timeTrack;
                }
                else if (event.keyCode == 68)
                {
                    right = timeTrack;
                }
                else if (event.keyCode == 87)
                {
                    up = timeTrack;
                }
                else if (event.keyCode == 83)
                {
                    down = timeTrack;
                }
            }
           
            public function keyUp(event:KeyboardEvent):void
            {
                if (event.keyCode == 65)
                {
                    left = 0;
                }
                else if (event.keyCode == 68)
                {
                    right = 0;
                }
                else if (event.keyCode == 87)
                {
                    up = 0;
                }
                else if (event.keyCode == 83)
                {
                    down = 0;
                }
            }
           
            public function moveBall(id:int, x:Number, y:Number, dx:Number, dy:Number):void
            {
                var b:Ball;
               
                if(Ball.Balls.length>0)
                {
                    b = findBall(id);
                   
                    b.x = x;
                    b.y = y;
                    b.dx = dx;
                    b.dy = dy;             
                }
            }
           
            public function findBall(id:int):Ball
            {
                var r:Ball;
               
                for each(var b:Ball in Ball.Balls)
                {
                    if(b.id == id)
                    {
                        r = b;
                    }
                }
                return r;
            }
           
            public function removeBall(id:int):void
            {
                var b:Ball;
                b = findBall(id);
                if(b!=null) b.die();
            }
           
            public function addBall(x:Number, y:Number, dx:Number, dy:Number, id:int, color:uint=0x000000, player:Boolean=false):void
            {
                if(player)
                {
                    container.stage.addChild(pBall = new Ball(x,y,id,color,dx,dy));
                    pBall.iAmPlayer();
                }
                else container.stage.addChild(new Ball(x,y,id,color,dx,dy));
            }
           
            public function CountArgs(input:String):int
            {
                var s:String = input;
                var a:int = 0;
               
                if(input.indexOf("|")>0)
                {
                    for(var i:int=0; i<input.length; i++)
                    {
                        if(s.indexOf("|")>0)
                        {
                            s = s.substring(s.indexOf("|")+1, s.length);
                            a++;
                        }
                        else
                        {
                            i=input.length;
                        }
                    }
                }
                else if(input.length>0)
                {
                    a+=1;
                }
                return a;
            }
           
            public function getArgs(input:String, arg:int):String
            {
                var s:String = input;
                var a:int = 0;
               
                if(input.indexOf("|"))
                {
                    for(var i:int=0; i<input.length; i++)
                    {
                        if(s.indexOf("|") && a+1<arg)
                        {
                            s = s.substring(s.indexOf("|")+1, s.length);
                            a++;
                        }
                        else
                        {
                            i=input.length;
                        }
                    }
                    if(s.indexOf("|"))
                    {
                        s = s.substring(0, s.indexOf("|"));
                    }
                }
                else
                {
                    s="not found";
                }
               
                return s;
            }
           
            public function Debug(s:String):void
            {
                Client.debugMsg += "\n"+s;
            }      
        }
    }

    Ball.as
    Actionscript Code:
    package
    {
        import flash.display.Sprite;
        import flash.events.Event;
       
        public class Ball extends Mover
        {
           
            public var sprite:Sprite;
            public static var Balls:Array = new Array();
            public var id:int;
            public var radius:int=10;
            public var color:uint;
           
            public function Ball(x:Number, y:Number, id:int, color:uint, dx:Number=0, dy:Number=0)
            {
                super(x, y, dx, dy);

                this.id = id;
                this.x = x;
                this.y = y;
                this.dx = dx;
                this.dy = dy;
                this.color = color;
               
                trace("New ball at " + this.x + ", " + this.y + ", with an ID of " + id);
               
                graphics.beginFill(color);
                graphics.drawCircle(0, 0, radius);
                graphics.endFill();
               
                Balls.push(this);
            }
           
            public function iAmPlayer():void
            {
                graphics.beginFill(0x000000);
                graphics.drawCircle(0, 0, radius/1.25);
                graphics.beginFill(0xFFFFFF);
                graphics.drawCircle(0, 0, radius/1.5);
                graphics.beginFill(0x000000);
                graphics.drawCircle(0, 0, radius/2);
                graphics.beginFill(color);
                graphics.drawCircle(0, 0, radius/2.25);
                graphics.endFill();
            }
           
            public override function update(event:Event):Boolean
            {
                if (!super.update(event)) return false;

                return true;
            }
           
            public override function die():void
            {
                super.die();
               
                var i:int = Balls.indexOf(this);          
                Balls[i] = Balls[Balls.length - 1];
                Balls.pop();
            }
        }
    }

  12. #32
    Registered User
    Join Date
    Dec 2011
    Posts
    3
    Mover.as
    Actionscript Code:
    package
    {
        import flash.display.Sprite;
        import flash.events.Event;
       
        public class Mover extends Sprite
        {
            public var dx:Number = 0;
            public var dy:Number = 0;
            public var speed:Number = 2;
           
            public function Mover(x:Number, y:Number, dx:Number, dy:Number)
            {
                this.x = x;
                this.y = y;
                this.dx = dx;
                this.dy = dy;
               
                addEventListener(Event.ENTER_FRAME, update);
            }
           
            public function update(event:Event):Boolean
            {
                if(this.visible==true)
                {
                    x += dx*speed;     
                    y += dy*speed;
                }
               
                return true;
            }
           
            public function die():void
            {
                removeEventListener(Event.ENTER_FRAME, update);
                parent.removeChild(this);  
            }
        }
    }

    JAVA CODE FOR THE SERVER

    Server.java
    Code:
    /*
     * To change this template, choose Tools | Templates
     * and open the template in the editor.
     */
    package server;
    
    import java.net.*;
    import java.io.*;
    
    /**
     *
     * @author Admin
     */
    public class Server {
    
        /**
         * @param args the command line arguments
         */
        public static ServerSocket server = null;
        public static PolicyServer pServer;
        public static boolean listening = true;
        public static int port = 8090;
        public static final boolean DEBUG = true;
        
        public static void main(String[] args) throws IOException
        {
                try
                {
                    server = new ServerSocket(port);
                    pServer = new PolicyServer(port+1);
                }
                catch(Exception e)
                {
                    System.out.println("Error: " + e);
                }
                
                pServer.start();
                while(listening)
                {
                    
                    new ServerThread(server.accept()).start();
                }
                
                server.close();
        }
        
        public static void debug(String label, String msg)
        {
            if (DEBUG)
            {
                System.out.println(label + ": " + msg);
            }
        }
    }
    ServerThread.java
    Code:
    package server;
    
    import java.net.*;
    import java.io.*;
    
    /**
     *
     * @author Admin
     */
    public class ServerThread extends Thread
    {
        
        private Socket socket = null;
        public static final String POLICY_REQUEST = "<policy-file-request/>";
        public static final String POLICY_XML =
                "<?xml version=\"1.0\"?>"
                + "<cross-domain-policy>"
                + "<allow-access-from domain=\"*\" to-ports=\"*\" />"
                + "</cross-domain-policy>";
      
        protected int port;
        protected ServerSocket serverSocket;
        protected boolean listening;
        
        private static Node users = null;
        private static int userCount=0;
        private static GameProtocol gp;
        
        public ServerThread(Socket s)
        {
            super("ServerThread");
            this.socket = s;
            
            gp = new GameProtocol();
            addUser(s);
        }
        
        public static void addID(Socket s, int id)
        {
            Node c;
            c = findUser(s);
            
            c.setID(id);
        }
        
        public static Node findUser(Socket s)
        {
            Node c;
            c = users;
            
            while(c.getSocket()!=s && c!=null)
            {
                c = c.getRight();
            }
            
            return c;
        }
        
        public static void addUser(Socket s)
        {
            if(users==null || users.getSocket()==null)
            {
                users = new Node(s);
                userCount=1;
            }
            else
            {
                Node n = new Node(s);
                Node c = users;
                Node p = c;
                
                while(c.getRight()!=null)
                {
                    p = c;
                    c=c.getRight();
                }
                
                c.setRight(n);
                userCount++;
            }
    
            sendToAll("SERVER|USERCOUNT|"+userCount+"|");
        }
          
        public static void removeUser(Socket s)
        {
            if(users==null || users.getSocket()==null)
            {
                System.out.println("WARNING: No users to remove!");
                userCount=0;
            }
            else
            {
                Node c = users;
                Node p = c;
                
                // remove the player's ball as well
                gp.removeObjects(findUser(s).getID());
                sendToAll("SERVER|REMOVE|"+findUser(s).getID()+"|");
                
                while(c!=null && c.getSocket()!=s)
                {
                    p=c;
                    c=c.getRight();
                }
                
                if(c!=users)
                {
                    if(c.getRight()!=null)
                    {
                        p.setRight(c.getRight());
                    }
                    else
                    {
                        p.setRight(null);
                    }
                    userCount--;
                }
                else
                {
                    if(c.getRight()==null)
                    {
                        c.setSocket(null);
                        userCount=0;
                        System.out.println("All users disconnected!");
                    }
                    else
                    {
                        users = c.getRight();
                        userCount--;
                    }
                }
            }
            
            sendToAll("SERVER|USERCOUNT|"+userCount+"|");        
        }
        
        public static void sendToAll(String s)
        {
            if(s.contains("USERCOUNT")) System.out.print("There are " + userCount + " users\n");
            if(users==null || users.getSocket()==null)
            {
                System.out.println("WARNING: No users to send to!");
                userCount=0;
            }
            else
            {
                Node c = users;
                
                while(c!=null && c.getSocket()!=null)
                {
                    try
                    {
                        PrintWriter send = new PrintWriter(c.getSocket().getOutputStream(), true);
                        
                        if(countArgs(s,"~")>1)
                        {
                            for(int i=1; i<=countArgs(s,"~"); i++)
                            {
                                send.println(getLines(s,i));
                                send.flush();
                            }
                        }
                        else
                        {
                            send.println(s);
                            send.flush();
                        }
    
                    }
                    catch(Exception e)
                    {
                        System.out.println("This is not my problem: " + e);  
                    }
                    
                    c=c.getRight();
                }
            }
        }
        
        public static int countArgs(String input, String d)
        {
                String s = input;
                int a = 1;
    
                if(s.contains(d))
                {
                        for(int i=0; i<input.length(); i++)
                        {
                                if(s.contains(d))
                                {
                                        s = s.substring(s.indexOf(d)+1, s.length());
                                        a++;
                                }
                                else
                                {
                                        i=input.length();
                                }
                        }
                }
                else if(input.length()==0)
                {
                        a=0;
                }
                return a;
        }
        
        public static String getLines(String input, int arg)
        {
            String s = input;
            int a = 0;
    
            if(input.contains("~"))
            {
                for(int i=0; i<input.length(); i++)
                {
                    if(s.contains("~") && a+1<arg)
                    {
                        s = s.substring(s.indexOf("~")+1, s.length());
                        a++;
                    }
                    else
                    {
                        i=input.length();
                    }
                }
                if(s.contains("~"))
                {
                    s = s.substring(0, s.indexOf("~"));
                }
            }
            else
            {
                s="not found";
            }
            return s;
        }
        
        public void run() {
            try
            {
                Server.debug("ServerThread", "connected!");
                PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
                BufferedReader in = new BufferedReader(new InputStreamReader( socket.getInputStream()) );       
                String inputLine, outputLine;
              //  GameProtocol gp = new GameProtocol();
                outputLine = gp.processInput(null);
                out.println(outputLine);
                int i;
    
                while ((inputLine = in.readLine()) != null)
                {
                    if(!gp.getArgs(inputLine,3).equals("MOVE")) System.out.println("Input:" + inputLine);
                    if(gp.getArgs(inputLine,3).equals("CONNECT"))
                    {
                        addID(socket, Integer.parseInt(gp.getArgs(inputLine, 2)));
                    }
                    outputLine = gp.processInput(inputLine);
                    
                    sendToAll(outputLine);
    
                    if (outputLine.equals("PLEASESTOP"))
                        break;
                    
                    
                }
                
                Server.debug("ServerThread", "disconnected!");
                removeUser(socket);
                out.close();
                in.close();
                socket.close();
            }
            catch (IOException e) 
            {
                System.out.println("Error on readline");
                e.printStackTrace();
                removeUser(socket);
            }
        }
    }
    GameProtocol.java
    Code:
    /*
     * To change this template, choose Tools | Templates
     * and open the template in the editor.
     */
    package server;
    
    import java.net.*;
    import java.io.*;
    
    /**
     *
     * @author Admin
     */
    public class GameProtocol
    {    
        
        public static Node objects=null;
        
        public String processInput(String input)
        {
            // WHO|ID|WHAT|INFO|...
            // CLIENT|1023|CONNECT|TIMESTAMP
            // CLIENT|1023|MOVE|X|Y|DX|DY|...        
            String r="Server: GP called. New connection, get!";
    
            if(input!=null)
            {
                String WHO = getArgs(input,1);
                String ID = getArgs(input,2);
                String WHAT = getArgs(input,3);
            
                if(WHAT.equals("CONNECT"))
                {
                    double x =  Math.random()*800+50;
                    double y =  Math.random()*600+50;
                    double dx = 0;
                    double dy = 0;
                    
                    addObjects(Integer.parseInt(ID), "BALL", x, y, dx, dy, getArgs(input,4));
                    r="SERVER|"+ID+"|BALL|"+x+"|"+y+"|"+dx+"|"+dy+"|"+getArgs(input,4)+"|";
                    r+=getObjects();
                }
                else if(WHAT.equals("MOVE"))
                {
                    double x = Double.parseDouble(getArgs(input,4));
                    double y = Double.parseDouble(getArgs(input,5));
                    double dx = Double.parseDouble(getArgs(input,6));
                    double dy = Double.parseDouble(getArgs(input,7));
                    
                    moveBall(Integer.parseInt(ID), x, y, dx, dy);
                    
                    r = "SERVER|"+ID+"|MOVE|"+x+"|"+y+"|"+dx+"|"+dy+"|";
                }
            }
            else
            {
                r="Server: unknown non-null message recieved.";
            }
            
            return r;
        }
        
        public void moveBall(int ID, double x, double y, double dx, double dy)
        {
            Node c = findObject(ID);
            c.setX(x);
            c.setY(y);
            c.setDx(dx);
            c.setDy(dy);
        }
        
        public Node findObject(int ID)
        {
            Node c;
            c = objects;
            
            while(c.getID()!=ID && c!=null)
            {
                c=c.getRight();
            }
            
            return c;
        }
        
        public String getObjects()
        {
            String s="";
            Node c;
            c = objects;
            
            while(c!=null)
            {
                s+="~SERVER|"+c.getID()+"|BALL|"+c.getX()+"|"+c.getY()+"|"+c.getDx()+"|"+c.getDy()+"|"+c.getColor()+"|";
                c=c.getRight();
            }
            
            return s;
        }
        
        public void removeObjects(int id)
        {
            Node n = objects;
            Node p = n;
            
            if(n==null)
            {
                System.out.println("no objects to remove!");
            }
            else
            {
                if(n.getID()==id)
                {
                    if(n.getRight()==null)
                    {
                        objects = null;
                    }
                    else
                    {
                        objects = n.getRight();
                    }
                }
                else
                {
                    while(n.getID()!=id && n != null)
                    {
                        p = n;
                        n = n.getRight();
                    }
                    
                    if(n.getRight()!=null)
                    {
                        p.setRight(n.getRight());
                    }
                    else
                    {
                        p.setRight(null);
                    }
                }
            }
        }
        
        public void addObjects(int id, String what, double x, double y, double dx, double dy, String color)
        {
            int i=0;
            
            if(objects==null)
            {
                objects = new Node(id, what, x, y, dx, dy, color);
            }
            else
            {
                Node n = new Node(id, what, x, y, dx, dy, color);
                Node c = objects;
                Node p = c;
                
                while(c.getRight()!=null)
                {
                    p = c;
                    c=c.getRight();
                    i++;
                }
                
                c.setRight(n);
            }
        }
    
        public String getArgs(String input, int arg)
        {
            String s = input;
            int a = 0;
    
            if(input.contains("|"))
            {
                for(int i=0; i<input.length(); i++)
                {
                    if(s.contains("|") && a+1<arg)
                    {
                        s = s.substring(s.indexOf("|")+1, s.length());
                        a++;
                    }
                    else
                    {
                        i=input.length();
                    }
                }
                if(s.contains("|"))
                {
                    s = s.substring(0, s.indexOf("|"));
                }
            }
            else
            {
                s="not found";
            }
            return s;
        }
    }

  13. #33
    Registered User
    Join Date
    Dec 2011
    Posts
    3
    Node.java
    Code:
    /*
     * To change this template, choose Tools | Templates
     * and open the template in the editor.
     */
    package server;
    
    import java.net.Socket;
    
    /**
     *
     * @author Admin
     */
    public class Node {
        
        public Node right;
        public Object data;
        public Socket socket;
        public double x,y,dx,dy;
        public int ID;
        public String who,what,color;
        
        public Node(Object d)
        {
            setData(d);
        }
        
        // for users
        public Node(Socket s)
        {
            setSocket(s);
        }
        
        // for static objects
        public Node(Object d, double x, double y)
        {
            setData(d);
            setX(x);
            setY(y);
        }
        
        // for all objects in the world
        public Node(int id, String what, double x, double y, double dx, double dy, String color)
        {
            setWho(who);
            setID(id);
            setWhat(what);
            setX(x);
            setY(y);
            setDx(dx);
            setDy(dy);
            setColor(color);
        }
        
        public void setDx(double dx)
        {
            this.dx = dx;
        }
        
        public double getDx()
        {
            return dx;
        }
        
        public void setDy(double dy)
        {
            this.dy = dy;
        }
        
        public double getDy()
        {
            return dy;
        }
        
        public void setID(int i)
        {
            ID = i;
        }
        
        public int getID()
        {
            return ID;
        }
        
        public void setWho(String s)
        {
            who = s;
        }    
        public String getWho()
        {
            return who;
        }
        
        public void setColor(String s)
        {
            color = s;
        }
        
        public String getColor()
        {
            return color;
        }
        
        public void setWhat(String s)
        {
            what = s;
        }
        
        public String getWhat()
        {
            return what;
        }
        
        public void setSocket(Socket s)
        {
            socket = s;
        }
        
        public Socket getSocket()
        {
            return socket;
        }
        
        public void setData(Object d)
        {
            data = d;
        }
        
        public Object getData()
        {
            return data;
        }
        
        public void setX(double x)
        {
            this.x = x;
        }
        
        public void setY(double y)
        {
            this.y = y;
        }
        
        public double getX()
        {
            return x;
        }
        
        public double getY()
        {
            return y;
        }
    
        public Node getRight()
        {
            return right;
        }
    
        public void setRight(Node n)
        {
            right = n;
        }
    }
    THAT WAS ALL OF THE CODE

    Some extra notes:

    The way I send information between the flash clients and the java server is terrible. But it works.

    The game doesn't do anything. There isn't a game. It's just a relatively simple way to get the two things talking together.

    In order to get other people to connect, in the flash Client.as, you need to change private var host:String="192.168.1.2"; to be your own external IP address. 192.168.1.2 is a local address. Go here to see what your current external IP address is.

    You will need to forward the port 8090 from your router. Look up "port forwarding" on google if you don't know what that is. Please do not break your router, or forward any more ports than you have to.

    And finally, I'm aware I am bumping this thread. I apologise to the moderators of this board for doing so. I might post this code on my website, and eventually it might overtake this forum, but until then this may be the best method to give code to anyone who is the type to learn by seeing how it's done, as opposed to making your own solutions.

    To anyone who does use this code - type it out yourself. Copy / pasting is the single worst habit you will ever have while learning to code. That's coming from a guy who maybe has five comments in my entire program, and three of those were automatically generated by my compiler.

    Here's some ****ing clowns.


    what do you mean I could have used pastebin?

    I'm also sorry to the moderator who has to approve these messages.
    I will not return to this forum to comment on replies or offer help, unless I am especially bored.

  14. #34
    Senior Member
    Join Date
    May 2005
    Posts
    223
    t1ger are you being sarcastic?

  15. #35
    Junior Member
    Join Date
    Feb 2012
    Posts
    1
    Quote Originally Posted by imjoedaddy View Post
    t1ger are you being sarcastic?
    (Are you seriously trying to ask a question to someone from four years ago?)

    My thanks goes out to Kritz. I've gotten pretty good with flash code but I knew nothing about making interaction between multiple workstations.

    If this could be stickied or something I think it would help many more.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  




Click Here to Expand Forum to Full Width

HTML5 Development Center