How to make a player stay within bounds of world with 2D Camera

Posted by Craig on Game Development See other posts from Game Development or by Craig
Published on 2012-11-18T18:47:36Z Indexed on 2012/11/18 23:34 UTC
Read the original article Hit count: 231

Filed under:
|
|

Im creating a simple top down survival game. At the moment, i have the sprite which is a ship and moves by rotating left or right then going forward in that direction. I have implemented a 2D camera, its always centered on the player.

However, when i move towards the bounds of the world that the sprite is in it just keeps on going :(

How to i sort it that it stops at the edge of the world and cant go beyond it?

Cheers :)

Below is the main game class

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

namespace GamesCoursework_1
{
/// <summary>
/// This is the main type for your game
/// </summary>
public class Game1 : Microsoft.Xna.Framework.Game
{
    GraphicsDeviceManager graphics;
    SpriteBatch spriteBatch;


    // player variables
    Texture2D Ship;
    Vector2 Ship_Position;
    float Ship_Rotation = 0.0f;
    Vector2 Ship_Origin;
    Vector2 Ship_Velocity;
    const float tangentialVelocity = 4f;
    float friction = 0.05f;

    static Point CameraViewport = new Point(800, 800);
    Camera2d cam = new Camera2d((int)CameraViewport.X, (int)CameraViewport.Y);
    //Size of world
    static Point worldSize = new Point(1600, 1600);
    // Screen variables
    static Point worldCenter = new Point(worldSize.X / 2, worldSize.Y / 2);

    Rectangle playerBounds = new Rectangle(CameraViewport.X / 2, CameraViewport.Y / 2, worldSize.X - CameraViewport.X, worldSize.Y - CameraViewport.Y);
    Rectangle worldBounds = new Rectangle(0, 0, worldSize.X, worldSize.Y);

    Texture2D background;


    public Game1()
    {
        graphics = new GraphicsDeviceManager(this);

        graphics.PreferredBackBufferWidth = CameraViewport.X;
        graphics.PreferredBackBufferHeight = CameraViewport.Y;
        Content.RootDirectory = "Content";
    }

    /// <summary>
    /// Allows the game to perform any initialization it needs to before starting to run.
    /// This is where it can query for any required services and load any non-graphic
    /// related content.  Calling base.Initialize will enumerate through any components
    /// and initialize them as well.
    /// </summary>
    protected override void Initialize()
    {
        // TODO: Add your initialization logic here

        base.Initialize();
    }

    /// <summary>
    /// LoadContent will be called once per game and is the place to load
    /// all of your content.
    /// </summary>
    protected override void LoadContent()
    {
        // Create a new SpriteBatch, which can be used to draw textures.
        spriteBatch = new SpriteBatch(GraphicsDevice);

        // TODO: use this.Content to load your game content here
        Ship = Content.Load<Texture2D>("Ship");
        Ship_Origin.X = Ship.Width / 2;
        Ship_Origin.Y = Ship.Height / 2;

        background = Content.Load<Texture2D>("aus");

        Ship_Position = new Vector2(worldCenter.X, worldCenter.Y);
        cam.Pos = Ship_Position;
        cam.Zoom = 1f;


    }

    /// <summary>
    /// UnloadContent will be called once per game and is the place to unload
    /// all content.
    /// </summary>
    protected override void UnloadContent()
    {
        // TODO: Unload any non ContentManager content here
    }

    /// <summary>
    /// Allows the game to run logic such as updating the world,
    /// checking for collisions, gathering input, and playing audio.
    /// </summary>
    /// <param name="gameTime">Provides a snapshot of timing values.</param>
    protected override void Update(GameTime gameTime)
    {
        // Allows the game to exit
        if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
            this.Exit();

        // TODO: Add your update logic here
        Ship_Position = Ship_Velocity + Ship_Position;
        keyPressed();

        base.Update(gameTime);
    }

    /// <summary>
    /// This is called when the game should draw itself.
    /// </summary>
    /// <param name="gameTime">Provides a snapshot of timing values.</param>
    protected override void Draw(GameTime gameTime)
    {
        GraphicsDevice.Clear(Color.CornflowerBlue);

        // TODO: Add your drawing code here
        spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, null, null, null,null, cam.get_transformation(GraphicsDevice));
        spriteBatch.Draw(background, Vector2.Zero, Color.White);
        spriteBatch.Draw(Ship, Ship_Position, Ship.Bounds, Color.White, Ship_Rotation, Ship_Origin, 1.0f, SpriteEffects.None, 0f); 
        spriteBatch.End();



