6 Replies - 724 Views - Last Post: 20 July 2017 - 02:26 AM Rate Topic: -----

#1 eazyyzae  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 23
  • Joined: 23-February 13

Cant decide how to tackle loading the next levels

Posted 07 July 2017 - 06:04 AM

I've got a platformer game basics done. It has 1 example map/level so far. If i were to go in a door or move off to the right edge of the level I want to be able to load up the next map say.

I have in my game a state machine that eventually loads of the Gameplayscreen class. like this

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content;

namespace ScreenTansitions1
{
    public class GameplayScreen : GameScreen
    {
        EntityManager player, enimies, hacksilber, floatingPlatform;
        Map map;
        Timer timer;
        SpriteFont font;
        Sprites sprite;

        public string mapID;

        public override void LoadContent(ContentManager content, InputManager input)
        {
            base.LoadContent(content, input);
            player = new EntityManager();
            enimies = new EntityManager();
            hacksilber = new EntityManager();
            floatingPlatform = new EntityManager();
            sprite = new Sprites(content, "");

            map = new Map();
            map.LoadContent(content, map, "Map1");

            player.LoadContent("Player", content, "Load/Player.jmg", "", input);
            enimies.LoadContent("Enemy", content, "Load/Enimies.jmg", "", input);
            hacksilber.LoadContent("Hacksilber", content, "Load/Hacksilber.jmg", "", input);
            floatingPlatform.LoadContent("FloatingPlatform", content, "Load/FloatingPlatform.jmg", "", input);

            timer = new Timer(300);
            font = content.Load<SpriteFont>("Fonts/DataFont");
        }

        public override void UnloadContent()
        {
            base.UnloadContent();
            player.UnloadContent();
            map.UnloadContent();
        }

        public override void Update(GameTime gameTime)
        {
            inputManager.Update();
            player.Update(gameTime, map);
            enimies.Update(gameTime, map);
            hacksilber.Update(gameTime, map);
            floatingPlatform.Update(gameTime, map);
            map.Update(gameTime);
            timer.Update(gameTime);
            Entity e;

            for (int i = 0; i < player.Entities.Count; i++)
            {
                e = player.Entities[i];
                map.UpdateCollision(ref e);
                player.Entities[i] = e;
            }

            for (int i = 0; i < enimies.Entities.Count; i++)
            {
                e = enimies.Entities[i];
                map.UpdateCollision(ref e);
                enimies.Entities[i] = e;
            }
            for (int i = 0; i < hacksilber.Entities.Count; i++)
            {
                e = hacksilber.Entities[i];
                map.UpdateCollision(ref e);
                hacksilber.Entities[i] = e;
            }

            for (int i = 0; i < floatingPlatform.Entities.Count; i++)
            {
                e = floatingPlatform.Entities[i];
                map.UpdateCollision(ref e);
                floatingPlatform.Entities[i] = e;
            }

            // Check for collisions
            player.EntityCollision(enimies);
            hacksilber.EntityCollision(player);
            floatingPlatform.EntityCollision(player);
            floatingPlatform.EntityCollision(enimies);
            
        }


        public override void Draw(SpriteBatch spriteBatch)
        {   // Try draw in order here
            base.Draw(spriteBatch);
            
            sprite.Draw(spriteBatch);

            map.Draw(spriteBatch);

            enimies.Draw(spriteBatch);

            floatingPlatform.Draw(spriteBatch);

            hacksilber.Draw(spriteBatch);

            player.Draw(spriteBatch);

            spriteBatch.DrawString(font, "T: " + (int)timer.TimeLeft, new Vector2(Camera.Instance.position.X + ScreenManager.Instance.Dimensions.X - 90, 10),  Color.Blue);
        }
    }
}



I can change the map using map.LoadContent(content, map, "Map1"); and my map file looks like this (shortend down)

Load=[MapProperties]

Load=[TileDimesnions]
[32,32]

EndLoad=[MapProperties]

Load=[Solid]
[3,0]
[3,1]
[3,2]

