2
\$\begingroup\$

I don't mean to ask a broad question, so let me explain. I'm creating a 2D top-down design game and I'd like to implement "portals" to be able to switch between worlds. Each world is a level class, and at the moment portals are rendered as tiles, and changing world is handled in the player collision code. However, I have no way of determining which portal is dedicated to which level. I would perhaps also like to have the ability to lock portals until a player becomes a certain rank. I've tried to set up a portal class, and implemented it as entities that were spawned during level creation at the location of the portal tiles, and then all collision handling was passed to that class. It took in params of currLevel, targetLevel, x and y. When the player collided, it would change to the set targetLevel. However, when I ran the code and collided with the portal, the game just froze. There was no error output, ups was at 60 as standard and the fps was at about 3000 as standard. The terminal was also outputting as normal, but the game was doing nothing.

To conclude, I'd like to know if there is a better way to go about completing this? I may have just missed something.

Thanks

Here is the code im using to render it as a tile:

(Level class):

if (tiles[x + y * width] == Tile.col_portal)
        return Tile.portal;

(in Mob class, for player collision):

        if (this instanceof Player) {
            if (level.getTile(ix, iy) instanceof SpawnWaterTile) {
                Player.swimming = true;
                Player.canShoot = false;
            } else if (level.getTile(ix,iy) instanceof SpawnPortalTile) {
                Game.getGame().changeLevel(Level.level1);
            } else {
                Player.swimming = false;
                Player.canShoot = true;
            }
        }

EDIT: After attempting to reintroduce the portal class in the way that @Reg suggested, i had the following error:

Portal Class:

package com.ritcat14.GotYourSix.entity;

import com.ritcat14.GotYourSix.Game;
import com.ritcat14.GotYourSix.graphics.Screen;
import com.ritcat14.GotYourSix.graphics.Sprite;
import com.ritcat14.GotYourSix.level.Level;

public class Portal extends Entity {

    private int x = 0, y = 0;
    private Level currLevel = null, locationLevel = null;

    public static Portal Level1 = new Portal(1,1,Level.spawn, Level.level1);
    public static Portal Level2 = new Portal(2,1,Level.spawn, Level.level2);
    public static Portal Level3 = new Portal(3,1,Level.spawn, Level.level3);

    public Portal(int x, int y, Level currLevel, Level locationLevel){
        this.x = x;
        this.y = y;
        this.currLevel = currLevel;
        this.locationLevel = locationLevel;
        sprite = Sprite.portal;
    }

    public Portal(int x, int y, Level currLevel){
        this.x = x;
        this.y = y;
        this.locationLevel = Level.spawn;
        this.currLevel = currLevel;
        sprite = Sprite.portal;
    }

    public void update(){
        System.out.println(this);
        // --> null?? System.out.println(currLevel);
        System.out.println(currLevel.getClientPlayer());
        System.out.println(currLevel.getClientPlayer().getBounds());
        if     (this.getBounds().intersects(currLevel.getClientPlayer().getBounds())) {
          Game.getGame().changeLevel(locationLevel);
          remove();
        }
    }

    public void render(Screen screen){
        screen.renderSprite(x, y, sprite, true);
    } 
}

The change level method works fine, the issue seems to be that the current level doesn't actually exist. This is how im adding the portals to the level in the Level.spawn level:

    public class SpawnLevel extends Level {

    public SpawnLevel(String path) {
        super(path, false);
    }

    protected void loadLevel(String path){
        try{
            BufferedImage image = ImageIO.read(SpawnLevel.class.getResource(path));
            int w = width = image.getWidth();
            int h = height = image.getHeight();
            tiles = new int[w * h];
            image.getRGB(0, 0, w, h, tiles, 0, w);
        }catch(IOException e){
            e.printStackTrace();
            System.out.println("Failed to load level file.");
        }
     generateLevel();
    }

     public void setPlayerLocation(){
      for (int i = 0; i < getPlayers().size(); i ++){
          getPlayers().get(i).setLocation(new Vector2i(5 * 16, 70 * 16));
      }
   }

  protected void generateLevel(){
    add(Portal.Level1);
    add(Portal.Level2);
    add(Portal.Level3);
    //no enemies!
  }
}

Any ideas? The currLevel is apparently null

\$\endgroup\$
7
  • \$\begingroup\$ We need more info. Narrow the question by making it about the specific code you're using, not the general problem. :) \$\endgroup\$ – Almo Nov 30 '15 at 21:35
  • \$\begingroup\$ how would i do that @Almo? what do you need me to include? \$\endgroup\$ – Kris Rice Nov 30 '15 at 21:36
  • \$\begingroup\$ "when I ran the code" what code? Show us. \$\endgroup\$ – Almo Nov 30 '15 at 21:36
  • \$\begingroup\$ @Almo added code \$\endgroup\$ – Kris Rice Nov 30 '15 at 21:40
  • \$\begingroup\$ Now you should show the "Game.getGame().changeLeve(..);" function too. Otherwise we can't know why it gets freeze. \$\endgroup\$ – Ahmet Zambak Nov 30 '15 at 23:32
3
\$\begingroup\$

There are several options I can think of for associating each portal with a level, but the one you tried already is worthy of another go. Since you seem to have the Level class sorted nicely with Level.level1, Level.level2 etc., why not try a parent portal class with the different portals associated with the different levels in the same fashion? i.e. Portal.portal1, Portal.portal2, etc. (although if these are subclasses I would insist using caps). Then you can not only associate the different portals with their specific levels (in a manner which is easy to record), but they can define different appearances and permissions in their fields. Permissions can depend on the player rank, or as in other games, keys gained by the player, or events triggered in the environment. If I read you correctly, the code which was causing the freezing first time around is exactly this code which you have dispensed with, so have another bash at it, and stick it up if it gives more/the same problem.

\$\endgroup\$
4
  • \$\begingroup\$ hi @Reg i attempted this and have edited my question as needed. I seem to be getting a null pointer exception \$\endgroup\$ – Kris Rice Dec 1 '15 at 20:25
  • \$\begingroup\$ Nowhere in the code you have provided is currLevel given any value other than null. I have many questions which can't be answered yet from the code you have provided. My best guess is that the fault lies in the initial construction of the particular Portal that invokes the update() method. Do a quick check - when it is created, what is its currLevel? I suspect it never got one. \$\endgroup\$ – Ger Dec 2 '15 at 17:50
  • 1
    \$\begingroup\$ fixed the issue, when currLevel was set through the constructor, the level hadn't yet been created so null was being passed through. Fixed it now thank you \$\endgroup\$ – Kris Rice Dec 2 '15 at 19:57
  • \$\begingroup\$ Delighted for you. :) \$\endgroup\$ – Ger Dec 3 '15 at 19:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.