nanoCAD and a bow on the side, or we program “Reversi” for a CAD platform

    Some time ago on Habré in a blog of Nanosoft the article about programming under nanoCAD was published . And on the same day, an article about “Reversi programming in Python” slipped through . A week later, Reversi was written in Silverlight , a little later - in Tcl / Tk . It was safe to say that the game Reversi went to the people. Just at that time, I was studying the capabilities of scripts under nanoCAD. But learning required practice. And I thought - why am I worse? And he decided to write a kind of "nano-boyan." So there were 3D Reversi.

    Title image

    The scripting capabilities of CAD platforms have always attracted me. Using a script, you can fasten your own functionality to a large system. Thus, using CAD not only as developers “sewed” into it, but also for my subjective purposes.

    To practice the study of the symbiosis of nanoCAD and JScript, I began to write a “frivolous” script, for a CAD system.


    I mentally divided the development of the game into three parts: the development of the game field (interface), the development of interactivity (interaction with the user) and the actual game algorithms themselves.

    To develop the playing field, I needed to create objects in the space of the nanoCAD model. Without documentation, all attempts to write something under something are probably doomed. And the first thing I did - I began to look for a description of objects and functions. I asked Google (almost like in a song) and received a large number of links to various sites describing the AutoCAD object model. For example, this site.

    Create Objects

    Objects are added using the ThisDocument.ModelSpace collection. I’ll say right away that I wrote in JScript, because I program in C ++ and the JS syntax is closer to me than the VB Script syntax.

    The field consists of 64 cells, a grid and chips. I made the grid and chips with three-dimensional shapes. And for the cells of the field I used hatching. Then I multiplied the cells and put them in their places. Further I need borders and game chips. It was not interesting to copy a game written in Python at all. I needed my own zest. Since nanoCAD has the ability to display objects in space, this highlight was the bulk of the board and game chips. Therefore, I made borders and chips 3DMesh objects. Each edge is just a rectangle. And every chip is a sphere.

    //Создаем рамку для штриховки (переменная shag задает сторону клетки).
    var polyline;
    var RefPoly = new Array(0,0,0, shag,0,0, shag,shag,0, 0,shag,0);

    polyline = ms.AddPolyline(ut.CreateTypedArrayFromJSArray(5, RefPoly));
    polyline.Closed = true;

    //После чего заштриховываем рамку:
    hatch = ms.AddHatch(1,"SOLID",false,0);

    Object objects are objects of the 3DMesh type. They are created using the Add3DMesh (...) method of the ModelSpace collection. This is a network of size M by N cells. To create it, you need to specify in the array the coordinates of all the nodes of the network. In rows: first the points of the first row, then the second, and so on to M.

    //Строим массив координат точек сети:
    var mesh = new Array();
    var n = 0;
    for (i=-1;i<2; ++i)
    	for (j=0;j<9; ++j)
    		mesh[n]  =0;
    // Создаем прямоугольник, заданный координатами, лежащий в плоскости YZ.
    var mesh3d = ms.Add3DMesh(3,9,ut.CreateTypedArrayFromJSArray(5,mesh));

    Then I still added thickness to the ribs so that the ribs did not disappear when viewed from above.

    It was more difficult to build a sphere than ribs. I had to recall the analytical geometry of the first year. I didn’t go to the library. I went to Wikipedia and found out how spherical coordinates are expressed through Cartesian ones.
    var Vertexs = new Array();
    var idx =-1;
    var r =22;
    for(j=0; j <= 20; ++j)
    	for(i=0; i < 20; ++i)
    		beta = Math.PI / 19 * j;
    		alfa = 2 * Math.PI / 20 * i;
    		Vertexs[++idx] = 25 + r*(Math.cos(alfa)*Math.sin(beta));
    		Vertexs[++idx] = 25 + r*(Math.sin(alfa)*Math.sin(beta));
    		Vertexs[++idx] = r*Math.cos(beta);
    fishka_b = ms.Add3DMesh(20,20,ut.CreateTypedArrayFromJSArray(5,Vertexs));

    As a result of these actions, the following playing field turned out:
    picture 1

    User interaction

    The next step was to organize the interaction of the script with the user. You need to ask where the player wants to put his chip. The GetEntity () function does this.

    // Смотрим, какие объекты выбраны, до тех пор, пока не выбран 1 объект штриховка
    while (hatch==null)
    	ut.GetEntity(RefPoly,null,"Ваш ход");
    	if (RefPoly.length == 1 && RefPoly [0].EntityName == "AcDbHatch")
    		// убеждаемся что эта штриховка – это клетка поля. Она хранит координаты клетки.
    		if (RefPoly[0].Hyperlinks.Count > 0)
    			hatch = RefPoly [0];
    	x = parseInt (hatch.Hyperlinks.Item(0).URLDescription);
    	y = parseInt (hatch.Hyperlinks.Item(0).URLNamedLocation);

    There is a trick here: in order not to calculate the coordinates of each of the hatchings, when creating in each of them, I put information about the location on the field. I will not dwell on the algorithms in more detail. I did not write super smart AI. And I copied the decision-making function from the source code of Reversi in Python. I must say that until this day I have not seen the Python language even once. Everything is completely readable. Adapting to JScript took me about 10 minutes.

    // здесь i, j – это координаты клетки

    //Когда пользователь выбирает клетку для хода, я получаю эти координаты обратно:
    x = parseInt (hatch.Hyperlinks.Item(0).URLDescription);
    y = parseInt (hatch.Hyperlinks.Item(0).URLNamedLocation);

    Nuances and Tricks

    Now about the nuances of script building under NanoCAD.
    I don’t know exactly how in VBS, but in JScript all variables are passed to functions by value, and not by reference. What does it mean? This means that if you specify a JScript variable when calling the method and expect that after the method is executed, the result will be returned to you, then you will be upset - this will not happen. The variable will not change. This happens, for example, with the GetEntity method (Object, PickedPoint [, Prompt]). The first parameter in it is the variable through which the set of selected objects is returned. But in JS, this does not work. How to get around this limitation? You need to pass an array instead of a variable.

    var RefPoly = new Array();
    ut.GetEntity(RefPoly,null,"Выберите объект");
    var entity = RefPoly[0]; // в массиве лежат выбранные энтити.

    The second important point is that the methods associated with coordinates (creating objects, for example) do not accept script arrays. Since JS and VBS languages ​​are weakly typed, their arrays can contain elements of different types. It is unacceptable. The functions of the Utility object CreateTypedArray (varArr, Type, ParamArray) and CreateTypedArrayFromJSArray (Type As Long, varJSArray) are used to cast to a typed array. Here Type is an indication of the type of array elements, and JSArray is the array itself.

    // Создаем js массив с координатами вершин полилинии
    var RefPoly = new Array(0,0,0, shag,0,0, shag,shag,0, 0,shag,0);

    // Создаем полилинию, передавая в нее координаты вершин, преобразованные к TypedArray.
    var polyline = ms.AddPolyline(ut.CreateTypedArrayFromJSArray(5,RefPoly));

    Script run

    To correctly display the elements of the game, you need to set the lighting style of the models. The style is set in the menu View -> Style. I set the style to Exact without showing edges.
    To start the reverse, write the command “JS” at the nanoCAD command line. And then we indicate the full path to the nanoReversi.js script.


    After three evenings, I reached my goal - the reversi game worked under nanoCAD.
    picture 2

    In isomerism, Reversi look much more unusual. I was absolutely pleased.
    picture 3

    Despite the fact that I wrote reverse, which is called “Just for fun”, the script demonstrates the capabilities of ActiveX Automation nanoCAD. And if you remember that in scripts you can use other ActiveX servers, for example, ADO for connecting to databases, then script tasks are no longer as serious as Reversi.

    The demo script can be downloaded here .

    Also popular now: