Out of Memory - Title, Menu, & Character Selection Screens

Bruce

Active member
Hello everyone,

I've posted my question regarding to this issue in another topic, but I think it is better for me to create a topic and post all my code.
I started learning how to add backgrounds and animations with arraylist to the title, menu, and character selection screens.
If I just start the game normally, there is no issue.
If I just loop the title, menu, then character selection screens back and forth for a while (40-50 times),
it would cause out of memory. I know that no one would be crazy enough to loop the screens back and forth like this,
but still it should not be out of memory if it was coded correctly.
Furthermore, if I start the game and then quit the game, and repeat the loop above, it causes out of memory alot quicker.
Also, if I don't comment out these 2 functions in the title screen
Code:
ClearGlobalArrays();  
SetupArrayLists();
and
Code:
ClearGlobalArrays()  in inLevelLoop(),
it causes out of memory alot quicker. It seems like it adds more stuff to the memory instead of removing them when I start looping back and forth , but why?????

Obviously, I didn't code it correctly....
Please any help, advises, comments to help me with better coding/route/understanding, would be greatly appreciated

Video link: Out of memory at the end of the video
Notice: this is just a tryout...

updated.c
Code:
#include "data/scripts/common/constants.h"
#include "data/scripts/story/story_clear.c"
#include "data/scripts/story.c"
#include "data/scripts/gettick.c"
#include "data/scenes/ScreenAnim.c"

#define BG_TITLE1          0
#define BG_TITLE2          1
#define BG_MENU1           2
#define BG_MENU2           3
#define BG_SELECT1         4
#define BG_BLK             5

//       ANIM_TITLE0       0   // NOT USED
#define ANIM_TITLE1        1                        
#define ANIM_TITLE2        2
#define ANIM_TITLE3        3
#define ANIM_TITLE4        4
#define ANIM_SELECT1       5
#define ANIM_SELECT2       6



void oncreate(){  
    InitializeVariables();
}

void ondestroy(){
    log("LOG: ON_DESTROY \n");
    ClearGlobalArrays();
    clearStory();
    clearglobalvar();
    clearlocalvar();
}

void main()
{
    if(openborvariant("current_scene")=="data/levels/scenes/credits/credits.txt")
    {
        clearStory();
        InitializeVariables();
    }
   
    mainLoop();
   
    if(openborvariant("in_selectscreen")){
        int TitleCounter = getlocalvar("TitleCounter");
        if(TitleCounter > 0){
    /*    ClearGlobalArrays();   //these causing the out of memory much quicker!
            SetupArrayLists();  */
            setlocalvar("TitleCounter", 0);
            void TitleAnimList = getglobalvar("List_TitleAnim");
            if(TitleAnimList != NULL())
            {               // GlobalVarIndex, Entity, XYZ
               SpawnScreenAnim(ANIM_SELECT1, "SelectAnim1", 961, 541, -2000);
               SpawnScreenAnim(ANIM_SELECT2, "SelectAnim2", 800, 500, 1);
            }  
        }
        void BG_List = getglobalvar("List_TitleBG");
        void SelectBG = get(BG_List, BG_SELECT1);
        if(SelectBG != NULL()){
            changedrawmethod(NULL(), "alpha", 0);
            drawsprite(SelectBG, 0, 0, 0);
        }
    }
}

void mainLoop()
{
    if(openborvariant("in_level")){
        inLevelLoop();
    }
    else
    {
        if(openborvariant("current_scene") == "data/scenes/intro.txt"){
            int TitleCounter = getlocalvar("TitleCounter");
            if(TitleCounter == NULL() || TitleCounter > 0){
                setlocalvar("TitleCounter", 0);
            }
        }

        else if(openborvariant("in_titlescreen")){
            int TitleCounter = getlocalvar("TitleCounter");
            if(TitleCounter != 1){
                clearStory();
                // InitializeVariables();
                playwebm("data/scenes/Press_Start_Screen.webm", 0);  // 0 = skippable
               
                void TitleAnimList = getglobalvar("List_TitleAnim");
                if(TitleAnimList != NULL())
                {
                    void SelectAnim1 = get(TitleAnimList, ANIM_SELECT1);
                    if(SelectAnim1 != NULL()){
                        killentity(SelectAnim1);
                    }
                    void SelectAnim2 = get(TitleAnimList, ANIM_SELECT2);
                    if(SelectAnim2 != NULL()){
                        killentity(SelectAnim2);
                    }
                }
                   
                if(TitleAnimList != NULL())
                {               // GlobalVarIndex, Entity, XYZ
                   SpawnScreenAnim(ANIM_TITLE1, "TitleAnim1", 500, 500, -1);
                   SpawnScreenAnim(ANIM_TITLE2, "TitleAnim2", 800, 500, -1);
                }              
               
                setlocalvar("TitleCounter", 1);
                playmusic("data/music/Title.ogg", 1);
            }
           
            drawstring(20,20,0, "TITLE");
            void BG_List = getglobalvar("List_TitleBG");
            void TitleBG = get(BG_List, BG_TITLE1); // see SetupArrayLists() for details
            if(TitleBG != NULL()){
                changedrawmethod(NULL(), "alpha", 0);
                drawsprite(TitleBG, 0, 0, -2);
            }
            void BlackMask = get(BG_List, BG_BLK);
            if(BlackMask != NULL()){
                changedrawmethod(NULL(), "alpha", 6);  // 50% transparency
                drawsprite(BlackMask, 0, 0, -1);
            }          
        }
       
        else if(openborvariant("in_menuscreen")){
            drawstring(20,20,0, "MENU");
            int TitleCounter = getlocalvar("TitleCounter");
             if(TitleCounter != 2)
            {
                setlocalvar("TitleCounter", 2);
                playmusic("data/music/Menu.ogg", 1);

                void TitleAnimList = getglobalvar("List_TitleAnim");
                if(TitleAnimList != NULL())
                {
                    void TitleAnim1 = get(TitleAnimList, ANIM_TITLE1);
                    if(TitleAnim1 != NULL()){
                        killentity(TitleAnim1);
                    }
                    void TitleAnim2 = get(TitleAnimList, ANIM_TITLE2);
                    if(TitleAnim2 != NULL()){
                        killentity(TitleAnim2);
                    }
                }
             }    
   
            void BG_List = getglobalvar("List_TitleBG");
            void MenuBG = get(BG_List, BG_MENU1);
            if(MenuBG != NULL()){
                changedrawmethod(NULL(), "alpha", 0);
                drawsprite(MenuBG, 0, 0, -1);
            }
            void BlackMask = get(BG_List, BG_BLK);
            if(BlackMask != NULL()){
                changedrawmethod(NULL(), "alpha", 6);  // 50% transparency
                drawsprite(BlackMask, 0, 0, -1);
            }
        }
    }
}

