Jump to content
  • Advertisement

Blogs

The 3D book

After a break of several years the 3D book project is back on.   A few short words now on what this blog is about.  I have to deliver my wife to the bus station in a few minutes, then a week alone so may have the time then to explain things.  But the 3D book is something I started in 014 and put several years into, then the break, now on again.  A win32 app with a text window and an ogl window. I just remembered I had something written on this so here it is I write to see if anyone in this community of game developers, programmers, enthusiasts,  may be interested in a project I have been developing[off and on] for several years now. So follows a short description of this project, which I call the 3D-Book project.  The 3D-Format Reader: A new format of media. Imagine opening a book, the left page is conventional formatted text - on the right page a 3D animation of the subject of the text on the left hand page.  The text page with user input from mouse and keyboard, the 3D page with user intput from a game pad.     An anatomy text for a future surgeon, with the a beating heart in 3D animation.
    
    A childrens' story adventure book with a 3D fantasy world to enter on the right page.   
    ...     Currently 3D-Format Reader consists of a C++ Windows program: Two "child" windows in a main window frame. Two windows: a text-2D rendering window and a 3D-rendering window.  The text-2D window, as its' name implies, displays text and 2D graphics; it is programmed using Microsoft's DirectWrite text formatting API and Microsoft's Direct2D API for 2D graphics.  The 3D-rendering window uses the OpenGL API.     A 3DE-Book page is formatted in one of two possible modes: DW_MODE or GL_MODE.  In GL_MODE both windows are shown; the text-2D rendering window is on the left and the 3D OpenGL window is on the right.  In DW_MODE, only the text-2D rendering window is shown, the OpenGL window is hidden (Logically it is still there, it has just been given zero width).     The 3D-Format Reader reads text files, which consists of the text of the book, control character for the formatting of text, (bold, underline, ...), display of tables,  loading of images(.jpg .png ...), and control of 2D and 3D routines.           3D-Reader programming is based on a Model-View-Controller (MVC) architecture.  The MVC design is modular: The Controller component handles user input from the operating system , the Model component processes the input, and the View component sends output back to the user on the display.  Typical Parent-Child windows programs have multiple "call back" window procedures(winProcs): One for the parent window and one for child window.  The MVC model, simplifies message routing by using a call-back window procedure which receives Windows messages for the main window, the text-2D window and the OGL window.   
    
    A sample MVC program by Song Ho Ahn was used as a template for the 3DE-Reader. Rushed for time now, so a hasty sign off and thanks for reading. ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 8 - 21 -18 I spent the last few days working on procedural mesh generation.  First looking to find a bit of code to do what I had in mind.  Which begs the question: What 
