Need to have a method constantly being called - java

I am making Flappy Bird in JavaFX and I have created a method to tell the score. I have tried using a timeline but if I make it call the method too often, it gets very glitchy and if I make it slower, the score increments wrongly. I need a way to have the score method constantly being called without making the game slow and glitchy.
Here is the method for the score:
public class Score {
static int score = 0;
static boolean incrementScore = false;
public static int ScoreCount() {
for (int i = 0; i < 100; i++) {
if (FlappyBird.bottomPipes[i].getTranslateX() == Bird.birdView.getTranslateX())
incrementScore = true;
if (incrementScore)
score++;
incrementScore = false;
System.out.println(score);
}
return score;
}
}
If anyone knows a good way to do this, please let me know.
If you would like to run the program, it can be downloaded here

You should consider calculating your score in every frame. Timeline is not suitable for this purpose. Rather use an AnimationTimer like this:
new AnimationTimer(){
#Override
public void handle(long now) {
Score.ScoreCount();
}
}.start();
handle will be called in every frame the timer is active.

Related

How to create game achievement in Java

I'm trying to create game achievements in Java. I have class Player and field int level. In game each time when player gets exp he can reach new level. How to trigger when player reaches a level 10?(without if operator because as I understand it's not correct to check all time on exp gain if player reaches level 10 or not. Becase if I will have more than one achievement?).
My suggestion is to use own event? I'm looking for correct way to perform this task.
package testMyAchievements;
public class AchievementTestMain {
private static class Player {
private int level = 1;
public int getLevel() {
return level;
}
public void setLevel(int level) {
this.level = level;
}
#Override
public String toString() {
return "Player{" +
"level=" + level +
'}';
}
}
public static void main(String[] args) {
Player player = new Player();
for (int i = 0; i < 100; i++) {
player.setLevel(player.getLevel() + 1);
/*how to trigger when player reaches a level 10?(without if operator)
* and say "You reached level 10!"*/
}
}
}
To be honest I don't think you can achieve what you're looking for without a conditional check. Your requirement is explicitly stating "If you get to level 10 then show an achievement". I think you're worried about the scaling of your achievement system. How about you build a hashmap. Where the key is the level and the value is the list of achievement(s) that are granted for that level?
Here is an example where you can have a hashmap pointing to a a singular achievement but ofcourse you can also use List<String> for multiple achievs.
If the level is contained in the hashmap then you show it's corresponding achievement.
Here is an example:
int level = 10;
Map<Integer, String> levelToAchievMap= new HashMap<>();
levelToAchievMap.put(10,"Congrats you've reached level 10");
if(levelToAchievMap.containsKey(level)){
System.out.println(levelToAchievMap.get(level);
}

Multiple game instance

I have a method createGame on Server which create an instance of a game. What i want is to create another instance of the game for differents clients, but when i create another instance of the game, the first game created does not work anymore.
Here is the code:
private void createGame(){
gameThread.add(new GameThread(playerList, controllers.get(controllerNumber), controllers.get(controllerNumber)));
gameThread.get(gameNumber).start();
//just to shift the array of game
gameNumber++;
//shift the array of controller
controllerNumber++;
clientCounter = 0;
playerList.clear();
controllers.add(new ControllerServerSide());
}
Why I can't play two games at the same time, if each one is on a different thread?
EDIT:
GameThread
public class GameThread extends Thread{
private Settings settings;
private Game game;
private static int gamesActive = 0;
public GameThread(ArrayList<Player> playerList, Observer observer, ObservableInput controllerServer){
ArrayList<Player> newPlayerList = new ArrayList<>();
int size = playerList.size();
for(int i = 0; i < size; i++){
newPlayerList.add(playerList.remove(0));
}
settings = new Settings("src/main/java/it/polimi/ingsw/ps05/gamelogic/mappa.xml", newPlayerList);
game = new Game(settings, gamesActive++, observer, controllerServer);
game.init();
}
public void run(){
game.play();
}
}
From your code it isn't clear what are the members or what they do.. it's really hard to understand what your code does..
But I'll give it a shot:
Try and see if one of the new threads change the same objects as the old game thread.
Or - and I think that might be the problem - you clear the array/list of players and controllers - which both games use.. so the first game works fine but the second clean those list/arrays and destrying what's in there - so your first game stop working.. check it out.
private void createGame(){
gameThread.add(new GameThread(playerList, controllers.get(controllerNumber), controllers.get(controllerNumber)));
gameThread.get(gameNumber).start();
//just to shift the array of game
gameNumber++;
//shift the array of controller
controllerNumber++;
clientCounter = 0;
playerList.clear();
controllers.add(new ControllerServerSide());

How to pass information through a method and returning a value

I'm new to Java, and need help. I have been asked to write a program that rolls dice and determines the chance of the player to get two "1s" on the top face of the dice. I have different functions such as role(), getTopFace() etc. I want to be get what the number on the dice is using these functions, but don't know how to call them in my main function. Here's my code:
import javax.swing.JOptionPane;
import java.util.Random;
public class SnakeEyes {
private final int sides;
private int topFace;
public static void main(String[]args)
{
String numberSides;
int n;
numberSides=JOptionPane.showInputDialog("Please enter the number of sides on the dice:");
n = Integer.parseInt ( numberSides);
int[]die=new int[n];
for (int index=0; index<n;index++)
{
die[index]=index+1;
}
//Here is where I want to get information from my functions and calculate the ods of getting two 1's.
}
public void Die(int n)
{
if(n>0)
{
int sides=n;
topFace=(int)(Math.random()*sides)+1;
}
else{
JOptionPane.showMessageDialog(null, " Die : precondition voliated");
}
}
public int getTopFace(int topFace)
{
return topFace;
}
public int role(int[] die)
{
topFace=(int)(Math.random()*sides)+1;
return topFace;
}
}
Make an object of your class SnakeEyes in your main method, and call the required functions using that object.
Example:
SnakeEyes diceObj = new SnakeEyes();
int topFace = diceObj.role(n,....);
If you want to call this functions from main this functions must be "static", because main its a static function and static function can only call other static functions.
But... this is a very ugly design for a java program, before jumping to write java code you need to understand at least a little about object orientation. For example, why you can't call a non-static function from a static function?, the answer of this question requires knowledge about object orientation and its a knowledge you need if you want to write serious java code.

Increment a static variable in object before returning that object

I have some code that creates Objects called Weights. Now there are subclasses of these Weights called - WeightSmall, WeightMedium, and WeightLarge - each with their own static variable called onScreen. This variable should increment when one of either WeightSmall, WeightMedium or WeightLarge is added, however these get return on the call of the create method rather than being added to an array. I have an array of Weight objects - is there a way to access what subclass type an element is in the array of the parent class?
Here is the code for creating weights:
public Weight createWeight() {
decider = Math.random() * 1;
// creates rocks randomly with the lowest chance for l, and the highest chance for m
if (decider <= 0.33) {
// small weight
return new WeightSmall(BitmapFactory.decodeResource(getResources(), R.drawable.weight_s), new Random().nextInt(screenWidth), -10);
} else if (decider <= 0.5 && decider > 0.33) {
// large weight
return new WeightLarge(BitmapFactory.decodeResource(getResources(), R.drawable.weight_l), new Random().nextInt(screenWidth), -10);
} else {
// medium weight
return new WeightMedium(BitmapFactory.decodeResource(getResources(), R.drawable.weight_m), new Random().nextInt(screenWidth), -10);
}
}
What needs to happen is for WeightSmall lets say, it needs to check WeightSmalls onScreen variable to see if it's smaller than, let's say 3. if it is return the weight. However I can't think of a way to access WeightSmall's onScreen variable as it needs to be created more than once and I tried implement them into an ArrayList but it causes complications in the update method. Here is the rest of the code (that matters) for the class:
public void render(Canvas canvas) {
if (canvas != null) {
canvas.drawColor(Color.WHITE);
player.draw(canvas);
Weight[] weightArray = weights.toArray(new Weight[0]);
for (Weight weight : weightArray) {
weight.draw(canvas);
}
}
}
// updates the weight's position on the screen and checks collision with the player
public void update() {
Weight[] weightArray = weights.toArray(new Weight[0]);
for (Weight weight : weightArray) {
weight.update();
if (weight.getBounds().intersect(player.getBounds())) {
player.setTouched(false);
Intent gameOverIntent = new Intent(this.getContext(), GameOverActivity.class);
this.getContext().startActivity(gameOverIntent);
((Activity) getContext()).finish();
}
}
}
// count down timer spawning weights in every tick
public void timer() {
if (start == true) {
if (weightSpawnTimer != null) {
weightSpawnTimer.cancel();
weightSpawnTimer = null;
}
weightSpawnTimer = new CountDownTimer(30000, 800) {
public void onTick(long millisUntilFinished) {
weights.add(createWeight());
}
public void onFinish() {
weightSpawnTimer.start();
}
}.start();
}
}
Edit for clarity: What I need to happen, is in the onTick method, check if the subclass of weight's onScreen variable is <= 3, if it is, create a new weight, if it isn't do nothing. Once the weight is then offscreen, decrement this variable so new weights of that subclass can then be created.
What about
class WeightSmall {
public WeightSmall(...) {
// increment static
}
}
Let each class be responsible to increment it's own number in case an instance is created.
Modifying a static variable from an instance is usually considered bad practice. The few legit use-cases are typically some sort of instance counting. At least when you don't count down.
Counting down is where the trouble starts because Objects do have a defined start but their end is not guaranteed. You can count down in finalize - i.e. when the garbage collector has found your instance - but that's not guaranteed to happen soon or at all. Using that to find out how many instances are on screen would correlate to the actual number but could be completely wrong.
So in a case when you want to know how many objects you show on screen you must actively count that number down once the place responsible for showing the objects let's go of one.
And since that is already a responsibility for the class that wants to know how many objects are on screen, it should as well keep track of the numbers in a local variable of it's own.
By using a static property you limit yourself to have just 1 screen. If you let the other place count the number you don't limit yourself.
Static variable initialized at 0, then on the constructor your make it +1

exception in thread "main" Java.lang.nullPointerException error?

I am getting the following error:
Exception in thread "main" java.lang.NullPointerException
at BallContainerImage.update(BallContainerImage.java:101)
at BallContainer.addBall(BallContainer.java:93)
at Game.ejectBall(Game.java:92)
at LotteryTestB.main(LotteryTestB.java:19)
Line 19 contains:
dramaticGame1.ejectBall();
the Dramatic Game class contains the following:
public class DramaticMachine extends Machine
{
// Constructor is given the person's name.
public DramaticMachine(String name, int length)
{
super(name, length);
}
public Ball ejectBall()
{
if (getNoOfBalls() >= 0)
return null;
else
{
//Math.random() * getNoOfBalls yields a number
//which is >=0 and < number of balls.
int ejectedBallIndex = (int) (Math.random() * getNoOfBalls());
for (int selectedBallIndex = 0; selectedBallIndex < ejectedBallIndex; selectedBallIndex++)
{
Ball selectedBall = getBall(selectedBallIndex);
selectedBall.flash(4, 5);
}
Ball ejectedBall = getBall(ejectedBallIndex);
ejectedBall.flash(4, 5);
swapBalls(ejectedBallIndex, getNoOfBalls() -1);
removeBall();
return ejectedBall;
}//else
}//ejectBall
public String getType()
{
return "Dramatic Lottery Machine";
}//getType
}//dramaticMachine
How can i fix this?
This is the code for the DramaticGame class:
public class DramaticGame extends Game
{
// Constructor is given the person's name.
public DramaticGame(String machineName, int machineSize, String rackName, int
rackSize)
{
super(machineName,machineSize,rackName,rackSize);
}
public Machine makeMachine(String machineName, int machineSize)
{
return new DramaticMachine(machineName, machineSize);
}//makeMachine
}
This is the code for LotteryTestB:
public class LotteryTestB
{
public static void main (String args[])
{
SpeedController speedController
= new SpeedController(SpeedController.HALF_SPEED);
LotteryGUI gui = new LotteryGUI("TV Studio", speedController);
Worker worker = new TraineeWorker("Jim",0);
DramaticGame dramaticGame1 = new DramaticGame("Lott O'Luck Larry", 49,
"Slippery's Mile", 7);
gui.addGame(dramaticGame1);
worker.fillMachine(dramaticGame1);
for (int count = 1; count <=dramaticGame1.getRackSize(); count++)
{
dramaticGame1.ejectBall();
speedController.delay(40);
}//for
}//main
}//LotteryTestB
NullPointerException is one of the easier problems to chase down. It means that some reference wasn't initialized properly. It should be easy to figure out by stepping through your code with a debugger.
If you are incapable of using a debugger, the stack trace makes this easy for you. There are only four places to look, and it says exactly where they are.
at BallContainerImage.update(BallContainerImage.java:101)
at BallContainer.addBall(BallContainer.java:93)
at Game.ejectBall(Game.java:92)
at LotteryTestB.main(LotteryTestB.java:19)
It's not the bottom one. The reference to dramaticGame is the only one on that line, and you call new to initialize it. Go on to the next one. Add a log or print statement to prove where the null reference is, then go and initialize it properly.
I don't think your code is layered properly. You'll never get this working unless you can decompose the problem into smaller chunks, unit test them until they work, and then use that code to build up the complex solution.
Separate UI from the game itself. Get the game working, then worry about display issues.

Categories