void InitializeVariables()
{
    setglobalvar("LevelFirstStart", 1);
    SetupArrayLists();
}

void inLevelLoop()
{
    turnWhite();
    storySystem();
    int LevelFirstStart = getglobalvar("LevelFirstStart");
    if(LevelFirstStart > 0)
    {
        setglobalvar("LevelFirstStart", 0);
        // ClearGlobalArrays();
    }
}
   
void SetupArrayLists()
{
    void TitleBG_List = getglobalvar("List_TitleBG");
    if(!TitleBG_List || TitleBG_List == NULL())
    {
        TitleBG_List = array(2);  //array(2) means total of 3 items
        set(TitleBG_List, BG_TITLE1, loadsprite("data/scenes/TitleScreen.png"));
        set(TitleBG_List, BG_TITLE2, NULL());
        set(TitleBG_List, BG_MENU1, loadsprite("data/scenes/MenuScreen.png"));
        set(TitleBG_List, BG_MENU2, NULL());
        set(TitleBG_List, BG_SELECT1, loadsprite("data/bgs/select.png"));
        set(TitleBG_List, BG_BLK, loadsprite("data/scenes/black.gif"));
        setglobalvar("List_TitleBG", TitleBG_List);
    }

    void AnimList = getglobalvar("List_TitleAnim");
    if(!AnimList || AnimList == NULL())
    {
        AnimList = array(3);  //array(3) means total of 4 items
        set(AnimList, 0, NULL());  //  NOT USED
        set(AnimList, ANIM_TITLE1, NULL());  // Title Animation 1
        set(AnimList, ANIM_TITLE2, NULL());
        set(AnimList, ANIM_TITLE3, NULL());
        set(AnimList, ANIM_TITLE4, NULL());
        set(AnimList, ANIM_SELECT1, NULL());
        set(AnimList, ANIM_SELECT2, NULL());
        setglobalvar("List_TitleAnim", AnimList);
    }
}  
   
void ClearGlobalArrays()
{
    int i;
    void BG_List = getglobalvar("List_TitleBG");

    if(BG_List)
    {
        for(i=0; i<size(BG_List); i++)
        {
            set(BG_List, i, NULL());
        }
        free(BG_List);
        setglobalvar("List_TitleBG", NULL());
    }
    void Anim_List = getglobalvar("List_TitleAnim");
    if(Anim_List)
    {
        for(i=0; i<size(Anim_List); i++)
        {
            set(Anim_List, i, NULL());
        }
        free(Anim_List);
        setglobalvar("List_TitleAnim", NULL());
    }
}

ScreenAnim.c:
Code:
void SpawnScreenAnim(int ArrayIndex, void AnimatedEntity, int X, int Y, int Z)
{
        void vSpawn;
        void subent;

        void AnimList = getglobalvar("List_TitleAnim");
        if(AnimList != NULL())
        {
            void TitleAnim = get(AnimList, ArrayIndex);
            if(TitleAnim != NULL()){
               killentity(TitleAnim); //Kill previous spawned enity to avoid duplicated entities
            }
        }
       
        loadmodel(AnimatedEntity); // name of the entity to be loaded
        clearspawnentry(); // clean the spawn entry
        setspawnentry("name", AnimatedEntity); // define the entity to be spawn
        setspawnentry("coords", X, Y, Z); // set the position of the entity
        subent=spawn();  //  spawn the entity
        if(AnimList != NULL())
        {
            set(AnimList, ArrayIndex, subent);
            setglobalvar("List_TitleAnim", AnimList);
        }
        changeentityproperty(subent, "position", X, Y, Z);//for safe, set again the position

}

SelectAnim1.txt
Code:
name         SelectAnim1
health         1
type         panel
speed         10
shadow     0
setlayer     -2000
facing         1

