How to make my game stop after ten seconds in libgdx? - java

I'm almost done with my project to make a very simple game. The point of the game is to count how many times the user touches the screen and compare it to the number of times an object popped up on the screen to be touched. It's considered a win if number of touches = number of objects. All of this is to happen in 10 seconds, and I have no idea where to start on how to time the game? (It's supposed to be a veryyy very simple game just to learn how to use libgdx)
As of now, there's a start screen that the user touches to start and then the game starts where objects pop up to be touched. The problem is that it's basically an endless game right now... Here's how I make an object "randomly pop up":
if (Gdx.input.isTouched()) {
touchCount++;
Vector3 touchPos = new Vector3();
touchPos.set(Gdx.input.getX(), Gdx.input.getY(), 0);
camera.unproject(touchPos);
visual.x = MathUtils.random(10, 700);
visual.y = MathUtils.random(100, 400);
}
Do I have to put some built in timer function in this part of the code? And how to I go about tracking the touches to compare with the number of objects that popped up?
Thanks, any advice would be very appreciated!

System.currentTimeMillis() gives you current time in milliseconds
For example you can do something like this
private long time;
public void show(){
//...
time = System.currentTimeMillis();
}
public void draw(){
//...
if(System.currentTimeMillis()>time+10000){
System.out.println("after 10 seconds");
}
}

You may use old fashioned java way either:
Timer timer = new java.util.Timer();
timer.schedule(new TimerTask() {
#Override
public void run() {
// Pause your game or just close it...
Gdx.app.exit();
}
}, 10000L);
Of course it's better to use synchronous timer approach, but for fast debuging or prototyping needs its sometimes more convenient.

Use the delta value inside your render() method.
render(float delta){
// ......
if (yeni_oyun_mesaji_var_MI)// a boolean value to increment my time value only it is needed.
oyun_uyari_zamani_tutucu += delta;
if (oyun_uyari_zamani_tutucu > oyun_uyari_zaman_siniri) {// after some time (**oyun_uyari_zaman_siniri**) do what you need
oyun_uyari_zamani_tutucu = 0f;
oyun_durum_mesaji_str = "";
yeni_oyun_mesaji_var_MI = false;
Gdx.app.log(TAG, "Uyarı Kapatıldı!");
}
}

Related

Can a .exe file be made to run automatically when the mose isn't moved?

i've made a java aplication that displays the current time as a digital clock, and i would like to make the file automatically run after the mouse isn't moved for 10 minutes.Does anyone have any ideas?
P.S. I'm new to StackOverflow and to coding as well at that, so forgive me if this is actualy a stupid question.
As per your comment, Java doesn't make .exe files. You would need to place your jar file into a special executable wrapper to accomplish that. Launch4j can do that for you.
You would want to run your application as a Service. This SO Thread can shed some additional light on that subject.
In your application:
Set your clock component so that it is non-visible. Create a TimerTask to monitor the System Mouse pointer location (x, y). Utilize the MouseInfo Class within the TimerTask's run() method to track the Mouse Pointer location. Keep track of the time from the mouse last movement. If 10 minutes has elapsed with no mouse movement then display your clock (make it visible). If you like, when the mouse is moved again make the clock non-visible again. Your code in relation to this might look something like this:
First declare and initialize four (4) Class Member Variables:
int mouseX = 0;
int mouseY = 0;
long timeOfLastMovement = 0L;
TimerTask mouseMonitorTask;
Somewhere in your Class copy/paste this method. Make the required changes as you see fit:
private void startMouseMonitoring() {
mouseMonitorTask = new TimerTask() {
#Override
public void run() {
PointerInfo info = MouseInfo.getPointerInfo();
Point pointerLocation = info.getLocation();
long currentTime = java.lang.System.currentTimeMillis();
//System.out.format("Mouse Location - X: %d, Y: %d\n", pointerLocation.x, pointerLocation.y);
float elapsedTime = (((currentTime - timeOfLastMovement) / 1000F) / 60);
if (pointerLocation.x == mouseX && pointerLocation.y == mouseY) {
// Check if 10 minutes has elapsed with no mouse movement
if (elapsedTime >= 10.0f) {
/* Make Clock Visible if it isn't already
or whatever else you want to do. */
if (clockIsNonVisible) {
// clock.setVisible(true);
}
}
}
else {
mouseX = pointerLocation.x;
mouseY = pointerLocation.y;
timeOfLastMovement = currentTime;
// Make clock non-visible if you like.
if (clockIsVisible) {
// clock.setVisible(false);
}
}
try {
Thread.sleep(500);
}
catch (InterruptedException e) {
cancel();
e.printStackTrace();
}
}
};
Timer monitorTimer = new Timer("Timer");
long delay = 1000L; // Start Delay: 1 second
long period = 1000L; // Cycle every: 1 second
monitorTimer.scheduleAtFixedRate(mouseMonitorTask, delay, period);
}
Call the startMouseMonitoring() method and the ball is rolling. I'm sure you'll figure out the rest.
If you want to cancel the TimerTask and Mouse Monitoring then you can call the TimerTask#cancel() method:
mouseMonitorTask.cancel();

How to prevent repeated actions from a key being held down?

I'm trying to make a simple action in a Java FX "game" in which an image of a pig 'jumps' upwards every time the spacebar is pressed. Here is the code for the key event handlers and the Animation Timer that I'm using to actually carry out the action.
Key Handlers:
ArrayList<String> in = new ArrayList<String>();
s.setOnKeyPressed(
new EventHandler<KeyEvent>()
{
public void handle(KeyEvent e)
{
String code = e.getCode().toString();
if ( !in.contains(code) ){
in.add( code );
}
}
});
s.setOnKeyReleased(
new EventHandler<KeyEvent>()
{
public void handle(KeyEvent e)
{
String code = e.getCode().toString();
in.remove( code );
}
});
Animation timer:
new AnimationTimer()
{
double q = 200;
public void handle(long currentNanoTime)
{
double t = (currentNanoTime - startNanoTime) / 4000000.0;
if(in.contains("SPACE")){
q -= 20;
}
double y = q + t;
if(y >= 520){
gc.drawImage(background1, 0, 0, 1160, 740);
gc.drawImage(pig, 90, 520, 125, 100);
}else{
gc.drawImage(background1, 0, 0, 1160, 740);
gc.drawImage(pig, 90, y, 125, 100);
}
}
}.start();
So as you can see I'm having the animation timer simply cause the 'pig' to gradually fall down the y-axis, and when the spacebar is pressed, it is given a slight boost upwards.
The problem is that if the spacebar is held down, the pig just flies continuously upwards without stopping. I want this to be prevented so that the spacebar must be repeatedly tapped and not just held down. So I want only one 'jump' per spacebar press. Nothing that I've tried to workaround it has worked. How can I do this?
EDIT: I reworked the answer. The original solution used a counter which prevented the pressed key from having any impact for a certain period of time. Unfortunately, this was not what this question was about. :) The current solution is more straight forward and uses only a simple boolean lock.
Before answering the question, here are some annoying tips: I would suggest to use Map<KeyCode, Boolean> instead of List<String> to store information about what keys are currently pressed. It will simplify your code in terms of readability and give it a performance boost at the same time. Next, creating a dedicated object to store information about the pig (haha!) might be a good idea. Finally, using constants instead of hard coded literal values is a good practice.
Also, note that you don't actually need to store information about whether the spacebar is pressed or not and then refer to it from the timer thread. This would only be necessary if you WANTED the pig to be controlled by HOLDING the spacebar. But since you want it to jump only when the spacebar is pressed, you could tell the pig to switch into "jump" state directly from the handler. Of course, this won't solve your problem, because the onKeyPressed handler is invoked repeatedly when holding a key for a longer period of time. But I thought it was worth mentioning. :)
Now, to answer the question. If you want to quickfix your current solution and ignore all the "good practice" crap, focus only on the jumpLock field of the Pig class. The trick is to keep telling the pig to jump repeatedly as you are currently doing, BUT making sure that the pig will obey only when the jumpLock allows it to do so.
NOTE: The following solution assumes you will update the state of your game using a fixed interval like every 30 milliseconds. But as noted at the end, this solution can be easily modified to use FPS based timer.
The following class contains constants which you may want to change when tweaking your game in the future:
public final class Settings {
private Settings() {
}
public static final double BOOST_VELOCITY = 10.0;
public static final double GRAVITY = 0.3;
}
This class represents the pig. The x and y fields store information about current position of the pig. velocityX and velocityY are vectors containing information about the direction and "speed" of the pig in X and Y axis, respectively. jumpLock is a simple boolean flag which is actually a solution to your problem. Whenever user makes a jump, this lock is set to true. And it will remain so until it will be told to release the lock, which will happen when user releases the spacebar.
public final class Pig {
private double x;
private double y;
private double velocityX;
private double velocityY;
private boolean jumpLock;
public Pig() {
// ...
}
public void timeChanged() {
x += velocityX;
y += velocityY;
velocityY -= Settings.GRAVITY;
}
public void jumpBoost() {
if (!jumpLock) {
velocityY = Settings.BOOST_VELOCITY;
jumpLock = true;
}
}
public void releaseLock() {
jumpLock = false;
}
public double getX() {
return x;
}
public double getY() {
return y;
}
}
Your handlers could look like this. Notice that Map<KeyCode, Boolean> is used to store information about currently pressed keys. It performs better than List<String> in this situation. Also adding the #Override annotation is a good practice even when overriding methods which are abstract:
final Map<KeyCode, Boolean> keyboard = new HashMap<>();
keyboard.put(KeyCode.SPACE, false);
scene.setOnKeyPressed(
new EventHandler<KeyEvent>() {
#Override
public void handle(KeyEvent e) {
if (e.getCode() == KeyCode.SPACE) {
keyboard.put(e.getCode(), true);
// You could alternately call pig.jumpBoost()
// directly from this handler and not having to
// deal with the 'keyboard' map at all
// as illustrated with by pig.releaseLock()
// in the next handler
}
}
});
scene.setOnKeyReleased(
new EventHandler<KeyEvent>() {
#Override
public void handle(KeyEvent e) {
if (e.getCode() == KeyCode.SPACE) {
keyboard.put(e.getCode(), false);
pig.releaseLock(); // IMPORTANT!!!
}
}
});
Finally, the following snippet of code must be executed repeatedly. This solution assumes this code will be executed in a fixed interval like every 30 milliseconds. If you are using FPS based timer (meaning there will be irregular interval between executions), you should pass the time which elapsed from the previous update as a parameter to the timeChanged() method, and multiply with it whatever necessary inside that method.
pig.timeChanged();
if (keyboard.get(KeyCode.SPACE)) {
pig.jumpBoost();
}
// Note that pig.releaseLock() could be called in else
// branch here and not in the onKeyReleased handler.
// Choose whatever solution suits you best.
// + draw image of the pig on pig.getX() and pig.getY() coordinates
Hope I got this right. I was almost asleep when writing this post and misunderstood the question at first. But I really need to earn some reputation points to be allowed to comment on an issue which is currently important to me. Haha! :D:D

