Can I move an image between cards?

Got a LiveCode personal license? Are you a beginner, hobbyist or educator that's new to LiveCode? This forum is the place to go for help getting started. Welcome!

Moderators: FourthWorld, heatherlaine, Klaus, kevinmiller

jacque
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 7215
Joined: Sat Apr 08, 2006 8:31 pm
Location: Minneapolis MN
Contact:

Re: Can I move an image between cards?

Post by jacque » Mon Sep 11, 2017 3:07 pm

I don't see why you'd need a database, you can save LC arrays to disk as either binary or text files and read them in directly.

I would envision the array with room names as keys and any moveable inventory objects on the card as each key's element. Each array would represent a single game.

Arrays are fast, and all you need to do on preopencard is create the elements listed for that corresponding key. There would also be one additional key that stores the current card name (updated on each card change) that allows the app to know where to resume on next launch.

Except for the database part, your steps seem right. When the game begins, check for an array on disk (no array means it's a new user) and store it in a script local or global variable. Read and update the array as the user navigates and does things. On quitting/closestack, write the array back to disk. If you want to be cautious, write the array to disk on every card change so the current state is preserved if something unexpected happens.

This method wouldn't require a launcher stack since all data can easily be stored in the array on disk. A launcher stack is always an option, but you'd need to create a whole new stack for every new game which seems like overkill for something like this.
Jacqueline Landman Gay | jacque at hyperactivesw dot com
HyperActive Software | http://www.hyperactivesw.com

bogs
Posts: 5435
Joined: Sat Feb 25, 2017 10:45 pm

Re: Can I move an image between cards?

Post by bogs » Mon Sep 11, 2017 7:44 pm

jacque wrote:A launcher stack is always an option, but you'd need to create a whole new stack for every new game which seems like overkill for something like this.
Not necessarily, there are plenty of examples out there such as Klaus's "launch any stack" and BvG's launcher.

To put it another way, lets say you develop a ton of apps, you don't want to create a launcher for each one. You would have a common directory that all your apps go into (assuming my best <Dr. Evil> immitation), which we'll call an "app" folder :twisted:
...Your launcher scans this "app" folder every time you launch it.
...Your launcher has a "list" of "apps" in your "app" folder which you've named in a particular way, so it only lists say "mySpecialxxx.livecode" files </Dr. Evil>

The nice thing about this type of system is that after downloading the first of any apps you make, the laucher is already on system in the folder, and the rest of your apps can all be just stack files which are TONS smaller to dl, and all self contained since they can save themselves to themselves.

Just another take on it, Jacque's point about arrrays is I'm sure spot on as well.
Image

jacque
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 7215
Joined: Sat Apr 08, 2006 8:31 pm
Location: Minneapolis MN
Contact:

Re: Can I move an image between cards?

Post by jacque » Mon Sep 11, 2017 8:07 pm

I've had a generic launcher system in place for many years and it's great for some things, but for a game like this I wouldn't use it. There's more overhead and maintenance involved when managing stack clones, when all that's needed is a tiny prefs file.
Jacqueline Landman Gay | jacque at hyperactivesw dot com
HyperActive Software | http://www.hyperactivesw.com

bogs
Posts: 5435
Joined: Sat Feb 25, 2017 10:45 pm

Re: Can I move an image between cards?

Post by bogs » Mon Sep 11, 2017 10:28 pm

I don't see anything wrong with using pref (or other) files, I've done so myself many times, however I feel I maybe misunderstanding what your explaining Jacque, so in advance please forgive my denseness :)

If you create a launcher that generically opens any stack of yours, assuming planning, naming convention, etc., how would you have overhead and maintenance on the launcher? I mean, the stacks your launching would contain any logic, and the stacks your launching would also be what you would perform maintenance on, isn't it? It isn't like the launcher code would probably have to change anytime soon, I am guessing, since it works pretty much the same all the way back to Mc from my testing.

Game changes *might* require maintenance on a stack you ship out, however even that could be overcome leaving save games to a set of stacks and game logic and artwork (which is all that should change far as I know) to a different stack.

I am sure I must be missing something simple in my thinking, feel free to point it out with the "blunt board of destiny" :)
Image

Jetboy
Posts: 7
Joined: Wed Sep 06, 2017 11:22 am