anim idle
    loop 1 1
    offset    961 541
    delay    15
    @cmd changeentityproperty getlocalvar("self") "direction" 1
    frame    data/scenes/SelectAnim/SelectAnim01.png
    @cmd changeentityproperty getlocalvar("self") "setlayer" -2000
    frame    data/scenes/SelectAnim/SelectAnim02.png
    frame    data/scenes/SelectAnim/SelectAnim03.png
    frame    data/scenes/SelectAnim/SelectAnim04.png
    frame    data/scenes/SelectAnim/SelectAnim05.png
    frame    data/scenes/SelectAnim/SelectAnim06.png
    frame    data/scenes/SelectAnim/SelectAnim07.png
    frame    data/scenes/SelectAnim/SelectAnim08.png
    frame    data/scenes/SelectAnim/SelectAnim09.png
    frame    data/scenes/SelectAnim/SelectAnim10.png
    frame    data/scenes/SelectAnim/SelectAnim11.png
    frame    data/scenes/SelectAnim/SelectAnim12.png
    frame    data/scenes/SelectAnim/SelectAnim13.png
    frame    data/scenes/SelectAnim/SelectAnim14.png
    frame    data/scenes/SelectAnim/SelectAnim15.png
    frame    data/scenes/SelectAnim/SelectAnim16.png
    frame    data/scenes/SelectAnim/SelectAnim17.png
    frame    data/scenes/SelectAnim/SelectAnim18.png
    frame    data/scenes/SelectAnim/SelectAnim19.png
    frame    data/scenes/SelectAnim/SelectAnim20.png
    frame    data/scenes/SelectAnim/SelectAnim21.png
    frame    data/scenes/SelectAnim/SelectAnim22.png
    frame    data/scenes/SelectAnim/SelectAnim23.png
    frame    data/scenes/SelectAnim/SelectAnim24.png
    frame    data/scenes/SelectAnim/SelectAnim25.png
    frame    data/scenes/SelectAnim/SelectAnim26.png
    frame    data/scenes/SelectAnim/SelectAnim27.png
    frame    data/scenes/SelectAnim/SelectAnim28.png
    frame    data/scenes/SelectAnim/SelectAnim29.png
    frame    data/scenes/SelectAnim/SelectAnim30.png

Thank you very much
 
Hello everyone,

I've posted my question regarding to this issue in another topic, but I think it is better for me to create a topic and post all my code.
I started learning how to add backgrounds and animations with arraylist to the title, menu, and character selection screens.
If I just start the game normally, there is no issue.
If I just loop the title, menu, then character selection screens back and forth for a while (40-50 times),
it would cause out of memory. I know that no one would be crazy enough to loop the screens back and forth like this,
but still it should not be out of memory if it was coded correctly.
Furthermore, if I start the game and then quit the game, and repeat the loop above, it causes out of memory alot quicker.
Also, if I don't comment out these 2 functions in the title screen
Code:
ClearGlobalArrays(); 
SetupArrayLists();
and
Code:
ClearGlobalArrays()  in inLevelLoop(),
it causes out of memory alot quicker. It seems like it adds more stuff to the memory instead of removing them when I start looping back and forth , but why?????

Obviously, I didn't code it correctly....
Please any help, advises, comments to help me with better coding/route/understanding, would be greatly appreciated

Video link: Out of memory at the end of the video
Notice: this is just a tryout...

updated.c
Code:
#include "data/scripts/common/constants.h"
#include "data/scripts/story/story_clear.c"
#include "data/scripts/story.c"
#include "data/scripts/gettick.c"
#include "data/scenes/ScreenAnim.c"

#define BG_TITLE1          0
#define BG_TITLE2          1
#define BG_MENU1           2
#define BG_MENU2           3
#define BG_SELECT1         4
#define BG_BLK             5

//       ANIM_TITLE0       0   // NOT USED
#define ANIM_TITLE1        1                       
#define ANIM_TITLE2        2
#define ANIM_TITLE3        3
#define ANIM_TITLE4        4
#define ANIM_SELECT1       5
#define ANIM_SELECT2       6



void oncreate(){ 
    InitializeVariables();
}

void ondestroy(){
    log("LOG: ON_DESTROY \n");
    ClearGlobalArrays();
    clearStory();
    clearglobalvar();
    clearlocalvar();
}

void main()
{
    if(openborvariant("current_scene")=="data/levels/scenes/credits/credits.txt")
    {
        clearStory();
        InitializeVariables();
    }
  
    mainLoop();
  
    if(openborvariant("in_selectscreen")){
        int TitleCounter = getlocalvar("TitleCounter");
        if(TitleCounter > 0){
    /*    ClearGlobalArrays();   //these causing the out of memory much quicker!
            SetupArrayLists();  */
            setlocalvar("TitleCounter", 0);
            void TitleAnimList = getglobalvar("List_TitleAnim");
            if(TitleAnimList != NULL())
            {               // GlobalVarIndex, Entity, XYZ
               SpawnScreenAnim(ANIM_SELECT1, "SelectAnim1", 961, 541, -2000);
               SpawnScreenAnim(ANIM_SELECT2, "SelectAnim2", 800, 500, 1);
            } 
        }
        void BG_List = getglobalvar("List_TitleBG");
        void SelectBG = get(BG_List, BG_SELECT1);
        if(SelectBG != NULL()){
            changedrawmethod(NULL(), "alpha", 0);
            drawsprite(SelectBG, 0, 0, 0);
        }
    }
}