did I have in mind?   I just wanted a cube mesh generator such that...   Requirements Input:    An integer  n = units from origin to cube face. Output:  The vertices for a unit cube centered on the origin.                                                                     8n² triangles per cube face. 3 times 8n² verts in clockwise winding order (from the outside of the cube) ready for the rendering pipeline. Screenshot of some cubes generated with the procedural cube mesh generator.                              That was about it for the output requirements.   I did not want to hand code even a single vertex and did not want to load a mesh file.   I was sure the 
code was out there somewhere, but was not finding it.  So, a bit reluctantly at first, I started coding the mesh generator. I started enjoying creating this thing and stopped searching for the "out-there-somewhere" code; although still curious how others did this. Analysis First question: How do we number the verts?  It would be great to conceive of some concise algorithm to put out the cube face verts all in clockwise
order for the outside faces of the cube directly.  That seemed beyond me so I plodded along step by step.  I decided to just use a simple nested loop to generate the cube face verts and number them in the order they were produced.  The hope(and the presumption) was: The loop code was in some order, running thru the x y and z coordinates in order, from -n to +n, therefore the output would be a recognizable pattern. The simple nested loop vert generator did not let us down: It gave us a recognizable pattern, at least for this face. It turned out (as expected now) that all six faces have similar recognizable patterns. Plotting the first row or two of verts you can easily see how to run the rest of the pattern.  Plot of the first(of six) cube faces verts output by the vert generator:  Input of n:  There are (2n+1)² verts per cube face, or 25 verts for n = 2.                                                          This is looking at the x = -n face from the outside of the cube.  To simplify the math it helps to define s = 2n.  Then there are                                                                                       (s + 1)²  verts,  or 25 for s = 4                                                                                       s²  cells on the face, or 16 for 4 = 2. We are going divide each cell into 2 triangles, so there are 2s² triangles per face, or 32 for s = 4. Second question: What pattern for the triangles?  How to number the 2s² = 32 triangles? What we want in the end is a bit of code such that... for triangles T[0] thru T[2s²-1]  or T[0] thru T[31]( for n = 4), we have T[N] = f0(N), f1(N), f2(N).  Where f0(N) gives the first vertex of T[N] as a function of N. and f1 and f2 give the second and third verts, all in CW winding order looking into the cube of course.  Here the choice is a bit arbitrary, but it would seem to make things easier if we can manage to have the order of triangles follow the order of verts to a degree.   Numbering the triangles.                                                   And now the problem becomes: Look at the triangle vert list,  T0 - T8...T31 in the image, and try to discern some pattern leading us to the sought after functions f0(N), f1(N), f2(N) where N is the number of the triangle, 0 thru 2s²-1. This really is the holy grail of this whole effort; then we have T[N] = f0(N), f1(N), f2(N) and that list of verts can be sent directly to the rendering pipeline.  Of course we want these functions to work for all six faces and all 12s² triangles to cover the cube.  But first let's see if we can just do this one face, 0 thru 2s²-1.. Thru a bit of trial and error the 32 triangles(T0 - T31) were ordered as shown.   Now we have an ordered list of the triangles and the
verts from our loop. T0 = 0 5 6
T1 = 6 1 0
T2 = 1 6 7
T3 = 7 2 1
T4 = 2 7 8
T5 = 8 3 2
T6 = 3 8 9
T7 = 9 4 3
T8 = 5 10 11 ... T30 T31. If we can find a pattern in the verts on the right side
of this list; we can implement it in an algorithm and
the rest is just coding. Pattern recognition: It appears T2 = T0 with 1 added to each component
T3 = T1 with 1 added to each component In general T[N+2] = T[N] with 1 added to each component, until we come to T8 at least.  Also it is hard to recognize a relation between the even and odd  triangles,To see what is happening here it helps to look at an image of the generalized case where n can take on any integer value n > 0. Looking for patterns in this generalized(for any n) vert plot we see... We have defined s = 2n. The 4 corner coordinates(+-n,+-n) of the x = - n cube face, one at each corner (+-n,+-n).  There are (s+1)² verts/face numbered (0 thru (s+1)² -1). There are 2s² triangles/face numbered (0 thru 2s² -1). They are indicated in red. It's not as bad as it looks iff you break it down.  Let's look at the even triangles only and just the 0th vert of these triangles.  For any row we see the number of that first vert of the even triangles just increases by one going down the row. We can even try a relation such as T[N].0 = N/2.  Here  T[N].0 denotes the 0th vert of th Nth triangle. Which works until we have to jump to the next row. Every time we jump a row we T[N+1].0  = T[N].0 + 2 for the first triangle in the higher row.  So we need a corrective term to the T[N].0 = N/2 relation that adds 1 every time we jump a row. We can use computer integer division to generate such a term and N/2s is such a term.  It only changes value when we jump rows and we get our first function ...                                                                                    f0(N) = N/2 + N/2s.  (even triangles) Remember the integer division will discard any remainder from the terms and check this works for the entire cube face, but only for the even triangles. What about the odd triangles?  Going back to the triangle vs vert list for the specific case n = 2, s = 4 for the first row; we see for the odd triangles T[N].0  = T[N-1].0 + s  + 2.  And adding this term, s + 2 to the formula for the even triangle 0th vert we get f0[N] for the odd triangles.                                                                                    f0(N) = N/2 + N/2s + s  + 2. (odd triangles) Continuing this somewhat tedious analysis for the remaining functions f1(N), f2(N) we eventually have these relations for the x = -n cube face triangles.                                                                                for N = 0  thru N = 2s² - 1.                                                                                defining   m = N/2 + N/2s.                                                                                T[N] = m,  m + s + 1,  m + s + 2       T[N]   =    f0(N), f1(N), f2(N).  (even N)                                                                                T[N] = m + s + 2,  m + 1,  m              T[N]   =   f0'(N), f1'(N), f2'(N) (odd N) So it turns out we have two sets of functions for the verts, fn(N) for the even triangles and fn'(N) for the odd. To recap here; we now have formulae for all the T[N] verts as functions of N and the input parameter n: Input:    An integer  n = units from origin to cube face. But this is only for the first face x = -n, we have five more faces to determine.  So the question is: Do these formulae work for the other faces? And the answer is no they do not, but going through a similar analysis for the remaining face gives similar T[N] = f0(N), f1(N), f2(N)  for them. There is still the choice of how to number the remaining triangles and verts on the remaining five faces, and the f0(N), f1(N), f2(N) will depend on the somewhat arbitrary choice of how we do the numbering.  For the particular choice of a numbering scheme I ended up making, it became clear how to determine the f0(N), f1(N), f2(N) for the remaining faces.  It required making generalized vert plots for the remaining five face similar to the previous image. Then these relation emerged... For face x = -n         T[N]   N(0 thru 2²-1)  we have the f0(N), f1(N), f2(N), even and odd For face x =  n         T[N]   N(2s² thru 4s²-1)       add (s+1)² to the x=-n face components and reverse the winding order For face y = -n         T[N]   N(4s² thru 6s²-1)       add 2(s+1)² to the x=-n face components and reverse the winding order For face y =  n         T[N]   N(6s² thru 8s²-1)       add 3(s+1)² to the x=-n face components  For face z = -n         T[N]   N(8s²0 thru 10s²-1)   add 4(s+1)² to the x=-n face components  For face z =  n         T[N]   N(10s²0 thru 12s²-1)  add 5(s+1)² to the x=-n face components and reverse the winding order And these are enough to allow us to write explicit expressions for all 12n² triangles for all 6 faces T[N] and what remains to be done is to implement these expression in code.  Which turned out to be a much simpler task than finding the f0(N), f1(N), f2(N) and resulted in a surprisingly short bit of code. Implementation I have attempted to make this C++ snippet of code as generic as possible and have removed any dev-platform specific #includes and the like.  GLM, a C++ mathematics library for graphics developed by Christophe Riccio is used.  It is a header only library. https://github.com/g-truc/glm/releases/download/0.9.9.0/glm-0.9.9.0.zip  That is the only outside dependency.   //  Procedural cube face verticies generator #include <vector> #include <glm/gtc/matrix_transform.hpp> struct Triangle {     glm::vec3 vert[3]; // the three verts of the triangle }; /* std::vector<Triangle> cube_Faces(int n) Input:        integer 'n'; the units from origin to cube face. Output:        vector<Triangle> glTriangle; container for the              12*(2*n)² triangles covering the 6 cube faces. */ std::vector<Triangle> cube_Faces(int n){     size_t number_of_triangles(12*(2*n )*(2*n));     size_t number_of_face_verts(6*(2*n +1 )*(2*n+1));     std::vector<glm::vec3> face_verts(number_of_face_verts);     std::vector<Triangle> glTriangle(number_of_triangles); //  Generate the 6*(2n +1 )² face verts -------------------------------     int l(0);     for(int i = 0; i < 6; i++){         for(int j = -n; j <= n; j++){             for(int k = -n; k <= n; k++){                 // Below "ifS" strip out all interior cube verts.                 if( i == 0){ // do yz faces                     face_verts[l].x = (float)(-n); //x                     face_verts[l].y = (float)j; //y                     face_verts[l].z = (float)k;}//z                 if( i == 1){ // do yz faces                     face_verts[l].x = (float)(n); //x                     face_verts[l].y = (float)j; //y                     face_verts[l].z = (float)k;}//z                             if( i == 2){ // do zx faces                     face_verts[l].x = (float)j; //x                     face_verts[l].y = (float)(-n); //y                     face_verts[l].z = (float)k;}//z                 if( i == 3){ // do zx faces                     face_verts[l].x = (float)j; //x                     face_verts[l].y = (float)(n); //y                     face_verts[l].z = (float)k;}//z                 if( i == 4){ // do xy faces                     face_verts[l].x = (float)j; //x                     face_verts[l].y = (float)k; //y                     face_verts[l].z = (float)(-n);}//z                 if( i == 5){ // do xy faces                     face_verts[l].x = (float)j; //x                     face_verts[l].y = (float)k; //y                     face_verts[l].z = (float)(n);}//z                 l++;             }         }     } //  Generate the 12*(2*n)² triangles from the face verts -------     int s = 2*n;    int q = 2*s*s;    int a = (s+1)*(s+1);     int f(0);        int r(0);        int h(0);     for( int N=0; N < number_of_triangles; ){          // triangles already in CW winding          if( N <  q || N <  5*q && N > 3*q - 1  ){              // do the even indicies             f= q*(N/q); r = a*(N/q); h = (N-f)/2 + (N-f)/(2*s) + r;             glTriangle[N].vert[0] = face_verts[h];             glTriangle[N].vert[1] = face_verts[s + 1 + h];             glTriangle[N].vert[2] = face_verts[s + 2 + h];             N++; f= q*(N/q); r = a*(N/q); h = (N-f)/2 + (N-f)/(2*s) + r;             // do the odd indicies             glTriangle[N].vert[0] = face_verts[s + 2 + h];             glTriangle[N].vert[1] = face_verts[ 1 + h];             glTriangle[N].vert[2] = face_verts[h];             N++; f= q*(N/q); r = a*(N/q); h = (N-f)/2 + (N-f)/(2*s) + r;         }         // triangles needing reverse order for CW winding         if( N >  5*q - 1 || N <  3*q && N > q - 1 ){              // do the even indicies             glTriangle[N].vert[0] = face_verts[s + 2 + h];             glTriangle[N].vert[1] = face_verts[s + 1 + h];             glTriangle[N].vert[2] =  face_verts[h];             N++; f= q*(N/q); r = a*(N/q); h = (N-f)/2 + (N-f)/(2*s) + r;             // do the odd indicies             glTriangle[N].vert[0] = face_verts[h];             glTriangle[N].vert[1] = face_verts[1 + h];             glTriangle[N].vert[2] = face_verts[s + 2 + h];             N++; f= q*(N/q); r = a*(N/q); h = (N-f)/2 + (N-f)/(2*s) + r;         }     } //  Normalize the cube to side = 1 ------------------------------     for(int i = 0; i < number_of_triangles; i++){         glTriangle[i].vert[0].x = glTriangle[i].vert[0].x/(2.0*(float)n);         glTriangle[i].vert[0].y = glTriangle[i].vert[0].y/(2.0*(float)n);         glTriangle[i].vert[0].z = glTriangle[i].vert[0].z/(2.0*(float)n);         glTriangle[i].vert[1].x = glTriangle[i].vert[1].x/(2.0*(float)n);         glTriangle[i].vert[1].y = glTriangle[i].vert[1].y/(2.0*(float)n);         glTriangle[i].vert[1].z = glTriangle[i].vert[1].z/(2.0*(float)n);         glTriangle[i].vert[2].x = glTriangle[i].vert[2].x/(2.0*(float)n);         glTriangle[i].vert[2].y = glTriangle[i].vert[2].y/(2.0*(float)n);         glTriangle[i].vert[2].z = glTriangle[i].vert[2].z/(2.0*(float)n);     };     return glTriangle; }   The rendering was done using OpenGl. // OGL render call to the cube mesh generator - PSUEDOCODE int n(2); int cube_triangle_Count = (12*(2*n)*(2*n)); std::vector<Triangle> cube_Triangles(cube_triangle_Count); cube_Triangles = cube_Faces(n); glBindBuffer(GL_ARRAY_BUFFER, uiVBO[0]); glBufferData(GL_ARRAY_BUFFER, cube_Triangles.size()*sizeof(Triangle), &cube_Triangles[0], GL_STATIC_DRAW); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3*sizeof(float), 0); glEnableVertexAttribArray(0); glDrawArray(GL_TRIANGLES,0,3*cube_triangle_Count);   This just gets the position attribute of the cube face triangle verts; for the color and other attributes there are a couple of options:  Use separate GL_ARRAY_BUFFERS for the color and other attributes.  Or add attributes to the Triangle struct... struct Triangle { glm::vec3 vert[3]; // the three verts of the triangle attribute1; attribute2; ... }; Screenshot of the spherified cube. What's next? Now that we have the cube mesh what we can do with with it practically unlimited.  The first thing I did was turn it into a sphere.  Playing with tesselating the cube or sphere or stellating it with different patterns;  might do.  Ended up trying a few matrix transformations on the cube mesh.  These are shown in the image below.     These shapes are result short bits of code like the code for the column shape below. //Column     for(int i = 0; i < number_of_triangles; i++){         for(int j = 0; j < 3; j++){             if( glTriangle[i].vert[j].y < 0.5f  && glTriangle[i].vert[j].y  > -0.5f  ){              float length_of_v = sqrt((glTriangle[i].vert[j].x * glTriangle[i].vert[j].x) + (glTriangle[i].vert[j].z * glTriangle[i].vert[j].z));             glTriangle[i].vert[j].x = 0.5f*glTriangle[i].vert[j].x/length_of_v;             glTriangle[i].vert[j].z = 0.5f*glTriangle[i].vert[j].z/length_of_v;             }         }     }   Doing this; the blacksmith at his forge analogy soon presents.  The mesh is the ingot, hammer matrices stretch, round and bend it against the fixed geometry of the anvil - coordinate system. I am the smith.   
    Tetrahedron The tetrahedron is the platonic solid with the least number of faces(4),  edges(6),  and verts(4).  In antiquity it was associated with the element of fire due to its' sharp vertices.   The algorithm for the tetrahedron mesh was developed in a similar way to the cube, but here it seemed simpler to get a routine for just one face - an equilateral triangle - and use matrix translations and rotations to form the complete tetrahedron.  So more like origami or tinsmithing than blacksmithing.   Procedural tetrahedron screenshot.   The n = 4 and the general case  To get an routine for the general case, n an integer > 0, a bit of what I think is known as mathematical induction was used.   PSUEDO-CODE Algorithm to generate equilateral triangle face with unit side composed of n² "sub-triangle" in the xy plane. std::vector<Triangle> equilateral(int n){ std::vector<Triangle> tri_Angle(n²); // Create the seed triangle in xy plane . // This is triangle "0" in the image above. // This is in the xy(z=0) plane so all the // tri_Angle.vert[0 thrue n -1 ].z = 0. // We just work with the x and y verts. tri_Angle[all].vert[all].z = 0; // The seed triangle tri_Angle[0].vert[0].x = 0; tri_Angle[0].vert[0].y = 0; tri_Angle[0].vert[1].x = 1/2n; tri_Angle[0].vert[1].y = sin(π/3)/n; tri_Angle[0].vert[2].x = 1/n; tri_Angle[0].vert[2].y = 0; // Build the equilateral triangle face. int count(0); for(int row = 0; row < n; row++){ count = 0; Spin = glmRotateMatrix( π/3, zaxis ); // The magic happens here! for(int i = 2*n*row - row*row; i < 2*n*row - row*row + 2*n - 2*row - 1; i++) { if (count % 2 == 0 ) // Triangle is even in the row - just translate { // more magic. x_Lat = glm_Matrix((count + row)/2n, row*sin(π/3)/n, 0.0f); tri_Angle[i].vert[0] = x_Lat* tri_Angle[0].vert[0]; tri_Angle[i].vert[1] = x_Lat* tri_Angle[0].vert[1]; } else // Triangle is odd in the row - rotate then translate { //and more magic. x_Lat = glm_Matrix((count + row + 1)/2n, row*sin(π/3)/n, 0.0f); tri_Angle[i].vert[0] = x_Lat*Spin*tri_Angle[0].vert[0]; tri_Angle[i].vert[1] = x_Lat*Spin*tri_Angle[0].vert[1]; } } count++; } return tri_Angle; }   This is the psuedocode version of the routine which generates the verts for the n² triangles in a face.  Getting this algorithm was a bit of a brain drain but looking for patterns in the image of the face allowed it to happen.  We use a "seed" triangle, which is triangle 0 on the lower left of the figure.  The verts of this one triangle are input; the rest of the n² triangles verts are generated by translating and rotating this seed triangle. Notice: There are n rows, every row has 2 less triangles than the row below.  If we number the triangles from 0 to 2n - 2*row - 2, where the rows run 0 to n; the even triangles just need to be translated ...                                                       in the x direction by (count + row)/2n  where count = their  position in the row 0 to 2n - 2*row - 2.                                                      in the y direction by row*height.  height = height of seed triangle. The odd triangles need to be rotated pi/3 = 60 degrees around the z axis then translated ...                                                       in the x direction by (count + row + 1)/2n  where count = their  position in the row 0 to 2n - 2*row - 2.                                                      in the y direction by row*height.  height = height of seed triangle. Now we have a single face for the tetrahedron, to join the four faces together we need the angle between the faces called the dihedral angle. Dihedral Angle Each of the five platonic solids has a characteristic called the dihedral angle. This is the angle between the faces. For the cube it is 90 degrees or pi/2 radians. For the tetrahedron it is 70.528779° = arccos(1/3) = atan(2*sqrt(2)); The tetrahedron, with just four faces, is the simplest of the platonic solids. The simplest way I can think of to build it: Start with the four face stacked one on another,  edges aligned. Imagine the top three faces each hinged to the bottom face along one edge.  Then rotate each face around then hinged edge by arccos(1/3), the dihedral angle. That is the method of the bit of code shown below. vector<Triangle> tetrahedron(int N){ std::vector<Triangle> tetra(4n²); tetra[all].vert[all].z = 0; // The seed triangle tetra[0].vert[0].x = 0; tetra[0].vert[0].y = 0; tetra[0].vert[1].x = 1/2n; tetra[0].vert[1].y = sin(π/3)/n; tetra[0].vert[2].x = 1/n; tetra[0].vert[2].y = 0; // ----- The first face ----- // generate the first equilateral triangle face with unit side // composed of n² "sub-triangle" in the xy(z=0) plane. int count(0); for(int row = 0; row < n; row++) { count = 0; Spin = glmRotateMatrix( π/3, zaxis ); for(int i = 2*n*row - row*row; i < 2*n*row - row*row + 2*n - 2*row - 1; i++) { if (count % 2 == 0 ) // Triangle is even in the row - just translate { x_Lat = glm_Matrix((count + row)/2n, row*sin(π/3)/n, 0.0f); tetra[i].vert[0] = x_Lat* tetra[0].vert[0]; tetra[i].vert[1] = x_Lat* tetra[0].vert[1]; } else // Triangle is odd in the row - rotate then translate { x_Lat = glm_Matrix((count + row + 1)/2n, row*sin(π/3)/n, 0.0f); tetra[i].vert[0] = x_Lat*Spin*tetra[0].vert[0]; tetra[i].vert[1] = x_Lat*Spin*tetra[0].vert[1]; } } count++; } // ----- The second face ----- // generate the second equilateral face from the first // by rotating around the X axis by the dihedral angle. float tetra_Dihedral = atan(2*sqrt(2)); Spin = glmRotateMatrix( -tetra_Dihedral, xaxis ); //just rotate for(int i = 0; i < n²; i++) { for(int j = 0; j < 3; j++) { tetra[n² + i].vert[j] = Spin*tetra[i].vert[j]; } } //The rotation gives CCW verts so need need to make them CW again for(int i = n²; i < 2n²; i++) { swap(tetra[i].vert[0] ---- with --- tetra[i].vert[2]; } // ----- The third face ----- // For the second face we rotated the first triangle around its' // base on the X - axis. For the third face we rotate the first // triangle around its' edge along the vector ( 0.5, 0.866025, 0.0 ). Spin = glmRotateMatrix( tetra_Dihedral ,glm::vec3(0.5f,0.866025f,0.0f)); for(int i = 0; i < n²; i++) { for(int j = 0; j < 3; j++) { tetra[2n² + i].vert[j] = Spin*tetra[i].vert[j]; } } //need to make it CW again for(int i = 2n²; i < 3n²; i++) { swap(tetra[i].vert[0] ---- with --- tetra[i].vert[2]; } // ----- The forth face ----- // For the forth face we first translate the original face along the // X axis so it right edge vector (-0.5f, 0.866025f, 0.0f) passes thru the origin. // Then we rotate the first triangle around the that vector by the dihedral angle. x_Lat = glm::translate( glm::vec3(-1.0f, 0.0f, 0.0f)); Spin = glmRotateMatrix( -tetra_Dihedral, glm::vec3(-0.5f,0.866025f,0.0f)); for(int i = 0; i < n²; i++) { for(int j = 0; j < 3; j++) { tetra[3n² + i].vert[j] = Spin*x_Lat*tetra[i].vert[j]; } } //need to make it CW again for(int i = 3n²; i < 4n²; i++) { swap(tetra[i].vert[0] ---- with --- tetra[i].vert[2]; } // We now have the complete tetrahedron, tetra(4n²), but its' base // is not horizontal so let's make is so. // put the base in the xz plane // rotate 90 - dihedral angle around X axis. Spin = glm::rotate( tetra_Dihedral - half_PI, xaxis); for(int i = 0; i < 4n²; i++) { for(int j = 0; j < 3; j++) { tetra[i].vert[j] = Spin*tetra[i].vert[j]; } } // We now have the complete tetrahedron, tetra(4n²), sitting with its' // base on the xz(y=0) plane, let's put its' center at the origin. // For this we need another Platonic Solid attribute: The radius of // the tetrahedrons circumscribed sphere which is sqrt(3/8). So the // center of the tet is this vertical distance down from its' apex. // To put the center at the origin we need to translate down this // distance along the Y axis. We need also to xlat along the Z axis // by 1/2(sqrt(3)) = 0.28867; the distance from the center of a face // to the center of a side. // Finally we need to center along the X axis( xlat -.5) x_Lat = glm::translate( glm::vec3(-0.5f, -sqrt(3/8), sqrt(3)/2); for(int i = 0; i < 4n²; i++) { for(int j = 0; j < 3; j++) { tetra[i].vert[j] = x_Lat*tetra[i].vert[j]; } } return tetra; } Notes: Oops: Left out std::vector<Triangle> tri_Angles(4*n*n);  Should be the first line of the function body!  Corrections to the corrections: First line of function definition vector<Triangle> tetrahedron(int N){   should be vector<Triangle> tetrahedron(int n){ Those last two for loops could and probably should be combined to do a translate*rotate*triangle in one statement, but I have not tried it. All distances are for a tetrahedron with unit side. The sign of the dihedral angle in the rotations was usually determined by trial and error.  I.e.; I tried one sign, compiled the code and rendered the tet.  If it was wrong I just reversed the sign. The end result is a tetrahedron with its' center at the origin, its' base in the xz plane, and one edge parallel to the X axis. Of the five platonic solids; three (tetrahedron, octahedron, icosahedron) are composed of equilateral triangle faces. One of square faces (cube).  And one of pentagon faces (dodecahedron). Two tetrahedrons fit nicely in a cube.                                                                                              11-16-18:  Corrections to code blocks for equilateral  triangle and tetrahedron. 11-18-18: More corrections.

