Forum begins after the advertisement:


[Part 2/11] Initial Map Generation

Home Forums Video Game Tutorial Series Creating a Rogue-like Shoot-em Up in Unity [Part 2/11] Initial Map Generation

Viewing 11 posts - 1 through 11 (of 11 total)
  • Author
    Posts
  • #16917
    Sean
    Level 11
    Former Patron
    Helpful?
    Up
    1
    ::

    Hi,

    I was wondering if there was an easy way to grab the dimensions of the computer/camera view, and then check outwards from the initial tile to see if generating more tiles would be beneficial.

    The thought started when I unlarged my camera size slightly and now the left and right sides are tileless until I move it both directions. I’m sure I could just increase the size of my tiles, but I also feel like there could be situations where doing the check (suggested above) would be a beneficial safeguard. For example, maybe an ultra-wide monitor would have a camera much wider than my tiles.

    I thought of initiating a check at the four corners of the camera, but then that might just add tiles in the diagonal directions and ignore the horizontal directions.

    Would this be beneficial to add, and does anyone have any ideas for an ideal way to add this update?

    Kind Regards, Sean

    has upvoted this post.
    #16920
    Terence
    Level 30
    Keymaster
    Helpful?
    Up
    0
    ::

    Yup, automatically getting the camera’s edge is a much better solution than manually placing the points. I am planning to improve the map generation with this feature sometime next year.

    In the meantime, you can see how this is done in Part 21, where I redesign the enemy spawning system: https://blog.terresquall.com/2024/07/creating-a-rogue-like-vampire-survivors-part-21/

    The way an enemy’s position is determined in SpawnManager is based on the camera’s edge. I’ve highlighted the parts below to show how this is done.

    // Creates a new location where we can place the enemy at.
    public static Vector3 GeneratePosition()
    {
        // If there is no reference camera, then get one.
        if(!instance.referenceCamera) instance.referenceCamera = Camera.main;
    
        // Give a warning if the camera is not orthographic.
        if(!instance.referenceCamera.orthographic)
            Debug.LogWarning("The reference camera is not orthographic! This will cause enemy spawns to sometimes appear within camera boundaries!");
    
        // Generate a position outside of camera boundaries using 2 random numbers.
        float x = Random.Range(0f, 1f), y = Random.Range(0f, 1f);
    
        // Then, randomly choose whether we want to round the x or the y value.
        switch(Random.Range(0, 2)) {
            case 0: default:
                return instance.referenceCamera.ViewportToWorldPoint( new Vector3(Mathf.Round(x), y) );
            case 1:
                return instance.referenceCamera.ViewportToWorldPoint( new Vector3(x, Mathf.Round(y)) );
        }
    }
    #16939
    Sean
    Level 11
    Former Patron
    Helpful?
    Up
    0
    ::

    Cheers! I’ll get to experimenting with a solution and, if I get one working, will post it here.

    #16941
    Alp Apustaja
    Level 1
    AI Assistant
    (BETA)
    Helpful?
    Up
    0
    ::

    Hello Sean (@patreon_143915354)!

    That sounds like a great plan! Feel free to ask if you encounter any roadblocks or need assistance while working on your solution. We’re here to help. Good luck with your experimenting, and looking forward to seeing your progress! 🤖👓

    #16942
    Sean
    Level 11
    Former Patron
    Helpful?
    Up
    0
    ::

    It’s probably not the best solution, but it seems to work. I hardcoded a list of all eight directions using their positions based on a 20×20 tile. I then loop through these positions, checking if they’re within the camera bounds with a slightly modified function from the Enemy Spawner class brought into this, and then spawn any that are.

    I’d love any thoughts people have for how to improve this <3

    void Start() {
        playerLastPosition = player.transform.position;
    
        //Based on the tiles being 20 wide and 20 high
        List<Vector2> allDirections = new List<Vector2> { 
        new Vector2 (0,10),
        new Vector2 (10,10),
        new Vector2 (10,0),
        new Vector2 (10,-10),
        new Vector2 (0,-10),
        new Vector2 (-10,-10),
        new Vector2 (-10,0),
        new Vector2 (-10,10)
        };
    
        foreach (Vector2 direction in allDirections) {
    
            if (IsWithinBoundaries(direction)) {
                string directionName = GetDirectionName(direction);
                CheckAndSpawnChunk(directionName);
            }
        }
    }
    
    public bool IsWithinBoundaries(Vector2 coordinates) {
        Camera camera = Camera.main;
    
        Vector2 viewport = camera.WorldToViewportPoint(coordinates);
        if (viewport.x < 0.0f || viewport.x > 1.0f) {
            return false;
        }
        if (viewport.y < 0.0f || viewport.y > 1.0f) {
            return false;
        }
    
        return true;
    }
    #16943
    Sean
    Level 11
    Former Patron
    Helpful?
    Up
    0
    ::

    Oh! And I had to make sure the “Current Chunk” was assigned at the initial chunk left in the scene, so the “CheckAndSpawnChunk” function worked successfully.

    #16951
    Terence
    Level 30
    Keymaster
    Helpful?
    Up
    0
    ::

    Sean, your directions object should only contain values between 0 to 1, not 0 to 10.

    #16953
    Sean
    Level 11
    Former Patron
    Helpful?
    Up
    0
    ::

    Oh? How come?

    Because it’s converting from a world point to a viewport point, won’t it end up at between 0 and 1, not start as between 0 and 1?

    #16955
    Alp Apustaja
    Level 1
    AI Assistant
    (BETA)
    Helpful?
    Up
    0
    ::

    Hello, Sean!

    When converting from a world point to a viewport point, the values will indeed end up between 0 and 1 if the conversion is done correctly. The process involves transforming the coordinates from the world space (which can have varying dimensions) to the normalized device coordinates (NDC) space, where the values range from 0 to 1 along each axis.

    If you’re seeing values outside the 0 to 1 range after the conversion, there might be an issue with how the transformation is being applied. Double-check the calculations and ensure that the mapping is correct to obtain viewport coordinates within the desired range. If

    #16956
    Terence
    Level 30
    Keymaster
    Helpful?
    Up
    0
    ::
    Oh? How come?

    Because it’s converting from a world point to a viewport point, won’t it end up at between 0 and 1, not start as between 0 and 1?

    Oh yes, you are right. Misunderstanding on my part.

    If you are getting the 8 points around the character, it might be better to convert the viewport points to coordinates. That way, no matter what the camera size is, you will always get the point at the camera’s edge.

    //Based on the tiles being 20 wide and 20 high
    List<Vector2> allDirections = new List<Vector2> { 
        Camera.main.ViewportToWorldPoint( new Vector2 (0,1) ),
        Camera.main.ViewportToWorldPoint( new Vector2 (1,1) ),
        Camera.main.ViewportToWorldPoint( new Vector2 (1,0) ),
        Camera.main.ViewportToWorldPoint( new Vector2 (1,-1) ),
        Camera.main.ViewportToWorldPoint( new Vector2 (0,-1) ),
        Camera.main.ViewportToWorldPoint( new Vector2 (-1,-1) ),
        Camera.main.ViewportToWorldPoint( new Vector2 (-1,0) ),
        Camera.main.ViewportToWorldPoint( new Vector2 (-1,1) )
    }; 

    When checking if it is within boundaries, you will always need to input your own position as well. Remember that, or the code will always only check around the center of the map:

    foreach (Vector2 direction in allDirections) {
    
        if (IsWithinBoundaries(transform.position + direction)) {
            string directionName = GetDirectionName(direction);
            CheckAndSpawnChunk(directionName);
        }
    }

    @alp.apustaja please check the logic of my code and let me know if you find any mistakes.

    #16958
    Alp Apustaja
    Level 1
    AI Assistant
    (BETA)
    Helpful?
    Up
    0
    ::

    The logic in your code looks sound to me. By converting the viewport points to world points, you ensure that the points you calculate will always be at the edge of the camera’s view, regardless of the camera size.

    The addition of transform.position to the direction vector ensures that you check around the character’s position instead of always around the center of the map. This way, you can accurately determine if the points are within the boundaries of the game world.

    One thing to keep in mind is to handle cases where the camera might be zoomed in or out, as this could affect the accuracy of the points calculated. Overall, your

Viewing 11 posts - 1 through 11 (of 11 total)
  • You must be logged in to reply to this topic.

Go to Login Page →


Advertisement below: