Adam's Lair Forum

game development and casual madness
It is currently 2018/10/22, 19:31

All times are UTC + 1 hour [ DST ]




Post new topic Reply to topic  [ 22 posts ]  Go to page Previous  1, 2, 3  Next
Author Message
PostPosted: 2018/07/12, 09:51 
Novice Member
Novice Member

Joined: 2018/06/17, 19:09
Posts: 11
Role: Hobbyist
Thanks! But am I correct that there is no way to attach a component to a gameobject without activating the component?


Top
 Profile  
 
PostPosted: 2018/07/12, 12:08 
Forum Addict
Forum Addict
User avatar

Joined: 2013/09/19, 14:31
Posts: 880
Location: Italy
Role: Hobbyist
Simply set to inactive before adding it

Code:
MyComponent cmp = new MyComponent();
cmp.Active = false;
myGameObject.AddComponent(cmp);

_________________
Come on Duality's Discord channel. We have cookies! :mrgreen:


Top
 Profile  
 
PostPosted: 2018/07/21, 19:35 
Novice Member
Novice Member

Joined: 2018/06/17, 19:09
Posts: 11
Role: Hobbyist
Why doesn't this work? It works for the first time when called but it seems that the MapManager stays active and subsequent calls won't do anything. Also, I have this small map and still CPU usage is around 30% and GPU over 90%. Why is this?
Code:
namespace TileMap_Test3
{
    public class MapController : Component, ICmpUpdatable
    {
        void ICmpUpdatable.OnUpdate()
        {
            if (DualityApp.Keyboard[Key.I])
            {
                AddMapManager(10);
            }
            if (DualityApp.Keyboard[Key.K])
            {
                AddMapManager(20);
            }
            if (DualityApp.Keyboard[Key.L])
            {
                AddMapManager(30);
            }
        }


        public void AddMapManager(int mapSize)
        {
            MapManager add = this.GameObj.GetComponent<MapManager>();
            if (add == null)
            {
                add = new MapManager(mapSize);
                this.GameObj.AddComponent<MapManager>(add);
            }
            else
            {
                add.MapSize = mapSize;
                add.Active = true;
            }
        }
    }
}


Code:
namespace TileMap_Test3
{
    [RequiredComponent(typeof(Tilemap))]
    public class MapManager : Component, ICmpInitializable
   {
        private int mapSize = 0;


        public MapManager(int size)
        {
            this.MapSize = size;
        }


        public int MapSize { get => mapSize; set => mapSize = value; }


        public void OnInit(InitContext context)
        {
            if (context == InitContext.Activate)
            {
                this.GameObj.GetComponent<Tilemap>().Resize(MapSize, MapSize);
                this.Active = false;
            }     
        }

