Create images using shapes - c#

Im trying to create a drag and drop module which can be used to build an Image.
EX: Using a triangle and rectangles to create a House.
I have created the drag and drop module but I cant make them fix with each other.
It will be a great help if someone can give me an idea or a sample code for this problem.
Please help me in this.
I'll explain the functionality a little bit, but forgive my English if any mistakes since it's not my native language.
The user is given a set of shapes and a question like "CREATE A HOUSE" so he should be able to drag the shapes that is
given and and build the house.
Thanks in Advance.

if you want to snap the house pieces to grid let's say 50 pixels put these equations
inside mouse up event
box.x = Math.floor(mouseX/50)*50;
box.y = Math.floor(mouseY/50)*50;
box.addEventListener(MouseEvent.MOUSE_UP,mUp)
function mUp(e:MouseEvent)
{
box.stopDrag();
box.x = Math.floor(mouseX/50)*50;
box.y = Math.floor(mouseY/50)*50;
}
that will fit the pieces together

Use this as a base class for your drag-able objects:
package
{
import flash.display.Sprite;
import flash.events.MouseEvent;
public class Dragable extends Sprite
{
// vars
private const SNAP:uint = 40;
/**
* Constructor
*/
public function Dragable()
{
addEventListener(MouseEvent.MOUSE_DOWN, _drag);
addEventListener(MouseEvent.MOUSE_UP, _drop);
}
/**
* MOUSE_DOWN
*/
private function _drag(e:MouseEvent):void
{
startDrag();
}
/**
* MOUSE_UP
*/
private function _drop(e:MouseEvent):void
{
stopDrag();
x = Math.round(x / SNAP) * SNAP;
y = Math.round(y / SNAP) * SNAP;
}
}
}
Modify SNAP to meet your requirements.

