Collision detection for Tiny Wings-esque Windows Phone game? - c#

I'm currently working on a Windows Phone game similar to Tiny Wings and I've been having trouble with collision detection between the player's character and the hills. I've been looking into a few different ways to do this including the Farseer Physics engine and a Silverlight tutorial
Player's character initialization
lander = new Lander(new Vector2(graphics.PreferredBackBufferWidth / 4, 100));
LoadContent
protected override void LoadContent()
{
// Create a new SpriteBatch, which can be used to draw textures.
spriteBatch = new SpriteBatch(GraphicsDevice);
primitiveBatch = new PrimitiveBatch(GraphicsDevice);
// Load textures
landerTexture = this.Content.Load<Texture2D>(".\\Sprites\\boysmall");
// Initialize lander based on texture
lander.Width = landerTexture.Width;
lander.Height = landerTexture.Height;
// Load the parallaxing background
bgLayer1.Initialize(Content, "hillsbackground", GraphicsDevice.Viewport.Width, -2, 150);
bgLayer2.Initialize(Content, "hillsbackground2", GraphicsDevice.Viewport.Width, -3, 220);
// Load hills
string[] hillsArray = new string[2]{"textured","hillsmooth"};
mainHill.Initialize(Content, hillsArray, GraphicsDevice.Viewport.Width, -4);
// Load Sky
mainBackground.Initialize(Content, "mainbackground", GraphicsDevice.Viewport.Width, -1, 0);
}
I understand that fundamentally, collision detection looks for intersection points between two rectangles, and have done that for the "lander", but don't know how I can do it for the hills and how to make it slide down smoothly? let me know if you need any additional code, thanks for your help!
Rectangle attempt for Lander
public Rectangle GetScreenRectangle()
{
// calculate the rectangle from the current location
// and the current source rectangle
var rectangle = new Rectangle(
(int)graphics.PreferredBackBufferWidth / 4,
(int)100,
lander.Width,
lander.Height);
return rectangle;
}
Hills Code
class MainHill
{
// The image representing the parallaxing background
Texture2D texture;
// An array of positions of the parallaxing background
//Vector2[] positions;
// The speed which the background is moving
int speed;
// Object array holding position and texture of each live texture
object[,] positionsArray = new object[2, 2];
public void Initialize(ContentManager content, Array hillsArray, int screenWidth, int speed)
{
// Load the background texture we will be using
//texture = content.Load<Texture2D>("textured");
// Set the speed of the background
this.speed = speed;
// If we divide the screen with the texture width then we can determine the number of tiles need.
// We add 1 to it so that we won't have a gap in the tiling
//positions = new Vector2[screenWidth / texture.Width + 2];
texture = content.Load<Texture2D>("textured");
// Set the initial positions of the parallaxing background
for (int i = 0; i < screenWidth / texture.Width + 2; i++)
{
//Pull out random texture
Random random = new Random();
string[] randomHill = new string[2];
randomHill[0] = "textured";
randomHill[1] = "hillsmooth";
string currentString = randomHill[(int)(random.Next(0, 2))];
texture = content.Load<Texture2D>(currentString);
// We need the tiles to be side by side to create a tiling effect
positionsArray[i,0] = new Vector2(i * texture.Width, 290);
positionsArray[i, 1] = texture;
}
}
public void Update(ContentManager content)
{
Debug.WriteLine("=========================");
// Update the positions of the background
for (int i = 0; i < positionsArray.GetLength(0); i++)
{
Vector2 current_position = (Vector2)positionsArray[i, 0];
// Update the position of the screen by adding the speed
current_position.X += speed;
// Check the texture is out of view then put that texture at the end of the screen
if (current_position.X <= -texture.Width)
{
// Figure out a possibly new texture if it's out of view
Random random = new Random();
string[] newHill = new string[2];
newHill[0] = "textured";
newHill[1] = "hillsmooth";
string currentString = newHill[(int)(random.Next(0, 2))];
texture = content.Load<Texture2D>(currentString);
Color[] textureData = new Color[texture.Width * texture.Height];
texture.GetData(textureData);
current_position.X = texture.Width * (positionsArray.GetLength(0) - 1);
positionsArray[i, 1] = texture;
}
positionsArray[i, 0] = current_position;
}
}
public void Draw(SpriteBatch spriteBatch, ContentManager content)
{
for (int i = 0; i < positionsArray.GetLength(0); i++)
{
Vector2 current_position = (Vector2)positionsArray[i, 0];
//Random random = new Random();
//string[] hillsArray = new string[2];
//hillsArray[0] = "textured";
//hillsArray[1] = "hillsmooth";
//string currentString = hillsArray[(int)(random.Next(0,2))];
//texture = content.Load<Texture2D>(currentString);
texture = (Texture2D)positionsArray[i, 1];
spriteBatch.Draw(texture, current_position, Color.White);
}
}
}