        public void OnShutdown(ShutdownContext context)
        {
        }


Top
 Profile  
 
PostPosted: 2018/07/21, 20:10 
Forum Addict
Forum Addict
User avatar

Joined: 2013/09/19, 14:31
Posts: 880
Location: Italy
Role: Hobbyist
That's a bit of a weird code you got there..

First of all, you can't just call
Code:
this.GameObj.AddComponent<MapManager>(add);


from your class and have everything set up properly, the RequiredComponent attribute is there for editor's use only; when you build Components or GameObjects directly by code, you have to provide all the necessary steps
i.e. in this case, you should add a Tilemap first, since it's required by your MapManager component.

Second, although it *should* work on paper, I think that changing your component's Active status inside an Active-change-response event might not work as expected.

Why not just change your AddMapManager call to something like
Code:
public void AddMapManager(int mapSize)
{
   MapManager mm = this.GameObj.GetComponent<MapManager>();
   if (mm == null)
   {
      this.GameObj.AddComponent<Tilemap>();
      mm = this.GameObj.AddComponent<MapManager>();
   }

   mm.SetSize(mapSize);
}

_________________
Come on Duality's Discord channel. We have cookies! :mrgreen:


Top
 Profile  
 
PostPosted: 2018/07/22, 12:35 
Novice Member
Novice Member

Joined: 2018/06/17, 19:09
Posts: 11
Role: Hobbyist
The TileMap is already there so I do not think it needs to be added? Also, as the MapManager component is going to activate when it is added to the gameobject (unless I first make it deactivated), it makes sense to make a constructor for the MapManager, so that I can use the mapSize as a parameter or doesn't it?

Well, I managed to make it work the way I wanted by moving the Active = false to the end of the AddMapManager call, out of the OnInit of MapManager.

Seems that the high CPU and GPU usage only happens when Debugging, but is that normal?


Top
 Profile  
 
PostPosted: 2018/07/22, 14:56 
Forum Addict
Forum Addict
User avatar

Joined: 2013/09/19, 14:31
Posts: 880
Location: Italy
Role: Hobbyist
StrigoiTyrannus wrote:
The TileMap is already there so I do not think it needs to be added? Also, as the MapManager component is going to activate when it is added to the gameobject (unless I first make it deactivated), it makes sense to make a constructor for the MapManager, so that I can use the mapSize as a parameter or doesn't it?

Ah, if you always have your Tilemap Component ready in your scene there is no need to explicitly add it. I thought you wanted to generate everything needed at runtime; and of course, if you feel better having a parametrized constructor feel free to do so :D mine was just an idea, not a to-do.

StrigoiTyrannus wrote:
Seems that the high CPU and GPU usage only happens when Debugging, but is that normal?

It's entirely possible, since while in debug (inside the editor) there is no cap to the FPS so your game runs as fast as possible.

_________________
Come on Duality's Discord channel. We have cookies! :mrgreen:


Top
 Profile  
 
PostPosted: 2018/07/23, 22:51 
Novice Member
Novice Member

Joined: 2018/06/17, 19:09
Posts: 11
Role: Hobbyist
Quote:
Ah, if you always have your Tilemap Component ready in your scene there is no need to explicitly add it. I thought you wanted to generate everything needed at runtime; and of course, if you feel better having a parametrized constructor feel free to do so :D mine was just an idea, not a to-do.


If I want to begin the game with nothing in it, how do I create the initial Scene? Or should I have a blank Scene and add stuff to it? And should the "blank" Scene have a some sort of GameManager component in it at the beginning, which would create everything I need? I mean, can you add anything to a completely blank scene?


Top
 Profile  
 
PostPosted: 2018/07/24, 07:30 
Forum Addict
Forum Addict
User avatar

Joined: 2013/09/19, 14:31
Posts: 880
Location: Italy
Role: Hobbyist
Absolutely yes, though probably it's better to have an "empty" scene with only one component, whose job is to actually build your game scene.
Even better, you could leverage that empty scene to make a nice loading screen (even just a fixed, full screen SpriteRenderer does wonders)

Anyway, this is what I'm doing for my game.. don't mind some of the weird parts such as using a Task or the MainThreadOperations stuff.. that's just me trying things :D

Code:
using System.Linq;
using System.Threading.Tasks;
using BrokenGalaxyNeo.Data;
using BrokenGalaxyNeo.Generators;
using BrokenGalaxyNeo.Services;
using BrokenGalaxyNeo.UI;
using Duality;
using Duality.Components;
using Duality.Components.Physics;
using Duality.Components.Renderers;
using Duality.Drawing;
using Duality.Plugins.Companion.Drawing;
using Duality.Plugins.Companion.Math.Graph;
using Duality.Resources;

namespace BrokenGalaxyNeo.Components
{
   public class LoadingManager : Component, ICmpUpdatable
   {
      private delegate void MainThreadOperation(Scene s);

      private class CompleteScene
      {
         public Scene Scene { get; set; }
         public MainThreadOperation MainThreadOperations { get; set; }

         public void ApplyMTOperations()
         {
            this.MainThreadOperations(this.Scene);
         }
      }

      public TextRenderer Text { get; set; }

      [DontSerialize]
      private Task<CompleteScene> _creatorTask;

      public void CreateGame(GameConfiguration config)
      {
         _creatorTask = new Task<CompleteScene>(() =>
         {
            return PrepareScene(config);
         });
         _creatorTask.Start();
      }

