cannot convert from 'int' to MsPacman.Ghost.Direction - c#

I have not used any of this in class but its still a requirement on our project and I'm getting a bit squeezed.
Summarized: I have to do a pacman game in 2D using the monogame extension on Visual Studio, language is C# and the problem is occuring when I try to move the ghosts, creating the autonomous moviment, I can not wrap my head around a solution so, here's what I got:
float dist = Vector2.Distance(position.ToVector2(), targetPosition.ToVector2());
if (dist <= 1)
{
List<Direction> availableDirections = new List<Direction>();
foreach (var dir in Surroundings)
if (game1.Board.board[targetPosition.X / (Game1.outputTileSize) + dir.Value.X, targetPosition.Y / (Game1.outputTileSize) + dir.Value.Y] == ' ')
availableDirections.Add(dir.Key);
if (availableDirections.Count == 0) return;
availableDirections = availableDirections.OrderBy(dir =>
{
float distP1 = Vector2.Distance(targetPosition.ToVector2() + Surroundings[dir].ToVector2() * Game1.outputTileSize, game1.Player.position.ToVector2());
return distP1;
}).ToList();
direction = availableDirections[0];
direction = Surroundings[availableDirections.Count - 1];
targetPosition = targetPosition + availableDirections[direction].Game1.outputTileSize;
}
else
{
//Position is not the same, move the guy
Vector2 vec = targetPosition.ToVector2() - position.ToVector2();
vec.Normalize();
position = (position.ToVector2() + vec).ToPoint();
//Incrementar frame
if ((position.X + position.Y) % 4 == 0)
frame++;
if (frame > 1) frame = -1;
}
I've tried to instantiate a different kind of list still using the dictionary,but the issue is that it's not recognizing the position on the list as an integer and it clashes. Here's the rest of the code that's relevant to understand the way everything connects:
namespace MsPacMan
{
public class Ghost : DrawableGameComponent
{
//enumeradores
enum Orientation { Horizontal, Vertical }
enum Direction { Up, Down, Left, Right }
#region variables
private Texture2D texture;
private SpriteBatch spriteBatch;
private SoundEffect eatghostSound;
private Game1 game1;
private int ghostType;
private Board board;
private Orientation orientation;
public Point position, targetPosition, origin;
int enemyLives = 4;
int patrolSize;
int patrolPosition = 0;
int direction = 1;
int frame = 0;
public static int ghostValue = 200;
Dictionary<Direction, Vector2> ghostColor;
Dictionary<Direction, Point> Surroundings;
Direction gDirection = Direction.Up;
#endregion
#region Constructor
public Ghost(Game1 game, int x, int y, int ghostType) : base(game)
{
orientation = Game1.rnd.Next(2) > 0 ? Orientation.Horizontal : Orientation.Vertical;
texture = game.SpriteSheet;
spriteBatch = game.SpriteBatch;
this.ghostType = ghostType;
position.Y = y;
position.X = x;
targetPosition = position;
game1 = game;
board = game1.Board;
origin = targetPosition = position;
patrolSize = 2 + Game1.rnd.Next(4);
eatghostSound = game1.Content.Load<SoundEffect>("pacman_eatghost");
Surroundings = new Dictionary<Direction, Point>
{
[Direction.Up] = new Point(0, -1),
[Direction.Down] = new Point(0, 1),
[Direction.Left] = new Point(-1, 0),
[Direction.Right] = new Point(0, 1),
};
ghostColor = new Dictionary<Direction, Vector2>
{
[Direction.Right] = new Vector2(0, ghostType),
[Direction.Left] = new Vector2(2, ghostType),
[Direction.Up] = new Vector2(4, ghostType),
[Direction.Down] = new Vector2(6, ghostType),
};
}
#endregion
#region Properties
public Board Board => board;
#endregion
#region Methods
public override void Update(GameTime gameTime)
{
Rectangle pRect = new Rectangle(game1.Player.position, new Point(Game1.outputTileSize));
Rectangle EnemyArea = new Rectangle(((position.ToVector2()) * Game1.outputTileSize).ToPoint(), new Point(Game1.outputTileSize));
ChasePattern(ghostType);
if (EnemyArea.Intersects(pRect))
{
Pellet.GetPelletStatus();
if (Pellet.powerPellet)
{
this.Die();
}
else
{
game1.Player.Die();
}
}
}
//Draws the different types of ghosts
public override void Draw(GameTime gameTime)
{
Rectangle outRect = new Rectangle(position.X * Game1.outputTileSize, position.Y * Game1.outputTileSize, Game1.outputTileSize, Game1.outputTileSize);
Rectangle sourceRec = new Rectangle(((ghostColor[gDirection] + Vector2.UnitX * frame) * 16).ToPoint(), new Point(15));
Rectangle sourcePelletRec = new Rectangle(8 * 16, 0, 16, 15);
spriteBatch.Begin();
Pellet.GetPelletStatus();
if (!Pellet.powerPellet)
{
spriteBatch.Draw(texture, outRect, sourceRec, Color.White);
}
else
{
spriteBatch.Draw(texture, outRect, sourcePelletRec, Color.White);
}
spriteBatch.End();
}
public void Die()
{
eatghostSound.Play();
enemyLives--;
int n = 4 - enemyLives;
AssignGhostValue(n);
game1.Ghosts.Remove(this);
game1.Components.Remove(this);
position = targetPosition = origin;
game1.Ghosts.Add(this);
game1.Components.Add(this);
}
public void AssignGhostValue(int n)
{
ghostValue = ghostValue * n;
game1.Player.Score += ghostValue;
}
public void ChasePattern(int ghostType)
{
int ghosType = ghostType;
int blinky = 0, pinky = 1, inky = 2, clyde = 3;
if (ghosType == blinky)
{
ChaseAggressive();
}
else if (ghosType == pinky)
{
ChaseAmbush();
}
else if (ghosType == inky)
{
ChasePatrol();
}
else if (ghosType == clyde)
{
ChaseRandom();
}
}
public void ChaseAggressive()
{
//Blinky the red ghost is very aggressive in its approach while chasing Pac - Man and will follow Pac-Man once located
float dist = Vector2.Distance(position.ToVector2(), targetPosition.ToVector2());
if (dist <= 1)
{
List<Direction> availableDirections = new List<Direction>();
foreach (var dir in Surroundings)
if (game1.Board.board[targetPosition.X / (Game1.outputTileSize) + dir.Value.X, targetPosition.Y / (Game1.outputTileSize) + dir.Value.Y] == ' ')
availableDirections.Add(dir.Key);
if (availableDirections.Count == 0) return;
availableDirections = availableDirections.OrderBy(dir =>
{
float distP1 = Vector2.Distance(targetPosition.ToVector2() + Surroundings[dir].ToVector2() * Game1.outputTileSize, game1.Player.position.ToVector2());
return distP1;
}).ToList();
direction = availableDirections[0];
direction = Surroundings[availableDirections.Count - 1];
targetPosition = targetPosition + availableDirections[direction]. Game1.outputTileSize;
}
else
{
//Position is not the same, move the guy
Vector2 vec = targetPosition.ToVector2() - position.ToVector2();
vec.Normalize();
position = (position.ToVector2() + vec).ToPoint();
//Incrementar frame
if ((position.X + position.Y) % 4 == 0)
frame++;
if (frame > 1) frame = -1;
}
}
}
}

