0

I started to write a game, but I am still learning object oriented programming.
I am using VS 2015 (Win7).

I created a class called Ship, a method which let me create a ship with only two parameters so far: position X and Y on map.

Ship[] submarine = new Ship[100]; 
// create first ship with only two
submarine[0].create_ship(140, 200);
parameters: position X and Y on future map

I want to make Ship move each second using a method move() and a Timer.

My code:
(Also on PasteBin)

public partial class Form1 : Form
{
    class Ship
    {
        private double ship_posX; // position X on map
        private double ship_posY; // position Y on map
        private int ship_heading; // current heading
        private int ship_speed_max; // max speed of a ship
        private int ship_current_speed; // current speed of a ship
        private string ship_class; // surface or submarine
        private string ship_foe; // friend or enemy?
        private string is_controllable; // is controllable by player?
        private int depth; // current depth of a submarine (if a submarine)

        public void move(int heading, int speed)
        {
            if (heading == 0)  ship_posY -= speed; // ship is heading NORTH
            if (heading == 45) // ship is heading NORTH-EAST
            {
                ship_posX += speed;
                ship_posY -= speed;
            }
            if (heading == 90) ship_posX += speed; // ship is heading EAST
            if (heading == 135) // ship is heading SOUTH-EAST
            {
                ship_posX += speed;
                ship_posY += speed;
            }
            if (heading == 180) ship_posY += speed; // ship is heading SOUTH
            if (heading == 225) // ship is heading SOUTH-WEST
            {
                ship_posX -= speed;
                ship_posY += speed;
            }
            if (heading == 270) ship_posX -= speed; // ship is heading WEST
            if (heading == 315) // ship is heading NORTH-WEST
            {
                ship_posX -= speed;
                ship_posY -= speed;
            }
        }

        public void create_ship(double posx, double posy)
        {
            ship_posX = posx;
            ship_posY = posy;
            // only a few parameters for now. Later will be name, speed_max, class, friend or foe and more
        }
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        // forms load == game starts
        Ship[] submarine = new Ship[100]; 
        submarine[0].create_ship(140, 200); // create first ship with only two parameters: position X and Y on future map
    }

    private void timer1_Tick(object sender, EventArgs e)
    {
        submarine[0].move(90, 15); 
        // ERROR: compiler shows "The name 'submarine' does not exist in the current context
    }
}

What is causing an error is this code?:

private void timer1_Tick(object sender, EventArgs e)
{
    submarine[0].move(90, 15); 
    //ERROR: compiler shows "The name 'submarine' does not exist in the current context
}

The Timer is Enabled by default, its Interval is set to 1000 and modifiers are Private.

What am I doing wrong?

It does not work inside the Timer event but if I use it inside Form.Load:

private void Form1_Load(object sender, EventArgs e)
{
     // forms load == game starts
     Ship[] submarine = new Ship[100]; 
      // create first ship with only two parameters: position X and Y on future map
     submarine[0].create_ship(140, 200);
     submarine[0].move(90, 15);
}

It works fine (but only once - so I want to use a Timer).

I hope the subject of post is understandable and my problem I described well enough.

I tried to modify public/private in some places but it did not help.

Jimi
  • 29,621
  • 8
  • 43
  • 61
Mariusz
  • 45
  • 1
  • 10

1 Answers1

0

The scope of a variable determines its visibility to the rest of a program. In the examples throughout the C# Fundamentals tutorial, variables have been defined within methods. When created in this way, the scope of the variable is the entire method after the declaration

in your case, you define and declare submarine in Form1_Load method, according to above definition, submarine is only available in Scope of Form1_Load method.

if you want use submarine in different method of Form1 class, you can introduce it as a Class Field.

It's means to:

public partial class Form1 : Form
{
    private static Ship[] submarine;

    .
    .
    .

    private void Form1_Load(object sender, EventArgs e)
    {
        // forms load == game starts

        submarine = new Ship[100]; 
        submarine[0].create_ship(140, 200); // create first ship with only two 
        parameters: position X and Y on future map
    }

    private void timer1_Tick(object sender, EventArgs e)
    {
        submarine[0].move(90, 15); // ERROR: compiler shows "The name 'submarine' 
        does not exist in the current context
    }

Now, you get error again

and it's because you didn't declare any instance of ship in you array: Create a static method in ship class with name of Initial"

public static void Initial()
{
    for(int i = 0; i < 100; i++)
    {
       submarine[i] = new ship();
    }
}

and use it in Form1_load():

private void Form1_Load(object sender, EventArgs e)
        {
            // forms load == game starts

            submarine = new Ship[100]; 
            ship.Initial();
            submarine[0].create_ship(140, 200); // create first ship with only two 
            parameters: position X and Y on future map
        }

After doing these change, I think it's work correctly.

Hamed Moghadasi
  • 1,523
  • 2
  • 16
  • 34
  • I tried to modify a code exactly like you wrote, but still get "Object reference not set to an instance of an object." inside timer1_Tick (but when program is running, not during compiling) – Mariusz Jan 30 '19 at 23:52
  • It's because you just define a array with type of `Ship`... and this array has not any member. then when you try to access to `submarine[0]`, you get this error – Hamed Moghadasi Jan 30 '19 at 23:55
  • Hamed Moghadasi - so how can i create multiple subs without array? I don't want to use: submarine1 = new Ship(); submarine2 = new Ship(); multiple times ? – Mariusz Jan 30 '19 at 23:57
  • @Mariusz you can find your answer in this [link](https://stackoverflow.com/questions/10210024/how-to-create-array-of-100-new-objects) – Hamed Moghadasi Jan 30 '19 at 23:57
  • @Mariusz I Update answer check it – Hamed Moghadasi Jan 31 '19 at 00:05
  • Hamed Moghadasi thank You for help. I modified a code and used PUBLIC double ship_posX; instead of PRIVATE so i can get access to it inside timer1_Tick (and will do it with the rest of variables) and also helped me this link you pasted. Skalli's loop on this page where your link redirects me works perfect. Problem is solved! – Mariusz Jan 31 '19 at 00:07
  • Hamed Moghadasi also had to modify your code: I had to use `private STATIC Ship[] submarine;` instead of just only private, otherwise had a error An object reference is required for the non-static field, method, or property. Now all is just fine – Mariusz Jan 31 '19 at 00:21