I'm developing controls for a mobile platform; my GUI takes up the left, center, and right thirds of the screen. When the player wants to jump, they press the center button. My problem is that it seems that only one GUI element is being allowed to be pressed at once (like the device has only one mouse cursor that moves) rather than me being allowed to jump and go right at the same time. My code:
// JavaScript
#pragma strict
static var guiLeft : int = 0;
static var guiRight : int = 0;
static var guiJump : int = 0;
function OnGUI () {
// leftarrow
if (GUI.RepeatButton (Rect (0,0,Screen.width/3,Screen.height), "", GUIStyle.none)) {
guiLeft = 1;
}
else{
guiLeft = 0;
}
// right
if (GUI.RepeatButton (Rect (Screen.width-Screen.width/3,0,Screen.width/3,Screen.height), "", GUIStyle.none)) {
guiRight = 1;
}
else{
guiRight = 0;
}
// jump
if (GUI.RepeatButton (Rect (Screen.width/3,0,(Screen.width/3)+2,Screen.height), "", GUIStyle.none)) {
guiJump = 1;
}
else{
guiJump = 0;
}
}
The Unity GUI only supports one inputsource at a time (for example the left mouse button, or the right mouse button). The correct way to tackle your problem would be to use Input.touches. That'd indeed mean you'll have to change a lot of things in your game.
Related
I created a puzzle where you can drag and drop 16 pieces. I used an array so that the code doesn't get too big. Now I want to add an function where each puzzle piece snaps into right place once you get near the destination.
My problem is that I don't know how to create an array which can achieve my goal. I tried the following(without an array but that creates too much code if I do it with all 16 puzzle pieces):
if(target1_mc.hitTestObject(piece1_mc.tar1_mc))
{
piece1_mc.x = 207,15;
piece1_mc.y = 119,25;
}
Code:
import flash.events.Event;
import flash.events.MouseEvent;
var puzzleArr:Array = new Array (piece1_mc, piece2_mc, piece3_mc, piece4_mc,
piece5_mc, piece6_mc, piece7_mc, piece8_mc,
piece9_mc, piece10_mc,
piece11_mc, piece12_mc, piece13_mc, piece14_mc, piece15_mc, piece16_mc);
for (var i:uint =0; i < puzzleArr.length; i++) {
puzzleArr[i].addEventListener(MouseEvent.MOUSE_DOWN, drag);
puzzleArr[i].addEventListener(MouseEvent.MOUSE_UP, drop);
}
function drag(event:MouseEvent):void {
event.currentTarget.startDrag();
}
function drop(event:MouseEvent):void {
event.currentTarget.stopDrag();
}
There a few ways to accomplish this. The easiest, is to add a dynamic property to your pieces that stores the target (correct location object) for the piece.
var puzzleArr:Array = []; //you don't really even need the array in my example
var tmpPiece:MovieClip; //this stores the current dragging piece, and I also reuse it in the loop below
//I don't like typing a lot, so let's use a loop for all 16 pieces and their targets
for(var i:int=1;i<=16;i++){
tmpPiece = this["piece" + i + "_mc"]; //get a reference to piece whose number matches i
if(!tmpPiece){
trace("Sorry - there is no piece called: 'piece" + i + "_mc'");
continue;
}
//give the piece a dynamic property that is a reference to it's target spot
tmpPiece.targetTile = this["target" + i + "_mc"];
if(!tmpPiece.targetTile){
trace("Sorry - there is no target called: 'target" + i + "_mc'");
continue;
}
tmpPiece.tar_mc = tmpPiece["tar" + i + "_mc"]; //it would be better to just take the number out of each pieces tar_mc child object making this line uneccessary
//track where the piece is placed
tmpPiece.startingPos = new Point(tmpPiece.x, tmpPiece.y);
//only add the mouse down listener to the piece (not mouse up)
tmpPiece.addEventListener(MouseEvent.MOUSE_DOWN, drag);
//if still using the array, add the piece to the array
puzzleArr.push(tmpPiece);
}
Next, add a mouse move listener only while dragging
function drag(event:MouseEvent):void {
tmpPiece = event.currentTarget as MovieClip; //assign the dragging object to the tmpPiece var
tmpPiece.startDrag();
//add a mouse move listener so you can check if snapping is needed
tmpPiece.addEventListener(MouseEvent.MOUSE_MOVE, moving);
//add the mouse up listener to the stage - this is good because if you drag fast, the mouse can leave the object your dragging, and if you release the mouse then it won't trigger a mouse up on the dragging object
stage.addEventListener(MouseEvent.MOUSE_UP, drop);
}
function drop(event:MouseEvent):void {
//stop all dragging
this.stopDrag();
if(tmpPiece){
//remove the mouse move listener
tmpPiece.removeEventListener(MouseEvent.MOUSE_MOVE, moving);
//ensure a snap at the end of the drag
if(!checkSnapping()){
//if not snapped, reset it's position
tmpPiece.x = tmpPiece.startingPos.x;
tmpPiece.y = tmpPiece.startingPos.y;
}
}
//remove the mouse up listener
stage.removeEventListener(MouseEvent.MOUSE_UP, drop);
}
Now lets do the snapping in the mouse move handler:
function moving(e:MouseEvent = null):void {
checkSnapping();
}
//return true if snapped
function checkSnapping():Boolean {
if(tmpPiece && tmpPiece.tar_mc.hitTestObject(tmpPiece.targetTile)){
tmpPiece.x = tmpPiece.targetObj.x - tmpPiece.tar_mc.x;
tmpPiece.y = tmpPiece.targetObj.y - tmpPiece.tar_mc.y;
return true;
}
return false;
}
for (var i:int = 0; i < puzzleArray.length; i++)
{
if(puzzleArray[i].hitTestObject(puzzleArray[i]._target))
{
puzzleArray[i].x = puzzleArray[i]._xGoal;
puzzleArray[i].y = puzzleArray[i]._yGoal;
}
}
Obviously you'll need to add a couple of properties to the puzzle piece objects (_xGoal, _yGoal,_target) and you can do that however you'd like. You could probably use a loop, but only if there is some sort of order to them. If they are not of equal size and in a grid, then you'll have to obviously just manually type these in.
If they are in a grid and each piece is equal size, let me know if you need help with creating those properties in a loop.
Hello Stackoverflowers!
I have a strange situation here. I wrote a small C# tool, to measure the time it takes to send a request via usb and wait until the response arrives. The communication is no problem, nor are the devices.
I put a simple TextBox on the GUI together with a "Start" button.
Pressing "Start" starts a thread with a loop (loops defined in the TextBox) sending requests and receiving the answers. In the GUI thread you can see a progress bar showing the status.
When I pressed "Start" I measured around 15 ms per command and response (in average) which is quite a long time.
When I pressed "Start" and clicked inside the TextBox (only setting the cursor inside), the worker thread ran through with an average time of 1.6 ms per command and response.
This is reproducible in my case. I even put in a new, totally useless TextBox. When clicking inside, the thread speeds up, when I focus another element, like a slider, the thread slows down again.
Has anyone ever heard about something like that and can explain to me, why this happens? And even better, how I can avoid this behavior?
FYI:
- I tried both BackgroundWorker and Thread, same behavior.
- For taking the times, I'm using .NET's stopwatch.
- Executing the measurement method in the GUI thread changes nothing. EDIT: Tried again and everything's as it should be. But now I have the problem, that the GUI freezes, since I'm working in its thread.
- Removing the progress bar changes nothing.
Thanks a lot!
EDIT:
private void tbAmount_Copy_PreviewKeyUp(object sender, KeyEventArgs e)
{
if (e.Key == Key.Enter)
{
if (String.IsNullOrEmpty(tbDevAddrTime.Text))
return;
pbTimeMeasure.Value = 0;
worker = new BackgroundWorker();
worker.DoWork += new DoWorkEventHandler(StartTimeMeasureHandler);
worker.RunWorkerAsync();
}
}
private void StartTimeMeasure()
{
int address = 1;
int loops = 1;
DispatchIfNecessary(() =>
{
address = Convert.ToInt32(tbDevAddrTime.Text);
loops = Convert.ToInt32(tbAmount_Copy.Text);
pbTimeMeasure.Maximum = loops;
});
System.Diagnostics.Stopwatch stopwatchLong = new System.Diagnostics.Stopwatch();
System.Diagnostics.Stopwatch stopwatchShort = new System.Diagnostics.Stopwatch();
var cmd = String.Format(":{0:X3}4010200300000000\r", RequestAddress + address);
for (int i = 0; i < loops; i++)
{
stopwatchLong.Start();
//SND
_canbus.Write(cmd, cmd.Length, ref _bytesWritten);
stopwatchShort.Start();
Thread.Sleep(1);
//RCV
var answer = ReadContent();
stopwatchShort.Stop();
stopwatchLong.Stop();
DispatchIfNecessary(() =>
{
pbTimeMeasure.Value++;
});
}
Double resLong = Convert.ToDouble(stopwatchLong.ElapsedMilliseconds);
Double resLongAvg = resLong / loops;
Double resShort = Convert.ToDouble(stopwatchShort.ElapsedMilliseconds);
Double resShortAvg = resShort / loops;
DispatchIfNecessary(() =>
{
lbTotalResLong.Content = resLong.ToString();
lbTotalResShort.Content = resShort.ToString();
int length = 5;
if (resLongAvg.ToString().Length < 5)
{
length = resLong.ToString().Length;
}
if (resShortAvg.ToString().Length < length)
{
length = resShortAvg.ToString().Length;
}
lbAvgResLong.Content = resLongAvg.ToString().Substring(0,length);
lbAvgResShort.Content = resShortAvg.ToString().Substring(0,length);
});
}
As the title suggests, I want to get a mouse over event at the corners of desktop. I tried to do it by getting the position of the mouse and polling it continuously to check if it is one of the edge coordinated and then trigger the event but I think thats bad way to do it. I tried to use the library MouseKeyHook but it wasn't useful for me to generate the necessary event.
Is there any better way to get mouse over events to the corners of the screen ?
I tried to improve the code by adding the following, but for some reason the mouse over to the corners isn't triggering the action.
public async void callMainLoop() {
var slowTask = Task<Boolean>.Factory.StartNew(() => mainMethodLoop(GetMousePosition()));
await slowTask;
}
public bool mainMethodLoop(Point point) {
while (true) {
double xRes = System.Windows.SystemParameters.PrimaryScreenWidth - 1;
double yRes = System.Windows.SystemParameters.PrimaryScreenHeight - 1;
if (point.X == 0 && point.Y == 0) {
if (comboBox0.SelectedItem != null) {
executeAction(comboBox0.SelectedItem.ToString());
return true;
}
}
return false;
}
}
I am not calling this in the constructor, there ins't any freezing now.
I don't know if it is even possible, but maybe someone found a way to do this...
I have a tab control to which I allow the user to add tabs with a button click.
I want to show some icons on the tab so I added an ImageList, but I can show only one icon at a time, and I need to show at least 3 icons together.
I thought about having an image of 3 icons together, but the icons are shown after some actions the use do. For example: at first I show icon_1 and if the user clicks some where I add icon_2 etc...
Can someone come up with a way to do this ?
Thank you very much in advance...
No. It's not possible. Using the standard WinForms TabControl component you only can show one image at the same time.
The solution here, is using overlay icons. You have a base icon, and you add decorators. This is how Tortoise SVN, for example,
The following code builds an overlayed image in C#:
private static object mOverlayLock = new object();
public static Image GetOverlayedImage(Image baseImage, Image overlay)
{
Image im = null;
lock (mOverlayLock)
{
try
{
im = baseImage.Clone() as Image;
Graphics g = Graphics.FromImage(im);
g.DrawImage(overlay, 0, 0, im.Width, im.Height);
g.Dispose();
}
catch
{
// log your exception here
}
}
return im;
}
NOTE: The overlayed image must have the same size than the base image. It must have transparent color, and the decorator in the overlayed image must be placed in the right place, for example bottom-right or top-right.
I found this code:
private Bitmap CombineImages(params Image[] images)
{
int width = 0;
for (int i = 0; i < images.Length; i++)
width += images[i].Width + 3;
int height = 0;
for (int i = 0; i < images.Length; i++)
{
if (images[i].Height > height)
height = images[i].Height;
}
int nIndex = 0;
Bitmap fullImage = new Bitmap(width, height);
Graphics g = Graphics.FromImage(fullImage);
g.Clear(SystemColors.AppWorkspace);
foreach (Image img in images)
{
if (nIndex == 0)
{
g.DrawImage(img, new Point(0, 0));
nIndex++;
width = img.Width;
}
else
{
g.DrawImage(img, new Point(width, 0));
width += img.Width;
}
}
return fullImage;
//img3.Save(finalImage, System.Drawing.Imaging.ImageFormat.Jpeg);
//img3.Dispose();
//imageLocation.Image = Image.FromFile(finalImage);
}
from this link http://www.codeproject.com/Articles/502249/Combineplusseveralplusimagesplustoplusformplusaplu
I am looking for a way to make a type of import button where users can import their music from their folder. I've got no idea on how to do this so any tips would be grateful.
Here is something to get you going:
float buttonX;
float buttonY;
float buttonW;
float buttonH;
void setup() {
textSize(24);
frame.setResizable(false);
background(255);
size(600, 200);
fill(0);
stroke(0);
noFill();
buttonW = 200;
buttonH = 50;
buttonX = width - width/2 - buttonW/2;
buttonY = height/2 - buttonH/2;
}
void draw() {
background(255);
fill(0);
rectMode(CORNER);
rect(buttonX, buttonY, buttonW, buttonH);
fill(255);
textAlign(LEFT);
text("Import File", buttonX+35, buttonY+30);
}
void mouseClicked() {
if (mouseX>buttonX && mouseX < buttonX+buttonW && mouseY > buttonY && mouseY < buttonY+buttonH) {
selectInput("Import music file", "fileSelected");
}
}
/* Taken from Processing.org */
void fileSelected(File selection) {
if (selection == null) {
println("Window was closed or user hit cancel");
} else {
println("User selected " + selection.getAbsolutePath());
}
}
Notice some things here. The button is simply a rect that is drawn on the screen and then the click is bound within the limit of the rect, which in effect creates a button. I am showing this here so you can understand that you can create a GUI with the simplest and the most basic objects available to you in Processing. This is a very simple sketch that doesn't do anything other than give you a file browser (check Processing docs for that) and prints the path of the file you choose or writes out a message if you hit cancel. What you do with this is up to you. Have fun with it.
Once you're done playing around and want to see what others have done and what some of the GUIs made by others look like, go to this page and check out the GUI section: http://www.processing.org/reference/libraries/ (this is only to see how they've implemented their buttons, not for the file browser).