Pass List index through class

Hello,

I try to get the IndexSprite of the 2d list in my Level class to check if the player will be able to walk or not.

My problem is that i need to get the list with the index from my Level class, and i need to create a new object
ancienneListe but if i have a new one the index will all be set to 1 (i decied to have it to 1 by default if not set in my Leve class)

public MapRowColumn ancienneListe = new MapRowColumn; // new = index set to 1 and my player cant move

This is from my class Player:

public MapRowColumn ancienneListe;   
public List<MapRowColumn.IndexLigne> nouvelleListe = new List<MapRowColumn.IndexLigne>();

if (Keyboard.GetState().IsKeyDown(Keys.Right) && old_right == false)
{
     if (ancienneListe.Rows[joueur_position.X].Columns[joueur_position.Y].IndexSprite == 0)
 { 
      direction = "droite";
      joueur_position.X++;
      old_right = true;
 }
 else if (ancienneListe.Rows[joueur_position.X].Columns[joueur_position.Y].IndexSprite == 1)
 {
      joueur_position.X = joueur_position.X + 0;                 
 }
}
if (Keyboard.GetState().IsKeyUp(Keys.Right) && old_right == true)
    old_right = false;

This is from my class Level:

  public MapRowColumn map_row_column;
  public Point joueur_pos = new Point(1, 2); // position du joueur

  public Niveau1()
  {
      map_row_column = new MapRowColumn(); 
        
      map_row_column.Rows[1].Columns[1].IndexSprite = 0;
      map_row_column.Rows[1].Columns[2].IndexSprite = 0;
      map_row_column.Rows[1].Columns[3].IndexSprite = 0;
      map_row_column.Rows[1].Columns[4].IndexSprite = 0;
  }

I hope this make sense and that you can help me, thank you :slight_smile:

What I would do is pass the desired direction (ie: where we wanna move) and test accordingly with the key:
(If no need to move in diagonal)
for x: Hdir: 1 is to the right, -1 to the left, 0: no move
for y: Vdir: 1 to the bottom, -1 to the top, 0: no move
without the need of creation of an ancienneliste.

Something like:

if (Keyboard.GetState().IsKeyDown(Keys.Right))
{
	Hdir = 1;
    bool result = CanMove(joueur_position.X + Hdir, joueur_position.Y);
	if(!result)
	{ 
		Hdir = 0;
	}
	UpdatePlayerPosition(Hdir, 0);
}

if (Keyboard.GetState().IsKeyDown(Keys.Up)) // for ex
{
	Vdir = -1;
    bool result = CanMove(joueur_position.X, joueur_position.Y + Vdir );
	if(!result)
	{ 
		Vdir = 0;
	}
	UpdatePlayerPosition(0, Vdir);
}

...

bool CanMove(int x, int y)
{
	//need to clamp values within the array !
	if(x < 0)
		return false;
	if(y < 0)
		return false;
	if(x >= theworld.length)
		return false;
	if(x >= theworld.height)
		return false;

	bool value =theworld.Rows[x].Columns[y].IndexSprite == 0;
	return value;
}

void UpdatePlayerPosition(int Hdir, int Vdir)
{
	joueur_position.X += Hdir;
	joueur_position.Y += Vdir;
}

More or less. This way you would only need to read directly the level, avoiding the use of 2 arrays.

The thing is that i have multiple class of Level (Niveau1 , Niveau2, etc…) all have different IndexSprite that i use to draw different texture in function of the index.

On my map i have my player and box that i can push around so i need those 2d arrays, the walls are not only in the border, there is some in the middle of my map.

By the way my project is to create a Sokoban, i have everything but the collision, my player and the boxes can go through the walls.

EDIT: i figure out how to get my IndexSprite but for some reason my player doesnt walk on all walkable texture (0 as IndexSprite) :thinking:

How is your level class made ?

class Level
{
 int witdh;
 int height;
 int[][] arrayofspriteindex;

...
}

?

Shouldn’t the class be common to a level, and load its data into a Level object instead of a class per level ?

I have a class like this for the 4 level i actually have

class Niveau2
{
    public MapRowColumn map_row_column;
    public List<Caisse> caisses;
    public Point joueur_pos = new Point(5, 5); // position du joueur