3dBookman

3dBookman

 

Join my Ludum Dare team!

I am joining a team for Ludum Dare 43, and I need a designer and an artist. We will use Unity3D for the  game engine. https://crowdforge.io/jams/ludumdare/teams/2621

DabbingTree

DabbingTree

 

Card Game

After alot of messing about in windows I have finally sorted out the game for people to play in a .zip compiled for win32 any feedback is welcomed.   If anyone is interested in a linux version this will be much easier for me   CardGame.zip

Gooey

Gooey

 

Gameplay Xilvan Design games for 2018-2019!

Hi everybody, Xilvan Design building 3D games since 2004 in Blitz3D, we now present you our kindly official gaming related pages. (please click on each links, download games & bookmark the pages): Lights of Dreams IV: Far Above the Clouds v9.47. Candy World II: Another Golden Bones v9.57. Candy Racing Cup: The Lillians Rallies v3.07. Candy World Adventures IV: The Mirages of Starfield v7.57. Candy to the Rescue IV: The Scepter of Thunders v7.27. Candy's Space Adventures: The Messages from the Lillians v17.57. Candy's Space Mysteries II: New Mission on the earth-likes Planets v7.57. New Xilvan Design Websites. Xilvan Design's Youtube Channel. Friendly, Alexandre L., Xilvan Design.