Related

The npc will move to the first or second point, then stop

The enemy will pick 1 or 2 positions, and then stop moving. If I get close enough, it will change to the chase state and follow me. So I do not know what causes them to freeze.
This holds the state machine, I intend to have more states and interactions, but I wanted to test the basic functionality, and it is broken.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BaseAI : MonoBehaviour
{
private enum State
{
Roaming,
ChaseTarget,
}
private PathfindAI pathMovement;
private Vector3 startingPosition;
public Vector3 roamPosition;
public PlayerScript player;
public Vector3 randomDirection;
[SerializeField] private State state;
public Vector3 playerPos;
private void Awake()
{
// pathMovement = GetComponent<PathfindAI>();
pathMovement = FindObjectOfType<PathfindAI>();
player = FindObjectOfType<PlayerScript>();
state = State.Roaming;
}
private void Start()
{
startingPosition = transform.position;
roamPosition = GetRoamingPos();
}
private void Update()
{
playerPos = player.PlayerPos();
switch (state)
{
default:
case State.Roaming:
pathMovement.MoveTo(roamPosition);
float reachedPos = 10f;
if (Vector3.Distance(transform.position, roamPosition) < reachedPos)
{
//reached destination
roamPosition = GetRoamingPos();
}
FindTarget();
break;
case State.ChaseTarget:
pathMovement.MoveTo(playerPos);
float attackRange = 10f;
if (Vector3.Distance(transform.position, playerPos) < attackRange)
{
//target within striking distance
}
break;
}
}
private Vector3 GetRoamingPos()
{
randomDirection = new Vector3(Random.Range(-1f, 1f), Random.Range(-1f, 1f), transform.position.z).normalized;
return startingPosition + randomDirection * Random.Range(10f, 70f);
}
private void FindTarget()
{
float targetRange = 50f;
if (Vector3.Distance(transform.position, playerPos) < targetRange)
{
state = State.ChaseTarget;
}
}
}
This allows them to move on the path from the pathfinding script. It uses A-star and I used a few tutorials to write it, mostly from CodeMonkey's youtube channel.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PathfindAI : MonoBehaviour
{
[SerializeField] float speed = 5f;
private int currentPathIndex;
private List<Vector3> pathVectorList;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
Debug.Log(currentPathIndex);
}
public Vector3 GetPosition()
{
return transform.position;
}
public void MoveTo(Vector3 targetPosition)
{
SetTargetPos(targetPosition);
HandleMove();
}
private void SetTargetPos(Vector3 targetPosition)
{
currentPathIndex = 0;
pathVectorList = AStar.Instance.FindPathVector3(GetPosition(), targetPosition);
if (pathVectorList != null && pathVectorList.Count > 1)
{
pathVectorList.RemoveAt(0);
}
}
public void HandleMove()
{
if (pathVectorList != null)
{
Vector3 targetPosition = pathVectorList[currentPathIndex];
if(Vector3.Distance(transform.position, targetPosition) > 5f)
{
Vector3 moveDir = (targetPosition - transform.position).normalized;
float distanceBefore = Vector3.Distance(transform.position, targetPosition);
transform.position = transform.position + moveDir * speed * Time.deltaTime;
}
else
{
currentPathIndex++;
if(currentPathIndex >= pathVectorList.Count)
{
StopMoving();
}
}
}
}
private void StopMoving()
{
pathVectorList = null;
}
}
I suspect the error involves the HandleMove function. When I change where and how I call it; I can get it to break completely. It may be me setting the pathVectorList to null; however, it should be set back to a valid value on the next update when GetRoamingPos is called again within the roaming state.
when I go into the inspector and manually move the npc, it will find its way back to the position it chose. And if I move the player close enough it will chase me.
This is my A-Star Implementation
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class AStar
{
private const int MOVE_STRAIGHT_COST = 10;
private const int MOVE_ANGLE_COST = 14;
public static AStar Instance { get; private set; }
private PathingGrid<PathNode> grid;
private List<PathNode> openList;
private List<PathNode> closedList;
public AStar(int width, int height)
{
Instance = this;
grid = new PathingGrid<PathNode>(width, height, 10f, Vector3.zero, (PathingGrid<PathNode> g, int x, int y) => new PathNode(g, x, y));
}
public PathingGrid<PathNode> GetGrid()
{
return grid;
}
public List<PathNode> FindPath(int startX, int startY, int endX, int endY)
{
PathNode startNode = grid.GetGridObject(startX, startY);
PathNode endNode = grid.GetGridObject(endX, endY);
openList = new List<PathNode> { startNode };
closedList = new List<PathNode>();
for (int x = 0; x<grid.GetWidth(); x++)
{
for (int y = 0; y<grid.GetHeight(); y++)
{
PathNode pathNode = grid.GetGridObject(x, y);
pathNode.gCost = int.MaxValue;
pathNode.CalcFCost();
pathNode.cameFromNode = null;
}
}
startNode.gCost = 0;
startNode.hCost = CalculateDistanceCost(startNode, endNode);
startNode.CalcFCost();
while (openList.Count > 0)
{
PathNode currentNode = GetLowestFCost(openList);
if (currentNode == endNode)
{
//reached final node
return CalculatedPath(endNode);
}
openList.Remove(currentNode);
closedList.Add(currentNode);
foreach (PathNode neighbourNode in GetNeighboursList(currentNode))
{
if (closedList.Contains(neighbourNode))
{
continue;
}
if (!neighbourNode.isWalkable)
{
closedList.Add(neighbourNode);
continue;
}
int tentativeGCost = currentNode.gCost + CalculateDistanceCost(currentNode, neighbourNode);
if (tentativeGCost < neighbourNode.gCost)
{
neighbourNode.cameFromNode = currentNode;
neighbourNode.gCost = tentativeGCost;
neighbourNode.hCost = CalculateDistanceCost(neighbourNode, endNode);
neighbourNode.CalcFCost();
if(!openList.Contains(neighbourNode))
{
openList.Add(neighbourNode);
}
}
}
}
//out of nodes on openList
return null;
}
private List<PathNode> GetNeighboursList(PathNode currentNode)
{
List<PathNode> neighbourList = new List<PathNode>();
if (currentNode.x - 1 >= 0)
{
//left
neighbourList.Add(GetNode(currentNode.x - 1, currentNode.y));
//left down
if (currentNode.y - 1 >= 0)
neighbourList.Add(GetNode(currentNode.x - 1, currentNode.y - 1));
//left up
if (currentNode.y + 1 < grid.GetHeight())
neighbourList.Add(GetNode(currentNode.x - 1, currentNode.y + 1));
}
if (currentNode.x + 1 < grid.GetWidth())
{
//right
neighbourList.Add(GetNode(currentNode.x + 1, currentNode.y));
//right down
if (currentNode.y - 1 >= 0)
neighbourList.Add(GetNode(currentNode.x + 1, currentNode.y - 1));
//right up
if (currentNode.y + 1 < grid.GetHeight())
neighbourList.Add(GetNode(currentNode.x + 1, currentNode.y + 1));
}
//down
if (currentNode.y - 1 >= 0)
neighbourList.Add(GetNode(currentNode.x, currentNode.y - 1));
//up
if (currentNode.y + 1 < grid.GetHeight())
neighbourList.Add(GetNode(currentNode.x, currentNode.y + 1));
return neighbourList;
}
public PathNode GetNode(int x, int y)
{
return grid.GetGridObject(x, y);
}
public List<Vector3> FindPathVector3(Vector3 startWorldPosition, Vector3 endWorldPosition)
{
grid.GetXY(startWorldPosition, out int startX, out int startY);
grid.GetXY(endWorldPosition, out int endX, out int endY);
List<PathNode> path = FindPath(startX, startY, endX, endY);
if (path == null)
{
return null;
}
else
{
List<Vector3> vectorPath = new List<Vector3>();
foreach(PathNode pathNode in path)
{
vectorPath.Add(new Vector3(pathNode.x, pathNode.y) * grid.GetCellSize() + Vector3.one * grid.GetCellSize() * .5f);
}
return vectorPath;
}
}
private List<PathNode> CalculatedPath(PathNode endNode)
{
List<PathNode> path = new List<PathNode>();
path.Add(endNode);
PathNode currentNode = endNode;
while (currentNode.cameFromNode != null)
{
path.Add(currentNode.cameFromNode);
currentNode = currentNode.cameFromNode;
}
path.Reverse();
return path;
}
private int CalculateDistanceCost(PathNode a,PathNode b)
{
int xDistance = Mathf.Abs(a.x - b.x);
int yDistance = Mathf.Abs(a.y - b.y);
int remaining = Mathf.Abs(xDistance - yDistance);
return MOVE_ANGLE_COST * Mathf.Min(xDistance, yDistance) + MOVE_STRAIGHT_COST * remaining;
}
private PathNode GetLowestFCost(List<PathNode> pathNodeList)
{
PathNode lowestFCostNode = pathNodeList[0];
for ( int i = 1; i < pathNodeList.Count; i++)
{
if (pathNodeList[i].fCost < lowestFCostNode.fCost)
{
lowestFCostNode = pathNodeList[i];
}
}
return lowestFCostNode;
}
}
One interesting point to note is that whenever my random point is chosen outside of the grid I have made, the error is not thrown where I would expect. Instead they claim that in my calculateDistance Cost"int xDistance = Mathf.Abs(a.x - b.x);" is not Finding an instanced Pathnode. Which makes sense because there wouldn't be one there. However, I would not expect that to be where the first error occurs with an out of bounds endpoint.

