I have the below code that creates a delay in-between drawing characters from a string, this works using println() however does not work when using the text() function. The code is supposed to wait an allotted time then print the next character, I'm really not sure what I'm doing wrong.
int startTimer;
int waitTime = 500;
boolean funcRun = true;
void setup(){
size(500, 500);
startTimer = millis();
}
void draw(){
while(funcRun){
textAnim("hello");
}
}
void textAnim(String textInput){
int counter = 0;
int x = 10;
while(counter < textInput.length()){
if(millis() - startTimer>waitTime){
text(textInput.charAt(counter), x , 100);
startTimer = millis();
++counter;
x = x + 10;
}
funcRun = false;
}
}
The displayed screen is updated at the end of the draw() function. So your while loop is fully executed and the completed text is shown. You'll have to modify the code such that it will constantly refresh/redraw the screen, and updates the displayed text based on the time loop.
For example like this:
int currentTime;
int waitTime = 500;
int characters_to_display = 0;
boolean stringComplete = false;
String textInput = "Hello";
void setup() {
size(500, 500);
currentTime = millis();
}
void draw() {
// Update text to be shown. increaseCharIndex() is called while the text is not yet fully displayed
if (stringComplete == false) {
increaseCharIndex();
}
//Draw screen:
// draw background to clear screen
background(0);
// display (a substring of) the text
text(textInput.substring(0, characters_to_display), 10, 100);
}
void increaseCharIndex() {
// if the waitperiod has passed, increase the number of characters to be displayed
if (millis() - currentTime>waitTime) {
currentTime = millis();
characters_to_display++;
}
// if the full text will be shown, end the call to increaseCharIndex()
if (characters_to_display >= textInput.length())
{
stringComplete = true;
}
}
Related
I made a test game in unity that makes it so when I click on a button, it spawns a cylinder created from a factory class. I'm trying to make it so when I create the cylinder, its height shrinks over the next 20 seconds. Some methods I found are difficult to translate into what I'm doing. If you could lead me to the right direction, I'd very much appreciate it.
Here's my code for the cylinder class
public class Cylinder : Shape
{
public Cylinder()
{
GameObject cylinder = GameObject.CreatePrimitive(PrimitiveType.Cylinder);
cylinder.transform.position = new Vector3(3, 0, 0);
cylinder.transform.localScale = new Vector3(1.0f, Random.Range(1, 2)-1*Time.deltaTime, 1.0f);
cylinder.GetComponent<MeshRenderer>().material.color = Random.ColorHSV();
Destroy(cylinder, 30.0f);
}
}
This can be done with the Time.deltaTime and Vector3.Lerp in a coroutine function. Similar to Rotate GameObject over time and Move GameObject over time questions. Modified it a little bit to do just this.
bool isScaling = false;
IEnumerator scaleOverTime(Transform objectToScale, Vector3 toScale, float duration)
{
//Make sure there is only one instance of this function running
if (isScaling)
{
yield break; ///exit if this is still running
}
isScaling = true;
float counter = 0;
//Get the current scale of the object to be moved
Vector3 startScaleSize = objectToScale.localScale;
while (counter < duration)
{
counter += Time.deltaTime;
objectToScale.localScale = Vector3.Lerp(startScaleSize, toScale, counter / duration);
yield return null;
}
isScaling = false;
}
USAGE:
Will scale GameObject within 20 seconds:
StartCoroutine(scaleOverTime(cylinder.transform, new Vector3(0, 0, 90), 20f));
Check out Lerp. A general example of how to use it would be something like this:
float t = 0;
Update()
{
t += Time.deltaTime;
cylinder.localScale = new Vector3(1, Mathf.Lerp(2f, 1f, t/3f), 1); // shrink from 2 to 1 over 3 seconds;
}
You will create a new monobehaviour script and add it to your primitive. Then you wil use "Update" method of monobehaviour (or use coroutine) for change object over time.
Monobehaviour must be look like this:
public class ShrinkBehaviour : MonoBehaviour
{
bool isNeedToShrink;
Config currentConfig;
float startTime;
float totalDistance;
public void StartShrink(Config config)
{
startTime = Time.time;
currentConfig = config;
totalDistance = Vector3.Distance(currentConfig.startSize, currentConfig.destinationSize);
isNeedToShrink = true;
transform.localScale = config.startSize;
}
private void Update()
{
if (isNeedToShrink)
{
var nextSize = GetNextSize(currentConfig);
if (Vector3.Distance(nextSize, currentConfig.destinationSize) <= 0.05f)
{
isNeedToShrink = false;
return;
}
transform.localScale = nextSize;
}
}
Vector3 GetNextSize(Config config)
{
float timeCovered = (Time.time - startTime) / config.duration;
var result = Vector3.Lerp(config.startSize, config.destinationSize, timeCovered);
return result;
}
public struct Config
{
public float duration;
public Vector3 startSize;
public Vector3 destinationSize;
}
}
For using this, you must do next:
public Cylinder()
{
GameObject cylinder = GameObject.CreatePrimitive(PrimitiveType.Cylinder);
var shrink = cylinder.AddComponent<ShrinkBehaviour>();
shrink.StartShrink(new ShrinkBehaviour.Config() { startSize = Vector3.one * 10, destinationSize = Vector3.one * 1, duration = 20f });
cylinder.transform.position = new Vector3(3, 0, 0);
cylinder.GetComponent<MeshRenderer>().material.color = Random.ColorHSV();
Destroy(cylinder, 30.0f);
}
You must remember, monobehaviour-script must be in separate file, and must have name similar to monobehaviour-class name. For example, ShrinkBehaviour.cs;
I am using below code to create tooltips.
m_ctrlToolTip.Create(this, TTS_ALWAYSTIP|TTS_BALLOON);
m_ti.cbSize = sizeof(TOOLINFO);
m_ti.uFlags = TTF_IDISHWND|TTF_TRACK|TTF_TRANSPARENT|TTF_ABSOLUTE;
m_ti.hwnd = m_hWnd;
m_ti.hinst = NULL;
m_ti.uId = (UINT)1;
m_ti.lpszText = "";;
m_ti.rect=CRect(0,0,0,0);
m_ctrlToolTip.SetMaxTipWidth(SHRT_MAX);
m_ctrlToolTip.SetDelayTime(TTDT_AUTOPOP,5000);
m_ctrlToolTip.Activate(TRUE);
void CLadIOView::OnMouseMove(UINT nFlags, CPoint point)
{
static CPoint prevPoint =0;
static CLadRemoteIOModule* pLastIO=NULL;
CLadRemoteIOModule* pLastIO1=pLastIO;
pLastIO=NULL;
bool bToolTipSet = false;
// Go thru each module already added
POSITION pos = gobjEztouchApp.m_objLadderLogic.m_objSysAttr.m_objRemoteIOModuleLst.GetHeadPosition();
for( ; pos != NULL; )
{
CLadRemoteIOModule* pIO = gobjEztouchApp.m_objLadderLogic.m_objSysAttr.m_objRemoteIOModuleLst.GetNext(pos);
// Get the rectangle for the module
CRect rectModule = GetIOModuleRect(pIO->m_nModulePosition);
if(!rectModule.PtInRect(pt)) continue;
pLastIO=pIO;
if(pLastIO1==pIO) break;
if(!m_bMouseDown && !m_bPlacingANewModule && prevPoint != pt)
{
CString sDescription, sPartNumber, sAddressRange;
GetIOModuleText2(pIO,sDescription, sPartNumber, sAddressRange);
sPartNumber.Remove('[');
sPartNumber.Remove(']');
CString sModuleDetails;
sModuleDetails.Format(_T("Position: M%d\nModule Type: %s\nModule Part No: %s"), pIO->m_nModulePosition+1, sDescription,sPartNumber);
if(pIO->GetIPSize() > 0)
sModuleDetails+=_T("\nInput Address: ")+ pIO->GetInputAdr()+_T(" - ")+pIO->GetEndInputAdr();
if(pIO->GetOPSize() > 0)
sModuleDetails+=_T("\nOutput Address: ")+ pIO->GetOutputAdr()+_T(" - ")+pIO->GetEndOutputAdr();
CPoint pp = pt-GetScrollPosition();
ClientToScreen(&pp);
m_ctrlToolTip.UpdateTipText(sModuleDetails,this,1);
m_ctrlToolTip.SendMessage(TTM_TRACKPOSITION, 0, (LPARAM)MAKELPARAM(pp.x, pp.y+16));//+16 to move the tooltip stem down
m_ctrlToolTip.SendMessage(TTM_TRACKACTIVATE, TRUE, (LPARAM)&m_ti);
//to track mouse leave abd there we can remove tooltip
TRACKMOUSEEVENT tk;
tk.cbSize = sizeof(tk);
tk.dwFlags = TME_LEAVE;
tk.hwndTrack = m_hWnd;
_TrackMouseEvent(&tk);
prevPoint = pt;
bToolTipSet = true;
}
bToolTipSet = true;
break;
}
if(!bToolTipSet)
{
m_ctrlToolTip.SendMessage(TTM_TRACKACTIVATE, FALSE, (LPARAM)&m_ti);
m_ctrlToolTip.UpdateTipText("",this,1);
m_ctrlToolTip.Pop();
}
The tooltip remains visible for very few seconds and then they disappear. I find this time too short to read some of the longer tooltips. Is there a way to increase the time they remain visible?
I tried to increase the time using setdelaytime function but it doesn't help me.
Thanks in advance.
I am trying to make a sound play with the timer goes to 3, 2, 1.
My timer starts at ten and has a three second delay. If I use the following code:
if (tl.myCoolTimer == 10)
{
print("Play Sound");
myAudioSource.Play();
}
It plays the Beep over and over again until the game starts and the counter goes below 10.
If I use the code:
if (tl.myCoolTimer == 3)
{
print("Play Sound");
myAudioSource.Play();
}
It doesn't play the sound at all. It doesn't even print the print statement.
I literally only changed the number. I am not sure why this isn't working.
I have also tried setting it to 3f to see if it is a float issue.
Timer Scripts
This is the starting Timer. it counts down to 3 (then the game starts)
public Text startGameTimerText;
public float startGameTimer = 3;
public void Start ()
{
startGameTimerText = GetComponent<Text> ();
}
public void Update ()
{
startGameTimer -= Time.deltaTime;
startGameTimerText.text = startGameTimer.ToString ("f1");
if (startGameTimer < 0) {
GameObject.Find ("GameStartTimer").SetActive (false);
}
}
This is the Game Timer It starts at 10 and counts down to 0.
public StartGameTimer gt; //this is the script the other timer is on
public Text timerText;
public float myCoolTimer = 10;
public void Start ()
{
timerText = GetComponent<Text> ();
}
public void Update ()
{
if (gt.startGameTimer > 0) {
myCoolTimer = 10;
} else {
myCoolTimer -= Time.deltaTime;
timerText.text = myCoolTimer.ToString ("f1");
}
}
Thanks Joe for the help. Here was my final answer. I know it is hacked, but I haven't figured out the Invoke thing yet. When I set the into it kept playing the entire time it was at "3", so i need to make it play only once.
private AudioSource myAudioSource;
public bool isSoundPlayed;
void Start()
{
myAudioSource = GetComponent<AudioSource>();
isSoundPlayed = false;
}
void Update()
{
if((int)tl.myCoolTimer == 3)
{
if (isSoundPlayed == false)
{
myAudioSource.Play();
isSoundPlayed = true;
}
return;
}
if ((int)tl.myCoolTimer == 2)
{
if (isSoundPlayed == true)
{
myAudioSource.Play();
isSoundPlayed = false;
}
return;
}
if ((int)tl.myCoolTimer == 1)
{
if (isSoundPlayed == false)
{
myAudioSource.Play();
isSoundPlayed = true;
}
return;
}
}
I'm having this little problem with some easy code, basically what I'm doing is sending information via the serial port via a program I wrote in Java. The information is getting their for basic statements (IE, can turn on lights and stuff) but I'm having errors getting it to decode strings with number values send to it.
So for example, I'm sending strings that look like this
BS//:+000/+000/+000
and the decoding method I'm using looks like this.
After adding the string via this:
if (inputString.startsWith("BS//:")) //**fixed
{
inputInfoToBaseStepper(inputString);
baseStepperRunAction(baseStepperRotCount, baseStepperRotStepSize, baseStepperTime);
}
Sends it too...
void inputInfoToBaseStepper(String baseStepper)
{
baseStepperRotCount = baseStepper.substring(6,9).toInt();
baseStepperRotStepSize = baseStepper.substring(10,13).toInt();
baseStepperTime = baseStepper.substring(15,18).toInt();
}
Which should decode and run
void baseStepperRunAction (int rotations, int StepSize, int delayTime)
{
for (int rotations; rotations >=0; rotations--)
{
baseStepper.step(StepSize);
delay(delayTime);
}
}
Problem seems to be that it doesn't decode... ideas I'm sort of lost at this stage. :/
(total past of the code, I know the information is getting there, just not compiling like it should.)
#include <Stepper.h>
//#include <HardwareSerial.h>
// int intensity = 0; // led intensity this is needed just as example for this sketch
String inputString = ""; // a string to hold incoming data (this is general code you can reuse)
boolean stringComplete = false; // whether the string is complete (this is general code you can reuse)
int stepsPerRevolution = 64; //at 5.625 degrees a step
// initialize the stepper library on pins 8 through 11:
Stepper baseStepper(stepsPerRevolution, 2,3,4,5); // protocols start with //BS:
Stepper shoulderStepper(stepsPerRevolution, 6,7,8,9); // protocols start with //SS:
Stepper armStepper(stepsPerRevolution, 10,11,12,13); // protocols start with //AS:
//--------baseStepper--------//
int baseStepperRotCount = 0; //how many rotations in the for loop is needed
int baseStepperRotStepSize = 0; // how large should the steps be...
int baseStepperTime = 0; //delay time needed between each step (delay); so the stepper can do it's work.
//--------shoulderStepper--------//
int shoulderStepperRotCount =0;
void setup() {
// initialize serial: (this is general code you can reuse)
Serial.begin(115200);
}
void loop() {
// when a newline arrives:
if (stringComplete) {
//these are test if statements, they serve no purpose after the intial boot, but must be included to test the connectivity;
if (inputString.startsWith("alpha"))
{
boolean msgRecognized = true;
pinMode(13, OUTPUT);
digitalWrite(13, HIGH);
inputString = "";
stringComplete = false;
}
else if (inputString.startsWith("beta"))
{
boolean msgRecognized = true;
pinMode(13, OUTPUT);
digitalWrite(13, LOW);
inputString = "";
stringComplete = false;
}
//---------------------///
//these statements set the engines and prepare for running of the program.
if (inputString.startsWith("//BS:")) // "BS//:+000/+000/+000"
{
inputInfoToBaseStepper(inputString);
baseStepperRunAction(baseStepperRotCount, baseStepperRotStepSize, baseStepperTime);
}
else if (inputString.startsWith("//SS:"))
{
//inputInfoToShoulderStepper();
//outputConfirmed();
}
else if (inputString.startsWith("//AS:"))
{
//inputInfoToArmStepper();
// outputConfirmed();
}
if(inputString.startsWith("alp://")) { // OK is a message I know (this is general code you can reuse)
boolean msgRecognized = true;
if(inputString.substring(6,10) == "kprs") { // KeyPressed }
msgRecognized = false; // this sketch doesn't know other messages in this case command is ko (not ok)
// Prepare reply message if caller supply a message id (this is general code you can reuse)
int idPosition = inputString.indexOf("?id=");
if(idPosition != -1) {
String id = inputString.substring(idPosition + 4);
// print the reply
Serial.print("alp://rply/");
if(msgRecognized) { // this sketch doesn't know other messages in this case command is ko (not ok)
Serial.print("ok?id=");
} else {
Serial.print("ko?id=");
}
Serial.print(id);
Serial.write(255); // End of Message
Serial.flush();
}
}
// clear the string:
inputString = "";
stringComplete = false;
}
}
}
/*
Send listen messages
int index = 0;
for (index = 0; index < digitalPinListeningNum; index++) {
if(digitalPinListening[index] == true) {
int value = digitalRead(index);
if(value != digitalPinListenedValue[index]) {
digitalPinListenedValue[index] = value;
Serial.print("alp://dred/");
Serial.print(index);
Serial.print("/");
Serial.print(value);
Serial.write(255);
Serial.flush();
}
}
}
for (index = 0; index < analogPinListeningNum; index++) {
if(analogPinListening[index] == true) {
int value = analogRead(index);
if(value != analogPinListenedValue[index]) {
analogPinListenedValue[index] = value;
Serial.print("alp://ared/");
Serial.print(index);
Serial.print("/");
Serial.print(value);
Serial.write(255); // End of Message
Serial.flush();
}
}
}
} */
//this method decodes and stores inputs
void inputInfoToBaseStepper(String baseStepper)
{
baseStepperRotCount = baseStepper.substring(6,9).toInt(); // B S / / : + 0 0 0 / + 0 0 0 / + 0 0 0
baseStepperRotStepSize = baseStepper.substring(10,13).toInt();// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8
baseStepperTime = baseStepper.substring(15,18).toInt();
}
//this method runs the base stepper off the decoded actions.
void baseStepperRunAction (int rotations, int StepSize, int delayTime)
{
for (int rotations; rotations >=0; rotations--)
{
baseStepper.step(StepSize);
delay(delayTime);
}
}
/*
SerialEvent occurs whenever a new data comes in the
hardware serial RX. This routine is run between each
time loop() runs, so using delay inside loop can delay
response. Multiple bytes of data may be available.
This is general code you can reuse.
*/
void serialEvent() {
while (Serial.available() && !stringComplete) {
// get the new byte:
char inChar = (char)Serial.read();
// add it to the inputString:
inputString += inChar;
// if the incoming character is a newline, set a flag
// so the main loop can do something about it:
if (inChar == '\n') {
stringComplete = true;
}
}
}
I want to make the clock application where user enters the number in the textbox and click ok then user get the number at every 1 sec.
Example if user enter 5 then the timer start the display screen shows the number 1,2,3,4,5,0,1,2,3,4,5,0,1,2,3,...so on.
Now i had taken form and text field for user to enter the number,then a timer which will change the number at every second.and 10 images of number (0-9).As i want to dispaly the number in very large size.Now i had implement this logic in below way:-
public class Clock extends MIDlet implements CommandListener {
public Command GO, Exit;
TextField TxtData;
protected Display display;
int number, counter;
Form form;
private Timer timer;
private TestTimerTask task;
boolean increment, time;
private StringItem s1 = new StringItem("", "");
Image image0;
Image image1;
Image image2;
Image image3;
Image image4;
Image image5;
Image image6;
Image image7;
Image image8;
Image image9;
Image[] secondAnimation;
protected void startApp() {
display = Display.getDisplay(this);
increment = true;
time = false;
form = new Form("Clock");
TxtData = new TextField("Number:-", "", 5, TextField.NUMERIC);
try {
image0 = Image.createImage("/images/0.png");
image1 = Image.createImage("/images/1.png");
image2 = Image.createImage("/images/2.png");
image3 = Image.createImage("/images/3.png");
image4 = Image.createImage("/images/4.png");
image5 = Image.createImage("/images/5.png");
image6 = Image.createImage("/images/6.png");
image7 = Image.createImage("/images/7.png");
image8 = Image.createImage("/images/8.png");
image9 = Image.createImage("/images/9.png");
secondAnimation = new Image[]{image0,image1,image2, image3, image4, image5, image6, image7, image8, image9};
} catch (IOException ex) {
System.out.println("exception");
}
GO = new Command("Go", Command.OK, 1);
Exit = new Command("Exit", Command.EXIT, 2);
form.append(TxtData);
form.append(s1);
form.addCommand(GO);
form.addCommand(Exit);
form.setCommandListener(this);
display.setCurrent(form);
}
protected void pauseApp() {
}
protected void destroyApp(boolean unconditional) {
timer.cancel();
notifyDestroyed();
}
public void commandAction(Command cmnd, Displayable dsplbl) {
String label = cmnd.getLabel();
if (label.equals("Go")) {
try {
System.out.println("txt==" + (TxtData.getString()));
if (!TxtData.getString().equalsIgnoreCase("")) {
counter = Integer.parseInt(TxtData.getString());
if (time) {
timer.cancel();
task.cancel();
}
number = 1;
timer = new Timer();
task = new TestTimerTask();
timer.schedule(task, 1000, 1000);
}
} catch (NumberFormatException ex) {
System.out.println("exception");
}
} else if (label.equals("Exit")) {
destroyApp(true);
}
}
private class TestTimerTask extends TimerTask {
public final void run() {
time = true;
s1.setText(""+ number);
if (counter < 10) {
form.append(secondAnimation[0]);
form.append(secondAnimation[0]);
form.append(secondAnimation[number]);
} else if (counter < 100) {
form.append(secondAnimation[0]);
form.append(secondAnimation[(number % 100) / 10]);
form.append(secondAnimation[(number % 10)]);
} else if (counter < 1000) {
form.append(secondAnimation[(number % 10)]);
form.append(secondAnimation[(number % 100) / 10]);
form.append(secondAnimation[(number / 100)]);
}
number++;
if (number == counter + 1) {
number = 0;
}
}
} }
But as the form goes on appending the image as timer moves it is not showing the desired output!
I had tried to do it through LWUIT but as i had user 10 .png files and adding LWUIT.jar file make the size of .jar file 557kb which is very heavy.
So i want to do it through normal forms only.
I cant use canvas as the keypad can vary like (touch,qwerty etc).So i need to do normal form or LWUIT only.Can anyone please help me for this.
I noticed you only append items but never remove - is that intended?
Also, did you try two different forms to animate instead of one? For simple test, say, fill them in parallel, just call setCurrent for one that is not displayed in the moment of update
//...
private void appendTwice(Image image) {
form1.append(image);
form2.append(image);
}
//...
public final void run() {
time = true;
s1.setText(""+ number);
if (counter < 10) {
appendTwice(secondAnimation[0]);
//...
}
display.setCurrent(number & 1 == 0 ? form1 : form2);
number++;
//...
}
//...