      private float CalculateSystemScore(StarSystem system, Player player)
      {
         float num = system.GetStrategicValueFor(player);
         float den = system.Neighbors.Sum(n => n.Owner == null ? 1 : 2);

         return (num / den);
      }

      private CompleteScene PrepareScene(GameConfiguration config)
      {
         this.Text.Text.SourceText = "Creating map...";
         GameServices.Instance.NewGame(config);

         this.Text.Text.SourceText = "Seeding galaxy with life...";
         foreach (Player player in GameServices.Instance.Players.AllPlayers)
         {
            GameServices.Instance.Map.Nodes
               .Where(n => n.Owner == null)
               .OrderByDescending(n => CalculateSystemScore(n, player))
               .First()
               .SetHomeworld(player);
         }

         foreach (StarSystem ss in GameServices.Instance.Map.Nodes.Where(n => n.Owner == null))
            ss.SetGarrison(new CombatFleet(Player.NotSet, MathF.Rnd.Next(5, 11)));

         this.Text.Text.SourceText = "Building scene...";
         CompleteScene result = new CompleteScene();
         Scene scene = new Scene();

         GameObject ssUI = new GameObject("StarSystemMenu");
         ssUI.AddComponent<StarSystemMenu>();
         scene.AddObject(ssUI);

         GameObject lnkUI = new GameObject("LinkMenu");
         lnkUI.AddComponent<LinkCreationMenu>();
         scene.AddObject(lnkUI);

         GameObject gameUI = new GameObject("GameControlMenu");
         gameUI.AddComponent<GameControlMenu>();
         scene.AddObject(gameUI);

         float centerX = GameServices.Instance.Map.Nodes.Average(x => x.Position.X) * Constants.GRAPH_SCALE_FACTOR;
         float centerY = GameServices.Instance.Map.Nodes.Average(x => x.Position.Y) * Constants.GRAPH_SCALE_FACTOR;

         GameObject camera = new GameObject("Camera");
         camera.AddComponent<Transform>();
         camera.AddComponent<Camera>();
         camera.AddComponent<GameController>();
         camera.AddComponent<PlayerController>();
         camera.AddComponent<GameOverlayRenderer>();
         camera.GetComponent<Transform>().Pos = new Vector3(centerX, centerY, -500);
         camera.GetComponent<PlayerController>().StarSystemMenu = ssUI.GetComponent<StarSystemMenu>();
         camera.GetComponent<PlayerController>().LinkCreationMenu = lnkUI.GetComponent<LinkCreationMenu>();
         scene.AddObject(camera);

         // for debug
         //camera.AddComponent<ProfileRenderer>().DrawGraphs = false;

         foreach (StarSystem ss in GameServices.Instance.Map.Nodes)
            scene.AddObject(CreateStarSystemGameObject(ss));

         foreach (Link<StarSystem> l in GameServices.Instance.Map.Links)
            scene.AddObject(CreateLink(l));

         this.Text.Text.SourceText = "Spreading gases...";
         Pixmap nebulaPixmap = PixmapGenerator.GenerateNebula(256, config.Seed, .25f, new ColorRgba(35, 40, 75).WithAlpha(.25f));
         Pixmap backgroundPixmap = PixmapGenerator.GenerateNebula(512, config.Seed * 2, .5f, new ColorRgba(.1f));

         this.Text.Text.SourceText = "Igniting background stars...";
         Pixmap starfieldPixmap = PixmapGenerator.GenerateStarfield(1024, config.Seed);

         result.MainThreadOperations = (s) =>
         {
            this.Text.Text.SourceText = "Finishing touches...";

            s.AddObject(CreateAOIRenderer(centerX, centerY, config.Width + 10, config.Height + 10));
            s.AddObject(CreatePlane("Background", backgroundPixmap, new Vector3(0, 0, 10), 2, .5f));
            s.AddObject(CreatePlane("Starfield", starfieldPixmap, new Vector3(0, 0, 5), 1, .25f));
            CreatePlane("Nebula", nebulaPixmap, Vector3.Zero, 5, .2f).Parent = camera;

            GameObject dragRenderer = new GameObject("DragRenderer");
            dragRenderer.AddComponent<DragRenderer>();
            scene.AddObject(dragRenderer);

            camera.GetComponent<PlayerController>().DragRenderer = dragRenderer.GetComponent<DragRenderer>();
         };

         result.Scene = scene;
         return result;
      }

