saveStrings() makes file one character per line. (P5.js)

My first post here (and thanks to everyone involved in P5.js for re-igniting my interest in coding)...

I am trying to write data to a text file with multiple characters per line but saveStrings() isn't working for me. It acts the same as save() and gives me just one character per line.

eg: dataList = "String"; saveStrings(dataList, 'dataString.txt');

gives me a text file with:

S t r i n g

Am I missing something?

Answers

  • Well, that didn't work. Obviously I need to use Preview in future :\">

    dataList = "String";
    saveStrings(dataList, 'dataString.txt');
    

    Gives me a text file with one character per line.

    S

    t

    r

    i

    n

    g

  • Answer ✓

    We need to pass an array as 1st argument for saveStrings(): L-)
    http://p5js.org/reference/#/p5/saveStrings

    The reason you see 1 character per line is b/c a JS String object got its characters indexed like an array. ;;)

  • edited October 2016

    Thanks for the quick reply. I'm new to JS so forgive me if I'm a little slow.

    I thought one-word strings were an array with one entry. I see I was wrong.

    What I'd like to do is save a one-dimensional array to a text file but include some semi-redundant info at the top of the file (for human readability) - like "DATA FILE" "CREATED"... followed by the data. FWIW, the data itself sets values in grid cells.

    Ultimately I'd like to split the array data into a grid layout of x character per line, then write that to the text file. Again, this is for readability - so the text-file data will give some visual clue as to the grid values.

    So, I guess I need to add each redundant line into an array separated by some token, then add the actual data to that string separated by the token at the appropriate points (I think I can work that bit out). Then saveStrings().

    Basically - add a split token at the end of each line of text.

    I'll fumble around some more and see what happens.

    EDIT: First test looks good. Thanks.

  • edited October 2016 Answer ✓

    I thought one-word strings were an array with one entry.

    We can indeed access each character of it via [] index operator, like this:
    console.log('Some String'[2]); // prints string's 3rd character 'm' to the console.
    However a String isn't by its own an actual Array container! [-X

    In JS, the most famous way to create an Array is by wrapping its initial entries w/ []: B-)
    https://developer.Mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array

    So instead of const dataList = 'String';, what you actually want is const dataList = [ 'String' ];. ;;)
    Now saveStrings(dataList, 'dataString.txt'); works as expected. :bz

  • edited October 2016

    I see. I actually got it to work by concatenating each string to another string with a "*" separator then using split as per the example. Since then I've decided not to write the redundant text but I still needed this solution to prevent my double-digit numbers being saved as single-digit (I think? Maybe I should check that.).

    So now I have a data file with one entry per line but at least each line is complete data.

    Now I just have to read it all back in again :|

    thanks.

  • edited October 2016

    Yea, both the original JS' String split() method and p5.js' split() & splitTokens() functions are pretty neat ways to get an Array object outta a whole String: *-:)

    1. https://developer.Mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/split
    2. http://p5js.org/reference/#/p5/split
    3. http://p5js.org/reference/#/p5/splitTokens

    But it seems like you're more interested in creating some ".csv" file in order to associate some extra info about each entry of your String list, right?

    Then take a look at these links below for it if you decide to pursue it: #:-S

    1. http://p5js.org/reference/#/p5/loadTable
    2. http://p5js.org/reference/#/p5/saveTable
    3. http://p5js.org/reference/#/p5.Table
    4. http://p5js.org/reference/#/p5.TableRow
  • edited October 2016

    I'm drawing a game grid - think platform. The grid is 32cells wide by 24cells high with a cell size of 30px (960x720 canvas).

    I don't know if it's good or common practice but I reference each cell by a single number from 0-(32*24) - roughly speaking. Each cell holds a different value according to its game-screen content - this is the array.

    The data file then just needs 32*24 entries with a single value for each entry denoting the relevant cell value - and I don't need to store X/Y values for each entry because its position in the dataset determines its location. Easy to write, easy to load. The code will take care of plotting it back to X/Y.

    I'm not sure I need a csv. The extra info is in addition to the main array, not to associate with it. Things like start-up values and maybe a comment or two.

    All of this is just for the sake of learning :) . This is something I made way back when QBasic was a new idea and, after watching some of Daniel Shiffman's vids, I felt I could create it in P5. I'm almost there. I've got the graphics and functionality sorted but need to be able to save and load data to go to the next step.

  • edited October 2016

    @AndyD -- another Processing-esque way of storing and retrieving values for each cell in a 2D array, referenced by number 0-(x*y) is ...

    So you could read and write your gamescreen data from 32*24 pixel images. Then your level editing would be done in any PNG-compatible graphics program with the zoom cranked way up. ;)

  • Sorry Jeremy, you lost me :)

    Are you basically saying, make the canvas background one giant image, then paint the levels in "Photoshop" and swap the image as needed?

    Not sure what you mean about the read/write data though?

    Do you mean use individual 32x24 pixel colours to denote data values then just translate those values to the canvas somehow?

    I think I've got it all "working" now. I'm building a scene editor so I can just throw levels together visually. Then I need to use yesterday's saveStrings() solution to put the data away somewhere safe.

    I often bang my head against things for hours wondering why something isn't working - before realising I did something dumb like turn on noLoop() for some earlier testing. Still, I often tidy up a few things while I try to solve those problems.

  • edited October 2016

    @AndyD -- my point was re:"I reference each cell by a single number from 0-(32*24) - roughly speaking. Each cell holds a different value according to its game-screen content - this is the array."

    So, for example, I just spend one minute drawing a 32*24 pixel level design in piskel and then exported it as a png. Here it is:

    32x24_LVL1

    And up close it looks like this:

    32x24_LVL1_closeup

    If you chose you could use such an image as a data format rather than Strings (not a graphic, or game background -- as positional data for loading platforms and such. black pixel data indicates a platform, yellow indicates a coin, red indicates lava etc.). Load your game level data with loadImage, then access it with PImage.pixels[]. Each pixels cell is indexed by a single number from 0-(32*24). Each cell holds a different value according to its game-screen content. Sound familiar? :)

  • edited October 2016

    Dunno... but I guess what he meant by cell is a class to store various attributes, like coordinates, dimensions & color, rather than raw pixels? :-??

  • Thanks Jeremy. Makes sense now. Interesting idea. By cell, I meant the locations on the map which are, for the most part, index values in an array.

Sign In or Register to comment.