[4,3]

[5,3]

[6,3]

Load=[OnewayUP]
[0,0]
[1,0]
[2,0]
[7,0]
[8,0]
[9,0]
[7,1]
[8,1]
[9,1]
[7,2]
[8,2]
[9,2]

Load=[NullTile]
[---]

Load=[Motion]

Load=[TileSet]
[JADTiles_01(32x32)]

Load=[StartLayer]
[---][---][---][---][---][---][---][---]
[---][---][---][---][---][---][---][---]
[---][---][---][---][---][---][---][---]
[---][---][---][---][---][---][---][---]
[---][---][---][---][---][---][---][---]
[---][---][---][---][---][---][---][---]
[---][---][---][---][---][---][---][---]
[---][---][---][---][---][---][---][---]
[---][---][---][---][7,4][7,4][7,4][7,4]
[---][---][---][---][6,4][6,4][6,4][6,4]
[---][---][---][---][6,4][6,4][6,4][6,4]
[---][---][---][---][6,4][6,4][6,4][6,4]
[---][---][---][---][6,4][6,4][6,4][6,4]
[0,0][1,0][1,0][1,0][1,0][1,0][1,0][1,0]
[0,1][1,1][1,1][1,1][1,1][1,1][1,1][1,1]

Load=[EndLayer]
[dummy]




I can use map.LoadContent(content, map, "Map1"); to change the map...

But I think that would end up with one GIGANTIC switch and enum if I had say 100+ different levels / maps.

Is that even reasonable???

Or should I have a bit in my map file for instance

Load=[Exits]
[001:Map2:10,400]
[002:Map3:5000, 400]

then read and compare it to the position of my player.

I cant seem to find a lot on how other people generally do it as most tutorials only cover 1 level

I feel like there is a better way and I'm just not seeing it

Is This A Good Question/Topic? 0
  • +

Replies To: Cant decide how to tackle loading the next levels

#2 modi123_1  Icon User is online

  • Suitor #2
  • member icon



Reputation: 13483
  • View blog
  • Posts: 53,820
  • Joined: 12-June 08

Re: Cant decide how to tackle loading the next levels

Posted 07 July 2017 - 08:25 AM

Are folk allowed to back track to the left to go to previous maps?
Was This Post Helpful? 0
  • +
  • -

#3 eazyyzae  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 23
  • Joined: 23-February 13

Re: Cant decide how to tackle loading the next levels

Posted 07 July 2017 - 08:37 AM

Yes
Was This Post Helpful? 0
  • +
  • -

#4 stayscrisp  Icon User is offline

  • フカユ
  • member icon

Reputation: 1040
  • View blog
  • Posts: 4,325
  • Joined: 14-February 08

Re: Cant decide how to tackle loading the next levels

Posted 11 July 2017 - 10:07 AM

Map properties could hold a next and previous map value, then you just need to read that to decide what to load.
Was This Post Helpful? 0
  • +
  • -

#5 eazyyzae  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 23
  • Joined: 23-February 13

Re: Cant decide how to tackle loading the next levels

Posted 12 July 2017 - 04:55 PM

Had a typo in my code that reads the plain text files in, preventing me from changing the maps by a mapID string.

Just took me about 4 hours to debug it.

so I changed these to mapID now;

map = new Map();
            map.LoadContent(content, map, mapID);

            player.LoadContent("Player", content, "Load/Player.jmg", mapID, input);
            enimies.LoadContent("Enemy", content, "Load/Enimies.jmg", mapID, input);
  
            hacksilber.LoadContent("Hacksilber", content, "Load/Hacksilber.jmg", mapID, input);
            floatingPlatform.LoadContent("FloatingPlatform", content, "Load/FloatingPlatform.jmg", mapID, input);


Now I only need to change the value of one string and the map/coins/enemies etc... all change

I think I might read in the exits as entities like my coins and enemies in a separate plain text file and if my player collides with the co-ords I read in while I press up or something on a door I can change the string to what it reads.

