Sorry your browser is not supported!

You are using an outdated browser that does not support modern web technologies, in order to use this site please update to a new browser.

Browsers supported include Chrome, FireFox, Safari, Opera, Internet Explorer 10+ or Microsoft Edge.

DarkBASIC Professional Discussion / What are your code line economy, routine shortcut techniques?

Author
Message
Chris Tate
DBPro Master
17
Years of Service
User Offline
Joined: 29th Aug 2008
Location: London, England
Posted: 30th Jan 2012 00:25 Edited at: 30th Jan 2012 00:50
I am getting in the habit of sticking to my own beliefs, without considering what others are doing.

What are you doing to improve your number of code lines Vs function Vs features. I am reaching the 15,000 line mark and could do with some pointers.

Ids
One of the first things I've tried which has proven pretty useful is the Matrix1 Freelists. Basically, these provide Ids for any item group you specify by number. You can reserve Ids and make them available per group.

Instead of writing functions like this for each and every UDT based array:


Just use the following:


Or with an alias (sort of) function:


There are other ways to handle this, but this is what sprung to my mind at the time. This principle applies to adding and removing ids; I also call a delegate function using
which can do some management on newly added items with their ids; they are effectily Events that occur when an item is added, deleted or updated; if I want the event.

How are you handling ids?

Types in types in types..
No more writing x#, y#, z#, width#, height#, name$ etc in each and every UDT for every object. If you are making a game about a ball that rolls in 4 directions on the screen then this is double-over-over-overkill. But if you got more types than folders on your hardrive, then having to rewrite such vague terms is a whole bunch of unjustified finger strain.

In my project, i am dealing with Positions, Sizes and Info types. At first glance you can see it saves me re-writting lots and lots of stuff in types; the compiler (virtually) writes it for me each time I declare a type in a type.

This also makes functions that can work on any type which contains a type. So if all doors and windows have positions, why shouldn't my MoveToPosition function be able to work on doors and windows? Why make a function for each UDT? Just pass in the type in the type like so:


Types are also effective at remedying typomania syndrome. (You cannot compile code that contains mistyped type members).

Ultimately, I send these types inside memblocks through the network to be used as function parameters; without any of this rubbish:


Just send my type arrays via memblock through the ethernet cable instead.

Loading and saving resources

I am currently going array to memblock crazy on this one. Nothing is being saved that is not a memblock which contains some header information and a series of arrays. This means I do not need to create much of an object parser. I have not used the simple file commands at all so far; but may use the file blocks for images and media later on.

I am giving the future hackers a tour on how to hack open my games, but I go in expecting the worst anyway.

I am sticking to UDT arrays and memblocks because these are easy to transmit over the network:


This sends all the array elements, which are usually macros, objects and positions.

What else could be done to make saving, loading and sharing easier? Any tactics anyone?

Functions
Once you put together an if branch or select statement, the only way to reuse your work is to copy and paste it. Your program is not being educated to redo things and you lengthing the code and your compile delay.

I have found heavy function use pretty useful so far. Although there is a tiny little delay during function calls, so far the FPS is doing good. Everytime I write something new, the program can do it again with another variable, because I put it in a function.

Array Pointers
Array pointers are a life saver; I used to only use them for passing specific arrays into functions. But they can also be used for running generic queries; and I find that generic functions are the most used.

Stuff like loading all images in any given text array, or applying all images to each subsequent stage of an object's texture has been cool. Stuff like loading all images in any compatible array, not just one. Some images are for textures and others are for GUI, so you can store them seperately then link to them:


Just call LoadImages( list ) and it does the work for me.

Call Function Ptr, Call Function Name$ functions are good for storing delagates. Basically, these are allowing me to store function calls for later, or obtaining functions from the user or script files.

These Matrix1 gems save me from having to do things like:


Instead I just use:


You can also return values and use parameters. These parameters can be defaulted in scripts, INI files or UDT members. So if a script file, INI or UDT hasn't got a parameter specified, the function is called with a default.

