I define an
int x = 10;
Now I want x to decrease every second until its 0:
if (Obstacle.activeItem == true) {
game.font.draw(game.batch, "Item active for: " + x, 100, 680);
}
How can I do that?
I've seen people do similar things using the Class Timer, but I don't know how it should look like for this case.
I tried
int x = 10;
ScheduledExecutorService execService = Executors.newScheduledThreadPool(1);
And then
if (Obstacle.activeItem == true) {
game.font.draw(game.batch, "Item active for: " + x, 100, 680);
}
execService.scheduleAtFixedRate(new Runnable() {
public void run() {
x--;
}
}, 0L, 10L, TimeUnit.SECONDS);
But that doesn't work as I want it to.
You tagged your question with libGdx so I think you work with libgdx.
Instead of creating a extra ExecutorService why you don't use the update(float delta) method to decrease your timer?
private float timer = 10;
#Override
public void render(float delta) {
timer -= delta;
if (Obstacle.activeItem == true) {
font.draw(batch, "Item active for: " + (int)timer, 100, 680);
}
}
Here's a sample of how you can implement a Timer type functionality using Executors
public class Main {
static int x = 10;
public static void main(String[] args) {
ScheduledExecutorService execService = Executors.newScheduledThreadPool(1);
execService.scheduleAtFixedRate(() -> {
System.out.println(x);
x--;
if (x == 0)
execService.shutdownNow();
}, 1L, 1L, TimeUnit.SECONDS); //initial delay, period, time unit
}
}
It is highly recommended that you read up on Executors. Consider this as a hint and implement it in your use case accordingly.
if that is libGdx i have some working sphagetti code for you:
int reducedInt = 10;
bool isReduce = false;
float timer = 1f;
in Render
timer -= delta;
if(timer<=0){
isReduce = true;
timer = 1;
}
if(isReduce){
reducedInt--;
isReduce = false;
}
This is classic LibGDX sphagetti timer code. Since you have tagged it as LibGDX.
Related
Hello Stack Overflow people :)
I'm a huge newbie when it comes to coding, and I've just ran into a problem that my brain just won't get over...
Before I start blabbering about this issue, I'll paste my code so as to give a little bit of context (sorry in advance if looking at it makes you wanna puke). The main focus of the issue is commented and should therefore be fairly visible :
Main
ArrayList<Individual> individuals = new ArrayList<Individual>();
void setup()
{
size(500,500);
for(int i = 0; i < 2; i++)
{
individuals.add(new Individual());
}
println(frameRate);
}
void draw()
{
background(230);
for(int i = 0; i < individuals.size(); i++)
{
individuals.get(i).move();
individuals.get(i).increaseTimers();
individuals.get(i).display();
}
}
Individual
class Individual
{
float x;
float y;
int size = 5;
Timer rdyBreed; /* Here is the object that appears to be shared
between individuals of the ArrayList */
float breedRate;
float breedLimit;
Individual()
{
x = random(0, width);
y = random(0, height);
rdyBreed = new Timer("rdyBreed", 0);
breedRate = random(.2, 3);
breedLimit = random(10, 20);
}
void move()
{
int i = (int)random(0, 1.999);
int j = (int)random(0, 1.999);
if (i == 0)
{
x = x + 1;
} else
{
x = x - 1;
}
if (j == 0)
{
y = y + 1;
} else
{
y = y - 1;
}
checkWalls();
}
void checkWalls()
{
if (x < size/2)
{
x = width - size/2;
}
if (x > width - size/2)
{
x = size/2;
}
if (y < size/2)
{
y = width - size/2;
}
if (y > width - size/2)
{
y = size/2;
}
}
void display()
{
noStroke();
if (!rdyBreed.finished)
{
fill(255, 0, 0);
} else
{
fill(0, 255, 0);
}
rect(x - size/2, y - size/2, size, size);
}
void increaseTimers()
{
updateBreedTimer();
}
void updateBreedTimer()
{
rdyBreed.increase(frameRate/1000);
rdyBreed.checkLimit(breedLimit);
rdyBreed.display(x, y);
}
}
Timer
class Timer
{
float t;
String name;
boolean finished = false;
Timer(String name, float t)
{
this.t = t;
this.name = name;
}
void increase(float step)
{
if (!finished)
{
t = t + step;
}
}
void checkLimit(float limit)
{
if (t >= limit)
{
t = 0;
finished = true;
}
}
void display(float x, float y)
{
textAlign(RIGHT);
textSize(12);
text(nf(t, 2, 1), x - 2, y - 2);
}
}
Now that that's done, let's get to my question.
Basically, I'm trying to create some sort of a personal Conway's Game of Life, and I'm encountering a lot of issues right off the bat.
Now my idea when writing this piece of code was that every individual making up the small simulated "society" would have different timers and values for different life events, like mating to have children for example.
Problem is, I'm not a huge pro at object-oriented programming, and I'm therefore quite clueless as to why the objects are not having each their own Timer but both a reference to the same timer.
I would guess making an ArrayList of timers and using polymorphism to my advantage could make a change, but I'm not really certain of it or really how to do it so... yeah, I need help.
Thanks in advance :)
EDIT : Here is a screenshot of the debugger. The values keep being the same with each iteration of the updates.
Screenshot
What makes you think they reference the same Timer object? The values of t displayed in the debugger are going to be the same until one of them reaches the breedLimit and gets set to 0, because they're being initialized at the same time.
Try this and see that the values of t are different.
void setup() {
size(500,500);
}
void mouseClicked() {
individuals.add(new Individual());
}
I'd recommend setting the breakpoint somewhere around here:
t = 0;
finished = true;
They do not share the same timer, you create a new Timer object for each Individual.
class Individual {
// ...
Timer rdyBreed;
Individual() {
// ...
rdyBreed = new Timer("rdyBreed", 0);
//...
The only way they could be sharing the same Timer is if you were setting rdyBreed elsewhere, but since you don't want that I recommend making it final.
If you did want to share the same Timer instance across all individuals then you could declare it static.
I am doing an assignment from the Java Exposure textbook, which was written in 2007. This book includes some code that I usually update to use some of the more recent features (just basic stuff). However, in this one I am running into a problem. All I tried to do is replace the show with setVisible(true) and change the Frame to a JFrame and add a gfx.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);. However, I noticed that this wouldn't actually cause the window to close. If I clicked many times, maybe 1/30 tries it would close. If I reduced the delay from 10 to 1, it usually closed within 2 tries. This of course led me to believe that the delay method is causing this erratic behavior. I tried Thread.sleep, but of course that didn't work. Is there any simply way to get this code so that the frame will close when I hit the close button? If there isn't, what would be the less simple way of doing it?
Here is the code:
// Lab30st.java
// The Screen Saver Program
// Student Version
import java.awt.*;
import java.awt.event.*;
import java.applet.*;
import javax.swing.JOptionPane;
public class Lab30st
{
public static void main(String args[])
{
GfxApp gfx = new GfxApp();
gfx.setSize(800,600);
gfx.addWindowListener(new WindowAdapter() {public void
windowClosing(WindowEvent e) {System.exit(0);}});
gfx.show();
}
}
class GfxApp extends Frame
{
private int circleCount, circleSize;
public GfxApp()
{
circleCount = 50;
circleSize = 30;
}
class Coord
{
private int xPos;
private int yPos;
public Coord(int x, int y)
{
xPos = x;
yPos = y;
}
}
public void paint(Graphics g)
{
int incX = 5;
int incY = 5;
int diameter = 30;
int timeDelay = 10;
Circle c = new Circle(g,diameter,incX,incY,timeDelay);
for (int k = 1; k <= 2000; k++)
{
c.drawCircle(g);
c.hitEdge();
}
}
}
class Circle
{
private int tlX; // top-left X coordinate
private int tlY; // top-left Y coordinate
private int incX; // increment movement of X coordinate
private int incY; // increment movement of Y coordinate
private boolean addX; // flag to determine add/subtract of increment for X
private boolean addY; // flag to determine add/subtract of increment for Y
private int size; // diameter of the circle
private int timeDelay; // time delay until next circle is drawn
public Circle(Graphics g, int s, int x, int y, int td)
{
incX = x;
incY = y;
size = s;
addX = true;
addY = false;
tlX = 400;
tlY = 300;
timeDelay = td;
}
public void delay(int n)
{
long startDelay = System.currentTimeMillis();
long endDelay = 0;
while (endDelay - startDelay < n)
endDelay = System.currentTimeMillis();
}
public void drawCircle(Graphics g)
{
g.setColor(Color.blue);
g.drawOval(tlX,tlY,size,size);
delay(timeDelay);
if (addX)
tlX+=incX;
else
tlX-=incX;
if (addY)
tlY+=incY;
else
tlY-=incY;
}
public void newData()
{
incX = (int) Math.round(Math.random() * 7 + 5);
incY = (int) Math.round(Math.random() * 7 + 5);
}
public void hitEdge()
{
boolean flag = false;
if (tlX < incX)
{
addX = true;
flag = true;
}
if (tlX > 800 - (30 + incX))
{
addX = false;
flag = true;
}
if (tlY < incY + 30) // The +30 is due to the fact that the title bar covers the top 30 pixels of the window
{
addY = true;
flag = true;
}
if (tlY > 600 - (30 + incY))
{
addY = false;
flag = true;
}
if (flag)
newData();
}
}
You are "freezing" the Event Dispatch Thread with
public void delay(int n)
{
long startDelay = System.currentTimeMillis();
long endDelay = 0;
while (endDelay - startDelay < n)
endDelay = System.currentTimeMillis();
}
This means that all the other stuff that is trying to happen (like closing the window) has to wait until the thread comes out of the "sleep".
basically you shouldn't be doing the delay in the EDT, it should be on a different thread and then ask the EDT thread to update.
Your "busy wait" delay may cause other problems too. You can improve the behavior by using Thread.sleep()
See Java Event-Dispatching Thread explanation
That's terrible.
You need to restructure the whole code.
Let's start with the really bad:
delay is (almost) a busy wait, I haven't seen busy waits since BASIC was modern. It basically holds the CPU hostage to the thread, not only does it do nothing, no other thread (almost) can use the time slice. The reason I say almost is that calling the system time function causes a context switch that could allow other threads to run, but it is still bad.
The still pretty bad:
Replacing with Thread.sleep. Better yes, no busy wait, but you are still holding the one and only UI thread. This means no other UI work can happen up to and including closing the main window.
What needs to happen:
Get an external timer (e.g. javax.swing.Timer) to trigger the draw event and do next part of the animation.
Search for "Java smooth animation" there are many examples of how to do this, double buffer and all.
I have a marching sound file which I play once a specific event occurs, but the issue comes down to having the file fade out in a specified amount of time before being stopped when the volume reaches 0. This project is for Desktop.
Sound marching = Gdx.audio.newSound(Gdx.files.internal("sounds/test.wav"));
The first attempt I had at this was scheduling a task through the Timer:
final long mId = marching.play(1f, 1f, 0);
for (float i = 1; i > 0; i -= 0.01) {
Timer.schedule(new Task() {
#Override
public void run() {
marching.setVolume(mId, i);
}
}, 0.3f);
}
marching.stop();
This, however seemed to invoke marching#stop before marching#setVolume
I decided to take another apporach:
float volume = 1;
final long mId = marching.play(volume, 1f, 0), startTime = TimeUtils .millis();
while (volume > 0) {
if (TimeUtils.millis() - startTime % 300 == 0) marching.setVolume(mId, volume -= 0.1);
}
marching.stop();
I thought that this would reduce the volume based on the amount of time allotted, yet it only made the program freeze.
Is there a straightforward way of fading SFX audio out or some manner of setting frequent sleeps so that I can lower the volume iteratively?
Thanks.
I think the easiest way is to put this in the render method:
float FACTOR = 10; // The bigger the factor, the faster the fade-out will be
float mVolume = 1;
boolean mIsPlaying = true;
public void render(float delta) {
// ...
if (mIsPlaying) {
mVolume -= delta * FACTOR;
if (mVolume > 0) {
marching.setVolume(mId, mVolume);
}
else {
marching.stop(mId);
mIsPlaying = false;
}
}
// ...
}
First solution is wrong, I rewrote it for you:
final long mId = marching.play(1f, 1f, 0);
Timer.schedule(new Task() {
#Override
public void run() {
for (float i = 1; i > 0; i -= 0.01)
{
marching.setVolume(mId, i);
if(i<=0)
marching.stop();
}
}
}, 0.3f);
Second solution freeze your app because you are calling it in the main thread and not in a async task!
However using the render task is not a good idea. You should detach render task from game loop task. Read that: http://gameprogrammingpatterns.com/game-loop.html. Logic of your game should run at the same speed in all machine. Cannot be limited by rendering issue/slow problem.
I find this works much better than using a loop.
I set MUSIC_FADE_STEP to 0.01f (i.e adjust volume by 1% each time through).
I adjust fadeRate (in seconds) as required. 0.01f works well as a starting point.
Timer.schedule(new Timer.Task() {
#Override
public void run() {
if (music.getVolume() >= MUSIC_FADE_STEP)
music.setVolume(music.getVolume()-MUSIC_FADE_STEP);
else {
music.stop();
this.cancel();
}
}
}, 0f, fadeRate);
I am trying to parallelize the raytracer im currently working on for university, but i cant quite seem to get it to work. Ive tried multiple implementations, but the problem stays the same.rendering stops after a few milliseconds and at most a small chunk of the picture is rendered.
final ExecutorService executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
long start = System.currentTimeMillis();
for (int i = 0; i < image.getWidth(); i++) {
final int ii =i;
executor.execute(new Runnable() {
public void run() {
for (int j = 0; j < image.getHeight(); j++) {
raster.setDataElements(ii, image.getHeight()-j-1, model.getDataElements(
getPixelColor(width,height,ii,j,world,pcameras2),0, null));
}
}
});
}
g.drawImage(this.image, 0, 0, this);
System.out.println("Rednering finished in: " + (System.currentTimeMillis()-start)/1000.0 + " seconds");
}
public static float[] getPixelColor(final int width,final int height,
final int x,final int y,final World world,final Camera camera){
final Hit hit = world.hit(camera.rayFor(width,height, x, y));
if(hit != null){
return new float[]{(float) hit.geo.material.ColorFor(hit,world).r,
(float) hit.geo.material.ColorFor(hit,world).g,(float) hit.geo.material.ColorFor(hit,world).b, 1};
} else {
return new float[]{(float) world.backgroundColor.r, (float) world.backgroundColor.g, (float) world.backgroundColor.b, 1};
}
}
I found out, that if i exlude the world.hit() method it works just fine, but as this contains most of the computation, thats not an option.
As explained here, you want to call shutdown to tell the Exector to shutdown after all currently queued tasks have been finished, and then awaitTermination to wait until they are all done.
executor.shutdown();
try {
executor.awaitTermination(100, TimeUnit.SECONDS);
}
catch (InterruptedException e) {
// what should happen if timeout was hit
}
// image is complete here (if InterruptedException was not thrown)
g.drawImage(this.image, 0, 0, this);
I'm working on a simulation for the growth of an organism, using jLabels for the organisms. However, when I implement a for loop and a timer to try and show it moving, it freezes and then displays the final position of the label rather than showing it move. Could anyone explain to me why this is happening?
public class TestView extends FrameView {
public TestView(SingleFrameApplication app) {
super(app);
initComponents();
picture = new JLabel();
picture.setIcon(new ImageIcon(System.getProperty("user.dir") +
File.separator + "mouse.gif"));
picture.setBounds(0, 0, 100, 100);
mainPanel.add(picture);
for (int x = 0; x < 20; x++) {
move();
wait(50);
}
}
public static void wait(int n) {
long t0, t1;
t0 = System.currentTimeMillis();
do {
t1 = System.currentTimeMillis();
} while (t1 - t0 < n);
}
public static void move() {
picture.setBounds(picture.getX() + 5, picture.getY(), 100, 100);
}
You might like this example of diffusion limited aggregation and other simulations.