I am testing how to store game data using Godot 3.2.2 (I also tested Godot 3.2.3-rc4). When I exported the project (basicly you press a button and 1 is added to the score, which is displayed by a label) on Windows everything worked fine, the score was saved. But when I exported it to my Android phone the data was not saved. In the export setting I have enabled all permissions and in the settings of my phone I enabled the storage permission to my app. Maybe anybody of you can explain this to me and tell me how to solve this problem, so that data is also stored on android.
Code:
extends Node2D
var score = 0
var path = "user://save_file.json"
var save_game_data
func _ready() -> void:
load_data()
set_label_text()
func _on_Button_pressed() -> void:
score += 1
set_label_text()
func set_label_text():
$Label.text = str(score)
func _notification(what: int) -> void:
if what == MainLoop.NOTIFICATION_WM_QUIT_REQUEST:
save_game_data = {
"score": score
}
save_data()
func save_data():
var save_game = File.new()
save_game.open(path, File.WRITE)
save_game.store_line(to_json(save_game_data))
save_game.close()
func load_data():
var save_game = File.new()
if not save_game.file_exists(path):
print("No save file found")
save_data()
return
save_game.open(path, File.READ)
save_game_data = parse_json(save_game.get_line())
score = save_game_data["score"]
print("Saved game loaded", save_game_data)
According to the docs on NOTIFICATION_WM_QUIT_REQUEST:
Implemented on desktop platforms.
NOTIFICATION_WM_QUIT_REQUEST is mainly so you can implement an "Are you sure you want to quit?" dialog, or similar. Mobile platforms generally don't have this option--when you press the home button, the window closes whether it wants to or not.
You could solve this by autosaving whenever the score changes (or at the end of a round, etc).
Related
I am programming an android game with Godot 3.2.2. Of course I want to save the game data, therefore I created a new scene called SaveGame.tscn with SaveGame.gd. I exported the project to my windows pc and everything worked fine, all datas were saved. After that I also exported it to my android phone, but this time no data was saved. Instead it showed me that it could not find the save path. Maybe anybody of you can help me with this problem so that data is also saved on android.
SaveGame.gd:
extends Control
const FILE_NAME = "user://save_game_data_one.json"
var save_game_data
func _ready() -> void:
Signals.connect("load_data", self, "load")
Signals.connect("game_quit", self, "save")
save_game_data = {
"highscore": Globals.highscore,
"coins": Globals.coins,
"music_volume": Globals.music_volume,
"sound_volume": Globals.sound_volume,
"button_gameplay": Globals.button_gameplay,
"button_gameplay_side": Globals.button_gameplay_side,
}
func save():
update_data()
var file = File.new()
file.open(FILE_NAME, File.WRITE)
file.store_string(to_json(save_game_data))
file.close()
func load():
var file = File.new()
if file.file_exists(FILE_NAME):
file.open(FILE_NAME, File.READ)
var data = parse_json(file.get_as_text())
file.close()
if typeof(data) == TYPE_DICTIONARY:
save_game_data = data
else:
printerr("Corrupted data")
else:
self.show() <---- Here it shows me the hidden scene (white rectangle), this means it could not find FILE_NAME
export_data()
func export_data():
Globals.highscore = save_game_data["highscore"]
Globals.coins = save_game_data["coins"]
Globals.music_volume = save_game_data["music_volume"]
Globals.sound_volume = save_game_data["sound_volume"]
Globals.button_gameplay = save_game_data["button_gameplay"]
Globals.button_gameplay_side = save_game_data["button_gameplay_side"]
func update_data():
if Globals.score_round >= Globals.highscore:
save_game_data["highscore"] = Globals.score_round
save_game_data["coins"] += Globals.coins_round
I also would like to know the answer. I am trying to figure a way to have "persistent time" in my android game where "time passes" in game even when closed. Best solution I figure so far is getting the unix time on the games first start and check against it when reopening the app. My problem is finding a way to save that original unix time to call upon for checks.
I have a bot that works flawlessly on desktop's app for Discord and Discord on my personal Android phone/mobile... but the same exact steps done on an IPhone/IOS does not work. I have little to no background on how IOS differs from Android or Windows as I have never owned Apple products...
Primarily, this has to do with when a query has escaped values. Someone enters a value (card name for a TCG bot I'm making) like "Drago's Fury". The ' gets escaped on desktop and android and the card title is put in double quotes versus being left in single quotes on the IOS version. Because of this, when that card's name is compared to a master list of cards, it cannot be found.
Here is how I get the master list that all card names get matched to via a loop...
var sql = `SELECT * FROM ??`
var inserts = ['cardsmaster']
con.query(sql, inserts, (error, rows, fields) => {
let cardsList = []
for (var i in rows) {
cardsList.push(rows[i].name)
}
The following code is run when a user is asked what cards to add. The reply is taken and run through a loop to match to the master list...
async function addToDeckQuestion(){
const agree = "✅"
const disagree = "❌"
let msg = await message.author.send(`Would you like to add cards to ${userdeckname}? Please react with one of the following...`)
await msg.react(agree)
await msg.react(disagree)
const filter = (reaction, user) => {
return ['✅', '❌'].includes(reaction.emoji.name) && user.id === message.author.id;
};
const reply = await msg.awaitReactions(filter, { max: 1 })
.catch(console.error);
const addtodeck = reply.first()
return addtodeck
}
let addtodeck = await addToDeckQuestion();
if (addtodeck.emoji.name == agree){
message.author.send("You have agreed to add cards to this new deck.")
async function cardExists() {
let msg = await message.author.send(`Please provide the cardnames that you would like to add to '${userdeckname}'.\n\n**NOTE:** Please separate each card with a comma and space, like so "Pact of Darkness, Aquos Slam, Karmic Balance"`)
const filter = m => m.author.id === message.author.id
const reply = await msg.channel.awaitMessages(filter, { max: 1 })
.catch(console.error);
let cardsToAdd = await reply.first()
let usercardnamearray = await cardsToAdd.content.split(", ")
let matchedcards = []
let unmatchedcards = []
for (let i = 0; i < usercardnamearray.length; i++) {
usercardnamearray[i] = usercardnamearray[i].replace(/'/gi, "\'");
let found = cardsList.indexOf(`${usercardnamearray[i]}`)
console.log(found)
if (found >= 0) {
matchedcards.push(usercardnamearray[i])
} else if (found == -1){
unmatchedcards.push(usercardnamearray[i])
}
}
console.log('Finished!')
return await [matchedcards, unmatchedcards]
}
let cards = await cardExists();
let matchedcards = await cards[0]
let unmatchedcards = await cards[1]
if (unmatchedcards.length >= 1){
message.author.send(await `The card **${unmatchedcards.join(", ")}** could **NOT** be added. Please check your spelling, capitalization and enter just these card names again!`)
}
So, for example, a user on desktop of Android would follow the step depicted in this image
The below images are from console logging the "found" variable in the code above.
This is how the command is console logged on Desktop and Android:
And this is how the command is console logged on IOS:
I would expect both versions to react to javascript the same way, but something about this doesn't work with IOS nicely. The only difference I have noticed is that Drago's Fury gets put in double quotes in desktop and Android, but not on IOS. I am unsure how to go about fixing this so my IOS users aren't excluded from using the bot entirely.
Any ideas as to why the same info gets interpreted differently in IOS than just about anything else? Thanks in advance for the help!
Since iOS 11, single and double quotation marks are made into their curly alternatives by default. For example, the default ASCII single quote character ' is typed as ‘ or ’ depending on the placement. However, users can turn this off in Settings, so it isn't consistent among all Apple users.
What this means for your code is that the search string is using a different character for the apostrophe in Drago's Fury. Therefore, the search isn't coming back with it because the two characters are actually different.
A simple solution is to replace these characters with the default ASCII characters used in the names.
const str = 'Drago’s Fury';
console.log(str);
const corrected = str.replace(/‘|’/g, '\'');
console.log(corrected);
For some reason, when I restart my PhoneGap app - it looses the localStorage vales that were stored before! I'm saving them in the normal way:
localStorage.setItem("foo","value");
This stores it just fine. However, when you restart the app (or leave the device off for a random amount of time), it seems to randomly loose the data. I've found a heck of a lot of posts about this - but no definative answer on how to get it to be persistent in a PhoneGap Build WebView app,
Any suggestions are much welcomed!
This seems to be quite a common problem with WebView apps:
Android 2.3.6 + Phonegap + localStorage
Android - Making Webview DomStorage persistant after app closed
I can't find a solution that works with PhoneGap Build apps though
An actual example I'm using, is:
var current_id = parseInt(currentId) + 1;
localStorage.setItem("entry_"+current_id,save_string);
localStorage.setItem("entryId",current_id);
..and then to extract it (not that this is important, as the problem is with the data going missing, and not with accessing it)
for (var i = 0; i < localStorage.length; i++){
if (localStorage.key(i).match("entry_")) {
outputString += "\n" + localStorage.getItem(localStorage.key(i));
}
}
I'm wondering if maybe upgrading from PhoneGap Build cli-5.2.0 to cli-6.0.0 may help. I will do this, and give it a whirl.
I guess another option, would be to use a SQL database to locally store the device (its just a bit trickier to setup, and means re-writing my code)
UPDATE: Not the ideal solution - but I have now moved the app over to use WebSQL for the app. It was a bit tricky to get the hang of (never used it before) - but seems to do the job, and shouldn't loose the data :)
EDIT
i tried it like this and it worked:
var current_id = parseInt(currentId) + 1;
localStorage.setItem("entry_"+current_id,save_string);
localStorage.setItem("entryId",current_id);
/*
//this is for checking, what is stored in localStorage
console.log("length: " + localStorage.length);
for(var i = 0; i < localStorage.length; i++) {
console.log(localStorage.key(i));
}
*/
var myEntryIdFromStorage = localStorage.getItem("entryId");
var myItem = localStorage.getItem("entry_" + myEntryIdFromStorage);
Old answer for clarification
How do you get your localstorage?
normally you should store items like you did:
var permanentStorage = window.localstorage;
permanentStorage.setItem("foo", "bar");
and get them back by initializing the permanentStorage the same way and:
//assuming you have permanentStorage in the same script file
//or else you have to initialize it again:
//var permanentStorage = window.localstorage;
var myItem = permanentStorage.getItem("foo");
console.log("myItem: " + myItem);
The method store item uses two parameters: the identifier and the data itself. Please check, that the identifier with which you store your data is the same as the one, with which you get it back.
Do you get any errors? Is the return (stored in my example in myItem) null or undefined or just an empty string? Does this fail in the browser or on the device?
You could clarify your question by providing more code or error messages!
I've a problem adding a record from a form.
When I do clic in a button call to function "save":
var indexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB;
var dataBase = null;
function save() {
dataBase = indexedDB.open("bbdd", 1);
dataBase.onupgradeneeded = function (e) {
active = dataBase.result;
};
dataBase.onsuccess = function (e) {
console.log('Database loaded!');
var active = dataBase.result;
var data = active.transaction(["docs"], "readwrite");
var object = data.objectStore("docs");
var request = object.put({
idDoc: document.querySelector("#idDoc").value,
name: document.querySelector("#name").value,
});
request.onerror = function (e) {
alert(request.error.name + '\n\n' + request.error.message);
};
data.oncomplete = function (e) {
idDoc: document.querySelector("#idDoc").value = '';
name: document.querySelector("#name").value ='';
};
}
dataBase.onerror = function (e) {
console.log('Error loading database');
};
}
Ok. I testing in Chrome and Firefox (Windows XP) and works fine. Data are added to database and fields are cleared.
Now, I built cordova project and run it in a Nexus 5 (Android 5.0.1) with:
cordova run android --devices="myId"
In Nexus 5 donesn't work. When I do click in the button the mobile phone does nothing. Data aren't added to database and fields aren't cleared.
What am I doing wrong?
I have this problem, too. There seems to be a bug on Android 5.0.1 related to the browser storage. This problem happens with localStorage, webSQL and indexDB.
A lot of people are experiencing this: Android 5.0.1 localstorage not persistent.
I made a simple app just for testing. I open the app and I just simply do (I added the code when onDeviceReady - when cordova is loaded):
var a = window.localStorage.getItem('test');
alert(a); //will give you undefined first time
if (!a) {
window.localStorage.setItem('test','12345678');
alert(windows.localStorage.getItem('test');
//this will display 12345678 from localstorage evertime
}
If you close the app after 2 or 3 seconds (force-closing the app) and re-open it, the value of test from localstorage is still undefined. You can do this for 10 times and you will get undefined every time. If you wait 10 or 12 seconds after you open the app and get the alerts, you will notice that after restarting the app (force restart), the data is there and localStorage works correctly.
I tested this on Android 5.0.1 and I used cordova 3.6.3, cordova 4.0, cordova 5.0. I did the same test on a tablet with Android 4.4.2 and the localStorage is set correctly.
I'm using Local Storage to pass values between pages in order to create a scroll to effect (user clicks link and is scrolled to particular part of the page based on ID)
I was previously using cookies but that didn't seem to work on Android, I read that local storage was supported so switched over to that. It works completely fine when in the browser but as soon as its packaged as a native app I lose all functionality? The API states that it should be supported, any ideas?
Here's my code:
Base URL:
var storage = window.localStorage;
$("a.scroll_link").click(function(event) {
event.preventDefault();
var value = $(this).attr("id");
storage.setItem("key",value);
console.log(value);
window.location=$(this).attr("href");
});
Receiving URL:
$(function () {
var value = window.localStorage.getItem("key");
if (value != "" && value != "undefined" && value != null) {
var storage = window.localStorage;
storage.setItem("key",value);
var scroll_type = "";
if ($.browser.webkit) {
scroll_type = "body";
} else {
scroll_type = "html";
}
$(scroll_type)
.stop()
.animate({
//get top-position of target-element and set it as scroll target
scrollTop: ($("#" + value).offset().top - 25)
//scrolldelay: 1.5 seconds
}, {
duration: 1500,
complete: function () {
storage.removeItem("key");
},
});
}
});
The code works fine in the browser just not natively, any ideas?
Thanks,
Use document.addEventListener("deviceready", onDeviceReady, false) instead of $(function(){...}
http://docs.phonegap.com/en/2.5.0/cordova_events_events.md.html#deviceready
1.Glad to know you solve your first problem. As gmh04 say, I think you should replace your init event with 'deviceready' which is triggered when the app start running.
2.
You mean window.localStorage.getItem("key") return null in Receiving URL?
I do not exactly encounter a problem as what you describe. However, you may try to move your code in receiving url to the same page of base url. I have tried for times and be very sure that the localStorage will work in the same page.
I would like add that there's a bug on the 2.6.0 version of cordova.js that make localStorage don't work on Android:
https://issues.apache.org/jira/browse/CB-3063
On the 2.5.0 version it works perfectly, and it is already fix on the 2.7.0 rc.