Welcome to Keen Software House Forums! Log in or Sign up to interact with the KSH community.
  1. You are currently browsing our forum as a guest. Create your own forum account to access all forum functionality.

Total programming noob

Discussion in 'Programming Questions and Suggestions' started by Maintenanceman_98, Jul 8, 2015.

Thread Status:
This last post in this thread was made more than 31 days old.
  1. Maintenanceman_98 Trainee Engineer

    Messages:
    4
    Hi guys, I need to say I know very little about programming C# but I'm trying to learn in game as it seems like it would be cool to learn something to be able to do by myself. Having said that, I could use some help just getting started. Every time I try to reverse a piston, I get the Caught exception during execution error. Thought it would be easy after spending a few days looking at others code but can't seem to do something this simple. I've tried:

    var door=GridTerminalSystem.GetBlockWithname("Hanger Door") as IMyPistonBase;
    door.GetActionWithName("Reverse").ApplyAction(door);

    And also some different variations of that. Anyone could tell me what I'm doing wrong on something so simple, I would appeciate it.
     
  2. Sinbad Senior Engineer

    Messages:
    2,788
    try

    IMyPistonBase Door = GridTerminalSystem.GetBlockWithName("Hanger Door") as IMyPistonBase;
    float Direction = Door.Velocity;
    Direction = -1*Direction;
    Door.SetValueFloat("Velocity",Direction);

    that will return the currently set velocity, invert it (which changes its direction) then write it back to the piston.
    i assume this is a piston operated door and not an airtight hanger door block?
    the first line, you are not declaring a variable, you are creating an object. the object requires an interface for you to interact with (thats where all the functions and parameters come from, think of it like a driver) the interface is the IMyPistonBase part.
    or, you could look at it like this:
    float Number;
    Number = 1;

    returns an error, because 1 isnt a float vartype. to make it work, you need to cast it as a float:
    Number = 1f;

    then you can jam the two lines together:
    float Number = 1f;

    which is basically saying 'make a box in the shape of a float, label it "Number" now take the number one, add bits to it and cut bits off to make it float shaped, and put it in the box.
    making th object works the same way.
    IMyPistonBase Door = GridTerminalSystem.GetBlockWithName("Hanger Door") as IMyPistonBase;
    make a box shaped like an IMyPistonBase, label it "Door", then look in the GridTerminalSystem (which is all the blocks you would see if you pressed K on something on that grid) for a box labled "Hanger Door". take a picture of it, tie a string between "hanger door" and the picture, then put the picture in the box called door.
     
    • Like Like x 1
  3. plaYer2k Master Engineer

    Messages:
    3,160
    That kind of exception also often happens when a block you want to look up is not present (i.e. wrong name) and you want to call it.

    So always make sure to check if the block you just tried to search for is null.
    Code:
    var door=GridTerminalSystem.GetBlockWithname("Hanger Door") as IMyPistonBase;
    if(door == null)
    {
      Echo("Unable to find the hangar door");
      return;
    }
    door.GetActionWithName("Reverse").ApplyAction(door);
    This code will check if the door is null (not present) and then give you an echo (an output message on the programmable block within your terminal) that the block was not present.

    Another option is that the action you try to get with GetActionWithName is not present as that could return null aswell. But iirc Reverse is the correct name.

    @Sinbad you could also just do Door.SetValueFloat("Velocity", -Door.Velocity) as that is much smaller and elegant imo :)
    Of course that doesnt unravel it for explanatory purposes.
     
    Last edited: Jul 8, 2015
    • Like Like x 1
  4. Maintenanceman_98 Trainee Engineer

    Messages:
    4
    Yes it is, sorry I didn't say. Thank you both, I will try it. And thanks for the explanation, I understand that now too. Kinda wondered what I had might be to broad or simple.
     
    • Like Like x 1
  5. Sinbad Senior Engineer

    Messages:
    2,788
    @plaYer2k I figure step by step, one function at a time, each function explained is a good place to start. elegance comes later. besides, this way I also got to show a full get and full set function, which will hopefully help with learning syntax.

    I've found too many teachers of 'basics' seem more concerned with showing the student over optimised shortcut filled complex examples of how smart they are/how powerful the language is than with teaching a simple concept. the official MSDN C# tutorials especially bad for this. Just show me a simple algebreic example of how to create a new array! Instead the declaration is 10 lines from creation, and element population is is a for each loop with a single to string function and a string list thrown in as well. Then 9 lines later, they kinda show you how to acess an array element, but its buried inside a complicated console write command that does about six different casts, a switch and 5 different string formats. So very frustrating. I miss imperative C.
    It had a simple instruction set that was very well defined. One 6 point double sided A4 page (fair enough, six columns of tables each side, margin to margin goodness) and you knew everything available in the language, and exactly how to use it.
    Sorry, ranting at no-one again.
     
  6. Maintenanceman_98 Trainee Engineer

    Messages:
    4
    Sinbad, I agree. I'm trying to learn this but most start at somewhat complicated, then go back and show what things are and by then I'm already confused. Kinda why I wanted to start at this simple for moving a single piston and work my way up from there. Also couldn't get either code in this thread to work, still getting same error. All compiles good but won't run. Not sure if it's me(probably) or a setting or what it is. Found Textors guides that i will start going through too. I appreciate all the help though.
     
  7. Sinbad Senior Engineer

    Messages:
    2,788
    well, I can recomend The Yellow Book by Rob Miles. google it up. its a university text thats a free pdf. the first chapter is "this is a computer" he assumes zero former knowledge beyond reading english.
    try my example again, but put an f after the -1 to cast it as float.
    as far as controlling a piston,
    Code:
    void Main()
    {
    float SetPoint = 5f;
    float MinVelocity = 0.2f;
    float Error;
    float Velocity;
    float Position = 0;
    
    IMyPistonBase ServoPiston = GridTerminalSystem.GetBlockWithName("Piston") as IMyPistonBase;
    
    Position =ServoPiston.CurrentPosition; //or .Position I think, check the docs. I usualy do this with rotors.
    
    Error = SetPoint - Position;
    
    if (Error>=5){Error=5f;} //if (check if this is true){do this if it is} //if not, carry on
    if (Error<=-5){Error=-5f;} //5and-5 are the max and min speeds for pistons.
    
    Velocity = ServoPiston.Velocity; //gets the current speed
    
    if ((Velocity<=MinVelocity)&&(Velocity>=-1*MinVelocity)){Error=0f;} //checks for an acceptable accuracy.
    
    ServoPiston.SetValueFloat("Velocity",Error); //sets the error as velocity for the next tick
    }
    
    this is basically a servomechanism for a piston. you tell the piston what position you want it to drive to with SetPoint. (above, 5f. don't forget the f) then it loohs at the position the piston is currently at. it subtracts the set point from the position;
    setpoint =5 ,position= 0, sp-pos= 5
    Setpoint = 5, position = 10, sp-pos = -5
    To prove the math works as intended.
    Then it checks to make sure the error hasn't accidentally exceeded +/- 5f, if it has, it set it to that limit.
    Then it checks to see if the piston has dropped below the MinVelocity +/-. if it has, thats close enough, so it sets Error to zero.
    Then it applies the Error as piston velocity.
    To make this work, you need to run a tickwise timer. Thats a timer block set to 'trigger now' itself, and run the PB. Because the timer actions are actualy carried out the folowing physics tick (Update from UPS) it ends up triggering once each tick, and running the PB each tick (60hz clock). To stop the trigger cycle, you have to turn it off. Stopping it won't work.
    So, set up a piston called "Piston", a PB, and a timer, copy this in and you should be set to fiddle. Just trigger the timer. Once its in position, stop the timer, edit the PB, change the setpoint, remember and exit, trigger the timer again. To limit the speed, change the 5 to a different number. Don't go above 5 because pistons can't move faster and they will throw an error.
    I really hope this one works for you. May I suggest a new empty creative world for script tesing only? Only put what is required for the test on the grid. The best why I've found to check these is to do a pencil and paper run through of the program, just list the variables for each tigk, do the math by hand and see if they change as expected. Remember, one tick is 1/60th of a second, so devide your velocity by 60 and add it to your position for how far it moves between ticks.
    Good luck.
     
  8. Maintenanceman_98 Trainee Engineer

    Messages:
    4
    So I finally found the solution cause I was the problem. I told you I was driving a hanger door with a piston when actually I had two doors being driven by two pistons. I put that 1st code you gave in,

    IMyPistonBase Door = GridTerminalSystem.GetBlockWithName("Hanger Door") as IMyPistonBase;
    float Direction = Door.Velocity;
    Direction = -1*Direction;
    Door.SetValueFloat("Velocity",Direction);

    and replaced Hanger Door with Piston1 (also worked separately with Piston2). It works fine that way. *derp*
    Now I will try to get two pistons working together. I need to try and get this on my own so I can continue to learn and understand, but don't be surprosed if I yell for help again lol
    Thank you very much Sinbad for all of your help. I do understand it a little better, at least this simple step.

    *Update: Just copy and paste, extra brackets and it worked. Two hanger doors, each with thier own piston and they both open and close at the same time running the script.
     
  9. Sinbad Senior Engineer

    Messages:
    2,788
    ah, I see the missing brackets. sorry, I thought I had double checked every thing. but bright side: bug hunting practice ;)
    glad you got it working.
    as a 'next script' idea, try to get only one allowed open at a time.
    so if 1 is open, and you tell it to open 2, 1 will close first, then two will open. its a lead-in to an airlock script.
    good luck, happy scripting :D
     
Thread Status:
This last post in this thread was made more than 31 days old.