Bukkit countdown doubles when 2 players online - java

I'v just created a countdown for a minigame im working on but when i was about to test the countdown i noticed that if i was the only one online the countdown worked perfect, but when another player joined the countdown doubled like this: 10,8,6,4 etc. I think it has something todo with "for(Player p : Bukkit.getOnlinePlayers()){" but i am not quite sure. Anyone that can help?
Here is my countdown class:
Main plugin;
public StartCountdown(Main pl) {
plugin = pl;
}
public static int timeUntilStart;
#Override
public void run() {
for(Player p1 : Bukkit.getOnlinePlayers()){
if(timeUntilStart == 0) {
if(!Game.canStart()) {
plugin.restartCountdown();
ChatUtilities.broadcast(ChatColor.RED + "Not enough players to start. Countdown will");
ChatUtilities.broadcast(ChatColor.RED + "restart.");
p1.playSound(p1.getLocation(), Sound.ENDERDRAGON_WINGS, 5, 1);
return;
}
Game.start();
}
if(timeUntilStart == 1) {
}
for(Player p : Bukkit.getOnlinePlayers()){
p.setLevel(timeUntilStart);
if(timeUntilStart < 11 || timeUntilStart == 60 || timeUntilStart == 30) {
p.playSound(p.getLocation(), Sound.ORB_PICKUP, 5, 0);
if(timeUntilStart == 1) {
p.playSound(p.getLocation(), Sound.ORB_PICKUP, 5, 1);
}
ChatUtilities.broadcast(String.valueOf(timeUntilStart)
+ " §6Seconds until the game starts!");
}
timeUntilStart -= 1;
}
if(timeUntilStart == 0) {
ChatUtilities.broadcast("§6The round has started, good luck!");
}
}
}
}