Xylvan

Xylvan

 

Major refactoring and script progress report

After coming up with the name Fusion for the ide, I decided to refactor the whole project to be called Fusion. So instead of vividengine, it's fusion engine. instead of vividscript, it's fusion script. Not just names, but major refactoring of class names etc. As for the newly titled fusionscript, I am half way through a complete rewrite of the parser. Also it now has reverse polish expressions, meaning they finally work like any other language.

Vivid3DDev

Vivid3DDev

Y'all ever just get wayyyy to distracted time n time again?

Like legit though! I got that recent Humble Bundle deal with all them pretty pictures and things and I'm just in RPG mode right now 🤣 I usually live stream some video games like Destiny or Dark Souls or whatever but I even abandoned that and spent 5 hours messing around with some new assets. Still streamed though, just of pc instead of ps4.. That's the important bit. I'm liking the attempt of an RPG because I don't know how to do it 100%.. Like a tower defense or space shooter or platformer, i've done those many times over.. I spent maybe 2 hours figuring out why my collision box wasn't triggering on a wall piece and preventing movement. Got it in the end though! That's also the important bit. Being able to figure it out. I'd hate to just watch a tutorial and follow it and be done with it like now I know things that I technically should have already known like the size of my sprite really matters because obviously my bounding box + my collision range is what's used. And I knew the second part but any other tutorials that may have been followed back in the day, they've got their sprites sorted so you just import sprPlayer and its already the right size... I'd have never got that little piece of information by just blinding following a tutorial. Plus I'd never wanna release anything for 'me' if it was made solely with a tutorial.  But yeah, my tower defense is still waiting on a few pieces so that's just in limbo right now, The space shooter got paused due to getting all these assets so I'm now messing around with RPG stuff and there's fairly 'simple' things that would just be the same as other games anyway, like moving to a room, the code/command for that is obviously the same and you just alter the condition. Ding! Winner! lol but yeah I feel like I'm making a 'proper' game when I'm spending a really long time making a level knowing full well I've got to spend many many more hours on all the other levels.  I'm basing my thought process there on the fact that I've mostly just been making games that run themselves once you've built the first part. Tower Defense that never ends (with 1 map/level), Space Shooter that infinitely Scrolls and/or Big Space Boss fight type stuff..  Although, I am on the hunt for a 'proper' solid wall collision method as I think several thousand objects called objSolid or objWall or objWhatever is ultimately going to slow the game/break stuff? I mean games can have like thousands if not millions of things in them though maybe? I'm just worried that I'm going to end up spending 10+ hours placing down thousands of objects and adjusting them and testing them and then find out that you can just use code like ""blah blah billy bob wrote this"" and that will check the type of tile or something you know? I was reading one method where someone talked about making a type of an array made as a grid for your entire map/screen that counted (and then destroyed) each instance of your wall and gave the wall tiles on the grid a value of 1 so you'd not have to worry about thousands of objects cluttering the place BUT you still need to insert them and test them... I'm thinking that is just 'a part of the process' though really. Like I don't want to take lots of shortcuts, I'm just currently not in the mindframe of spending hours doing 1 task like adding all the wall objects on top of the soon to be 'wall tiles' so I think a bit of personal adjustment is required really. I just want to make sure that this is what people really do. If it is then I'd be happy to just get on with it...  Heh, look at that! Attempting to join the level designer guild  which reminds me. I need to go learn how to make 'cool levels' in an RPG!!! I can make a house but where does it go? Hmmmm    

