Hi there everyone (:
Im here to ask if any of u can recomend some links or scripts with stuff with .txt files and that... (open, using stuff inside it, etc)
I really want to start studying it (:
Thanks
This one: http://www.ruby-doc.org/core/classes/File.html
And possibly this one, too: http://www.ruby-doc.org/core/classes/IO.html
You might be interested in this one as well: http://ruby-doc.org/core/classes/Dir.html
wowa xD
Thanks a lot, I'm sure it will help me ^^
By the way, do you know any script that uses .txt file as a 'source'?
For instance, imagine that a script needs numbers and names for a lot of stuff.
Then, the scripter using rgss, reads that codes ans uses them for something.
That's what I'm more interested with xD
You can use
FileTest.exist?(filename) to check file if it is exist.
And use
Dir.glob("*."+filetype){|f|
//Command (f = eachfile)
}To each everyfile in the folder, you can put
Dir.chdir(foldername){ to select a folder first. (Don't put an extra
})
Use this to open a file.
File.open(filename,openingType){|f|
//Command (f = eachfile)
}You can choose a
basic openingType from below..
f.read(characterCount) and
f.write(value) will work for you as a command.
You can use
writeFile(pathToFile+filename"."+filetype,value) to write a file right away too..
Hope this helped you. :)
Well... I didn't understand it that well XD, maybe because im really at the beginning of this part of rgss :P
Thanks a lot ^^
Well, may I ask for an example? xD
So, imagine that i create a new txt file even before opening project xD
I put data that I will need in rgss scripts, such as:
Text file, named 'example'
something => does_that
... (so on)
Now, using rgss to pick up that data and use it...
File.open("example", rb)
#stuff picking up that data <.<
File.close
So, what should I begin with there?
Quote from: Apidcloud on February 06, 2011, 04:31:26 pm
Well... I didn't understand it that well XD, maybe because im really at the beginning of this part of rgss :P
Thanks a lot ^^
Well, may I ask for an example? xD
So, imagine that i create a new txt file even before opening project xD
I put data that I will need in rgss scripts, such as:
Text file, named 'example'
something => does_that
... (so on)
Now, using rgss to pick up that data and use it...
File.open("example", rb)
#stuff picking up that data <.<
File.close
So, what should I begin with there?
I don't think so.. I'm finding it out too..
I'm wondering like you too, but still.. you can't convert
STRING into
FUNCTIONS!
If you find it let me know because none of the computer languages (PHP, RGSS, VB, C+, etc.) can convert string into functions.
Well, I've done an example with a string but...with numbers it would be possible or not? xD
Quote from: Apidcloud on February 06, 2011, 04:49:54 pm
Well, I've done an example with a string but...with numbers it would be possible or not? xD
I'm thought you are talking about converting
String into
Functions! XD
Oh well, you just read a file you want to, and when you got the number just use
[YOUR NUMBER].to_f.
Now you converted it to fixnum. (Number) :)
Look into actual Ruby. That is how it is done with that, simply reading .rb files.
If you simply want to execute a whole file, or load it into memory, save a text document with an .rb extension and use:
If you want to use an external text file and execute code off of it, something like this should work:
lines = IO.readlines('TEXT_DOC_NAME.txt')
# You can use the ".join" method to combine the lines into a single string, otherwise it will be an array of lines
eval(lines[LINE_INDEX_TO_EXECUTE])
If you want to create an instance of the file:
file = File.open('TEXT_DOC_NAME.txt', 'rb')
# Do something
file.close
To write text to the doc:
file = File.open('TEXT_DOC_NAME.txt', 'wb')
file.write("This is a string")
file.write("\r\nThis is on the second line\r\n")
file.write("\tThis is the third line, and indented")
file.close
EDIT:
And "yes", you can convert strings into functions. I even came up with ways to construct and add new methods to instances of classes at runtime.
Quote from: ForeverZer0 on February 06, 2011, 04:59:39 pm
Look into actual Ruby. That is how it is done with that, simply reading .rb files.
If you simply want to execute a whole file, or load it into memory, save a text document with an .rb extension and use:
If you want to use an external text file and execute code off of it, something like this should work:
lines = IO.readlines('TEXT_DOC_NAME.txt')
# You can use the ".join" method to combine the lines into a single string, otherwise it will be an array of lines
eval(lines[LINE_INDEX_TO_EXECUTE])
If you want to create an instance of the file:
file = File.open('TEXT_DOC_NAME.txt', 'rb')
# Do something
file.close
To write text to the doc:
file = File.open('TEXT_DOC_NAME.txt', 'wb')
file.write("This is a string")
file.write("\r\nThis is on the second line\r\n")
file.write("\tThis is the third line, and indented")
file.close
EDIT:
And "yes", you can convert strings into functions. I even came up with ways to construct and add new methods to instances of classes at runtime.
OH!!! Thanks Zer0! I totally forgot of the
require method! I focused too much about the script so I forgot about the files.. DARN!
Well thanks a lot xD
Im going to test some stuff here with all that (:
lvl up everyone xd
@F0: You don't need to use \r if you open the files in 'w' or 'r' mode. Windows automatically adds them if you don't use 'w+', 'r+', 'wb' or 'rb'. Actually 'w' and 'r' are Windows hacks, all other OSes use binary file modes and it's kinda more convenient that way, too, because of multiplatform compatibility.
@blizz
You are right, its just kind of a (bad?) habit I got into. Honestly, I have only wrote code under Windows platforms, so I have never really concerned myself with cross-platform compatibility, which is something I should pay more attention to now that I'm getting into other languages. Never really had the need when writing scripts for RGSS, though.
I used to do it as well. But then I just switched to \n. xD
Quote from: Blizzard on February 06, 2011, 05:39:30 pm
I used to do it as well. But then I just switched to \n. xD
I used to say "\n" is the basic of string. XD
in case your wondering to convert a string into a function call first convert it to a symbol then send a message to the object with the function
look into the .call method to learn more. in the ruby-docs it should be under object
Hmmm, Im testing some stuff here...although...it's difficult xD
document = "Something.txt"
file = File.open(document, rb)
for line in 0...file.lines
IO.readlines(document)[line]
end
#I don't know exactly what I've to do now?
file.close
Well <.< I don't even know if this works at really...Can some1 help? xd
I accept advices for the logic of this code...
Note:
pick up .txt data and use it for something..?
file = File.open(document, "rb")
Note the quotes used around rb.
This sets the local variable "file" as an instance of the file. You can iterate it with methods like:
file.each_line {|line| print line }
and...
file.lines.each {|line| print line }
You will also need to make sure to close the file when you are done with it.
OR you can do this, not both.
lines = IO.readlines(document)
This simply creates a normal array, with each element being a string line of the document.
You can iterate the array normally, and have no need to close the file.
What you do with code totally and utterly depends on what it is, and what exactly you are trying to accomplish. I really can't help you with that until I know what you are trying to do.
I personally prefer the File.open way because it's a lot more readable. You can really see that it's a file that's being read.
I also prefer to open a file, use readlines or read, then close the file handle and after all of that work with the data that I read. I like doing it this way so the file is open as short as possible and other programs can open it afterwards. I do the same when writing to files. I first prepare the whole data, open the file, write everything into it and then close it right away.
Also, when using readlines or readline, keep in mind that the string will contain the \n at the end of the line if there is one. So you might want to use line.gsub!("\n") {''} on each line.
Quote from: Ryex on February 06, 2011, 06:03:08 pm
in case your wondering to convert a string into a function call first convert it to a symbol then send a message to the object with the function
look into the .call method to learn more. in the ruby-docs it should be under object
Can you actually link me the page or an example? There are so many calls.
Thanks a lot everyone :P
Im at school right now, but as soon as i arrive home I will practise it a bit...
Another question...u said that it will make my document an array right?
How does it works in this case?
line[0] = #information on first line
line = #information on i line
like that?
Exactly.
Quote from: Apidcloud on February 07, 2011, 06:22:59 am
Thanks a lot everyone :P
Im at school right now, but as soon as i arrive home I will practise it a bit...
Another question...u said that it will make my document an array right?
How does it works in this case?
line[0] = #information on first line
line = #information on i line
like that?
It splits into array.
Example, this is your text document:
+-------------------------------+
| Dear Blah, |
| How are you doin? |
| If you received my msg just call |
| me back, ok? |
| |
| Love, |
| Awesome Face |
+-------------------------------+
line[0] = Dear Blah,
line[1] = How are you doin?
line[2] = If you received my msg just call
line[3] = me back, ok?
line[4] =
line[5] = Love,
line[6] = Awesome Face
Hmmm ok, and what if I want to split my lines? xD
Something like this:
#Document
1 => 2
3 => 4
#
How would i use 'values' and 'keys' of arrays?
for this you need regular expressions, there is a good tut here on this forum (http://forum.chaos-project.com/index.php/topic,56.0.html) that explains how they work
take this code example with you as it dose what you want.
string = "1 => 2"
string.gsub(/([0-9]+)\s=>\s([0-9]+)/)
key = $1
value = $2
of course there is like 10 ways to do the second line. Regexp are heavily intragrated in to ruby
you could do it like this
case string
when /([0-9]+)\s=>\s([0-9]+)/
key = $1
value = $2
end
this is most useful when there is several patterns the string could follow
you could also do this
if string =~ /([0-9]+)\s=>\s([0-9]+)/
key = $1
value = $2
end
good luck
Thanks a lot xD
Although, shouldnt we use: key = $1.to_i #? xD
Well, I was doing something like that as well
Thanks again for the help
Bye~
yes true, the way I did it you'll just have strings, if you want to format those strings use to_i for an integer and to_f for floating point values.
Outch xD I could do something oO but it is returning an error.
Permission denied to acess the document lol
whats happening? <.< I used this as 'file' opening:
file = File.open("Data", "rb").each_line {|line|}
When I test the prject and this part comes up, it appears
---------------------------
Teste
---------------------------
Erro no Script Text -part 2, em 266 na linha 'Errno::EACCES'
Permission denied - Data
---------------------------
OK
---------------------------
Someone help here T_T
Your not using the call right. Nor are you including the file extension. I'm at work at the moment, I'll explain more when I get home here in a about an hour.
Forgot about the extension .txt <.< epic fail xD Thanks (:
@Edit <.< I though all my logical was ok...but i was wrong XD screen gets froze everytime i call this...
So, my code consists in picking up the strings and numbers from the .txt file and use them as teletransportation data...
In the document, there are lines as this one:
"string" = "string", number, number, number.
Here is the code:
@map_name = []
@respawn_map =[]
@respawn_x = []
@respawn_y = []
@respawn_dir = []
$old_map_id = $game_map.id
data = load_data("Data/MapInfos.rxdata")
return if !File.exists?("Data")
file = File.open("Data.txt", "rb")
file.each_line do |line|
case line
when /(\".*\")\s\=\>\s(\".*\")\,\s(\d+)\,\s(\d+)\,\s(\d+)\,\s(\d+)\./i
@map_name.push = $1
@respawn_map.push = $2
@respawn_x.push = $3.to_i
@respawn_y .push = $4.to_i
@respawn_dir.push = $5.to_i
end
end
file.close
for i in 1...data.size
if data[i].name != nil
actual_name = data[i].name
respawn_name = data[i].name
end
if actual_name == @map_name
actual_id = i
break
end
if respawn_name == @respawn_map
respawn_id = i
break
end
end
for j in 0...@map_name.size
return if @map_name.nil?
if $old_map_id == actual_id
$game_temp.player_new_map_id = respawn_id
$game_temp.player_new_x = @respawn_x[j]
$game_temp.player_new_y = @respawn_y[j]
$game_temp.player_new_direction = @respawn_dir[j]
$game_player.refresh
$game_map.update
$scene = Scene_Map.new
end
end
I fail to see any reason to make a simple task so complicated as all that. You can simply write an array to the text doc, then in the game set a variable to it using the "eval" function.
ex. Text Document (Array is used like this: [MAP_ID, RESPAWN_X, RESPAWN_Y, DIRECTION])
[1, 20, 20, 2]
[2, 15, 30, 4]
[3, 18, 9, 6]
[4, 2, 45, 8]
Then within the code, set it to a variable:
@respawns = IO.readlines("Data.txt") # No need to include "rb" or close file with this method
@respawns.collect! {|array| eval(array) } # Execute block on each element, then change array to returned value
If you want the map names in the array, run a method to add them. You could do this different ways, or even include it in the text document if you would like. I wouldn't even worry about, but just use the ID to find it if it was ever needed.
Either way, you now have an array labeled "@respawns", whose elements are arrays of integers.
To set the current respawn, just reference the desired one by its index, or line number of the text document if it helps you to think of it that way (remember the index is 0 based).
temp = @respawns[WHATEVER_INDEX_YOU_LIKE]
$game_temp.player_new_map_id = temp[0]
$game_temp.player_new_x = temp[1]
$game_temp.player_new_y = temp[2]
$game_temp.player_new_direction = temp[3]
$game_player.refresh
$game_map.update
You actually could do it with less code than that, but this should demonstrate how it works a little easier.
I am curious though, why would you ever do it this way. If you are merely trying to learn, that it fine, I have done much stranger things in the process of learning Ruby, but I would highly suggest against something so inefficient for an actual game. You could simply store the values in array within the game, and not use a file at all.
First of all XD
Im doing this...most likely to learn something about File, IO and Dir classes...and I already did this(without txt file) inside the script :P
Now I wanted to 'change' that information into .txt folder and then use rgss to take all that, string and integers...
Im going to try to use what u said.
One more time, thanks a lot for the help ^^
@Edit:
I failed using what u said there XD
Im going to explain my previous code..
Without .txt file, I could just do a class with this type of conditions:
if $old_map_id == 1
$game_temp.player_new_map_id = 2
$game_temp.player_new_x = 10
$game_temp.player_new_y = 20
$game_temp.player_new_direction = 6
$game_player.refresh
$game_map.update
$scene = Scene_Map.new
end
With txtfile ->
First of all, I though about creating some arrays, what would store the values of .txt document.
@map_name = []
@respawn_map =[]
@respawn_x = []
@respawn_y = []
@respawn_dir = []
Then, I thought about using regexp to take the lines that follow it:
data = load_data("Data/MapInfos.rxdata")
return if !File.exists?("Data")
file = File.open("Data.txt", "rb")
file.each_line do |line|
case line
when /(\".*\")\s\=\>\s(\".*\")\,\s(\d+)\,\s(\d+)\,\s(\d+)\,\s(\d+)\./i
@map_name.push = $1
@respawn_map.push = $2
@respawn_x.push = $3.to_i
@respawn_y .push = $4.to_i
@respawn_dir.push = $5.to_i
end
end
file.close
Each of these variables, will store the correspondent $'s.
After this, I needed to check the name of the maps(map where actor dies, and where it respawns) and then convert it to id:
for i in 1...data.size
if data[i].name != nil
actual_name = data[i].name
respawn_name = data[i].name
end
if actual_name == @map_name
actual_id = i
break
end
if respawn_name == @respawn_map
respawn_id = i
break
end
end
Finally, as each array have the same size, I only needed to use the size of one to make all necessary conditions...
for j in 0...@map_name.size
return if @map_name.nil?
if $old_map_id == actual_id
$game_temp.player_new_map_id = respawn_id
$game_temp.player_new_x = @respawn_x[j]
$game_temp.player_new_y = @respawn_y[j]
$game_temp.player_new_direction = @respawn_dir[j]
$game_player.refresh
$game_map.update
$scene = Scene_Map.new
end
end
This latter code, with .txt logic it is freezing the screen all the time I call it xD
Someone help please? :P
Just make a hash with the map IDs as the keys. Then you can simply use a single array to store all the needed data like the x, y, and direction.
All of the loops, iterations, and regular expressions are unneeded and are very inefficient. They have no real practical use, and are the likely use of your problem. It would be a good idea to rethink your initial approach than to try to force a bad one to work. I've had to rewrite entire scripts for this reason. About 3/4 of the way through, I see an easier way to do it, so I erase everything I've done and start over. The final result is usually 1/2 the code, easier to use, easier to overview, and is far more efficient. Sometimes you just need to go back to the drawing board. Everything you are trying to do could be done in 20 lines of code or less.
For the last example of code you have, I do see one obvious error right off the bat. The "return if @mapname.nil?" is quite worthless. The iteration would never get far enough to check that line, and would through an error if it was nil. I imagine you meant "@mapname[j] == nil" (I prefer using comparison, not ".nil?"). This will check the element for this iteration. I don't believe you need to call "$scene = Scene_Map.new" IF this is being called from Scene_Map.
What my previous post said should work. The only thing I see that I forgot to mention is what Blizzard mentioned earlier about the "/n" not being removed. That can be fixed by substituting this line:
@respawns.collect! {|array| eval(array) }
...with this one:
@respawns.collect! {|array| eval((array.gsub(/\n/) { '' })) }
I just arrived home xD that's the reason I couldn't asnwer here...I'm going to try to use that again :P
Thanks
Lemme warn you that you cannot load text files normally form within an encrypted archive.
If you want to encrypt your game you can convert the text file to a format load_data understands. (You can load the file as a string and save it using save_data)
One problem with that approach is that you cannot search for all file and you have to try and load a file to check if it exist. Since the files are encrypted they are not immediately available for the players to edit. Even if they decrypt the game it's still bothersome to edit marshalled files.
You can have them outside of the encrypted archive which is most easily achieved by not putting them in the data folder or some subfolder, but rather create another folder for the text files. This way you can use the file system utilities all you want. The player will be able to see and depending on your format edit it. Which for some cases is positive.
Of course you can have combination where you use one way for some files and the other for other files.
*hugs*
Thanks XD
At the moment im studying something else (something that i really need to do, and fast...), so when im over with it, I'll try it again XD
See ya