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.

AppGameKit Classic Chat / Question about Sprite ID's..

Author
Message
David Gervais
Retired Moderator
19
Years of Service
User Offline
Joined: 28th Sep 2005
Location: Montreal, Canada
Posted: 7th Feb 2014 02:24
I have a question, can I Dim a multi dimensional array for the pointers? Something like this..



Note I would probably assign the values through a pair of for next loops, to make the code a bit neater. this sample is just to make things perfectly clear.

Thanks in advance for any insight.

Cheers!

easter bunny
12
Years of Service
User Offline
Joined: 20th Nov 2012
Playing: Dota 2
Posted: 7th Feb 2014 03:27 Edited at: 7th Feb 2014 03:28
Yes.




Do you mean to have it like this?

Global DIM CubeSpr[45,4] as integer

REM then assign values to the elements like this..

CubeSpr[1,1] = 101
CubeSpr[1,2] = 102
CubeSpr[1,3] = 103

CreateSprite(CubeSpr[1,2],imageID)

???
if so, wouldn't it be better like this:


Global DIM CubeSpr[45,4] as integer

REM then assign values to the elements like this..

CubeSpr[1,1] = CreateSprite(imageID)
CubeSpr[1,2] = CreateSprite(imageID)
CubeSpr[1,3] = CreateSprite(imageID)

David Gervais
Retired Moderator
19
Years of Service
User Offline
Joined: 28th Sep 2005
Location: Montreal, Canada
Posted: 7th Feb 2014 10:41
thanks for the quick reply easter bunny

I use the first method..

CreateSprite(CubeSpr[1,2],imageID)

mainly because I have hundreds of sprites in my current project and I like to give them some kind of order, ie knowing one set of sprites has their ID in the 100-299 range and other sprites in the 300-499 range .. and I like to keep the ID's 1 to 99 for Intro sprites, GUI, wigets and spfx.

That said, thanks again for the quick reply, It'll make handling my large amount of sprites allot easier.

Cheers!

fog
21
Years of Service
User Offline
Joined: 5th Oct 2003
Location: Newcastle, England
Posted: 7th Feb 2014 20:32
Hi David. You want to get away from referencing sprite IDs like that, especially fixed ranges of numbers, as quickly as possible.

Sooner or later it will come back to bite you and, apart from anything else, it takes a lot more work to write and modify code that way.

Follow easter bunny's second example above, have AppGameKit assign the numbers and forget about them.

The same goes for image numbers, sound ID's etc. I have tens of thousands of lines of code and not a single ID anywhere.

Digital Awakening
AGK Developer
22
Years of Service
User Offline
Joined: 27th Aug 2002
Location: Sweden
Posted: 7th Feb 2014 22:19
Same here!

David Gervais
Retired Moderator
19
Years of Service
User Offline
Joined: 28th Sep 2005
Location: Montreal, Canada
Posted: 8th Feb 2014 11:42
simple enough fix, thanks for the suggestion.

Cheers!

SoftMotion3D
AGK Developer
19
Years of Service
User Offline
Joined: 24th Aug 2005
Location: Calgary,Alberta
Posted: 9th Feb 2014 07:32
I think default.... aren't all dims global as I have never used the word global in front of any dim statements and I have been able to access them fine in any random function...

??

maybe they are not global if the dim statement is within a function?

I have no clue....

Digital Awakening
AGK Developer
22
Years of Service
User Offline
Joined: 27th Aug 2002
Location: Sweden
Posted: 9th Feb 2014 09:21
All arrays are always global. I dim 90% of mine within functions and never had a problem. Some people prefers to declare them as global.

SoftMotion3D
AGK Developer
19
Years of Service
User Offline
Joined: 24th Aug 2005
Location: Calgary,Alberta
Posted: 9th Feb 2014 19:41
that's what I thought...

Marl
13
Years of Service
User Offline
Joined: 19th Nov 2011
Location: Bradford, UK
Posted: 9th Feb 2014 20:56
100% agree with easter bunny , fog and D.A.

Let AppGameKit do the work keeping track of sprite ID's it will save time and work in the long run.

Quote: "mainly because I have hundreds of sprites in my current project and I like to give them some kind of order, ie knowing one set of sprites has their ID in the 100-299 range and other sprites in the 300-499 range .. and I like to keep the ID's 1 to 99 for Intro sprites, GUI, wigets and spfx."

