I am a beginner in Monogame and C#. I am making my first game.
I have changed the screen dimensions in Game1 constructor. I am drawing a sprite where I have set the Rectangle width and height to width and height of the screen to fit it on the screen. I am creating a scrolling background for which I have to change the position of the sprite. I am setting the position to Vector. Zero which is making the sprite stretched towards the right.
Game1
//member variables
Vector2 stage;
Texture2D fbTexture;
private List<ScrollingBackground> sb;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
//change the screen size
graphics.PreferredBackBufferHeight = 900;
graphics.PreferredBackBufferWidth = 600;
Window.Title = "Flappy Bird Returns";
graphics.ApplyChanges();
}
protected override void LoadContent()
{
stage = new Vector2(graphics.PreferredBackBufferWidth,
graphics.PreferredBackBufferHeight);
//Day Background
Texture2D dayTex = Content.Load<Texture2D>("Images/background-day");
Vector2 daySpeed = new Vector2(1, 0);
sb = new List<ScrollingBackground>()
{
//set the width and height to be the same as the screen
//dimensions then this will
//stretch the image past its original dimensions to fit.
new ScrollingBackground(this,
spriteBatch,
dayTex,
new Vector2(0,0),
new Rectangle(0,0, (int)stage.X, (int)stage.Y),
daySpeed)
};
foreach (ScrollingBackground scrollbackg in sb)
this.Components.Add(scrollbackg);
}
//ScrollingBackground.cs
private SpriteBatch spritebatch;
private Texture2D tex;
private Vector2 position1;
private Vector2 speed;
private Rectangle srcRect;
public ScrollingBackground(Game game, SpriteBatch spriteBatch, Texture2D tex, Vector2 pos, Rectangle srcRect, Vector2 speed) : base(game)
{
this.spritebatch = spriteBatch;
this.tex = tex;
this.position1 = pos;
this.speed = speed;
this.srcRect = srcRect;
}
public override void Draw(GameTime gameTime)
{
spritebatch.Begin();
spritebatch.Draw(tex, position1, srcRect, Color.White);
spritebatch.End();
base.Draw(gameTime);
}
//Without position1
spritebatch.Draw(tex, srcRect, Color.White);
You need to give an argument to the float scale parameter. This means you'll need to use a more specific signature for this method :
SpriteBatch.Draw(Texture2D texture, Vector2 position, Rectangle? sourceRectangle, Color color, float rotation, Vector2 origin, **float scale**, SpriteEffects effects, float layerDepth)
At the same time, you'll need to specify default values for every other parameter. For example, here's how you'd write that same Draw() method with the aforementioned method signature :
public override void Draw(GameTime gameTime)
{
spritebatch.Begin();
spritebatch.Draw(tex, position1, srcRect, Color.White, 0f, Vector2.Zero, 2f, SpriteEffects.None, 0f);
spritebatch.End();
base.Draw(gameTime);
}
Here, I put your texture to 2x it's original size. Change that 2f to the size you want. Keep in mind the final size will be the width/height values of your srcRect multiplied by that number.
Related
I have been trying to make an infinitely repeating background. Found this piece below but it goes horizontally instead of vertically. I tried rotating my sprites but it didn't work, also changed the x values with y and the loop stopped happening.
I'm stuck trying to figure out a solution.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class RepeatBg : MonoBehaviour
{
private BoxCollider2D boxCollider;
private Rigidbody2D rb;
private float width;
private float speed = -3f;
// Start is called before the first frame update
void Start()
{
boxCollider = GetComponent<BoxCollider2D>();
rb = GetComponent<Rigidbody2D>();
width = boxCollider.size.x;
rb.velocity = new Vector2(speed,0);
}
// Update is called once per frame
void Update()
{
if (transform.position.x<-width)
{
Reposition();
}
}
private void Reposition()
{
Vector2 vector = new Vector2(width * 2f, 0);
transform.position = (Vector2)transform.position + vector;
}
}
You need to change all "vertical stuff" to horizontal.
Add a member variable
private float height;
In method Start set
height = boxCollider.size.y;
rb.velocity = new Vector2(0, speed);
In method Update change the condition to
if (transform.position.y < -height)
In method Reposition set
Vector2 vector = new Vector2(0, height * 2f);
For this setup in Unity, there is a circular dial. The values of the rotation are being used to scale the model. The actual scaling code is removed because there is a bug in the way zAngle value is calculated. Ideally it should be in steady increments in all directions, but here, the values jump across horizontal and vertical axes but they grow slowly when the dial is dragged in other directions.
Is there a recommended practice for such cases when using the screen drag position to calculate the rotation value?
zAngle is the final angle value used to rotate the dial and would be also used after some clamping to scale the model, but that is not the requirement here.
public class CircularScaleDial : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler
{
RectTransform rectTransform;
public GameObject model;
[SerializeField] Vector2 delta = Vector2.one;
[SerializeField] CanvasScaler canvasScaler;
private Vector3 startPosition;
[SerializeField] int zAngle;
Vector3 gd1 = Vector3.zero;
private void Awake()
{
rectTransform = GetComponent<RectTransform>();
}
public void OnBeginDrag(PointerEventData eventData)
{
startPosition = GetDelta_3(eventData);
}
int GetAngleFromPosition(Vector2 pos) {
var angleRadians = Mathf.Atan2(pos.y, pos.x);
var angleDegrees = angleRadians * Mathf.Rad2Deg;
return (int)angleDegrees;
}
Vector3 GetDelta_3(PointerEventData data)
{
Vector3 pos = new Vector3(data.position.x, data.position.y, 0);
Vector3 s2vp = Camera.main.ScreenToViewportPoint(pos);
return s2vp;
}
public void OnDrag(PointerEventData data)
{
if (data.dragging)
{
gd1 = GetDelta_3(data);
delta.x = gd1.x;
delta.y = gd1.y;
zAngle = GetAngleFromPosition(delta);
rectTransform.localRotation = Quaternion.Euler(new Vector3(0, 0, zAngle));
}
}
}
It was sort of fixed with a simpler code. Made other tweaks but this was the main change. The essence here is to resolve the delta along y. For this case I just take the y component but ideally we would take a dot product of two values to resolve one along the other.
public void OnBeginDrag(PointerEventData eventData)
{
startV2 = eventData.position;
}
public void OnDrag(PointerEventData data)
{
if (data.dragging)
{
endV2 = data.position;
Vector2 deltaV2 = endV2 - startV2;
deltaV2 = deltaV2.normalized;
rectTransform.Rotate(new Vector3(0, 0, -deltaV2.y), Space.Self);
startV2 = endV2;
}
}
I am making a game which let you click on a ball and drag to draw a line renderer with two points and point it to a specific direction and when release I add force to the ball,
for now, I just want to know how can I limit the distance between those two points like give it a radius.
You can simply clamp it using a Mathf.Min.
Since you didn't provide any example code unfortunately here is some example code I made up with a simple plane with a MeshCollider, a child object with the LineRenderer and a camera set to Orthographic. You probably would have to adopt it somehow.
public class Example : MonoBehaviour
{
// adjust in the inspector
public float maxRadius = 2;
private Vector3 startPosition;
[SerializeField] private LineRenderer line;
[SerializeField] private Collider collider;
[SerializeField] private Camera camera;
private void Awake()
{
line.positionCount = 0;
line = GetComponentInChildren<LineRenderer>();
collider = GetComponent<Collider>();
camera = Camera.main;
}
// wherever you dragging starts
private void OnMouseDown()
{
line.positionCount = 2;
startPosition = collider.ClosestPoint(camera.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, transform.position.z)));
var positions = new[] { startPosition, startPosition };
line.SetPositions(positions);
}
// while dragging
private void OnMouseDrag()
{
var currentPosition = GetComponent<Collider>().ClosestPoint(camera.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, transform.position.z)));
// get vector between positions
var difference = currentPosition - startPosition;
// normalize to only get a direction with magnitude = 1
var direction = difference.normalized;
// here you "clamp" use the smaller of either
// the max radius or the magnitude of the difference vector
var distance = Mathf.Min(maxRadius, difference.magnitude);
// and finally apply the end position
var endPosition = startPosition + direction * distance;
line.SetPosition(1, endPosition);
}
}
This is how it could look like
I've written the following pseudo code, which may help you
float rang ;
Bool drag=true;
GameObject ball;
OnMouseDrag () {
if(drag) {
//Put your dragging code here
}
if (ball.transform.position>range)
Drag=false;
else Drage=true;
}
I have two GameObjects with a box collider. One is the player, moved with a fixed velocity towards the other. The collision stops the player (the Poo character ;D)
But they overlap, you can see it here:
I don't know why this is happening. Colliding with the top or bottom works just fine...The same effect happens from the left side. The green block has just a collider, no RigidBody.
Gif:
Another Gif, with MovePosition() ... Colliding fromt the top works, but "reentering" stops the character. Why?!:
GIF, moving up and down is okay, left and right at the top of the blocks slows him down. Weird...
Movement Script:
public class PlayerController : MonoBehaviour
{
public float Speed = 10f;
private Rigidbody2D rb2D;
private Vector2 DirectionLeft;
private Vector2 DirectionRight;
private Vector2 DirectionUp;
private Vector2 DirectionDown;
private Vector2 CurrentDirection;
// Use this for initialization
void Start()
{
rb2D = GetComponent<Rigidbody2D>();
DirectionLeft = new Vector2(Speed*-1, 0);
DirectionRight = new Vector2(Speed, 0);
DirectionUp = new Vector2(0, Speed * -1);
DirectionDown = new Vector2(0, Speed);
CurrentDirection = DirectionLeft;
}
void SetAnimationDirection()
{
Vector3 scale = transform.localScale;
if (CurrentDirection == DirectionLeft)
scale.x = 1;
else
scale.x = -1;
transform.localScale = scale;
}
void FixedUpdate()
{
float moveHorizontal = Input.GetAxis("Horizontal");
float moveVertical = Input.GetAxis("Vertical");
if (moveHorizontal > 0)
CurrentDirection = DirectionRight;
if (moveHorizontal < 0)
CurrentDirection = DirectionLeft;
if (moveVertical < 0)
CurrentDirection = DirectionUp;
if (moveVertical > 0)
CurrentDirection = DirectionDown;
Debug.Log(CurrentDirection);
SetAnimationDirection();
rb2D.velocity = CurrentDirection;
}
The solution to the first problem (overlapping):
I used transform.localScale = scale to change the direction of the sprite on every FixedUpdate() and also forgot to update the factor of the scale, since I added a new extension, which resized my object by 1 more Unity unit.
The other problem (getting stuck at the edge) is solved adding setting the Edge Radius of the Collider 2D to something below 1.0f (e.g 0.09f) and also resize the bounding box. This will prevent the object from getting stuck at the edges, because the bounding box edges are now rounded.
I'm creating an Archery, Platformer, Shooting game named "ArcheryRun" with a small team. We have a powerbar (shown in orange) which increases as you hold down the "Left Mouse Button". However since its a UI element it is static in a position.
I would like it to appear above the player when they change their z-axis as Ive done with the Arrow Image by using a 2D Sprite object. However I can't seem how to change the z-axis of a UI Image relative to the player or use a Game Object which allows a fill option.
Any help is appreciated, thanks :)
Change Orange Powerbar to Follow Player
If we understand your question, this should work:
This method gives you screen canvas position from world position:
public static Vector3 GetScreenPositionFromWorldPosition(Vector3 targetPosition)
{
Vector3 screenPos;
screenPos = Camera.main.WorldToScreenPoint(targetPosition);
return new Vector3 (screenPos.x, screenPos.y, 0f);
}
Then you need a script on top of power bar, lets say like this:
public class PowerBar : MonoBehaviour
{
public Transform target;
RectTransform _rectTransform;
void Awake ()
{
_rectTransform = GetComponent<RectTransform> ();
}
public void updatePosition()
{
Vector3 pos = YourStaticClassWith.GetScreenPositionFromWorldPosition (target.position);
Vector2 rpos = pos;
_rectTransform.anchoredPosition3D = rpos + Vector2.up * 100f; // 100f is value of how many pixels above the target that UI element should apear
}
void LateUpdate()
{
updatePosition ();
}
}
The target is basicly transform of your player object.
The 100f value represents pixels above the target.