About Store Forum Documentation Contact
Donations:
327$/mo



Post Reply 
Building Placement RTS
Author Message
NewBorn Offline
Member

Post: #1
Building Placement RTS
Hello everyone !

I saw on this forum a TowerDefense game here :
http://esenthel.com/forum/showthread.php?tid=6235

I was trying to run it/play around with, but after resolving the compilation error, the building placement system doesn't work properly.

The first Turret I try to place work perfectly, the others, it's just random ..
Here is a video that can explain better :




After spending some time on it, i still can't figure it out.
You can download the project, if one of you have time (it's a small one wink) or here is the code i think it's responsible of it :

Code:
Turret* Turret.Create()
{
   ObjectPtr  tempParams=UID(3249259405, 1294192879, 2507658368, 1464910172); // get turret object parameters  
   // Every Turret points to the same mesh-instance. We need to duplicate the mesh so that it's unique for each Turret.
   ObjectPtr newParams;
   MeshPtr newMesh = new Mesh();
   newMesh->add(*tempParams->mesh());  
   // Copy our material param too
   MaterialPtr newMat = new Material();
   newMat = UID(2213835078, 1185514479, 1447066557, 906687580); //tempParams->material(); // get the material from the .obj, assign to new material
   //material = newMat; // Change pointer to that material
   // Apply all the duplicates to the new ObjParamsPtr
   newParams = tempParams;
   newParams->mesh(1, newMesh);
   newParams->mesh()->material(newMat);
   // Create a new Turret in the world manager and return the pointer to that new Turret object.
   Turret* turret;
   if (Game.Obj* obj = Game.World.objCreateNear(*newParams, Matrix(newParams->scale(), Vec(0,0,0)))) // create new object at position and give objects default scaling
   {
      turret = CAST(Turret, obj);
      turret->actor.group(AG_TURRET);
   }
   return turret;
}
Code:
void Turret.UpdateConstruction()
{
   // Construct the turret, part-by-part
   if (m_Constructed >= m_PartConstructTime)
   {
      ++m_PartsShown;
      m_PartsFlagged |= IndexToFlag(m_PartsShown); // Add the next part to the current flags using "binary or" (draw: part1 -> part1 + part2 -> part1 + part2 + part3 -> ...)  
      m_Constructed = 0;
      // Mask will be set just before drawing the turret (see drawPrepare())
   }
   // Last part has been made visible; turret is now complete. Replace with proper turret (2 parts, skeleton, ..) and go to next state
   if (m_PartsShown == Part8) // LAST PART IS VISIBLE (Is there a clean way to get the amount of elements in an enum?)
   {
      ObjectPtr tempParams=UID(1580207742, 1152603128, 734962056, 2386524293); // get turret object parameters

      // Replace the current mesh
      mesh = tempParams->mesh();

      // Create the skeleton
      Skeleton* newSkel = new Skeleton();
      newSkel = tempParams->mesh()->skeleton();
      skel.create(newSkel); // cskel will be used to handle the rotation of the turret-top

      // Add the skeleton to the mesh
      mesh()->skeleton(newSkel);
      
      // Set up the actor so we can click on the turret and get/set params
      actor.create(*tempParams->phys());
      actor.group(AG_TURRET);
      actor.obj(this);

      m_CurrentState = STATE_BUILT; // Turret is constructed, and final new turret has been initialized: Go to the last state
      
      InitParticles(); // Initialize particles
   }
   m_Constructed += Time.rd(); // Increment construction time for next mesh part
}
Code:
Bool TurretManager.PlaceTurret()
{
   Turret temp;
   // This is the first time we create a turret. Make one right away.
   if (Turrets.elms() == 0)
   {
      // Create a turret (uses ObjCreateNear)
      temp.Create();
   }
   // Only create a new turret if we didn't have one (unplaced) already
   else if(!Turrets[Turrets.elms()-1].GetState() == STATE_BLUEPRINT)
   {
      // Create a turret (uses ObjCreateNear)
      temp.Create();
   }      
   return true;
}
Code:
Bool TurretManager.UpdateTurretPlacement()
{
   if (Turrets.elms() && (Turrets)[Turrets.elms()-1].GetState() == STATE_BLUEPRINT)
   {
      // If we just convert the Mouse screen position to world position, it will be on a tilted plane (since the camera is tilted).
      // We cannot use this world position as the position for our new turret.
      // We cast a ray from before our mouse position in world space (mousepos - direction of screen) to behind (mousepos + direction of screen)
      // If we hit the terrain, that's where we place our turret
      Vec mousePos = ScreenToPos(Ms.pos());
      Vec start = Vec(mousePos - ScreenToDir(Ms.pos())*10), // starting position of ray
            end = Vec(mousePos + ScreenToDir(Ms.pos())*100); // ending position of ray

      PhysHit phys_hit; // phys-hit object for receiving hit parameters if any
      
      if(Physics.ray(start, end-start, &phys_hit, IndexToFlag(AG_TERRAIN))) // if ray hit the terrain
      {
         // If the turret that we have selected is a blueprint
         if (Turrets[Turrets.elms()-1].GetState() == STATE_BLUEPRINT)
         {
            m_MouseHoveringLocation = phys_hit.plane.pos;
            Turrets[Turrets.elms()-1].mesh()->material(m_OriginalTurretMat); // Set turret material to original one
            
            // We can NOT place this turret on the road (check material of terrain on "pos". pos is on a horizontal plane)
            // We check on a plane because for each point on that plane is only one corresponding point on the heightmap. there's no need for the Y(up)-value
            MaterialPtr clicked = Game.World.hmMaterial(m_MouseHoveringLocation.xz());
            if(clicked.id() != UID(2786128996, 1138576899, 2137332655, 3258567423))
            {
               m_DrawUnplaceableLocations = false; // Stop drawing where we can't place the turret
              
               // Player has clicked the RMB, place the turret
               if (Ms.b(0)) (Turrets)[Turrets.elms()-1].SetState(STATE_UNBUILT);
            }
            
            else // Turret can not be placed
            {              
              Turrets[Turrets.elms()-1].mesh()->material(m_BlockedTurretMat); // Change colour of the turret to red
            }
            
         }
      }
   }
   return true;
}

Thanks for your time
12-14-2015 06:54 PM
Find all posts by this user Quote this message in a reply
Tottel Offline
Member

Post: #2
RE: Building Placement RTS
Hi there!

I made that project a long time ago (when I was still fairly new to programming). There are many things I don't remember from it, and many things I would probably do different now. in any case, I'll help with what we have here! smile
In the near future, I hope to bring out some more step-by-step tutorials for programming in Esenthel.

First of all: I am on my home PC and messed up my installation of visual studio 2015 (I had a couple of different versions installed and uninstalled those to save space on my Hard Drive.. Don't do that, really.. I can't get it to work even after a full reinstall). So, I can't compile the project.

Secondly: Since I can't compile, I need to see the video but it's set to private. Could you change the accessibility to public/ or direct link please?
12-14-2015 09:34 PM
Find all posts by this user Quote this message in a reply
NewBorn Offline
Member

Post: #3
RE: Building Placement RTS
Hey,
Yeah I know it's you, thanks for you share !grin
I had a system that worked (a bad one), but i didn't really like it, so i decided to check your source, see how it was going.
The video is on public now, you should be able to see it.

ps : I did the same with visual studio ... Terrible idea, I feel your pain bro' ^
12-14-2015 11:04 PM
Find all posts by this user Quote this message in a reply
Tottel Offline
Member

Post: #4
RE: Building Placement RTS
I checked it just now and figured out the problem. I'm not sure how that stayed in there for so long, as it is a serious issue.

In TurretManager::UpdateTurretPlacement, there is a check to see if the mouse button is pressed.
Code:
if(Ms.b(0)) ..
This should be:
Code:
if(Ms.bp(0)) ..

After clicking on the GUI, I eat the mouse action so it doesn't also register as a click for the turret manager. However: Ms.b is true for EVERY FRAME that the button is down, so the eat() is useless. Changing to Ms.bp fixes this as it will be set to false again right after clicking on the GUI.

Also, there is a crash when you close the application. In the Turret Save/Load functions: Don't save/load m_Target. That was a very silly thing to do and should not be there.
12-15-2015 10:00 AM
Find all posts by this user Quote this message in a reply
NewBorn Offline
Member

Post: #5
RE: Building Placement RTS
You're right about it, serious issue i didn't pay attention. But it doesn't solve it for me.

I will spend more time on it this night. For the crash, I don't use them for now theyr are just here to let me compile properly ^^
12-15-2015 12:27 PM
Find all posts by this user Quote this message in a reply
Tottel Offline
Member

Post: #6
RE: Building Placement RTS
Here, try with my version. I've made some more changes to UpdatePlacement() too. It's nothing spectacular, just a bit cleaner and possibly more correct.

https://www.dropbox.com/s/lfmlzu54xdrhgu...se.7z?dl=0
12-15-2015 01:16 PM
Find all posts by this user Quote this message in a reply
NewBorn Offline
Member

Post: #7
RE: Building Placement RTS
It works perfectly thanks to you. I didn't have time to check it in depth, so I still don't know why it wasn't working for me (even after changing Ms.b to Ms.bp), I will look into it tomorrow.
Big thanks to you dude, still pretty new with esenthel, they are some thing that I need to work harder smile
12-15-2015 10:25 PM
Find all posts by this user Quote this message in a reply
Post Reply