Apply gesture effects only when the user touches the object - c#

I am a newbie in game development, and I am developing a concept for windows store using monogame implementation of XNA where in, I am making a ball move on flick gesture. But, my problem is the ball moves not only on applying the gesture on to the ball but applying the gesture anywhere on the screen makes my ball move. What I want is, my ball shall only move when I apply flick on the ball itself but not on the other areas of the screen. I am using rectangle bounding box to see whether user touches the ball object but in vain.
I am sharing with my method to Update Gametime
//Global vars
//cat is the ball object here
GraphicsDeviceManager _graphics;
SpriteBatch _spriteBatch;
private Texture2D cat;
private Vector2 _spritePosition;
private SpriteFont _fontMiramonte;
BounceableImage mBall;
const float DECELERATION = 1000;
Vector2 position = Vector2.Zero;
Vector2 velocity;
//Update method
protected override void Update(GameTime gameTime)
{
// TODO: Add your update logic here
while (TouchPanel.IsGestureAvailable)
{
GestureSample gesture = TouchPanel.ReadGesture();
if (IsPointInObject(position))
{
if (gesture.GestureType == GestureType.Flick)
velocity += gesture.Delta;
if (gesture.GestureType == GestureType.Hold)
position = gesture.Position;
}
}
// Use velocity to adjust position and decelerate
if (velocity != Vector2.Zero)
{
float elapsedSeconds = (float)gameTime.ElapsedGameTime.TotalSeconds;
position += velocity * elapsedSeconds;
float newMagnitude = velocity.Length() - DECELERATION * elapsedSeconds;
velocity.Normalize();
velocity *= Math.Max(0, newMagnitude);
}
UpdateSprite(gameTime, ref position, ref velocity);
base.Update(gameTime);
}
//method to detect whether the touched point lies inside the object ball
public bool IsPointInObject(Vector2 positionVector)
{
Rectangle bbx = new Rectangle((int)position.X , (int)position.Y, (int)cat.Width, (int)cat.Height);
return bbx.Contains((int)(positionVector.X), (int)(positionVector.Y));
}

You'll have to set a canvas on TouchPanel and set and lock this canvas for gesture movements from player. You'll have to set canvas block smaller from Panel, where you want to see touch effect.

Related

how to find a position of an Object from World Space and convert to Canvas UI with render mode : Screen Space - Camera in Unity 2d?