Your call to decrement time (timeUntilStart -= 1;) is inside a loop for(Player p1 : Bukkit.getOnlinePlayers())....
This means that for each player online, you decrement timeUntilStart by one. However, you only want to do that once per run - take it outside of the for each player p1 loop.
With that being said, most of this logic only should be happening once per RUN, not per player per run (i.e. unless you know something I don't, game.start should probably only get called once)... but that's irrelevant so I'll leave it alone.

Related

Changes to Array not reflecting in program?

I was trying to make a battleship clone but ended up running into one problem. I made a BattleShipGrid class that had two 2D arrays, one for each player. The array called p1/p2grid holds their ship and the locations the other player has shot at. The second array called p1/p2fire is the one that shows only where they shot, and not where the enemy ship is, though they can see where they’ve hit it. Im having a problem where I want to print player 1's fire grid after them firing to show if they missed or not. But each time I print player 1's fire grid it still sets everything as 0, like they never even fired on anything. I made 1 a miss and 3 a hit and 2 to represent the location of a ship.
Here is my code in my main:
boolean player1Turn = true;
if (player1Turn) {
fire = grid.fireAtPlayerTwo(x, y);
} else {
fire = grid.fireAtPlayerOne(x, y);
}
if (fire == 0) {
System.out.println("Miss!");
} else if (fire == 2) {
System.out.println("=====================================");
System.out.println("Hit!");
if (player1Turn) {
System.out.println(grid.printP1Fire());/* printing regular old empty array filled with zeros like when a player just starts and hasn't fired on anything.*/
} else {
System.out.println(grid.printP2Fire());
}
System.out.println("=====================================");
}
Here is my methods that I called when firing on the other player( fire at player one and fire at player two do the same thing but are named different ) :
int Empty = 0;
public int fireAtPlayerTwo ( int x, int y)
{
int result = p2Grid[x][y];
if (result == EMPTY) {
p1Grid[x][y] = MISS;/* This should change the value in p1Grid at that coordinate but it is not refelcting back in the main*/
p2Fire[x][y] = MISS;
} else if (result == SHIP) {
p1Grid[x][y] = HIT;
p2Fire[x][y] = HIT;
}
return result;
}

How to delete entity when "health <= 0"?

Ive been followin an online tutorial for a top down shooter game, but the tut is unfinished (and I dont see the creator continuing it), so Id like to complete it myself. So far, the tutorial has helped me to give the player health and a string above it to show how much health, but nothing happens when health gets to and goes below 0. It just goes down in the increment I set. Id like the game to close when there is no more health, so how would I go about doing this?
This is what happens when the player gets hit by an enemy bullet:
private void playerBulletCollision(){
for (Bullet b:mobBullets){
if (b.collisionBox.intersects(player.collisionBox)){
player.health -= b.damage;
b.isAlive = false;
break;
}
}
}
And this is what happens when player bullet hits enemy
private void mobBulletCollision(){
for (Bullet b:bullets){
for (Entity m: mobs){
if (b.collisionBox.intersects(m.collisionBox)){
m.health -= b.damage;
b.isAlive = false;
break;
}
}
}
}
so how can I make it so the game ends when player health is no more? Sorry if my explanation isnt clear or the code I showed isnt enough/not relevant. Tell me and Ill fix it to the best of my abilities.
Thank you
Edit: I tried to make it so it checks to see if health <= 0 and if it does it despawns:
private void playerBulletCollision(){
for (MobBullet b:mobBullets){
if (b.collisionBox.intersects(player.collisionBox)){
player.health -= b.damage;
b.isAlive = false;
break;
}
if(player.health <=0)
player.isAlive = false;
}
}
It didnt work.
Edit 2: This is the process to remove the dead enemies. I think because there is no such thing for the player, player.health = false; does nothing.
private void removeDead(){
for (int i = 0; i <bullets.size(); i++){
if (bullets.get(i).isAlive == false )
bullets.remove(i);
}
for (int i = 0; i <mobs.size(); i++){
if (mobs.get(i).isAlive == false )
mobs.remove(i);
}
for (int i = 0; i <mobBullets.size(); i++){
if (mobBullets.get(i).isAlive == false )
mobBullets.remove(i);
}
bullets.trimToSize();
mobs.trimToSize();
mobBullets.trimToSize();
}
How should this piece be modified to incorporate the player?
You should do this. On a collision you decrement the health and after the loop you check the player health if this is <=0 you set isAlive to false.
private void playerBulletCollision(){
for (MobBullet b:mobBullets){
if (b.collisionBox.intersects(player.collisionBox)){
player.health -= b.damage;
b.isAlive = false;
break;
}
}
if(player.health <=0){
player.isAlive = false;
}

LibGDX - isKeyPressed() do not count just one

I'm trying to do a game. When you press "A" my character was supposed to jump ONE square forward, but he is jumping like 7 squares each time I press the "A" key. Someone knows how to limit it to 1? I know why it is happening, but I didn't find any ways to do that until now.
My "Player" class code, that is my Character class:
ArrayList<Square> squareList = new ArrayList<Square>();
int count = 0;
Vector2 position = new Vector2(50,50);
if(Gdx.input.isKeyPressed(Keys.A))
{
j = j + 1;
position.x = squareList.get(i).getPosition().x;
position.y = squareList.get(i).getPosition().y;
i++;
}
Try this:
if (Gdx.input.isKeyJustPressed(Keys.A)) {
System.out.println("KEY PRESSED");
}
It only runs once when you press the key, but if you press and hold it only triggers once. Tested it.
Something like this i imagine would work:
if (Gdx.input.isKeyPressed(Input.Keys.P)) {
// Use a helper so that a held-down button does not continuously switch between states with every tick
if (pauseHelper) {
if (isPaused) {
Util.toConsole ("No longer paused");
isPaused = false;
}
else {
Util.toConsole ("Now paused");
isPaused = true;
}
pauseHelper = false;
}
}
else {
pauseHelper = true;
}
(See http://pastebin.com/vsVWeHj6)
However, technically you need to implement an InputProcessor provided by LibGDX to handle key presses.
Another way to do it if you don't want to implement an InputProcessor:
//Member variable:
boolean mAKeyWasPressed = false;
//In method:
boolean aKeyIsPressed = Gdx.input.isKeyPressed(Keys.A);
if (aKeyIsPressed && !mAKeyWasPressed)
//Just pressed. Do stuff here.
}
mAKeyWasPressed = aKeyIsPressed;

Swing components freezing (Java)

I've coded a complex Snake game using Swing components.
I have a timer (call it moveRate) that calls repaint(); every x ms (x is changed during game and never goes below 50).
Now for the issue: I'm successful playing like 4 min or so before the whole frame freezes.
MoveRate class:
class MoveRate extends Timer{
private Date dateCreated=new Date();
private long timeLast=0;
public MoveRate(){
super(190, null);
dateCreated=new Date();
addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if(getWidth()>0 && getHeight()>0){
if(points.get(0).x+HOPS>getWidth() || points.get(0).x<0 ||
points.get(0).y+HOPS>getHeight() || points.get(0).y<0)
if(!crosswalls && !cheats){
moveRate.stop();
prizeRate.stop();
GameOver();
}
else{
if(points.get(0).y<0)
points.get(0).y=sp.getHeight()-HOPS;
else if(points.get(0).y+HOPS>sp.getHeight())
points.get(0).y=0;
else if(points.get(0).x<0)
points.get(0).x=sp.getWidth()-HOPS;
else
points.get(0).x=0;
}
timeLast=(System.currentTimeMillis()-dateCreated.getTime())/SECONDS;
score+=timeLast*(200/moveRate.getDelay());
}
if(prize!=null)
if(points.get(0).x==prize.x && points.get(0).y==prize.y){
int newX = points.get(points.size()-1).x-(points.get(points.size()-1).x - points.get(points.size()-2).x);
int newY = points.get(points.size()-1).y-(points.get(points.size()-1).y - points.get(points.size()-2).y);
points.add(new Point(newX, newY));
if(moveRate.getDelay()>50)
moveRate.setDelay(moveRate.getDelay()-5);
prize.createPrize(PU_NONE);
prizeRate.restart();
score+=timeLast*20*eatmultiplier;
}
if(powerup!=null)
if(points.get(0).x==powerup.x && points.get(0).y==powerup.y){
int newX = points.get(points.size()-1).x-(points.get(points.size()-1).x - points.get(points.size()-2).x);
int newY = points.get(points.size()-1).y-(points.get(points.size()-1).y - points.get(points.size()-2).y);
//points.add(new Point(newX, newY)); //if powerup should increase size
powerUpPerform(powerup.getType());
if(moveRate.getDelay()>50)
moveRate.setDelay(moveRate.getDelay()-5);
//powerUpRate.restart();
score+=timeLast*20*eatmultiplier;
powerup=null;
}
p.setScore(score);
repaint();
}
});
}
}
Basically MoveRate is responsible for animation aswell "eat moves" for prizes & powerups and checks for Game Over situations.
Some other notes:
I thought this has something to do with threads which I haven't learned yet so I added this:
new Thread(new Runnable() {
public void run() {
moveRate=new MoveRate();
moveRate.start();
powerUpRate.start();
prizeRate.start();
}
}).start();
Frame still freezes.
System.gc(); doesn't work neither if I time it every 30 seconds.
Be easy with me because I'm junior student with Java :>
EDIT
I've tried to reproduce the "bug" by making the snake longer (much longer - using my final int SNAKE_INITIAL_LENGTH=200). doesn't seem to have any effect on the problem.