void mainLoop()
{
    if(openborvariant("in_level")){
        inLevelLoop();
    }
    else
    {
        if(openborvariant("current_scene") == "data/scenes/intro.txt"){
            int TitleCounter = getlocalvar("TitleCounter");
            if(TitleCounter == NULL() || TitleCounter > 0){
                setlocalvar("TitleCounter", 0);
            }
        }

        else if(openborvariant("in_titlescreen")){
            int TitleCounter = getlocalvar("TitleCounter");
            if(TitleCounter != 1){
                clearStory();
                // InitializeVariables();
                playwebm("data/scenes/Press_Start_Screen.webm", 0);  // 0 = skippable
              
                void TitleAnimList = getglobalvar("List_TitleAnim");
                if(TitleAnimList != NULL())
                {
                    void SelectAnim1 = get(TitleAnimList, ANIM_SELECT1);
                    if(SelectAnim1 != NULL()){
                        killentity(SelectAnim1);
                    }
                    void SelectAnim2 = get(TitleAnimList, ANIM_SELECT2);
                    if(SelectAnim2 != NULL()){
                        killentity(SelectAnim2);
                    }
                }
                  
                if(TitleAnimList != NULL())
                {               // GlobalVarIndex, Entity, XYZ
                   SpawnScreenAnim(ANIM_TITLE1, "TitleAnim1", 500, 500, -1);
                   SpawnScreenAnim(ANIM_TITLE2, "TitleAnim2", 800, 500, -1);
                }             
              
                setlocalvar("TitleCounter", 1);
                playmusic("data/music/Title.ogg", 1);
            }
          
            drawstring(20,20,0, "TITLE");
            void BG_List = getglobalvar("List_TitleBG");
            void TitleBG = get(BG_List, BG_TITLE1); // see SetupArrayLists() for details
            if(TitleBG != NULL()){
                changedrawmethod(NULL(), "alpha", 0);
                drawsprite(TitleBG, 0, 0, -2);
            }
            void BlackMask = get(BG_List, BG_BLK);
            if(BlackMask != NULL()){
                changedrawmethod(NULL(), "alpha", 6);  // 50% transparency
                drawsprite(BlackMask, 0, 0, -1);
            }         
        }
      
        else if(openborvariant("in_menuscreen")){
            drawstring(20,20,0, "MENU");
            int TitleCounter = getlocalvar("TitleCounter");
             if(TitleCounter != 2)
            {
                setlocalvar("TitleCounter", 2);
                playmusic("data/music/Menu.ogg", 1);

                void TitleAnimList = getglobalvar("List_TitleAnim");
                if(TitleAnimList != NULL())
                {
                    void TitleAnim1 = get(TitleAnimList, ANIM_TITLE1);
                    if(TitleAnim1 != NULL()){
                        killentity(TitleAnim1);
                    }
                    void TitleAnim2 = get(TitleAnimList, ANIM_TITLE2);
                    if(TitleAnim2 != NULL()){
                        killentity(TitleAnim2);
                    }
                }
             }   
  
            void BG_List = getglobalvar("List_TitleBG");
            void MenuBG = get(BG_List, BG_MENU1);
            if(MenuBG != NULL()){
                changedrawmethod(NULL(), "alpha", 0);
                drawsprite(MenuBG, 0, 0, -1);
            }
            void BlackMask = get(BG_List, BG_BLK);
            if(BlackMask != NULL()){
                changedrawmethod(NULL(), "alpha", 6);  // 50% transparency
                drawsprite(BlackMask, 0, 0, -1);
            }
        }
    }
}

void InitializeVariables()
{
    setglobalvar("LevelFirstStart", 1);
    SetupArrayLists();
}

void inLevelLoop()
{
    turnWhite();
    storySystem();
    int LevelFirstStart = getglobalvar("LevelFirstStart");
    if(LevelFirstStart > 0)
    {
        setglobalvar("LevelFirstStart", 0);
        // ClearGlobalArrays();
    }
}
  
void SetupArrayLists()
{
    void TitleBG_List = getglobalvar("List_TitleBG");
    if(!TitleBG_List || TitleBG_List == NULL())
    {
        TitleBG_List = array(2);  //array(2) means total of 3 items
        set(TitleBG_List, BG_TITLE1, loadsprite("data/scenes/TitleScreen.png"));
        set(TitleBG_List, BG_TITLE2, NULL());
        set(TitleBG_List, BG_MENU1, loadsprite("data/scenes/MenuScreen.png"));
        set(TitleBG_List, BG_MENU2, NULL());
        set(TitleBG_List, BG_SELECT1, loadsprite("data/bgs/select.png"));
        set(TitleBG_List, BG_BLK, loadsprite("data/scenes/black.gif"));
        setglobalvar("List_TitleBG", TitleBG_List);
    }

    void AnimList = getglobalvar("List_TitleAnim");
    if(!AnimList || AnimList == NULL())
    {
        AnimList = array(3);  //array(3) means total of 4 items
        set(AnimList, 0, NULL());  //  NOT USED
        set(AnimList, ANIM_TITLE1, NULL());  // Title Animation 1
        set(AnimList, ANIM_TITLE2, NULL());
        set(AnimList, ANIM_TITLE3, NULL());
        set(AnimList, ANIM_TITLE4, NULL());
        set(AnimList, ANIM_SELECT1, NULL());
        set(AnimList, ANIM_SELECT2, NULL());
        setglobalvar("List_TitleAnim", AnimList);
    }
} 
  
void ClearGlobalArrays()
{
    int i;
    void BG_List = getglobalvar("List_TitleBG");

    if(BG_List)
    {
        for(i=0; i<size(BG_List); i++)
        {
            set(BG_List, i, NULL());
        }
        free(BG_List);
        setglobalvar("List_TitleBG", NULL());
    }
    void Anim_List = getglobalvar("List_TitleAnim");
    if(Anim_List)
    {
        for(i=0; i<size(Anim_List); i++)
        {
            set(Anim_List, i, NULL());
        }
        free(Anim_List);
        setglobalvar("List_TitleAnim", NULL());
    }
}

ScreenAnim.c:
Code:
void SpawnScreenAnim(int ArrayIndex, void AnimatedEntity, int X, int Y, int Z)
{
        void vSpawn;
        void subent;

        void AnimList = getglobalvar("List_TitleAnim");
        if(AnimList != NULL())
        {
            void TitleAnim = get(AnimList, ArrayIndex);
            if(TitleAnim != NULL()){
               killentity(TitleAnim); //Kill previous spawned enity to avoid duplicated entities
            }
        }
      
        loadmodel(AnimatedEntity); // name of the entity to be loaded
        clearspawnentry(); // clean the spawn entry
        setspawnentry("name", AnimatedEntity); // define the entity to be spawn
        setspawnentry("coords", X, Y, Z); // set the position of the entity
        subent=spawn();  //  spawn the entity
        if(AnimList != NULL())
        {
            set(AnimList, ArrayIndex, subent);
            setglobalvar("List_TitleAnim", AnimList);
        }
        changeentityproperty(subent, "position", X, Y, Z);//for safe, set again the position

}

