here is an image ( I cant post )show what I am gonna to do in my XNA game , I want to check if the player is inside zone range and if yes then attack the player , I tried to do this using checking ray but it's odd and give null results as player must be in front of enemy so he can be detected !
![enter image description here][1]
if (enemyRay.Intersects(cci.CharacterController.Body.CollisionInformation.BoundingBox) <= 200)
{
RunController(dwarfAnimatior, dwarfwalk);
dwarfChrachterController.Body.ApplyImpulse(dwarfChrachterController.Body.OrientationMatrix.Forward,
Vector3.Normalize(enemyRay.Direction) * 50.0f);
if (enemyRay.Intersects(cci.CharacterController.Body.CollisionInformation.BoundingBox) <= 50)
{
sound.playAh();
}
}
You need to do two things:
Check the distance between the player's position and the enemy
position.
Check that the angle made by the line between the player and enemy &
the line pointing in the direction of the player's view is less than
180degrees.
The first is easy:
bool isCloseEnoughToAttack = Vector.Magnitude( Math.abs(player.position - enemy.position) ) < distanceToStartAttacking
The second is a little more complicated. As long as you don't need to be really particular about what 'in-front of player' means, you can fairly easily check the angle is not behind by checking the Dot Product is greater than 0:
bool isInFrontOfPlayer = Vector.DotProduct(Vector.Normalize(player.position - enemy.position), player.lookAtDirection) > 0
Note - This code is psudeocode, I don't know the exact naming of your variables/libraries; but it should be fairly similar.
Related
I'm using Lance for a game where the gameplay area is a tiled map. When a player presses the left-arrow key, their character should move one tile to the left, etc. I tried two approaches, see below, but got neither to work.
Could either approach be modified to work with tile-based movement? Or is a third approach needed? Or is Lance not suited to this kind of game?
Approach 1: Adjust the player's position directly when a key is pressed. From my GameEngine class:
if (inputData.input == 'left') {
player.position.x -= 32;
player.angle = 180;
}
While this works well for a single player, it doesn't in multiplayer. When player A moves, their position is not updated on player B's screen.
Approach 2: Set the player's state when a key is pressed:
if (inputData.input == 'left') {
player.state = 'walkLeft';
}
Then add a postStep handler in the common GameEngine class. (Adding it to Player didn't work). This code turns the player (over many steps) to face 180 degrees and then accelerates the player in that direction:
onPostStep(event) {
let players = this.world.queryObjects({instanceType: Player});
players.forEach(player => {
if (player.state == 'walkLeft') {
if (Math.abs(player.angle - 180) > 2)
player.turnLeft(2);
}
else {
player.accelerate(1);
player.state = '';
}
}
})
}
With this approach, if a player presses the left arrow key, their angle changes as expected at first, but the acceleration and movement is erratic. Also, Player A's position appears different on their screen vs the screen of Player B.
The Spaaace demo is the base for my project, so my project uses the same bending, physics engine, etc.
The first approach is better. The Brawler game in the sample collection does exactly what you describe. You can look at the BrawlerGameEngine.js code in https://github.com/lance-gg/tinygames/tree/master/brawler
Make sure that the action is processed in the method
GameEngine::processInput(inputData, playerId)
I have a 2D tile matrix (of walls for now) and for each wall I check if my player's next Rectangle (next as in where it will be in next frame) is colliding with that wall, and if it is, I want my player to stand right next to it, without going inside of it.
Here is the formula I came up with (this is just for left and right collision):
//*move entity
if (KState.Down(Keys.W)) en.AddForce(new Vector2(0, -10));
if (KState.Down(Keys.S)) en.AddForce(new Vector2(0, 10));
if (KState.Down(Keys.A)) en.AddForce(new Vector2(-10, 0));
if (KState.Down(Keys.D)) en.AddForce(new Vector2(10, 0));
foreach(Item i in map.Items)
{
//resolve left-right collision
if (en.NextBody(elapsedTime).Intersects(i.Body))
{
//check distance between top left corners
int distance = (int)Math.Abs(i.Position.X - en.Position.X);
//stop player in his horisontal movement
en.AddForce(new Vector2(-en.Force.X, 0));
//place player next to the wall his about to collide with
en.Position = new Vector2(en.Position.X - distance + i.Body.Width, en.Position.Y);
}
}
//stop player in place
if (KState.Clicked(Keys.Space)) en.AddForce(en.Force*-1);
en.Update(elapsedTime);
**
Which gave me this result (note that fps is not stable and that currently rectangles are squares 32x32):
Top line of text is players Rectangle, and bottom one is Rectangle of the wall that player collided with last.
Now, when the rocks (player) is moving to the left, I'm holding left key for some time, and when going to the right, I'm holding right key for some time.
Problem: As you can see in gif, when player's going left, he's moving 1 pixel to and from left wall. And when he's moving right, he bounces once, and then stays right next to the right wall. I don't want any bouncing but I don't know how to fix this in logic that I'm using.
Also, if you know good logic for how to resolve Rectangle collision so that they are not intersecting from any sides, I'd appriciate sharing it with me.
Edit 1: I managed to resolve collision to the right problem. Instead of the code above I've put
int sign = Math.Sign(i.Position.X - en.Position.X);
en.AddForce(new Vector2(-en.Force.X, 0));
//wall is right and player is left
if (sign > 0) en.Position = new Vector2(i.Body.Left - en.Body.Width, en.Position.Y);
//wall is left and player is right
if (sign < 0) en.Position = new Vector2(i.Body.Right, en.Position.Y);
but the problem with the left side collision is the same. I tried
if (sign < 0) en.Position = new Vector2(i.Body.Right + 1, en.Position.Y); and if (sign < 0) en.Position = new Vector2(i.Body.Right - 1, en.Position.Y); just in case, but the problem is the same (on "...-1..." case player gets stuck in wall).
Edit 2: As #paste requested, here is the code for NextBody(float elapsedTime) from player class.
public Rectangle NextBody(float elapsedTime)
{ return new Rectangle((int)(force.X * elapsedTime) + body.X, (int)(force.Y * elapsedTime) + body.Y, body.Width, body.Height); }
This is what's happening:
The first time the objects collide while the rocks are moving left, the algorithm works as it should. It sees that the objects are overlapping, it sets the force to Vector2.Zero, and it moves the en so that it is touching the item's right side. Good. Your object is stopped and in the right place.
What happens in the next frame is where things go wrong. You set up your force vector, and then call NextBody(). Let's just look at the X-coordinate. It gets set to:
(int)(force.X * elapsedTime) + body.X
What does this evaluate to? force.X is non-zero, and elapsedTime is also non-zero, but they're less than 1, so when they get converted to int, the result is zero. Therefore, your body is in the same place as it was before, which means the Rectangles do not overlap. This means your collision response code gets skipped and your force vector is still not zero!
Then, further down, you call your player's Update() method. I'm guessing that in that code you update the player's Position and Body. But since force is not zero, and you are using a Vector2 for Position, the x-coordinate will end up being something like 31.841304... instead of 32. If you use that number to calculate the new Body and use it in your Draw method, you'll end up drawing it at x = 31. The next time you check, it'll detect a collision, and the player will bounce out again.
There are a number of ways to fix this. What I do in my collision code is to actually move the objects first and keep a record of where they were in the previous frame. That way, the last adjustment to their position is when they are moved out of the collision area.
I'm using a SpriteKit game engine within XCode while developing a game that bounces a ball and platforms come from the sky and the objective is to bounce on the platforms to get higher. I need to add a velocity to the ball when it falls down + comes in contact with a platform. I'm having trouble trying to detect the balls Y position. I had something like this in the update method but nothing happens... I'm open to suggestions.
//The value of the _number instance variable is the Y position of the ball.
if (_number++) {
NSLog(#"UP");
}
if (_number--) {
NSLog(#"DOWN");
}
You can see a node's position by using code like this:
if(myNode.position.y > 0)
NSLog(#"y is greater than 0");
If you want to check a node's current speed (vector) you can do it like this:
if(myNode.physicsBody.velocity.dy > 0)
NSLog(#"Moving up");
if(myNode.physicsBody.velocity.dy < 0)
NSLog(#"Moving down");
Remember that position and speed (vector) are not the same thing.
You need to read the SKPhysicsBody docs to understand about CGVector and other important issues.
Alright, this:
if (_number++) {
NSLog(#"UP");
}
if (_number--) {
NSLog(#"DOWN");
}
doesn't work to do anything. It shouldn't even run. I don't why it doesn't give an error.
number++; is a simplified form of
number = number + 1;
You can't place it in an if statement.
First make the variable #property int ypos in your header.
Then every update compare the current y to the ypos.
After comparing, save the current y to ypos.
Place this in your Update method.
if (ball.position.y > _ypos)
{
//going up
}
else if (ball.position.y < _ypos)
{
//going down
}
_ypos = ball.position.y;
P.S. I haven't had access to a computer so the formatting might suck from my phone
i have a game where the user must move the ball in a vertical way between 2 objects , i want to have a scoring system that allows me to add 1 to the score each time the ball is equal to the 2 objects so i tried the code below but it is not working probably,it is not adding one each time the ball's y coordinates are equal to the object's y cooridnates.
if(imageview.center.y == imageview1.center.y){
int score = score + 1;
scorelabel.text = [NSString stringWithFormat:#"%i",score];
}
As I assume your imageview.centre.y will be different then imageView1.centre.y .Also you could use this method CGRectIntersection(<#CGRect r1#>, <#CGRect r2#>) and place your both frame in provided fields. So it will notify whenever there is an intersection of two frames. Code will be like -
if (CGRectIntersectsRect(self.pacman.frame, self.exit.frame))
{
//Wirte your score handling code here...
}
else
{
//Skip or do what you want...
}
Hope this might help you.
Your variable is recreated every time your if is performing.
Define it somewhere before #implementation
int score = 0;
And replace int score = score + 1; with score++
As comment you should be aware of comparison of double. See This Question for details
I have a BIG problem!! I want to make something like old space shooter games like “Asteroids”, where the ship, when going out of the screen, is reappearing at the other side. For example, when the ship go out at the top of the screen, it come back at the bottom. But in my game, there’s a camera following the player, showing only a quarter of the world, and I want to simulate an infinite world this way! Here’s a picture showing what I mean :
What I thought doing was simulate the scroll by only moving game objects, stored in an array, but not the player, and calculating at every frame if the objects are out of the world boundary and re-adding them at the other end of the world (i.e going out at the left would add it back at the right).
But I don’t really like that way of doing… I’d like something more… intuitive..?
Do you guys have any idea of how doing it? Like, any tutorial on the web or just the right words to explain what I mean so I could do a bright research on google (I’m french, so I had a really hard time writing that question)!
Thank you in advance!
Knowing the players position, x,y check to see if the player is within the bounds of the area. If the player has left those bounds, set the player's position to the opposite bounds, possibly adding width/height. I'll do it here for the Y coordinate only:
const float minWarpAreaY( 0 );
const float maxWarpAreaY( 400 );
//if (player.y < minWarpAreaY) { player.y = maxWarpAreaY - player.height; }
//if (player.y > maxWarpAreaY) { player.y = minWarpAreaY + player.height; }
if (player.y < minWarpAreaY) { WarpPlayer(0.0f, (maxWarpAreaY - minWarpAreaY)); }
if (player.y > maxWarpAreaY) { WarpPlayer(0.0f, -(maxWarpAreaY - minWarpAreaY)); }
void WarpPlayer(float amountX, float amountY)
{
player.x += amountX;
player.y += amountY;
for (eachObject in World)
{
eachObject.x += amountX;
eachObject.y += amountY;
}
}
Something along those lines should help.