SKOQ – Some Kind of Quest

This game project is a much simpler distillation of many ideas I’ve had over the years. The marching cubes and voxel engines i’ve messed about with have been a great deal of fun but some of the math involved is out of my league and i find myself eventually hitting walls which stall the project.

With this i’ve decided to try and simplify things to a degree.

I’ve taking inspiration from games like Ultima IV and board games like Talisman and Dungeon.

Initially i used the scripting and development platform in the virtual world SecondLife to build a prototype. SL uses a script language similar to C# called LSL, so some of the noise scripts i used for pseudo random terrain generation were translatable. The prototype worked well, though it was a challenge, an admittedly enjoyable one to work within the constraints.

SKOQ prototype made in Secondlife
The SKOQ prototype made in SL

Bringing this into Unity was very straightforward. Unity has all the tools you need and working with GameObjects made everything pretty simple (so far).

It’s still not at the point where it has the features of the Prototype but the basics are here and i now have a chance to throw a bit more at it given the additional power of unity, custom shaders and mobile platform support.

Chunk Class for Unity Voxel Engine (Example)

Here’s an example of a Chunk class i use in some variants of the engine. This one is a bit experimental but working OK so far.

chunk

 

using UnityEngine;
using System.Collections.Generic;

public enum ChunkState:int {
    Invalid = 0,
    Base = 1,
    Terra = 10,
    ReGen = 11,
    Light = 15,
    Post_Light = 16,
    Mesh = 20,
    Render = 30   

}
public class LightSource {

    public Lux light;
    public int x;
    public int y;
    public int z;
}

public class Chunk {

    //render mesh data
    public List<int> triangles;
    public List<int>[] subtriangles;
    public List<Vector2> uvs;
    public List<Vector3> vertices;
    public List<Color> colours;
    public List<Vector3> normals;
    public List<Vector4> tangents;
    public List<Lux> lightsources;
    public List<IntVect> sunlitBlocks;

    //collision mesh data
    public List<int> col_triangles;
    public List<Vector3> col_vertices;



    //chunk world position
    public int x;
    public int y;
    public int z;

    public GameObject chunkObject;
    public ChunkState state;

 

    public bool AboveReady(ChunkState s) {
      
        if (y == World.yChunkRadius - 1) { return true; }

        int ts = (int)s;
        int cs = (int)World.GetChunkState(x, y + 1, z);

        if (cs == 0) { return true; }
        if (cs >= ts) { return true; }
        return false;
    }

    public bool SurroundingState(ChunkState cstate)
    {
        ChunkState north = World.GetChunkState(x, y, z + 1);
        if ((int)north < (int)cstate && north != ChunkState.Invalid) { return false; }

        ChunkState south = World.GetChunkState(x, y, z - 1);
        if ((int)south < (int)cstate && south != ChunkState.Invalid) { return false; }

        ChunkState east = World.GetChunkState(x + 1, y, z);
        if ((int)east < (int)cstate && east != ChunkState.Invalid) { return false; }

        ChunkState west = World.GetChunkState(x - 1, y, z);
        if ((int)west < (int)cstate && west != ChunkState.Invalid) { return false; }
        if (!AboveReady(cstate)) { return false; }

        /*
        ChunkState stack;
        for (int i = 0; i < World.yChunkRadius; i++)
        {
            stack = World.GetChunkState(x, i, z);
            if ((int)stack < (int)cstate && stack != ChunkState.Invalid) { return false; }
        }
        */


        return true;
    }

    public void Init(int _x, int _y, int _z)
    {
        x = _x; y = _y; z = _z;
        state = ChunkState.Base;

    }
    public void ReBuild() {
        sunlitBlocks = new List<IntVect>();
        col_vertices = new List<Vector3>();
        col_triangles = new List<int>();
        vertices = new List<Vector3>();
        triangles = new List<int>();
        uvs = new List<Vector2>();
        colours = new List<Color>();
        normals = new List<Vector3>();
        tangents = new List<Vector4>();

        subtriangles = new List<int>[Mats.matCount];
        for (int n = 0; n < Mats.matCount; n++) { subtriangles[n] = new List<int>(); }

    }





}