I have not fully grasped CoRoutines and Arglists yet, my brain is not having it. CoRoutines seem like a good toolset to use for certain low priorty game object update tasks later.

There is more I am doing, but the point is what you are doing, and how I could save more time and compile attempts.

MrValentine
AGK Backer
15
Years of Service
User Offline
Joined: 5th Dec 2010
Playing: FFVII
Posted: 30th Jan 2012 01:24
WoW... definitely reading this again ...

basjak
16
Years of Service
User Offline
Joined: 16th Apr 2010
Location: feel like signing up for mars
Posted: 30th Jan 2012 04:14 Edited at: 30th Jan 2012 04:15
thanks chris tate, I a bit disagree with using pointers. many pointers can cause confusion and reduce principle of least privilege.

I'd better use globals instead of pointers.

Diggsey
20
Years of Service
User Offline
Joined: 24th Apr 2006
Location: On this web page.
Posted: 30th Jan 2012 15:01
@basjak
That's unnecessary, you don't need to actually run through global variables for them to exist. Also, I don't see how that is similar in any way to pointers?

[b]
IanM
Retired Moderator
23
Years of Service
User Offline
Joined: 11th Sep 2002
Location: In my moon base
Posted: 30th Jan 2012 22:33
Quote: "CoRoutines seem like a good toolset to use for certain low priorty game object update tasks later."

I personally see them as 'do a bit, come back later to do a bit more'. In that way, they're almost like a state machine, but without you having to maintain the state yourself.

Simple example - note that there are two unending loops running simultaneously:


Experimentally, I've used this technique to dynamically create a large terrain object on the fly without overly impacting the game loop.

Quote: "I have not fully grasped ... Arglists yet"

They allow you to pass variables into your called functions without having to code your functions to accept specific types or numbers of variables:


Diggsey put together a simple printf equivalent using this, which you can find in the code snippets forum.

Quote: "There is more I am doing, but the point is what you are doing"

How about:
- At program startup, look for functions with names starting with 'Initialise', and automatically call them to initialise subsystems. Do the same for 'Shutdown'.
- Hook functions up to the pre and post sync events, and have those run their own lists of functions to call before and after every SYNC automatically.
- Load the function names dynamically from an INI file at runtime to alter behaviour of your program.

@basjak,
Quote: "and reduce principle of least privilege.
I'd better use globals"

Um... did you read that before you hit Post Message?

Because of the way DBPro was designed as a language, using array pointers rather than array globals enhances the abstraction of the code.

You can do exactly what Chris has done (well almost: make InteratorIndex() and String$() local to the function instead of global), and have one routine doing its thing on many arrays, rather than multiply-define the same function under different names.

Reduction of globals supports the principle of least privilege.

Chris Tate
DBPro Master
17
Years of Service
User Offline
Joined: 29th Aug 2008
Location: London, England
Posted: 30th Jan 2012 22:49
Hey

@basjak
I don't follow. Would it be possible for you to explain how using global position variables is saving you time?

I do have sections in my code that operate on global variables for iteration; looping through and operating on something variable; it may be what you are talking about, I'm not sure. Here is a piece of what I have available in my library based on globals:


But it is just there at the moment for when I cannot be asked to keep telling the program what object I am dealing with and where it is, and when timing is low priority.

About Array Pointers, I guess it is either you allow your functions to read similar lists, or not; it is down to what you want. For me, I cannot stand having to write seperate functions for each array. I tend to not worry about confusion that is not present; it is just the way I feel so far; maybe I will get confused later, maybe I won't; I'd have to deal with it.

Chris Tate
DBPro Master
17
Years of Service
User Offline
Joined: 29th Aug 2008
Location: London, England
Posted: 31st Jan 2012 01:20 Edited at: 31st Jan 2012 01:26
Excuse my double post, I noticed Ian's life changing reply after making my post... Following on...

@IanM

Coroutines;

I see why I did not grasp them now, thanks to your snippet. I must enclose the next routine command in a loop, for it to proceed within the function. I wasn't looping it.