SelectAnim1.txt
Code:
name         SelectAnim1
health         1
type         panel
speed         10
shadow     0
setlayer     -2000
facing         1

anim idle
    loop 1 1
    offset    961 541
    delay    15
    @cmd changeentityproperty getlocalvar("self") "direction" 1
    frame    data/scenes/SelectAnim/SelectAnim01.png
    @cmd changeentityproperty getlocalvar("self") "setlayer" -2000
    frame    data/scenes/SelectAnim/SelectAnim02.png
    frame    data/scenes/SelectAnim/SelectAnim03.png
    frame    data/scenes/SelectAnim/SelectAnim04.png
    frame    data/scenes/SelectAnim/SelectAnim05.png
    frame    data/scenes/SelectAnim/SelectAnim06.png
    frame    data/scenes/SelectAnim/SelectAnim07.png
    frame    data/scenes/SelectAnim/SelectAnim08.png
    frame    data/scenes/SelectAnim/SelectAnim09.png
    frame    data/scenes/SelectAnim/SelectAnim10.png
    frame    data/scenes/SelectAnim/SelectAnim11.png
    frame    data/scenes/SelectAnim/SelectAnim12.png
    frame    data/scenes/SelectAnim/SelectAnim13.png
    frame    data/scenes/SelectAnim/SelectAnim14.png
    frame    data/scenes/SelectAnim/SelectAnim15.png
    frame    data/scenes/SelectAnim/SelectAnim16.png
    frame    data/scenes/SelectAnim/SelectAnim17.png
    frame    data/scenes/SelectAnim/SelectAnim18.png
    frame    data/scenes/SelectAnim/SelectAnim19.png
    frame    data/scenes/SelectAnim/SelectAnim20.png
    frame    data/scenes/SelectAnim/SelectAnim21.png
    frame    data/scenes/SelectAnim/SelectAnim22.png
    frame    data/scenes/SelectAnim/SelectAnim23.png
    frame    data/scenes/SelectAnim/SelectAnim24.png
    frame    data/scenes/SelectAnim/SelectAnim25.png
    frame    data/scenes/SelectAnim/SelectAnim26.png
    frame    data/scenes/SelectAnim/SelectAnim27.png
    frame    data/scenes/SelectAnim/SelectAnim28.png
    frame    data/scenes/SelectAnim/SelectAnim29.png
    frame    data/scenes/SelectAnim/SelectAnim30.png

Thank you very much
I see you are using many abbreviations in script functions, it's a bit hard to point where the problem is exactly. However, I suppose that this may be a loop involving loadsprite function.

Unlike the loadmodel or loadsample, the loadsprite will accumulate in the memory if you are loading the same asset until the engine crashes. Maybe your script is allowing more than 1 cycle for the loadsprite step, causing the memory overload.

Here's an example, look how the "used ram" will go crazy if I don't add any limitation to the loadsprite fuction. In addition, even if you limit the sprite loading, you should free it through the free() function before clearing the variable, otherwise you will load the same sprite again.

Before suggesting any alternative for your script, I suggest first comment all the lines related to loadsprite/drawsprite and see if it solves the problem. If yes, certainly there's a problem with the scripts that are loading/clearing the sprites.
 
Unlike the loadmodel or loadsample, the loadsprite will accumulate in the memory if you are loading the same asset until the engine crashes. Maybe your script is allowing more than 1 cycle for the loadsprite step, causing the memory overload.
If you take a look at the function ClearGlobalArrays(), there are free() function inside. I know it's not a good naming, so I'll rename it.

If I understand it correctly, if I don't unload the sprites and everytime I use drawsprite(), it would add more memory.
Basically, it adds 50 times more memory when I loop the title and selection screens back and forth 50 times?

I've tried to free(): then the loadsprites again everytime it gets to character selection screen or title screen.
However, this seems to overload the memory quicker.

What's a proper way to load and unload sprites between title, menu, selection screens? I'm not at home atm44.

Thank you
 
If I understand it correctly, if I don't unload the sprites and everytime I use drawsprite(), it would add more memory.
No, indeed you need to free the sprites before clearing the variables, it's due to the clearglobalvar() function you are using. Otherwise you will lose the reference for the sprites already loaded and the new loaded sprite will accumulate in the memory together with the old sprites.

1718427570027.png

But what I meant was that you need to put a variable as a flag in order to stop the sprite loading task and run once. Keep in mind that update scripts run at each engine cycle, it means a lot of times per second. So, let's suppose that each second contains 200 cycles, the script will run 200 times in a single second and will load the same sprite 200 times in a second, this is what's happening in the video I posted.

As an example, this is a shortened version of my script used to load sprites at the title screen. You can see that in the end of the script there's a variable as a flag to stop the loading proccess, then it will only run again at the title screen where all variables are cleared and then reloaded.
C:
void saveAssets()
{//Load global assets for further use

    if(getglobalvar("saveAssets") == NULL()){ //FLAG IS NULL?? SAVE ALL SPRITES INTO VARIABLES
       
        //GLOBAL USAGE
        setglobalvar("borders", loadsprite("data/sprites/borders.png"));
        setglobalvar("charHud", loadsprite("data/sprites/charhud.png"));
       
        //SET FLAG TO 1 IN ORDER TO STOP THE PROCCESS UNTIL ALL GLOBAL VARIABLES ARE CLEARED AGAIN
        setglobalvar("saveAssets", 1);
    }
}
 