Creating a grid mesh programmatically in Unity 3D

using System;
using System.Collections.Generic;
using UnityEngine;

public static class Grid
{

    public static void Create(bool withCollision)
    {
        GameObject gridObject = new GameObject();
        gridObject.name = "Grid";
        gridObject.transform.position = Vector3.zero;

        List<int> triangles = new List<int>();
        List<Vector3> vertices = new List<Vector3>();
        List<Vector2> uvs = new List<Vector2>();

        List<int> collision_triangles = new List<int>();
        List<Vector3> collision_vertices = new List<Vector3>();

        int vertexIndex = 0;
        int collisionVertexIndex = 0;

        int count = 64; // n+1 grid lines (n = even number)
        int n = count / 2; // halve count for +/- iteration

        float w = 0.05f; //line width
        float s = 1.0f; //width of space

        Vector3 v1;
        Vector3 v2;
        Vector3 v3;
        Vector3 v4;


        //Collision mesh

        if (withCollision)
        {
            v1 = new Vector3(-n, 0, -n);
            v2 = new Vector3(-n, 0, n);
            v3 = new Vector3(n, 0, n);
            v4 = new Vector3(n, 0, -n);

            collision_vertices.Add(v1);
            collision_vertices.Add(v2);
            collision_vertices.Add(v3);
            collision_vertices.Add(v4);

            collision_triangles.Add(collisionVertexIndex);
            collision_triangles.Add((collisionVertexIndex + 1));
            collision_triangles.Add((collisionVertexIndex + 2));
            collision_triangles.Add((collisionVertexIndex + 2));
            collision_triangles.Add((collisionVertexIndex + 3));
            collision_triangles.Add(collisionVertexIndex);

        }


        //Grid mesh
        for (int x = -n; x < n + 1; x++)
        {

            v1 = new Vector3((x * s), 0, -n);
            v2 = new Vector3((x * s), 0, n);
            v3 = new Vector3((x * s) + w, 0, n);
            v4 = new Vector3((x * s) + w, 0, -n);

            vertexIndex = vertices.Count;

            vertices.Add(v1);
            vertices.Add(v2);
            vertices.Add(v3);
            vertices.Add(v4);

            triangles.Add(vertexIndex);
            triangles.Add((vertexIndex + 1));
            triangles.Add((vertexIndex + 2));
            triangles.Add((vertexIndex + 2));
            triangles.Add((vertexIndex + 3));
            triangles.Add(vertexIndex);

            uvs.AddRange(Mats.Generic);

            //back face
            vertexIndex = vertices.Count;

            vertices.Add(v4);
            vertices.Add(v3);
            vertices.Add(v2);
            vertices.Add(v1);

            triangles.Add(vertexIndex);
            triangles.Add((vertexIndex + 1));
            triangles.Add((vertexIndex + 2));
            triangles.Add((vertexIndex + 2));
            triangles.Add((vertexIndex + 3));
            triangles.Add(vertexIndex);

            uvs.AddRange(Mats.Generic);

        }


        for (int z = -n; z < n + 1; z++)
        {

            v1 = new Vector3(-n, 0, (z * s));
            v2 = new Vector3(n, 0, (z * s));
            v3 = new Vector3(n, 0, (z * s) + w);
            v4 = new Vector3(-n, 0, (z * s) + w);

            vertexIndex = vertices.Count;

            vertices.Add(v1);
            vertices.Add(v2);
            vertices.Add(v3);
            vertices.Add(v4);

            triangles.Add(vertexIndex);
            triangles.Add((vertexIndex + 1));
            triangles.Add((vertexIndex + 2));
            triangles.Add((vertexIndex + 2));
            triangles.Add((vertexIndex + 3));
            triangles.Add(vertexIndex);

            uvs.AddRange(Mats.Generic);

            //back face
            vertexIndex = vertices.Count;

            vertices.Add(v4);
            vertices.Add(v3);
            vertices.Add(v2);
            vertices.Add(v1);

            triangles.Add(vertexIndex);
            triangles.Add((vertexIndex + 1));
            triangles.Add((vertexIndex + 2));
            triangles.Add((vertexIndex + 2));
            triangles.Add((vertexIndex + 3));
            triangles.Add(vertexIndex);

            uvs.AddRange(Mats.Generic);

        }

        Mesh mesh = new Mesh();
        mesh.vertices = vertices.ToArray();
        mesh.triangles = triangles.ToArray();
        mesh.uv = uvs.ToArray();

        mesh.RecalculateNormals();
        mesh.Optimize();

        MeshFilter meshFilter = gridObject.AddComponent<MeshFilter>();
        MeshRenderer meshRenderer = gridObject.AddComponent<MeshRenderer>();

        if (withCollision)
        {
            MeshCollider meshCollider = gridObject.AddComponent<MeshCollider>();
            Mesh collision_mesh = new Mesh();
            collision_mesh.vertices = collision_vertices.ToArray();
            collision_mesh.triangles = collision_triangles.ToArray();
            meshCollider.sharedMesh = collision_mesh;
        }

        meshRenderer.material = Mats.Grid();
        meshFilter.sharedMesh = mesh;

    }

}

