2
\$\begingroup\$

I have a text file that I am using for my map for the tiles to be allocated. This works fine, but I am running into issues figuring out how I would go about loading in a different part of the map.

For example, say I wanted the character to go into a cave or building, what would be a good way to go about loading this new area?

Right now I have my handler class setting the world in my game state class, and I have tried messing around in the game state class to try and accomplish what I want but have not had much success. In that game state class I have a tick and render method, and in the constructor I have it being set.

The methods that I have tried have resulted in a new map to be loaded in, but the other map is still loaded in under this, and I know this because the character has collisions set up. This also goes along with this issue, but what would be a good way to trigger this loading of the new section of the map?

Below is the code in my GameState class. (changeWorld is based off of the X coordinate when in game, and once you reach a certain point it switches maps; this was just done for testing because it is not an accurate way of doing it).

// Constructor...
    World1 = new Worlds(handler,"resources/Worlds/world1.txt");

    SpawnWorld = new Worlds(handler,"resources/Worlds/world2");

    if(Worlds.changeWorld() == false)
        handler.setWorld(World1);
    }
    else if(Worlds.changeWorld() == true) {
        World1=SpawnWorld;
        handler.setWorld(World1);
        entityManager.setPlayer(new Player (handler, 0,0));
    }
}//end contructor

public void tick() {    
    if(Worlds.changeWorld() == false)  {
        World1.tick();  
    }
    else if(Worlds.changeWorld() == true){
        World1=SpawnWorld;
        handler.setWorld(World1);
        SpawnWorld.tick();
    }   
}//end tick

public void render(Graphics g) {
    if(Worlds.changeWorld() == false) {
        World1.render(g);
    }//end if
    else if(Worlds.changeWorld() == true) {
            World1=SpawnWorld;
            handler.setWorld(World1);
            World1.render(g);
    }
}//end graphics
\$\endgroup\$
  • \$\begingroup\$ instead of checking if(Worlds.changeWorld()==true) you could simply write if(Worlds.changeWorld()) \$\endgroup\$ – Martin Frank Feb 19 at 7:21
  • \$\begingroup\$ do you try to develop on android? if you do so, you might add an appropriate tag \$\endgroup\$ – Martin Frank Feb 19 at 7:39
1
\$\begingroup\$

some of your ideas are good, some are terrible...

Data Model

first you have to create a proper design - that means you have to think about what data you have and how they interact - this part is missing yet (as far as i can see from that question)

Architecture

as you are a beginner i suggest you try to achieve something like a M-VC (Model-View-Control) to separate your game logic from your drawing tasks.

on the other hand it seems to be a good idea to update your game (your model) frequently using a tick() method - but keep in mind that you update only model values within the model (not controller or not on view) - maybe you trigger the GuiListener but that would be all.

UML-Diagramm (Draft)

enter image description here

reaction on changes

i'm not sure how you do implement input handling so i come up with this idea: Input Handling is done in the controller and delegated into the model. This is done by creating first a GUI and add ActionListener on the widget, maybe a keyListener for input on Keyboards or an actionListener on a button. These Inputs are delegated to the model and the model reacts to these changes

Data flow

finally comes some code - haha

User Input
the User presses a key (or a Button) on the GUI and this event is catched by the correlated Listener. this Listener is located inside the Controller:

public class Controller implements GuiListener{

    private final Game game;

    public Controller (Game game){
        this.game = game;
    }

    public void onButtonPresse(ActionEvent e){
        //Let's assume that was the Button to move player NORTH
        game.movePlayer(Direction.NORTH);

        //TODO validate input before:
        //if(game.canMove(Direction.North)){game.movePlayer(Direction.NORTH)}
        //else{notifyInvalidMovement();}
    }

    @Override
    public void guiChanged(Point center){
        //maybe somehting like this
        canvas.render(game.getViewport(center));
    }
}

that was all what happens on controller side - the input is simply delegated to the model!

Game reaction (finally he talks about how to load seperate maps!!!)
now the Input Event has come into the Model (aka the Game). The model updates it's values according to the input

public class Game{

    private final Map map;    
    private final Player player;
    private final GuiListener guiListener;

    public void movePlayer(Direction dir){
        Point from = player.getLocation();
        Point to = Direction.getDestiny(from, dir);
        map.movePlayer(from, to);

        if(map.isLocationTeleporter(to)){
           MapId mapId = map.getTeleportId();
           Point teleportDestiny = map.getTeleportDestiny();
           map = MapLoader.loadMap(mapId);
           map.setPlayer(teleportDestiny);
        }        

        //whatever happened now you might notify the UI to render these changes
        guiListener.guiChanged(player.getLocation());
    }
}

the changes from the controller are now properly handled and the map has been updated as soon as the player enters the teleport location (stairs to the basement). Even more, the player is set to the proper location on the new map.

Implementation hints

instead of using x/y-coordinates it seems very helpful to create a Data Object that encapsules these valuse: a Point!

class Point {
    private int x;
    private int y;

    //default constructor
    public Point(){
        this(0,0); //calls internally my two-parameter constructor
    }

    public Point(int x, int y){
        this.x = x;
        this.y = y;
    }

    public int getX(){
        return x;
    }

    public int getY(){
        return y;
    }

    @Override
    public String toString(){
        return "x/y:"+x+"/"+y;
    }

    public void translate(int dx, int dy){
        x = x + dx;
        y = y + dy;
    }

    public void translate(Point d){
        translate(d.getX(), d.getY());
    }
}

UML-Diagramm of Point
its much smaller than all this code and can be changed easier: good for playing with design/architecture/data models

enter image description here

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ as usual i've written all code out of my head without using any IDE - so there might be typos or worse... \$\endgroup\$ – Martin Frank Feb 19 at 8:36
  • \$\begingroup\$ Thank you for the diagrams that actually helped understand it much easier. I have a Key Listener that reads the input for the player and it is under the tick() method, and a separate camera class to follow around. I think what I am struggling to understand is how to stop the first map from being rendered or ticked once the player goes to the point to teleport. Also, for the line Point teleportDestiny ... , how would I do that If I have an X and a Y? \$\endgroup\$ – Jt792019 Feb 19 at 21:22
  • \$\begingroup\$ a Point is a Data Object (Data is important as mentioned in my answer) - a Data Object that contains an x and an y-coordinate - i'll add a class in my answer \$\endgroup\$ – Martin Frank Feb 20 at 5:16
  • \$\begingroup\$ I really appreciate you writing out the code, and point class is something I am definitely going to implement because I think it will help solve some headaches. All your help is greatly appreciated. \$\endgroup\$ – Jt792019 Feb 20 at 5:32
  • \$\begingroup\$ it was nice to talk with someone as passionate as i am =) happy coding!!! \$\endgroup\$ – Martin Frank Feb 20 at 6:20

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.