Jump to content
  • Advertisement

Project: unirule

Structures Update, Scripted Events & Development

Sign in to follow this  
Awoken

683 views

Hello GameDev :) 

In this blog I'll be covering
- development life-cycle thus far
- provide an update on dynamic structures
- introduce scripted events.

Development life-cycle 
I think the time has come at last.  What time is that exactly?  Well let me explain... 
A couple months back I was thumbing through my blog series and I was startled.  I noticed that it appeared as though I have been repeating myself for the better part of 4 years, coming up on 5 now.  I wondered if maybe I was stuck in some sort of mental recursive loop or something, forever redoing, rebuilding, remaking. 
Quickly though I realised I was reading the situation incorrectly.  Even though it may seem I've been talking about the same stuff for this long I've come to realise there have been 3 distinct phases this project has gone through and they are:

Experimentation
684993847_Screenshotfrom2015-12-0111_27_26.thumb.png.2ae1524c3e3512e8bb7612c5b848992c.png

At the very beginning when I first started using THREE.js and node.js I played around with them and worked out a rough idea of how to get certain things to work a certain way.  I made different colored boxes to represent different players.  Each client could move one box and node.js would coordinate the movement.  I had also written my first dynamic-wall functions.  I remember they were atrociously slow and the boxes could not move around them.  I learned what ideas were worth perusing and which needed to be scraped.

Integration
Eventually a time came when I felt comfortable enough with my abilities in javascript that I decided I needed start combining many of the different features I had made.  I had boxes that could move around, walls that could be built and eventually I wrote my first function to merge the two,  getting the boxes to move around walls that is.  That too was extremely slow.  Integrating these separate elements gave me a greater appreciation for logic that can be utilised across different applications, if that makes any sense :S.

Stability 

Then in 2016 I decided it was time to kick things up a notch.  I didn't know it at the time, but my first attempt at creating a robust function was probably the best thing to happen for this project.  At the time I just wanted to finally make a function that wasn't going to break on me.  I remember spending weeks tackling all the errors wondering does it ever end?  But after I had that function executing like clock work it dawned on me just how important stable functions are.  Especially if I want a framework for a game that is to be dependable.  So there you have it Stable Integrated Code.

Now of course there has always been a gradual transition from one phase to the next.  And even today I find myself experimenting, after all experimenting can breath fresh life into a project.


Dynamic Structures
I'm incredibly proud to show off my first polished video showing the latest and greatest dynamic structure tool.  In the video, if you're interested, I build a structure from scratch so you can see how user friendly I tried to make it :) 


Scripted Events
I would also like to share with you a video that showcases the my first attempt at a scripted event.  Now the video is the one I currently use on my project page updated earlier this month. If you haven't checked it out please do so.  You can skip the first 25 seconds or so..

It's an idea I came up with a few months back for promoting the project.  I've been getting to thinking that since these simulin live in a simulated world that I really want to play on that idea.  So this is just one example of a scripted event.  But there is no reason why the player can't also be informed the simulated nature of the world.  For instance, the world is much to small come game time for there to be tons for wildlife roaming around,  But I could have intermittent scripted events where wildlife materialise and stampede across a plain only to de-materialise once again.  And I have many more ideas for scripted events.

Conclusion
I feel confident enough now and think it's time to move one full foot to game development.  I've talked about transitioning in the past but I think enough is enough with the framework.  I will still work on it until it has fully incorporated all the features I want.  But lately I've been getting more and more excited to just get on with the game.


Parting thought, If I didn't have somebody somewhere to share all this with I would never would have come this far.  Thank you all for being a supportive and curious bunch! :D 

Sign in to follow this  


0 Comments


Recommended Comments

I really enjoy seeing the progression on this. :) Good work!

Share this comment


Link to comment
11 hours ago, Rutin said:

I really enjoy seeing the progression on this. :) Good work!

Right now is a special moment in the time-line for my version of the game. 
I have attempted the game many times in the past and would always reach a plateau highlighting the shortcomings of my vision.  Instead of moving on I have repeatedly chosen to go back to the drawing board.

I have always wanted a frame-work that would allow for many players to log into the same website, access the same 3D world and play a game with each other involving thousands of individual people.  I had 10,000 people as the magic number in mind.  I had no idea if I was going to reach that goal. ( Although figuring out how to incorporate Rodrigues' rotational matrix was a huge confidence boost early on ).
Visually I know it doesn't have that much juice as compared to others in the same category( indie, world terrain, etc.. ). However, what it lacks visually I hope to make up for in game.

Years ago I had asked the community if they knew of an existing engine that could do what I needed, and I remember khawk writing back something along the lines of 'so you want someone else to write your engine for you hey?' or something to that effect.  I was so honoured that the guy who ran the site even took notice.  That was a huge motivator for me at a time when encouragement by others in the blogging section was sparse.

Thank you very much Rutin :) 

