How to move a sprite without decimals in its position - xna

Currently, my game using some pixel detections.
For exemple, for sprites, i retrieve the pixel of its position.
When i move it, the position values have some decimals like :
thePixel = new vector(position.X, position.Y);
//thePixel = (52.2451, 635.2642)
so i have to Round These values
thePixel = new vector((float)Math.Round(position.X, 0), (float)Math.Round(position.Y, 0));
//thePixel = (52, 635)
I would like to know if there are some other ways to get perfect position (means, without decimal) without Rounding them.
Is it maybe a moving method problem ?
Thx for reading, hope you can help.

You can't really get around the need to round your values, but you can make it a lot nicer to code by using an extension method:
public static class Vector2Extensions
{
public static Vector2 Floor(this Vector2 vector)
{
return new Vector2((float)Math.Floor(vector.X), (float)Math.Floor(vector.Y));
}
}
(As you can see, personally I prefer Floor to Round. I also have one for Ceiling.)
Then you can just use it like this:
HandleCollision(position.Floor());
Of course, if you're doing per-pixel collision detection - your collision maths should probably be integer-based (not stored as float in a Vector2). You could use Point. Turns out I have an extension method for that too:
public static class Vector2Extensions
{
public static Point AsXnaPoint(this Vector2 v)
{
return new Point((int)v.X, (int)v.Y);
}
}
Then:
HandleCollision(position.AsXNAPoint());
Or possibly:
HandleCollision(position.Floor().AsXNAPoint());

Related

SetMatrix has no effect (WebCamTexture Unity)

I'm using WebCamTexture to get input from the camera (iOS&Android). However, since this is raw input, the rotation is wrong when rendered to a texture. I read around a lot, and found this (look at the bottom): WebCamTexture rotated and flipped on iPhone
His code (but with test-values):
Quaternion rotation = Quaternion.Euler(45f, 30f, 90f);
Matrix4x4 rotationMatrix = Matrix4x4.TRS(Vector3.zero, rotation, new Vector3(1, 1, 1));
material.SetMatrix("_Rotation", rotationMatrix);
But whatever value I use, nothing happens (neither in the editor or on devices)...
Thanks!
Edit
After some intense testing, I found that material.SetMatrix, SetFloat, SetWhatever has NO effect (not setting the value) unless it's declared inside the "Properties"-block. Looking at unity:s own example, this should't have to (and can't) be done for a matrix (can't be declared inside Properties, only inside the CGProgram). So... How do you set a matrix then? Or what else am I doing wrong?
You should be using: WebCamTexture.videoRotationAngle
its designed to solve exactly this problem, read more about this here.
Example code:
using UnityEngine;
using System.Collections;
public class ExampleClass : MonoBehaviour {
public WebCamTexture webcamTexture;
public Quaternion baseRotation;
void Start() {
webcamTexture = new WebCamTexture();
renderer.material.mainTexture = webcamTexture;
baseRotation = transform.rotation;
webcamTexture.Play();
}
void Update() {
transform.rotation = baseRotation * Quaternion.AngleAxis(webcamTexture.videoRotationAngle, Vector3.up);
}
}
Just rotate the camera to 90 degrees along the z axis (the camera is which is rendering the webcamtexture gameobject).