CyberFlash

CyberFlash

 

13 RONIN - DevLog #7 - Fight or flight!

Since I had no previous experience of coding a computer player I turned to our friend google for advice. I found a number of threads on the subject, some talked about AI, but most of them talked about reaction based solutions, but since I’m not interested in AI and rather want to mimic the feeling found in old-school fighting games I decided to go for the reaction based solution. And when I use the phrase “reaction based”, I’m referring to an implementation that selects action-based on one or several conditions e.g. if the opponent hit then block.  Feeling a bit over-confident, I stopped reading and headed over to Visual Studio just to realize that this was not as easy as I had thought. Soon I had a bunch of if-statement and a code hard to follow. I refactored the code, but still I wasn’t pleased Along came Halloween and at my workplace, we had an amazing party (I was dressed as the Invisible Man). After dinner, I chatted with a colleague and talking about the computer player he asked if I was using a decision-tree for action selection. Decision trees? What’s this, yet another gap of knowledge. The name itself told me that this was something I had to read up on. So, the day after, still recovering from the party, I started reading. And oh yes, this was what I’ve been looking for. (Thanks Mikael for the suggestion) Decision trees The full definition is somewhat longer, but simplified, a decision tree is a tree structure describing conditions and results. Every node is a condition deciding upon which branch to follow until reaching the leaf and the result of the path taken. This was exactly the kind of data structure I needed to find a structure around the computer player logic Using a fluent builder I could put all conditions in a tree and let the leaves contain what actions to perform. Decision tree for the computer player. DecisionTreeNode My implementation of the decision tree is very basic, it consists of a DecisionTreeNode-class that I use for the tree as well as for the nodes and the leaves.  The Condition-property is only applicable to condition nodes. It’s a delegate that when called will evaluate what child node to step into. It returns the name of the child to step into. The Result-property is only applicable to leaves. It’s a delegate with actions associated to the leaf. The GamePlayState-class contains all data needed when deciding computer action. DecisionTreeBuilder I’m quite fond of fluent coding so when building the DecisionTreeBuilder it was a natural pattern to choose. Using this pattern makes classes easy to use and code easy to read.
 
This is how I build the decision tree var decisionTree =     DecisionTreeBuilder         .Begin(             "Reacting",             state =>                 state.Player.IsReacting()                     ? "Elapsed"                     : "Opp new action")         .AddNode(             "Elapsed",             state =>                 state.Player.IsTimeToReact(state.GameTime.TotalGameTime)                     ? "Facing"                     : "Done 1")         .AddNode(             "Facing",             state =>             {                 return                     state.Player.IsFacingOpponent()                         ? "Reachable 1"                         : "Reachable 2";             })         .AddNode(             "Reachable 1",             state =>                 state.Player.IsWithinReach(state.Opponent)                     ? "Opp attacking"                     : "Opp approaching")         .AddNode(             "Opp attacking",             state =>                 state.Player.ActionToReactUpon is AttackAction                     ? "Defend"                     : "Attack 1")         .AddLeaf(             "Defend",             state =>             {                 state.Player.ResetReaction();                 state.Player.ParryHeadCut();             })         .AddLeaf(             "Attack 1",             state =>             {                 state.Player.ResetReaction();                 state.Player.HeadCut();             })         .Parent()         .AddNode(             "Opp approaching",             state =>                 state.Opponent.IsAdvancing() &&                 state.Opponent.IsFacingOpponent()                     ? "Idle 1"                     : "Advance 1")         .         .         .         .Build(); AddNode will create and append a new node to the current nodes’ children and then go into the newly created node and make it current. AddLeaf will create and append a new leaf, but not go into it. Parent will go to the parent node and make it current. Build will return the newly composed tree.  The choice to use strings for names makes it easy to follow the code but also makes it easy switching between the diagram and the code. The Parent-, and Name-properties together with the GetFullName method make nice tools while debugging. Player In my game I have a HumanPlayer-class and a ComputerPlayer-class, both implementing an abstract class Player. The main difference between the Human- and the ComputerPlayer-class is how the Update-method is implemented. The HumanPlayer-class is using input from keyboard and gamepad to control the player character while the ComputerPlayer is using the decision tree.  The code for using the tree looks like this:     var leaf = _decisionTree.Evaluate(state);
    leaf.Action(state); Nice, isn’t it?
Happy coding!
jan.  

ERASERHEAD STUDIO

ERASERHEAD STUDIO

【STUFF】

This is how another 10 levels look like. There are new mechanics involved: the slow bonus, the immunity bonus and the damage objects. Music: Wanna░chat?https://discord.gg/9guZGAC   Thank you for following the development of our games!

SilviuShader

SilviuShader

GameDev Challenge - Frogger - Part 4 (Final)

Hello everyone!   This will be a final update for this little series!   Sadly, I don't really have much time, so this will be super short. Not really much happened this week. Since I don't really have any new ideas my goal is to complete this project this weekend. For this week I finished updating the main menu and focused on finding and eliminating bugs.  I am quite happy with the current gameplay and I have implemented all necessary elements for this challenge. I know the game does not look really beautiful, but I did not expect anything better from me.  Currently I am only waiting for the feedback of my play tester. Afterwards I am ready to create and upload the final builds. Since I don't really have much else do report enjoy some screenshots of the final game: Main Menu: Items are spawning randomly: Peasons are patrolling the streets and rivers: Next Goals Create final builds for Windows, Mac and Linux Test and submit final builds   Write a little post-mortem to reflect on this project Thanks for reading and until the next project!   - Znippy Last Part:  

Znippy

Znippy

 

10hz Smoothness

The old fixed timestep paradigm. Juicy stuff, and arguably the backbone of many a great gaming title  Until recently, I'd not bothered to implement it, instead preferring my own questionable potpourri of odds and ends, with maybe a little vertical blanking here and there.  I checked out DeWitter's game loop many moons ago but, in spite of it's virtues,  it wasn't what I needed at the time. After being asked by a work-colleage-turned-indy-gamedev guy for a rundown on how it worked, what the point of it is and 'what the hell is this interpolation business?', I cobbled together a little demo.  In this video, everything is updated at a fixed timestep (60hz) however, only the colored bar is rendered with interpolated state.  At about the halfway mark, after throwing some white boxes onto the screen, I switch down to a 10hz update rate (after a brief pause).  Thanks to interpolation,, the colored bar retains most of it's smooth movement, even at `10hz.  The white boxes, with all their physics goodness, don't fare well at 10hz without interpolation.  I haven't implemented it there because I'm honestly not sure how.. https://www.youtube.com/watch?v=6SptavKHwew&feature=youtu.be    

ROGRat

ROGRat

 

Planet generation in real time.....