Smooth movement in Java

I'm making a simulation in a 3D environment. So far, I have the movements of all the creatures, but it is not "smooth". I've tried quite a few things but was horribly wrong. Now I just have no idea what to do. I was thinking of implementing a vector (not vector class) but don't really know how.
import env3d.EnvObject;
import java.util.ArrayList;
abstract public class Creature extends EnvObject
{
/**
* Constructor for objects of class Creature
*/
public Creature(double x, double y, double z)
{
setX(x);
setY(y);
setZ(z);
setScale(1);
}
public void move(ArrayList<Creature> creatures, ArrayList<Creature> dead_creatures)
{
double rand = Math.random();
if (rand < 0.25) {
setX(getX()+getScale());
setRotateY(90);
} else if (rand < 0.5) {
setX(getX()-getScale());
setRotateY(270);
} else if (rand < 0.75) {
setZ(getZ()+getScale());
setRotateY(0);
} else if (rand < 1) {
setZ(getZ()-getScale());
setRotateY(180);
}
if (getX() < getScale()) setX(getScale());
if (getX() > 50-getScale()) setX(50 - getScale());
if (getZ() < getScale()) setZ(getScale());
if (getZ() > 50-getScale()) setZ(50 - getScale());
// collision detection
if (this instanceof Fox) {
for (Creature c : creatures) {
if (c.distance(this) < c.getScale()+this.getScale() && c instanceof Tux) {
dead_creatures.add(c);
}
}
}
}
}
import env3d.Env;
import java.util.ArrayList;
/**
* A predator and prey simulation. Fox is the predator and Tux is the prey.
*/
public class Game
{
private Env env;
private boolean finished;
private ArrayList<Creature> creatures;
/**
* Constructor for the Game class. It sets up the foxes and tuxes.
*/
public Game()
{
// we use a separate ArrayList to keep track of each animal.
// our room is 50 x 50.
creatures = new ArrayList<Creature>();
for (int i = 0; i < 55; i++) {
if (i < 5) {
creatures.add(new Fox((int)(Math.random()*48)+1, 1, (int)(Math.random()*48)+1));
} else {
creatures.add(new Tux((int)(Math.random()*48)+1, 1, (int)(Math.random()*48)+1));
}
}
}
/**
* Play the game
*/
public void play()
{
finished = false;
// Create the new environment. Must be done in the same
// method as the game loop
env = new Env();
// Make the room 50 x 50.
env.setRoom(new Room());
// Add all the animals into to the environment for display
for (Creature c : creatures) {
env.addObject(c);
}
// Sets up the camera
env.setCameraXYZ(25, 50, 55);
env.setCameraPitch(-63);
// Turn off the default controls
env.setDefaultControl(false);
// A list to keep track of dead tuxes.
ArrayList<Creature> dead_creatures = new ArrayList<Creature>();
// The main game loop
while (!finished) {
if (env.getKey() == 1) {
finished = true;
}
// Move each fox and tux.
for (Creature c : creatures) {
c.move(creatures, dead_creatures);
}
// Clean up of the dead tuxes.
for (Creature c : dead_creatures) {
env.removeObject(c);
creatures.remove(c);
}
// we clear the ArrayList for the next loop. We could create a new one
// every loop but that would be very inefficient.
dead_creatures.clear();
// Update display
env.advanceOneFrame();
}
// Just a little clean up
env.exit();
}
/**
* Main method to launch the program.
*/
public static void main(String args[]) {
(new Game()).play();
}
}
You haven't shown enough of your program. Basically, if you want animation to be smooth, and you want to do it yourself (as opposed to using JavaFX or something), then you need to do lots of inter-frames. So rather than advancing an entire timer tick, advance a 10th of a timer tick, move everything on a screen a tiny bit, and then advance again. You should have the background redraw happening every 10th of a second for smooth animation.
As vy32 mentioned, we need to see more of your code. But it looks like you are missing timing code.
What you probably want to do is check the time each iteration of your game loop and then sleep for a certain amount of time to achieve some desired frame rate. Otherwise your game loop will run hundreds of thousands of times a second.
Alternatively, you should be advancing your creatures by a distance that is proportional to the amount of time that has elapsed since the previous frame.
Here is an example of a very simple regulated loop ("fps" is the desired framerate):
private long frameLength = 1000000000 / fps;
public void run() {
long ns = System.nanoTime();
while (!finished) {
//Do one frame of work
step();
//Wait until the time for this frame has elapsed
try {
ns += frameLength;
Thread.sleep(Math.max(0, (ns - System.nanoTime())/10000000));
} catch (InterruptedException e) {
break;
}
}
}
It should be very easy to retrofit this into your game loop.

Categories

Resources