Hi im building a chess game in Unity and my issue is that the queen can move above a friendly piece.
When a piece is selected, an array of legal moves on the board is generated
legalMoves = piece.Move();
I chose to work with vectors here so any move within the list is a 2d Vector.
Then in a loop, I check if any of the moves are within the boundaries of the board and if the move would place the piece on another friendly piece. If it does, then discard that move but my problem is that it should discard all the moves within that direction.
For example: if the queen is on (3,3) and there is a pawn on (3,5), then all the moves (3,6), (3,7) ... should be discarded but not (3,4).
Similarly, if the black queen is on (7,7) and a pawn is on (7,5) then all moves (7,4), (7,3), (7,2) .. should be discarded but not (7,6).
My intuition here was that when a vector has a friendly piece on it, check the direction and the length of all my legal moves against it:
if (dir.normalized.Equals(temp[j].normalized) && dir.SqrMagnitude() < temp[j].SqrMagnitude())
The idea was to remove all the vectors from the legalmoves with the same direction but with greater length, however this doesn't really seem to work because the normalized vectors will not be equal.
Here is the relevant code
foreach (var dir in legalMoves)
{
if (0 <= dir.x && dir.x <= 7 && 0 <= dir.y && dir.y <= 7)
{
//TODO shrink this to 1d array search
if (board[(int) dir.x, (int) dir.y].getPiece() == null)
{
Instantiate(trail, dir, Quaternion.identity);
}
else
{
List<Vector2> temp = legalMoves.ToList();
GameObject[] trails = GameObject.FindGameObjectsWithTag("bullet");
for (int j = 0; j< temp.Count; j++)
{
if ( dir.normalized.Equals(temp[j].normalized) && dir.SqrMagnitude() < temp[j].SqrMagnitude())
{
foreach(var t in trails)
{
// remove trail
if (t.transform.position.Equals(temp[j])) Destroy(t);
}
// remove the move with the same direction
temp.Remove(temp[j]);
}
}
temp.Remove(dir);
legalMoves = temp.ToArray();
}
}
}
here is my problem visualized chess collision issue
Ok, maybe there could be a better solution, however, the way I managed to do it is the following:
Our queen = q is at (3,0) , obstructed piece = k is at (3,6),
If we calculate the offset from k to q we always get an axis which is 0 (either x or y ) in this case it is x.
Since we know an axis is 0 we can check which one is 0 using a boolean, in this case it is x, and simply discard all the legal moves which are on x and above 6 or below 6 for black pieces.
I haven't thought about how to do it if a piece obstructs horizontally, however I'm sure its just a matter of adding/ substracting the right coordinates as above.
Related
I'm trying to move a PictureBox diagonally in a game I'm making.
private void movebulletupright()
{
//this part is mainly for checking the action[![enter image description here][1]][1]
for (int k = bulletlistupright.Count - 1; k >= 0; k--)
{
bulletlistupright[k].Location.X++;
bulletlistupright[k].Location.Y++;
//This part is just basically meant to get rid of the bullet
//when it reaches the end of the screen
if (bulletlistupright[k].Left >= this.ClientSize.Height)
{
this.Controls.Remove(bulletlistupright[k]);
bulletlistupright.RemoveAt(k);
}
}
}
I'm using a timer to move the bullets. What I would like to do is move the bullet 5 pixel per tick (which is 1 millisecond). if you look at the attached picture below, what i'm trying to do is move those yellow bullet shaped in the corners diagonally.(i only have them there so i can represent where they spawn in). [1]: http://i.stack.imgur.com/wQc5l.png
Try to move in one go:
bulletlistupright[k].Location = new Point(
bulletlistupright[k].Location.X + 5, // 5 is X step
bulletlistupright[k].Location.Y + 5); // 5 is Y step
in order to prevent jitting (i.e. unwanted redrawing - first redrawing after X coordinate is changed, than after Y)
I'm not sure I understand your question, but if you are moving it 1 pixel in your code, to move it 5 pixels, you'd only need to do:
bulletlistupright[k].Location.X+=5;
bulletlistupright[k].Location.Y+=5;
If that's not what you are looking for, please be more clear in your question
I'm new at this and I'm making a very simple 2D platformer with a level is loaded from a text file. I'm having trouble to try how to figure out how I can have my character sprite collide with the tiles.
This is an example of a .txt that my game will run:
1,1,1,1,1,1,1,1,
1,1,1,0,0,0,0,1,
1,1,0,0,0,1,0,1,
1,0,0,0,0,1,1,1,
1,0,0,0,0,0,0,1,
1,0,0,0,1,0,0,1,
1,S,0,1,1,0,F,1,
1,1,1,1,1,1,1,1,
I've managed to figure out how to successfully draw them onto the page, but cannot progress further.
My current model has my character colliding with the edge of the screen by having a boolean for Collision equal to true when the edge of the sprite touches the edge of the screen and setting its velocity to 0, but I'm not sure how to do that to block that are generated from a .txt
My current model of drawing a level looks like this:
if (currentState == GameState.Playing)
{
for (y = 0; y <= 7; y++)
{
string[] mapchars = maplines[y].Split(','); //where maplines is each row of characters and mapchars is each individual character//
for (x = 0; x <= 7; x++)
{
if (mapchars[x] == "1")
{
spriteBatch.Begin();
spriteBatch.Draw(block, new Vector2((200 + (50 * x)), ((50 * y))), Color.White);
spriteBatch.End();
}
if (mapchars[x] == "F")
{
spriteBatch.Begin();
spriteBatch.Draw(block, new Vector2((200 + (50 * x)), ((50 * y))), Color.Yellow);
spriteBatch.End();
}
if (mapchars[x] == "S")
{
spriteBatch.Begin();
spriteBatch.Draw(sprite, new Rectangle((200 + (50 * x)), ((50 * y)), 40, 40), Color.White*0.5f);
spriteBatch.End();
}
if (x > 7)
{
break;
}
}
if (y > 7)
{
break;
}
}
}
Where maplines[] is each line of the .txt and where mapchars[] is for each individual character on each line.
If anyone knows a solution to this problem, it would be a great help :)
Thanks.
Don't do that like this ! You are wasting a lot of speed with a game coded like this. I have an issue for you.
First, get all your .txt map into a string[] wich is line is an string. Do that with the method File.ReadAllLines(string yourtxtfilepath).
Once you have done this, create an new 2 dimensional array of Block (Block[,]). You have to create an general abstract class Block wich all your types of blocks (rock, air, grass ...) inherits from its.
Create a for loop who checks all chars in all the string of the array of string you got. In that loop check if the character is an '1' or an 'F' or something else by a case statement. For example, if it was an 'F' add a new GrassBlock to your Block 2 dimensional array.
Finally, after the loop you get your map in your 2 dimensional Block array, wich is perfect to get access to all your blocks in the map.
Just put a foreach loop in the Draw() method to draw each block to your screen by incrementing their positions by the width and the heights of your tiles.
If you don't understand what I said, just do some Google searches to get the necessary knowledge so you will understand. Start by acknowledge what I try to explain you and after, you can concentrate yourself on collisions, wich is more advanced.
I am currently creating a brickbreaker clone (yeah, another) and have the ball-brick collision for 1 brick. I have 4 other bricks commented out, because when the ball collides with the brick I have the right code for, it just removes all bricks rather than the specific one it collided with. Also, the ball only collides with the first brick when the ball is near the top left corner of the game screen (pretty far from the actual brick). I'm really not sure what to do, I have tried spacing the bricks out a bit more but that didn't help.
int score = 0;
if ((ballY > picBrk1.Height) && (ballY < picBrk1.Height + 30) && (ballX > picBrk1.Width) && (ballX < picBrk1.Width + 71))
{
// ball rebounds off brick
yChange = -yChange;
// each brick adds 1 to score
score = score + 1;
lblScore.Text = "Score: " + score;
picBrk1.Visible = false;
}
You need to be very clear about the localisation of your bricks.
I suggest adding a UpperLeft property to your Brick class:
public class Brick
{
/* your other properties here */
public Point UpperLeft {get; set;}
}
Make sure UpperLeft value is properly set to the coordinates of the upper left corner of your brick.
My assumption is that your X and Y follow the standard computer image representation where 0,0 is the top left corner of the image and y increases when you go south (which is different from the usual mathematical standard).
Then your collision check will be:
Point ballRelativeToBrick1 = new Point(
ballX - picBrick1.UpperLeft.X,
ballY - picBrick1.UpperLeft.Y)
bool collide = 0 < ballRelativeToBrick1.X && ballRelativeToBrick1.X < picBrick1.Width
&& 0 < ballRelativeToBrick.Y && ballRelativeToBrick.Y < picBrick1.Height
I have a bouncing ball application and I have to extend it to prevent overlapping of the balls.
When ball overlaps another, they should move away as in real life.
I have to extend the given MoveBall method:
private void MoveBall()
{
prevX = x;
prevY = y;
x += xVelocity;
y += yVelocity;
// Is there too closed ball?
foreach (Ball ball in parentForm.balls)
{
distance = Math.Sqrt(Math.Pow((double)(ball.prevX - prevX), 2) +
Math.Pow((double)(ball.prevY- prevY), 2));
overlap = ((radius + ball.radius) - distance);// +ball.radius;
if (ball.id != this.id &&
ball.id != lastID &&
overlap > 0)
{
lastID = this.id;
if (xVelocity > 0) // roading right
{
xVelocity = -xVelocity;
x -= xVelocity - ball.xVelocity;
}
else if (xVelocity <= 0) // roading left
{
xVelocity = -xVelocity;
x += xVelocity + ball.xVelocity;
}
if (yVelocity > 0)
{ // going up
yVelocity = -yVelocity;
y -= yVelocity - ball.yVelocity;
}
else if (yVelocity <= 0) // down
{
yVelocity = -yVelocity;
y += yVelocity + ball.yVelocity;
}
}
}
// ***********************************************
// ***************** END MY CODE *****************
if (x > parentForm.Width - 10 - (radius) || x < 0)
{
if (x < 0) x = 0;
if (x > parentForm.Width - 10) x = parentForm.Width - 10 - radius;
xVelocity = -xVelocity;
}
if (y > parentForm.Height - 40 - (radius) || y < 0)
{
if (y < 0) y = 0;
if (y > parentForm.Height - 40) y = parentForm.Height - 40 - (radius);
yVelocity = -yVelocity;
}
}
x,y, xVelocity, yVelocity, radius, prevX, prevY declared as int.
overlap, distance as double.
When 2 overlap, they are getting stuck. Why?
Unfortunately, I can't upload all source code because there are lot of modules.
I'm using Visual C# Express 2010.
As no Question is asked explicitly, I will assume the question "Why are the balls sticking together?"
You have only shown one loop in source code, that's not enough ;-) To check all possible collisions, you need to check n*(n-1)/2 possible collisions. That is normally done with two loops. You have to put in careful measures to avoid handling the same collision twice.
The reason that your balls get stuck is that you handle the same collision multiple times. For example two balls colliding exactly horizontal: The left one has velocity 5 and x-position of 100. The other one shall have a position of 110 and velocity of -6. When the collision happens:
x is set to 105.
Collision detected: x is set to 104 and velocity to -5.
The other Ball handles the same collision:
He moves according to his velocity to position 104.
Collision handling: His velocity becomes 6 and position becomes 105.
The balls were at 100 and 110 resp. and have been moved to 104 and 105. While the velocities are now pointing away from each other, the collision handling in the following step will invert them again. So the positions are close together and the velocities are changing sign every frame. The balls seem "stuck to each other".
I hope the answer helps you to understand your problem. For a better implementation of an elastic collision (that handles each collision exactly once) look here: Ball to Ball Collision - Detection and Handling
Having stumbled upon similar issues when I made my first attempts at collision detection algorithms, I'll try to describe what I think is the problem here.
Maybe the balls move fast enough so that, before collision is even detected by your code, they are already partially "inside" each other. When collision detection comes and notices that, it does what it's supposed to do: change the planned trajectories of the objects according to the details of the collision that just happened. The problem is that, because these objects got sort-of "merged" before collision detection caught them, they can't get unstuck because collision detection is fired again, trapping them with each other.
If this is the source of the problem, then maybe the above code would work with a small enough velocity vector. Of course, that's not a real solution, but if it does work for very small velocities, it probably confirms my hypothesis and you have some idea regarding how to proceed.
I'm working on an assignment for uni where I have to create a Breakout game in Visual Studio 2010 using C# Win Forms. At the moment, I am concentrating on there being only one brick to be destroyed so I have the mechanics down before expanding on it.
To clarify about my current program: I am using a picture box as a Graphics object and a timer to create the animation effect. The ball can skip, at each frame, between 1 and 10 pixels — this is part of creating a random starting vector for the ball.
This works fine until it comes to checking if the ball has 'hit' the brick I have drawn. What I have is an if statement that checks if the ball is at any of the coordinates on the picture box that corresponds to the outline of the brick. I know that the logic is fine because it works some of the time. However, because of the variation in the 'jumping' of the ball's position, I need to add a buffer area of +/- 5 pixels to my if statement.
This is where the problem arises, because my if statement (two, really) is really complicated as it is:
// Checks if ball hits left side or top of brick
if (((x >= brickX) && (x <= (brickX + 50)) && (y == brickY)) ||
((y >= brickY) && (y <= (brickY + 20)) && (x == brickX)))
{
brickHit = true;
}
// Check if ball hits right side or bottom of brick
else if ((((x >= brickX) && (x <= brickX + 50)) && (y == (brickY + 20))) ||
(((y >= brickY) && (y <= brickY + 20)) && (x == brickX + 50)))
{
brickHit = true;
}
For clarification: x and y are the coordinates of the ball and brickX and brickY are the coordinates of the top-left corner of the rectangle brick (which is 50 pixels wide, 10 pixels high).
Is there any way to simplify the above if statements? If I can make them simpler, I know it'll be much easier to add in the 'buffer' (which only needs to be 5 pixels either side of the brick's outline' to allow for the ball's change in position).
If further clarification is needed, please ask — I'm writing this question at 5:12am so I know I might be a little unclear.
One way you could possible simplify this (and I may be misunderstanding your spec), but you can make a Rectangle out of the bounds of the brick and check the Contains for your x,y point.
Rectangle rec = new Rectangle(brickX, brickY, 50, 20);
rec.Offset(-5, -5);
rec.Inflate(10, 10);
if (rec.Contains(new Point(x,y))
{
brickHit = true;
}
brickHit = new Rectangle(brickX,brickY,50,20).Contains(x,y);
Adding a buffer:
int buffer = 5;
brickHit = new Rectangle(brickX,brickY,50,20).Inflate(buffer,buffer).Contains(x,y);
The Rectagle class can come in handy sometimes.
This worked for me:
var rect1 = new System.Drawing.Rectangle(pictureBox1.Location,
pictureBox1.Size);
var rect2 = new System.Drawing.Rectangle(pictureBox2.Location,
pictureBox2.Size);
if (rect1.IntersectsWith(rect2))
{
//code when collided
}