game_start not working in room 52

Started by bx83, Sat 17/07/2021 04:57:06

Previous topic - Next topic

bx83

I have a script (header/code) for my little Tankman module. In room52, where I have the graphics for the game, I have a game_start() function.
In game_start(), I've put all the initialisation code, and the code for 'theGrid', an array which represents my game-map:

Tankman.ash
Code: ags
Tile *theGrid[];    //dynamic array of pointers


Room52.asc
Code: ags
function game_start()
{
...
theGrid=new Tile[numRows*numCols];  //define it as a new Tile array of size rows*colums
Display("rgarghath");
SetupGridValues();    <------Display output for testing, sets up grid values now it's been properly instantiated
GetTargetRed();   <----- function than generates Display output
}


Nothing displays output, nothing runs.
If I put SetupGridValues() in room_Load(), it runs it, and then says theGrid is a null pointer (obviously never instantiated).

I would've thought that game_start() would be the first and foremost thing to run?

How and where do I run 'theGrid=new Tile[numRows*numCols];' to set it as a global variable (within game/room52), then run all 'setup' code, and then just get to the actual game-loop in room_RepExec()?

Crimson Wizard

#1
game_start is not run in the room scripts, because no room is loaded at the game start yet.

You may only have these in script modules, but not in room scripts.

Quote from: bx83 on Sat 17/07/2021 04:57:06
How and where do I run 'theGrid=new Tile[numRows*numCols];' to set it as a global variable (within game/room52), then run all 'setup' code, and then just get to the actual game-loop in room_RepExec()?

room_Load ("room before fade-in") event is meant for setting a room up, have you tried putting everything there?

bx83

Okay, that explains that.
Now I've got:

Room52.asc:
Code: ags
function room_Load()
{
...

  theGrid=new Tile[numRows*numCols];  //define it as a new Tile array of size rows*colums
  Display("%d %d",numRows, numCols);
  theGrid[0].x=25;   theGrid[0].y=25;    theGrid[0].up=0;  theGrid[0].right=1;  theGrid[0].down=1;  theGrid[0].left=0;  theGrid[0].content=0;
  theGrid[1].x=75;   theGrid[1].y=25;    theGrid[1].up=0;  theGrid[1].right=1;  theGrid[1].down=0;  theGrid[1].left=1;  theGrid[1].content=0;
  theGrid[2].x=125;  theGrid[2].y=25;    theGrid[2].up=1;  theGrid[2].right=1;  theGrid[2].down=0;  theGrid[2].left=1;  theGrid[2].content=0;
  
  
  Display("rgarghath");
  SetupGridValues();
  GetTargetRed();


It displays:
8 10
'Runtime error: null pointer referenced'

The first line, theGrid[0].x=25, etc etc is the null pointer. So instantiation is right, but then 'theGrid' drops from memory. Or something. :/

Crimson Wizard

#3
Quote from: bx83 on Sat 17/07/2021 05:17:03
It displays:
8 10
'Runtime error: null pointer referenced'

Well, that's weird. May you try printing theGrid value as well?
Code: ags

Display("%p %d %d", theGrid, numRows, numCols);


How and where is theGrid declared?

EDIT: oh I see in your first post:
Quote
Tankman.ash

Code: ags
Tile *theGrid[];    //dynamic array of pointers


This is a wrong thing to put into a header. The variables should be put in the script body, and headers should have import declarations.
https://adventuregamestudio.github.io/ags-manual/TheScriptHeader.html
https://adventuregamestudio.github.io/ags-manual/ImportingFunctionsAndVariables.html

bx83

#4
Tankman.ash
Code: ags
// new module header
struct __Tankman
{
  import function Enable();
  import function Disable();
};
import __Tankman Tankman;


#define numRows     8
#define numCols     10
#define tankLoop  314

managed struct Tile {
  int x;  //x centre of tile
  int y;  //y centre of tile
  bool up;      //has up direction
  bool right;   //has right direction
  bool down;    //has down direction
  bool left;    //has left direction
  int content;  //is it a free tile or blocked space?
};

#define numCrowds   4


managed struct Crowd {
  int aX;     //actual x eg. 312
  int aY;     //actual y eg. 472
  int tX;     //target x - x centre of target tile
  int tY;     //target y - y centre of target tile
  
  int mode;   //mode, 0=chase, attack=1, scatter=2, scared=3, regen=4
  
  int timer1; //timer to stay in mode
  int timer2; //timer to stay aggressive
  int waittimer;  //timer for wait between attacks/cooldown time
  int timercontrol; //a timer is on=1/off=0
  
  int dir;    //0=up, 1=right, 2=down, 3=left  Never Eat Soggy Wheatbix
  int nogo;   //opposite direction to where your pointed; dir/nogo 0/2 1/3 2/0 3/1
  int moving; //1=moving to next coord, 0=not moving, decision/action time
  bool attack;  //are they programmed to be aggressive? 0-no 1-yes
  int id;     //object ID, leads to control of object loop/position
  bool dead;  //0=alive, 1=dead
  
  import void ResetTimers(Crowd *crowd);
  import void FindTargetBasedOnMode(Crowd *crowd, int mode);
  import void MoveCrowdToTarget(Crowd *crowd);
  import int CleanUpDeadCrowd(Crowd *crowd);
};

managed struct TM {
  int tileX;  //tm's current tile
  int tileY;
  int dir;  //tm's current dir
  int nogo; //diametric opposite to dir
  int mode; 
  int id;   //object id
};

import int SetNogo(int dir);
import int DirToLoop(int dir);
import int LoopToDir(int loop);
import Tile* GetTile(int x=-1, int y=-1);


Tankman.asc
Code: ags
__Tankman Tankman;
export Tankman;

bool gEnabled = false;
export gEnabled;


function __Tankman::Enable()
{
  gEnabled = true;
}

function __Tankman::Disable()
{
  gEnabled = false;
}


Tile *theGrid[];    //dynamic array of pointers
Crowd* rabble[4];    //4 crowds: red, yellow, green, purple
TM* TMan;

...


Room52
Code: ags
...

function room_Load()
{
  Tankman.Enable();
  
  gIconbar.Visible=false;
	
  oTM.Baseline=768;
  
  
  cJulius.x=2000;   //the main character of the game; he's here, but off-screen
  cJulius.y=2000;
  
  AG_playing=true;
  AG_gameover=false;
  
  newdirection=eKeyboardMovement_Up;

  //set crowd views
  oC0.SetView(330); //red
  oC1.SetView(332); //yellow
  oC2.SetView(331); //green
  oC3.SetView(329); //purple
  oTM.SetView(314); //tankman
  
  
  
  theGrid=new Tile[numRows*numCols];  <------ Error: Undefined token 'theGrid'



EDIT: added these to the bottom of Tankman.ash:

Code: ags
import Tile *theGrid[];
import Crowd* rabble[4];    //4 crowds: red, yellow, green, purple
import TM* TMan;


Gets through compile, but then has a runtime error on startup in room52:

Error: unable to create local script: Runtime error: unresolved import 'theGrid'

Crimson Wizard

Quote from: bx83 on Sat 17/07/2021 05:54:00
Code: ags

  theGrid=new Tile[numRows*numCols];  <------ Error: Undefined token 'theGrid'

[/code]

Well, you need to declare an import for this variable.

https://adventuregamestudio.github.io/ags-manual/ImportingFunctionsAndVariables.html

In the script body:
Code: ags

Tile *theGrid[];    //dynamic array of pointers
...
export theGrid;


In the script header:
Code: ags

import Tile *theGrid[];

bx83

Alrighty, that worked, exports were the missing piece (which I... should have remembered. I need lunch).

Now, it gets back in room 52 to:

Code: ags
function room_Load()
{
  Tankman.Enable();
  
	gIconbar.Visible=false;
	
  oTM.Baseline=768;
  
  
  cJulius.x=2000;   //the main character of the game; he's here, but off-screen
  cJulius.y=2000;
  
  AG_playing=true;
  AG_gameover=false;
  
  newdirection=eKeyboardMovement_Up;

  //set crowd views
  oC0.SetView(330); //red
  oC1.SetView(332); //yellow
  oC2.SetView(331); //green
  oC3.SetView(329); //purple
  oTM.SetView(314); //tankman
  
  
  
  theGrid=new Tile[numRows*numCols];  //define it as a new Tile array of size rows*colums
  
  Display("%p %d %d",theGrid, numRows, numCols);    <---------displays "<8 random hex characters> 8 10"
  theGrid[0].x=25;              <---------------------------------Error: null pointer referenced, PROGRAM STOPS HERE
  Display("%p %d %d",theGrid, numRows, numCols);
  
  Display("rgarghath");
  SetupGridValues();
  GetTargetRed();

Crimson Wizard

Ah, I got it.

"theGrid" is an array of Tiles, but Tile is a managed struct, so each tile should also be created.

It's not theGrid which is the null pointer, it's theGrid[0] which is a null pointer.

So you have to do this:

Code: ags

int size = numRows*numCols;
theGrid=new Tile[size ];
for (int i = 0; i < size; i++)
    theGrid[i] = new Tile;

bx83

It all works now, thank you :)

....except TMan. As usual I will try all combinations of definition before complaining.

*does this over 20 minutes*

Okay, I'm out of ideas.

Tankman.ash
Code: ags
...
import Tile *theGrid[];
import Crowd* rabble[numCrowds];    //4 crowds: red, yellow, green, purple
import TM* TMan;


Tankman.asc
Code: ags
__Tankman Tankman;
export Tankman;

bool gEnabled = false;
export gEnabled;


function __Tankman::Enable()
{
  gEnabled = true;
}

function __Tankman::Disable()
{
  gEnabled = false;
}


Tile *theGrid[];    //dynamic array of pointers
Crowd* rabble[4];    //4 crowds: red, yellow, green, purple
TM* TMan;
export theGrid; 
export rabble;
export TMan;
...


Room52.asc
Code: ags
function room_Load()
{
  Tankman.Enable();
  
  gIconbar.Visible=false;
	
  oTM.Baseline=768;
  
  
  cJulius.x=2000;   //the main character of the game; he's here, but off-screen
  cJulius.y=2000;
  
  AG_playing=true;
  AG_gameover=false;
  
  newdirection=eKeyboardMovement_Up;

  //set crowd views
  oC0.SetView(330); //red
  oC1.SetView(332); //yellow
  oC2.SetView(331); //green
  oC3.SetView(329); //purple
  oTM.SetView(314); //tankman
  
  
  //fill out theGrid with Tile objects
  int size = numRows*numCols;
  
  theGrid=new Tile[size]; //instantiate theGrid
  for (int i = 0; i < size; i++) {
    theGrid[i] = new Tile;
  }
  SetupGridValues();
  
  for (int j=0; j<numCrowds;j++) {
    rabble[j]=new Crowd;
  }
  
  //now, setup crowds:
  
  ///////////
  // 0 RED //
  ///////////
  rabble[0].mode=Random(1);       //chase or scatter
  
  //get random start tile
  Tile *rt0 = GetTile();
  rabble[0].aX=rt0.x;

....

 else if (rt3.left==1)  rabble[3].dir=3;
  
  //set nogo based on dir
  rabble[3].nogo=SetNogo(rabble[3].dir);
  

  //setup tankman:
  
  /////////////
  // Tankman //
  /////////////
  
  
  TMan.tileX=6;  <----NULL POINTER REFERENCED


so you know :(
TMan is still not acting as a nice global.

Crimson Wizard

Well, it's the exactly same reason, you have a "TM* TMan;" which is a pointer, but do you create the actual object anywhere with "new"?

bx83

Code: ags
...

//fill out theGrid with Tile objects
  int size = numRows*numCols;
  
  theGrid=new Tile[size]; //instantiate theGrid
  for (int i = 0; i < size; i++) {
    theGrid[i] = new Tile;
  }
  SetupGridValues();
  
  for (int j=0; j<numCrowds;j++) {
    rabble[j]=new Crowd;
  }

  TMan=new TM;



...and it works :P

Cassiebsg

OT: You can make your code look like AGS code in your posts, instead of [ code ] use [ code=ags ] (without the spaces).  ;)
There are those who believe that life here began out there...

SMF spam blocked by CleanTalk