I could use the MapProperties like you say but that file deals with a tilemap using a sprite sheet and I think it might be a bit more difficult for me to try and separate them from just co-ords and a map name. MapProperties could hold the left and right edge side values of my map though which would be real handy.


I'll see what happens tomorrow as it's getting late now. Thanks anyway
Was This Post Helpful? 0
  • +
  • -

#6 stayscrisp  Icon User is offline

  • フカユ
  • member icon

Reputation: 1040
  • View blog
  • Posts: 4,325
  • Joined: 14-February 08

Re: Cant decide how to tackle loading the next levels

Posted 15 July 2017 - 05:20 PM

I don't see why you would need to store coordinates for exists beyond a value that indicates they are an exit, read from the text file before hand and store the values, then when you hit a tile that has an exit id look it up.

Tile tile = GetTile(nextPosition);
if(tile.typeID == Exit)
{
      //load new level
      LoadLevel(exits[tile.exit]);
}


Was This Post Helpful? 0
  • +
  • -

#7 eazyyzae  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 23
  • Joined: 23-February 13

Re: Cant decide how to tackle loading the next levels

Posted 20 July 2017 - 02:26 AM

Got it working fine.

Here is a video of it working, Needs a bit of a polish. I have the door drawn in the video for debugging, obv they wouldn't be drawn.

Youtube video of doors working

I just read in a file like this;
Load=[Overworld1]
Load=[Image][Position][Frames][MapDest]
[door][176,384][1,1][Map1]
EndLoad=[OverWorld1]

Load=[Map1]
Load=[Image][Position][Frames][MapDest]
[door][176,384][1,1][Map2]
EndLoad=[Map1]

Load=[Map2]
Load=[Image][Position][Frames][MapDest]
[door][144,384][1,1][Map1]
EndLoad=[Map2]


I read them in using my Entity class. This was easier I found than using the tiles. I would have needed a lots of different tiles for different doors I thought.

namespace Floki
{
    public class Entity
    {
        protected int health, range, direction, platformDirection;
        protected Animation moveAnimation;
        protected SpriteSheetAnimation ssAnimation;
        protected float moveSpeed, gravity;
        protected ContentManager content;
        protected Texture2D image;
        protected Vector2 position, velocity, prevPosition;
        protected List<List<string>> attributes, contents, L_hacksilber;
        protected bool activatedGravity, syncTilePosition, onTile;
        protected Vector2 destPosition, origPosition;
        protected bool jumpKeyEnabled;
        protected float jumpPos;
        public bool hasJumped, isAlive;
        public float startPos, maxPos;
        protected string mapDestination, name, dialogue;
        public bool overworld;

        #region properties
        public string MapDestination
        {
            get { return mapDestination; }
            set { mapDestination = value; }
        }

        public float JumpPos
        {
            get { return jumpPos; }
            set { jumpPos = value; }
        }
    
        public int Direction
        {
            get { return direction; }
            set
            {
                direction = value;
                destPosition.X = (direction == 2) ? destPosition.X = origPosition.X - range :
                    destPosition.X = origPosition.X + range;
            }
        }

        public bool JumpKeyEnabled
        {
            get { return jumpKeyEnabled; }
            set { jumpKeyEnabled = value; }
        }

        public bool OnTile
        {
            get { return onTile; }
            set { onTile = value; }
        }
        public Vector2 PrevPosition
        {
            get { return prevPosition; }
        }
        public List<List<string>> LHackSilber
        {
            get { return L_hacksilber; }
        }

        public Animation Animation
        {
            get { return moveAnimation; }
        }

        public Vector2 Velocity
        {
            get { return velocity; }
            set { velocity = value; }
        }

        public Vector2 Position
        {
            get { return position; }
            set { position = value; }
        }

        public bool ActivateGravity
        {
            set { activatedGravity = value; }
        }

        public bool SyncTilePosition
        {
            get { return syncTilePosition; }
            set { syncTilePosition = value; }
        }