If this is easier for you, then what about using use the array index as the use indicator.
Naphier
14
Years of Service
User Offline
Joined: 2nd Oct 2010
Location: St Petersburg, Florida
Posted: 11th Feb 2014 02:41
I use a user function for creating sprites so that I can later manage them. It also references a data file with the colors of the sprites for easy updating.


The data file is a text file using Chr(31) (unit separator Alt+numpad 031) to separate the color type and a 12-digit color code. This method can be easily expanded to include depth, size, etc. if you wish. You could even take it further and name your sprites so that you can later reference them by a string of their name.

DavidAGK
AGK Developer
10
Years of Service
User Offline
Joined: 1st Jan 2014
Location:
Posted: 11th Feb 2014 13:01
Ugh! I've started a tile map editor and set IDs manually as the original poster. I can now see the error of my ways so thanks for the input. I can see that I'm going to have to go back through my code and alter it to let AppGameKit manage the IDS. This will require a bunch of arrays which brings me to a question...

How large can arrays be before they become unstable and how much memory do they consume? I have no real clue if I'm a million miles away from trouble or it's just around the corner. Is Dim Bob[1000,1000,20] pushing boundaries or not even registering on the trouble-o-meter?
Marl
13
Years of Service
User Offline
Joined: 19th Nov 2011
Location: Bradford, UK
Posted: 11th Feb 2014 13:33
Quote: " Is Dim Bob[1000,1000,20] pushing boundaries or not"

That would depend on what you want to run the app on.
1000 x 1000 x 20 x 4 bytes = 80 Megabytes + overheads

If you found you needed an array like that, I would seriously look at how you store your data.

I prefer to use UDTs with single dimension arrays and where an entry needs additional dimensions, I use strings with comma delimeters and getstringtoken();

Its a workaround until UDTs support arrays.
DavidAGK
AGK Developer
10
Years of Service
User Offline
Joined: 1st Jan 2014
Location:
Posted: 11th Feb 2014 14:08
Out of interest, why/how does that use less memory? Don't the separate fields of the UDT create space in memory similar to having more cells in an array?

How fast is accessing data via your method when it comes to lines like the val( getStringToken( mySibling$ , "," , sibling ) ) compared to straight array accessing or is this such a small consideration that it's a mute point?

It's a shame you can't define variables smaller than an integer (eg a word of 8bits)

Thanks for the sample code - really helps me gain an insight into better coding! I bet you'd all laugh if you saw my code!
Digital Awakening
AGK Developer
22
Years of Service
User Offline
Joined: 27th Aug 2002
Location: Sweden
Posted: 11th Feb 2014 15:19
80 MB of RAM isn't that much today. A Galaxy S2 from 2011 has 1 GB of RAM. You're not even using 10% of that! Just don't go nuts and have multiple ones of those.

And do not use strings unless needed. Each character is 1 byte and I wonder how much memory is reserved for each string declared.

Worrying about RAM in simple 2D games is needless today. Unless you want to target some crappy old phones that probably can't run AppGameKit anyway. The original S2 couldn't, only with a system update. A game requiring an array of that size is probably not meant to be played on some tiny screen anyway.

Don't over complicate things when it's not necessary

Phaelax
DBPro Master
21
Years of Service
User Offline
Joined: 16th Apr 2003
Location: Metropia
Posted: 11th Feb 2014 17:20
Quote: "A Galaxy S2 from 2011 has 1 GB of RAM. You're not even using 10% of that! "

But there's other things running on the device too, so you can't rely on having 1gb available for your app anyway.


Quote: "Worrying about RAM in simple 2D games is needless today"

I wouldn't say needless. Even if the device is capable of running your app using 256mb, if you can cut that amount in half then I suggest doing so. You think ram grows on tress that you can just waste it! But I wouldn't go to the extreme of bitshifting bytes together to save room.

Quote: "It's a shame you can't define variables smaller than an integer (eg a word of 8bits)"

Isn't a word 16bits?

Can't recall the post, but someone once explained to me why AppGameKit uses integers for everything and why there is no byte or word. Because of how modern architecture works, if you defined a byte, it would still reserve an integer anyway and simply bitmask for the value of that byte, thus adding an extra step into reading/writing smaller data types. At least I think that's what it was. Not 100% sure I'm remembering it correctly.

