Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 2 years ago.
Improve this question
I was trying to translate something from C++ to C#, now the translation is completely done, however I'm getting an error when compiling that says index of array is out of bounds so I want to know if I declared the array properly.
[Entire Code]
using System;
using SFML.Graphics;
using SFML.Window;
using SFML.Audio;
using SFML.System;
namespace Pruebas_Algoritmia
{
class Program
{
const int num = 8;
static int[,] points = new int[num, 2] {{300, 610},
{ 1270, 430},
{1380,2380},
{1900,2460},
{1970,1700},
{2550,1680},
{2560,3150},
{500, 3300}};
public struct Car
{
public float x;
public float y;
public float speed;
public float angle;
public int n;
public Car(float speed,float angle, int n)
: this()
{
speed = 2;
angle = 0;
n = 0;
}
public void move()
{
x += MathF.Sin(angle) * speed;
y -= MathF.Cos(angle) * speed;
}
public void findTarget()
{
float tx = points[n, 0];
float ty = points[n, 1];
float beta = angle - MathF.Atan2(tx - x, -ty + y);
if (Math.Sin(beta) < 0)
{
angle += 0.005f * speed;
}
else
{
angle -= 0.005f * speed;
}
if ((x - tx) * (x - tx) + (y - ty) * (y - ty) < 25 * 25)
{
n = (n + 1) % num;
}
}
};
static void OnClose(object sender, EventArgs e)
{
RenderWindow window = (RenderWindow)sender;
window.Close();
}
static void Main(string[] args)
{
RenderWindow app = new RenderWindow(new VideoMode(640, 480), "Car Racing Game", Styles.Default);
app.SetFramerateLimit(60);
app.SetVerticalSyncEnabled(true);
app.DispatchEvents();
app.Clear();
Texture t1 = new Texture("c://images/background.png");
Texture t2 = new Texture("c://images/car.png");
t1.Smooth = true;
t2.Smooth = true;
Sprite sBackground = new Sprite(t1);
Sprite sCar = new Sprite(t2);
sBackground.Scale = new Vector2f(2, 2);
sCar.Origin = new Vector2f(22, 22);
float R = 22f;
const int N = 5;
Car[] car = new Car[N];
for (int i = 0; 0 < N; i++)
{
car[i].x = 300 + i * 50;
car[i].y = 1700 + i * 80;
car[i].speed = 7 + i;
}
float speed = 0f;
float angle = 0f;
float maxSpeed = 12.0f;
float acc = 0.2f;
float dec = 0.03f;
float turnSpeed = 0.08f;
float offsetX = 0;
float offsetY = 0;
while (app.IsOpen)
{
Event e;
app.Closed += new EventHandler(OnClose);
app.Display();
}
bool up = false;
bool down = false;
bool right = false;
bool left = false;
if (Keyboard.IsKeyPressed(Keyboard.Key.Up))
{
up = true;
}
if (Keyboard.IsKeyPressed(Keyboard.Key.Right))
{
right = true;
}
if (Keyboard.IsKeyPressed(Keyboard.Key.Down))
{
down = true;
}
if (Keyboard.IsKeyPressed(Keyboard.Key.Left))
{
left = true;
}
//movement
if (up && speed < maxSpeed)
{
if (speed < 0)
{
speed += dec;
}
else
{
speed -= acc;
}
}
if (down && speed >- maxSpeed)
{
if (speed > 0)
{
speed -= dec;
}
else
{
speed -= acc;
}
}
if (!up && !down)
{
if (speed - dec > 0)
{
speed -= dec;
}
else if(speed + dec < 0)
{
speed += dec;
}
else
{
speed = 0;
}
}
if (right && speed != 0)
{
angle += turnSpeed * speed / maxSpeed;
}
if (left && speed != 0)
{
angle -= turnSpeed * speed / maxSpeed;
}
car[0].speed = speed;
car[0].angle = angle;
for (int i = 0; i < N; ++i)
{
car[i].move();
}
for (int i = 0; i < N; ++i)
{
car[i].findTarget();
}
for (int i = 0; i < N; ++i)
{
for(int j = 0; i < N; ++j)
{
float dx = 0;
float dy = 0;
while (dx * dx + dy * dy < 4 * R * R)
{
car[i].x += dx / 10.0f;
car[i].x += dy / 10.0f;
car[j].x += dx / 10.0f;
car[j].x += dy / 10.0f;
dx = car[i].x - car[j].x;
dy = car[i].y - car[j].y;
}
}
}
app.Clear(Color.White);
if (car[0].x > 320) offsetX = car[0].x - 320;
if (car[0].y > 240) offsetY = car[0].y - 240;
//sBackground
sBackground.Position = new Vector2f(-offsetX, -offsetY);
app.Draw(sBackground);
Color[] colors = new Color[] { Color.Red, Color.Green, Color.Magenta, Color.Blue, Color.White};
for (int i = 0; i < N; ++i)
{
sCar.Position = new Vector2f(car[i].x - offsetX, car[i].y - offsetY);
sCar.Rotation = car[i].angle * 180 / 3.141593f;
sCar.Color = colors[i];
app.Draw(sCar);
}
app.Display();
}
}
}
I'm getting the error around line 88 where I have this.
const int N = 5;
Car[] car = new Car[N];
for (int i = 0; 0 < N; i++)
{
car[i].x = 300 + i * 50;
car[i].y = 1700 + i * 80;
car[i].speed = 7 + i;
}
Originally this looked like this in C++
const int N=5;
Car car[N];
for(int i=0;i<N;i++)
{
car[i].x=300+i*50;
car[i].y=1700+i*80;
car[i].speed=7+i;
}
The error I get literally says the index is out of bounds, also I'm getting an exception after this for loop saying that there's unreachable code for every line below the loop
You made a typo in your C# code. You wrote 0 < N instead of i < N.
Related
I work on Unity3D and I have a Vector3 array, this array is the vertex of a polygon.
Now I try to Generate a random point inside the polygon and I don't know how many vertex I have.
e.g:
polygonBorders = new Vector3[3];
polygonBorders[0] = new Vector3(35.3f, 1.3f, -20.1f);
polygonBorders[1] = new Vector3(35.3f, 1.3f, -3.42f);
polygonBorders[2] = new Vector3(52.11f, 1.3f, -3.42f);
this is my polygon and I want a method like that:
Vector3 GeneratePointInsidePolygon(Vector3[] polyogn, Vector3 point)
I try to find a solution all over the Internet and there is no solution or libraey
I find a nice way to do that with the next snippet:
private Vector3 GeneratePointInsidePolygon(List<Vector3> polygon)
{
Vector3 MinVec = MinPointOnThePolygon(polygon);
Vector3 MaxVec = MaxPointOnThePolygon(polygon);
Vector3 GenVector;
float x = ((Random.value) * (MaxVec.x- MinVec.x)) + MinVec.x;
float z = ((Random.value) * (MaxVec.z - MinVec.z)) + MinVec.z;
GenVector = new Vector3(x, groundHight, z);
while(!InConfinedSpace.IsPointInPolygon(polygon,GenVector))
{
x = ((Random.value) * (MaxVec.x - MinVec.x)) + MinVec.x;
z = ((Random.value) * (MaxVec.z - MinVec.z)) + MinVec.z;
GenVector.x = x;
GenVector.z = z;
}
return GenVector;
}
private Vector3 MinPointOnThePolygon(List<Vector3> polygon)
{
float minX = polygon[0].x;
float minZ = polygon[0].z;
for (int i = 1; i<polygon.Count;i++)
{
if(minX > polygon[i].x)
{
minX = polygon[i].x;
}
if (minZ > polygon[i].z)
{
minZ = polygon[i].z;
}
}
return new Vector3(minX, groundHight, minZ);
}
private Vector3 MaxPointOnThePolygon(List<Vector3> polygon)
{
float maxX = polygon[0].x;
float maxZ = polygon[0].z;
for (int i = 1; i < polygon.Count; i++)
{
if (maxX < polygon[i].x)
{
maxX = polygon[i].x;
}
if (maxZ < polygon[i].z)
{
maxZ = polygon[i].z;
}
}
return new Vector3(maxX, groundHight, maxZ);
}
private bool IsPointInPolygon(List<Vector3> polygon, Vector3 point)
{
bool isInside = false;
for (int i = 0, j = polygon.Count - 1; i < polygon.Count; j = i++)
{
if (((polygon[i].x > point.x) != (polygon[j].x > point.x)) &&
(point.z < (polygon[j].z - polygon[i].z) * (point.x - polygon[i].x) / (polygon[j].x - polygon[i].x) + polygon[i].z))
{
isInside = !isInside;
}
}
return isInside;
}
The snippet finds the minimum and maximum polygon vertex and then generates a random number inside and checks if the point is inside the polygon every time, if it's not it generates another point.
I have this script and I need to assign a different value to vertices every frame but I can't convert Vector3 to Vector3[], I tried In many ways but I am not able to solve this
public Vector3 calculatePointOnPlanet(Vector3 directions)
{
float firstLayerValue = 0;
float elevation = 0;
directions = directions;
if (noiseFilters.Length > 0)
{
firstLayerValue = noiseFilters[0].Evaluate(directions);
if (settings.noiseLayers[0].enabled)
{
elevation = firstLayerValue;
}
}
for (int i = 0; i < noiseFilters.Length; i++)
{
if (settings.noiseLayers[i].enabled)
{
float mask = (settings.noiseLayers[i].useFirstLayerAsMask) ? firstLayerValue : 1;
elevation += noiseFilters[i].Evaluate(directions) * mask;
}
}
return directions * settings.radius * (1 + elevation);
}
public void a(Vector3[] vertices, Vector3[] directions)
{
for (int i = 0; i < noiseFilters.Length; i++)
{
vertices[i] = calculatePointOnPlanet(directions);
}
}
You probably forgot the index
// |
// V
vertices[i] = calculatePointOnPlanet(directions[i]);
Note btw that
directions = directions
does absolutely nothing
I need help with trajectory prediction on mobile.
I'm able to do that on PC using the mouse, but I'm not able to do that with touch functions on mobile.
I've the dot that I copy on the start, and while I'm dragging the ball I want to calculate my trajectory.
After touch will end I will destroy these dots.
As I said I'm able to do it using Input.GetMouseButton/Up/Down but I'm not able to do that using touch function.
Here is my code:
private void Update()
{
//if (Input.touchCount > 0)
//{
Touch touch = Input.GetTouch(0);
if (touch.phase == TouchPhase.Began)
{
startPosition = Input.GetTouch(0).position;
for (int i = 0; i < number; i++)
{
trajectoryDots[i] = Instantiate(trajectoryDot, gameObject.transform);
}
}
if (Input.touchCount > 0)
{
for (int i = 0; i < number; i++)
{
trajectoryDots[i].transform.position = calculatePosition(i * 0.1f);
}
}
if (touch.phase == TouchPhase.Ended)
{
for (int i = 0; i < number; i++)
{
Destroy(trajectoryDots[i]);
}
endPoisiton = Input.GetTouch(0).position;
force = startPosition - endPoisiton;
ballRigid.gravityScale = 1;
ballRigid.velocity = new Vector2(force.x * power, force.y * power);
}
//}
}
private Vector2 calculatePosition(float elapsedTime)
{
return new Vector2(endPoisiton.x, endPoisiton.y) +
new Vector2(force.x * power, force.y * power) * elapsedTime +
0.5f * Physics2D.gravity * elapsedTime * elapsedTime;
}
The code I used for mouse input
if (Input.GetMouseButtonDown(0))
{ //click
startPos = gameObject.transform.position;
for (int i = 0; i < number; i++)
{
trajectoryDots[i] = Instantiate(trajectoryDot, gameObject.transform);
}
}
if (Input.GetMouseButton(0))
{ //drag
endPos = Camera.main.ScreenToWorldPoint(Input.mousePosition) + new Vector3(0, 0, 10);
gameObject.transform.position = endPos;
forceAtPlayer = endPos - startPos;
for (int i = 0; i < number; i++)
{
trajectoryDots[i].transform.position = calculatePosition(i * 0.1f);
}
}
if (Input.GetMouseButtonUp(0))
{ //leave
rigidbody.gravityScale = 1;
rigidbody.velocity = new Vector2(-forceAtPlayer.x * forceFactor, -forceAtPlayer.y * forceFactor);
for (int i = 0; i < number; i++)
{
Destroy(trajectoryDots[i]);
}
}
So after little changes it's much better, I' am getting closer to what i want there are still some glitches i guess because of touch.moved so when I' am on display with my finger and do only little moves ball is jumping on the screen
Here is the code
private void Update()
{
if (Input.touchCount > 0)
{
var touch = Input.GetTouch(0);
switch (touch.phase)
{
case TouchPhase.Began:
initPosition = gameObject.transform.position;
startPosition = cam.ScreenToWorldPoint(touch.position) + new Vector3(0, 0, 10);
for (int i = 0; i < number; i++)
{
trajectoryDots[i] = Instantiate(trajectoryDot, gameObject.transform);
trajectoryDots[i].transform.position = calculatePosition(i * 0.1f);
}
break;
case TouchPhase.Moved:
endPosition = Camera.main.ScreenToWorldPoint(touch.position) + new Vector3(0, 0, 10);
gameObject.transform.position = initPosition;
force = startPosition - endPosition;
for (int i = 0; i < number; i++)
{
trajectoryDots[i].transform.position = calculatePosition(i * 0.1f);
}
break;
case TouchPhase.Ended:
ballRigid.gravityScale = 1;
ballRigid.velocity = new Vector2(force.x * power, force.y * power);
for (int i = 0; i < number; i++)
{
Destroy(trajectoryDots[i]);
}
break;
}
}
}
private Vector2 calculatePosition(float elapsedTime)
{
return new Vector2(initPosition.x, initPosition.y) +
new Vector2(force.x * power, force.y * power) * elapsedTime +
0.5f * Physics2D.gravity * elapsedTime * elapsedTime;
}
Ok i have final soution and it's working correctly
private void Update()
{
if (Input.touchCount > 0)
{
var touch = Input.GetTouch(0);
switch (touch.phase)
{
case TouchPhase.Began:
initPosition = gameObject.transform.position;
startPosition = cam.ScreenToWorldPoint(touch.position) + new Vector3(0, 0, 10);
for (int i = 0; i < number; i++)
{
trajectoryDots[i] = Instantiate(trajectoryDot, gameObject.transform);
trajectoryDots[i].transform.position = calculatePosition(i * 0.1f);
}
break;
case TouchPhase.Ended:
ballRigid.gravityScale = 1;
ballRigid.velocity = new Vector2(force.x * power, force.y * power);
for (int i = 0; i < number; i++)
{
Destroy(trajectoryDots[i]);
}
break;
}
endPosition = Camera.main.ScreenToWorldPoint(touch.position) + new Vector3(0, 0, 10);
gameObject.transform.position = initPosition;
force = startPosition - endPosition;
for (int i = 0; i < number; i++)
{
trajectoryDots[i].transform.position = calculatePosition(i * 0.1f);
}
}
}
private Vector2 calculatePosition(float elapsedTime)
{
return new Vector2(initPosition.x, initPosition.y) +
new Vector2(force.x * power, force.y * power) * elapsedTime +
0.5f * Physics2D.gravity * elapsedTime * elapsedTime;
}
So just taking your mouse code and convert it to touch code it might look like
if(Input.touchCount > 0)
{
var touch = Input.GetTouch(0);
switch(touch.phase)
{
case TouchPhase.Began:
// Note: to be more accurate you actually probably would
// rather also here use ScreenToWorldPoint on the touch.position
// same way as later. Otherwise you might allways get a force even if touch wasn't moved at all
//startPos = transform.position;
startPos = Camera.main.ScreenToWorldPoint(touch.position) + new Vector3(0, 0, 10);
for (int i = 0; i < number; i++)
{
trajectoryDots[i] = Instantiate(trajectoryDot, gameObject.transform);
trajectoryDots[i].transform.position = calculatePosition(i * 0.1f);
}
break;
case TouchPhase.Moved:
// These were missing in your touch version
// You did it only in the end so there were no preview trajectory
// And note that also touch is in pixel screenspace so if you
// want to use world positions you need to convert them just the same as for mouse input!
endPos = Camera.main.ScreenToWorldPoint(touch.position) + new Vector3(0, 0, 10);
transform.position = endPos;
force = endPos - startPos;
for (int i = 0; i < number; i++)
{
trajectoryDots[i].transform.position = calculatePosition(i * 0.1f);
}
break;
case TouchPhase.Ended:
rigidbody.gravityScale = 1;
// Not sure why but in your mouse code you used a negative force here
// but in this case your trajectory would have been wrong since there you didn't use negative values...
rigidbody.velocity = force * forceFactor;
for (int i = 0; i < number; i++)
{
Destroy(trajectoryDots[i]);
}
break;
}
}
Btw the calculate method gets better to read like
private Vector2 calculatePosition(float elapsedTime)
{
return endPoisiton
+ force * power * elapsedTime
+ Physics2D.gravity * 0.5f * elapsedTime * elapsedTime;
}
Note: Typed on smartphone but I hope the idea gets clear
private void MoveToNewFormation()
{
squadMembers = GameObject.FindGameObjectsWithTag("Squad Member");
float step = speed * Time.deltaTime;
for (int i = 0; i < squadMembers.Length; i++)
{
squadMembers[i].transform.LookAt(newpos[i]);
squadMembers[i].transform.position = Vector3.MoveTowards(squadMembers[i].transform.position, newpos[i], step);
//squadMembers[i].transform.rotation = qua[i];
}
}
And calling it in the Update:
void Update()
{
if (Input.GetKeyDown(KeyCode.F))
{
ChangeFormation();
}
if (move == true)
MoveToNewFormation();
}
Once when one of the squadMembers reached to the newpos then i want to make
squadMembers[i].transform.rotation = qua[i];
qua is a List and i want to rotate the squad member once he reached the newpos.
Inside MoveToNewFormation i thought to add after the loop the line:
if (squadMembers[i].transform.position == newpos[i])
{
squadMembers[i].transform.rotation = qua[i];
}
But it's after the loop so 'i' not exist.
This is the complete script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SquadFormation : MonoBehaviour
{
enum Formation
{
Square, Circle, Triangle
}
public Transform squadMemeber;
public int columns = 4;
public int squareSpace = 10;
public int circleSpace = 40;
public int numberOfObjects = 20;
public float yOffset = 0;
public float speed = 3;
private Formation formation;
private GameObject[] squadMembers;
private List<Quaternion> qua = new List<Quaternion>();
private List<Vector3> newpos = new List<Vector3>();
private bool move = false;
// Use this for initialization
void Start()
{
formation = Formation.Square;
ChangeFormation();
}
// Update is called once per frame
void Update()
{
if (Input.GetKeyDown(KeyCode.F))
{
ChangeFormation();
}
if (move == true)
MoveToNewFormation();
}
private void ChangeFormation()
{
switch (formation)
{
case Formation.Square:
FormationSquare();
break;
case Formation.Circle:
FormationCircle();
break;
}
}
private Vector3 FormationSquarePositionCalculation(int index) // call this func for all your objects
{
float posX = (index % columns) * squareSpace;
float posY = (index / columns) * squareSpace;
return new Vector3(posX, posY);
}
private void FormationSquare()
{
for (int i = 0; i < numberOfObjects; i++)
{
Transform go = Instantiate(squadMemeber);
Vector3 pos = FormationSquarePositionCalculation(i);
go.position = new Vector3(transform.position.x + pos.x, 0, transform.position.y + pos.y);
go.Rotate(new Vector3(0, -90, 0));
go.tag = "Squad Member";
}
formation = Formation.Circle;
}
private Vector3 FormationCirclePositionCalculation(Vector3 center, float radius, int index, float angleIncrement)
{
float ang = index * angleIncrement;
Vector3 pos;
pos.x = center.x + radius * Mathf.Sin(ang * Mathf.Deg2Rad);
pos.z = center.z + radius * Mathf.Cos(ang * Mathf.Deg2Rad);
pos.y = center.y;
return pos;
}
private void FormationCircle()
{
Vector3 center = transform.position;
float radius = (float)circleSpace / 2;
float angleIncrement = 360 / (float)numberOfObjects;
for (int i = 0; i < numberOfObjects; i++)
{
Vector3 pos = FormationCirclePositionCalculation(center, radius, i, angleIncrement);
var rot = Quaternion.LookRotation(center - pos);
pos.y = Terrain.activeTerrain.SampleHeight(pos);
pos.y = pos.y + yOffset;
newpos.Add(pos);
qua.Add(rot);
}
move = true;
formation = Formation.Square;
}
private void MoveToNewFormation()
{
squadMembers = GameObject.FindGameObjectsWithTag("Squad Member");
float step = speed * Time.deltaTime;
for (int i = 0; i < squadMembers.Length; i++)
{
squadMembers[i].transform.LookAt(newpos[i]);
squadMembers[i].transform.position = Vector3.MoveTowards(squadMembers[i].transform.position, newpos[i], step);
//squadMembers[i].transform.rotation = qua[i];
}
//if (squadMembers[i].transform.position == newpos[i])
}
}
You can use a threshold and check the distance using that threshold.
Define threshold like this at start of script.
public float threshold = 0.1f;
Then change the MoveToNewFormation() function like this:
private void MoveToNewFormation()
{
squadMembers = GameObject.FindGameObjectsWithTag("Squad Member");
float step = speed * Time.deltaTime;
for (int i = 0; i < squadMembers.Length; i++)
{
squadMembers[i].transform.LookAt(newpos[i]);
squadMembers[i].transform.position =
Vector3.MoveTowards(squadMembers[i].transform.position, newpos[i], step);
if(Vector3.Distance(squadMembers[i].transform.position,newpos[i])<threshold){
squadMembers[i].transform.rotation = qua[i];
}
}
//if (squadMembers[i].transform.position == newpos[i])
}
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...'