This site requires JavaScript, please enable it in your browser!
Greenfoot back
bilibull
bilibull wrote ...

2016/1/12

Need help with door and key(Lockpick) system.

1
2
bilibull bilibull

2016/1/12

#
So as the title implies I want to create a system in which I have a score that also happens to be my lock pick count. The keys are used to open random doors in the level which can either lead you to a room (small box on the level) with more of those lockpicks that my character can pick them up or just use them to open the other doors in the level in order to move on to the next one. So here are basically that I want to do in a list: 1. Have a score system that is linked to my lockpick count. 2. The score/lockpick count to get reduced every time I open a door. 3. To have doors that are opened by those lockpicks when ever the a binding key is used (so press 'e' to open the door, else the door wont open) I know I am asking a lot, but I really have no idea how to make such a system successful due to my lack of experience with programming. I understand how most code works but I would massively appreciate if I get a good explanation on how and why does the code works. Thank you for your time, and thank you if you even bother helping me.
Super_Hippo Super_Hippo

2016/1/12

#
If I understand this correctly, the character can pick up lock picks (and gets points for this) and open one (any) door for each lock pick. So you do not have key A which only opens door A, right? As an idea:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
private int lockpick = 0;
private int lockpick_total = 0;
 
//in act method
if (isTouching(Lockpick.class))
{
    removeTouching(Lockpick.class);
    lockpick++;
    lockpick_total++;
}
 
if (Greenfoot.isKeyDown("e") && lockpick > 0)
{
    Door d = (Door) getOneIntersectingObject(Door.class);
    if (d != null && !d.getState()) //if there is a closed door
    {
        d.open(); //open the door
        lockpick--;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
//in Door class
private boolean open = false;
 
public void open()
{
    setImage("openDoor.png");
    open = true;
}
 
public boolean getState()
{
    return open;
}
bilibull bilibull

2016/1/14

#
"So you do not have key A which only opens door A, right?" That is very correct Sir! So this code will avoid opening doors as long as the user doesn't press the e key? If i so i guess the !d.getState is the code part that makes that door un-openable. So here is a quick question. Will this code block my actor from passing through a door? since there is going to be multiple doors in one level.
danpost danpost

2016/1/15

#
I believe the 'open' field and the 'getState' method are there to prevent you from opening the same door more than once. So, it prevents you from using the door if it has already been used. The name of the method (to make it more readable when called) should be something like 'wasOpened'. If this is not possible or you do not mind the same door being used more than once, then you can remove the field and the method from the Door class and change line 15 above to just:
1
if (d != null)
Super_Hippo Super_Hippo

2016/1/15

#
Yes, what I was thinking is that if the actor touches the door and the user presses 'e', all lockpicks would be gone because usually a click on a key lasts longer than one act cycle. It is possible to solve this with using 'getKey', but it will not prevent the actor to open an already opened door which wouldn't make any sense to me.
danpost danpost

2016/1/15

#
Instead of using the current state of the 'e' key, use one of the changes in state of the key (the pressing or the releasing of the key. This will only require you to add an instance boolean field to track the state so one act can compare the current state with the last state. You will actually still use the current state to determine which state it has changed to; but it is restricted to acts where its state has changed.
bilibull bilibull

2016/1/17

#
So here is the thing; After I spend a good 2 days trying to implement the code on my game I have encountered 2 problems so far. 1. The door is not stopping the actor from passing through it which I think I may have an idea on how to fix it. 2. The score/Lockpick_total count does not fully work. The game keeps internally the score and it does open doors when pressing E but for the score counter that I made (using a code borrowed and changed for my game from another post of danpost). Here is my code for the score counter:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import greenfoot.*;
import java.awt.Color;
public class Lockpick_total extends Actor
{
    int Lockpick_total = 0;
 
    public Lockpick_total()
    {
        updateBoard();
    }
 
    private void updateBoard()
    {
        setImage(new GreenfootImage("Lockpick Total: " + Lockpick_total, 16, Color.black, new Color(0, 0, 0, 0)));
    }
 
    public void add(int addVal)
    {
        Lockpick_total +=addVal; updateBoard();
    }
 
    public int getLockpick_total()
    {
        return Lockpick_total;
    }
}
This is the code used for the pickup of the lockpicks:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)
 
public class Player extends Actor
 
{
 
    private int Lockpick = 0;
    private int Lockpick_total = 0;
    public void act()
    {
        {
            if (isTouching(Lockpick.class))
            {
                removeTouching(Lockpick.class);
                Lockpick++;
                Lockpick_total++;
            }
 
            if (Greenfoot.isKeyDown("e") && Lockpick > 0)
            {
                Door d = (Door) getOneIntersectingObject(Door.class);
                if (d != null && !d.getState())
                {
                    d.open();
                    Lockpick--;
                }
            }
        }
  {
            MyWorld dungeon = (MyWorld) getWorld();
            Lockpick_total lBoard = dungeon.scoreboard;
            lBoard.add(1);
        }
        move(3);
    }
//ignore the move(3); code, that was for my movement
And this is the statement for the scoreboard into my world subclass:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)
 
public class MyWorld extends World
{
    //GreenfootSound Melody = new GreenfootSound("Lalalala.wav");
    public Lockpick_total scoreboard = new Lockpick_total();
    public MyWorld()
    {   
        super(600, 400, 1);
        //Melody.playLoop();
    }
 
    public void stopped()
    {
        //Melody.pause();
    }
 
    public void started()
    {
        //Melody.playLoop();
    }
 
}
bilibull bilibull

2016/1/17

#
Update: After 2 bottles of Pepsi and some kicks ass music plus a LOT of trial and error plus searching I have finally fixed some of my problems. The main one that I have fixed was the counter not working. So what I did to fix it (this response is for the future programmers that would like to fix this problem) is the following. 1) Use your counter code from here (thanks a lot Danpost for your wonderful compressed work!) and did the following on my code. For the Lockpick_total subclass I made (my score counter).
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import greenfoot.*; 
import java.awt.Color;
public class Lockpick_total extends Actor
{
    int Lockpick_total = 0; //named my variable Lockpick_total because... well I like it! 
 
    public Lockpick_total() // Created the update function that will update my scoreboard after a pickup or unlock for a door
    {
        updateBoard();
    }
 
    public void updateBoard() // Added my score counter image courtesy of DanAwesomePost 
    {
        setImage(new GreenfootImage("Lockpick left: " + Lockpick_total, 16, Color.black, new Color(0, 0, 0, 0)));
    }
 
    public void add(int addVal) //Made an add function for every pickup; Note you can name this anything you like such as: Plus_one,extra etc just don't forget to add (int addVal) its quite important for the next line.
    {
        Lockpick_total += addVal; updateBoard(); //Put your score counters name then += and the name in your int from on top. then add your update function command
    }
 
    public void sub(int subVal) // Same thing as on top but for a subtraction.
    {
        Lockpick_total -= subVal; updateBoard();
    }
 
    public int getLockpick_total() // Make sure you add this last public value code.
    {
        return Lockpick_total;
    }
 
     
    public void act() // you can ignore your act method.
    {
    }
}
2) Time to add this your world subclass code. In my case:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)
 