I am working in a Game which is pretty similar to Mario. So when player touches the coin object in World Space, I need to animate by moving that coin object to Coin meter, when the render mode of Canvas is Screen Space - Overlay, I can get the sprite object position easily with below code
CoinSprite Code
GameObject coinCanvasObject = Instantiate(prefab, canvas.transform);//Instantiate coin inside Canvas view
coinCanvasObject.transform.position = Camera.main.WorldToScreenPoint(coinSpriteObject.transform.position);//getting coin position from World Space and convert to Screen Space and set to coinCanvasobject position
AnimateCoin animate = coinCanvasObject.GetComponent<AnimateCoin>();
animate.animateCoin(coinSpriteObject.transform.position);
coinSpriteObject.SetActive(false);
AnimateCoin
public class AnimateCoin : MonoBehaviour
{
private float speed = 0f;
private bool isSpawn = false;
private Vector3 screenPos;
public void animateCoin(Vector3 screenPosTemp, Camera cam, Canvas canvas)
{
screenPos = Camera.main.WorldToScreenPoint(screenPosTemp);
isSpawn = true;
}
private void Update()
{
if (isSpawn)
{
speed += 0.025f;
transform.position = Vector3.Lerp(screenPos, targetObject.transform.position, speed);
if (Vector3.Distance(transform.position, targetObject.transform.position) <= 0)
{
StartCoroutine(deActivateCoin());
}
}
}
private IEnumerator deActivateCoin()
{
isSpawn = false;
yield return new WaitForSeconds(0.2f);
gameObject.SetActive(false);
}
}
Since I need to bring particle effect into Canvas view, I am changing the Canvas render mode to Screen Space - Camera.
When I change the Canvas to this render mode I could not get the exact sprite object position to trail the coin effect.
Hope this helps:
public Camera cam; // Camera containing the canvas
public Transform target; // object in the 3D World
public RectTransform icon; // icon to place in the canvas
public Canvas canvas; // canvas with "Render mode: Screen Space - Camera"
void Update()
{
Vector3 screenPos = cam.WorldToScreenPoint(target.position);
float h = Screen.height;
float w = Screen.width;
float x = screenPos.x - (w / 2);
float y = screenPos.y - (h / 2);
float s = canvas.scaleFactor;
icon.anchoredPosition = new Vector2(x, y) / s;
}
PD: It worked perfectly for me in a 2D video game, I didn't test it in a 3D game, but I think it should work too.
I rewrote my previous solution because it might not work correctly on some devices with non-standard resolutions.
This code should always work.
uiObject.anchoredPosition = GetUIScreenPosition(myPin.position, cam3d, uiObject.anchorMin);
public static Vector2 GetUIScreenPosition(Vector3 obj3dPosition, Camera cam3d, Vector2 anchor)
{
Vector2 rootScreen = _rootCanvasRect.sizeDelta;
Vector3 screenPos = cam3d.WorldToViewportPoint(obj3dPosition);
return (rootScreen * screenPos) - (rootScreen * anchor);
}
We take the sizeDelta of our UI Canvas, because it may differ from the screen resolution of the device.
Then we cast the WorldToViewportPoint from our 3d camera to get the relative position on the screen in the format from 0 to 1 by X and Y.
With anchors in the lower left corner ((0,0)(0,0)) this is our final anchoredPosition. However with anchors for example in the center ((0.5,0.5)(0.5,0.5)) we need to adjust the positions by subtracting half the canvas size.
In this example, we will get an unpredictable result when using different min and max anchors in the final object. For example ((0,25,0.25)(0.75,0.75)). But I sincerely doubt that you really need such anchors on an object with a dynamic position depending on the 3d object.

Using Camera.main.ScreenToWorldPoint while the camera is moving

want to make a game where there is a 2D ball which moves to the position of the cursor. To get the position of the cursor, I use this code:
Vector2 PixelPos = Input.mousePosition;
Then to convert the screen position to world position I use this code:
Vector2 Pos = Camera.main.ScreenToWorldPoint(PixelPos);
The problem is that the main camera move up so that if forces the player to move. But when it move I get some weird movement with the ball.(as the camera is moving up it is always moving the ball)
Is there an alternate way to make this work??
Or more simply can I replace this piece of code:
Vector2 Pos = Camera.main.ScreenToWorldPoint(PixelPos);
with some other things which does not require a camera to convert the screen positions to world position?
Thanks!
Since you want the cursor to be moved only by the player and to be updated relative to world space, not screen space, you need to implement a virtual cursor that exists in world space.
First, create your virtual cursor as a GameObject. On Update you can update its position with
float sensitivity = 1f;
transform.position += sensitivity * new Vector2(
Input.GetAxis("Mouse X"),
Input.GetAxis("Mouse Y")
);
Then, instead of using the camera to find the cursor position, you just check the `transform.position` of that virtual cursor `GameObject`.
Second, you'll need to lock the built-in cursor. You can do that with
Cursor.lockState = CursorLockMode.Locked;
If you need to undo that (for instance, if you bring up a menu, and need to use the regular cursor without moving the virual cursor around), then you can use:
Cursor.lockState = CursorLockMode.None;
or, if you need the cursor to stay in the window:
Cursor.lockState = CursorLockMode.Confined;
If you only want to move the ball to the last position clicked/touched then here is an easier solution.
Keep track of the goal position for the ball, and if one has been set yet:
private Vector2 moveGoalPos;
private bool moveGoalSet= false;
Only change moveGoalPos on frames where the mouse is clicked/the screen is touched.:
bool isTouched;
if (isMouseEnable) {
isTouched = Input.GetMouseButtonDown(0);
PixelPos = Input.mousePosition;
} else {
isTouched = Input.touchCount > 0;
Touch touch = Input.GetTouch(0);
PixelPos = touch.position;
}
if (isTouched) {
moveGoalPos= Camera.main.ScreenToWorldPoint(PixelPos);
moveGoalSet= true;
}
However, on every frame, you'll want to move the ball to the world space moveGoalPos (only if a goal has been set):
if (moveGoalSet) {
Vector2 OffsetPos = moveGoalPos + CursorOffSet;
GCursor.transform.position = OffsetPos;
print(OffsetPos);
Vector2 LerpPos = Vector2.Lerp(rb.transform.position, OffsetPos, 0.05f);
rb.MovePosition(LerpPos);
}
When you need to stop the ball from moving to the last touched/clicked position (for instance, if you change or reset a level), you'll need to reset moveGoalSet:
moveGoalSet = false;

