Case study 6: Modularity & Components

From Open Surge Wiki
Jump to: navigation, search
Stub
This article is a stub. This typically means the article is a placeholder for more content to come. Knowledgeable users are encouraged to help expand the article.

Modularity

Motivation

Whenever your game gets big, having lots of global variables can make your code difficult to read. The need to remember many of them and what they do may be a big problem.

Fortunately, we can decouple the code. If one day you need to change how specific elements of the game work, you don't need to go through all your scripts and modify a lot of code, because you have used the power of decoupling.

Example

Working example

Let's say our game stores a lot of data related to the player: how long has he or she been playing, how many bonus items have been collected, and so on. You could store those stuff in global variables and get over with it, but then you'd have tightly coupled code. A better way to solve this problem is to have an object to store the data internally, and then talk to that object to retrieve or modify the values.

In the example below, we have a .player_data object which will store all the player data. testObject will talk to .player_data, but notice that globals aren't used for anything other than exchanging variables. This results in decoupled code, and gives .player_data full control over its data. .player_data may be used independently of testObject. The goal is to have as few dependencies as possible.

// stores data related to the player
object .player_data
{
    requires 0.2.0
    always_active

    state main {
        hide
        let $bonus=0
        change_state wait
    }

    state wait {
    }

    // adds $_fun_param1 to the bonus score
    state @add_bonus {
        let $bonus+=$_fun_param1
        return_to_previous_state
    }

    // sets the bonus score to $_fun_value
    state @get_bonus {
        let $_fun_value=$bonus
        return_to_previous_state
    }
}

// will communicate to .player_data
object testObject
{
    requires 0.2.0
    always_active

    state main {
        create_child .player_data // ideally, .player_data should be spawned by the startup object
        change_state retrieve_data
    }

    state retrieve_data {
        change_closest_object_state .player_data @get_bonus
        let $bonus=$_fun_value
        change_state idle
    }

    state update_data {
        let $_fun_param1=10
        change_closest_object_state .player_data @add_bonus
        change_state retrieve_data
    }

    state idle {
        textout default 0 0 "Bonus: $bonus"
        on_button_pressed fire1 update_data
    }
}

Components

TODO