So, I'm creating a isometric game in JAVA; to put it simply, it has a map made of tiles, and when the user drag the mouse on the screen, the map moves. To give you guys an idea, it currently looks like this:
Before the actual prototype version, I built a small java application that had no "Game Loop" per se; the only thing updating the tile-map position was the event listeners for the mouse dragging, and it called the repaint() method after the movement update. It worked fine, and I could select Tiles and move the map without a problem.
Since then, I rebuild the prototype thinking in developing something more like a real game engine, with a Game States Manager and a real Game Loop; the Game Loop code looks like this:
init();
long start;
long elapsed;
long wait;
while(running){
start = System.nanoTime();
update();
draw();
drawToScreen();
elapsed = System.nanoTime() - start;
wait = targetTime - elapsed / 1000000;
if(wait < 0)wait = 5;
try{
Thread.sleep(wait);
} catch(Exception e) {
e.printStackTrace();
}
}
A GameStateManager is acessed with the update() and draw() methods, so I can draw the map just fine, like the older prototype. The problem happened when I dragged the mouse on the screen so the map could move; the animation became VERY croppy, in the extent that I could actually see the black background between the tiles moving before the final position of all tiles.
At first I thought the problem was in a concurrency between the Game Loop thread and the event listeners of the main class, because the mouseDragged event could be called while the JPanel was trying to draw what the map was like a moment ago; then I tested this on my game loop code:
SwingUtilities.invokeLater(new Runnable(){
public void run(){
draw();
drawToScreen();
}
});
//draw();
//drawToScreen();
And now the prototype is working just fine.
So, my question is, is this performance heavy, or just a bad practice in Java? Also, was my "concurrency" assumption right? This is my first time dealing with threads in Java, so I don't really know if I dealed with the problem the right way.
obs: This is the entire class I made in which the game loop is in:
http://pastebin.com/RMRHYc5X
obs2: If someone is interested, the game loop logic I worked in was based on a youtube java tutorial made by pj644 named "2D Game Programming in Java".
obs3: Sorry if the question became too big, this is my first time posting a question on this site!
Swing isn't really a great technology for writing games, it updates slowly and is quite limited in a number of ways.
Having said that yes calling invokeLater or using a SwingWorker would be the correct way to update the screen when your game thread has done its work.
Before you go too much further though I really suggest looking at a 2d or 3d java graphics and game framework. You will be able to get much better results that way and a lot of the work in terms of setting up the game loop, updates, managing frame rates, etc will be done for you.
Related
I am creating a bullet hell game where the player tries to dodge all the bullets on screen. My current game loop updates all the objects on the screen using multiple for loops in multiple methods.
Since this is a bullet hell game, there are could be up to hundreds of bullets on screen at the same time. Also I have a method called checkCollisions that checks if the sprite of a bullet over laps a player. Due to this, the game usually starts lagging when the amount of bullets reaches over a hundred bullets because its essentially iterating over the list of bullets twice.
I thought about using running a thread on the side to update the positions of the bullets and to check the collisions. The code is shown below. Each thread essentially just calls the update methods in the main game class. However, this just made the game lag more at lower bullet numbers. I'm not sure if this is because I'm creating new thread classes or for some other reason. Or maybe it is because of all the concurrentModification errors the program is throwing.
public void actionPerformed(ActionEvent e) {
if (inGame) {
updateEnemies();
projectileChecker = new Thread(new checkProjectiles(this));
projectileChecker.start();
//updateProjectiles();
updateBags();
updateCharacter();
//checkCollisions();
collisionChecker = new Thread(new checkCollision(this));
collisionChecker.start();
repaint();
}
}
Currently I've thought of 4 ways to solve this.
Continue with the thread method but (1) Use a thread executor to stop defining new threads, or (2) use a while loop inside the thread to call the method so don't have to define new threads (This seems to break the code, bullets show on screen but no longer move/disappear)
Combine update projectiles and collision checker, this seems like doing twice the work for half the iterations, which doesn't seem like it will make much of a difference
Stop repainting after every call of update projectile/collision check, only repaint at 60 fps or something like that.
Stop drawing the background image every time it repaints. (Not that useful due to in the future would want to create a camera object that follows the player around a bigger map)
I've tried the first two and the code just doesn't work, and I have no idea how to approach the last 2. Does anyone have any suggestions?
Unrelated note, a profiler is showing the number of active threads increasing constantly through the runtime of the program. Maybe that has an effect? Also, shows that a majority of the time is taken by paintComponent.
I just finished developing my mini-game on Android and I got some questions about perfomance and generally "how to": If I have 25+ objects on the creeen (just a polygon with 7-8 angles) its starts to lag hard and CPU usage is very high (15-20% without colision detection, up to 50% with collision detection on samsung note 10.1 tablet).
So I have ~25 polygons (asteroids) and they are always "flying". So to move them I make a Timer, right? On TimerTask I got something like this
public void move() {
translate[1] += speed[1];
translate[0] += speed[0];
updateTranslateMatrix(); // updating translate matrix and then send it into vertex shader
updateAABBCoords(); // update coordinates of Axis-aligned bounding box
updateCoordsByTranslate(); // update coordinates of verticles (to be able to define exact collision (with bullets and starship))
}
Is there something unnecessary in this method?
Also I want to ask if it is OK to run this timer every 17 ms? Or 17 ms is too often? I feel smoothness of movement only at 17 ms, may be I am doing it wrong? And same Timer interval I got on starship/bullets movement and on Collision detection.
Help me, please. I feel like missing something huge and fundamental, because 50% CPU on note 10.1 in that simple Asteroids game is not normal.
One key issue, I believe, is that you are assigning an individual Timer to every object instead of employing a general purpose game loop. A vast majority of games use a game loop which runs continuously and can be split, typically, into two components: Update and Render.
An article on basic game loop design for Java/Android
An answer to a relevant question on game loop design on gamedev.stackexchange.com
When using a game loop you can not guarantee being able to update exactly every 17ms or some other arbitrary duration. Instead, the Update and Render methods receive a DeltaTime parameter which is the time since the last frame.
This is then used when, for example, getting new object positions by multiplying it with the object's velocity. Doing so allows for smooth interpolation of position and ensures that object speed is not affected by CPU speed.
I looked up many threads on how to use delta time and I can't figure it out.
I want my guy to move at a constant speed every time I run the game.
So I have:
timer = new Timer(9, this);
timer.start();
then the paint method.
I tried doing start time at the beginning of the paint method and then a current time at the end of it. How would I make it affect the timer's speed or how far the player moves. I've tried multiplying the time delta by the increment to the x. nHeroX = dx*deltaTIme;
I feel like it's very simple I just need someone to tell me straight what to do please.
Traditionally, game programming relies on a continuous loop.
Anyway, all I have realized.
In this loop, you should separate model update and graphic update.
In your snipset, you seem to try mixing the two things.
In this loop :
- In a first time, you let the model to update.For example : guy's move from x to x1.
- In a second time, you must refresh the graphics to allow the guy to have a new position in the screen.
The speed of your guy depends on the guy model (ex: constant in your guy class).
But the speed of another type of guy could be different.
The general speed of your game relies on the FPS set in your main loop.
You can see an example on this post :
Java Main Game Loop
Good luck
Get the system time from the System object.
Get it again during your animation. Delta time is nothing more than subtraction.
Get rid of the JavaScript tag. The languages are completely different.
I am developing a game, and just wanted to test it on a different computer to check if the resolutions are ok and all that stuff but noticed one big problem, the game runs in slow motion for some reason... Not laggy, but slow motion..
My game loop is a temporary:
while(gameisRunnin){
doStuff();
Thread.sleep(1000/60);
But after the test, I've tried to check how much time does it take to do the doStuff(); code and I tested it like this:
while(gameisRunnin){
long startT = System.currentTimeMillis();
doStuff();
long stopT = System.currentTimeMillis();
System.out.println(stopT-startT);
Thread.sleep(1000/60);
The result it gives me is 0, on both computers, (On the one I am developing the game which runs in the perfect speed, and on the pc that it runs in slow motion..
Also I tested it with nano time, it gives me like 50000-80000 on both computes too (pretty much same result.
Seriously what's up? Could a superman save me?
UPDATE:
Ok so when I run the game on the other computer NOT on full screen, it's runs fine, but when it is on full screen, it's slowmotion
Update:
Looks like I am the superhero here, I've set the displaymode the refresh rate to unknown, I guess that was the whole problem...
You've to use something what is usually called "delta time". Basically it means, that you measure how long it takes to do one iteration of the game loop and then use this number for all the movements.
This is because of the different count of FPS on different computers. Instead of moving objects for just constant amount of pixels, you're defining speed and calculating the actual size of movement dynamically.
Short example:
public void gameLoop() {
long initialTime = System.nanoTime();
game.redraw();
game.update(System.nanoTime() - initialTime);
}
// inside the class Game
public void update(long deltaTime) {
someObject.moveToRight(deltaTime * speed);
}
The answer is that the refresh rate of the game wasn't supported by the monitor, changing the refresh-rate from 60 to DisplayMode.REFRESH_RATE_UNKNOWN fixes the slowmotion problem.
Read this article: click here
Also, as a side note, use System.nanoTime() because System.getTimeMillis() isn't as accurate.
I'm making a simple 2d shooter like space invaders, and I want to move my "enemy" only horizontally, from one side to another with the same speed.
How can I do that?
I have already did it for my "hero" with a KeyListener but I don't know how to do it automatically.
Here there's some code that might help.
public SimpleEnemy(String linkimg, int x, int y, int life) {
super(linkimg, x, y);
this.life=life;
this.isMoving=false;
}
public void move() {
x += dx;
y += dy;
}
What you need is a game loop. For example a while-loop that never ends (endless-loop) and which updates your hero position if needed.
while (true) {
// insert statement if move is needed here
move();
}
That's a pretty basic example but it should make things clear.
Since I assume that you are using java, you can take a look at some game frameworks like jgame. These frameworks take a similar approach and make it more comfortable to work with.
Edit:
Note that processors are running extremely fast these days and this endless-loop will be run very very often in a small amount of time (like 1000+ times per second). So you might have to limit the execution time of this loop, or your hero will be outside the screen faster you can look.
You can achive this with a sleep or something similar. Also these frameworks I mentioned will have this limitation on board.