Unity C# camera movement

I'm currently trying to create a Camera Control for unity (to follow around a prefab and be able to zoom and such ...
I am very new to C#
an issue I am having with this script is that
camera zooming to 0,0,0. (when I need it to stay at it's current Y-axis, I tried changing the void "Move()" but the vector requires 3 m_....'s
I also need to write a piece of code that will allow the player to zoom the camera in and out using the
scroll wheel... (In "Public Void Update()"...
I've been looking through guides and videos and can't find anything to assist me with this..
this is the section of code I require help with :
private void FixedUpdate()
{
Move();
}
private void Move()
{
m_DesiredPosition = m_target.position;
transform.position = Vector3.SmoothDamp(transform.position,
m_DesiredPosition, ref m_MoveVelocity, m_DampTime);
}
public void Update()
{
// Get the scroll value of the mouse scroll wheel
// float scroll = Input.GetAxis("Mouse ScrollWheel");
// Is the scroll value not 0?
// Modify the orthographic size by the scroll value
Camera.main.orthographicSize = 4.8f;
}
For keeping the camera at Y = 0 simply override Y:
m_DesiredPosition = m_Target.position;
m_DesiredPosition.Y = 0;
transform.position = Vector3.SmoothDamp(transform.position,
m_DesiredPosition, ref m_MoveVelocity, m_DampTime);
For zooming the camera you'll want to add/subtract the value to orthographicsize instead of simply setting it:
// Zoom in
Camera.main.orthographicSize -= 4.8f;
// Zoom out
Camera.main.orthographicSize += 4.8f;

Rotation of a Sprite Around Its Pivot

I have a class below that I attach to a object in order to make it rotate around its pivot. I sent the pivot of the sprite via the inspector.
This works exactly how I want it too, BUT the issue I am having is that whenever I touch and drag it, and then touch and drag it again, it snaps to a new position.
What I would like for it to do is, when it is rotated and then rotated again, the sprite stays in its same rotation and not snap to a new position and I would like the angle of the sprite to be reset to 0. The next then is that I want the angle to continually rotate. So if I rotate it in the positive direction, the angle should keep increasing in the positive direction and not change..Such as 0---> 360 ----> 720 -----> etc, etc. And then when the mouse is released, the sprite stays in the same position but the angle is now set back to 0. And then when clicked again to rotate, it rotates from that exact position.
Here is my code thus far which works well for rotating, but I would like to modify it to achieve the above scenario. Any help with this?
public class Steering : MonoBehaviour {
float prevAngle,wheelAngle,wheelNewAngle = 0;
public SpriteRenderer sprite;
void Start () {
}
void Update () {
}
public float GetAngle(){
return wheelAngle;
}
void OnMouseDrag(){
Vector3 mouse_pos = Input.mousePosition;
Vector3 player_pos = Camera.main.WorldToScreenPoint(this.transform.position);
mouse_pos.x = mouse_pos.x - player_pos.x;
mouse_pos.y = mouse_pos.y - player_pos.y;
wheelNewAngle = Mathf.Atan2 (mouse_pos.y, mouse_pos.x) * Mathf.Rad2Deg;
if (Input.mousePosition.x > sprite.bounds.center.x) {
wheelAngle += wheelNewAngle - prevAngle;
} else {
wheelAngle -= wheelNewAngle - prevAngle;
}
this.transform.rotation = Quaternion.Euler (new Vector3(0, 0, wheelAngle));
Debug.Log (wheelAngle);
prevAngle = wheelNewAngle;
}
void OnMouseUp(){
prevAngle = wheelNewAngle;
wheelAngle = 0;
}
}
By angle of the sprite, do you mean the rotation? I'm not sure how the position is changing if there's nothing in your code doing that. Does it always move to the same position? I'm having a little trouble visualizing how your system is supposed to look but I hope this helps.
It looks like you might want to store the previous mouse position so you can get the relative amount to rotate each frame.
At the top:
Vector3 prevMousePos = Vector3.zero;
This method will help get the position when the player pressed:
void OnMouseDown(){
prevMousePos = Input.mousePosition;
}
Then in OnMouseDrag() get the difference between the two mouse positions to get the relative position (if you moved the mouse left, right, up, or down since pressing):
Vector3 mouseDiff = Input.mousePosition - prevMousePos;
With this it will use the relative mouse position after pressing instead of the current one, which should smooth things out.

Character jump in XNA

I am new in Game Programming but I'm interested in this domain; now I am working on a small game for my course work. I have used some ideas from the internet to make my hero jump; the code is working, but after I press first time space, the hero is jumping and is not coming back to his position, he remains on the top of the screen. Please help me to make my hero, then return to his initial position. If I press space again he is jumping, but is jumping there, on the top of the screen.
public void Initialize()
{
startY = position.Y;
jumping = false;
jumpspeed = 0;
}
public void Update(GameTime gameTime)
{
KeyboardState keyState = Keyboard.GetState();
rectangle = new Rectangle(currentFrame * frameWidth, 0, frameWidth, frameHeight);
origin = new Vector2(rectangle.Width / 2, rectangle.Height / 2);
AnimateRight(gameTime);//calling AnimateRight function to animate heroes sprite
if (jumping)
{
position.Y += jumpspeed;
jumpspeed += 1;
if (position.Y >= startY)
{
position.Y = startY;
jumping = false;
}
}
else
{
if (keyState.IsKeyDown(Keys.Space))
{
jumping = true;
jumpspeed = -14;
}
}
}
You have to set startY when pressing Space:
if (keyState.IsKeyDown(Keys.Space))
{
jumping = true;
jumpspeed = -14;
startY = position.Y;
}
I know that you are new, but I replicated a movement system that worked great if you can understand it, here is the link to see the player movement in action, and here is the web site for it. If you want to download it here is the link.
This player movement uses a couple important things,
First:
Inside the Player class there is a method called public Player, yes, you make a method that is the same name as the class. By doing this you can transfer information from the Game1 class to Player class. So you can send the player texture, position, speed, ect...
Second:
Inside the Player method the info that is called over from the Game1 class needs to be collected and stored in the Player class. So if you wanted to transfer the texture of you player you would need to do the following.
Create the Player Texture and create a the link that will allow you to create the link to the Player class:
Texture2D personTexture;
'Player player'
Then in the Load Content you need to call on the personTexture and put it into the player function:
personTexture = Content.Load <Texture2D>("Person");
player = new Player(personTexture);
Now that the Texture is now in side the Player method in the Player class you will now store it in the Player class so that you can use it, add a Texture2D Texture to your Player class then enter the following:
public Player(Texture2D Texture)
{
this.Texture = Texture;//this.Texture is the one you create in side the
Player class, the other is the Texture you stated
}
Now your done and able to use your texture in that class.
Hopefully this will help you understand how to create your jumping player.

Categories

Resources