Accessing strings in c++ from c#

Scenario; You may have some c++ code you wish to output string data to be used in a c# application.

#include <stdio.h>
#include <string.h>

extern "C"
{
	__declspec(dllexport) int GetString(char* buf,int n)
	{
		strncpy(buf,"my string in cpp", n);
		return 0;
	}
}
using System.Runtime.InteropServices;

[DllImport("mycppdll.dll", CallingConvention = CallingConvention.Cdecl)]
static extern int GetString(StringBuilder buffer, int capacity);

void csharp(){
StringBuilder sb = new StringBuilder(1000);
GetString(sb, sb.Capacity);
string mycppstring = sb.toString();
}

SQL to JSON with C#

This seems to work quite well. If there is a more efficient way please let me know.

string SQLtoJSON(string _sqlCon, string _sqlQuery) 
{
 using (SqlConnection con = new SqlConnection(_sqlCon))
 {
 using (SqlCommand cmd = new SqlCommand(_sqlQuery, con))
 {
 using (SqlDataAdapter adapter = new SqlDataAdapter(cmd))
 {

 DataTable sqlData = new DataTable();
 adapter.Fill(sqlData); 

System.Web.Script.Serialization.JavaScriptSerializer serializer = new System.Web.Script.Serialization.JavaScriptSerializer();
 List<Dictionary<string, object>> rows = new List<Dictionary<string, object>>(); 
Dictionary<string, object> row;

 foreach (DataRow dr in sqlData.Rows) 
{ 
row = new Dictionary<string, object>();
 foreach (DataColumn col in sqlData.Columns)
 {
 row.Add(col.ColumnName, dr[col]);
 } 
rows.Add(row); 
} 
return serializer.Serialize(rows); } } } } 

void SendJSON(string json) {
 Response.Clear();
 Response.ContentType = "application/json; charset=utf-8"; 
Response.Write(json); 
Response.End();
 }

 

php mysql database connection

Connecting to mysql via php.

<?php 
$servername = "hostname";
$username = "username";
$password = "password";
$dbname = "database";
$loggedin = false;

$conn = new mysqli($servername, $username, $password, $dbname);
if ($conn->connect_error) 
{
//handle it
} 
?>

this is nice to keep in a separate file (inc/conn.php) which can be included into other pages via;

require_once 'inc/conn.php';

upload via FTP with c#

Quick and easy way to get files uploaded with c#;

  static void Upload(string pathSource, string pathDest, string ftpServer, string ftpUsername, string ftpPassword ) {
            using (WebClient client = new WebClient())
            {
                client.Credentials = new NetworkCredential(ftpUsername, ftpPassword);
                try
                {
                    client.UploadFile(ftpServer + pathDest, "STOR", pathSource);
                }
                catch(System.Net.WebException ex){
                    Console.Write(ex.Message + " - " +
                        ex.StackTrace);
                }
            }
        
        }