      private GameObject CreateStarSystemGameObject(StarSystem system)
      {
         RigidBody rb = new RigidBody() { IgnoreGravity = true };
         rb.ClearShapes();
         rb.AddShape(new CircleShapeInfo(Constants.RB_SYSTEM_RADIUS, Vector2.Zero, 1) { IsSensor = true });

         GameObject go = new GameObject(system.Name);
         go.AddComponent<Transform>();
         go.AddComponent<SpriteRenderer>();
         go.AddComponent<RigidBody>(rb);
         go.AddComponent<StarSystem>(system);
         go.GetComponent<Transform>().Pos = new Vector3(system.Position * Constants.GRAPH_SCALE_FACTOR, 0);
         go.GetComponent<SpriteRenderer>().Rect = Rect.Align(Alignment.Center, 0, 0, Constants.RB_SYSTEM_RADIUS * 2, Constants.RB_SYSTEM_RADIUS * 2);
         go.GetComponent<SpriteRenderer>().CustomMaterial = new BatchInfo(ContentProvider.RequestContent<Material>(@"Data\Graphics\Shaders\StarSystem.Material.res").Res);

         return go;
      }

      private GameObject CreateLink(Link<StarSystem> link)
      {
         Vector2 linkVector = link.To.Position - link.From.Position;
         float linkLength = linkVector.Length * Constants.GRAPH_SCALE_FACTOR;

         GameObject go = new GameObject(link.From.Name + "-" + link.To.Name);
         go.AddComponent<Transform>();
         go.AddComponent<SpriteRenderer>();
         go.AddComponent<LinkController>();
         go.GetComponent<Transform>().Pos = new Vector3((link.To.Position + link.From.Position) * Constants.GRAPH_SCALE_FACTOR / 2, 0);
         go.GetComponent<Transform>().Angle = linkVector.Angle;
         go.GetComponent<SpriteRenderer>().Rect = Rect.Align(Alignment.Center, 0, 0, 5, linkLength);
         go.GetComponent<SpriteRenderer>().CustomMaterial = new BatchInfo(ContentProvider.RequestContent<Material>(@"Data\Graphics\Shaders\Link.Material.res").Res);
         go.GetComponent<SpriteRenderer>().Offset = 1;
         go.GetComponent<LinkController>().Link = link;

         return go;
      }

      private GameObject CreateAOIRenderer(float centerX, float centerY, int width, int height)
      {
         GameObject go = new GameObject("AOIRenderer");
         go.AddComponent<Transform>();
         go.AddComponent<SpriteRenderer>();
         go.AddComponent<AOIRenderer>();
         go.GetComponent<Transform>().Pos = new Vector3(centerX, centerY, 1);
         go.GetComponent<Transform>().Scale = Constants.GRAPH_SCALE_FACTOR;
         go.GetComponent<SpriteRenderer>().Rect = Rect.Align(Alignment.Center, 0, 0, width, height);
         go.GetComponent<SpriteRenderer>().SharedMaterial = null;
         go.GetComponent<SpriteRenderer>().CustomMaterial = new BatchInfo(
            DrawTechnique.Alpha,
            Colors.White.WithAlpha(.2f),
            new Texture(width, height, TextureSizeMode.NonPowerOfTwo, TextureMagFilter.Nearest, TextureMinFilter.Nearest));
         go.GetComponent<SpriteRenderer>().Offset = 1;

         return go;
      }

