I'm trying to make an action "stretch" over a certain period of time, being 1 second.
public static int i = 0;
public static void click() {
Robot robot;
try {
robot = new Robot();
for (i = i; i < cps; i++) {
robot.mousePress(InputEvent.BUTTON1_MASK);
Random rn = new Random();
int range = cps - 10 + 1;
int randomNum = rn.nextInt(range) + 10;
robot.delay(randomNum);
robot.mouseRelease(InputEvent.BUTTON1_MASK);
i++;
}
if (i == cps) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
i = 0;
}
} catch (AWTException e) {
e.printStackTrace();
}
}
As you can see, this is the code for a "simple" auto clicker.
It runs within this timer.
public static void getClick() {
timer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
while (enabled) {
click();
}
}
}, 1, 1);
}
Is it in any way possible to make this action "stretch" it's action to 1 second. I really don't want it to click 12 times (Example), and then pause for 1 second. It'd be way nicer if these 12 clicks were "stretched" over that 1 second.
Is it possible anyone can help me?
You could just let it sleeps for 1000ms/cps. If the user set cps=10 then 10 Thread.sleep(1000/cps)would let it click ten times in one sec. With cps=0.5 it would click once in two seconds.
(with a little discrepancy, because your code needs time to execute). And you should not create your random object in your loop.
Random rn = new Random();
while(true) {
robot.mousePress(InputEvent.BUTTON1_MASK);
int range = cps - 10 + 1;
int randomNum = rn.nextInt(range) + 10;
robot.delay(randomNum);
robot.mouseRelease(InputEvent.BUTTON1_MASK);
i++;
try {
Thread.sleep(1000/cps);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Related
I have a program that displays a picture of a coin. When the user clicks the coin the coin changes from heads to tails and vice versa. That works fine.
The problem arises when I want to have a button that flips the coin a random number of times (In this case between 3 and 10 times inclusive).
The method used to change the image icon:
flip.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent e1) {
playerCoinState = coinState;
System.out.println("Clicked");
int flips = (new Random().nextInt(8)) + 3;
for(int i = 0; i < flips; i++){
try{
Thread.sleep(1000);
}catch(InterruptedException e2){
System.exit(1);
}
System.out.println("Auto Flipped");
changeFace();
}
}
});
And this is the method used to change the ImageIcon of the JLabel coin:
private void changeFace(){
System.out.println("Changing...");
switch(coinState){
case 0:
System.out.println("Coin State 0");
try {
coin.setIcon(new ImageIcon(ImageIO.read(new File("res/Heads.png"))));
} catch (IOException e) {
e.printStackTrace();
}
coinState = 1;
break;
case 1:
System.out.println("Coin State 1");
try {
coin.setIcon(new ImageIcon(ImageIO.read(new File("res/Tails.png"))));
} catch (IOException e) {
e.printStackTrace();
}
coinState = 0;
break;
}
}
The JLabel coin is initialised as:
coin = new JLabel(new ImageIcon("res/Tails.png"));
coinState represents the value of the coin. 0 for heads, 1 for tails.
playerCoinState is used to keep track of the coin state the player has selected before the coin is to be flipped by the computer the random amount of times.
This...
for(int i = 0; i < flips; i++){
try{
Thread.sleep(1000);
}catch(InterruptedException e2){
System.exit(1);
}
System.out.println("Auto Flipped");
changeFace();
}
Is blocking the event dispatching thread, preventing ui from been updated until after the method exits
You should try using a Swing Timer instead, which acts as a pseudo loop, but waits in the background for a prescribed period of time before triggering a tick within the context of the EDT, making it safe to update the UI from
coin = new JLabel(new ImageIcon((ImageIO.read(new File("path"))));
Use this instead of coin.setIcon(new ImageIcon(ImageIO.read(new File("res/Tails.png")))); So you are creating the coin label new every time. If you are working with eclispe and windowbuilder, you can just use the tools on the sidebar.
MadProgrammer helped me to solve this.
The new and improved ActionListener for the button is:
flip.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e1) {
playerCoinState = coinState;
int flips = (new Random().nextInt(10) + 5);
Timer timer = new Timer(400, new ActionListener(){
int counter = 0;
#Override
public void actionPerformed(ActionEvent e) {
if(counter == flips){
((Timer)e.getSource()).stop();
}
changeFace();
counter++;
}
});
timer.start();
}
});
Thanks again MadProgrammer =)
I am just a beginner in Java. We have a college project and we are making a game called othello (also called reversi), we are using Java applet for the game. Board design and gameplay is complete and is working fine but we are having an issue with the timer.
The problem is player's move is not detected until timer has elapsed completely, i.e suppose timer for each move is 10 sec and if the user places his move at the 5th sec, his move will be detected only after 10 sec This behavior does not serve any purpose.
The method I am following is:
Display the time(integer) on the applet screen
Sleep for one sec
Increment time and update graphics
The whole thing is put inside the loop which is actually creating the problem. I need a better and in fact a working modification to this code.
Here are the code of two relevant functions
void startTimer() {
Graphics g = getGraphics();
for(sec =0 ; sec < 10 ; sec++){
String time = new String();
time = Integer.toString(sec);
g.drawString(time, WIDTH+80, 145);
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
Logger.getLogger(NewApplet.class.getName()).log(Level.SEVERE, null, ex);
}
update(getGraphics());
}
}
public boolean mouseUp(Event e, int x, int y) {
int column = (int)(x / (WIDTH / 8));
int row = (int)(y / (WIDTH / 8));
if (turn == BLACK) {
if (placeLegalCheck(column, row, turn) == true){
flipDisk(column, row, turn);
turn = - turn;
diskCount();
startTimer();
update(getGraphics());
try {
Thread.sleep(500);
} catch (Exception excep){
}
}
}
if (turn == WHITE) {
if (placeLegalCheck(column, row, turn) == true){
flipDisk(column, row, turn);
turn = - turn;
diskCount();
startTimer();
update(getGraphics());
try {
Thread.sleep(500);
} catch (Exception excep){
}
}
}
return true;
}
In a game board we are developing in Java we want to show a sort of rolling dice when a button is pressed. We are trying to use the following image as a sprite:
so when the button is pressed, here's what happens:
private void startAnimationDie(final JPanel panel) {
int launchResult = /* getting a launch dice result from the core game (from 1 to 6)*/
new Thread() {
public void run() {
try {
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
BufferedImage[] animationBuffer = initAnimationBuffer();
BufferedImage[][] exactDieFaces = initExactDieFaces();
int launchResult = coreGame.launchDie();
coreGame.getMyPartecipant().setLastLaunch(launchResult);
AnimationSprite animation = new AnimationSprite(animationBuffer, Constants.DIE_ANIMATION_SPEED);
animation.start();
JLabel resultDie = new JLabel();
resultDie.setBounds(60, 265, Constants.DIE_SIZE, Constants.DIE_SIZE);
for (int counter = 0; counter < Constants.DIE_ANIMATION_SPEED * 100; counter++) {
animation.update();
//panel.removeAll();
panel.updateUI();
//System.out.println("infor");
resultDie.setIcon(new ImageIcon(animationBuffer[counter % Constants.ROTATIONS]));
panel.add(resultDie);
panel.updateUI();
updateUI();
}
panel.removeAll();
panel.updateUI();
AnimationSprite resultAnimation = new AnimationSprite(exactDieFaces[launchResult - 1], 6);
resultAnimation.start();
resultAnimation.update();
System.out.println("0");
resultDie.setIcon(new ImageIcon(exactDieFaces[launchResult - 1][0]));
System.out.println("1");
resultDie.setBounds(60, 265, Constants.DIE_SIZE, Constants.DIE_SIZE);
System.out.println("2");
panel.add(resultDie);
try {
Thread.sleep(200);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
userPlayer.getGamePanel().makePossibleMoveFlash();
}
});
} catch (Exception ex) {
}
}
}.start();
where exactDieFaces contains the dice faces according to the pawn color which is launching and that face will be shown after the simulated rolling has finished; on the other hand, animationBuffer contains 40 or 50 random faces of all colors taken from the sprite image like that:
private BufferedImage[] initAnimationBuffer() {
BufferedImage[] result = new BufferedImage[Constants.ROTATIONS];
int rowSprite, colSprite;
Random random = new Random();
for (int i = 0; i < Constants.ROTATIONS; i++) {
rowSprite = 1 + random.nextInt(5);
colSprite = 1 + random.nextInt(5);
result[i] = DieSprite.getSpriteExact(0 /* offset */,colSprite, rowSprite);
}
return result;
}
The problem is that nothing is shown during the animation: I expected to see many dice faces change one after the other until the for cycle ends but nothing is shown...The only thing I see is the launch result according to the color pawn which has launched the die but meanwhile there is nothing...can you help me?
If I understand your code correctly you are attempting to update the UI many times within the same for loop. That's not how animation works. You need a timer which regularly notifies you to move to the next frame to view.
A good place to start in understanding how to use timers is here in the Java tutorial.
Sorry if this is a very closed question that won't be useful to others, but I'm just stumped by this bug and I haven't been able to solve it for weeks!
I am working on a wave based survival game and am currently working on a spawning mechanism.
The code I wrote works perfectly for one wave, but somehow doesn't restart for further waves.
I have written the code below:
public void run() {
while (ingame) {
if (enemyList.isEmpty()) {
stopSpawn = false;
try {
Thread.sleep(500);
spawnNewEnemy();
} catch (InterruptedException ex) {
System.out.println("Interrupted");
}
} else {
if (!enemyList.isEmpty() && !stopSpawn) {
// getEnemyAmount returns the amount of enemies that should be spawned this wave
for (int enemiesSpawned = 0; enemiesSpawned < getEnemyAmount(); enemiesSpawned++) {
try {
Thread.sleep(500);
} catch (InterruptedException ex) {
}
System.out.println(currentWave);
spawnNewEnemy();
}
stopSpawn = true;
}
}
}
}
Here is the spawnNewEnemy method
public void spawnNewEnemy() {
Random spawn = new Random();
int spawnX = spawn.nextInt(500);
int spawnXTest = b.bX - spawnX;
if (spawnXTest < 20) {
spawnX = spawnX + 20;
} else {
}
int spawnY = spawn.nextInt(500);
int spawnYTest = b.bX - spawnY;
if (spawnYTest < 20) {
spawnY = spawnY + 20;
} else {
}
spawnY = spawnY + 20;
spawnX = spawnX + 20;
enemyList.add(new Enemy(spawnX, spawnY));
}
I can read the following in your code:
If the list of enemies is empty, you set stopSpawn to false and spawn an enemy.
That triggers your else-statement.
There, you spawn enemies based on the enemy count.
stopSpawn is set to true, thus your else-statement doesn't get triggered anymore.
Nothing happens anymore untill your enemylist is empty.
If your enemylist is empty again, you start over.
The logics seems ok, so I'm thinking either the way you spawn enemies through spawnNewEnemy() is faulty, or the way you remove enemies from the enemyList is faulty. I see neither of that code so that is as far as I can go in this answer.
I guess your problem with a loop is in stopSpawn value.
You set it to true after the first wave and likely not setting to `false' before starting the next wave.
I am working on an app that counts the number of questions marks in a few paragraphs of text.
After the scanning is done (which takes no time at all) I would love to have the total presented after the number goes from 0 to TOTAL. So, for 10: 0,1,2,3,4,5,6,7,8,9 10 and then STOP.
I have tried a couple of different techniques:
TextView sentScore = (TextView) findViewById(R.id.sentScore);
long freezeTime = SystemClock.uptimeMillis();
for (int i = 0; i < sent; i++) {
if ((SystemClock.uptimeMillis() - freezeTime) > 500) {
sentScore.setText(sent.toString());
}
}
Also I tried this:
for (int i = 0; i < sent; i++) {
// try {
Thread.sleep(500);
} catch (InterruptedException ie) {
sentScore.setText(i.toString());
}
}
I am sure these are both completely amateur attempts. Any help would be much-appreciated.
Thanks,
Richard
I've used a more conventional Android-style animation for this:
ValueAnimator animator = new ValueAnimator();
animator.setObjectValues(0, count);
animator.addUpdateListener(new AnimatorUpdateListener() {
public void onAnimationUpdate(ValueAnimator animation) {
view.setText(String.valueOf(animation.getAnimatedValue()));
}
});
animator.setEvaluator(new TypeEvaluator<Integer>() {
public Integer evaluate(float fraction, Integer startValue, Integer endValue) {
return Math.round(startValue + (endValue - startValue) * fraction);
}
});
animator.setDuration(1000);
animator.start();
You can play with the 0 and count values to make the counter go from any number to any number, and play with the 1000 to set the duration of the entire animation.
Note that this supports Android API level 11 and above, but you can use the awesome nineoldandroids project to make it backward compatible easily.
Try this:
private int counter = 0;
private int total = 30; // the total number
//...
//when you want to start the counting start the thread bellow.
new Thread(new Runnable() {
public void run() {
while (counter < total) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
t.post(new Runnable() {
public void run() {
t.setText("" + counter);
}
});
counter++;
}
}
}).start();
The question is very old, but I am posting this so that it would help someone else.
I have used these 2 amazing libraries.
Try them
https://github.com/MasayukiSuda/CountAnimationTextView
Or
2. https://github.com/robinhood/ticker
Hope this helps :) Happy Coding!!!
Use TextSitcher
for the best effects. It will transform the text softly.
When coming to the change of the text use the below Code.
> int number = 0;
> Timer obj = new Timer();
> TimerTask tt = new TimerTask() {
> #Override public void run() {
> // TODO Auto-generated method stub
> textView.setText(number++);
> if(number < score)
> obj.schedule(tt, 200); } };
> obj.schedule(tt, 200);
Use a worker thread to do the waiting and update your UI thread.
You could use an AsyncTask, though it might be an overkill for this job. If you use this, In the doInBackground() loop over the number of sleep periods and after every sleep period, update the count in the UIthread.
There you go! Slukain just gave you the working code :P
Maybe try changing the for loop to something like:
int count = 0;
while (count != sent) {
if ((SystemClock.uptimeMillis() - freezeTime) > 500) {
count++;
sentScore.setText("" + count);
freezeTime = SystemClock.uptimeMillis();
}
}