Re: Can I move an image between cards?

Post by Jetboy » Tue Sep 12, 2017 1:57 pm

jacque wrote:I don't see why you'd need a database, you can save LC arrays to disk as either binary or text files and read them in directly.
I'm using an SQLite database (i.e. a local one stored in the 'Documents' folder) because I think that having a 'grid' to deal with rather than a string of text is easier to maintain. I should probably emphasise that none of the data will be kept server-side because really... I don't want to be responsible for the data itself (or maintain a server...etc). I'm using SQLite in place of a text file or XML doc (prefs file?) because it can be as big or small as I want it to be. If it does get massive, then I have the room to expand, whereas, a text document with a heap of concatenated text could get a little fidgety.

While this is a small game at the moment, I envision that it will be a game that will have 50-100 cards and multiple 'saved game' spots.

SQL is another reason why I've gone wit SQLite. I'm familiar with SQL, so doing all the data work in SQL (using LiveCode for the more complex logic statements) is a plus.
bogs wrote:Um. I'd suggest a slightly different way to your goal with saved games. I would make one separate card with a simple table object to hold all the things you are planning to put into a database, and I'd use a launcher stack to launch the game.
This was my initial plan and I guess it's still an option. One question with this would be how long the data is saved for. For example if I push out an update to my app (or somebody deletes it), I suspect the new app will then start fresh, with a new card. I could avoid this by dumping everything to an external file, but when it gets to that point I feel I might as well just use a database in the first place.
bogs wrote:I don't see anything wrong with using pref (or other) files, I've done so myself many times, however I feel I maybe misunderstanding what your explaining Jacque, so in advance please forgive my denseness
I guess my SQLite database is my 'prefs file'. But point taken... maybe what I really need to be doing is using multiple data sources for different purposes? I'm currently fixated on trying to whack a lot of stuff into a single cell. Can't say I've worked with XML much... what would this give me that SQLite doesn't already?

bogs
Posts: 5435
Joined: Sat Feb 25, 2017 10:45 pm

Re: Can I move an image between cards?

Post by bogs » Tue Sep 12, 2017 3:08 pm

Jetboy wrote: One question with this would be how long the data is saved for. For example if I push out an update to my app (or somebody deletes it), I suspect the new app will then start fresh, with a new card. I could avoid this by dumping everything to an external file, but when it gets to that point I feel I might as well just use a database in the first place.
Well, if the card is saved separately from your game stacks, the data would be there as reliably as anything else, barring as you mention over-writing it, some one deleting it, etc.
...I would point out that all of these examples are possible no matter how you save the data, whether in a db, prefs file, bin file, etc. Unless you plan to have total control over the file (i.e. the server you already said you don't want to do), and even then things happen on servers.
...You could do the same as you would fearing loosing any other information by saving the stack/cards out to separate locations and running a comparison between the default set and the duplicate set, but I think thats going a tad far for a simple save game either road.

The upsides of doing it this way depends on the structure you wind up with in my p.o.v.
...Most people who are just starting might try to put the whole game in one stack if it is simple enough, even with 50-100 cards this is not a big deal, btw, but to my way of thinking actually makes maintenance harder.
...To me, it would make more sense to break the stacks down by function, i.e. you have your launcher which starts the program stack, you have your program stack which contains the main logic and probably artwork and resources since those are likely to change over time, and you would have a separate stack for your game data and playing screens.

Laid out that way (or similar, details would depend ultimately on your structure), you could literally save all the cards of the game data/playing screens as is, taking away the requirement for a db or external file of any kind since all prefs would be saved with the cards. If you changed some logic or artwork in the program stack, it would have no impact on the saved stack/cards/prefs.

There are downsides with this method, just as there are with external files. With a db that saves game info/prefs, if you want to make sure you never wipe out whats there you would have to either a.) keep whatever structure you lay out initially or b.) read it all in and save it out as the new format if you ever changed it.
...With the saved stack/cards prefs, you could simply add or modify the save routine to compensate, in other words, same as the db but infinitely easier to accomplish.