Custom A star crashes unity when enabling raycasts for walls in Unity

I decided to make my own A*. When I enable this part of the code Unity crashes.
if (Physics2D.Raycast(transform.position, a - new Vector2(current.x, current.y), 1, mask))
{
print(i);
continue;
}
There are no other objects than walls that would enable the Raycast.
The code probably enters an infinite loop, but I have no idea how because it works fine if i disable raycasts.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading;
using UnityEditor;
using UnityEngine;
public class Star : MonoBehaviour
{
private int x, y;
private int nextX, nextY;
public Vector2 targetNode;
private Vector2 nextNode;
private List<Node> path = null;
LayerMask mask;
Bounds area;
private bool moving;
private bool check;
public float timeStart;
public Vector3 startPos;
public float speed = 1f;
float u;
Rigidbody2D rb;
void Start()
{
rb = GetComponent<Rigidbody2D>();
mask = LayerMask.GetMask("Default");
}
void FixedUpdate()
{
if (!moving)
{
Move();
}
else
MoveTo(speed);
}
private void Move()
{
area = new Bounds(transform.position, new Vector3(100, 100));
int playerX = (int)Mathf.Round(Player.x);
int playerY = (int)Mathf.Round(Player.y);
Vector2 start = new Vector2((int)transform.position.x, (int)transform.position.y);
Vector2 destination = new Vector2(playerX, playerY);
if (getDistance(start, destination) > 1f)
path = findPath(start, destination);
else
path = null;
nextX = 0;
nextY = 0;
if (path != null)
{
if (path.Count > 0)
{
nextNode = new Vector2(path[path.Count - 1].x, path[path.Count - 1].y);
if (x < nextNode.x) nextX++;
if (x > nextNode.x) nextX--;
if (y < nextNode.y) nextY++;
if (y > nextNode.y) nextY--;
}
}
if (nextX != 0 || nextY != 0)
{
Move(nextX, nextY);
}
}
public List<Node> findPath(Vector2 start, Vector2 goal)
{
x = (int)start.x;
y = (int)start.y;
List<Node> openList = new List<Node>();
List<Node> closedList = new List<Node>();
Node current = new Node(x, y, null, 0, getDistance(start, goal));
openList.Add(current);
while (openList.Count > 0)
{
openList.Sort();
current = openList[0];
if (new Vector2(current.x, current.y).Equals(goal))
{
List<Node> path = new List<Node>();
while (current.parent != null)
{
path.Add(current);
current = current.parent;
}
openList.Clear();
closedList.Clear();
return path;
}
openList.Remove(current);
closedList.Add(current);
for (int i = 0; i < 9; i++)
{
if (i == 4/* || i == 0 || i == 2 || i == 6 || i == 8*/) continue;
int x = current.x;
int y = current.y;
int xi = (i % 3) - 1; // -1, 0, 1
int yi = (i / 3) - 1;
Vector2 a = new Vector2(x + xi, y + yi);
if (Physics2D.Raycast(transform.position, a - new Vector2(current.x, current.y), 1, mask))
{
print(i);
continue;
}
double gCost = current.gCost + (getDistance(new Vector2(current.x, current.y), a));
double hCost = getDistance(a, goal);
Node node = new Node((int)a.x, (int)a.y, current, gCost, hCost); // store the node
if (!vecInList(openList, a)) openList.Add(node);
}
}
closedList.Clear();
return null;
}
private double getDistance(Vector2 tile, Vector2 goal)
{
int dx = (int)(tile.x - goal.x);
int dy = (int)(tile.y - goal.y);
return Mathf.Sqrt((dx * dx) + (dy * dy));
}
private bool vecInList(List<Node> list, Vector2 vector)
{
foreach (Node n in list)
{
Vector2 tile2 = new Vector2(n.x, n.y);
if (tile2.Equals(vector)) return true;
}
return false;
}
public void Move(int x, int y)
{
targetNode = transform.position + new Vector3(x, y);
if (area.Contains(new Vector3(Player.x, Player.y)) && (moving == false))
{
moving = true;
check = true;
}
}
public void MoveTo(float speed)
{
if (check)
{
check = false;
moving = true;
timeStart = Time.time;
startPos = transform.position;
}
if (moving)
{
u = (Time.time - timeStart) / (1 / speed);
if (u >= 1)
{
u = 1;
moving = false;
}
//transform.position = (1 - u) * (Vector2)startPos + u * targetNode;
rb.MovePosition((1 - u) * (Vector2)startPos + u * targetNode);
}
}
}
Edit: got this to work thanks to Yuri's comment. Changed to:
if (Physics2D.Raycast(new Vector2(current.x, current.y), a - new Vector2(current.x, current.y), 1, mask))
I was checking from the start position instead of the last position in the nodes.