What's a proper way to load and unload sprites between title, menu, selection screens? I'm not at home atm44.
The proper way to unload is by first running the free() function and then clearing the variable using NULL() or clearglobalvar().

C:
free(getglobalvar("charhud"));
clearglobalvar();
Or
C:
free(getglobalvar("charhud"));
setglobalvar("charhud", NULL());

At the title screen, you can run the free/clear tasks first and then run the loadsprite/setglobalvar tasks. Don't forget to use variables as flags in order to stop any process at the end of the script, you can use global variables for that because it will keep all loaded data into memory until you finish the playthrough and go to the title screen again.
 
The proper way to unload is by first running the free() function and then clearing the variable using NULL() or clearglobalvar().

free(getglobalvar("charhud"));
clearglobalvar();[/CODE]Or
C:
free(getglobalvar("charhud"));
setglobalvar("charhud", NULL());
So after you unload them, then load them again with these?
Code:
setglobalvar("borders", loadsprite("data/sprites/borders.png"));
setglobalvar("charHud", loadsprite("data/sprites/charhud.png"));
That's what I was trying to do, but with an array instead. Maybe I didn't setup or free the array correctly.
I also had the counters that make sure the sprites only load once.

Can you take a look at my SetupArrayLists() and ClearGlobalArrays() functions to see if they are ok?
I'm not at home to try out your suggestions yet.
Thank you
 
That's what I was trying to do, but with an array instead. Maybe I didn't setup or free the array correctly.
I also suggest putting all the scripts in the void main() instead of oncreate/ondestroy to see if the problem happens.

Can you take a look at my SetupArrayLists() and ClearGlobalArrays() functions to see if they are ok?
Like I said, there's many abbreviations in your functions and I didn't understand very well how your code should work. Did you try to disable both loadsprite/drawsprite to see if the problem persists?
 
I also suggest putting all the scripts in the void main() instead of oncreate/ondestroy to see if the problem happens.
I will try that.

Like I said, there's many abbreviations in your functions and I didn't understand very well how your code should work. Did you try to disable both loadsprite/drawsprite to see if the problem persists?
lol I need to work on better abbreviations then.
Not yet because I am not home until later tonight.

Haven't said that, I think I've found part of the problem in the SetupArrayLists() function.
Take a look at the comments where I wrote all caps below.
I added more items to the array list but forgot to update the array(x).
Basically when I tried to free all the items in the ClearGlobalArrays() function,
it wouldn't free all the items because the array(x) is shorter than the actual list of items.

Code:
void SetupArrayLists()
{
    void TitleBG_List = getglobalvar("List_TitleBG");
    if(!TitleBG_List || TitleBG_List == NULL())
    {
        TitleBG_List = array(2);  //array(2) //THIS SHOULD BE array(5)
        set(TitleBG_List, BG_TITLE1, loadsprite("data/scenes/TitleScreen.png"));
        set(TitleBG_List, BG_TITLE2, NULL());
        set(TitleBG_List, BG_MENU1, loadsprite("data/scenes/MenuScreen.png"));
        set(TitleBG_List, BG_MENU2, NULL());
        set(TitleBG_List, BG_SELECT1, loadsprite("data/bgs/select.png"));
        set(TitleBG_List, BG_BLK, loadsprite("data/scenes/black.gif"));
        setglobalvar("List_TitleBG", TitleBG_List);
    }

    void AnimList = getglobalvar("List_TitleAnim");
    if(!AnimList || AnimList == NULL())
    {
        AnimList = array(3);  //THIS SHOULD BE array(6)
        set(AnimList, 0, NULL());
        set(AnimList, ANIM_TITLE1, NULL());
        set(AnimList, ANIM_TITLE2, NULL());
        set(AnimList, ANIM_TITLE3, NULL());
        set(AnimList, ANIM_TITLE4, NULL());
        set(AnimList, ANIM_SELECT1, NULL());
        set(AnimList, ANIM_SELECT2, NULL());
        setglobalvar("List_TitleAnim", AnimList);
    }
}

Thank you
 
Did you try to disable both loadsprite/drawsprite to see if the problem persists?
I disabled them and fixed the array(x), and it's alot better now, but it eventually overloads the memory regardless.
something is leaking the memory, maybe the screen animations?
But still if I spawn the screen animations and destroy them with killentity then free them from the globalvar or localvar,
shouldn't they be removed off the memory?
I can't understand how the memory keeps getting larger and larger for looping back and forth with the same stuff between the screens like this.

I am tagging @DCurrent for help, thank you


Edit: I've even tried them with no arrays as well
 
Last edited:
I removed the array lists, 2 sprites, and limited to 1 animation per screen, and use localvar instead of globalvar. Now it can run 357 times before it freezes.
I guess I am happy with it for now. However, I still would like to understand why the it overloads the memory overtime with the array lists and more sprites on the screen like that. Especially, I wasn't even loading that many sprites and animations. Maybe there was memory leakage somewhere....
 
Last edited:
I removed the array lists, 2 sprites, and limited to 1 animation per screen, and use localvar instead of globalvar. Now it can run 357 times before it freezes.
I guess I am happy with it for now. However, I still would like to understand why the it overloads the memory overtime with the array lists and more sprites on the screen like that. Especially, I wasn't even loading that many sprites and animations. Maybe there was memory leakage somewhere....
I suggest disabling all the scripts and then reactivating one by one gradually in order to see when the memory issue starts. In addition, I suggest looking for other things like loadmodel(), maybe the crash is not related with the sprites.
 