In other languages I've used, I certainly would have gone the way Jacque mentions, but they don't have the advantages Lc provides with saving the whole thing ad-hoc (as long as it isn't the executable).

I don't know, Jacque has had far FAR more experience in such than I have, and as I say I may have completely missed the point, so just my .02 cents, which due to inflation and the devaluation of the dollar is probably .00000000002 cents :mrgreen:
Image

jacque
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 7215
Joined: Sat Apr 08, 2006 8:31 pm
Location: Minneapolis MN
Contact:

Re: Can I move an image between cards?

Post by jacque » Tue Sep 12, 2017 5:02 pm

I wrote a response but our internet went out before I could post it. Will do that when I have a connection again and not typing on a tiny phone.

I wouldn't use any card or stack copying, it isn't appropriate for this.
Jacqueline Landman Gay | jacque at hyperactivesw dot com
HyperActive Software | http://www.hyperactivesw.com

bogs
Posts: 5435
Joined: Sat Feb 25, 2017 10:45 pm

Re: Can I move an image between cards?

Post by bogs » Tue Sep 12, 2017 7:12 pm

jacque wrote:I wrote a response but our internet went out before I could post it. Will do that when I have a connection again and not typing on a tiny phone.
Ugh, you have my complete sympathy, I never try to type on my phone.
Image

jacque
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 7215
Joined: Sat Apr 08, 2006 8:31 pm
Location: Minneapolis MN
Contact:

Re: Can I move an image between cards?

Post by jacque » Wed Sep 13, 2017 6:58 pm

Back online again. Here's what I wrote 2 day ago:
bogs wrote:If you create a launcher that generically opens any stack of yours, assuming planning, naming convention, etc., how would you have overhead and maintenance on the launcher?
Not necessarily the launcher, it's the game stacks. You'd have to store a copy of the game stack as a template that would be cloned for each game. While a naming convention for the stacks would be important to avoid stack collisions, it wouldn't even be an issue with an array-based file.

Concerning maintenance: If you find a bug, or if you want to change the interface, or add a feature, or even just correct a typo, every existing stack clone will immediately be out of date. So you need to write scripts to update every stack that already exists, which is a real pain. You'd need exporter scripts that read directories looking for game stacks, scan each stack for the data on each card, collect that data, clone the new template, and import all the data you just exported. The user will have to sit through that, so depending on how many clones need to be updated you may need to add a progress bar. (Does it sound like I've been through this?) :)

Overhead: There are size considerations. The OP mentioned a 50-card stack. A data file for a 50-card stack would be very small, and it can be compressed as well if necessary. A two-card solitaire game stack I wrote years ago is about 400K; another game I wrote that had five cards was closer to 800K. Much of the size was the graphics and controls, which each cloned stack would include. After only a few games, disk usage would add up and almost all of the file size would be duplicates of identical content.

There are a lot of advantages to keeping the user data separate from the stack that displays it, and is almost always the best way for multiples of the same type of data. The "view" is the stack framework with its graphics, controls, and logic; the data itself is a pretty minor piece that can easily be loaded and unloaded on demand. In this case, the load would be instantaneous because it's just a quick disk read that's popped into a variable.

The launcher approach is extremely useful when you have different types of stacks with different structures, views, and features. It essentially creates a generic engine that can open anything. I use mine almost daily for testing different projects. But for multiple uses of the same stack, it is almost always more efficient in the long run to load data into the viewer rather than duplicate the entire structure and content.
Jacqueline Landman Gay | jacque at hyperactivesw dot com
HyperActive Software | http://www.hyperactivesw.com

jacque
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 7215
Joined: Sat Apr 08, 2006 8:31 pm
Location: Minneapolis MN
Contact:

Re: Can I move an image between cards?

Post by jacque » Wed Sep 13, 2017 7:43 pm

I guess my SQLite database is my 'prefs file'. But point taken... maybe what I really need to be doing is using multiple data sources for different purposes? I'm currently fixated on trying to whack a lot of stuff into a single cell. Can't say I've worked with XML much... what would this give me that SQLite doesn't already?
XML would be more trouble than a LC array, or even than the database you already have. I wouldn't bother. But I do suggest trying LC arrays, which are extremely fast and efficient and can hold tens of thousands of entries and still have an access time of a few milliseconds. For a game like you describe, it would probably be less than one millisecond. Since the array is native to LC, you don't have to mess around with scripting access to external databases.

