jeudi 18 février 2016

ue4 : AI in a space game : relative coordinate : part 1

I will make some articles about AI I am building.
I will not use for the moment, tooling set in ue, because I will not have change of behaviour (attack, defense, patrol).
I will for the moment make only one behaviour, and one goal to reach, without modification depending of the situation of the AI.

My goal is to put in space 2 cubes, and to spawn an AI pawn controlled by an AI controller.
The AI will retrieve first cube, and will fly to this one. It will shoot at it, destroy it, next it will change of target, and fire on the second one.

I ve created a pawn, with a static mesh, with physic enabled.
Don't forget to precise that the pawn is possessed by your specific AIController blueprint:





For my purpose, one of the central need I have, it to be able to orient my pawn to my target.

In AIController,  I ve defined a variable TargetToGo
and create a function to associate a value to the target


I retrieve all object in the scene which are from class gopoint (my cubes, there are two of them). If actual targetToGo is different of the one retrieve in foreach loop, I affect it, and break the loop.
Quite simple.

Ok, for now, I have a target for my pawn... The difficulty is to know how to orient my ship to the target, to move near it, and shoot at it.

Ue4 gives possibilities through transformation tools, to make world location, in local location relative to the ship.

From my pawn, and target, I retrieve static mesh.
From AI ship, I create a transform object (world transform) and I connect it to an inverse transform location object. This last one is the way to make world location into relative location (transform location does the inverse, relative to world).
In parameter, you give actual world location of the target, and you will have a vector in output.




Now, if you break the vector, y which is a left/right coordinate, and z a up/down coordinate. When z and y are at 0, target must be in front of you.
X value in case of y and z at 0 will be the distance to the target.
X can give you clue, if your spaceship is going to, or going away of. If x is equal to - (distance), you are going away from the target.

You have to make rotation, to make x near from distance, and then re apply torque to reduce y and z to 0





dimanche 14 février 2016

Third Party server with UE4 : part 4 : C++ : thread

UE brings you what you need to thread your program.

class POCSHIM_API UShimServer : public FRunnable

just extend the interface FRunnable, you will have to implement
    virtual bool Init();
    virtual uint32 Run();
    virtual void Stop();

Run will be the function which will be threaded, so you can put a while (1), with a break condition, mutex, and so on into.

I ve created a singleton in shimserver

in shimserver.h:
static UShimServer* getInstance();

static UShimServer *instance;


in shimserver.cpp
UShimServer*  UShimServer::getInstance() {
    if (!UShimServer::instance) {
        UShimServer::instance = new UShimServer();
    }
    return UShimServer::instance;
}

UShimServer* UShimServer::instance = nullptr;


In myGameInstance class, I ve created an intialize function, which retrieve the singleton of shimserver, and from it create and launch the thread.
once you create the thread, it will run automatically init on instance, and run().

Third Party server with UE4 : part 3 : C++ : connect and read socket

I ve created mainly two functions, one to connect, one other to read socket


I think it is quite easy to understand, and easy to modify to what you need, because apart port and ip, you don't have to modify lot of thing :D.

this->connected, is a variable to store connection status, you can use in a function like isConnected :D


This function will read the socket, retrieve the data in receivedData.
In my case, I will deserialize data from string to json, and I will store the message into a customize class, which will store all message.

This function is called each tick, because I have not lot of information send into these socket.
If you prefer to thread it, you can





Third Party server with UE4 : part 2 : C++ : include package

For now, we need C++ code.
I will not explain how ue manage class, path to includes, and so on. All is not very clear for me.
It seems that when you need to use "package", you have to include it in your build.cs.

Here it is a screenshot of filetree on my computer, of the engine source. In red the non exhaustive list of package under source/runtime.

We will need socket package, and networking, so in my build.cs

using UnrealBuildTool;

public class pocshim : ModuleRules
{
    public pocshim(TargetInfo Target)
    {
        PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore","Blu", "Networking", "Sockets","Json" });

    }
}






Third Party server with UE4 : part 1 : nodejs

I have discovered that ue4 is very good for certain purpose, but not good for others.
One of the point is that if you want to manage persistance, or if you want to have information you can dispatch to all players, you need to use a third party server for this (for chat purpose too for example, because you must know all players who are playing to the game).

I ve found piece of code to write a nodejs server. For the moment, it is the easiest way (if you know javascript of course) to write an external third party server. It is light, easy to write, and enough for my purpose.
This server will:
-- receive connection
-- receive TCP message
   -- receive login message
       -- check if the login/password are ok in database
       -- send a json to the sender by TCP message



var net = require('net');
var mysql = require('mysql');

var mySqlClient = mysql.createConnection({
  host     : "*****",
  user     : "****",
  password : "********",
  database : "*******"
});


// Keep track of the chat clients
var clients = [];

// Start a TCP Server
net.createServer(function (socket) {
   
  // Identify this client
  socket.name = socket.remoteAddress + ":" + socket.remotePort

  // Put this new client in the list
  clients.push(socket);

  // Send a nice welcome message and announce
  //~ socket.write("Welcome " + socket.name + "\n");
  broadcast(socket.name + " joined the chat\n", socket);

  // Handle incoming messages from clients.
  socket.on('data', function (data) {
    //broadcast(socket.name + "> " + data, socket);
      try{
        var val = JSON.parse(data);
        if (val.code == "1"){
            login(socket,val);
        }
      }catch(err){
            console.log("data received not in JSON format : "  + data  + "/////" + err);
      }
  });
    socket.on('error',function(){
        console.log('socket reset');
        clients.splice(clients.indexOf(socket), 1);
    });
  // Remove the client from the list when it leaves
  socket.on('end', function () {
    clients.splice(clients.indexOf(socket), 1);
    broadcast(socket.name + " left the chat.\n");
  });
 
  function login(sender,jsonObj){
      //~ console.log(jsonObj);
      var selectQuery = "SELECT * FROM table where name ='" + jsonObj.login + "' and passwd = '" + jsonObj.password +"'";
       var status=0;
        var sqlQuery = mySqlClient.query(selectQuery);
        sqlQuery.on("result", function(row) {

          status=1;
        });
       
        sqlQuery.on("end", function() {
            //~ if (status){
          //~ mySqlClient.end();
            //~ }
          sender.write('{"code":"1","status":"' + status + '"}');
        });
       
        sqlQuery.on("error", function(error) {
          console.log(error);
            sender.write('{"code":"1","status":"-1"}');
        });

  }
 
  // Send a message to all clients
  function broadcast(message, sender) {
    clients.forEach(function (client) {
      // Don't want to send it to sender
      if (client === sender) return;
      client.write(message);
    });
    // Log it to the server output too
    process.stdout.write(message)
  }

}).listen(5000);

// Put a friendly message on the terminal of the server.
console.log("Chat server running at port 5000\n");