JAVA GAME loop?

I have a problem with my java game. I’m beginner, but i have to write it as a school project.
Game is called „Birthday Cake” there is 7 candles on the cake and randomly one of it is showing for let say 30s and during this time u have to click on it to get point, if u don’t click on it during this time next candle will show. Game end when 10 candle shows.
I made for loop and i tried to make it work for sooo long that I’m dying from frustration
my for loop works but it is so fast that i use Thread.sleep(1000), i tried lots of solutions it looks ok. BUT when i start my game nothing is happening and after few seconds all 7 candles shows and quickly disappear. I think I’m doing something wrong, but i have no idea what.
if(Dane.start){
int liczbaLosowa = 0;
for(int i=0; i<10 ;i++){
liczbaLosowa = (int)(Math.random()*7);
this.wspX= wspX_p[liczbaLosowa];
this.wspY= wspY_p[liczbaLosowa];
g2d.drawImage(plomienImg, wspX, wspY,null);
Toolkit.getDefaultToolkit().sync();
try {
Thread.sleep(1000);
} catch (Exception ex) { }
//repaint();
}
Dane.start=false;
}
this loop is inside JPanel paintComponent...
Never,
Never,
NEVER
call Thread.sleep(...) inside of paintComponent ever. Please understand that this method largely determines the perceived responsiveness of your program and anything that slows it down or freezes it will severely slow down and freeze your GUI. In fact you should never call Thread.sleep inside the code of most Swing programs (all that runs on the Swing event thread) but doing so in paintComponent is an even worse sin. The solution is to use a Swing Timer, and put code that you want to be called repeatedly at regular intervals inside of the Timer's ActionListener's actionPerformed code. Within this method, change the value held by fields within your class, for instance wspX and wspY, call repaint(), and then use those fields inside of paintComponent to determine what gets painted where.
Thread.sleep() is a bad call which can lead into many problems. i was told to never use it. instead i will show you the way i do my game loops. it might not be the perfect game loop but it is good.
i recommand implemets runnable and putting your loop in your run method.
public void run(){
init(); //initialisation of images, sound..etc. will be executed once only
int fps = 60 //number of update per second.
double tickPerSecond = 1000000000/fps;
double delta = 0;
long now;
long lastTime = System.nanoTime();
while(running){
now = System.nanoTime();
delta += (now - lastTime)/tickPerSecond;
lastTime = now;
if(delta >= 1){
tick();
render();
delta--;
}
}
}
private void init(){
//initialisation image, sound, loading world, generate maps....etc
}
private void tick(){
//tick player, world, entities..etc
}
private void render(){
//render graphics.
}
also dont forget to create start and stop method for the thread. you can change the fps to what number you would like, no need to go higher than 60.