        public FloatRect Rect
        {
            get { return new FloatRect(position.X, position.Y, moveAnimation.FrameWidth, moveAnimation.FrameHeight); }
        }

        #endregion

        /// <summary>
        /// Loads in the contents from the plain text files such as player, enimies, exits
        /// </summary>
        /// <param name="content"></param>
        /// <param name="attributes"></param>
        /// <param name="contents"></param>
        /// <param name="input"></param>
        public virtual void LoadContent(ContentManager content, List<string> attributes, List<string> contents, InputManager input)
        {
            this.content = new ContentManager(content.ServiceProvider, "Content");
            moveAnimation = new Animation();
            ssAnimation = new SpriteSheetAnimation();
            JumpKeyEnabled = false;

            for (int i = 0; i < attributes.Count; i++)
            {
                switch (attributes[i])
                {
                    case "Health":
                        health = int.Parse(contents[i]);
                        break;
                    case "Frames":
                        string[] frames = contents[i].Split(',');
                        moveAnimation.Frames = new Vector2(int.Parse(frames[0]), int.Parse(frames[1]));
                        break;
                    case "Image":
                        image = content.Load<Texture2D>(contents[i]);
                        break;
                    case "Position":
                        frames = contents[i].Split(',');
                        position = new Vector2(int.Parse(frames[0]), int.Parse(frames[1]));
                        break;
                    case "MoveSpeed":
                        moveSpeed = float.Parse(contents[i]);
                        break;
                    case "Range":
                        range = int.Parse(contents[i]);
                        break;
                    case "Direction":
                        direction = int.Parse(contents[i]);
                        break;
                    case "MapDest":
                        mapDestination = contents[i];
                        break;
                    case "ScreenWidth":
                        Data.screenWidth = int.Parse(contents[i]);
                        break;
                    case "Name":
                        name = contents[i];
                        break;
                    case "Dialogue":
                        dialogue = contents[i];
                        break;
                    case "Overworld":
                        Data.overworld = bool.Parse(contents[i]);
                        break;
                }
            }

Using a simple Exit class;

namespace Floki
{
    public class Exit : Entity
    {
        public string mapID;

        public override void LoadContent(ContentManager content, List<string> attributes, List<string> contents, InputManager input)
        {
            base.LoadContent(content, attributes, contents, input);
            moveAnimation.DrawColor = Color.White;
            moveAnimation.IsActive = true;
        }

        public override void UnloadContent()
        {
            base.UnloadContent();

        }

        public override void Update(GameTime gameTime, InputManager inputManager, Collision col, Layer layer)
        {
            base.Update(gameTime, inputManager, col, layer);
            moveAnimation.IsActive = true;
            ssAnimation.Update(gameTime, ref moveAnimation);
        }

        //
        // Handles collision between player and Exit
        //
        public override void OnCollision(Entity e)
        {

            Type type = e.GetType();
            if (type == typeof(Player))
            {
                    Data.newMap = mapDestination;
            }
        }

        public override void Draw(SpriteBatch spriteBatch)
        {
            base.Draw(spriteBatch);
            moveAnimation.Draw(spriteBatch);

        }
    }




Then in my Gamplayscreen.cs

    public class GameplayScreen : GameScreen
    {
        EntityManager player, enimies, hacksilber, floatingPlatform, exit, npc;
        Map map;
        Timer timer;
        SpriteFont font;
        Sprites sprite;
        
        public string mapID = "Overworld1";

        public override void LoadContent(ContentManager content, InputManager input)
        {
            base.LoadContent(content, input);
            player = new EntityManager();

            npc = new EntityManager();

            enimies = new EntityManager();
            hacksilber = new EntityManager();
            floatingPlatform = new EntityManager();
            sprite = new Sprites(content, "");
            exit = new EntityManager();

            map = new Map();
            map.LoadContent(content, map, mapID);

            player.LoadContent("Player", content, "Load/Player.jmg", mapID, input);

            npc.LoadContent("NPC", content, "Load/NPCs/NPC.jmg", mapID, input);

            enimies.LoadContent("Enemy", content, "Load/Enimies.jmg", mapID, input);
            exit.LoadContent("Exit", content, "Load/Exit.jmg", mapID, input);
            hacksilber.LoadContent("Hacksilber", content, "Load/Hacksilber.jmg", mapID, input);
            floatingPlatform.LoadContent("FloatingPlatform", content, "Load/FloatingPlatform.jmg", mapID, input);

            timer = new Timer(300);
            font = content.Load<SpriteFont>("Fonts/DataFont");
        }

        public override void UnloadContent()
        {
            base.UnloadContent();
            player.UnloadContent();
            map.UnloadContent();
        }

        public override void Update(GameTime gameTime)
        {
            inputManager.Update();
            player.Update(gameTime, map);
            npc.Update(gameTime, map);
            enimies.Update(gameTime, map);
            hacksilber.Update(gameTime, map);
            floatingPlatform.Update(gameTime, map);
            map.Update(gameTime);
            timer.Update(gameTime);
            Entity e;

            for (int i = 0; i < player.Entities.Count; i++)
            {
                e = player.Entities[i];
                map.UpdateCollision(ref e);
                player.Entities[i] = e;
            }

            for (int i = 0; i < enimies.Entities.Count; i++)
            {
                e = enimies.Entities[i];
                map.UpdateCollision(ref e);
                enimies.Entities[i] = e;
            }
            for (int i = 0; i < hacksilber.Entities.Count; i++)
            {
                e = hacksilber.Entities[i];
                map.UpdateCollision(ref e);
                hacksilber.Entities[i] = e;
            }

            for (int i = 0; i < floatingPlatform.Entities.Count; i++)
            {
                e = floatingPlatform.Entities[i];
                map.UpdateCollision(ref e);
                floatingPlatform.Entities[i] = e;
            }

            for (int i = 0; i < exit.Entities.Count; i++)
            {
                e = exit.Entities[i];
                map.UpdateCollision(ref e);
                exit.Entities[i] = e;
            }

            for (int i = 0; i < npc.Entities.Count; i++)
            {
                e = npc.Entities[i];
                map.UpdateCollision(ref e);
                npc.Entities[i] = e;
            }
            // Check for collisions
            player.EntityCollision(enimies);
            hacksilber.EntityCollision(player);
            floatingPlatform.EntityCollision(player);
            floatingPlatform.EntityCollision(enimies);

            if(Data.speakChar)
                npc.EntityCollision(player);

            if(Data.enterDoor)
                exit.EntityCollision(player);

            if (Data.overworld)
                exit.EntityCollision(player);


            if (Data.currentMap != Data.newMap)
            {
                mapID = Data.newMap;
                Data.newMap = Data.oldMap;

                map = new Map();
                map.LoadContent(content, map, mapID);
                player.LoadContent("Player", content, "Load/Player.jmg", mapID, inputManager);

                npc.LoadContent("NPC", content, "Load/NPCs/NPC.jmg", mapID, inputManager);

                enimies.LoadContent("Enemy", content, "Load/Enimies.jmg", mapID, inputManager);

                exit.LoadContent("Exit", content, "Load/Exit.jmg", mapID, inputManager);

                hacksilber.LoadContent("Hacksilber", content, "Load/Hacksilber.jmg", mapID, inputManager);
                floatingPlatform.LoadContent("FloatingPlatform", content, "Load/FloatingPlatform.jmg", mapID, inputManager);

                mapID = Data.currentMap;
            }
        }



I made a Data class to hold some variables as I was struggling to get some of the objects to interact with each other;

namespace Floki
{
    public class Data
    {

        public static int score = 0;
        public static int lives = 3;
        public static string currentMap, oldMap, newMap;
        public static bool debug = false, fixedCamera = true, enterDoor = false, speakChar = false;
        public static int screenWidth, screenHeight;
        public static bool overworld = true;
    }


Was This Post Helpful? 0
  • +
  • -

Page 1 of 1