        base.Draw(gameTime);
    }

    private void Ship_Move(Vector2 move)
    {
        Ship_Position += move;
    }

    private void keyPressed()
    {
        KeyboardState keyState;
        // Move right
        keyState = Keyboard.GetState();

        if (keyState.IsKeyDown(Keys.Right))
        {
            Ship_Rotation = Ship_Rotation + 0.1f;
        }
        if (keyState.IsKeyDown(Keys.Left))
        {
            Ship_Rotation = Ship_Rotation - 0.1f;
        }
        if (keyState.IsKeyDown(Keys.Up))
        {
            Ship_Velocity.X = (float)Math.Cos(Ship_Rotation) * tangentialVelocity;
            Ship_Velocity.Y = (float)Math.Sin(Ship_Rotation) * tangentialVelocity;
            if ((int)Ship_Position.Y < playerBounds.Bottom && (int)Ship_Position.Y > playerBounds.Top) cam._pos.Y = Ship_Position.Y;
            if ((int)Ship_Position.X > playerBounds.Left && (int)Ship_Position.X < playerBounds.Right) cam._pos.X = Ship_Position.X;

            //tried world bounds here
            if (!worldBounds.Contains(new Point((int)Ship_Position.X, (int)Ship_Position.Y))) Ship_Position -= new Vector2(0.0f, -tangentialVelocity * 2);
            if (!worldBounds.Contains(new Point((int)Ship_Position.X, (int)Ship_Position.Y))) Ship_Position -= new Vector2(0.0f, 2 * tangentialVelocity);

        } 
        else if(Ship_Velocity != Vector2.Zero)
        {
            float i = Ship_Velocity.X;
            float j = Ship_Velocity.Y;

            Ship_Velocity.X = i -= friction * i;
            Ship_Velocity.Y = j -= friction * j;

            if ((int)Ship_Position.Y < playerBounds.Bottom && (int)Ship_Position.Y > playerBounds.Top) cam._pos.Y = Ship_Position.Y;
            if ((int)Ship_Position.X > playerBounds.Left && (int)Ship_Position.X < playerBounds.Right) cam._pos.X = Ship_Position.X;
        }
        if (keyState.IsKeyDown(Keys.Q))
        {
            if (cam.Zoom < 2f) cam.Zoom += 0.05f;
        }
        if (keyState.IsKeyDown(Keys.A))
        {
            if (cam.Zoom > 0.3f) cam.Zoom -= 0.05f;
        }

    }
}
}

my 2d camera class

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

namespace GamesCoursework_1
{
public class Camera2d
{
    protected float _zoom; // Camera Zoom
    public Matrix _transform; // Matrix Transform
    public Vector2 _pos; // Camera Position
    protected float _rotation; // Camera Rotation
    public int _viewportWidth, _viewportHeight; // viewport size

    public Camera2d(int ViewportWidth, int ViewportHeight)
    {
        _zoom = 1.0f;
        _rotation = 0.0f;
        _pos = Vector2.Zero;

        _viewportWidth = ViewportWidth;
        _viewportHeight = ViewportHeight;
    }


    // Sets and gets zoom
    public float Zoom
    {
        get { return _zoom; }
        set { _zoom = value; if (_zoom < 0.1f) _zoom = 0.1f; } // Negative zoom will flip image
    }

    public float Rotation
    {
        get { return _rotation; }
        set { _rotation = value; }
    }

    // Auxiliary function to move the camera
    public void Move(Vector2 amount)
    {
        _pos += amount;
    }
    // Get set position
    public Vector2 Pos
    {
        get { return _pos; }
        set { _pos = value; }
    }


    public Matrix get_transformation(GraphicsDevice graphicsDevice)
    {
        _transform =       // Thanks to o KB o for this solution
          Matrix.CreateTranslation(new Vector3(-_pos.X, -_pos.Y, 0)) *
                                     Matrix.CreateRotationZ(Rotation) *
                                     Matrix.CreateScale(new Vector3(Zoom, Zoom, 1)) *
                                     Matrix.CreateTranslation(new Vector3(_viewportWidth * 0.5f, _viewportHeight * 0.5f, 0));
        return _transform;
    }

}
}

© Game Development or respective owner

Related posts about c#

Related posts about xna-4.0