I'm making a "space-invaders style" game. You(the player) move left and right at the bottom of the screen. There will be one enemy in each window, and you have to move to the window and shoot.
I'm working on the enemies popping up system. The window in which an enemy is random and should change every 3 seconds. Here's my code for this:
int enemylocation = new Random().nextInt(2) +1;
if(enemylocation==1){
enemy1.setFilter(Image.FILTER_NEAREST);
enemy1.draw(200,170,s*10);
}
if(enemylocation==2){
enemy2.setFilter(Image.FILTER_NEAREST);
enemy2.draw(200,360,s*10);
}
Everything works, but the random number part is always picking a new number, so both windows are flickering. How can I delay the timer to change the value of enemylocation every 3 seconds and not constantly?
Thanks
I'd say the "right" way to do this is to have a game loop that ticks x times per second. You decide to change the value of the enemylocation every x ticks. If you tick 60 times per second, that means 3 seconds will be 60 * 3 = 180. That means you can change the enemylocation when tickNumber % 180 == 0
I am guessing you already have a gameloop with a timer since you are able to render, the flickering comes from enemylocation being set too often so the enemy is rendered all over the place. What I would do is to implement a cooldown. In pseudo-ish code (no IDE):
int enemySpawnRate = 3000;
int timeElapsed = enemySpawnRate+1; //Spawn the first time
void spawnEnemy(int delta) {
timeElapsed +=delta;
if(timeElapsed>enemySpawnRate) {
//spawn enemy as before, your code snippet
timeElapsed=0;
}
}
Where delta is the ammount of time that has passed since the previous run of your gameloop.
Note this depends entirely on you have a timerbased gameloop, if you don't and you are rendering on INPUT (eg render if key pressed) the code will be different, you would have to utilize a timertask or a swingtimer if you are using swing.
Related
Recently i added that enemy shoots but unfortunately i cannot randomize delay of Shooting for every object.
Project 60 times in second :
update (all code here is connected to this part)
draw
sleep
Fragment of code :
Fragment of code.
public void createNewEnemyBullet(){
for(Enemy enemy: enemies){
EnemyBullet enemyBullet = new EnemyBullet(getResources());
randomShot = random.nextInt(60-40)+40;
System.out.println("Randomowy shot :"+ randomShot);
enemyBullet.x = (int) (((enemy.x+enemy.widthEnemy/2)-18)*screenRatioX);
enemyBullet.y= enemy.y+20;
enemyBullets.add(enemyBullet);
}
System.out.println("\n\n");
}
Screenshot of my result
enter image description here
Use Math.random(). It'll be your friend here. Compare (Math.random() <= epsilon) the output of random() with some number epsilon you want as your threshold for making an enemy shooting decision.
If enemyBullets is what the UI code uses to draw bullets, you may want to add a Thread.sleep(Math.random()) to add variable delay in adding them.
Solution for generating random delay of bullet is to change this delay when a enemy starship is shot.
I am beginner when it comes to java and I have come across with a problem that I haven't found a solution to just yet. The thing is that I have working methods for drawing an letter and also for rotating it - when I set rotation it works the way it should. However I would like to make this slightly more interactive, at school we were given the basic framework for that - I was able to create a button that when you click on it the letter's angle changes and the letter is redrawed correctly. But I would like to make it an animation, for example you click on the button and for 10 seconds (or until you press the button again) the letter will be rotating.
On the internet I found a way to perform an action after certain period of time, and I thought I will use this. I wanted to add an angle and redraw an image, after let's say 1 second, then it would repeat - I thought this would make it look like it is animated. But I was wrong. I tried so many ways to do this, the best thing was that after few seconds that I set I want the animation to go for, it changed an angle and redraw, unfortunately it was the final state and it didn't draw states in between to create an animation. And this latest code doesn't even do that, the program just freezes.
int animation = 0;
int steps = 0;
public void G_draw() {
graphic.clear();
if (animace==1)
{
animation();
}
letter('a', G_Color.G_cBlack, 2, 2);//drawing an letter
}
public void G_mousePressed(G_Button button, int x, int y) {
if (button.equals(G_Button.B_LEFT)&&x>700&&x<750&&y>500&&y<520){
animation=1;
G_draw();
}
}
public void animation() {
long start = System.currentTimeMillis();
long end = start + 2 * 1000;
while (System.currentTimeMillis() < end) {
}
langle+=30; // adding an angle
steps++;
G_repaint();
G_draw();
if (steps<4) animace();
}
instead of this
long start = System.currentTimeMillis();
long end = start + 2 * 1000;
while (System.currentTimeMillis() < end) {
}
use
Thread.sleep(# in milliseconds);
We can't see where you use langle
This line if (steps<4) animace(); only runs when animace<>1 otherwise it's skipped because animate()calls G_draw() calls animate and so on.
I am currently working on a 2d game in which a player sprite pushes other sprites around on the screen.
My current code (within subclass):
//x and y being the co-ords i want this object to move to (e.g 50 pixels
right of its starting point etc.)
public Boolean move(float x, float y, int delta) {
this.setx(x);
}
How do i make the object move say 50 pixels every 1 second? or alternatively every x frames.
I've tried using delta but that results in smooth motion which is much harder to control for my particular needs.
Any help would be much appreciated
Your approach to accomplish it with the deltas is right. Assuming you have your move method inside your update method and call it in there (or implementing it in a similar way). One way you could achieve these would be the following:
class YourGameStateWithUpdateRenderInit extends BasicGameOrWhatever{
//Global variables for updating movement eacht second.
float myDelta = 0; // your current counter
float deltaMax = 1000; // 1 second, determines how often your object should move
public void update(...){
objectToMove.move(50,50,delta); //The object which contains the move method and you move it by 50 x/y per second.
}
}
Inside your objectToMove class you have your move method:
public Boolean move(float x, float y, float pDelta) {
myDelta += pDelta;
if(myDelta >= deltaMax){
this.setx(x);
myDelta = 0;
}
}
This should work for an update every second. However this implementation is not really good or precise since as you stated you probably have that move method in a sub class or something similar. So you need to adapt it to your needs, but i hope you get the idea behind it. I think it demonstrates the purpose of counting an class attribute up by the delta values until a certain value (e.g. 1000 for 1 second) and after that set it back to zero.
I'm creating a game like flappy bird where the bird flaps his wings only when the screen is touched, but I'm having a problem activating the animation when the screen is touched.
batch.draw(animation.getKeyFrame(myTimeState, false), x, y); //the myTimeState is 0 to render the 1st frame only.
Then when the screen is touched I do this:
//myTimeStep is just basically a controllable timeState for the animation only
if(Gdx.input.justTouched){
myTimeState = timeState;
}else if(Gdx.input.justTouched == false && animation.isAnimationFinished(timeState)){
myTimeState = 0;
}
I don't think the animation is able to play all the frames because myTimeStep become 0 immediately after finishing to touch the screen. Also I don't think this is the right way of doing it, if you guys have better ideas or solution please help. Thanks in advance.
There are probably several ways to achieve this. You'll need to increment your timeState, of course, and also it depends how long your animation is and if you want it to loop.
If you've created your animation to play only once, and then stop (until the screen is touched again), you could simply set your myTimeState to 0 when the screen is touched, and then increment it every frame. The animation will run through and then "stop" on its own when it reaches the end (as you said no loop). The next time someone touches the screen, your myTimeState is set back to 0 and the animation starts again.
Firstly, you have to ensure your animation's playmode is set to Animation.PlayMode.NORMAL. It's a default setting, but if you set it somewhere to LOOPED, nothing would work as expected.
Secondly, I wouldn't use Input.justTouched() in this case. Instead, a listener in your input processor would be a great fit. Here's an example with Stage. If you have no idea what input processor is, here's tutorial on event handling and class documentation.
stage.addListener(new ClickListener() {
#Override
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
if(button == Input.Buttons.LEFT) {
timeState = 0;
}
return super.touchDown(event, x, y, pointer, button);
}
});
You can pick what's going to be displayed (animation's keyframe or sprite) based on result of animation.isAnimationFinished()
if(animation.isAnimationFinished(timeState)) {
//draw some sprite
} else {
//draw animation keyframe
}
I haven't checked it but there's a possibility, that this could lead to the last frame being cut out, because as soon as it gets displayed, animation.isAnimationFinished() will return true. I may be wrong, so you'll have to check it. If it becomes an issue, you can add your sprite as the last frame of your animation. When animation ends, it frezzes on the last frame, which would be your static sprite.
In both cases you'll get your animation played at the beginning of game because timeStep equal to 0. I see 2 solutions, I advise you to take the second:
Set timeStep to a large number, that is for sure larger than your animation's duration. Animation.isAnimationFinished() will then return true.
Introduce boolean variable isAnimationPlayed that:
is initialized with false,
gets set to true in your click listener,
gets set to false during isAnimationFinished(), which is called each frame only when isAnimationPlayed is true,
is used in draw() method to determine what to display.
You could just set your timeState to the duration of the animation.
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.