    public Niveau2()
    {
        map_row_column = new MapRowColumn(); // initialistion de la classe permettant de créer l'objet Rows (carte)

        // Changer l'IndexSprite pour afficher une autre texture (0 = texture du vide, de base IndexSprite = 1 pour la texture du mur) 
        map_row_column.Rows[1].Columns[1].IndexSprite = 0;
        map_row_column.Rows[1].Columns[2].IndexSprite = 0;
        map_row_column.Rows[1].Columns[3].IndexSprite = 0;
        map_row_column.Rows[1].Columns[4].IndexSprite = 0;
        map_row_column.Rows[1].Columns[5].IndexSprite = 0;
        map_row_column.Rows[1].Columns[6].IndexSprite = 2;
        map_row_column.Rows[1].Columns[7].IndexSprite = 0;

        map_row_column.Rows[2].Columns[1].IndexSprite = 0;
        map_row_column.Rows[2].Columns[2].IndexSprite = 0;
        map_row_column.Rows[2].Columns[3].IndexSprite = 0;
        map_row_column.Rows[2].Columns[4].IndexSprite = 0;
        map_row_column.Rows[2].Columns[5].IndexSprite = 0;            
        map_row_column.Rows[2].Columns[7].IndexSprite = 0;

        caisses = new List<Caisse>(); // ajouter les caisses du niveau
        caisses.Add(new Caisse(2, 2));
        caisses.Add(new Caisse(3, 3));
        caisses.Add(new Caisse(4, 4));
    }
}

And i have a switch that create an object depending on the level i chose

 public class Map  
 {
    public Map(int _niveau) // permet faire les actions nécessaires en fonction du niveau choisi 
    {
        switch(_niveau) 
        {
            case 1:
                Niveaux.Niveau1 niveau1 = new Niveaux.Niveau1();
                map_row_column.Rows = niveau1.map_row_column.Rows; 
                map_caisses = niveau1.caisses;                      
                map_joueur_pos = niveau1.joueur_pos;                
                break;
            case 2:
                Niveaux.Niveau2 niveau2 = new Niveaux.Niveau2();
                map_row_column.Rows = niveau2.map_row_column.Rows;
                map_caisses = niveau2.caisses;
                map_joueur_pos = niveau2.joueur_pos;
                break;
            case 3:
                Niveaux.Niveau3 niveau3 = new Niveaux.Niveau3();
                map_row_column.Rows = niveau3.map_row_column.Rows;
                map_caisses = niveau3.caisses;
                map_joueur_pos = niveau3.joueur_pos;
                break;
            case 4:
                Niveaux.Niveau4 niveau4 = new Niveaux.Niveau4();
                map_row_column.Rows = niveau4.map_row_column.Rows;
                map_caisses = niveau4.caisses;
                map_joueur_pos = niveau4.joueur_pos;
                break;
        }
    }
 }

i know i can have an object Niveau1 , NiveauX … in one class but i’ll still need the switch to load one of these object once chosen in the menu or i’m completly wrong ?

PS: it’s the first game i ever make, i still have a lot to learn :pensive:

No problem, we are here to help each other

A class is like ‘engine’ in a car. It is the thing that gives power to the car. But by instanciating it. It becomes an essence, diesel, gpl, electric engine.
You can have a class for the seats (that become an object covered of leather, velvet…)
So does the level class. :wink:
A class becomes an object when instanciated.
This was just to make things clear (i hope)

The level class should be generic to all levels to be loaded
Then in a global file, or one file per level, of type txt or xml or json etc, you store the levels definition:
Levelname:niveauX
Width:96
Height:64
Startposition:2,4
Caisses:5
Caisse1pos:3,5
Caisse1Tex:chemin/de/la/texture
Caisse2pos:3,6
Caisse2Tex:chemin…
Trigger1StarScore:100
Trigger2StarScore:200
Trigger3StarScore:500
PossibleNumberOfMoves (if needed etc) .

In an xml format, this would give:

<?xml version="1.0" encoding="utf-8" ?>
<leveldefinition>
  <width>96</width>
  <height>64</height>
  <name></name>
  <Startposition>
    <X>2</X>
    <Y>4</Y>
  </Startposition>
  <Caisses>
    <number>5</number>
    <Positions>
      <Caisse1>
        <pos>
          <X>3</X>
          <Y>8</Y>
        </pos>
        <AssetTex>chemin/de/la/texture</AssetTex>
      </Caisse1>
      <Caisse2>
        <pos>
          <X>3</X>
          <Y>8</Y>
        </pos>
        <AssetTex>chemin/de/la/texture</AssetTex>
      </Caisse2>
    </Positions>
  </Caisses>
  <Trigger1StarScore>100</Trigger1StarScore>
  <Trigger2StarScore>
    200
  </Trigger2StarScore>
  <Trigger3StarScore>
    500
  </Trigger3StarScore>
</leveldefinition>

Then the switch would only be needed to inform the app of the level to load

So if i make xml file for each of my levels, it’s in the xml that i “draw” my level by giving my indexes like i did in my NiveauX class ?

Should i have an xml file only for levels or my player and the boxes too ?

The xml is only there to feed the level object.
Then it is the level that draws, for ex in the level class:

void Draw()
{
   DrawMe(); //draws the level
   DrawBoxes();
   DrawPlayer();
}