Share this comment


Link to comment

I'm glad you've found that motivation! Khawk seems like a very standup guy, and it's nice to see engagement. I know on one of my art posts he replied, it was a 2d small painting of an older guy,  but I was struggling a bit to push forward and I'm still going!

I personally enjoy seeing all the talented people like yourself sharing their projects and watching them grow with every update.

I've personally found that a lot of people get lost at some stage and just abandon their projects. It's a hard thing to do when you factor in all the skills sets you need, self discipline, motivation, and time. I applaud anyone sticking out game development and creating whatever projects that interest them.

Share this comment


Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Advertisement
  • Advertisement
  • What is your GameDev Story?

    In 2019 we are celebrating 20 years of GameDev.net! Share your GameDev Story with us.

    (You must login to your GameDev.net account.)

  • Blog Entries

  • Similar Content

    • By FFA702
      I'll jump straight into the context:
      I have a 2D grid map stored into a simple 2D object array. Every object and agent exists on this 2D array (so their positions are discrete and binded to their location on the array). I'm expecting agents to move quite a bit, so the grid is dynamic in nature. The game itself is fully deterministic and discrete operations based, the goal being to make it multiplayer portable (with the lockstep method). I'd like to populate the map with large impassable structure, concave and convex, such as buildings and lakes.
      These agents are rigged with an FSM for decision making. I wish them to be able to act on these decision in believable way, and one of these challenges is to allow them A > B navigation that works and looks believable.
      I'd like to have as much active npc in the world as possible, and right now the biggest hurdle is finding the right path finding algorithm. I'm not sure about my update tick budget, but right now I'm thinking anything reliably less than ~500ms would be acceptable (I'm making the game "turn based" for testing purposes, and wish to later make it real time using a good amount of linear interpolation on the display layer).
      At this time I have a 100x100 map for testing, with hundreds of agents (with almost fully implemented AI, lacking path finding and collision detection), and a tick time of 10ms.
      What pathfinding algorithm and implementation would suit this situation ? I know A* would be okay-ish, but since the grid changes every ticks, and the number of agents is quite large, I'm not sure it would be the best (short of computing the path once and evaluating if a collision occurred each travelling steps, then recomputing it). I'm trying to keep everything simple, and I am willing to reduce the scope of the simulation regarding the number of active agents to do so. Any idea or advice ?
      FYI, I'm not sure if I'm doing this right, but every agent has a command list, which contains a list of "todos" populated by the fsm and ran each ticks (the first command in line). The pathfinding algorithm would be contained in the command object, so the flexibility is quite large (it could be broken down into smaller steps).
    • By Satyrant
      Hello GameDevs,
      Context:
      I would consider myself a novice and am working on a RTS working project to practice my C++ and game programming skills. It is a tech demo to practice optimisation in the future, I am aiming to have it contain as many basic agents with rudimentary AI that can be controlled and optimising the system to allow for the most amount of these agents while still maintaining 60 FPS as a benchmark.
      Problem:
      I am aiming to implement Flow Fields for pathfinding and have managed a basic implementation with Flow Field follow and no steering behaviour as of yet. However, I have run into a design decision I am unsure of ,and was wondering if anyone could advise me of some potential architecture choices. When implementing Goal-Based Vector Field Pathfinding, what would be the most efficient way of keeping the flow field data when manipulating many clusters of agents?
      Current Thinking:
      It seems inefficient to recalculate per cluster of agents unless a new goal is set for them, so I would have to maintain the flow field at least up until the goal is met. I was considering creating a data structure like a map, that indexes each generated and maintained Flow Field based on whether some agent clusters are still trying to reach that goal, after which I would terminate. Then update each cluster every 1 to 2 seconds in order to not throttle the cpu. Currently the algorithm for updating the Flow Field is rudimentary and not optimised. Each Flow Field currently takes up about 11MB (31x31 for testing purposes) of memory and I am concerned that I could run into a scenario that could take up a lot of memory if enough particularly small clusters of agents are all trying to move across the map, especially when the map would be bigger.
      Question:
      Could you provide any advice on potential architecture choices that would be ideal in this Scenario or direct me to some implementations/papers?
      I have so far only managed to find implementations and demos of Flow Fields only with 1 goal and 1 cluster in mind, but not when put into practice in a real game with multiple clusters of units simultaneously moving around the map.
      Many thanks.
    • By assboot
      I've recently implemented runtime lua scripting in my game engine, and am currently just polishing it. During the polishing I noticed that when I do this one specific thing in lua, the stack gets overflown. I'm doing the memory management my self for the lua stack, and I'll code dump it at the bottom of this post in case it has any relevance.
      To give some context, I'm using the __index and __newindex metamethods for reading and writing fields in the user data "LuaEntity", which is basically just a wrapper for the Entity class in my engine. This is somewhat what the __index and __newindex functions look like in C++
      static int32 __index(lua_State *ls) { string _index = lua_tostring(ls, -1); if (lua_isuserdata(ls, -2) && !lua_isnil(ls, -2)) { auto _entity = (LuaEntity*)lua_touserdata(ls, -2); if (SceneManagement::GetEntity(_entity->id)) { _entity->UpdateProps(); if (_index == "x") { lua_pushnumber(ls, _entity->x); } else if (_index == "some_field") { lua_pushnumber(ls, _entity->some_field); } else if (_index == "some_other_field") { lua_pushnumber(ls, _entity->some_other_field); } else /* if reading a non-default field */ { lua_getuservalue(ls, -2); WZ_ASSERT(!lua_isnil(ls, -1), "Tried reading unitialized field '" + _index + "' in '" + _entity->name + "'"); lua_pushvalue(ls, -2); lua_gettable(ls, -2); lua_remove(ls, -2); } return 1; } } else { lua_pushnil(ls); } return 1; } static int32 __newindex(lua_State *ls) { string _index = lua_tostring(ls, -2); if (lua_isuserdata(ls, -3) && !lua_isnil(ls, -3)) { auto _entity = (LuaEntity*)lua_touserdata(ls, -3); if (SceneManagement::GetEntity(_entity->id)) { if (_index == "x") { WZ_ASSERT(lua_isnumber(ls, -1), "Expected number value"); // .. Set "x" to the value top on stack } else if (_index == "some_field") { WZ_ASSERT(lua_isnumber(ls, -1), "Expected number value"); // .. Set "some_field" to the value top on stack } else if (_index == "some_other_field") { WZ_ASSERT(lua_isnumber(ls, -1), "Expected number value"); // .. Set "some_other_field" to the value top on stack } else /* if writing a non-default field */ { lua_getuservalue(ls, -3); lua_pushvalue(ls, -3); lua_pushvalue(ls, -3); lua_settable(ls, -3); lua_remove(ls, -1); } _entity->UpdateProps(); } } return 0; } }; This all works fine as in I can read and write both the default but also user-made fields in the entity table without a problem like this:
      local function update() -- A callback function that's invoked each frame from C++ local entity = entity_get("some_entity") local old_x = entity.x local old_y = entity.y -- .. do stuff if (old_x ~= entity.x or old_y ~= entity.y) then -- .. entity moved end end This keeps the memory steady with no problems, however, If I were to do the same thing but instead of storing entity position in old_x and old_y I would store it in a table called old_pos like this:
      local function update() -- A callback function that's invoked each frame from C++ local entity = entity_get("some_entity") local old_pos = { x = entity.x, y = entity.y } -- return values 'x' and 'y', pushed to the stack in C++, doesn't get garbage collected - memory fills up -- .. do stuff if (old_pos.x ~= entity.x or old_pos.y ~= entity.y) then -- .. entity moved end end then the values x and y, each pushed to the stack in __index as a return value, seems to not get garbage collected by lua which quickly fills up my stack budget and causes the stack to overflow.
      Here is how I've told lua to handle stack memory:
      struct LuaMemPool { const void *head; const void *tail; const ubyte *headByte; ubyte *current; LuaMemPool(void *head, void *tail) : head(head), tail(tail), current((ubyte*)head), headByte((ubyte*)head) { } void Free(void */*ptr*/) { } void *Allocate(size_t sizeBytes) { void *_ptr = current; current += sizeBytes; WZ_ASSERT(current <= tail, "Memory usage overflow"); return _ptr; } void *Realloc(void *ptr, size_t oldSize, size_t newSize) { void *_newPtr = Allocate(newSize); memcpy(_newPtr, ptr, oldSize); Free(ptr); return _newPtr; } int32 Allocated() { return (int32)(current - headByte); } static void *Alloc(void *ud, void *ptr, size_t osize, size_t nsize) { LuaMemPool& _pool = *((LuaMemPool*)ud); if (nsize == 0) { if (ptr != nullptr) { _pool.Free(ptr); } return NULL; } else { if (ptr == nullptr) { return _pool.Allocate(nsize); } return _pool.Realloc(ptr, osize, nsize); } } }; I am aware that I'm not freeing memory.
    • By Vu Chi Thien
      Hi everyone.
      I'm working on a vehicle (more specifically: cars) simulation in Unity3D with a complete drivetrain system of engine, gearbox, differential, and wheels as separate components. Each component will update itself with the torque passing through the system. More specifically:
      The torque starts from the engine initially, then through the clutch and gearbox to the differential, where the torque is splinted appropriately to two sides (either active wheels or axle differentials). The wheels update themselves and pass the force to the rigidbody. The feedback torque from the wheels is then passed through the system back the the engine in the next step to determine engine torque for this next step.
      Currently my system is at early step where the engine never stall, the clutch is permanently locked. So the engineRPM is a simple (wheelLeftRPM + wheelRightRPM) * 0.5f.
      I'm trying to simulate the open differential  by splitting the torque 50-50 to both active wheels simply: wheelLeftTorque = wheelRightTorque = engineTorque * gear * 0.5f. 
       
      This works OK when the torque comes from the engine. But in the case where the torque comes from one of the active wheel or outside, for example, when the car is jacked up and one wheel got spun when the engine is not running. In this case, the other wheel will spin the other way.
      I've watched some videos about open diff to be able to understand this. When one wheel is spinning and the diff case is held static, the spider gear that sits in between the side gears of two wheel axle, would spin (because the sun gear that the spider gear is connected to is held static, so it can only spin on its own axis). This rotation of the spider gear transfer rotation of one side gear to the other, making the other wheel spins the other way.
      Mathematically, since wheelSpeedLeft + wheelSpeedRight = 2.0f * CageSpeed, when CageSpeed is 0, then wheelSpeedLeft and wheelSpeedRight must have opposite sign, which illustrates the opposite rotations of the wheels.
      However, that's in term of speed and power flow. Since I'm working with torque, I don't know how the flow of torque going from one wheel to the other in this case. What is the amount of torque that goes from one wheel to the other? How should I model or come up with a formula that covers both cases when torque comes from the engine or from one side, or rather, fully cover the full flow of torque in the diff? The final answer that I need is the amount of torque that will flow to each wheel.
      Thank you very much.
    • By Robotex
      I am currently working on a legacy codebase that was using AngelScript 2.4.1e for its scripting engine and I'm trying to upgrade it.
      After having settled with the compilation errors, one problem that I encountered is that all the scripts have a common function which is called from the application to set an instance of a Game class and that Game class is an interface/wrapper for interacting with the game engine (each script instance is sandboxed).
      Scripts:
      Game@ instance; void SetInstance(Game &in i) { @instance = @i; } Application:
      class Game { private : Game(); public : Game(IScript *); virtual ~Game(); int AddRef(); int Release(); void ScriptLoaded(); // ... }; // Legacy code: r=engine->RegisterObjectType("Game", sizeof(Game), asOBJ_CLASS); r=engine->RegisterObjectBehaviour("Game", asBEHAVE_ADDREF, "void f()", asMETHOD(Game, AddRef), asCALL_THISCALL); r=engine->RegisterObjectBehaviour("Game", asBEHAVE_RELEASE, "void f()", asMETHOD(Game, Release), asCALL_THISCALL); // ... // After upgrade: r=engine->RegisterObjectType("Game", sizeof(Game), asOBJ_REF); assert(r >= 0); r=engine->RegisterObjectBehaviour("Game", asBEHAVE_ADDREF, "void f()", asMETHOD(Game, AddRef), asCALL_THISCALL); assert(r >= 0); r=engine->RegisterObjectBehaviour("Game", asBEHAVE_RELEASE, "void f()", asMETHOD(Game, Release), asCALL_THISCALL); assert(r >= 0); // ... // In Game's ScriptLoaded method context->Prepare(module->GetFunctionByName("SetInstance")); context->SetArgObject(0, (void*)this); context->Execute(); The error that I am getting and being thrown during runtime is "Parameter type can't be 'Game&in', because the type cannot be instantiated." when SetInstance is being compiled/called.
      How can I fix it? I tried registering a copy constructor with asBEHAVE_FACTORY but no luck. Keeping in mind I would like to avoid editing manually over 300 scripts if possible.
      Thanks in advance.
       
×

Important Information

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

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!