Thread Question

Hi, at the moment i have different gameplay questions.

For example I thought about 2 units attacking each other automaticly. If I would use the normal update loop to trigger the attack cooldown the gameplay would become very crazy when you have only a few FPS. Because of this I think i need to seperate the gameplay in an own thread (or use many timer).

What do you think about this? And is there already a way to update the animations etc. easily when you work in another thread?

if you want to have “cooldowns”. why dont you just save the time of the last attack, and then compare, it with the current time minus the saved time? if thats greater then the cooldown, the next attack can be made, otherwise it can not.



Some pseudo code:



if(current_time - last_attack > cooldown) {

attack = get_attack_from_attack_queue();

cooldown = attack.getCooldown()

last_attack = current_time;

attack.execute();

}

else {

; //still on cooldown => do nothing

}

As @Tr3kker says, checking the time every loop is often a better solution than creating threads.

Yes, it might seem like a lot of work but a check for null or comparison is something your computer can do millions of times a second, having an event-based system or even worse separate threads means much more overhead in the end. Also its the most consistent programming scheme really, applications and especially games have been done like this for ages really.

Okay, but I dont want to create many variables that save the time and check it. (I think it would be confusing)

Does JME have a “timer” class which could count the time for me?

Well normally you only need a few timers max per class (e.g. AppState or Control). I don’t know whats the issue with having one variable and adding tpf instead of having a whole class and the variable.

@ogerlord said:
Okay, but I dont want to create many variables that save the time and check it. (I think it would be confusing)

Then use an array instead of multiple variables?

An array, or maybe in its very own class. :o



If it’s well made, perhaps it can be used in other classes as well.

Maybe something like this:

[java]import java.util.PriorityQueue;



public interface MyRunnable

{

public void run(Object value);

}



public class MyTimer implements Comparable{



private static PriorityQueue heap

private static long myTime;



private MyRunnable runnable;

private Object value;

private long time;

private boolean loop;

private long loopDuration;



public static void init()

{

myTime=0;

heap = new PriorityQueue();

}



public static void update(float tpf)

{

if(heap.isEmpty()==false)

{

myTime += (long)(tpf*1000);

while(heap.isEmpty()==false && ((MyTimer)heap.peek()).time < myTime )

{

MyTimer t = (MyTimer)heap.peek();

heap.remove();

t.execute();

}

}

}



public MyTimer(MyRunnable runnable, Object value, int time, boolean loop )

{

this.runnable=runnable;

this.value=value;

this.time = myTime+(long)time;

this.loop=loop;

if(loop)

{

loopDuration = (long)time;

}

heap.add(this);

}



private void execute()

{

if(runnable != null)

{

runnable.run(value);

if(loop)

{

time = time + loopDuration;

heap.add(this);

}else{

value=null;

runnable=null;

}

}

}



public void cancel()

{

value=null;

runnable=null;

heap.remove(this);

}



public int compareTo(Object o)

{

return (int)(time -((MyTimer)o).time);

}



}[/java]



Example:

[java]



public void simpleInitApp() {

MyTimer.init();



new MyTimer(new PrintMessage(),"loop",1000,true);

new MyTimer(new PrintMessage(),"first",500,false);

new MyTimer(new PrintMessage(),"third",5000,false);

new MyTimer(new PrintMessage(),"second",2000,false);



}



public void simpleUpdate(float tpf){

MyTimer.update(tpf);

}



private class PrintMessage implements MyRunnable

{

public void run(Object o)

{

System.out.println("Test:"+o);

}

}[/java]

For something like that you can rather use the app.enqueue method… I think it was mainly about the counter itself.

Hm? I cant follow you. Why should be the app.enqueue method better?

I mean the whole runnable logic… I guess its possible to do it this way but it kind of requires you to encapsulate everything in runnables instead of checking some timer in an update() call or something.