I am trying to create a snake game where i use arrow keys or WASD to move the snake.
Initially the snake is slow and moves at 2 fps speed (like the classic snake game), i want the snake to move faster when i am holding down one of the keys and set it to original speed when i release it.
i tried changing the movement rate inside onKeyPressed like so:
scene.setOnKeyPressed(event -> {input = event.getCode().toString();
for (String acceptedKey : acceptedKeys) {
if (event.getCode().toString().contains(acceptedKey)) {
movement.setRate(4);
break;
}
}
});
Then changing it to normal rate when i released it:
scene.setOnKeyReleased(event -> movement.setRate(1));
*movement is a Timeline which starts since the beginning of game till stopped or death of snake.
The code works as i intended But every time i hit a key it speeds up for a cycle and then slows down.
I want the speed to change only when i hold a key for a certain duration (say 400 milliseconds) so is there a way i can put an if statement that checks duration of onKeypressed()?
Instead of handling this complicated logic in the listener, set a boolean flag that is flipped on when a key is pressed.
scene.setOnKeyPressed(event -> {input = event.getCode().toString();
for (String acceptedKey : acceptedKeys) {
if (event.getCode().toString().contains(acceptedKey)) {
acceptedKeyBeingPressed = true;
break;
}
}
});
scene.setOnKeyReleased(event -> acceptedKeyBeingPressed = false);
Then keep track of time with some sort of numTicksHeld variable when the flag acceptedKeyPressed is true.
Check if acceptedKeyPressed is true on each tick. Reset the numTicksHeld variable to 0 when acceptedKeyPressed is false. If it is true, increment by one. If numTicksHeld is above some threshold, movement.setRate(4).
I don't know what the tick/update method looks like in your framework but it would be something like:
public void tick() {
if(acceptedKeyPressed) {
numTicksHeld++;
if(numTicksHeld > KEY_HELD_THRESHOLD)
movement.setRate(4)
} else {
numTicksHeld = 0;
movement.setRate(1)
}
}
Related
I'm developing a game with JavaME and I need to count the number of collisions in my game.
I'm using the collidesWith() method, and I'm doing something like this:
private void checkCollision()
{
if (spBoy.collidesWith(spBall, true)) {
this.collides++;
if (this.collides == 3) {
//here I will show a Game Over image.
}
}
}
As you can see, if the number of collisions is 3, the game is over, but I can't count the number of collisions, because when I increment this.collides, automatically I have 3 collisions in one time.
I'm assuming you're calling checkCollision() inside your main loop. This means it gets called 30-60 times per second.
If the two sprites doesn't move at all during that second, there will be 30-60 collisions - because it's true in each cycle.
What you wanna do is add a timer where your spBoy sprite can't be hurt.
int safeTimer = 0;
int timeSinceLastLoop; // Add this calculation to your loop
private void checkCollision() {
safeTimer-= timeSinceLastLoop;
if (spBoy.collidesWith(spBall, true) && safeTimer<=0) {
this.collides++;
safeTimer=3000; // Wait 3 seconds till vulnerability
if (this.collides == 3) {
//here I will show a Game Over image.
}
}
}
I am using LibGdx to develop an android game . I have implemented the gesture listener class in my InputHandler class . Now in the tap method I have to implement two features , short jump and long jump on single tap and double tap respectively. When I try to implement it using the count value of the function , the problem is when I double tap the screen the count value firstly becomes 1 and then 2 so it does not go into the second if statement and and the feature of short jump occurs. So how to differentiate single jump from double jump? Below is the code
#Override
public boolean tap(float x, float y, int count, int button) {
// TODO Auto-generated method stub
if(count==1)
{
//feature 1
}
if(count==2)
{
//feature 2
}
return true;
}
two solutions comes to my mind:
Use delay technique which would come with following steps:
when tap-count is 2 : trigger action for double tap
when tap-count is 1 : wait some time, if not tapped second time trigger action for single tap
code would be something like:
if(count==1)
{
if(wait) //wait is a boolean tells if it was tapped once already
{
if(getCurrentTime() - startTime > interval) //getCurrentTime() return current time or frame count or something
{
wait = false;
//feature 1
}
}
else
{
wait = true;
startTime = getCurrentTime(); //start time keeps the time when tapped first one
}
}
if(count==2)
{
//feature 2
}
return true;
}
the problem I see here is firstly "how to choose long enough interval for waiting for secon tap?" - if you will choose to short it will be impossible to make double tap, if too long there will be a lag and user will see that the character is not jumping directly after tap
Divide jump for a pieces and trigger them depends on tap count
And it depends on your "jumping" mechanism. If it be something like:
A. add force to jump
B. keep adding some force for some time to keep object in the air
C. avoid adding force to take object down back to ground
you could modify time to keep object in the air longer. If your "jumping mechanism" is more like impuls adding force (in upper example it would be variant without B point) you could add the force in A again for a some time and if user tapped second time before this interval ends keep on adding it just longer.
This solution eliminates lag problem but depends on "jumping mechanism" you choose.
Regards,
MichaĆ
I have a simple game where a player shoots some bullets. However, I want to make it so that the player can only shoot a bullet every x seconds. How would I do this?
I have tried to do it by taking the average time between bullets and saying that if average time is less than one second don't let the space bar (the control for shooting) work. However, I don't know how to make the space bar not work, AND that would mean a player could just not shoot for a wile and then shoot a lot of bullets at once.
The method for shooting looks something like this:
public void keyPressed(KeyEvent e) {
if (!keysDown.contains(e.getKeyCode()))
keysDown.add(new Integer(e.getKeyCode()));
This adds the integer of the key value to an array, which is then read here:
if (keysDown.contains(KeyEvent.VK_SPACE)) {
b = new Bullets(x);
bullCount.add(b);
System.out.println(bullCount.get(0).getY());
System.out.println ("There are " + bullCount.size() + "bullets alive.");
//elapsed = System.nanoTime() - start;
//if ((elapsed / bulletCount) < 1000000000) {
//this is where I would say 'no more bullets shot until
//average time in nanoseconds is more than 1 second!' but I don't know how
//}
Make a global variable ie: long lastShot.
When user shot, check if (System.currentTimeMilis()-lastShot>5000) before you allow him to shoot.
If it is ok to shoot, store the lastShot = System.currentTimeMilis(); and do the real shot. If not, don't allow him to shoot.
Here is an example in pseudo-code:
class SomeClass {
private long lastShot;
public void userPressedShot() {
if (System.currentTimeMillis()-lastShot>5000) {
lastShot = System.currentTimeMillis();
doTheRealShot();
}
// Ignored till 5000 miliseconds from last shot
}
}
One overkill option is to use the Guava's RateLimiter
final RateLimiter rateLimiter = RateLimiter.create(2.0); // rate is "2 permits per second"
while(true) {
rateLimiter.acquire();
shootSomething();
}
For this solution I assume that you use a Player Object.
It's very simple:
1.: add the field lastShot of the type long with the value 0 to your class.
2.: Whenever the player shoots, set lastShot to System.currentTimeMillis()
3.: Now, before you let him shoot, check if System.currentTimeMillis()-lastShot is smaller than your bullet delay in seconds.
This would be a MWE which has to be inserted in your player class:
Just call the Method player.shoot() to let him shoot - or not, if it's not possible.
private long lastShot = 0;
//return value is for you to check if the shot happened
public boolean shoot(){
//Did the last shot happen less than 1 second (1000 milliseconds) ago
if(System.currentTimeMillis()-lastShot <= 1000){
//If yes: return false, the shot can not happen
return false;
}else{
lastShot = System.currentTimeMillis();
//If no: insert your shooting code here to be executed
//return true, the shot happened
return true;
}
}
Try using a timer that resets every second the bullets count :
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
public void run() {
bullCount.clear();
}
}, 0, 1000); // 0 is the delay in milliseconds before it starts and 1000 is the time in milliseconds between successive task executions
Then when a player wants to shoot you just have to look at bullCount's size
i have a game(like super jumper, this game is a jumping game) that our character has life. after collision with enemies, his life reduce. and i want to after 1 sec , calculate the collisions. i mean in this 1 sec, if my character contact with enemies , nothing happen and he continue his way.
for this , i define a boolean variable in my GameScreen class, name "collision" and another in Wolrd class, name "collBirds". after one contact with enemy collision and collBirds change to true. but i want after 1 sec collistion change to false. i use several things like System.currentTimeMillis() and "for loop",and nothing happen. i'm not so good in java.
this is my condition:
if(World.collBirds == true && collition == false){
life -= 1;
lifeString = "Life : " + life;
World.collBirds = false;
collition = true;
for (??? "need to stay here for 1 sec" ???) {
collition = false;
}
}
In some cases you could also want to use com.badlogic.gdx.utils.Timer
Example usage:
float delay = 1; // seconds
Timer.schedule(new Task(){
#Override
public void run() {
// Do your work
}
}, delay);
When the first collision occurs, set a float timeSinceCollision = 0;
Then each loop, you will need to add the time since last check to the variable, and check if it's more than a second.
timeSinceCollision += deltaTime;
if(timeSinceCollision > 1.0f) {
// do collision stuff
} else {
// ignore the collision
}
If you want to do this in same thread than you can use Thread.sleep(). But in this case your current thread will freeze and if this is single thread game, than your whole game will freeze. If you don't want your game to freeze for 1 second, than you should spawn the thread and in that thread call the sleep and after sleep, change the flag
I am making a little game in Processing which is similar to those Guitar Hero style games and I am trying to do 2 things:
When the game loads, stop the time from moving
During the game, allow for Pause functionality
Now, I know I cant stop the time since the millis() returns the milliseconds since the application launched, so my timer will need to be millis() - millis() at the start to equal zero, so when the user presses START, they can obviously start at the start. The game reads a file at the start, similar to a subtitles file, that has the note to be played and the time in milliseconds that it should appear on screen.
My problem is, when I pause the game, the timer keeps going and when I unpause the game, all the notes get "bunched up" due to my logic, as you'll see from my code.
Can someone suggest a better algorithm than the one I'm using? Its late and I've been working on this all day and night. I think the problem is with the for() below:
public void draw()
{
if (gameInProgress)
{
currentTimerValue = millis(); // Update the timer with the current milliseconds
// Check to see if the note times falls between the current time, or since the last loop (difficult to match exact millisecond)
for(int i=0 ; i<songNotes.length ; i++)
{
if( songNotes[i].getStartTime() > previousTimerValue && songNotes[i].getStartTime() <=currentTimerValue)
notes.add(songNotes[i]);
}
noStroke();
textFont(f,18);
drawButtons(); //Draws coloured buttons relating to Button presses on the controller
drawHighScoreBox(); // Draws high score box up top right
drawLines(); // Draws the strings
moveNotes(); // Moves the notes across from right to left
//Now set the cutoff for oldest note to display
previousTimerValue=currentTimerValue; //Used everytime on the following loop
}
else
{
drawMenu(); // Draw the Main/Pause menu
}
}
NOTE: The boolean gameInProgress is set below when the users presses the pause button, eg "P", and songNotes is an array of objects of type Note that I wrote myself. It has 2 member variables, noteToBePlayed and timeToBePlayed. The method getStartTime()returns timeToBePlayed which is a millisecond value.
Any help is appreciated.
Thanks
How about having another integer to store time when you pause and use that to offset the game timer ?
So, in 'gameInProgress' mode you update currentTimerValue and previousTimerValue and in 'paused/menu' mode you update a pausedTimerValue, which you use to offset the 'currentTimerValue'. I hope this makes sense, it sounds more complicated in words, here's what I mean:
boolean gameInProgress = true;
int currentTimerValue,previousTimerValue,pausedTimerValue;
void setup(){
}
void draw(){
if(gameInProgress){
currentTimerValue = millis()-pausedTimerValue;
println("currentTimerValue: " + currentTimerValue + " previousTimerValue: " + previousTimerValue);
previousTimerValue=currentTimerValue;
}else{
pausedTimerValue = millis()-currentTimerValue;
}
}
void mousePressed(){
gameInProgress = !gameInProgress;
println("paused: " + (gameInProgress ? "NO" : "YES"));
}
Click the sketch to toggle modes and look in the console for times. You'll notice that you only loose a few millis between toggles, which is acceptable.
Use not system timer but special timer class with pause functionality. I'm sure it is not hard to implement such class by yourself. I know that java has Timer class but unfortunately it not support pause functionality.