Marl
13
Years of Service
User Offline
Joined: 19th Nov 2011
Location: Bradford, UK
Posted: 11th Feb 2014 18:19 Edited at: 11th Feb 2014 18:34
Quote: "Out of interest, why/how does that use less memory? Don't the separate fields of the UDT create space in memory similar to having more cells in an array?"
It doesn't necessarily use less, but it expands in one direction primarily. A 3 dimensional array would need to grow 3 ways and we all know how reliable that's been.

Quote: "How fast is accessing data via your method when it comes to lines like the val( getStringToken( mySibling$ , "," , sibling ) ) compared to straight array accessing "

Personally, I've found array access to be quite slow - certainly slower than certain system calls. In tests, I found that accessing an array of pre-calculated sines was much slower than calling the sine function. I think AppGameKit is the first language I've used where this is the case.

Quote: "80 MB of RAM isn't that much today. A Galaxy S2 from 2011 has 1 GB of RAM. You're not even using 10% of that! Just don't go nuts and have multiple ones of those"
It's that kind of thinking that made Windows what it is today - Large, Slow, Bloaty and more concerned with collecting user stats than serving user needs.

I liked my S2, but it died. The S3 has much less free ram due to "features", often going as low as 80 MB. But as Phaelax stated, you should always try to be efficient, by limiting your app to only higher end devices, you are limiting your market.

Quote: "And do not use strings unless needed. Each character is 1 byte and I wonder how much memory is reserved for each string declared."
I thought it was 2 bytes per character, plus a terminator, but could be wrong. Any other overhead would also be true of all data types.

There is a lot of resistance to String use - particularly from older C users ( C was traditionally rubbish at handling them ).

The main advantage here is that they are variable length, so if a record doesn't need the space, it's not used.

Quote: ".. someone once explained to me why AppGameKit uses integers for everything and why there is no byte or word."
That might have been me, I did a post some time ago while arguing FOR smaller data types.

It's because modern architecture is primarily 32 bits. To access a byte in memory, the CPU reads four of them and discards three. In a short sighted move, someone decided that since it reads four bytes, we should use them - why would anyone need less after all?

It's a limitation of AppGameKit, not the platform architecture, after all C++ has Boolean data types ( as Tier 2 users will no doubt point out )

The problem is that it looks solely at performance over space.

A 32 bit number could be used to store 32 1 bit numbers ( Boolean data type or true / false ), such as the numbers used to store collision states etc.

By limiting to a 32 bit datatype we have two choices;
1) do the bit manipulation yourself
2) use 32 bit numbers to store 1 bit of data.

The former adds back in, the work the language developers didn't want to do - but at a higher level, so slower than if it was part of the language.

The second wastes 97% of the storage used - in an app designed to be used on devices with limited resources.

Madness.
Naphier
14
Years of Service
User Offline
Joined: 2nd Oct 2010
Location: St Petersburg, Florida
Posted: 11th Feb 2014 18:48
While an 80mb array seems like a lot, if it is one of your biggest resources then don't worry.
The original question was at what point does it become unstable.
I've used some really large arrays in testing and I've not run into any issues with the array itself. The biggest issue comes from having to do anything with the array. If you need to sort or search for data in that array it is going to take a long long time. So if you can split your array up into uses then do so.
Also yes, UDTs are your friend, but beware they are glitchy!
I've often had UDT arrays be initialized with dim only to find that AppGameKit didn't clear the memory for it and some values were in there. Seems to happen more on the mobile platforms than it does on Windows. So you can be developing in Win and never notice it until you get some really strange behavior on Android... Lesson: After dimming a UDT array make sure to null out its values!

DavidAGK
AGK Developer
10
Years of Service
User Offline
Joined: 1st Jan 2014
Location:
Posted: 11th Feb 2014 20:04
This is all seriously useful info... I need to have a re-think on how I'm handling data. I can see that manually using IDs is a no-no..so that definitely needs to change. Performance isn't such an issue with the map editor but I can see the same thing coming back for the actual game and that's when I will want speed...so I guess it's now store the map data and tile attribute data etc in 2/3D arrays or use UDTs.