public class Dungeon extends World
{
    Lockpick_total counter = new Lockpick_total();
    public Dungeon() //Create your counter info here. For more info about this just check danpost's counter explanation from that link above.
    {   
        super(300, 200, 1);  // This is a temporary setting I have for my world.
        prepare(); // If you haven't created a place were you place your objects on the screen go make one! To make one just add prepare(); then make a private prepare.
    }
     
    public Lockpick_total getLockpick_total() //Make sure
    {
      return counter; 
    }
     
    private void prepare() // this is the area in which I will be adding stuff onto my world AKA coordinates of the placement of the objects. For more info just check Jim Stewart from youtube. (he makes great tutorials!)
    {
        addObject(counter, 100, 20); //Make absolutely to add your object into the world from here or else the code wont work at all!
    }
}
Here is a link to Jim Stewart youtube. 3) Now I went to my actor class (named player) and added the code given from Super_Hippo (Massive thanks btw) while also modifying it with some parts of danpost's scorecounters code.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import greenfoot.*; 
 
public class Player extends Actor
 
{
    private int Lockpick = 0; //make your int values for your keys/objects that you want to pick up
    private int Lockpick_total = 0; //this is the int for from my scoreboard, so add the private int of your scoreboard.
    public void act() // in the act method I put super's code
    {
        if (isTouching(Lockpick.class)) //this means that if my character is on top or near the key/object.
        {
            Dungeon dungeon = (Dungeon) getWorld(); // This code just says that the sub class Dungeon (my world) is transformed into another variable which you can name whatever you want.
            Lockpick_total lTotal = dungeon.counter; // This is the same as above. I just made my counter class name into a smaller variable that is combined by the scoreboard(counter) and the world coordinates (dungeon)
            lTotal.add(1);// now I used my new counter with the add class/command I made before (which said that it will add any values inserted in the statement to my total score) then added the amount I want to add each time I pick up a key/object. NOTE: Make sure this to code is imputed BEFORE the removal code.
            removeTouching(Lockpick.class);
            Lockpick++;
            Lockpick_total++; // self explanatory.
        }
 
        if (Greenfoot.isKeyDown("e") && Lockpick > 0)
        {
            Door d = (Door) getOneIntersectingObject(Door.class);
            if (d != null && !d.getState()) //if there is a closed door //this is the part I have to change somehow in order to make my door solid which I will try to do next.
            {
                d.open(); //opens the door
                Dungeon dungeon = (Dungeon) getWorld(); //this is the same code I did for the addition code on top only for subtraction.
                Lockpick_total lTotal = dungeon.counter;
                lTotal.sub(1); //used the sub command made in Lockpick_total class
                Lockpick--;
            }
        }
And bang! it now works! So all thats left now is to fix the door not being solid before opening it and making it a non-solid after its unlocked. Back to Pepsi and failures.
Super_Hippo Super_Hippo

2016/1/18

#
bilibull wrote...
//this is the part I have to change somehow in order to make my door solid which I will try to do next.
Actually no. In the act method, there should also be some code to move the actor. That's what you have to modify in order to make your doors impenetrable. Btw, in your comments, you state that the getter-methods are important. But you don't use them at all. If you want to use them, change the variable from 'public' to 'private' and change every call to it from outside (simply compile, it will show the errors) to the getter method. If not, you can remove the getter methods.
bilibull bilibull

2016/1/19

#
Oh ... well Am still trying to fully understand how the code works myself. The comments are developed from my own experience from trying to fix its problems. Which so far I am still having a problem when it comes to making the door solid when its closed. I will keep on trying to get it solid... till then you are welcome to try and help me with my struggles.
Super_Hippo Super_Hippo

2016/1/19

#
It will be something like: - save position - move - move back to saved position if it is touching a wall, a closed door or whatever else
bilibull bilibull

2016/1/22

#
Am not really that good with code in order to figure out on how to do that. I have been trying to do it with other methods like attempting to use my wall code to block my way when ever i touch the door. Then try to make an if statement that when the door is unlocked that code is voided. BUT! I am having quite the trouble putting it together. To give you an idea on what my code for movement and wall blocking is here:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public void move(int moveAmt)   
  {
      int dx = 0, dy = 0;
      if (Greenfoot.isKeyDown("d")) dx++;
      if (Greenfoot.isKeyDown("a")) dx--;
      if (Greenfoot.isKeyDown("w")) dy--;
      if (Greenfoot.isKeyDown("s")) dy++;
      if (dx != 0 || dy != 0) setLocation(getX()-dx, getY()-dy);
      for (int i = 0; i < moveAmt; i++)
 
      /* this is my wall blocking code, it was taken from one of danpost replies
          and then modified to work with my code*/
          setLocation(getX() + dx, getY());
          if (getOneIntersectingObject(WallPiece.class) != null) setLocation(getX()  - dx, getY());
          setLocation(getX(), getY() + dy);
          if (getOneIntersectingObject(WallPiece.class) != null) setLocation(getX(), getY() - dy);
      }
 
  }
danpost danpost

2016/1/22

#
I am not sure why you have your actor moving slightly backwards at line 8. I can understand the condition of something not being zero (meaning that some movement key was detected); however, I believe you should ask the opposite and just return out of the method if both are zero:
1
if (dx == 0 && dy == 0) return;
Other than that, it looks like it should work.
bilibull bilibull

2016/1/22

#
danpost wrote...
I am not sure why you have your actor moving slightly backwards at line 8.
To be honest I have no idea why I had to chance the values like that BUT! If it didn't have my values like that then the actor would not move correctly. I can post my game so you can see for your self if you want. On the side note, I fixed the problem about the door not stopping me, however now I have a problem of the door doing its job a bit too damn well. What I mean by that is that I cannot longer open the door if I am touching it. In order for the door to open I laterally have to glitch my actor on the set up and then press my key to unlock the door. So this is what I did in order to make the door solid.
1
2
3
4
5
6
setLocation(getX() + dx, getY());
           if (getOneIntersectingObject(WallPiece.class) != null) setLocation(getX()  - dx, getY());
           if (getOneIntersectingObject(Door.class) != null) setLocation(getX()  - dx, getY());
           setLocation(getX(), getY() + dy);
           if (getOneIntersectingObject(WallPiece.class) != null) setLocation(getX(), getY() - dy);
           if (getOneIntersectingObject(Door.class) != null) setLocation(getX(), getY() - dy);
I just added it inside the wall code. As for my game scenario here it is: My game (Work on progress) For now i guess i will just work on trying to have my mouse unlock the door, rather than my actor.
Super_Hippo Super_Hippo

2016/1/22

#
If you walk back because of touching a WallPiece, you should use 'else if' to prevent the actor from moving back twice if touching Wall and Door. To only be blocked by closed doors, you can use something like this then:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
setLocation(getX() + dx, getY());
if (getOneIntersectingObject(WallPiece.class) != null) setLocation(getX()  - dx, getY());
else
{
    Door d = (Door) getOneIntersectingObject(Door.class);
    if (d != null && !d.getState()) //maybe you changed the name of the method
    {
        setLocation(getX()  - dx, getY());
    }
}
setLocation(getX(), getY() + dy);
if (getOneIntersectingObject(WallPiece.class) != null) setLocation(getX(), getY() - dy);
else
{
    Door d = (Door) getOneIntersectingObject(Door.class);
    if (d != null && !d.getState()) //maybe you changed the name of the method
    {
        setLocation(getX(), getY() - dy);
    }
}
There are more replies on the next page.
1
2