I see that you can set the order of coroutines on the fly. That's good. I just need to play around with it; as you say, this is good for terrain streaming; there is alot of stuff that needs taking care of without using up all the frame rate that could be spread out using coroutines. It seems good for loading screens aswell.

Arglists

What the!! How did I not see this? This is just what I need in life; options. Wow, I really missed optional parameters in other languages, but this is it isn't it.

Half my functions have duplicates for different parameters; a bit like overloads; but I should really try Arglists; this is beautiful for making more good use of fewer functions with more options, it shouldn't make much of a speed difference if I use it well enough.

Thanks for the note about the Printf snippet; it was on my TODO list to create someway to skip using Str$() calls with numbers in text. Text is everywhere and needs formatting.

@Diggsey
Thanks for saving me from having to write the printf function.

Nice method for calling functions without parenthesises: printf "Test %i, a formatted %s and a %character",1,"string",asc("c"), it may take a longer to compile lots of constants#, but it beats having to write paranthesises for functions that do not return anything


@Ian
Quote: "At program startup, look for functions with names starting with 'Initialise', and automatically call them to initialise subsystems."


Hmm, why am I not thinking outside of my box? I am not even thinking inside of it.. I'm not even searching for any functions for anything in the first place?


[Shaking my head from side to side]

This is like switching a light switch on or off that switches other light switches on or off, without you having to go and switch them off yourself. This applies to all things that need initializing and shutting down...

It matters when every minute you spend coding is a minute not paying the rent (At the moment anyway )

I need to step 3 metres back and think more about this one before I continue, because I may not need to specify what functions to call in certain situations, it can work out what functions it should call itself; providing I provide the parameters take caution.

I have about 50 initialize subroutines already. (The only thing I use subroutines for, by habit, only because I used to think you could only declare globals outside of functions)

Quote: "Hook functions up to the pre and post sync events, and have those run their own lists of functions to call before and after every SYNC automatically"


A bit like sync events really. So far I am calling update functions manually. I do have some routines that must occur on every sync, but I think I would need to think about how to deal with what purpose the sync call was called for; eg: to do a full sync, to sync a camera effect or a modal error message box (TopGUI) etc.

Perhaps these hooked functions can check the purpose for the sync call before doing what they do using some global specifications.

So far I do not call Sync directly; the Sync sits inside various functions; for example; one calls physics updates and the sync, another calls just the sync, for when I do not want the physics updated.

There are also your commands for running functions before and after camera, sprite, windows and other updates that I will consider aswell. I'll consider putting a select case branch in the callbacks to manage what they should do.

Quote: "Load the function names dynamically from an INI file at runtime to alter behaviour of your program"


Will do, will definately do. This saves me from recompiling 1000s of lines just to change one line of code. This is not a bad method for defining customizable player entities; assigning variable functions for certain events...


Thinking ahead of myself here; but I don't know if I will ever need custom Sql querying on designated arrays so that I can do pretty much anything on item arrays from some sort of command line or script; but if I ever start to get fed up of defining queries in hard code, I feel that these are the tools that can make DIY Sql happen.

I might consider it when compiling starts to take more than 10 minutes... (5 so far). I have Unity for Lua scripts, but I am saving that for player submitted mods and interface customization, I will not expose development functions to Lua

One thing I can't get my head around when creating a script/sql parser, is how to code the parenthesis order... The last time I created a script language, I gave up on parenthesises.

But maybe now that I am more comfortable, I might give DIY SQL a go if my heart cannot take recompiling game item queries. I just see things getting real silly later on when tweaking logic with player inventory and item usage queries over a network. Something like populating certain Gui elements with a query: 'Select Name From (Select * From Players Where Points > TargetPoints OrderBy Points GroupBy Team)' could be easily modified in an INI file or script so you have more control over the logic of things without having to recompile, giving you more time for other things in life.

I'll stick with changing values in an INI file for the time being.

Thanks guys

Login to post a reply

Server time is: 2026-07-10 23:33:57
Your offset time is: 2026-07-10 23:33:57