0 votes

I'm making a mock stock/share trading game, and I'm thinking to implement a little window that draws a line graph displaying values of a variable that is changing price. How would I use Line2D, or any other part of the Godot engine to achieve this?

in Engine by (48 points)

1 Answer

0 votes
Best answer

You can use somthing like this:

extends Line2D

export var graph_width : float = 100
export var graph_height : float = 100

func create_graph(values : Array) -> void:
    var length : int = len(values)
    assert(length > 0 and (values[0] is int or values[0] is float))

    var points_ : PoolVector2Array 

    var maximum : float = values[0]
    var minimum : float = values[0]


    for value in values:
        assert(value is int or value is float)
        if value > maximum:
            maximum = value
        if value < minimum:
            minimum = value

    for index in range(length):
        points_.append(Vector2(
                    lerp(0.0, graph_width, index / float(length - 1)),
                    lerp(graph_height, 0.0, (values[index] - minimum) / (maximum - minimum))))

    points = points_


func _ready():
    create_graph([1, 3, 7, 6, 6, 8, 9, 7, 11, 13])

This will create a graph from Line2D in a given space (graph_height/width)
If you want ths specify minimum and maximum by yourself, you need to expand this a little bit.

by (1,448 points)
selected by

Game_UI.gd:

extends Node2D

const MINIMUM_PRICE = 100.0 # no stock will be priced cheaper than this
const FACTOR = 2.0 # the highest possible price will be 2x your balance
const PROGRESS = 1.0 # adds to noise_progress

var balance : float = 10.0
var price : float = MINIMUM_PRICE
var noise : OpenSimplexNoise
var noise_progress : float = 0.0

onready var pricelabel : Label = $PriceLabel 
onready var graph : Line2D = $Graph

func _ready():
    randomize()

    noise = OpenSimplexNoise.new()
    noise.seed = randi()

    # --- tweak this to your needs ---
    noise.octaves = 4
    noise.period = 20.0
    noise.persistence = 0.8
    # --------------------------------

    generate_stock_price()


func generate_stock_price():
    var noise_modify : float = (balance * (FACTOR / 2.0))
    price = MINIMUM_PRICE + noise_modify 
    price += noise.get_noise_1d(noise_progress) * noise_modify 
    noise_progress += PROGRESS
    pricelabel.update_price(price)
    graph.add_value(price)
    graph.create_graph()

func _on_Timer_timeout():
    generate_stock_price()

func _on_Button_pressed():
    get_tree().change_scene("res://Title Screen/title_screen.tscn")

Graph.gd

(i made some mistakes, here is a better (working) version)

extends Line2D

export var graph_width : float = 100
export var graph_height : float = 100
export var graph_max_points : int = 0 # Zero for unlimited graph-points
export var grow : bool = false

var graph : Array

func create_graph() -> void:
    var length : int = len(graph)
    assert(length > 0 and graph[0] is float and graph_max_points >= 0)

    var points_ : PoolVector2Array = []

    var maximum : float = graph[0]
    var minimum : float = graph[0]

    if length == 1:
        graph.append(graph[0])
        length += 1

    for value in graph:
        assert(value is float)
        if value > maximum:
            maximum = value
        if value < minimum:
            minimum = value

    if minimum == maximum:
        minimum -= 1.0
        maximum += 1.0

    for index in range(length):
        points_.append(Vector2(
            0.0,
            lerp(graph_height, 0.0, (graph[index] - minimum) / (maximum - minimum))))
        if grow and graph_max_points:
            points_[-1].x = lerp(0.0, graph_width, index / float(graph_max_points - 1))
        else:
            points_[-1].x = lerp(0.0, graph_width, index / float(length - 1))

    points = points_

func pop_values() -> void:
    if graph_max_points != 0:
        if len(graph) > graph_max_points:
            graph.pop_front()
            pop_values()

func add_value(value : float) -> void:
    graph.append(value)
    pop_values()

Just copy&paste it. It should be pretty easy to understand what i changed, and how it works.

If you want to understand the OpenSimplexNoise, i would recommand you, to create a noise-texture, and play with the values in the inspector. There you see a live-preview of what you would get. Just imagine a line from left to right in the texture. Thats what the 1D-Noise whould be. black is -1.0, grey is 0.0 and white is 1.0. Darker grey is then somthing between -1.0 and 0.0.

Hello, it's me again! I implemented a saving and loading mechanic, and want to make sure the stock price would be saved and loaded too. It saves, and it's in the save file, but it doesn't get loaded. Would the problem be with the variable itself or the way price is generated?

Please start a new topic :)
dont forget to show us your code and make a good description what you expect to happen, and what does not work.

Yes, sorry of course, just you've been so helpful I grew accustomed to going to you for help. Thank you :>

Its just because the title is something about graphs, and now you have trouble with saving/loading ;)
Maybe in the future someone has similar problems like you, and than it's easy to find, if the problem matches the title :P

Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to webmaster@godotengine.org with your username.