Game timer won't stop

I am trying to set a timer to randomly set the frame in the screen, but then, depending on the boolean, set it back to normal. I have already tried .cancel() but it doesn't work. How could I stop this timer?:
if(e.getSource()==impossible){
impossiblity=!impossiblity;
System.out.println(impossiblity);
if(!impossiblity){
new Timer().schedule(new TimerTask() {
public void run() {
int randWidth=(int)((dim.width-gameFrame.getSize().width) * Math.random());
int randHeight=(int)((dim.height-gameFrame.getSize().height) * Math.random());
gameFrame.setLocation(randWidth, randHeight);//sets location to center
}
}, 1000, 1000);
} else gameFrame.setLocation(dim.width/2-gameFrame.getSize().width/2, 0);//sets Location to center of screen
}
right now it does set the gameframe back to normal but then goes right back to randomizing
In general trying to cancel timers or other threads from outside the thread is a bad idea and leads to all sorts of problems.
Your best bet is to set some sort of flag or counter that the TimerTask checks when it comes to run.

Limiting FPS for my game

Alright, i'm making a small game, and I need to limit my FPS, because, when I play on my really fast computer, I have around 850 FPS, and the game will go like, REALLY fast, and when I switch to my older computer, it goes alot slower, so I will need to limit my FPS to get this right. How do I limit my FPS?
My main game loop:
public void startGame(){
initialize();
while(true){
drawScreen();
drawBuffer();
plyMove();
//FPS counter
now=System.currentTimeMillis();
framesCount++;
if(now-framesTimer>1000){
framesTimer=now;
framesCountAvg=framesCount;
framesCount=0;
}
try{
Thread.sleep(14);
}catch(Exception ex){}
}
}
How I draw the screen, and draw all of the other things, players, the ball, etc.
The game is a pong remake, btw.
public void drawBuffer(){
Graphics2D g = buffer.createGraphics();
g.setColor(Color.BLACK);
g.fillRect(0,0,600,500);
g.setColor(Color.GREEN);
g.fillRect(ply1.getX(),ply1.getY(),ply1.getWidth(),ply1.getHeight());
g.setColor(Color.RED);
g.fillRect(ply2.getX(),ply2.getY(),ply2.getWidth(),ply2.getHeight());
g.setColor(Color.WHITE);
g.fillOval(ball1.getX(),ball1.getY(),ball1.getWidth(),ball1.getHeight());
g.drawString("" + framesCountAvg,10,10);
}
public void drawScreen(){
Graphics2D g = (Graphics2D)this.getGraphics();
g.drawImage(buffer,0,0,this);
Toolkit.getDefaultToolkit().sync();
g.dispose();
}
It sounds like your display it tied to your game engine. Make sure the two are disconnected. You want the game playing at the same speed no matter what the framerate is. If your fast computer repaints the screen faster that is ok if the engine is causing the game to play at a constant speed.
Rather than limiting your FPS, make it so that the game doesn't go really fast when the fps is high.
Presumably you have code that does certain things each frame e.g. moves the character forward if a button is pressed. What you want to do instead is move the character forward an amount dependent on the amount of time that has passed since the previous frame.
As aforementioned you need to separate your display loop from your update loop somewhere at the core of you game there is probably something like this
while (1)
{
drawscene();
update();
}
and in update you are advancing the time by a fixed amount e.g 0.17 sec. If you drawing at exactly 60fps then the animations are running in realtime, at 850fps everything would be sped by a factor 14 (0.17*850) to prevent this you should make your update time dependent. e.g.
elapsed = 0;
while (1)
{
start = time();
update(elapsed);
drawscene();
sleep(sleeptime);
end = time();
elapsed = end - start;
}
A description of what I meant in my comment. Inside your method plyMove(); I suspect there is something like
plyMove() {
ply1.x += amountX;
ply1.y += amountY;
}
Instead make the movement depending on the time elapsed
plyMove(double timeElapsed) {
ply1.x += amountX * timeElapsed;
ply1.y += amountY * timeElapsed;
}
where you calculate timeElapsed from the time difference inside your main loop and scale it accordingly to get a decent movement.
double timePrev = System.currentTimeMillis();
while(true) {
double timeNow = System.currentTimeMillis();
double elapsed = timeNow - timePrev;
drawScreen();
drawBuffer();
plyMove(0.001 * elapsed);
timePrev = timeNow;
}
If you really want a fixed timeframe game you could do this:
float timer = 0;
float prevTime= System.currentTimeMillis();
while(true)
{
draw();
float currentTime = System.currentTimeMillis();
timer += currentTime - prevTime;
while (timer > UPDATE_TIME) // To make sure that it still works properly when drawing takes too long
{
timer -= UPDATE_TIME;
update();
}
}
Where UPDATE_TIME is at what interval you want to update at in milliseconds.
One way would be using
try {
Thread.sleep(20);
} catch(InterruptedException e) {}
at the end of the main loop. Adjust the number to your needs.

Categories