Related

How to slice sprite by script ?(not use Editor)

I trying to slice Sprite(type casted to Texture2D) by script,
when project is running on Android or IOS Platform
is it possible by script??
I trying to use UnityEditor Class and it is work on Computer
but When I trying to Build Android or IOS It is failed.
void OnPreprocessTexture()
{
TextureImporter textureImporter = (TextureImporter)assetImporter;
textureImporter.textureType = TextureImporterType.Sprite;
textureImporter.spriteImportMode = SpriteImportMode.Multiple;
textureImporter.mipmapEnabled = false;
textureImporter.filterMode = FilterMode.Point;
}
public void OnPostprocessTexture(Texture2D texture)
{
Debug.Log("Texture2D: (" + texture.width + "x" + texture.height + ")");
int spriteSize = 350;
int colCount = texture.width / spriteSize;
int rowCount = texture.height / spriteSize;
List<SpriteMetaData> metas = new List<SpriteMetaData>();
for (int r = 0; r < rowCount; ++r)
{
for (int c = 0; c < colCount; ++c)
{
SpriteMetaData meta = new SpriteMetaData();
meta.rect = new Rect(c * spriteSize, r * spriteSize, spriteSize, spriteSize);
meta.name = c + "-" + r;
metas.Add(meta);
}
}
TextureImporter textureImporter = (TextureImporter)assetImporter;
textureImporter.spritesheet = metas.ToArray();
}
public void OnPostprocessSprites(Texture2D texture, Sprite[] sprites)
{
Debug.Log("Sprites: " + sprites.Length);
}
It is not working When running project on Android or IOS
[What I want]
Procedure
During running on Android or IOS Platform
1) Receive some Images from server (Url or file)
2) Load Image on C# script
3) Change type Images to Texture or Sprite ect...
4) Slice Images(Don't use Editor)
5) Save Pieces of Image
6) Use piece of Image
What I want is all procedure worked by Script
TextureImporter belongs to the UnityEditor namespace which doesn't exist in a built app but only within the Unity Editor itself. → You can not use this!
What you can do is using Sprite.Create to generate a sprite from a given Texture2D.
Cropping
If it is actually only about cutting out a certain part of the texture to use it as sprite than you only need to define in the rect parameter the part of the texture you want to use from that image.
// Wherever you get the texture from
Texture texture = ...;
// E.g. for using the center of the image
// but half of the size
var rect = new Rect(texture.width / 4, texture.height / 4, texture.width / 2, texture.height / 2);
// Create the sprite
var sprite = Sprite.Create(texture, rect, Vector2.one * 0.5f);
where rect is the
Location of the Sprite on the original Texture, specified in pixels.
Slicing
If you additionally want a slicing border (which you usually define in the Sprite Editor within Unity) there is an overload of Sprite.Create that additionally takes a border parameter e.g.
var borders = new Vector4(2, 2, 2, 2);
var sprite = Sprite.Create(texture, rect, Vector2.one * 0.5f, 100, SpriteMeshType.FullRect, borders);
where border
Returns the border sizes of the sprite.
X=left, Y=bottom, Z=right, W=top.
API doesn't say it but I guess like the rect values those values are also in pixels.
I solved using rect and Sprite Rnederer
here is my code
void Start()
{
rect = new Rect(0f, 0f, 255, 255);
this.GetComponent<SpriteRenderer>().sprite = Sprite.Create(img, rect, new Vector2(0.5f, 0.5f));
this.GetComponent<RectTransform>().localScale = new Vector3(100, 100, 0);
StartCoroutine(Update());
}
/*
* rect = new Rect(i, 0, 255, 255);
this.GetComponent<SpriteRenderer>().sprite = Sprite.Create(img, rect, new Vector2(0.5f, 0.5f));*/
IEnumerator Update()
{
while (true)
{
if (i < 1000)
{
i += 255;
if (i > 770)
{
i = 0;
}
}
yield return new WaitForSeconds(0.25f);
rect = new Rect(i, 0f, 255, 255);
this.GetComponent<SpriteRenderer>().sprite = Sprite.Create(img, rect, new Vector2(0.5f, 0.5f));
}
}

Changing sprite texture pixels results in gigantic grey square

