Position and Event logging in Godot

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By hsn

Hi all

I am new to godot and I am doing a project where we are making a board game. I want to log events and also want to log the positions of those events for research purposes e.g if I drag a block onto the board so I want to log what type of event occured and at what coordinates that specific event happened.
I need a starting approach and how to integrate it within my game.

Thanks

Where would you like the logs to be stored? Do you want them sent to a server somewhere?

Eric Ellingson | 2019-11-06 02:58

On a local device, I just need a JSON or CSV file so that I can do research on the data.

hsn | 2019-11-07 10:44

:bust_in_silhouette: Reply From: Eric Ellingson

If you are looking to store the file on the device running the game, then you can do:

var data = {
    # your data goes here
}
var file = File.new()
var filepath = "user://data.json" # or whatever you want to call it
var json_string = to_json(data)
file.open(filepath, File.WRITE)
file.store_string(json_string)
file.close()

if you need to locate the user:// directory of whatever system you’re on, you can use OS.get_user_data_dir()


Sorry, I forgot about the other part of your question. This should work I think, however it is untested so might need some tweaking.

# EventLogger.gd

extends Node

const SAVE_INTERVAL = 10
const FILE_PATH = 'user://events.json'

var events: Array = []
var dirty: bool = false
var timer: Timer = Timer.new()

func _ready():
    timer.wait_time = SAVE_INTERVAL
    timer.one_shot = false
    timer.autostart = true
    timer.connect("timeout", self, "save")

func log_event(event_type: String, event_data: Dictionary):
    var event : Dictionary = {
        'event': event_type,
        'data': event_data,
    };
    
    events.append(events)
    dirty = true

func save():
    # if we haven't logged any new events, don't bother saving the data
    if not dirty:
        return
    
    var file = File.new()
    file.open(FILE_PATH, File.WRITE)
    file.store_string(to_json(events))
    file.close()
    
    dirty = false

The main idea is that you add events to an array, which periodically get saved to file. I don’t know how often you’ll be logging events, so you probably don’t want to write to file evey single time, so I have added a timer to do it every so often. You’ll want to register this as an autoloaded script. Then from any other script, you can do:

func _on_dragged(block):
    EventLogger.log_event('block_added_to_board', block.position)

Of course, you’ll have to set up the function(s) that will call this (not _on_dragged(block)), I don’t know what your setup is like.

Thanks, yeah it will work for storing data.

hsn | 2019-11-10 12:04

@hsn i updated the answer to include something for the actual logging as well. let me know if you have issues with it

Eric Ellingson | 2019-11-10 15:26

Thanks alot for detailed response.

I won’t be logging events after some intervals of time, rather I will have to store events whenever the position of block is changed (I will store the initial positions of all the pentomino blocks, as soon as they are dragged, their x and y coordinates are changed so on that change, I have to store new/updated xy coordinates along with width and height of a block to recognize what kind of block is it and also the timestamp that when this change in position happened). I hope you get what I am trying to say here.

hsn | 2019-11-11 00:30

This will record all events, it just saves to the file only every x-number of seconds so that you aren’t constantly writing to a file.

Eric Ellingson | 2019-11-11 01:03

if you really do just want to just save every time, then get rid of the timer stuff, and change to something like this:

func log_event(event_type: String, event_data: Dictionary):
    var event : Dictionary = {
        'event': event_type,
        'data': event_data,
    };

    events.append(events)
    save()

You may also want to use a timestamp in the json filename so that everytime you boot up the game it outputs to a unique file.

var file_path = 'user://events'

func _ready():
    file_path = "%s-%s.json" % [file_path, str(OS.get_unix_time())]

Eric Ellingson | 2019-11-11 01:06

Well thanks again, this helps (y)

hsn | 2019-11-11 12:11

Hi there :slight_smile: New Godot user here! This was already super helpful, thanks. I can’t figure out though how to apply this in Godot 4. Any way you could help me with that?