Well we're back with a new entry.  As usual we have made a lot of bug fixes. The primary new feature though is the separation of graphics, and planet generation in different threads. Here's the somewhat familiar code that was modified from our first entry.... void CDLClient::InitTest2() { this->CreateConsole(); printf("Starting Test2\n"); fflush(stdout); // Create virtual heap m_pHeap = new(MDL_VHEAP_MAX, MDL_VHEAP_INIT, MDL_VHEAP_HASH_MAX) CDLVHeap(); CDLVHeap *pHeap = m_pHeap.Heap(); // Create the universe m_pUniverse = new(pHeap) CDLUniverseObject(pHeap); // Create the graphics interface CDLDXWorldInterface *pInterface = new(pHeap) CDLDXWorldInterface(this); // Camera control double fMinDist = 0.0; double fMaxDist = 3200000.0; double fSrtDist = 1600000.0; // World size double fRad = 400000.0; // Fractal function for world CDLValuatorRidgedMultiFractal *pNV = new(pHeap) CDLValuatorRidgedMultiFractal(pHeap,fRad,fRad/20,2.0,23423098); //CDLValuatorSimplex3D *pNV = new(pHeap) CDLValuatorSimplex3D(fRad,fRad/20,2.0,23423098); // Create world CDLSphereObjectView *pSO = new(pHeap) CDLSphereObjectView( pHeap, fRad, 1.0 , 0.25, 6, pNV ); pSO->SetGraphicsInterface(pInterface); // Create an astral reference from the universe to the world and attach it to the universe CDLReferenceAstral *pRef = new(pHeap) CDLReferenceAstral(m_pUniverse(),pSO); m_pUniverse->PushReference(pRef); // Create the camera m_pCamera = new(pHeap) CDLCameraObject(pHeap, FDL_PI/4.0, this->GetWidth(), this->GetHeight()); m_pCamera->SetGraphicsInterface(pInterface); // Create a world tracking reference from the unverse to the camera m_pBoom = new(pHeap) CDLReferenceFollow(m_pUniverse(),m_pCamera(),pSO,fSrtDist,fMinDist,fMaxDist); m_pUniverse->PushReference(m_pBoom()); // Set zoom speed in the client this->SetZoom(fMinDist,fMaxDist,3.0); // Create the god object (Build point for LOD calculations) m_pGod = new(pHeap) CDLGodObject(pHeap); // Create a reference for the god opbject and attach it to the camera CDLReference *pGodRef = new(pHeap) CDLReference(m_pUniverse(), m_pGod()); m_pCamera->PushReference(pGodRef); // Set the main camera and god object for the universe' m_pUniverse->SetMainCamera(m_pCamera()); m_pUniverse->SetMainGod(m_pGod()); // Load and compile the vertex shader CDLUString clVShaderName = L"VS_DLDX_Test.hlsl"; m_pVertexShader = new(pHeap) CDLDXShaderVertexPC(this,clVShaderName,false,0,1); // Attach the Camera to the vertex shader m_pVertexShader->UseConstantBuffer(0,static_cast<CDLDXConstantBuffer *>(m_pCamera->GetViewData())); // Create the pixel shader CDLUString clPShaderName = L"PS_DLDX_Test.hlsl"; m_pPixelShader = new(pHeap) CDLDXShaderPixelGeneral(this,clPShaderName,false,0,0); // Create a rasterizer state and set to wireframe m_pRasterizeState = new(pHeap) CDLDXRasterizerState(this); m_pRasterizeState->ModifyState().FillMode = D3D11_FILL_WIREFRAME; // Initailze the universe m_pUniverse()->InitFromMainCamera(); // Run the universe! m_pUniverse->Run(); }
Right at the end we call "m_pUniverse->Run();". This actually starts the build thread. What it does is continuously look at the position of the god object which we have attached to the camera above in the code, and build the planet with the appropriate LOD based on it's proximity to the various terrain chunks.........Let's not bore you with more text or boring pictures. Instead we will bore you with a boring video:
  As you can see it generates terrain reasonably fast.  But there is still a lot more we can do. First off we should eliminate the backside of the planet.  Note that as we descend towards the planet the backside becomes bigger and bigger as the horizon becomes closer and closer to the camera. This is one advantage of a spherical world.  Second we can add a lot more threads. In general we try to cache as much data as possible.  What we can still do is pre-generate our octree at one level down using a fractal function pipeline.  In general most the CPU time is spent in the fractal data generation, so it makes sense to put add more threading there.  Fortunately this is one of the easier places we can use threading. For our next entry we hope to go all the way down to the surface and include some nominal shading.

Gnollrunner

Gnollrunner

Game Events based on Physics Interactions

So, last night I jumped a giant hurdle in design with regards to triggering game events. The problem I faced was that I had two systems that were decoupled, Game and Physics, however, the goal was to generate a game event from a physics interaction, in this case, an AABB collision. This required the use of a callback function, which I determined logic for in the Game Class, but registering it with the physics class, so that the physics could use the callback to initiate game events. In my case, I wanted to make an explosion, so here we have this bit:   this->onIntersect = [this](PhysicalObject & a, PhysicalObject & b) { GameObject * objectA = reinterpret_cast<GameObject*>(a.userData); GameObject * objectB = reinterpret_cast<GameObject*>(b.userData); if (objectA->Type == GameObjectType::ENEMY && objectB->Type == GameObjectType::PLAYER) { GenerateExplosion(objectA->getPosition(), 64, 64); objectB->resetPosition(); } };   The call back takes two physical objects that have collided and reinterprets their void userData pointer into a game object. Then, after determining what game object types we're dealing with, we apply the logic, in this case, we want to generate an explosion, and for now, I'm resetting the goblin's position to its origin. The GameObjectType is something I just newly added to this process, and it has also enabled me to gate the response of the trigger objects, so that the player is not reset back to its origin if it runs into a lane trigger box (the thing that causes my lanes to reset).   Another problem was identified upon successfully generating an explosion, it didn't animate! This initiated a long string of changes to how my game objects handle their animations. My game object was previously reliant on whether or not the object was in motion (a boolean provided by the physical component) to determine whether it should animate or not. Therefore, no movement, no animation. This caused me to restructure how I handle animations. Now, I have set it up so that doing nothing is actually running an IDLE animation, even if that animation is just one frame. Now, things are always animating. There were a lot of ins and outs to this change but I'll post the updated game object update code so that you can get an idea: void GameObject::Update(float dt) { Position = myPhysics->getNewPosition(dt); if (myPhysics->getDirection() >= 0) { currentDirection = myPhysics->getDirection(); } mySprite->setPosition(Position); mySprite->SetAnimation(currentAction, currentDirection); if (updateTimer.GetMilisecondsElapsed() >= mySprite->getFrameTime()) { mySprite->AdvanceFrame(); updateTimer.Restart(); } }   Changes summarized: Game object needed to be aware of its current facing direction Set animation needed modified to take an action, and a direction, this was quite a large undertaking, taking around 3 hours for me to get working. I had to change the way I initialized my animations, as well as use the currentAction and currentDirection to get a key into the animations hash map. Remove dependency of bool inMotion to determine whether or not to animate Add idle animations to everything, and a default animation set as IDLE/UP if there is only one animation Cause all game objects to start in facing position UP etc... the list goes on Here is the result! Game Event Triggers and Updated Animations!.mp4 This has paved the way for me to meet some of the other requirements of the challenge, namely, triggering game win and game over events. Also, I just purchased a humblebundle pack, here: HumbleBundle RPG Pack So, hopefully, next time I post, we'll have some vastly improved visuals and new baddies to play with! But, not before I set up some of the aforementioned triggers, not to mention the obvious, making it so my generated explosions don't perpetually exist :).

Oh, and the explosion is from here: https://mbtskoudsalg.com/explore/explosion-sprite-sheet-png/#gal_post_3691_explosion-sprite-sheet-png-3.png, after reading the site terms I decided it was safe to use.

JWColeman

JWColeman

The Final Form

After a bit of motivation trouble earier this week, managed to create a somewhat complicated model in around a day. I've dubbed him "Pulgator", and if people are curious, here's how he looks closer-up in Blender: Yeah, I kind of decided to get fancy with baking from a high-poly sculpture, and we both paid for it. I had to actually paint the face manually (with a mixed result), because baking was messing up. And some problems I didn't fix. Also the diffuse texture... Well, it was a nightmare to paint around the (partially messed up) normals, and... Anyway, it's not going to be seen from close-up nor sit on the screen for a long time. You'll also notice in the video, that I added a moving row. Let's say that the "lava" texture is a work in progress.  I still don't have any idea about making shaders, so I tried my best by stacking together three layers with the same texture, moving at a slightly different speed. Hopefully that'll be passable? Finally, maybe it's time to address one old issue: I'm making the level out of separate, one-sided tile models, and I'm getting all kinds of funny lighting problems. Well, by "address" I mean I've got no idea how to. Maybe I should add a back side to all tiles? But the whole setup seems kind of inefficient. Any ideas are welcome.

supermikhail

supermikhail

I nearly broke everything I'm sure of it

I mean just look at that army of space ships 🤣 Despite how confident I was, given that I'd just done a similar thing in my Tower Defense I have very clearly forgotten something in my infinite spawning on condition code and I'm just glad I closed it as soon as I did cuz I'm sure my computer would go bye bye -- Maybe not, Maybe computers survive more things but this would have just gone on forever. Oops..   But on the plus side, My spaceship will move and shoot now.. Hurray!  Last night though before I shut everything down, It looked like this.. Like it didn't go haywire and I loaded it up today and clicked play to remind myself (cuz I haven't done my strikethrough ritual yet 😏 ) and it just decided to keep on spawning and like spawning a lot of them too!! So i'm glad I stay around the basic stuff. I need to do it more often so its more of a smooth process instead of once every blue moon make things and then pause for a year (cuz i've decided a blue moon is an annual event but for some reason didn't just say once every year.. weird)   See lots of bullets  the 'basics' work... Just really gotta tone down the enemy spawn thingy. 

CyberFlash

CyberFlash

Making an arcade racer like CTR

I always liked playing both Mario Kart (the most was on DS) and Crash Team Racing. There's just something fascinating with the mechanics of the game. I could play it endlessly, despite a small number of different circuits. Actually I like racers in general. Two years ago I made a racer looking like Outrun, which is another type of game which I loved as a child (at a time where games didn't yet have a defined standard, so it was OK to just play to hit the road and explore environments, without princess to save, big boss or other deadly stake). Link: https://itunes.apple.com/us/app/highway-runners/id964932741?mt=8 But still, back to Crash Team Racing, I always wanted to make my own clone for fun, and I gave up due to lacking physics knowledge (and free time). This remained a dream though, and this time I committed to it harder, and learned, fiddled with every concept until I grasped it. It started with an inspiring video about Space Dust Racing. I think that's the one mentioned everywhere when it comes to developing an arcade racer. I think I kinda knew that it was lacking a lot of concepts that I'd eventually have to fiddle with, but many people were saying that the theory was alright, so I started. I also created a topic, which I'll now turn to a blog: Anyway as with many things the very hard part was the beginning. It's amazing when I think about how at first I was unsure about everything. About how I had to swallow my ego and realize that I wasn't able to implement a simple spring correctly, or to understand the true implications. Well I can say that I still don't truly understand everything, but it's enough to get what my car does and make it do what I want so so this blog may just start with a common and sweet "Believe in yourself" claim I hope to develop it into a fully playable game (homebrew quality though), focusing on the mechanics, and detail here some specific algorithmic areas. I'm not sure yet of the final form, maybe I'll want to get as close to the CTR as possible. Maybe I'll go for something else and think about special challenges that I could bring to the table. Here's how it looks for now Not playable demo yet, but feel free to leave your impressions, suggestions, and anything that you'd like to see in such a project CarGame-v2.mp4

Brunni

Brunni

I'm going for basic.

Howdy! I am not some super pro programmer (or English writer it seems) but I've been around a bit. I keep going through little bursts of motivation and then nothing and then again and then nothing 🤣. I started again with a tower defense and that's sat chilling at the moment now. I'm waiting a few new art pieces and will be doing an update over weekend so instead of completing stopping everything I decided to mess around and make something else. I think going for basic things are cool for now.. The dream one day is like ultra pro skillz RPG legendary blah blah something cool... but I don't wanna get started on something and never see the end of it cuz of whatever reasons.. Althought this latest humble bundle game art bundle has got me thinking about RPG's again.. I'm currently now making a 'basic' space shooter. I figured I'd write a little 'progress' post and write words about stuff to do with what I'm doing.. Things to do: Controller Setup (not game controls, like a foreman controller) Main Menu How To Play Play Screen (Ship Select) You Lose Screen Player Sprite (Decides sprite Subimage) Player Movement Player Shoot Enemy Spawning (Start with 1 type) Bullet Collision Enemy Death Effect Score System Powerups Lives/Health System Shields — remember frogger/water collision x2 Bosses Wave Counter Wave Countdown Game Background(s) Splashscreen Sound Effects Game Font I made myself this list because I like making lists and then going back through them with the strikethrough. Feels so cool.  I can already cross off the menu stuff now because I've actually done that before writing this but yeah figured I would do a start to finish posting thing whilst making space shooter. I have made space shooters in different programs many times. It always come to the point where I'll meet some one/people and we'd get started and I'll go through the motions of making a prototype and then their Old Aunt would fall through the Wifi into the pond by the horses and then get dragged by Megaman into an arena of gladiators so they've gotta go barter for freedom or some excuse like that and things wouldn't get done. Then I found Kenney.nl and I've got no need for not 'getting things done' at least to the point where I can have a fully functioning game and then communicate with people "Hey, this is my idea, this is what I've got.. would you fancy drawing some awesome stuff to make it much better looking?" or even one day pay people to do it (hmm bit of a stretch but possibilities..)   So yeah here are some images just showing menu stuff, (I've learnt recently that I don't put any effort into making a button look like a button, I mean it looks nice because I go through finding a 'good' font (in my eyes) but then I forget that it just looks like a word when I expect people to click on it... so we all learn things new!) But here:   To be a really cool title screen!! To be a really cool How To Play Screen!! (Going to have ships flying around in background randomly.. maybe to the extent they shoot each other.. Maybe I dunno)) To be a really cool ship select!! (3 types of ship but they also have 4 possible colours -- going to make colour randomly chosen once you've picked ship type)

CyberFlash

CyberFlash

 

Adding Code to the Questionnaire, Elevator, and Key Cards

Questionnaire: So far, the data from the questionnaires the player fills out at the end of each level is sent to a new CSV file. In the future, more data will be sent to the CSV file such as the current time so we will know how long the player spent playing the previous level. This information will give us insight on the player's sense of ownership and/or agency. For example, if they take a long time to complete a level with many dangerous elements, it's likely they have a sense of ownership over their avatar. The script entitled SliderValue updates a text component for each questionnaire question to display its associated slider value. Those text components are what the script "SubmitButton" is sending to the CSV file. Elevator: Currently, the initial two elevators have a script titled "elevator" attached to them that will play an "up" or "down" animation if the player presses a button (or if the space key is pressed for testing on a PC). However, the elevator at the end of the main hallways goes to more than two floors in an unplanned order. Therefore, there are too many possible combinations for animations to be used and another script will be made involving the elevator model increasing its Y position to various heights as specific buttons are pressed. Key Cards The script titled "KeyCard" is attached to the escape pod. When a key card asset collides with the escape pod's collider, the key card will disappear and the questionnaires set as active. - Kristen

DATT3701Group

DATT3701Group

 

Battle Gem Ponies DevLog #196 (Showcase Dreams)

Can you picture it...? Yotes Games, out there among the other young hopefuls, trying to convince anybody walking by to give this little pony RPG a shot. By all means, it outta do as great as it did at Orlando Overdrive but with a much bigger crowd over the span of 3 days instead of 1.

    Serious planning has begun, so far it's only been preemptive measures and bookmarking things to come back to later. Now I'm getting down the fine details of everything I need to know, do, study, and purchase in order to make the most out of this Magfest trip.

More on yotesgames.com

Yotes Games

Yotes Games

 

Getting Back In To It Card Game Day 2

So I messed about with my card game again today for a couple of hours. I am happy to say it went well I added two new game modes Addition and Subtraction which took all of about 10 mins. I added some options so you can choose the highest number card(1 - 13) amount of decks(1 - 13) I cheated a bit on the decks as I just used the menu for the highest card number. Adding in subtraction made me realise I needed negative numbers which wasnt a problem till I realised the - wasn't showing up. This caused me a headache for quite the while . Finally after an hour of changing fonts and what not making sure it wasn't something stupid I went back to my text rendering code... This is where I found a massive mistake (bmap.rows - glyph->bitmap_top) / fontSize, with that line. In my head bmap.rows - glyph->bitmap_top would give me a nice floaty number. Instead it was giving me a vary large unsigned(as that is what bmap.rows and glyph->bitmap_top return. A quick change and bang we were back in business! ((float)bmap.rows - (float)glyph->bitmap_top) / fontSize, magic! I then decided I had a few spare mins so i put in a win screen that congratulates you if you get 0% or 100% right flashy colours included.

Gooey

Gooey

I Am Overburdened, saving my soul

Hello everyone, So much time has passed. I’ve been away from my online life and making games for months. Thanks to some new opportunities it looks like the time has come for me to return to active development again And what better way to restart my venture than putting out new updates for my games I will share some details about my short term plans soon, but I’m devoting this entry to a long-overdue I Am Overburdened update! Update Version 1.2.0 is live and the highlight of it is the save-game feature! Besides this one major addition, it is mostly a bug-fix and tweak build. Save & Exit Finally the game can be suspended in the dungeon and continued later. Since a full play-through is relatively short plus I Am Overburdened is primarily a rogue-like and save-scumming would undermine this core idea so only one save slot exists. Of course more could be added with slots only having a continue option if there are genuine requests for it, but I think the game works well this way. This is more like a convenience feature to be able to stop playing at any point you wish and finish the run when you have the time to spare. The pause menu had to be reorganized a bit, since it was already crammed. As you can see it’s cleaner now and the last option saves and closes the game. I would like to create a more technical post too about this specific feature. Kind of like a tutorial about aspects of save systems. Let me know if you are interested! Immediate (Save &) Exit The immediate exit hot-key was remapped from F10 to F9. Sorry about this change, it was a necessity (os/platform reasons), but as a bright side it also supports saving the game. So now if you hit F9 during play and the game could be continued (e.g.: the player is not dead ), the state will be saved just like when saving and exiting using the pause menu. This change is already reflected in the input guide. Pesky bugs I’ve been working on the game on and off in short bursts in the last months and alongside with the community I discovered some problems too. I fixed quite a few things so I’m simply going to list them: Few items and their related skills could cause a crash under super specific circumstances. It’s not likely many of you run into these issues, but if your play was interrupted by a crash I’m sorry.
Certain item skills with persisting effects (e.g.: Fear, Cripple) could get stuck or be triggered on recently summoned/resurrected monsters in rare cases. These were not visible, but could affect how well you did, so my apologies for the occasional unfair (de-)buffs.
The positioning of hallucinations from toxicity effects (e.g.: Toad monsters, poison in potion) were not correctly randomized. These hallucinated monsters were always placed in the upper-left quarter of the map, breaking the illusion. Now this is fixed.
A while ago I added item-slot notifications to item pickups and chests when standing nearby. It did not occur to me though, that with this modification the treasury pickups and chests triggered unnecessary ones too. Oops, fixed!
  In balance With this update balance tweaks found their way into the game too. There were still some complaints regarding this aspect, so I made normal mode a tad bit harder and nightmare difficulty a tiny bit more forgiving. These are not substantial changes, only slightly affecting the pickup and chest spawn rates. Another extra is “near death” detection. Simply put if you end up in a really bad situation at some point, the game tries not to punish you even harder on the next dungeon level These changes are subtle, so they keep the game challenging, but they were introduced to make it more fair at the same time. Boss confusion Some people found the boss level corpses confusing. I don’t know if the new version will work out better (this is not the first time I change this ), but now the number of corpses (below the one serving as the story hint) are tied to the unlock progress of the boss entry in the monster book. I know some other unlocks still need more and better hints too. I’m going to work on these problems in the near future… Am I still alive? Yes, pretty much. Due to personal and financial reasons I had to put full-time game development on hold for a long while, but I’m back now and I will be working on my projects in the upcoming months. Before I vanished from the face of the INTERNETZ I teased possible ports and a bigger content update for I Am Overburdened. These are not forgotten and progressing well In a week or two I will reveal more details about my plans. Until then, have a fun-filled time.
Thanks for reading and take care!

Spidi

Spidi

The autopsy of Crazy Chicken..

Just to start off with... I have this underlined fear that I've missed a part of the challenge that says "Must be a Frog" 🤣, But howdy! I quite liked making this little game. I first thought that it was going to be well complicated to do and then I really thought about it and it was simply 'collision' and 'movement' really... (Just FYI this is done via Game Maker Studio but NOT drag & drop, actually coded -- Don't know if that matters) and so I began to crash cars into this small Chicken Icon.. and I did actually miss out on a detail from the challenge actually...  "Must maneuver the character across obstacles, moving and stationary" -- I specifically missed the 'and' so I'd made a working version with 3 bits of road and cars going left n right, I'd messed with speed a bit to try and find a decent 'balance', I was thinking to myself about 'How would I do something like the logs from frogger?' and 'Its okay, I'll submit just with Cars and then try to do an update with a water area or something' so upon 'finishing' I reread everything as a checklist and realized that you actually need to have moving obstacles.. I thought it was over! lol The water and boats bit wasn't too bad though once I started thinking about it. (I am now some super pro coder so there's probably much better methods that I am yet to learn) I've gone with the approach that IF the chicken is touching a water tile and NOT touching a boat, die. Kinda thing.. I first tried to add this in reverse as in, IF the water is touching the chicken and not a boat but it just wouldn't register, maybe because there's multiple water tiles or multiple boats or it just didn't want too but the chicken accepted it! And i'm really glad it did because genuinely last night I was actually lay awake for a bit thinking about the old frogger with logs... The boats I used are actually from a pirate pack from Kenney Assets and its like a 'bare' pirate ship.. I don't have mad skills with graphics and the challenge didn't mention having to draw so i went with it. I hope that's okay! I reckon I might need to slow down the boats a bit and maybe add more cars... but this is my nemesis right here... "Balance". I'm trying to think about what went wrong and what went right, it kind of all went right at the moment.. I mean I don't think it was an overly complicated process and if you break it down into its core mechanics, Move, Collide, Die, then add Timer, Then add points and/or point conditions. I made it so if you have 15 seconds or more you 'get' 200 points, 10 seconds or more 100 points, else you get 50, The score doesn't really do anything or go anywhere but it works. I hope that meets the requirement for a score system and I don't actually use a score variable. I was thinking about just taking the remaining time and multiplying by 10 and then that is your score but I opted for the 3 set scores instead. I know how to do both I just chose the timed conditions (Which could also work with a point system and you use time conditions to give a 'bonus' either points equal to the value of remaining time or if you have 10 seconds left get 10 points etc etc...  I don't really do the whole bloggy thing much so I end up just writing more words than are necessary and I'm not sorry nah kidding, Peace out! -- how do you end a blog though? lol

CyberFlash

CyberFlash

Frogger GameDev Challenge - Part 4 - Frog Jump

I haven't touched this project since my last update on October 24 2018, motivation is a bit shot with this one... but I'm still going to try to complete the challenge. This project is really just an excuse for me to try out Unity as I've never used it before. I've spent a few days in the engine and must say it's pretty straight forward and thanks to @lawnjelly for helping me out with a few questions I had. I did a quick animation for the frog jump in Blender, then loaded it into Unity, and added in the movement to work with parts of the animation. Nothing outstanding animation wise but it will work for now. Movement will stay 4 directional with animation lock. I'll need to edit the move value once I figure out spacing. GIF Below: Later today I'll workout my "game plan" for how to put everything together then post back. I haven't really consider scales yet for objects, or environment textures. Anyhow, that is all for now.

Rutin

Rutin

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!