For something like this (ignoring the dragging and dropping, which you've got some good examples for here), you set all this up previously.
Say your goal is to build a house. Here, you'd assemble the pieces beforehand and save out the final position and rotation in an xml or something similar. When you drag the pieces in the game, you just need to check if it's close enough to the final position and if it is, just snap it to the final position. You can work in rotation easily enough (though I'd keep the angles to 45 degrees for simplicitly).
As an idea for position:
private var m_finalPos:Point = new Point( 10.0, 10.0 );
private var m_snapDist:Number = 100.0;
private function _onDrop( e:MouseEvent ):void
{
// get the distance squared (quicker, and we don't really care about the distance)
var diffX:Number = this.m_finalPos.x - this.x;
var diffY:Number = this.m_finalPos.y - this.y;
var distSq:Number = ( diffX * diffX ) + ( diffY * diffY );
// if we're close enough, snap to the final position
if( distSq < this.m_snapDist )
{
this.x = this.m_finalPos.x;
this.y = this.m_finalPos.y;
}
}
Lower the snapDist to make it harder.

Related

Zoom In & Zoom Out in Unity

So, Hey guys. Im new to Unity and Im trying a very simple code that allows the player to Zoom-in & Zoom-Out. Here's the code of it:
[Header("Vertical Zooming")]
[SerializeField] private float zoomSpeed;
private void Update()
{
VerticalZooming();
}
private void VerticalZooming()
{
Vector3 initialPosition = new Vector3();
// bool canMove = false;
if (Input.GetMouseButtonDown(0))
{
initialPosition = mCamRef.ScreenToViewportPoint(Input.mousePosition);
Debug.Log(initialPosition.y);
}
if (Input.GetMouseButton(0))
{
Vector3 newPosition = mCamRef.ScreenToViewportPoint(Input.mousePosition);
Debug.Log("newPosition" + newPosition.y);
if (newPosition.y < initialPosition.y)
{
Zoom((zoomSpeed * Time.deltaTime) * -1f);
}
if (newPosition.y > initialPosition.y)
{
Zoom(zoomSpeed * Time.deltaTime);
}
intialPosition = newPosition;
}
}
private void Zoom(float inZoomSpeed)
{
transform.Translate(mCamRef.transform.position.z * inZoomSpeed * transform.forward);
}
So, if you see the code above. On mousebuttondown we note down the initial position and on holding the mouse button we keep track of new position constantly.. What i want is pretty simple. With reference to my initial mouse click im checking if my new position is greater in y is yes i need to zoom out. If new position is lower than initial position in y-axis. Them, i need to zoom in. Which I did, But for some reason its not working.
Two problems here:
Though if there is no change to newposition i.e., even if both my newposition variable and initial position variable are in same spot my camera moves(Zoom-out in my case) which shouldn't happen. It should only happen if my newPosition.y variable is greater that that of initialposition.y. I'm not able to figure out why this is happening. I tried using bool conditions to do this, but failed.
If i play test this in my mobile.. Its only going on one direction. in my case its only zooming out continously though my zoom-in if-condition meets. But when playtesting in unity game window. The zoom in works when my mouse is out of the game-screen. Because its only working outside the game screen.This is the reason its not working in mobile as there is no space outside mobile display. Which i dont know why this is happening or dont know how to overcome this.
Let me know why! Im stuck at it for a long time and not getting any idea. Thanks <3
If Any doubt in question let me know. Sorry for a huge explanation. Just wanted to be very precise on the question.
I have seen people suggesting zoom in zoom out through using FOV. But i wanna do it using translate or move the camera itself.
So your problem here is on taking count on the screenToViewPort point.
Instead just try this..
if (Input.GetMouseButtonDown(0))
{
mInitialPosition = Input.mousePosition.y;
}
if (Input.GetMouseButton(0))
{
mChangedPosition = Input.mousePosition.y;
if (mChangedPosition == mInitialPosition)
{
return;
}
if (mChangedPosition < mInitialPosition)
{
Zoom((mZoomSpeed * -1f) * Time.deltaTime);
}
if (mChangedPosition > mInitialPosition)
{
Zoom(mZoomSpeed * Time.deltaTime);
}
}
private void Zoom(float inZoomSpeed)
{
transform.Translate(mCamRef.transform.position.z * inZoomSpeed * transform.forward);
}
Not sure how ScreenToViewport point works... But I guess this code should do the magic for you... Here I'm just straight away taking the mouse.y value on click and hold and did the same functions as you did and also telling it not to do anything when both the y values are same and return the function... So meaning that you already had everything in your code itself... Have a nice day

SkiaSharp Touch Bitmap Image

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.

Looking for ways to optimize multi poly-lines on canvas in wpf

I'm working on program in WPF that need to plot on one of her screens 50 poly-lines that describes movement of some energy in space. One more demand from the program is to move two lines and a dot to indicate the mouse location when its relevant.
The problem is that when the poly-lines cover a high percent of the canvas and the mouse is fly over the canvas then all start to run really slowly.
I succeeded to improve this a little but its still not good enough so I'm asking for your help please.
So because this canvas related to another one, I spited the work for two - the handler and the movement function:
private void rayTraceCanvas_MouseMove(object sender, MouseEventArgs e)
{
System.Windows.Point pos = e.GetPosition(rayTraceCanvas);
mouseMove(pos);
if (m_MouseMoveCallback != null)
m_MouseMoveCallback(m_CurrentDepth);
}
And then the movement function:
private void mouseMove(Point currentPos)
{
m_CurrentDepth = Math.Round((currentPos.Y) / (m_PixelPerDepthUnit));
m_CurrentRange = Math.Round((currentPos.X) / (m_PixelPerRangeUnit));
DepthPos.Text = "D: " + m_CurrentDepth.ToString();
RangePos.Text = "R: " + m_CurrentRange.ToString();
rayTraceWidthLine.Y1 = currentPos.Y;
rayTraceWidthLine.Y2 = currentPos.Y;
rayTraceHeightLine.X1 = currentPos.X;
rayTraceHeightLine.X2 = currentPos.X;
Canvas.SetLeft(rayTraceDotOnGraph, currentPos.X - (rayTraceDotOnGraph.Width / 2));
Canvas.SetTop(rayTraceDotOnGraph, currentPos.Y - (rayTraceDotOnGraph.Height / 2));
}
I tried this without the deleget from the handler function and its work the same so the problem isn't there.

How to draw a 2D graph on Canvas in Unity 5

I need to draw a graph for my decibel app that I am making with Unity. The solution below works but is not as exact as my employer would like. Could I make this graph look more professional and exact? Basically I want the lines to be of equal width and prevent the line from going almost invisible like in the following pic: http://puu.sh/qjSvO/a51c11cef5.png
I was thinking about making a 2D texture and using SetPixel, but I am not sure if that is the correct way.
The graph is drawn on a canvas as part of an scalable UI.
public class Graph : MonoBehaviour {
public float graphWidth;
public float graphHeight;
LineRenderer newLineRenderer;
List<int> decibels;
int vertexAmount = 50;
float xInterval;
GameObject parentCanvas;
// Use this for initialization
void Start ()
{
parentCanvas = GameObject.Find("Canvas");
graphWidth = transform.Find("Linerenderer").GetComponent<RectTransform>().rect.width;
graphHeight = transform.Find("Linerenderer").GetComponent<RectTransform>().rect.height;
newLineRenderer = GetComponentInChildren<LineRenderer>();
newLineRenderer.SetVertexCount(vertexAmount);
xInterval = graphWidth / vertexAmount;
}
//Display 1 minute of data or as much as there is.
public void Draw(List<int> decibels)
{
if (decibels.Count == 0)
return;
float x = 0;
for (int i = 0; i < vertexAmount && i < decibels.Count; i++)
{
int _index = decibels.Count - i - 1;
float y = decibels[_index] * (graphHeight/130); //(Divide grapheight with the maximum value of decibels.
x = i * xInterval;
newLineRenderer.SetPosition(i, new Vector3(x - graphWidth / 2 , y - graphHeight / 2 , 0));
}
}
}
Using the editor, you can "cut" sprites into nine pieces, so that there is a texture for each side, a texture for each corner and a texture to fill it in. I would recommend using that to make it look good if you want it so. It is some time since i used it myself, but maybe you can find information on the Unity manual.

mono c# CairoHelper.Translate

using Cairo;
I have drawn a rectangle inside a bigger rectangle witch is inside a drawing area.
I have managed to attach a event to the Drawing area witch is a object I have extended from it
this.AddEvents ((int) EventMask.ButtonPressMask);
this.ButtonPressEvent += delegate(object o, ButtonPressEventArgs args) {
hasInterface(args.Event.X, args.Event.Y);
Console.WriteLine("Button Pressed " + args.Event.X + ", " + args.Event.Y);
};
I'm dynamically drawing the squares using:
cr.Translate(width/2, height/2);
cr.Rectangle((pX + (i * tmp)) , pY, boxsize, boxsize);
private void recordPosition(double x, double y)
{
x = x*2;
y = y*2;
boxCoordinates.Add( new double[,]
{
{x, y}
}
); // store coords
}
List<double,double> boxCoordinates
So for the inside of the drawing area the square is drawn at x=0, y=0 from the "outside" point of view it's in x=90, y=45; the width = 180 , height = 100
I was using translate (since half of this is copied ) of the size/2 so this means that the drawing area was doing a resize of the square, to solve this issue I was saving the position's multiplying it by 2, but this is not working has I'm getting "hits" outside of the rectangle drawn.
What is the best way to do this? I mean to translate the X Y positions from the window to the drawing area, I saw this was possible in other languages but not sure how to do it in C# and the drawing area from mono.
Thanks for any help.
I've done this a few times in C w SDL and C# with Cairo, basically, you want to be able to convert the bounding box of each of your rectangles to and from the coordinates you are using for rendering on the cairo canvas.
For each of your rectangles, you'll have the location you of your rectangles in thier own world. I like to call these the "world coordinates" and their "screen coordinates" (which map to where your mouse will be).
You can store the world coordinates of each box and then translate them to screen ones for each frame you render.
public class Shape {
public Point WorldLoc { get; set; }
}
You would do all your physics (if you have any) on the WorldLoc values. When you come to render, You want to be able to convert your WorldLoc to ScreenLoc.
public class Scene {
public double Zoom;
public Point Offset;
public Point WorldToScreen( Point world ){
var p = new Point();
p.x = (world.x - Offset.x) * Zoom;
p.y = (world.y - Offset.y) * Zoom;
return p;
}
}
Each time you render somthing in this Scene, you'll use WorldToScreen() to get the screen coordinates. You can then use the same thing to work out if your mouse is in the screen box of a world box.

Categories