I have a 32x32 sprite that I am trying to access the pixel data of and modify.
To do this I am simply taking the sprite's texture, creating a new texture based on the old and then changing the pixel values of the new texture. I then create a new sprite with the modified texture and change the SpriteRenderer's sprite parameter to the new sprite.
However, when I actually run my script what I get is a huge grey square, easily 10x the size of the original 32x32 sprite. I'm very new to unity so I'm not sure why this is happening. Any insight would be great.
private Sprite sprite;
private Texture2D texture;
// Use this for initialization
void Start ()
{
sprite = this.gameObject.GetComponent<SpriteRenderer>().sprite;
texture = sprite.texture;
Texture2D newTexture = modifyTexture(texture);
SpriteRenderer sr = this.gameObject.GetComponent<SpriteRenderer>();
sr.sprite = Sprite.Create(newTexture, new Rect(0, 0, newTexture.width, newTexture.height), new Vector2(0, 0), 10);
}
public Texture2D modifyTexture(Texture2D baseTexture)
{
Texture2D newTexture = new Texture2D(baseTexture.width, baseTexture.height);
int x = 0;
while(x < newTexture.width)
{
int y = 0;
while(y < newTexture.height)
{
Color currentPixel = baseTexture.GetPixel(x,y);
Color modifiedPixel = currentPixel;
modifiedPixel.r = (float)(modifiedPixel.r + 0.10);
modifiedPixel.b = (float)(modifiedPixel.b + 0.10);
modifiedPixel.g = (float)(0.10);
newTexture.SetPixel(x, y, modifiedPixel);
y++;
}
x++;
}
Debug.Log(newTexture.GetPixel(5, 5).ToString());
return newTexture;
}
After modifying pixels of a Texture, you must call the Apply function upload the modified pixels to the graphics card.
public Texture2D modifyTexture(Texture2D baseTexture)
{
Texture2D newTexture = new Texture2D(baseTexture.width, baseTexture.height);
int x = 0;
while (x < newTexture.width)
{
int y = 0;
while (y < newTexture.height)
{
Color currentPixel = baseTexture.GetPixel(x, y);
Color modifiedPixel = currentPixel;
modifiedPixel.r = (float)(modifiedPixel.r + 0.10);
modifiedPixel.b = (float)(modifiedPixel.b + 0.10);
modifiedPixel.g = (float)(0.10);
newTexture.SetPixel(x, y, modifiedPixel);
y++;
}
x++;
}
//Upload changes to Graphics graphics card
newTexture.Apply();
Debug.Log(newTexture.GetPixel(5, 5).ToString());
return newTexture;
}

Split Texture using a Curved Line in Unity3D C#

I have a texture that I want to slice into 2 parts, using a Vector2 array.
I have all the Vector2 points for the curved line.
Question
How can I slice the texture into 2 parts using the curved line of points.
Alternative Solutions/Questions
How can I 'pixel' fill a Vector2[] shape to create a Texture?
My attempts
1) Generating Vector2 points to create a square, with the top part being the curve edge. Looked promising but when I tried generating a Mesh, the points sorting was incorrect.
2) Dynamically created a Polygon2D Collider - mimicking the bottom part of the sliced texture - this had the same issue as attempt 1, the point ordering. So when convert the Collider to Mesh, it obviously had the same results as attempt
In the picture below:
The red line simulates my Vector2 array
The gray+green square is the texture 1024 x 1024 pixels
The green area is the target area I want
This makes a mesh that is the shape you want (but with jagged edges on top), hopefully that is a step in the right direction. The Vector2 points[] array contains your red line. It should be sorted by the x coordinate, and all the numbers should be between 0 and 1. Needs a mesh filter and a mesh renderer with your texture.
using UnityEngine;
[RequireComponent(typeof(MeshFilter))]
[RequireComponent(typeof(MeshRenderer))]
public class createMesh : MonoBehaviour {
void Start () {
Vector2[] points = new Vector2[4];
points [0] = new Vector2 (0, .5f);
points [1] = new Vector2 (.33f, 1f);
points [2] = new Vector2 (.66f, .5f);
points [3] = new Vector2 (1, 1f);
MeshFilter mf = GetComponent<MeshFilter> ();
Mesh mesh = new Mesh();
Vector3[] verticies = new Vector3[points.Length * 2];
int[] triangles = new int[(points.Length - 1)*6];
Vector3[] normals = new Vector3[points.Length * 2];
Vector2[] uv = new Vector2[points.Length * 2];
int vIndex = 0;
int tIndex = 0;
int nIndex = 0;
int uvIndex = 0;
for (int i = 0; i< points.Length; i++) {
Vector3 topVert = points[i];
Vector3 bottomVert = topVert;
bottomVert.y = 0;
verticies[vIndex++]= bottomVert;
verticies[vIndex++]=topVert;
//uv
uv[uvIndex++] = bottomVert;
uv[uvIndex++] = topVert;
//normals
normals[nIndex++] = -Vector3.forward;
normals[nIndex++] = -Vector3.forward;
if (i<points.Length - 1) {
//triangles
triangles[tIndex++] = (i)*2;
triangles[tIndex++] = (i)*2+1;
triangles[tIndex++] = (i)*2+2;
triangles[tIndex++] = (i)*2+2;
triangles[tIndex++] = (i)*2+1;
triangles[tIndex++] = (i)*2+3;
}
}
mesh.vertices = verticies;
mesh.triangles = triangles;
mesh.normals = normals;
mesh.uv = uv;
mf.mesh = mesh;
}
}
Bonus: here's a way to do it just with the texture. To use this the bitmap has to be set to Advanced, with read/write enabled in the import settings. This method uses 0 to 1023 (or however large your texture is) for coordinates, and should work for numbers out of that range too.
using UnityEngine;
using System.Collections;
public class tex2d : MonoBehaviour {
public Vector2[] points;
void Start () {
MeshRenderer mr;
Texture2D t2d;
Texture2D newTex = new Texture2D (1024, 1024);
mr = GetComponent<MeshRenderer> ();
t2d = mr.material.GetTexture (0) as Texture2D;
MakeTex (points, t2d, ref newTex, 1024);
mr.material.SetTexture (0, newTex);
}
void MakeTex(Vector2[] pnts, Texture2D inputTex, ref Texture2D outputTex, int size){
Color bgcolor = new Color (1, 0, 1, 1);
for (int i=0; i<(pnts.Length-1); i++) {
Vector2 p1=pnts[i];
Vector2 p2=pnts[i+1];
//skip points that are out of range
if ((p1.x <0 && p2.x <0) || (p1.x > size && p2.x>size)) continue;
for (int x =(int)p1.x; x<(int)p2.x; x++) {
if (x<0) continue;
if (x>=size) break;
float interpX = (x-p1.x)/(p2.x-p1.x);
int interpY = (int) ((p2.y-p1.y)*interpX + p1.y);
for (int y=0; y<interpY; y++) {
outputTex.SetPixel(x,y,inputTex.GetPixel(x,y));
}
for (int y= interpY; y<size; y++) {
outputTex.SetPixel(x,y,bgcolor);
}
}
}
outputTex.Apply ();
}
}