Collision Detection in C# XNA

Collision detection has been a huge issue for me lately, been breaking my mind over this particular problem.
After I got a reasonable collision detection for my Super Mario World remake in C# (XNA) I have the following problem: I keep getting sort of stuck in blocks when I jump against them...
Example: https://gyazo.com/0f1ac6f4894f41aa4bcbdc73e572e36d
This is my current code than handles the collision: http://pastebin.com/iWsnffWQ
If anyone knows anything that could help my problem, I have been searching high and low for the solution but I to no avail...
EDIT:
This problem has been fixed though a new one arised with object collision on the infamous mario "Mystery Blocks". Whenever I stand on them (not moving) either mario or the world starts to vibrate up and down by about one pixel.
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
namespace PlatFormer
{
public abstract class Entity
{
protected ContentManager _Content;
protected Texture2D _Image;
protected Texture2D _Outline;
protected SpriteSheetAnimation _MoveAnimation;
protected FileManager _FileManager;
protected List<List<string>> _Attributes;
protected List<List<string>> _Contents;
protected Vector2 _Velocity;
protected Vector2 _PrevPosition;
protected Vector2 _Frames;
protected Rectangle _Collbox;
private Rectangle _TileBounds;
protected int _Health;
protected float _MoveSpeed;
protected float _Gravity;
protected float _PreviousBottom;
protected bool _ActivateGravity;
protected bool _TilePositionSync;
protected bool _FacingRight;
protected const float _Friction = 0.9f;
protected const float _Grav = 10f;
protected const float _TerminalVelocity = 10f;
protected Vector2 _Acceleration;
public bool _OnGround;
protected bool _IsJumping;
protected int collisiondeny;
public Vector2 Position;
public SpriteSheetAnimation Animation
{
get { return _MoveAnimation; }
}
public virtual void LoadContent(ContentManager content)
{
_Content = new ContentManager(content.ServiceProvider, "Content");
_Attributes = new List<List<string>>();
_Contents = new List<List<string>>();
}
public virtual void LoadContent(ContentManager content, InputManager input)
{
_Content = new ContentManager(content.ServiceProvider, "Content");
_Attributes = new List<List<string>>();
_Contents = new List<List<string>>();
}
public virtual void UnloadContent()
{
_Content.Unload();
}
public virtual void Update(GameTime gameTime, List<List<WorldTile>> TileMap, List<Enemy> EntList)
{
_PrevPosition = Position;
Position.X = _FacingRight ? Position.X + _MoveSpeed : Position.X - _MoveSpeed;
_Velocity.Y += _Gravity;
if (!_OnGround) { }
else
_Velocity.Y = 0;
UpdatePhysics(gameTime, TileMap, EntList);
_MoveAnimation.Position = Position;
_MoveAnimation.Update(gameTime);
}
public virtual void Update(GameTime gameTime, InputManager input, List<List<WorldTile>> TileMap)
{
}
public virtual void Draw(SpriteBatch spriteBatch)
{
_MoveAnimation.Draw(spriteBatch);
}
protected virtual void UpdatePhysics(GameTime gameTime, List<List<WorldTile>> TileMap, List<Enemy> EntList)
{
_Acceleration *= _Friction;
_Velocity *= _Friction;
_Velocity += _Acceleration;
Position.X = _FacingRight ? Position.X + _Velocity.X : Position.X - _Velocity.X;
Position.Y += _Velocity.Y;
if (Math.Abs(_Acceleration.X) < 0.001f)
{
_MoveAnimation.IsActive = false;
}
UpdateCollBox();
CollisionHandle(TileMap);
EntCollisionHandle(EntList);
if (Position.X == _PrevPosition.X)
_Velocity.X = 0;
if (Position.Y == _PrevPosition.Y)
_Velocity.Y = 0;
}
protected virtual void UpdatePhysics(GameTime gameTime, InputManager input, List<List<WorldTile>> TileMap)
{
float totalSecElapsed = gameTime.ElapsedGameTime.Milliseconds / 1000f;
_Acceleration.X *= _Friction;
_Velocity.X *= _Friction;
_Acceleration.Y = _Grav;
_Velocity.Y += _Acceleration.Y * totalSecElapsed;
_Velocity.X += _Acceleration.X;
if (_Velocity.Y >= _TerminalVelocity)
{
_Velocity.Y = _TerminalVelocity;
}
Position += _Velocity;
if (Math.Abs(_Acceleration.X) < 0.001f)
{
_MoveAnimation.IsActive = false;
}
UpdateCollBox();
CollisionHandle(TileMap); //replace with horizontal collision first then vertical collision
//TestCollisionHandle(TileMap);
if (Position.X == _PrevPosition.X)
_Velocity.X = 0;
if (Position.Y == _PrevPosition.Y)
_Velocity.Y = 0;
}
public void ObjectCollision(List<LevelObject> obj)
{
//OnThisNiceMysteryBox = false;
for (int i = 0; i < obj.Count; i++)
{
if (_Collbox.Intersects(obj[i].Bounds))
{
if (obj[i].Collision != TileCollision.Empty)
{
Vector2 depth = IntersectDepth(_Collbox, obj[i].Bounds);
if (depth != Vector2.Zero)
{
float absDepthX = Math.Abs(depth.X);
float absDepthY = Math.Abs(depth.Y);
if (absDepthY < absDepthX)
{
if (_Collbox.Top <= obj[i].Bounds.Bottom && _Collbox.Top >= obj[i].Bounds.Top)
{
Vector2 tempPos = obj[i].Position;
if (obj[i] is MysteryBox)
{
obj.Remove(obj[i]);
obj.Insert(i, new MysteryBox(tempPos));
}
}
if (_PreviousBottom <= obj[i].Bounds.Top)
{
_OnGround = true;
}
if (obj[i].Collision == TileCollision.Solid || _OnGround)
{
Position = new Vector2((float)Math.Round(Position.X), (float)Math.Round(Position.Y + depth.Y));
_Velocity.Y = 0;
UpdateCollBox();
}
}
else if (obj[i].Collision == TileCollision.Solid)
{
Position = new Vector2((float)Math.Round(Position.X + depth.X), (float)Math.Round(Position.Y));
UpdateCollBox();
}
}
}
}
_PreviousBottom = _Collbox.Bottom;
}
}
protected void EntCollisionHandle(List<Enemy> EntList)
{
for (int i = 0; i < EntList.Count; i++)
{
if (!(EntList[i] == this))
{
Vector2 intersection = IntersectDepth(this._Collbox, EntList[i]._Collbox);
if (intersection != Vector2.Zero)
{
if (collisiondeny == 0)
{
_FacingRight = !_FacingRight;
Position.X = _FacingRight ? Position.X - intersection.X : Position.X + intersection.X;
collisiondeny = 1;
}
else
{
collisiondeny--;
}
//if intersection has occured call both collision handles in colliding classes
}
}
}
}
protected void CollisionHandle(List<List<WorldTile>> TileMap)
{
int leftTile = (int)Math.Floor((float)_Collbox.Left / WorldTile.Width);
int rightTile = (int)Math.Ceiling(((float)_Collbox.Right / WorldTile.Width)) - 1;
int topTile = (int)Math.Floor((float)_Collbox.Top / WorldTile.Height);
int bottomTile = (int)Math.Ceiling(((float)_Collbox.Bottom / WorldTile.Height)) - 1;
_OnGround = false;
for (int y = topTile; y <= bottomTile; y++)
{
for (int x = leftTile; x <= rightTile; x++)
{
TileCollision collision = TileCollision.Empty;
if (y >= 0)
{
if (x >= 0)
{
if (y < TileMap.Count && x < TileMap[y].Count)
collision = TileMap[y][x].Collision;
}
else
{
collision = TileCollision.Solid;
}
}
if (collision != TileCollision.Empty)
{
_TileBounds = new Rectangle(x * WorldTile.Width, y * WorldTile.Height, WorldTile.Width, WorldTile.Height);
Vector2 depth = IntersectDepth(_Collbox, _TileBounds);
if (depth != Vector2.Zero)
{
float absDepthX = Math.Abs(depth.X);
float absDepthY = Math.Abs(depth.Y);
if (absDepthY <= absDepthX || collision == TileCollision.OneWay)
{
if (_PreviousBottom <= _TileBounds.Top)
_OnGround = true;
if ((collision == TileCollision.Solid) || _OnGround)
{
Position = new Vector2((int)Math.Round(Position.X), (int)Math.Round(Position.Y + depth.Y));
UpdateCollBox();
}
}
else if (collision == TileCollision.Solid)
{
Position = new Vector2((int)Math.Round(Position.X + depth.X), (int)Math.Round(Position.Y));
_FacingRight = !_FacingRight;
//_Velocity.Y = 0;
UpdateCollBox();
}
}
}
}
}
_PreviousBottom = _Collbox.Bottom;
}
protected void TestCollisionHandle(List<List<WorldTile>> TileMap)
{
int leftTile = (int)Math.Floor((float)_Collbox.Left / WorldTile.Width);
int rightTile = (int)Math.Ceiling(((float)_Collbox.Right / WorldTile.Width)) - 1;
int topTile = (int)Math.Floor((float)_Collbox.Top / WorldTile.Height);
int bottomTile = (int)Math.Ceiling(((float)_Collbox.Bottom / WorldTile.Height)) - 1;
_OnGround = false;
for (int y = topTile; y <= bottomTile; y++)
{
for (int x = leftTile; x <= rightTile; x++)
{
TileCollision collision = TileCollision.Empty;
if (y >= 0)
{
if (x >= 0)
{
if (y < TileMap.Count && x < TileMap[y].Count)
collision = TileMap[y][x].Collision;
}
}
if(collision != TileCollision.Empty)
{
//if collision can occor, get tilecollisionbox for horizontal
_TileBounds = new Rectangle(x * WorldTile.Width, y * WorldTile.Height, WorldTile.Width, WorldTile.Height);
//get the horizontal collision depth, will return zero if none is found
GetHorizontalIntersectionDepth(_Collbox, _TileBounds);
}
}
}
_PreviousBottom = _Collbox.Bottom;
}
private void UpdateCollBox()
{
_Collbox = new Rectangle((int)Math.Round(Position.X), (int)Math.Round(Position.Y), Animation.FrameWidth, Animation.FrameHeight);
}
private Vector2 IntersectDepth(Rectangle rectangleA, Rectangle rectangleB)
{
float halfWidthA = rectangleA.Width / 2.0f;
float halfHeightA = rectangleA.Height / 2.0f;
float halfWidthB = rectangleB.Width / 2.0f;
float halfHeightB = rectangleB.Height / 2.0f;
Vector2 centerA = new Vector2(rectangleA.Left + halfWidthA, rectangleA.Top + halfHeightA);
Vector2 centerB = new Vector2(rectangleB.Left + halfWidthB, rectangleB.Top + halfHeightB);
float distanceX = centerA.X - centerB.X;
float distanceY = centerA.Y - centerB.Y;
float minDistanceX = halfWidthA + halfWidthB;
float minDistanceY = halfHeightA + halfHeightB;
// If no intersection is happening, return Vector2.Zero
if (Math.Abs(distanceX) >= minDistanceX || Math.Abs(distanceY) >= minDistanceY)
return Vector2.Zero;
// Calculate instersection depth
float depthX = distanceX > 0 ? minDistanceX - distanceX : -minDistanceX - distanceX;
float depthY = distanceY > 0 ? minDistanceY - distanceY : -minDistanceY - distanceY;
return new Vector2(depthX, depthY);
}
private float GetHorizontalIntersectionDepth(Rectangle rectA, Rectangle rectB)
{
// Calculate half sizes.
float halfWidthA = rectA.Width / 2.0f;
float halfWidthB = rectB.Width / 2.0f;
// Calculate centers.
float centerA = rectA.Left + halfWidthA;
float centerB = rectB.Left + halfWidthB;
// Calculate current and minimum-non-intersecting distances between centers.
float distanceX = centerA - centerB;
float minDistanceX = halfWidthA + halfWidthB;
// If we are not intersecting at all, return (0, 0).
if (Math.Abs(distanceX) >= minDistanceX)
return 0f;
// Calculate and return intersection depths.
return distanceX > 0 ? minDistanceX - distanceX : -minDistanceX - distanceX;
}
private float GetVerticalIntersectionDepth(Rectangle rectA, Rectangle rectB)
{
// Calculate half sizes.
float halfHeightA = rectA.Height / 2.0f;
float halfHeightB = rectB.Height / 2.0f;
// Calculate centers.
float centerA = rectA.Top + halfHeightA;
float centerB = rectB.Top + halfHeightB;
// Calculate current and minimum-non-intersecting distances between centers.
float distanceY = centerA - centerB;
float minDistanceY = halfHeightA + halfHeightB;
// If we are not intersecting at all, return (0, 0).
if (Math.Abs(distanceY) >= minDistanceY)
return 0f;
// Calculate and return intersection depths.
return distanceY > 0 ? minDistanceY - distanceY : -minDistanceY - distanceY;
}
public enum Direction
{
Horizontal,
Vertical
}
private bool TileIntersectsPlayer(Rectangle player, Rectangle block, Direction direction, out Vector2 depth)
{
depth = direction == Direction.Vertical ? new Vector2(0, GetVerticalIntersectionDepth(player, block)) : new Vector2(GetHorizontalIntersectionDepth(player, block), 0);
return depth.Y != 0 || depth.X != 0;
}
}
}
Consider using or just compare your code to the libraries that exist already: see GeoLib which is very simple to use and/or clipper lib. 'Do not reinvent...'

