I am trying to update my player by mouse click. I have tried different actions on player to update such as free drag. They work. But mouse click does not work. Can anybody help me?
For more detail, my player class holds animation texture and its position. I am trying to change another texture to current one.
It works. I mean: when I drag the player its animation changes. It means my class functionality has no problem. But when I try the same thing with mouse click, it does not work.
//initialize method
player.Initialize(player1, player1.Position);
//update method
protected override void Update(GameTime gameTime)
{
currentMouseState = Mouse.GetState();
UpdatePlayer(gameTime);
_bgLayer1.Update(gameTime);
_bgLayer2.Update(gameTime);
base.Update(gameTime);
}
//update player method
void UpdatePlayer(GameTime gameTime)
{
player.Update(gameTime);
// Touch inputs
while (TouchPanel.IsGestureAvailable)
{
GestureSample gesture = TouchPanel.ReadGesture();
if (gesture.GestureType == GestureType.FreeDrag)
player.Position += gesture.Delta;
player.PlayerAnimation = player2;
}
// Get Mouse State
if (previousMouseState.LeftButton == ButtonState.Released && currentMouseState.LeftButton == ButtonState.Pressed)
{
player.PlayerAnimation = player2;
}
previousMouseState = currentMouseState;
}
Related
We are building an example that is similar to the "Kitten - Placing Virtual objects in AR" as shown here:
https://developers.google.com/tango/apis/unity/unity-howto-placing-objects.
Basically when you touch the screen, a kitten appears on the real world plane (floor).
In our app we have a side menu, with a few buttons and each shows a different game object. We want to detect touch anywhere on the screen except where there is UI. We want the UI to block touches in Tango, and only allow touches to instantiate the related game objects on areas of the screen without UI elements.
The touch specific code is here:
void Update() {
if (Input.touchCount == 1) {
// Trigger placepictureframe function when single touch ended.
Touch t = Input.GetTouch(0);
if (t.phase == TouchPhase.Ended) {
PlacePictureFrame(t.position);
}
}
}
(The PlacePictureFrame() places a picture frame object at the touch position.)
I can't find any Tango examples which has touch and UI combined. I've tried an asset called LeanTouch to block touches behind UI elements but it doesn't seem to work with Tango specifically. Please help!
I have tried using method 5 from this:
How to detect events on UI and GameObjects with the new EventSystem API
and while it does add a PhysicsRaycaster to the TangoARCamera (which is tagged as MainCamera), the OnPointerDown method produces no debug logs no matter where you touch the screen. Tango is a special case so this is not a duplicate question. See below:
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
public class PictureFrameUIController : MonoBehaviour, IPointerClickHandler {
public GameObject m_pictureFrame;
private TangoPointCloud m_pointCloud;
void Start() {
m_pointCloud = FindObjectOfType<TangoPointCloud>();
addPhysicsRaycaster();
}
void addPhysicsRaycaster() {
PhysicsRaycaster physicsRaycaster = GameObject.FindObjectOfType<PhysicsRaycaster>();
if (physicsRaycaster == null) {
Camera.main.gameObject.AddComponent<PhysicsRaycaster>();
}
}
public void OnPointerClick(PointerEventData eventData) {
Debug.Log("Clicked: " + eventData.pointerCurrentRaycast.gameObject.name);
PlacePictureFrame(eventData.pointerCurrentRaycast.screenPosition);
}
//void Update() {
// if (Input.touchCount == 1) {
// // Trigger placepictureframe function when single touch ended.
// Touch t = Input.GetTouch(0);
// if (t.phase == TouchPhase.Ended) {
// PlacePictureFrame(t.position);
// }
// }
//}
void PlacePictureFrame(Vector2 touchPosition) {
// Find the plane.
Camera cam = Camera.main;
Vector3 planeCenter;
Plane plane;
if (!m_pointCloud.FindPlane(cam, touchPosition, out planeCenter, out plane)) {
Debug.Log("cannot find plane.");
return;
}
// Place picture frame on the surface, and make it always face the camera.
if (Vector3.Angle(plane.normal, Vector3.up) > 60.0f && Vector3.Angle(plane.normal, Vector3.up) < 140.0f) {
Vector3 forward = plane.normal;
// Vector3 right = Vector3.Cross(plane.normal, cam.transform.forward).normalized;
// Vector3 forward = Vector3.Cross(right, plane.normal).normalized;
Instantiate(m_pictureFrame, planeCenter, Quaternion.LookRotation(forward, Vector3.up));
} else {
Debug.Log("surface is not steep enough for picture frame to be placed on.");
}
}
public void DeleteAllFrames() {
GameObject[] frames = GameObject.FindGameObjectsWithTag("Frame");
if (frames == null) {
return;
}
foreach (GameObject frame in frames) {
Destroy(frame);
}
}
}
If you want to detect a click anywhere on the screen except for where there is a UI control/component, you have to check if the pointer is over the UI with EventSystem.current.IsPointerOverGameObject(Input.GetTouch(0).fingerId).
If on desktop, use EventSystem.current.IsPointerOverGameObject(). You are using Tango so EventSystem.current.IsPointerOverGameObject(Input.GetTouch(0).fingerId). should be used.
void Update()
{
if (Input.touchCount == 1)
{
//Trigger placepictureframe function when single touch ended.
Touch t = Input.GetTouch(0);
if (t.phase == TouchPhase.Ended)
{
//Make sure that pointer is not over UI before calling PlacePictureFrame
if (!EventSystem.current.IsPointerOverGameObject(Input.GetTouch(0).fingerId))
{
PlacePictureFrame(t.position);
}
}
}
}
Edit:
It seems like this works with TouchPhase.Began only.
Change t.phase == TouchPhase.Ended to t.phase == TouchPhase.Began and this should work as expected. Make sure to test with a mobile device/tango instead of your mouse.
I am using MonoGame 3.6.0.906 on MacOS. I am trying to get some mouse input code working, but I have found some strange behaviour. It appears that the mouse position does not update when the left button is pressed. This makes it impossible to implement mouse dragging input.
To investigate, I added print statements when the left mouse button is pressed, when is released and the mouse position every update. I then tried clicking and dragging. The mouse definitely moved when the left button was down.
Here is the log:
...
{X:89 Y:384}
{X:89 Y:385}
{X:90 Y:386}
pressed
released
{X:91 Y:386}
{X:94 Y:386}
{X:96 Y:386}
...
As can be seen, the mouse position does not change when the left button is down.
Why is this? Is this a bug in MonoGame?
The important code:
MouseState previousMouseState;
protected override void Update(GameTime gameTime)
{
var mouseState = Mouse.GetState();
if (mouseState.LeftButton == ButtonState.Pressed &&
previousMouseState.LeftButton == ButtonState.Released)
{
Console.WriteLine("pressed");
}
if (mouseState.LeftButton == ButtonState.Released &&
previousMouseState.LeftButton == ButtonState.Pressed)
{
Console.WriteLine("released");
}
if (mouseState.Position != previousMouseState.Position)
{
Console.WriteLine(mouseState.Position);
}
previousMouseState = mouseState;
base.Update(gameTime);
}
Update I just tested this in a MonoMac application and it works correctly. The problem occurs when using the cross platform desktop template, the Xamarin Mac template and the Xamarin Classic template.
This was fixed in a later version: https://github.com/MonoGame/MonoGame/issues/5296
I want to play the gunshot sound once I click the left button mouse, but my code is not working.(is running without errors, but not playing the sound)
If I remove the "if condition" and run the game, once the game is running the the first thing will be the gunshot sound.
But if I use the "if condition" it does not work anymore even if I click the left mouse button. I need help to solve this one.
class Gun
{
Texture2D gun;
Vector2 position;
SoundEffect soundEffect;
public Gun(ContentManager Content)
{
gun = Content.Load<Texture2D>("Gun");
position = new Vector2(10, 10);
MouseState mouse = Mouse.GetState();
if (mouse.LeftButton == ButtonState.Pressed)
{
soundEffect = Content.Load<SoundEffect>("gunshot");
soundEffect.Play();
}
}
As mentioned in the comments on your original post, you are checking the LeftButton state only when the object is created. What you need to do is add an Update method that does the check and plays the sound effect. I would also move the soundEffect loading out of that loop and do it when you construct or load the object so you have something like this:
public class Gun
{
Texture2D gun;
Vector2 position;
SoundEffect soundEffect;
MouseState _previousMouseState, currentMouseState;
public Gun(ContentManager Content)
{
gun = Content.Load<Texture2D>("Gun");
soundEffect = Content.Load<SoundEffect>("gunshot");
position = new Vector2(10, 10);
}
public void Update(GameTime gameTime)
{
// Keep track of the previous state to only play the effect on new clicks and not when the button is held down
_previousMouseState = _currentMouseState;
_currentMouseState = Mouse.GetState();
if(_currentMouseState.LeftButton == ButtonState.Pressed && _previousMouseState.LeftButton != ButtonState.Pressed)
soundEffect.Play();
}
}
Then in your Game's Update loop, just call gun.Update(gameTime) (where gun is an instance of your gun class)
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.
How can you read two gestures at the same time. I'm currently developing a game where two players should use the FreeDrag gesture.
What happens now is:
When player A starts, and he is dragging it works perfectly. If player B then also starts it's FreeDrag gesture, the TouchPanel.ReadGesture(); doesn't register it until player A's gesture is finished.
I use the following code:
In Initialize()
TouchPanel.EnabledGestures = GestureType.FreeDrag;
In Update()
if (TouchPanel.IsGestureAvailable)
{
GestureSample touch = TouchPanel.ReadGesture();
if (touch.GestureType == GestureType.FreeDrag)
{
if (touch.Position.Y > GraphicsDevice.Viewport.Height/2)
{
//logic Player A here
}
else
{
//logic Player B there
}
}
}
You have an example in the MSDN documentation:
http://msdn.microsoft.com/en-us/library/ff827740.aspx
// get any gestures that are ready.
while (TouchPanel.IsGestureAvailable)
{
GestureSample gs = TouchPanel.ReadGesture();
switch (gs.GestureType)
{
case GestureType.VerticalDrag:
// move the poem screen vertically by the drag delta
// amount.
poem.offset.Y -= gs.Delta.Y;
break;
case GestureType.Flick:
// add velocity to the poem screen (only interested in
// changes to Y velocity).
poem.velocity.Y += gs.Delta.Y;
break;
}
}
You can't, FreeDrag isn't a multitouch gesture, you should try using TouchLocation and TouchCollection which let you detect multitouch. Unfortunately you can't use default gestures you've declared in TouchPanel.EnabledGestures.