I'm not sure exactly what you will need to store for this game, but as an example, let's say that you want to store the location and icon of each inventory item that currently resides on a particular card. It would be easy to add as many other elements as you need. So to begin with, you need to store the name of the card to use as array keys. This can be the short name of the card or the ID of the card, but for convenience and safety I'd give each card a unique name. That way when you're debugging it will be easy to identify what card is being accessed. I'd also name each inventory item uniquely.

You can manage the array as either a one-dimensional array where you dump all the inventory items on the card into a single element, or as a mulitple-dimension array. If you are only storing a few bits of info about each inventory item, dumping them all together will work fine. If you don't want to parse the element text, or you want direct access to each bit of info, use a multi-dimensional array.

Example of a single-dimension array:

Code: Select all

gamePrefsArray
  cardOne
      Inv1:100,234:12345
      Inv2:362,567:39473
  cardTwo
      Inv3:123,567:595847
      Inv4:562,328:393947
This stores the name of the inventory item as a return-delimited list per card. Using colon as a separator the name is followed by a location for the button followed by the icon ID it uses. To get the info, you get the lineoffset of the inventory name that is in the card name key. Set the itemdelimiter to colon and grab the item you need from that line.

To use a nested array, there's no parsing:

Code: Select all

gamePrefsArray
  cardOne
      Inv1
         loc -> 100,234
         icon -> 12345
      Inv2
         loc -> 362,567
         icon -> 39473
  cardTwo
      Inv3
         loc -> 123,567
         icon -> 595847
      Inv4
         loc -> 562,328
         icon -> 393947
To get the icon for an inventory item named "Inv1" from a nested array:

Code: Select all

put gamePrefsArray["CardOne"]["Inv1"]["icon"] into tIcon
You only need to store the inventory items in use. If you request an item that isn't in the array it will return empty, so you know it hasn't been placed on any card yet. On preOpenCard, you'd get the keys of gamePrefsArray[<card name>] which will give you all the inventory items that are on that card, and you can set them up with the locations and icons.

When you're ready to store the array as a file on disk, turn it into a binary file:
put arrayEncode(gamePrefsArray) into url ("binfile:" & <pathTofile>)

To read it back into memory on game launch:
put arrayDecode(url ("binfile:" & <pathToFile>)) into gamePrefsArray -- EDITED, original contained a "No coffee" error.

As I mentioned, I'd set up each card dynamically before it displays, and remove all the inventory on closeCard after repopulating the array with the current info. Also, if the game ships with some inventory already in place on cards (which I expect it will) then you can create the initial array and store it in the stack before you build. That gives the ability to just transfer the initial array to disk on first launch so you have a premade array all ready to go.

(Written without enough coffee, but hopefully gets the idea across.)
Last edited by jacque on Wed Sep 13, 2017 9:03 pm, edited 1 time in total.
Jacqueline Landman Gay | jacque at hyperactivesw dot com
HyperActive Software | http://www.hyperactivesw.com

bogs
Posts: 5435
Joined: Sat Feb 25, 2017 10:45 pm

Re: Can I move an image between cards?

Post by bogs » Wed Sep 13, 2017 8:43 pm

jacque wrote:(Does it sound like I've been through this?) :)
As I said, she has far AND AWAY more experience concerning such than I do :)

Thank you for the extended explanation, it gives me a lot to think about and was very appreciated. I guess my thinking is that this is what Mc's and Lc's structure looks to me, and while neither is a game, it seems to work pretty well. I'll have to test some of this out a bit more before continuing my (debatable) contribution to the topic :)
Image

jacque
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 7215
Joined: Sat Apr 08, 2006 8:31 pm
Location: Minneapolis MN
Contact:

Re: Can I move an image between cards?

Post by jacque » Wed Sep 13, 2017 9:10 pm

bogs wrote: I guess my thinking is that this is what Mc's and Lc's structure looks to me, and while neither is a game, it seems to work pretty well.
If you are using tiny, minimal stacks that are only a few K in size, it wouldn't affect disk storage much. But if you ever decide you want to change the stack content or structure in any way, you're stuck with the update headaches.
Jacqueline Landman Gay | jacque at hyperactivesw dot com
HyperActive Software | http://www.hyperactivesw.com

Post Reply

Return to “Getting Started with LiveCode - Complete Beginners”