C# XNA - Sprite moves out of window/screen

When I press left or up arrow keys the sprite gets out of the window/screen. My code:
Texture2D m_PlayerShipTex;
Rectangle m_PlayerShipHitBox;
Vector2 m_PlayerShipPos = new Vector2(400, 486);
Vector2 m_PlayerShipOrigin;
int m_PlayerShipCurrentFrame = 1;
int m_PlayerShipFrameWidth = 62;
int m_PlayerShipFrameHeight = 64;
float m_Timer = 0f;
float m_Interval = 100;
public void LoadContent(ContentManager Content)
{
m_PlayerShipTex = Content.Load<Texture2D>(".\\gameGraphics\\gameSprites\\playerShip\\playerShipSpriteSheet");
}
public void Update(GameTime gameTime)
{
m_PlayerShipHitBox = new Rectangle(m_PlayerShipCurrentFrame * m_PlayerShipFrameWidth, 0, m_PlayerShipFrameWidth, m_PlayerShipFrameHeight);
m_PlayerShipOrigin = new Vector2(m_PlayerShipHitBox.X / 2, m_PlayerShipHitBox.Y / 2);
MouseState m_MouseState = Mouse.GetState();
KeyboardState m_KeyboardState = Keyboard.GetState();
m_Timer += (float)gameTime.ElapsedGameTime.Milliseconds;
if (m_Timer > m_Interval)
{
m_PlayerShipCurrentFrame++;
m_Timer = 0f;
}
if (m_PlayerShipCurrentFrame == 2)
{
m_PlayerShipCurrentFrame = 0;
}
m_PlayerShipHitBox = new Rectangle(m_PlayerShipCurrentFrame * m_PlayerShipFrameWidth, 0, m_PlayerShipFrameWidth, m_PlayerShipFrameHeight);
m_PlayerShipOrigin = new Vector2(m_PlayerShipHitBox.Width / 2, m_PlayerShipHitBox.Height / 2);
if (m_KeyboardState.IsKeyDown(Keys.Right))
{
m_PlayerShipPos.X += 3;
}
if (m_KeyboardState.IsKeyDown(Keys.Left))
{
m_PlayerShipPos.X -= 3;
}
if (m_KeyboardState.IsKeyDown(Keys.Down))
{
m_PlayerShipPos.Y += 3;
}
if (m_KeyboardState.IsKeyDown(Keys.Up))
{
m_PlayerShipPos.Y -= 3;
}
if (m_PlayerShipPos.X <= 0)
{
m_PlayerShipPos.X = 0;
}
if (m_PlayerShipPos.X + m_PlayerShipTex.Width >= 1141)
{
m_PlayerShipPos.X = 1141 - m_PlayerShipTex.Width;
}
if (m_PlayerShipPos.Y <= 0)
{
m_PlayerShipPos.Y = 0;
}
if (m_PlayerShipPos.Y + m_PlayerShipTex.Height >= 620)
{
m_PlayerShipPos.Y = 620 - m_PlayerShipTex.Height;
}
}
public void Draw(SpriteBatch spriteBatch)
{
spriteBatch.Draw(m_PlayerShipTex, m_PlayerShipPos, m_PlayerShipHitBox, Color.White, 0f, m_PlayerShipOrigin, 1.0f, SpriteEffects.None, 0);
}
I don't know what could be wrong, my window is 800x600 but if I set m_PlayerShipTex.Width >= 800 I can get only to half of the screen, that's why I'm using 1141. Same goes for window height... What am I doing wrong and why the ship's out of the "reacheable" area?
To fix the original problem, use this draw function:
public void Draw(SpriteBatch spriteBatch)
{
spriteBatch.Draw(m_PlayerShipTex, m_PlayerShipPos, m_PlayerShipHitBox, Color.White, 0f, Vector2.Zero, 1.0f, SpriteEffects.None, 0);
}
This will use (0,0) as the origin for drawing; which means that your "edge" calculations will work as originally expected. If you want the centered origin, then you need to account for that adjustment when calculating the edges.
The only reason to change the origin is to make rotation easier; in general, you can just use Vector2.Zero.

