Working on a game here and I've so far made a menu system for my game. I added three different buttons. I have everything sorted out except one thing.
So, I am using a normal if intersects method to see if the mouse and the button rectangle is colliding to play a sound effect. However, I don't know how to stop this sound and it's just looping itself all the time, until I remove the mouse from the button. I want to make it so that it only plays one time.
public void Update(MouseState mouse, GraphicsDevice graphics, SoundEffect soundEffect)
{
rectangle = new Rectangle((int)position.X, (int)position.Y, (int)size.X, (int)size.Y);
Rectangle mouseRectangle = new Rectangle(mouse.X, mouse.Y, 1, 1);
if(mouseRectangle.Intersects(rectangle))
{
if (mouse.LeftButton == ButtonState.Pressed) isClicked = true;
size = new Vector2(graphics.Viewport.Width / 9, graphics.Viewport.Height / 13);
soundEffect.Play();
}
else
{
size = new Vector2(graphics.Viewport.Width / 10, graphics.Viewport.Height / 14);
isClicked = false;
}
Any help would be apreciated.
BTW: This is not neccesary, but I got another "problem" when I hover over the buttons, they get bigger which is intended. But it doesn't get bigger from the center. It's kind of hard to explain but it gets bigger in x and y position, not -x and -y. It has the same positon.
You're going to have to employ some status fields or events to do what you want. Something simple might be to track when the mouse enters and leaves the rectangle:
private bool _mouseIsIntersecting;
public void Update(...)
{
rectangle = new Rectangle(...);
Rectangle mouseRectangle = new Rectangle(...);
if(mouseRectangle.Intersects(rectangle))
{
// Handle click and size stuff
// Only play the sound if mouse was not previously intersecting
if (!_mouseIsIntersecting)
soundEffect.Play();
_mouseIsIntersecting = true;
}
else
{
_mouseIsIntersecting = false;
// Handle other stuff
}
}
Related
In the app I'm trying to develop a key part is getting the position of where the user has touched. First I thought of using a tap gesture recognizer but after a quick google search I learned that was useless (See here for an example).
Then I believe I discovered SkiaSharp and after learning how to use it, at least somewhat, I'm still not sure how I get the proper coordinates of a touch. Here are sections of the code in my project that are relevant to the problem.
Canvas Touch Function
private void canvasView_Touch(object sender, SKTouchEventArgs e)
{
// Only carry on with this function if the image is already on screen.
if(m_isImageDisplayed)
{
// Use switch to get what type of action occurred.
switch (e.ActionType)
{
case SKTouchAction.Pressed:
TouchImage(e.Location);
// Update simply tries to draw a small square using double for loops.
m_editedBm = Update(sender);
// Refresh screen.
(sender as SKCanvasView).InvalidateSurface();
break;
default:
break;
}
}
}
Touch Image
private void TouchImage(SKPoint point)
{
// Is the point in range of the canvas?
if(point.X >= m_x && point.X <= (m_editedCanvasSize.Width + m_x) &&
point.Y >= m_y && point.Y <= (m_editedCanvasSize.Height + m_y))
{
// Save the point for later and set the boolean to true so the algorithm can begin.
m_clickPoint = point;
m_updateAlgorithm = true;
}
}
Here I'm just seeing or TRYING to see if the point clicked was in range of the image and I made a different SkSize variable to help. Ignore the boolean, not that important.
Update function (function that attempts to draw ON the point pressed so it's the most important)
public SKBitmap Update(object sender)
{
// Create the default test color to replace current pixel colors in the bitmap.
SKColor color = new SKColor(255, 255, 255);
// Create a new surface with the current bitmap.
using (var surface = new SKCanvas(m_editedBm))
{
/* According to this: https://learn.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/graphics/skiasharp/paths/finger-paint ,
the points I have to start are in Xamarin forms coordinates, but I need to translate them to SkiaSharp coordinates which are in
pixels. */
Point pt = new Point((double)m_touchPoint.X, (double)m_touchPoint.Y);
SKPoint newPoint = ConvertToPixel(pt);
// Loop over the touch point start, then go to a certain value (like x + 100) just to get a "block" that's been altered for pixels.
for (int x = (int)newPoint.X; x < (int)newPoint.X + 200.0f; ++x)
{
for (int y = (int)newPoint.Y; y < (int)newPoint.Y + 200.0f; ++y)
{
// According to the x and y, change the color.
m_editedBm.SetPixel(x, y, color);
}
}
return m_editedBm;
}
}
Here I'm THINKING that it'll start, you know, at the coordinate I pressed (and these coordinates have been confirmed to be within the range of the image thanks to the function "TouchImage". And when it does get the correct coordinates (or at least it SHOULD of done that) the square will be drawn one "line" at a time. I have a game programming background so this kind of sounds simple but I can't believe I didn't get this right the first time.
Also I have another function, it MIGHT prove worthwhile because the original image is rotated and then put on screen. Why? Well by default the image, after taking the picture, and then displayed, is rotated to the left. I had no idea why but I corrected it with the following function:
// Just rotate the image because for some reason it's titled 90 degrees to the left.
public static SKBitmap Rotate()
{
using (var bitmap = m_bm)
{
// The new ones width IS the old ones height.
var rotated = new SKBitmap(bitmap.Height, bitmap.Width);
using (var surface = new SKCanvas(rotated))
{
surface.Translate(rotated.Width, 0.0f);
surface.RotateDegrees(90);
surface.DrawBitmap(bitmap, 0, 0);
}
return rotated;
}
}
I'll keep reading and looking up stuff on what I'm doing wrong, but if any help is given I'm grateful.
I'm working on an application where several GUI Label display names of planes.
And here's the result :
The problem is, if I rotate my camera by 180 °, those label are here, like there is a point symmetry :
So my label appear twice, once on the plane, which is good, and a second time, behind the camera.
I check if my script was not added twice, but there is no problem, more strange, if I look from an above view, the problem just disappear :
I have no idea where this can come from, here's my code, who is attached to every plane :
void OnGUI()
{
if (showInfos)
{
Rect r = new Rect((Camera.main.WorldToScreenPoint(gameObject.transform.position)).x+25, Camera.main.pixelHeight - (Camera.main.WorldToScreenPoint(gameObject.transform.position)).y+25, 75f, 75f);
GUI.Label(r, gameObject.transform.root.name);
}
}
You are drawing the labels whether or not they are in the view frustum or not.
From Camera.WorldToScreenPoint (emphasis mine):
Screenspace is defined in pixels. The bottom-left of the screen is (0,0); the right-top is (pixelWidth,pixelHeight). The z position is in world units from the camera.
You need to check if the Z value of the screen point is negative or positive (I don't know which one is in front of cam and which one is behind it, I don't use Unity), and according to that decide if it needs to be rendered or not.
void OnGUI()
{
if (showInfos)
{
var pt = Camera.main.WorldToScreenPoint(gameObject.transform.position);
if (pt.z > 0) //or < 0, no idea.
{
Rect r = new Rect(pt.x + 25, Camera.main.pixelHeight - pt.y + 25, 75f, 75f);
GUI.Label(r, gameObject.transform.root.name);
}
}
}
So a friend and I are making a horizontal scroller game. There are mice hidden throughout the screen and because it's a horizontal scroller game you can also scroll to the left and right and see more mice.
We originally made this game in de default xna screensize (800 x 480). We're now at a point where we want our game to be fullscreen. Our point of the game is to click on the mice and get a higher score, etc...
Now before we made our game fullscreen we could click on the mice and our score would add up. After we've made it fullscreen we can't click on the mice anymore. Well, we can still click on them, but instead of adding points to our score nothing happens.
We're using bounding boxes on the mice, and whenever the X & Y position of our computermouse is withing one of those boundingboxes and you will click with your computermouse at the moment that your computermouse is inside a mouse boundingbox then you're supposed to get points adding up to your score. This is the code for the boundingbox on every mouse.
public Rectangle getBoundingBox()
{
return new Rectangle(
(int)_position.X,
(int)_position.Y,
_texture.Width,
_texture.Height
);
}
We gave all our mice a position by the next code:
_position = _scrollerBackground.GetPosition() + _offsetFromBackground;
The next piece of code is how we get the position of our mouse and what it should do when the position of the mouse is within one of our mice(_number0). When the mouseposition is within the boundingbox from the mouse and when the computermouse clicks at that moment then input = 0;
public void UpdateMouse()
{
mouse = Mouse.GetState();
mousePosition.X = mouse.X;
mousePosition.Y = mouse.Y;
}
public void OnMouseOver()
{
if (_number0.getBoundingBox().Contains(mousePosition))
{
if (mouse.LeftButton == ButtonState.Pressed && oldMouseState.LeftButton == ButtonState.Released)
{
input += "0";
}
}
This is how it worked before we made our game fullscreen, but now that doesn't work anymore. This is the code we used to make our game fullscreen:
graphics.IsFullScreen = true;
Does anyone have any similar experiences or maybe knows how to fix this?
Using Artemis, Visual Studio, C# and Monogame.
Just starting to get a grasp on Artemis, but looking fo the proper place to add a clickable rectangle/area to an entity, there will be multiple entities on the screen.
Basic simple idea, i have small square sprites randomly showing and moving in the 2D play area.
I need to be able to click on them and keeping it simple, delete the square.
In Artemis you have Components, Entities, Systems.
I know i'll be adding this rectangle area to the Texture2D square, guessing it should be its own component.
Trying to figure out
Get the rectangle the size of the square, and stay with the square when it moves.
How in some system, detect that this square was clicked or touched.
UPDATE
In my DrawableGameComponent entity.
DrawPosition is a vector2 and set in the Main Game routine.
It is the location of my square.
I use that and texture size to calculate the size and location of my rectangle.
AreItemsIntersecting function will take the Mouse position when the screen is clicked, then i used that to create a little rect, and then checked if the 2 intersect. If they do, then the object was clicked.
public override void Update(GameTime gameTime)
{
var bx = DrawPosition.X;
var by = DrawPosition.Y;
var w = _texture.Bounds.Width;
var h = _texture.Bounds.Height;
_bounds = new Rectangle((int)bx, (int)by, w+1, h+1);
base.Update(gameTime);
}
public override void Draw(GameTime gameTime)
{
if (_texture != null)
{
_spriteBatch.Begin();
_spriteBatch.Draw(_texture, DrawPosition, Color.White);
_spriteBatch.Draw(_texture, _bounds, Color.Transparent);
_spriteBatch.End();
base.Draw(gameTime);
}
public bool AreItemsIntersecting(int x, int y)
{
var vect = new Rectangle(x, y, 1, 1);
if (vect.Intersects(_bounds))
{
return true;
}
return false;
}
I would create a BoundingBox component. It will expose a Bounds property of type Rectangle.
With this component in place you can create a KillEntityOnClickSystem to handle the removal of clicked entities. You'll just need to check whether the mouse is inside the Bounds of the entity BoundingBox when the mouse button is clicked.
Hope this helps!
For a project, I'm making a game and in it I have a scrolling map. The map moves left and right and is redrawn in a picturebox so that I can have a large map in a small picturebox. The top portion of the map is transparent so that I can change the sky colour later on. However when I move the map, the transparent part glitches out.
Original map before moving
After moving the map a bit
As you can see, everything above the tree line gets stretched, that is because that is where the transparency starts. The picturebox's parent is the form and the form is light blue, which is why the background is light blue.
Here is my code for moving the picture/redrawing it onto the picturebox:
private void timerTick_Tick(object sender, EventArgs e)
{
move();
//Draws new portion of the map
g.DrawImage(image, new Rectangle(0, 0, pbMap.Width, pbMap.Height), new Rectangle(imageX, imageY, pbMap.Width, pbMap.Height), GraphicsUnit.Pixel);
//Refreshes
pbMap.Image = bmp;
}
private void move()
{
//Right arrow events
if (right)
{
imageX += mapSpeed;
//Makes sure the picture stays within borders
if (imageX >= (imageWidth - pbMap.Width))
{
imageX = imageWidth - pbMap.Width;
}
}
//Left arrow events
if (left)
{
imageX -= mapSpeed;
//Makes sure the picture stays within borders
if (imageX <= 0)
{
imageX = 0;
}
}
}
Can anyone help explain the glitching?
Try calling g.Clear() with your sky color before the g.DrawImage() call. I think it's just drawing on top of itself and that's causing the smearing.
To me it seems like you are redrawing over and over without clearing the display from the previous draw! What type of framework are you using to develop that? Does it have a custom drawing class? As tesserex suggested more specifically call g.Clear() and u will be fine.
You shouldn't need g.Clear in this case because you're Re-Drawing a new image every time.
My bet is that imageX is greater then (imageWidth - pbMap.Width) so it will not enter the IF, therefore it will redraw the same as before.
Note: I don't know how you create g but if you use .CreateGraphics() don't forget to Dispose()
Cheers