      private GameObject CreatePlane(string name, Pixmap pixmap, Vector3 position, float scale, float scrollingMult)
      {
         GameObject go = new GameObject(name);
         go.AddComponent<Transform>();
         go.AddComponent<PlaneRenderer>();
         go.GetComponent<Transform>().Pos = position;
         go.GetComponent<Transform>().Scale = scale;
         go.GetComponent<PlaneRenderer>().CustomMaterial = new Material(DrawTechnique.Alpha, Colors.White,
               new Texture(pixmap, TextureSizeMode.Default,
                  TextureMagFilter.Linear, TextureMinFilter.LinearMipmapLinear,
                  TextureWrapMode.Repeat, TextureWrapMode.Repeat,
                  TexturePixelFormat.Rgba));
         go.GetComponent<PlaneRenderer>().Scrolling = PlaneRenderer.ScrollingMode.Both;
         go.GetComponent<PlaneRenderer>().ScrollingMultiplier = scrollingMult;

         return go;
      }

      void ICmpUpdatable.OnUpdate()
      {
         if (_creatorTask != null && _creatorTask.Status == TaskStatus.RanToCompletion)
         {
            _creatorTask.Result.ApplyMTOperations();

            GameServices.Instance.Scene.SetScene(_creatorTask.Result.Scene);
            Scene.SwitchTo(_creatorTask.Result.Scene);
         }
      }
   }
}


So basically in that Scene I only have a Camera, a TextRenderer, and that Component;
the actual gameplay Scene is fully built inside it (PrepareScene method).

Hope it helps :D

_________________
Come on Duality's Discord channel. We have cookies! :mrgreen:


Top
 Profile  
 
PostPosted: 2018/08/20, 10:57 
Novice Member
Novice Member

Joined: 2018/06/17, 19:09
Posts: 11
Role: Hobbyist
Few questions again.

I'm a bit confused when to make a component and when just make a static class or an object that a component uses. Is there some general guideline when something should be its own component or not? Or should basically everything be a component?

I have MapData component, which holds all the information regarding the tiles in a 2d array. The TileMap is generated based on the data in this component. Should the TileData in the MapData contain as little information as possible also, so that it uses less memory. Lets say I have a Desert tile. Should the information in the TileData only be something like int TileType = 5 (which would mean desert in this case) or Char TileType = 'D' and then generate the text "Desert" out of that whenever it's needed, instead of the TileData having String TileType = "Desert"?

Also, thanks for all the replies, they have really helped me get going!


Top
 Profile  
 
PostPosted: 2018/08/20, 16:10 
Forum Addict
Forum Addict
User avatar

Joined: 2013/09/19, 14:31
Posts: 880
Location: Italy
Role: Hobbyist
StrigoiTyrannus wrote:
Few questions again.

I'm a bit confused when to make a component and when just make a static class or an object that a component uses. Is there some general guideline when something should be its own component or not? Or should basically everything be a component?

There is not a right or wrong way to do it, as with many other things, it pretty much depends on your own preference.
Personally, if it's an object that provides engine-related behavior (i.e. implements any of the ICmpInterfaces), then it's a Component; if it's something that multiple objects or entities reference, and does not require ICmpInterfaces, then probably it's modeled as a static object, or at the very least accessed through a game-wide singleton. In all other cases it's a simple object.

StrigoiTyrannus wrote:
I have MapData component, which holds all the information regarding the tiles in a 2d array. The TileMap is generated based on the data in this component. Should the TileData in the MapData contain as little information as possible also, so that it uses less memory. Lets say I have a Desert tile. Should the information in the TileData only be something like int TileType = 5 (which would mean desert in this case) or Char TileType = 'D' and then generate the text "Desert" out of that whenever it's needed, instead of the TileData having String TileType = "Desert"?

Also, thanks for all the replies, they have really helped me get going!

why not use an enum? the small size of an int (or even just a byte, really) with the full expressiveness of a string

_________________
Come on Duality's Discord channel. We have cookies! :mrgreen:


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 22 posts ]  Go to page Previous  1, 2, 3  Next

All times are UTC + 1 hour [ DST ]


Who is online

Users browsing this forum: No registered users and 20 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Jump to:  
cron
Powered by phpBB® Forum Software © phpBB Group