I'm looking into how I should design my games in regards to management/transitioning of different "screens" as well as effect timings. I'm currently using AndEngine on Android, which doesn't have an explicit game loop, although I'm interested in hearing how these issues are dealt with both with or without a game loop.
I've already written a temporary system that I'm using to handle the different "screens" in my game (splash, menu, game, options etc), which is based on "scenes" within AndEngine. I've got 3 base "scenes" which act as layers for a background, content and popups. Each Screen has onTransitionIn() and onTransitionOut() methods which are called by the ScreenManager when it's own methods (such as closePopup(), that sort of thing) are called. However, all code in the transition methods would obviously be run at once, meaning all animations, the screen status etc would be executed instantly. To overcome this problem, I used the postDelayed(runnable, delay) method in the Android Handler class. That way, I was able to change the screen status after the transition animations were completed and run one animation after another. Now the entire system is pretty much based on running delayed code via the handler. Unsurprisingly, it's crude, not particularly stable and generally amateurish.
The second issue regarding "effect timings" is closely linked to my usage of the Handler class. Let's just say I want to create an effect when a user completes a task, where some animation is played and a number is increased on the screen. At the moment, the only way of having one run after the other is by using the Handler. As stated previously, this appears to me like a crude/unstable/amateurish method.
I'd really like to know how these issues are generally handled in games (both with/without an explicit loop).
From your description, it sounds like when you want to trigger a chain of actions, you're basically firing them all off at once, each with some fixed delay. This is quite fragile - if you change the duration of one of the actions, it might no longer sync up with something that's supposed to happen after it.
A more robust approach would be to use the Observer Pattern. Each action could have an onCompleted() event (and/or various other events, depending on the nature of the action), which could be used to trigger the start of the next action.
For example, let's say that when the user presses the selects a menu item, you want this sequence of events:
Play an animation of the selected item.
When 1 is finished, transition the current screen off.
When 2 is finished, transition the next screen on.
It sounds like you're doing something like this:
void onItemSelected(MenuItem menuItem) {
runNow(new SelectedItemAnimationHandler(menuItem)); // Takes 500ms
// Delay for 500ms to wait until end of selection anim.
postDelayed(new ScreenTransitionOffHandler(currentMenu), 500); // Takes 1000ms
// Delay for 1500ms to wait until end of transition off.
postDelayed(new ScreenTransitionOnHandler(nextMenu), 1500);
}
You might chain the events by creating Actions (which fulfil the 'subject' role in the Observer pattern) and ActionObservers (which fulfil the 'observer' role):
void onItemSelected(MenuItem menuItem) {
// Set up the actions
// Actions call onCompleted() on any observers when they complete.
SelectedItemAnimationAction sa = new SelectedItemAnimationAction(menuItem);
ScreenTransitionOffAction stoff = new ScreenTransitionOffAction(currentMenu);
ScreenTransitionOnAction ston = new ScreenTransitionOnAction(nextMenu);
// Add some observers to the actions
sah.addOnCompletedHandler(new ActionObserver() {
public void onCompleted() {
stoff.start();
}
});
stoff.addOnCompletedHandler(new ActionObserver() {
public void onCompleted() {
ston.start();
}
});
// Start the first action
sa.start();
}
This way, you don't need to specify the duration of the SelectedItemAnimationHandler when you set up the ScreenTransitionOffHandler.
EDIT: Tried to make implementation of the Observer pattern clearer.
EDIT 2: Changed runNow(action) to action.start()
Related
I have recently been developing a game for android. The game is of a similar format to the classic Pokemon games (quite complex). I have got quite far without any problems. However, I am finding it difficult to develop the dialogue (typewriter text) boxes that appear at the bottom of the screen when someone is talking. I am stuck on waiting for any input without blocking the render and update methods (as they all run on the same thread).
This is a simplified version of my game loop, outlining the structure and what I do each frame. The update method shown is called through the View#onDraw method.
public static void update(Canvas canvas, GameView view){
//time operations (calculating delta etc.)
long cTime = System.currentTimeMillis();
delta = cTime - time;
time = cTime;
globals.put("time", time);
globals.put("delta", delta);//set vars for scripts
camera.applyToCanvas(canvas);//apply camera matrix to canvas
if(map != null)map.update();
if(battle != null)map.update();
Effect.updateAll();//update everything (game logic)
render.load(canvas);//load the canvas into my custom render engine
render();//call render method (shown below)
view.invalidate();//reset view for redraw
}
public static void render(){
render.reset();//clears the canvas using canvas.setColor(Color.BLACK)
if(map != null)map.draw();
if(battle != null)battle.draw();
if(dialog != null)dialog.draw();
if(gui != null)gui.draw(); //draw everything using the renderengine
}
As you can see, these operations update all the game components (map, battles, guis etc.) and then renders them to the screen. By looking at the code, it's clear that I'm running these operations on the same thread, so this thread can obviously not be blocked (otherwise the game will just stop).
This is where my problem is. I use an in game gui with a few buttons. These buttons are assigned to 8 integers (0-8) and when the up button is pressed for example, that input data is passed through the game to the existing dialog or battle or whatever needs it. These buttons rely on the main activity's touch events where the MotionEvent which, as a result of running the game loop off of the onDraw method, tuns on the same thread as the game itself. Here is how I handle dialogs:
I use javascript (rhino parser) as follows (passing a dialog object to the script in the variable 'dialog'):
var d = dialog.show("Hello! How are you.");
To get the input, I call the getInput method which takes in the dialog, and up to 4 strings as selection options. This method is supposed to return an integer value. This can be called through the script as follows:
var response = dialog.getInput(d, "I'm fine, thank you!", "Who wants to know.");
The getInput method is as follows in my Dialog class:
public static int getInput(Dialog d, String... args){
d.waitingForInput = true;
d.lastInput = -1;
while(d.waitingForInput || d.lastInput == -1){
//render options
//main thread is obviously blocked here.
}
return d.getLastInput();//returns the d.lastInput and resets waitingForInput and lastInput. The script can then use this value to decide what to do.
}
Now my main question is how to run this method without blocking the render and update thread. More specifically setting the value of d.lastInput and d.waitingForInput when the user touches a certain region of the screen (where the gui select button is).
If there are any doubts about what I am trying to ask in this question, please leave a comment as I am quite tired and have spent some time trying to solve this.
EDIT:
I have thought about running the input on a separate thread but this will still lead to blocking other input methods from being called (such as changing the selected option in the dialog).
If you don't want to stop the threads and you are already half way through
Method1: Use ConcurrentLinkedQueue, ArrayBlockingQueue and its families as static variable and put your values inside it.
Method2: you use can use TCP/UDP sockets using localhost adapter like a message queue system and try to get those values with the same ConcurrentLinkedQueue, ArrayBlockingQueue technique
Try to refer any opensource java game engine source codes and identify how they did or you can use those game engines, like "jMonkeyEngine" "LWJGL" ...etc
I have decided to approach this through a form of event handlers instead. When the required input is down, the specified script is run by the game.
I'm writing a 2D polygon and physics editor, one functionality is to set a rotation limit for joints.
To use this functionality, the user clicks and drags a line between the joint points which need to receive the limit.
The logic of determining if the pick is valid happens outside of the GUI code.
If a pick is found, I wanted to pop up a JOptionPane.showInputDialog where the user can input the limit.
Thing is, if I do it directly, the program becomes unresponsive, I figure it's because of threading.
I's there a way to define an event listener the GUI can use that doesn't require an actual GUI component?
I want to send an event that also contains a reference to the target object to that component, then telling it that a valid pick has been made and user input is required, and then send the value back via a method of the target object.
I am very inexperienced with Swing.
My hunch is that I might be able to add an ActionListener to the main window, but I don't know how I could address that listener specifically.
As in, how would I need to define an Action that only gets processed by that particular listener?
If that is actually possible, of course.
So far I have only used listeners to let the GUI talk to the logic, not the other way around...
Edit:
The program becomes unresponsive the movement I call
result = JOptionPane.showInputDialog(this,"Enter Limit.");
That just breaks it. Can't even enter anything into the textbox, nor close it, etc.
I figure it's because it spawns a modal dialog that pauses some thread, and calling it from somewhere in the bowels of non GUI code is just not the thing I should do, but I'm too inexperienced to know another way...
Edit2:
I should add that I can use JOptionPane.showInputDialog without any problems if I spawn it, for example, after clicking a button or choosing a popup menu option.
In fact that's how I rename the items I am working with.
But I assume at that point, the dialog is being spawned inside the GUI thread, or this Event Dispatcher queue thing.
The problem with this though is, that this takes visible, interactive GUI components that fire that event.
What I'd like, however, is some sort of component that would spawn JOptionPane.showInputDialog just like a clicked button or context menu would, but without having to be interacted with by the user, but instead by the code.
I guess I could use invisible buttons and emulate mouseclick events, but that's pretty hacky...
Also, I tried spawning Threads and Runnables which spawned the JOptionPane.showInputDialog, but that didn't help either.
Unless I spawn the JOptionPane from a GUI source, everything stalls, and the dialog won't work.
The publisher will have a public add/remove listener, where the subscriber will add itself or be added via another channel to the EventListenerList in the publisher.
You can create your own listener interface that extends EventListener and a function to shoot an event. Below is an example:
import java.util.EventListener;
public interface MyEventListener extends EventListener {
public void myEventOccurred(MyEvent event);
}
You can then create your custom event class, "MyEvent" in the example above like:
import java.util.EventObject;
public class MyEvent extends EventObject {
// customer fields and methods here
public MyEvent(Object source) //more possible args here {
super(source);
//other things here to do what you want
}
}
Now you can have your subscriber implement MyEventListener and override the myEventOccurred(..) method.
Another approach would be to use the SwingWorker class to execute the logic of determining the pick in a dedicated thread without blocking the GUI dispatch thread, and use its callback method to execute the GUI action (open the input dialog).
See : http://docs.oracle.com/javase/6/docs/api/javax/swing/SwingWorker.html
(This page has a better explanation of concept than I could write.)
It should be possible for your background thread to spawn a dialog with invokeAndWait():
final double[] result = new double[1];
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
try {
result[0] = Double.parseDouble(
JOptionPane.showInputDialog("Enter value:"));
} catch(NumberFormatException e) {
result[0] = -1;
}
}
}
// ... do something with result[0]
Here I made the result an array just so that it can be final (accessible to the anonymous class) and also mutable.
I'm working on a Java Game and I've come to a point where I'm having problems with the KeyListeners/KeyBinding. What I basically want to do is temporarily disable the keyboard/do not allow more inputs when an animation occurs. This animation is generated by updating data.
What I currently get is that I press the key for the animation, the animation starts, and I press another key that does some other function. It gets added to the stack/queue(?) of the keyboardlistener and triggers when the first animation finishes.
I'm using a JPanel that implements KeyListener.
To give an idea of the code:
public void keyPressed(KeyEvent arg0) {
//Prevents Repeated keys
pressed.add(arg0);
if (pressed.size() == 1) {
int key = ((KeyEvent) pressed.toArray()[0]).getKeyCode();
if (key == KeyEvent.VK_ENTER) {
doSomeAnimation();
} else if (key == KeyEvent.VK_SPACE) {
doADifferentAnimation();
}
Update();
}
}
Things I've tried:
1) Set the focusable(false) on the JPanel before the calls to the animations. Then set the focusable(true) and grab the focus when they've been completed.
2) Used a boolean to track when an animation occurred.
3) Use Key Bindings.
No matter what method I used, I always ended up with the problem that I would still take in input from the keyboard when the animation was occurring. Then, once that animation was finished, it'd go to the next element in the stack/queue(?) and process that. Also, these animations would need to occur more than once (so using an array of booleans to verify if it's been executed already wouldn't be helpful).
So, if you have any idea or help (or places to point me to) that would be greatly appreciated.
Some Extra Information: Java 1.6, IDE Eclipse, MVC structure. (This in question is the Controller/Model)
Assuming your animation is driven by an instance of javax.swing.Timer, the queue in question is the EventQueue, which runs events in "the same order as they are enqueued" by the Timer. Because it is impractical to stop other devices on the host platform from evoking your listeners, you have to track the effect in your application. As a concrete example, this game has several overloads of the model's move() method to handle input from disparate sources: keyboard, mouse or animation timer. The timer may be toggled on or off to see its effect. This example, which supplants the EventQueue with a custom implementation, may also offer some insight.
I'm doing a path-finding project as part of my 4th year software engineering degree.
We're suppose to give visual representation to a bunch of multi-agent pathfinding algorithm. The simplest one is A* adapted for multiagents.
Anyway our environment is a grid map where every cell can be either blocked or used as part of an agent's path. What I want to do is use animation to give a good representation of the final movement of the agent, but animating color change in my grid.
I.E paint every step in the path for a second or so with some color to show how the agent moves.
And the other thing I want to do is to represent the way the algorithm works by painting the changes in the open list and closed list of the A* algorithm while its doing its calculation.
I'm using an adapted version of the observer design pattern to send events from my algorithm layer to my controller and GUI layer.
What I want to do in the GUI layer is every time a tile is added to the open list, I want to have that cell painted in some color and then have it fade away according to a predefined timer or maybe later add a slider to control this timer.
I looked at the code here. It seems pretty simple, the problem is that every tile animation has to be independent of the others to allow the algorithm and everything to keep running and different animations to start.
So what's the best way to achieve the results I'm looking for? Should I just open a different thread for each animation or have a pre-made thread for each cell?
Would that be an overkill for the application, since there can be up to 1000 cells and therefore close to 1000 threads performing animation.
Another issue I think I might encounter is the fact that it might happen that a cell will start its color fading animation and then will have to restart and I don't want the two animations to go at the same time (only one thread performing animation for the same cell at the same time).
I hope I was clear enough with what I'm trying to achieve, if someone has any ideas or thought it could really help me with my project.
You can find Trident animation library useful. More information at http://kenai.com/projects/trident/pages/Home
I would consider a scenario with a single animation thread only. You might e.g. try the following strategy:
standard event thread for swing events
one worker thread for your logic
only one additional for all animations
This third thread manages all animation within your gui. Therefore it maintains a list of animation actions to perform together with their timestamp. Such an action can be e.g. "set color of cell [1,2] to CF0000 # 17:01:00" in an approriate data structure. This list of actions is then filled by the worker thread with the animation actions (e.g. you may add several actions at once for a fading cell - 1) set to 100% # now; 2) set to 75% # now+10s; 3) set to 50% # now+20s ...). Make sure that this list is properly synchronized since it will be accessed from both threads.
If you keep this list sorted by timestamp it is quite easy to determine the which actions this thread has to do at any time. This thread has then a quite simple loop, e.g. something like
while(true) {
AnimationAction action = list.get(0);
if(action!=null && action.timestamp <= now()) {
action.perform(); // <= be sure that paint events occur in the edt
list.remove(0);
continue;
}
sleep(...);
}
Note that you can determine the time to sleep from the timestamp of the next action but consider that a new animation event arriving might have to interrupt this. Otherwise you can also sleep for some short amount of time.
Regarding your second question this thread might remove any actions from this list on demand for a special cell if a new action arrives. Therefore you might also maintain a secondary data structure in order to do this efficiently.
I'd use javax.swing.Timer and AlphaComposite, as demonstrated here.
I am building a swing application. At some point, I have to start an "animation":
...
jpanel1.setBackground(Color.Black);
Delay(milli)
jpanel1.setBackground(Color.White);
...
and so on.
The gui itself and all the logic behind it work.It is just this time depended color-changing that does not. I have read, that swing is not thread safe, but all the examples I found showed me how to start another thread (for example in the background) but never how to stop the current swing-gui thread.
Edit:
The application should work as following:
configuration files are read, jframe is set up.
some simple questions are beeing asked
a dialogue is opened, which explains the animation.
after the user clicked "ok" the animation - some color flashing - is started. the color and the delay between the color-changing is depended on the configuration
another dialogue is opened and the programm continues -> new jpanel inside the jframe, buttons and so on.
the online thing that does not work are the delays between the color-changing. I understand now why it does not work and I am trying to build a timer, which activates a actionlister, which then changes the color and stops the timer... it just seems so much work for a simple delay... and I have to reorganize the entire animation in the application.
Take a look at: https://timingframework.dev.java.net/
and the samples that come in http://filthyrichclients.org/
They provide some very good information on how animation work and using the Timer framework. You'll have a good understanding of how it works.
I did a sample animation here with Swing after reading those:
count down demo app http://img580.imageshack.us/img580/742/capturadepantalla201004wd.png
Java application featuring blog.stackoverflow.com page ( click on image to see the demo video )
But I'm not even sure what is what you want to achieve.
EDIT
I read about the timing framework to understand better what is all about, but I actually didn't use it ( it is useful to create animations with no linear times - ie no every second as mine, but things like 1, 5, 3, 2 seconds )
The code I'm using in the demo above is exactly this:
final Timer imageTimer = new Timer();
imageTimer.schedule( new TimerTask() {
public void run() {
changeImage();
}
}, 0, 10000 ); //<-- every 10 seconds.
The animation for the "stackoverflowing" and the count down use a similar approach.
You do not want to stop the GUI thread, even if you want to have a flashing effect. This is because other basic actions, like repainting when the GUI is hidden by other windows, will be stalled. Take a look at Timer. It will allow you to have an event fired on an interval and you can handle that, in the GUI thread, in your actionPerformed method.
You will want to use the javax.swing.Timer class and not the java.util.Timer class.
The later is preferred when you need general timing the former is preferred for UI updating/changes.
See http://java.sun.com/docs/books/tutorial/uiswing/misc/timer.html
You may also want to look at https://timingframework.dev.java.net/.
Do the timer on another thread and when the timer goes off it can send an update message for the animation to draw the next frame.
Another consideration is the delay itself. Don't pick a fixed delay-interval. Old games used to do that and they become unplayable on faster computers. Instead what the newer games do is use the speed of the current CPU to figure out how many update events they need a second at runtime, call it a 'delay-factor', and is set when the program starts up. . The timer uses the delay factor so the animation displays correctly even on machines of different clock-speed.