I suggest disabling all the scripts and then reactivating one by one gradually in order to see when the memory issue starts. In addition, I suggest looking for other things like loadmodel(), maybe the crash is not related with the sprites.
I created a title and menu video in Filmora myself and extracted the png files for the title and menu animations last night.
They overloaded the memory very quickly. I think it may have to do with the way I converted them to indexed png files with the batch converter that I created myself in Photoshop. Last year I normally used GIMP then PalApply V.2, but the sprites didn't turn out as good as Photoshop because some sprites looked blurry at some areas or messy colors depending on the images.
I've figured Photoshop can do better job, but the problem is that I am still trying to find the best way to convert them to indexed png files without problems.
Most of my sprites come from the videos that I captured from UMVC3. Index conversion is tricky and it always gets me :-(
 
Last year I normally used GIMP then PalApply V.2, but the sprites didn't turn out as good as Photoshop because some sprites looked blurry at some areas or messy colors depending on the images.
I've figured Photoshop can do better job, but the problem is that I am still trying to find the best way to convert them to indexed png files without problems.

Then, put simply, you are doing it wrong.

An indexed image is an indexed image. It's lossless compression, and if done correctly there is absolutely no difference between them.

Im not trying to be harsh, but over and over it seems you try to reinvent the wheel, then come to us with odd problems as a result. Stop. It. Follow the instructions we give, and I promise most of your issues will fix themselves.

DC
 
An indexed image is an indexed image. It's lossless compression, and if done correctly there is absolutely no difference between them.
Sorry I do apologize for asking questions and I do very appreciate for those who have tried to help me. I wasn't trying to be an idiot. As far as index conversion, I did try to follow the exact step by step instructions that they had on this forum. If it was working fine for all the sprites I have, I would not be stupid enough to waste my time trying to find an alternative. I said "I think" the issue may be the index conversion from Photoshop. As you said there is absolutely no difference between GIMP and Photoshop, then
It could just be the Openbor engine can not handle many high resolution sprites, I don't know. This is why I am trying to find out what is causing the problems.

Thank you
 
It could just be the Openbor engine can not handle many high resolution sprites, I don't know. This is why I am trying to find out what is causing the problems.

Yeah no, that's not the problem either. OpenBOR will run 5000 simultaneous sprites of any resolution and up to 2.4 billion loaded. You might slow it down, but you're not going to crash it.

Nobody said or implied anything personal about you - certainly not being an idiot as you put it. I won’t do that nor allow it.

However, your questions and problems are clearly indicative of fundamental production issue. I'd like to know exactly what you're doing and maybe we can locate the disconnect.

DC
 
Yeah no, that's not the problem either. OpenBOR will run 5000 simultaneous sprites of any resolution and up to 2.4 billion loaded. You might slow it down, but you're not going to crash it.

Nobody said or implied anything personal about you - certainly not being an idiot as you put it. I won’t do that nor allow it.

However, your questions and problems are clearly indicative of fundamental production issue. I'd like to know exactly what you're doing and maybe we can locate the disconnect.

DC
Well, I just did the test with GIMP and PalApply2, it also crashed with the out of memory issue.
I will post my new code and the video that I created and what I am trying to do shortly.

Code:
Video track: resolution=1920*1080, display resolution=1920*1080, 30.00 frames/second
Audio track: 44100.000000 Hz, 2 channels, 8 bits/sample
Video track: resolution=1920*1080, display resolution=1920*1080, 30.00 frames/second
Audio track: 44100.000000 Hz, 2 channels, 8 bits/sample
Loaded 'TitleScreenAnim' from data/scenes/TitleScreenAnim.txt
Loaded 'MenuScreenAnim' from data/scenes/MenuScreenAnim.txt
Loaded 'CharSelScreenAnim' from data/scenes/CharSelScreenAnim.txt


********** An Error Occurred **********
*            Shutting Down            *

Out of memory!
Allocation of size 2096330 failed in function 'loadsprite' at openbor.c:4305.

Thank you
 
Here is the new updated.c
This code can run 330+ times with only selection screen animation being used for the title, menu and selection screen before it freezes.
After I added 2 more screen animations, it freezes very quickly...

Code:
#include "data/scripts/common/constants.h"
#include "data/scripts/gettick.c"


void oncreate(){   // only triggers when the game starts for the 1st time
    setglobalvar("LevelFirstStart", 1);
    LOAD_Screen_Sprites_Animations();
}

void main()
{
    // CREDIT SCREEN =====================================
    if(openborvariant("current_scene")=="data/levels/scenes/credits/credits.txt")
    {
        setglobalvar("LevelFirstStart", 1);
    }
   
    mainLoop();
}

void mainLoop()
{
    // IN LEVEL SCREEN ===================================
    if(openborvariant("in_level")){
        inLevelLoop();
    }
    else
    {
        // INTRO SCREEN ==================================
        if(openborvariant("current_scene") == "data/scenes/intro.txt")
        {
            int LimiterCounter = getlocalvar("LimiterCounter");
            if(LimiterCounter == NULL() || LimiterCounter > 0){
                setlocalvar("LimiterCounter", 0);
            }
        }
        // TITLE SCREEN ====================================
        else if(openborvariant("in_titlescreen"))
        {
            drawstring(20,20,0, "TITLE");
            int LimiterCounter = getlocalvar("LimiterCounter");
            if(LimiterCounter != 1){
                setlocalvar("LimiterCounter", 1);
                // clearStory();
                playwebm("data/scenes/Press_Start_Screen.webm", 0);  // 0 = skippable
               
                UNLOAD_Screen_Sprites_Animations();
                LOAD_Screen_Sprites_Animations();
               
                playmusic("data/music/Title.ogg", 1);
                SpawnScreenAnim("TitleScreenAnim", 961, 541, -2); // LocalVar,  Entity, XYZ
            }            
            void BlackMask = getlocalvar("BG_BlackMask");
            if(BlackMask){
                changedrawmethod(NULL(), "alpha", 6);  // 50% transparency
                drawsprite(BlackMask, 0, 0, -1);
            }

        // MENU SCREEN =================================
        else if(openborvariant("in_menuscreen"))
        {
            drawstring(20,20,0, "MENU");
            int LimiterCounter = getlocalvar("LimiterCounter");
             if(LimiterCounter != 2)
            {
                setlocalvar("LimiterCounter", 2);
                playmusic("data/music/Menu.ogg", 1);

                UNLOAD_Screen_Sprites_Animations();
                LOAD_Screen_Sprites_Animations();
                SpawnScreenAnim("MenuScreenAnim", 961, 541, -2);  // LocalVar,  Entity, XYZ
            }    
            void BlackMask = getlocalvar("BG_BlackMask");
            if(BlackMask){
                changedrawmethod(NULL(), "alpha", 6);  // 50% transparency
                drawsprite(BlackMask, 0, 0, -1);
            }
        }
        // CHAR SELECTION SCREEN
        else if(openborvariant("in_selectscreen"))
        {
            int LimiterCounter = getlocalvar("LimiterCounter");
            if(LimiterCounter > 0){
                setlocalvar("LimiterCounter", 0);
                playmusic("data/music/CharacterSelect.ogg", 1);
               
                UNLOAD_Screen_Sprites_Animations();
                LOAD_Screen_Sprites_Animations();
                SpawnScreenAnim("CharSelScreenAnim", 961, 541, -2);  // LocalVar,  Entity, XYZ
            }
            void CharSelectionSprite = getlocalvar("BG_CharSelection");
            if(CharSelectionSprite){
                changedrawmethod(NULL(), "alpha", 0);
                drawsprite(CharSelectionSprite, 0, 0, 0);
            }
        }
    }
}

void inLevelLoop()
{
    turnWhite();
    storySystem();
    int LevelFirstStart = getglobalvar("LevelFirstStart");
    if(LevelFirstStart > 0)
    {
        setglobalvar("LevelFirstStart", 0);
        UNLOAD_Screen_Sprites_Animations();
        log("LOG: LevelFirstStart \n");
    }
}

void LOAD_Screen_Sprites_Animations()
{
    setlocalvar("BG_CharSelection",  loadsprite("data/bgs/select.png"));
    setlocalvar("BG_BlackMask",  loadsprite("data/scenes/black.gif"));
}  
   
void UNLOAD_Screen_Sprites_Animations()
{
    // Unload Sprites
    void CharacterSelection = getlocalvar("BG_CharSelection");
    if(CharacterSelection)
    {
        free(CharacterSelection);
        setlocalvar("BG_CharSelection", NULL());
    }
    void BlackMask = getlocalvar("BG_BlackMask");
    if(BlackMask)
    {
        free(BlackMask);
        setlocalvar("BG_BlackMask", NULL());
    }
}

void SpawnScreenAnim(void AnimatedEntity, int X, int Y, int Z)
{
    void subent;  
    int LimiterCounter = getlocalvar("LimiterCounter");
    if(LimiterCounter > 0)
    {
        void SpawnedEntity = getlocalvar("LocalvarScreenAnim");
        if(SpawnedEntity)
        {
            killentity(SpawnedEntity);
        }
    }
    loadmodel(AnimatedEntity); // name of the entity to be loaded
    clearspawnentry(); // clean the spawn entry
    setspawnentry("name", AnimatedEntity); // define the entity to be spawn
    setspawnentry("coords", X, Y, Z); // set the position of the entity
    subent=spawn();  //  spawn the entity
    setlocalvar("LocalvarScreenAnim", subent);
    changeentityproperty(subent, "position", X, Y, Z);//for safe, set again the position
}

Here is the list of what I am trying to do:

1. Play the Logo, then intro webm.

2. Play the Title intro webm before looping the title screen animation (press start button screen)
everytime the game starts or when they quit / complete the game, or pressing the back button from selection screen.

3. Loop the menu screen animation with the black color sprite (50% alpha).

4. Loop the selection screen animation with character selection sprite.

Here are the videos that I created in Filmora and split them into png files for screen animations:
Title Intro webm
Title Screen Animation
Menu Screen Animation


Thank you
 
I even followed the index conversion in Photoshop from DC here, which looks very promising and easy, but it is still not solving the memory overloading problem :-(
I've been trying to do tests, including disable some functions/script to see if it would help. Sadly nothing helps.
My updated.c looks very simply, and I do not see anything would cause the freezing problem.
I just can't understand what's going on as DC said the Openbor engine can handle a lot of high resolution sprites, so I believe my sprites should be fine.
How can it freeze with 1 animation looping at 1 time for the total of 3 animations for 3 different screens? This does not make sense at all.

Thank you
 
Further investigation:

I've found out that the sprites that I had for Dante's super1 and super 2 were one of the reasons that caused the memory overload.
I captured these sprites from the UVC3, and they already had the black background on them, and I can not remove this black background because the sprites won't look good.

I removed these sprites off Dante's supers and the memory overload seems to help alot.

Can someone please take a look at the attached sprite to see if there is a way to prepare the sprites properly?
I've already tried DC's index conversion method, but no difference.
The sprites are ~200kb+ each, so I don't understand how they would overload the memory. I do have 70+ sprites for each of these 2 supers though.Super2_37.png

Thank you very much
 
It's a terrible idea to use a sprite like that. Every effect on this image will cast shadow, which makes no sense.
Plus, you will have colorloss thanks to how much stuff you have on the same image.
 
Back
Top Bottom