Implementing water effects (splashes) into XNA 4.0 game

Edit: Link to Question on GameDev SE: https://gamedev.stackexchange.com/questions/51656/implementing-water-effects-splashes-into-xna-4-0-game
I am creating a 2D XNA game and came across a tutorial on adding water effects (splashes) to an XNA game but after implementing it into my game I can't get it to scale down. Currently it takes up the entire screen.
The Water class looks like this
class Water
{
struct WaterColumn
{
public float TargetHeight;
public float Height;
public float Speed;
public void Update(float dampening, float tension)
{
float x = TargetHeight - Height;
Speed += tension * x - Speed * dampening;
Height += Speed;
}
}
PrimitiveBatch pb;
WaterColumn[] columns = new WaterColumn[201];
static Random rand = new Random();
public float Tension = 0.025f;
public float Dampening = 0.025f;
public float Spread = 0.25f;
RenderTarget2D metaballTarget, particlesTarget;
SpriteBatch spriteBatch;
AlphaTestEffect alphaTest;
Texture2D particleTexture;
private float Scale { get { return spriteBatch.GraphicsDevice.Viewport.Width / (columns.Length - 1f); } }
List<Particle> particles = new List<Particle>();
class Particle
{
public Vector2 Position;
public Vector2 Velocity;
public float Orientation;
public Particle(Vector2 position, Vector2 velocity, float orientation)
{
Position = position;
Velocity = velocity;
Orientation = orientation;
}
}
public Water(GraphicsDevice device, Texture2D particleTexture)
{
pb = new PrimitiveBatch(device);
this.particleTexture = particleTexture;
spriteBatch = new SpriteBatch(device);
metaballTarget = new RenderTarget2D(device, device.Viewport.Width, device.Viewport.Height);
particlesTarget = new RenderTarget2D(device, device.Viewport.Width, device.Viewport.Height);
alphaTest = new AlphaTestEffect(device);
alphaTest.ReferenceAlpha = 175;
var view = device.Viewport;
alphaTest.Projection = Matrix.CreateTranslation(-0.5f, -0.5f, 0) *
Matrix.CreateOrthographicOffCenter(0, view.Width, view.Height, 0, 0, 1);
for (int i = 0; i < columns.Length; i++)
{
columns[i] = new WaterColumn()
{
Height = 240,
TargetHeight = 240,
Speed = 0
};
}
}
// Returns the height of the water at a given x coordinate.
public float GetHeight(float x)
{
if (x < 0 || x > 800)
return 240;
return columns[(int)(x / Scale)].Height;
}
void UpdateParticle(Particle particle)
{
const float Gravity = 0.3f;
particle.Velocity.Y += Gravity;
particle.Position += particle.Velocity;
particle.Orientation = GetAngle(particle.Velocity);
}
public void Splash(float xPosition, float speed)
{
int index = (int)MathHelper.Clamp(xPosition / Scale, 0, columns.Length - 1);
for (int i = Math.Max(0, index - 0); i < Math.Min(columns.Length - 1, index + 1); i++)
columns[index].Speed = speed;
CreateSplashParticles(xPosition, speed);
}
private void CreateSplashParticles(float xPosition, float speed)
{
float y = GetHeight(xPosition);
if (speed > 120)
{
for (int i = 0; i < speed / 8; i++)
{
Vector2 pos = new Vector2(xPosition, y) + GetRandomVector2(40);
Vector2 vel = FromPolar(MathHelper.ToRadians(GetRandomFloat(-150, -30)), GetRandomFloat(0, 0.5f * (float)Math.Sqrt(speed)));
CreateParticle(pos, vel);
}
}
}
private void CreateParticle(Vector2 pos, Vector2 velocity)
{
particles.Add(new Particle(pos, velocity, 0));
}
private Vector2 FromPolar(float angle, float magnitude)
{
return magnitude * new Vector2((float)Math.Cos(angle), (float)Math.Sin(angle));
}
private float GetRandomFloat(float min, float max)
{
return (float)rand.NextDouble() * (max - min) + min;
}
private Vector2 GetRandomVector2(float maxLength)
{
return FromPolar(GetRandomFloat(-MathHelper.Pi, MathHelper.Pi), GetRandomFloat(0, maxLength));
}
private float GetAngle(Vector2 vector)
{
return (float)Math.Atan2(vector.Y, vector.X);
}
public void Update()
{
for (int i = 0; i < columns.Length; i++)
columns[i].Update(Dampening, Tension);
float[] lDeltas = new float[columns.Length];
float[] rDeltas = new float[columns.Length];
// do some passes where columns pull on their neighbours
for (int j = 0; j < 8; j++)
{
for (int i = 0; i < columns.Length; i++)
{
if (i > 0)
{
lDeltas[i] = Spread * (columns[i].Height - columns[i - 1].Height);
columns[i - 1].Speed += lDeltas[i];
}
if (i < columns.Length - 1)
{
rDeltas[i] = Spread * (columns[i].Height - columns[i + 1].Height);
columns[i + 1].Speed += rDeltas[i];
}
}
for (int i = 0; i < columns.Length; i++)
{
if (i > 0)
columns[i - 1].Height += lDeltas[i];
if (i < columns.Length - 1)
columns[i + 1].Height += rDeltas[i];
}
}
foreach (var particle in particles)
UpdateParticle(particle);
particles = particles.Where(x => x.Position.X >= 0 && x.Position.X <= 800 && x.Position.Y - 5 <= GetHeight(x.Position.X)).ToList();
}
public void DrawToRenderTargets()
{
GraphicsDevice device = spriteBatch.GraphicsDevice;
device.SetRenderTarget(metaballTarget);
device.Clear(Color.Transparent);
// draw particles to the metaball render target
spriteBatch.Begin(0, BlendState.Additive);
foreach (var particle in particles)
{
Vector2 origin = new Vector2(particleTexture.Width, particleTexture.Height) / 2f;
spriteBatch.Draw(particleTexture, particle.Position, null, Color.White, particle.Orientation, origin, 2f, 0, 0);
}
spriteBatch.End();
// draw a gradient above the water so the metaballs will fuse with the water's surface.
pb.Begin(PrimitiveType.TriangleList);
const float thickness = 20;
float scale = Scale;
for (int i = 1; i < columns.Length; i++)
{
Vector2 p1 = new Vector2((i - 1) * scale, columns[i - 1].Height);
Vector2 p2 = new Vector2(i * scale, columns[i].Height);
Vector2 p3 = new Vector2(p1.X, p1.Y - thickness);
Vector2 p4 = new Vector2(p2.X, p2.Y - thickness);
pb.AddVertex(p2, Color.White);
pb.AddVertex(p1, Color.White);
pb.AddVertex(p3, Color.Transparent);
pb.AddVertex(p3, Color.Transparent);
pb.AddVertex(p4, Color.Transparent);
pb.AddVertex(p2, Color.White);
}
pb.End();
// save the results in another render target (in particlesTarget)
device.SetRenderTarget(particlesTarget);
device.Clear(Color.Transparent);
spriteBatch.Begin(0, null, null, null, null, alphaTest);
spriteBatch.Draw(metaballTarget, Vector2.Zero, Color.White);
spriteBatch.End();
// switch back to drawing to the backbuffer.
device.SetRenderTarget(null);
}
public void Draw()
{
Color lightBlue = new Color(0.2f, 0.5f, 1f);
// draw the particles 3 times to create a bevelling effect
spriteBatch.Begin();
spriteBatch.Draw(particlesTarget, -Vector2.One, new Color(0.8f, 0.8f, 1f));
spriteBatch.Draw(particlesTarget, Vector2.One, new Color(0f, 0f, 0.2f));
spriteBatch.Draw(particlesTarget, Vector2.Zero, lightBlue);
spriteBatch.End();
// draw the waves
pb.Begin(PrimitiveType.TriangleList);
Color midnightBlue = new Color(0, 15, 40) * 0.9f;
lightBlue *= 0.8f;
float bottom = spriteBatch.GraphicsDevice.Viewport.Height;
float scale = Scale;
for (int i = 1; i < columns.Length; i++)
{
Vector2 p1 = new Vector2((i - 1) * scale, columns[i - 1].Height);
Vector2 p2 = new Vector2(i * scale, columns[i].Height);
Vector2 p3 = new Vector2(p2.X, bottom);
Vector2 p4 = new Vector2(p1.X, bottom);
pb.AddVertex(p1, lightBlue);
pb.AddVertex(p2, lightBlue);
pb.AddVertex(p3, midnightBlue);
pb.AddVertex(p1, lightBlue);
pb.AddVertex(p3, midnightBlue);
pb.AddVertex(p4, midnightBlue);
}
pb.End();
}
}
Then in the Game1.cs I have the following
LoadContent method
protected override void LoadContent()
{
// Create a new SpriteBatch, which can be used to draw textures.
spriteBatch = new SpriteBatch(GraphicsDevice);
font = Content.Load<SpriteFont>("Font");
particleImage = Content.Load<Texture2D>("metaparticle");
backgroundImage = Content.Load<Texture2D>("sky");
rockImage = Content.Load<Texture2D>("rock");
water = new Water(GraphicsDevice, particleImage);
.
.
.
}
In my update method I have the following (along with other code for the game, i am just showing water part)
protected override void Update(GameTime gameTime)
{
lastKeyState = keyState;
keyState = Keyboard.GetState();
lastMouseState = mouseState;
mouseState = Mouse.GetState();
water.Update();
Vector2 mousePos = new Vector2(mouseState.X, mouseState.Y);
// if the user clicked down, create a rock.
if (lastMouseState.LeftButton == ButtonState.Released && mouseState.LeftButton == ButtonState.Pressed)
{
rock = new Rock
{
Position = mousePos,
Velocity = (mousePos - new Vector2(lastMouseState.X, lastMouseState.Y)) / 5f
};
}
// update the rock if it exists
if (rock != null)
{
if (rock.Position.Y < 240 && rock.Position.Y + rock.Velocity.Y >= 240)
water.Splash(rock.Position.X, rock.Velocity.Y * rock.Velocity.Y * 5);
rock.Update(water);
if (rock.Position.Y > GraphicsDevice.Viewport.Height + rockImage.Height)
rock = null;
}
Then in the Draw method I have the following (when the active enum is InGame)
case ActiveScreen.InGame:
water.DrawToRenderTargets();
level.Draw(gameTime, spriteBatch);
DrawHud();
spriteBatch.Begin();
spriteBatch.Draw(backgroundImage, Vector2.Zero, Color.White);
if (rock != null)
rock.Draw(spriteBatch, rockImage);
spriteBatch.End();
water.Draw();
break;
My problem is this obviously takes up the entire screen. I realise why it takes up the entire screen but I can't figure out how to scale it down and set it on a fixed location in the game. If anyone could read through this and direct me towards how I would go about scaling this down successfully, I'd greatly appreciate it.
Notice that
private float Scale { get { return spriteBatch.GraphicsDevice.Viewport.Width / (columns.Length - 1f); } }
creates a Scale corresponding to the entire screen. And in both your Draw() and DrawToRenderTargets() methods
Vector2 p1 = new Vector2((i - 1) * scale, columns[i - 1].Height);
Vector2 p2 = new Vector2(i * scale, columns[i].Height);
which means that the top of the vectors (water columns) will start from the beginning of the screen. That's where you need to make change of.

Categories

Resources