I should probably have chosen a smaller program to start with!
Marl
13
Years of Service
User Offline
Joined: 19th Nov 2011
Location: Bradford, UK
Posted: 11th Feb 2014 21:49
Quote: "So I guess it's now store the map data and tile attribute data etc in 2/3D arrays or use UDTs."
There are also memblocks, but I've never used them so can't comment on performance.

This is effectively a block of memory of a given size, that can be accessed in different ways; byte (8 bits), short (16 bits) or int / float (32 bits). Though it should be noted that both int and float return signed values

If your tile data would fits into a byte or word, this would provide a more efficient way to store it.

A byte map of 1024 x 1024 would need a one meg memblock and the address could be reached through bit manipulation of the row and column.

offset = row x 1024 + column ( in bit operations offset = ( row<<10 ) || column )

To achieve your theoretical example of 1000 x 1000 x 20, I would allocate 20 memblocks rather than using one large one.

Memory management handles twenty 1 Meg blocks much better than one 20 meg block at the cost of slightly more overhead.
Digital Awakening
AGK Developer
22
Years of Service
User Offline
Joined: 27th Aug 2002
Location: Sweden
Posted: 11th Feb 2014 22:57
To quote Jonathan Blow, don't optimize things that are not speed critical. It's a waste of time.

fog
21
Years of Service
User Offline
Joined: 5th Oct 2003
Location: Newcastle, England
Posted: 11th Feb 2014 22:59 Edited at: 11th Feb 2014 23:00
TBH I'd avoid memblocks and stick with an array of whatever type is needed. Don't over complicate things unless it's really necessary.

The size of the array will obviously depending on what the UDT is, but 1000 x 1000 x 20 isn't particularly big.

Also I'd avoid using strings like in some of the examples given here where there's an easier way. They can give an unnecessary performance hit and, on some platforms, regular use can create a lot of garbage that can cause the GC to trigger a surprising amount, causing the framerate to judder. (unless AppGameKit Basic is recycling the strings in the background for you)

EDIT: What DA said.

JimHawkins
15
Years of Service
User Offline
Joined: 26th Jul 2009
Location: Hull - UK
Posted: 11th Feb 2014 23:01
marl - AppGameKit uses ANSI strings, which are 1 byte per char. Unicode uses 3 or more bytes. On Windows, Unicode is generally faster for system calls involving strings, because Windows is internally Unicode.

Why would you need 1000 x 1000 elements?

I can see why people want to store the index in an array, but careful allocation of numbers would mean that you wouldn't need an array at all. So I have a slight theoretic difference with those who say you should always use arrays of automatic indices.

-- Jim - When is there going to be a release?
DavidAGK
AGK Developer
10
Years of Service
User Offline
Joined: 1st Jan 2014
Location:
Posted: 11th Feb 2014 23:07
My original idea was an X,Y,Depth array that would hold the tile IDs at the corresponding X and Y and then the Depth would hold tile attributes...but as you've done above, I could make it a single dimension array and simply use an offset from the start based on the x and Y coordinates (ie map width in tiles * how many rows down plus the column you're in) This would let me have a single dimension array which sounds like a safer option all round. Each entry could then have UDT fields which hold the various pieces of info eg sprite number and attributes. Does that sound like a sensible solution?

Not even read up about memblocks. The reality is that I'll probably only need maps about 250x250x2 tiles (ie I have two depth of tile) but they will need several attributes each, so maybe I need to think of a good way of encoding the attributes into a single entry.
Naphier
14
Years of Service
User Offline
Joined: 2nd Oct 2010
Location: St Petersburg, Florida
Posted: 11th Feb 2014 23:18
@DavidAGK - UDTs all the way! They make data management easy.

I use a combo of memblocks and arrays. Our data file is encrypted and needs to be read into a memblock to read/write the data. I think memblocks are truly best for data that will be written to file. Also they can be good for manipulation of image data and sounds, but I'm not sure AppGameKit supports that fully yet. Once the data is in a memblock you likely need to be able to do iterative operations on chunks of it and that's where arrays are needed. You could technically write the memblocks to mimic arrays, but I think it would be more work than it is worth. Once data is in memory the access is really fast. The larger performance hit comes from trying to read/write a lot. For example, Wordspionage writes to file pretty frequently to save states of small things like where the player placed there tiles or what order they are in their tile tray. It can cause a bit of a bump in performance when the file size gets to be around 100kb. Looking back I should have created separate data files for every single game instead of lumping it all together, but I've maxed the file size to 100kb so it isn't much of an issue and only happens when someone is playing 30 simultaneous games.