Why Vector2 (from XNA's library) uses float not int?

Why Vector2 (from XNA's library) uses float not int?
Position on computer screen is given in pixels so that cursor position can be defined by two integers. There is no such a thing like half a pixel. Why we use floats then?
In SpriteBatch class I've found 7 overloaded methods called Draw. Two of them:
public void Draw(Texture2D texture, Rectangle destinationRectangle, Color color);
public void Draw(Texture2D texture, Vector2 position, Color color);
So we can see that Draw accepts both int and float coordinates.
I came across this problem when I've been implementing screen coordinates of my game's objects. I assumed that Rectangle is good choice to hold object's size and screen coordinates. But now I'm not sure...
Mathematically, a vector is a motion, not a position. While a position on the screen might not technically be able to be between integers, a motion definitely can. If a vector used ints then the slowest you could move would be (1, 1). With floats you can move (.1, .1), (.001, .001), and so on.
(Notice also that the XNA struct Point does actually use ints.)
You could use both Vector2 and Rectangle to represent your objects coordinates. I usually do it like this:
public class GameObject
{
Texture2D _texture;
public Vector2 Position { get; set; }
public int Width { get; private set; } //doesn't have to be private
public int Height { get; private set; } //but it's nicer when it doesn't change :)
public Rectangle PositionRectangle
{
get
{
return new Rectangle((int)Position.X, (int)Position.Y, Width, Height);
}
}
public GameObject(Texture2D texture)
{
this._texture = texture;
this.Width = texture.Width;
this.Height = texture.Height;
}
}
To move objects, just set their Position property to a new value.
_player.Position = new Vector2(_player.Position.X, 100);
You don't have to worry about the rectangle, as it's value depends directly on Position.
My game objects also usually contain methods to draw themselves, such as
public void Draw(SpriteBatch spriteBatch, GameTime gameTime)
{
spriteBatch.Draw(this._texture, this.Position, Color.White);
}
Collision detection code in your Game.Update() could just use the PositionRectangle to test for collisions
//_player and _enemy are of type GameObject (or one that inherits it)
if(_player.PositionRectangle.Intersects(_enemy.PositionRectangle))
{
_player.Lives--;
_player.InvurnerabilityPeriod = 2000;
//or something along these lines;
}
You could also call the spriteBatch.Draw() with PositionRectangle, you shouldn't notice much difference.
There is such a thing as "half a pixel." Using float coordinates that aren't pixel-aligned will cause your sprites to be rendered at sub-pixel coordinates. This is often necessary to make objects appear to scroll smoothly, but it can also produce an unpleasant shimmering effect in some circumstances.
See here for a summary of the basic idea: Subpixel rendering

Drag, rotate and ease in ActionScript

I need to make a MovieClip rotate around it's center point to the left or right depending on mouse drag. I got some basic semblance of what i want going, but it's pretty hackish. Normally i calculate the angle and such but i only really need to use the distance the mouse travels and apply it to the movieclip and for flavor add some nice easing when you let go.
public function Main()
{
var wereld:MainScreen = new MainScreen();
addChild( wereld );
wereld.x = -510;
planet = wereld["planet"];
wereld.addEventListener( MouseEvent.MOUSE_DOWN, startRotatingWorld );
}
private function startRotatingWorld( e:MouseEvent ):void
{
m_mouseStartPos = stage.mouseX;
stage.addEventListener( MouseEvent.MOUSE_UP, stopRotatingWorld );
stage.addEventListener( Event.MOUSE_LEAVE, stopRotatingWorld);
}
private function applyRotationToWorld( e:MouseEvent ):void
{
//Calculate the rotation
var distance:Number = (m_mouseStartPos - stage.mouseX) / 10000;
//apply rotation
planet.rotation += -distance //* 180 / Math.PI;
}
private function stopRotatingWorld():void
{
stage.removeEventListener( MouseEvent.MOUSE_MOVE, applyRotationToWorld );
}
here is source and demo of a potential solution for you:
http://wonderfl.net/c/o8t0
I based the drag rotation detection on keith peter's minimalcomps, specifically the source for his knob component
In the Minimal Comp's Knob source, you can get rotational, horizontal, and vertical movement in the 'onMouseMoved' function.
Finally I used TweenLite to handle the easing back. In my code I Tween the 'this' object, but in practice you should create a public value in the object you are tweening and tween that item, so you can have more that one item tweening easily.
If this is for a public facing project, let me know when you've implemented it; wouldn't mind taking a look on what it is for ^_^

Defining two SpriteSortModes?

In DirectX it is possible to set the D3DXSPRITE parameters to be a combination of both:
D3DXSPRITE_SORT_DEPTH_BACKTOFRONT
and
D3DXSPRITE_SORT_TEXTURE
Meaning that sprites are sorted first by their layer depth and then secondly by the texture that they are on. I'm trying to do the same in XNA and i'm having some problems. I've tried:
SpriteBtch.Begin(SpriteBlendMode.AlphaBlend, SpriteSortMode.BackToFront & SpriteSortMode.Texture, SaveStateMode.None);
But it doesn't work and just seems to do them in Texture ordering, ignoring the textures layer depth. Am I doing something wrong!? Or is it not even possible?
SpriteSortMode is an enum and should be combined using the | operator:
SpriteSortMode.BackToFront | SpriteSortMode.Texture
Update: as this article mentions, your scenario is not possible in XNA:
sorting by depth and sorting by
texture are mutually exclusive
A possible solution :
Define a new object representing a sprite to draw
class Sprite
{
public float Priority { get; set; } // [0..1]
public String TextureName { get; set; }
public void Draw(SpriteBatch spriteBatch)
{
spriteBatch.Draw(TextureName, ..., Priority); // here Priority is useless because of the sort mode.
}
}
Then add a "sprites to draw" list that you:
Sort by drawing priority, reverse order so Priority == 1 is first
Sort by texture when a.Priority == b.Priority (this is the tricky part but not THAT hard)
So in your Main class for example, you'll have :
private List<Sprite> spritesToDrawThisTick = new List<Sprite>();
And every tick, you :
Add sprites to draw
Do the sorting logic
Call your SpriteBatch.Begin using SpriteSortMode.Immediate
Do a foreach on your list to call every Sprite's Draw method
important: empty your spritesToDrawThisTick list

How can I fill an actionscript 3 polygon with a solid color?

I'm building a map editor for a project and need to draw a hexagon and fill it with a solid color. I have the shape correct but for the life of me can't figure out how to fill it. I suspect it may be due to whether the thing is a Shape, Sprite or UIComponent. Here is what I have for the polygon itself:
import com.Polygon;
import mx.core.UIComponent;
public class greenFillOne extends UIComponent {
public var hexWidth:Number = 64;
public var hexLength:Number = 73;
public function greenFillOne() {
var hexPoly:Polygon = new Polygon;
hexPoly.drawPolygon(40,6,27+(hexWidth*.25),37,0x499b0e,1,30);
addChild(hexPoly);
}
}
The Polygon class isn't a standard Adobe library, so I don't know the specifics. However, assuming that it uses the standard flash API, it should be no problem to add some code to extend the function. You just need to make sure you're doing a graphics.beginFill before the graphics.lineTo / graphics.moveTo functions. And then finish with graphics.endFill.
e.g.,
var g:Graphics = someShape.graphics;
g.beginFill(0xFF0000,.4); // red, .4 opacity
g.moveTo(x1,y1);
g.lineTo(x2,y2);
g.lineTo(x3,y3);
g.lineTo(x1,y1);
g.endFill();
This will draw a triangle filled with .4 red.
I'll put this here because answering it as a comment to Glenn goes past the character limit. My actionscript file extends UIComponent. When I created a variable hexPoly:Polygon = new Polygon; it would render the outline of the hex, but would not fill it no matter what I did. I examined polygon.as and duplicated the methods, but as a sprite and it worked. So, I need to figure out how to wrap the polygon as a sprite, or just leave it as is.
var hexPoly:Sprite = new Sprite;
hexPoly.graphics.beginFill(0x4ea50f,1);
hexPoly.graphics.moveTo(xCenter+(hexWidth*.25)+Math.sin(radians(330))*radius,offset+(radius-Math.cos(radians(330))*radius));
hexPoly.graphics.lineTo(xCenter+(hexWidth*.25)+Math.sin(radians(30))*radius,offset+(radius-Math.cos(radians(30))*radius));
hexPoly.graphics.lineTo(xCenter+(hexWidth*.25)+Math.sin(radians(90))*radius,offset+(radius-Math.cos(radians(90))*radius));
hexPoly.graphics.lineTo(xCenter+(hexWidth*.25)+Math.sin(radians(150))*radius,offset+(radius-Math.cos(radians(150))*radius));
hexPoly.graphics.lineTo(xCenter+(hexWidth*.25)+Math.sin(radians(210))*radius,offset+(radius-Math.cos(radians(210))*radius));
hexPoly.graphics.lineTo(xCenter+(hexWidth*.25)+Math.sin(radians(270))*radius,offset+(radius-Math.cos(radians(270))*radius));
hexPoly.graphics.endFill();
addChild(hexPoly);

Resources