XNA Drawing Terrain in the wrong places

I need to draw a terrain and have a camera with surfacefollow in XNA, but in some places it doesnt draw what is suposed to draw and draws the terrain behind it. Any suggestions of what it may be?
public void Draw()
{
camera.Effect.TextureEnabled = true;
camera.Effect.VertexColorEnabled = false;
camera.Effect.World = worldMatrix;
camera.Effect.Texture = texture;
camera.Effect.CurrentTechnique.Passes[0].Apply();
device.SetVertexBuffer(vertexBuffer);
device.Indices = indexBuffer;
for (int i = 1; i < (alturas.Height - 1); i++)
{
device.DrawIndexedPrimitives(PrimitiveType.TriangleStrip, 0, 0, heights.Width * 2, (heights.Width * 2) * i, (heights.Width * 2) - 2);
}
}
heights is the texture of the height map. The construction of the vertices is working fine.

Cropping texture2d on all sides in xna c#

i am trying to crop a texture2d in xna. i have found the following code which will crop the image on the top and right sides, i have played around with the code and cannot figure a way to crop all sides at a specific interval. below is the code i have been trying to modify:
any help or ideas would be much appreciated.
Rectangle area = new Rectangle(0, 0, 580, 480);
Texture2D cropped = new Texture2D(heightMap1.GraphicsDevice, area.Width, area.Height);
Color[] data = new Color[heightMap1.Width * heightMap1.Height];
Color[] cropData = new Color[cropped.Width * cropped.Height];
heightMap1.GetData(data);
int index = 0;
for (int y = 0; y < area.Y + area.Height; y++) // for each row
{
for (int x = 0; x < area.X + area.Width; x++) // for each column
{
cropData[index] = data[x + (y * heightMap1.Width)];
index++;
}
}
cropped.SetData(cropData);
Here is the code to crop a texture. Note that the GetData method can already select rectangular subsection of the image - there is no need to manually crop.
// Get your texture
Texture2D texture = Content.Load<Texture2D>("myTexture");
// Calculate the cropped boundary
Rectangle newBounds = texture.Bounds;
const int resizeBy = 20;
newBounds.X += resizeBy;
newBounds.Y += resizeBy;
newBounds.Width -= resizeBy * 2;
newBounds.Height -= resizeBy * 2;
// Create a new texture of the desired size
Texture2D croppedTexture = new Texture2D(GraphicsDevice, newBounds.Width, newBounds.Height);
// Copy the data from the cropped region into a buffer, then into the new texture
Color[] data = new Color[newBounds.Width * newBounds.Height];
texture.GetData(0, newBounds, data, 0, newBounds.Width * newBounds.Height);
croppedTexture.SetData(data);
Of course, keep in mind that SpriteBatch.Draw can take a sourceRectangle parameter, so you may not even need to copy the texture data around at all! Just use a subsection of the original texture. For example:
spriteBatch.Draw(texture, Vector2.Zero, newBounds, Color.White);
(Where newBounds is calculated in the same way as in the first code listing.)

Categories

Resources