Regarding string comparison - definitely don't do it every frame, you might take a performance hit for this. I'd be surprised if it was a lot, but if those who are concerned would test it out I think they'd find the performance hit isn't all that bad. AppGameKit handles array data and string comparison quite well.

Marl
13
Years of Service
User Offline
Joined: 19th Nov 2011
Location: Bradford, UK
Posted: 11th Feb 2014 23:55 Edited at: 11th Feb 2014 23:58
Quote: "Regarding string comparison - definitely don't do it every frame, you might take a performance hit for this."

I was primarily suggesting strings as an alternate way to store such as map data, intended to be used for example to build the map on screen at the start of a level.

Quote: "AGK handles array data and string comparison quite well."

Agreed, I first used the getStringtoken() thing as a quick way to get some level data onto screen while testing a mockup and as a way of passing lots of data to and from functions;

mySprite = MyCreateSprite( thisImage , "W=100,H=50,OX=50,OY=25,X=12,Y=35,R=255,G=128,B=64,D=50,F=1")

I expected it to get all chuggy, suggesting I'd have to go back and do the "proper" routine, but it didn't. So now I use it all over the place.
Quote: "marl - AppGameKit uses ANSI strings, which are 1 byte per char. Unicode uses 3 or more bytes."

Thanks Jim, I would have gone with that, but felt sure I'd seen mention of two bytes somewhere. Guess not. One byte is better for the example.
Naphier
14
Years of Service
User Offline
Joined: 2nd Oct 2010
Location: St Petersburg, Florida
Posted: 12th Feb 2014 00:08
Quote: "I was primarily suggesting strings as an alternate way to store such as map data, intended to be used for example to build the map on screen at the start of a level."

That's the way I use it and pretty frequently.

It's good to know that AppGameKit strings are much smaller than I thought

Quote: "mySprite = MyCreateSprite( thisImage , "W=100,H=50,OX=50,OY=25,X=12,Y=35,R=255,G=128,B=64,D=50,F=1")"

That's a lot like what I do, only I don't use that much data. It certainly could make management a bit easier if you do something like this - you can also store this type of data in a CSV file which you program reads. That way you have a nice spreadsheet to work from for changing the data. I did something quite similar to that with dFenz.

I've found getStringToken to be really fast too. I believe I did some tests on that vs. parsing the data by stepping through the string with mid() and it was orders faster.

For a map/level editor program I'd definitely make use of strings and data files as much as possible. If you use a CSV data file to store your sprite data it can be really handy and easy to manipulate. I think my code example above even includes a function that updates all of the sprite colors (something we were using during testing to make it super easy to get the colors we wanted).

Marl
13
Years of Service
User Offline
Joined: 19th Nov 2011
Location: Bradford, UK
Posted: 12th Feb 2014 00:49 Edited at: 12th Feb 2014 00:59
Quote: "It certainly could make management a bit easier if you do something like this "

Precisely, by using string parameters for such as sprite creation, you can have string templates for different things and combine them when passed to the function.
mySprite = MyCreateSprite( thisImage , frogSpriteTemplate$ + defaultColour$ + StartPosition$ )

Code management is also easier as the handling of each parameter is coded in a case section of a select structure, making adding parameters a matter of dropping another block in.

You just have to get over any hangups about string manipulation
EDIT:

As a freebie for anyone needing an idea about data files and using stringtokens, here's a function from my current project

It uses some other functions and a lot of UDTs, but their purpose should be obvious from the names and their use should give some ideas.

Modularization Baby
JimHawkins
15
Years of Service
User Offline
Joined: 26th Jul 2009
Location: Hull - UK
Posted: 12th Feb 2014 09:04
marl - I typed 3 bytes per Unicode char when I should have typed 2. By using an "escape" value this can be 4 or more for complex scripted languages.

I totally agree about using strings for this kind of data. It makes it much easier to debug, because you can read the file. It's also far easier to extend than binary data.

-- Jim - When is there going to be a release?
DavidAGK
AGK Developer
10
Years of Service
User Offline
Joined: 1st Jan 2014
Location:
Posted: 12th Feb 2014 16:22
I'm going to have to read through this thread a few times before I continue with my map editor. It's a bit of an eye opener and I can see there is some super useful stuff in here. I think I'm still coding like I did all those years ago in Amos on the Amiga.
DavidAGK
AGK Developer
10
Years of Service
User Offline
Joined: 1st Jan 2014
Location:
Posted: 12th Feb 2014 17:11
I'm thinking out aloud here...

Just re-read Jim's post re "I can see why people want to store the index in an array, but careful allocation of numbers would mean that you wouldn't need an array at all. So I have a slight theoretic difference with those who say you should always use arrays of automatic indices."

That's what I'm effectively doing now - I don't store ID's as I tell AppGameKit which ones to use and so I know what they are...if that makes sense. The only place I was planning on using an array was storing which sprite Ids were placed by the user at what coordinates on the map and I was planning on having two depths of tiles (so spinning coins for example can be removed and still leave the background in place). Each coordinate would hold the original ID of tile to clone in the game and the id of the sprite being used to display in the map in the editor (as each tile can obviously be placed numerous times). I would therefore need two pieces of data per layer and so planned on having an array four deep. From the array I'd write a file out for reading in the actual game. Certainly, I can see from a data management/understanding a UDT that holds the four pieces of info rather than an ever deeper 3D array makes sense and probably making the array a single dimension simplifies things too.

So far manually allocating IDs has worked but I recognize that I am having to manage IDs so I'm torn (because I'll have to re-write the code!). Whichever way you go you need to keep track of either the ID or the location in the array that points to the correct data.

Argh, decisions!
Marl
13
Years of Service
User Offline
Joined: 19th Nov 2011
Location: Bradford, UK
Posted: 12th Feb 2014 20:19
A lot depends on the nature of the app and how the data will be reused.

My current project uses a tiled board, each place can hold an object and each object is made up of between 1 and 5 sprites.

Each position on the map has a single value to identify the object at that location. This is an index to an array of objects which contain the sprite references used for that object.

What this means is that no matter how many sprites an object needs, it takes only one entry in the map - the pointer to the object. Moving an object on the map is a matter of moving that one piece of information from one map location to another and then telling that object to move.

Objects are created and destroyed on the fly, so the sprite IDs used are regularly changing, since I can't know in advance how the game will play out, I can't know which objects will be deleted and so which sprite IDs will be reused.

If at any time, I need to add a few sprites, I just do without worrying about which ID ranges are free and which are in use

For me, and the style of app, its much easier to let AppGameKit keep track of things, my time is spent worrying about the game rather than it's resources.
Naphier
14
Years of Service
User Offline
Joined: 2nd Oct 2010
Location: St Petersburg, Florida
Posted: 12th Feb 2014 20:28
I prefer to let AppGameKit manage the sprite IDs because... I'm lazy sure. Also I don't really have the extra time to ensure that I'm doing it correctly. It's the whole reason that AppGameKit will do it for you, but I do understand wanting to manage them yourself. With dFenz I did a combination of the two. I had a constant for the sprite ID for a base sprite (one that would be cloned or only existed once).
I had to create a parser that would convert a CSV to lines of constant declarations to make it easy to add and delete sprite ID constants. In the end it was a pain and required a lot of constants (because who wants to remember the actual number to call a sprite by). It's so much easier to deal with a name than a number.

Also if you ever want to do batch operations on sprites you need an array of their IDs. I mean what happens if you have one set of sprites for a screen and want to hide them all? You have to call each by its number. Sure you can use a for loop if the numbers are concurrent, but then you want to add or delete one later and that's another fun mess that's just wasting time you could be spending on functionality.

Use all the tools at your disposal. Those tools exist to make your job easier so you can get your program completed.

JimHawkins
15
Years of Service
User Offline
Joined: 26th Jul 2009
Location: Hull - UK
Posted: 12th Feb 2014 22:57
Part of this discussion was the RAM overhead using automatic allocation into arrays. The deletion and re-allocation problem remains the same whichever way you do it.

You can only use name strings if you have a trivial number - but presumably that's only for the compiler.

I do laugh sometimes, these days. I started programming on an Apple ][ computer expanded to a massive 48K of RAM. Every bit counted. But it does teach you how to conserve memory, even on today's vast RAM chips.

-- Jim - When is there going to be a release?

Login to post a reply

Server time is: 2024-11-25 02:10:48
Your offset time is: 2024-11-25 02:10:48