diff options
| author | sowgro <tpoke.ferrari@gmail.com> | 2024-08-31 21:39:29 -0400 | 
|---|---|---|
| committer | sowgro <tpoke.ferrari@gmail.com> | 2024-08-31 21:39:29 -0400 | 
| commit | e026f360ca7777fe72ec1b3bd86045f7d94aa834 (patch) | |
| tree | faedd4ea64e444063d804d6d81a16a64dd1bdfef /src | |
| parent | 2dd291f259734564b8d507a10b29602ef3a4e462 (diff) | |
| download | NPEhero-e026f360ca7777fe72ec1b3bd86045f7d94aa834.tar.gz NPEhero-e026f360ca7777fe72ec1b3bd86045f7d94aa834.tar.bz2 NPEhero-e026f360ca7777fe72ec1b3bd86045f7d94aa834.zip | |
finish SongPlayer rewrite
- move from gameloop to timeline
- significant code clean up
- change design of blocks and targets
Diffstat (limited to 'src')
9 files changed, 217 insertions, 324 deletions
| diff --git a/src/main/java/net/sowgro/npehero/gameplay/NoteInfo.java b/src/main/java/net/sowgro/npehero/gameplay/NoteInfo.java deleted file mode 100755 index a34e939..0000000 --- a/src/main/java/net/sowgro/npehero/gameplay/NoteInfo.java +++ /dev/null @@ -1,28 +0,0 @@ -/*Name:	Guitar Hero Project - *Description: Contains the info for when to send a note - */ -package net.sowgro.npehero.gameplay; - -import javafx.scene.paint.Color; - -public class NoteInfo -{ -    private double sendTime; -    private Color col; - -    public NoteInfo(double t) { -        sendTime = t; -    } -     -    public double getTime() { -        return sendTime; -    } -     -    public Color getColor() { -        return col; -    } - -    public double compareTo(NoteInfo other) { -        return sendTime - other.sendTime; -    } -} diff --git a/src/main/java/net/sowgro/npehero/gameplay/ScoreController.java b/src/main/java/net/sowgro/npehero/gameplay/ScoreController.java index 1865a56..4c603c1 100755 --- a/src/main/java/net/sowgro/npehero/gameplay/ScoreController.java +++ b/src/main/java/net/sowgro/npehero/gameplay/ScoreController.java @@ -37,10 +37,8 @@ public class ScoreController{      /**       * Called when the user misses a note       */ -    public void miss(boolean muted) { -        if (!muted) { -            Sound.playSfx(Sound.MISS); -        } +    public void miss() { +        Sound.playSfx(Sound.MISS);          combo = 0;          comboMultiplier = 1;          scoreProperty.setValue(score+""); @@ -48,7 +46,7 @@ public class ScoreController{          // System.out.println("Miss");      } -    /* +    /**       * Increments the combo by one       */      private void combo() { diff --git a/src/main/java/net/sowgro/npehero/gameplay/SongPlayer.java b/src/main/java/net/sowgro/npehero/gameplay/SongPlayer.java index bf7b8a2..5361b96 100755 --- a/src/main/java/net/sowgro/npehero/gameplay/SongPlayer.java +++ b/src/main/java/net/sowgro/npehero/gameplay/SongPlayer.java @@ -1,20 +1,18 @@  package net.sowgro.npehero.gameplay; -import java.io.FileNotFoundException; -import java.io.IOException;  import java.util.ArrayList; -import java.util.LinkedList; -import java.util.Queue; - -import javax.sound.sampled.LineUnavailableException; -import javax.sound.sampled.UnsupportedAudioFileException;  import javafx.event.EventHandler; +import javafx.geometry.Insets;  import javafx.scene.input.KeyEvent;  import javafx.scene.media.Media; +import javafx.scene.shape.Line; +import javafx.scene.shape.Rectangle;  import net.sowgro.npehero.Driver;  import net.sowgro.npehero.levelapi.Difficulty;  import net.sowgro.npehero.levelapi.Level; +import net.sowgro.npehero.levelapi.Note; +import net.sowgro.npehero.levelapi.Notes;  import net.sowgro.npehero.main.*;  import net.sowgro.npehero.gui.GameOver;  import javafx.geometry.Pos; @@ -27,244 +25,180 @@ import javafx.scene.paint.Color;  import javafx.animation.*;  import javafx.util.*; -class KeyLane { -	Target target; //Initializes the button, each parameter is a placeholder that is changed later -	Queue<NoteInfo> sends = new LinkedList<>(); //Queue that dictates when to send the notes -	ArrayList<Block> lane = new ArrayList<>(); //Array list containing all the notes currently on the field for that lane -} - -public class SongPlayer extends Pane { -	private Double bpm;		//initializes the bpm of the song, to be read in from a metadata file later -	private double songLength; //initializes the length of the song in terms of the song's bpm, to be read in later - -	private EventHandler<KeyEvent> eventHandler; +public class SongPlayer extends HBox { -	private Media song; -	private boolean songIsPlaying = false; -	private boolean missMute = false; - -	private Level level; -	private Difficulty difficulty; -	private Page pane; - -	Timer timer;			//the timer that determines when notes will fall, counted in terms of the song's bpm -	final int TIME = 1000;  //delay for notes falling down the screen +	static class Lane { +		Target target; //Initializes the button, each parameter is a placeholder that is changed later +		ArrayList<Block> blocks = new ArrayList<>(); //Array list containing all the notes currently on the field for that lane +		Pane pane = new Pane(); +	} -	ScoreController scoreCounter = new ScoreController();	//used to keep track of the user's score +	private final int FALL_TIME = 1;  // delay for notes falling down the screen (seconds) +	private final double START_DELAY = 1;  // seconds -	HBox buttonBox = new HBox();	//used to align the buttons horizontally -	VBox place = new VBox();		//used to place the buttons within the frame +	private final Level level; +	private final Media song; +    private final ScoreController scoreCounter; -	KeyLane[] lanes = new KeyLane[5]; +    private final EventHandler<KeyEvent> eventHandler; +	private final Timeline timeline; -	{ -		lanes[0] = new KeyLane(); -		lanes[0].target = new Target(Color.RED, 50, 50, 5, Control.LANE0.targetString()); -		lanes[1] = new KeyLane(); -		lanes[1].target = new Target(Color.BLUE, 50, 50, 5, Control.LANE1.targetString()); -		lanes[2] = new KeyLane(); -		lanes[2].target = new Target(Color.GREEN, 50, 50, 5, Control.LANE2.targetString()); -		lanes[3] = new KeyLane(); -		lanes[3].target = new Target(Color.PURPLE, 50, 50, 5, Control.LANE3.targetString()); -		lanes[4] = new KeyLane(); -		lanes[4].target = new Target(Color.YELLOW, 50, 50, 5, Control.LANE4.targetString()); -	} +	private boolean done = false; +	private final Lane[] lanes = new Lane[5]; -	/** -	 * Establishes what the chart for the song is going to look like -	 * @throws FileNotFoundException -	 */ -	public void loadSong() throws FileNotFoundException { -		difficulty.notes.list.forEach(e -> lanes[e.lane].sends.add(new NoteInfo(e.time.get() * (bpm / 60)))); -	} +	public SongPlayer(Difficulty diff, Page prev, ScoreController scoreController) { +		this.level = diff.level; +		this.song = diff.level.song; +		this.scoreCounter = scoreController; // Uses the song's designated scoreCounter +		double songLength = diff.endTime != 0 ? diff.endTime : diff.level.song.getDuration().toSeconds(); +        Notes notes = diff.notes; -	public SongPlayer(Difficulty diff, Page prev, ScoreController cntrl) {  		Sound.stopSong(); -		song = diff.level.song; - -		if (diff.level.background != null) { -			Driver.setBackground(diff.level.background); -		} -		bpm = 60.0;					//Reads the song's bpm from a metadata file -		level = diff.level; -		difficulty = diff; -		pane = prev; - -		//System.out.println(d.bpm + " " + d.numBeats); - -		if (diff.endTime != 0) { -			songLength = diff.endTime; -		} -		else { -			songLength = diff.level.song.getDuration().toSeconds(); +		if (level.background != null) { +			Driver.setBackground(level.background);  		} -		timer = new Timer(bpm);	//Sets the timer's bpm to that of the song -		scoreCounter = cntrl;			//Uses the song's designated scoreCounter - -		try { -			loadSong();			//Calls the file loading from the song's notes.txt file -		} catch (FileNotFoundException e) { +		// create targets +        for (int i = 0; i < lanes.length; i++) { +			lanes[i] = new Lane(); +			var tmp = new Target(level.colors[i], 50, 50, 20, Control.lanes[i].targetString()); +			bindTarget(tmp); +			lanes[i].target = tmp;  		} -		for (int i = 0; i < lanes.length; i++) { -			lanes[i].target.setColor(level.colors[i]); -			genButton(lanes[i].target); +		// create timeline +		timeline = new Timeline(); +		for (Note note : notes.list) { +			// schedule each note to send at its time +			KeyFrame kf = new KeyFrame(Duration.seconds(note.getTime() + START_DELAY), _ -> sendNote(note)); +			timeline.getKeyFrames().add(kf);  		} - +		// schedule the song to start after the delay +		timeline.getKeyFrames().add(new KeyFrame(Duration.seconds(FALL_TIME + START_DELAY), _ -> { +            if (!done) { +                Sound.playSong(song); +            } +        })); +		// schedule the game over screen to show at the end +		timeline.getKeyFrames().add(new KeyFrame(Duration.seconds(songLength + START_DELAY), _ -> { +			Driver.setMenu(new GameOver(level, diff, prev, scoreCounter.getScore())); +			cancel(); +		})); + +		// handle keyboard input  		eventHandler = e -> { -			/* -			 * The keyboard detection for the game: when a key is pressed it -			 * calls the checkNote() method for the corresponding lane -			 */ -			if (e.getCode() == Control.LANE0.getKey()) { -				checkNote(lanes[0].lane, lanes[0].target); -			} -			if (e.getCode() == Control.LANE1.getKey()) { -				checkNote(lanes[1].lane, lanes[1].target); -			} -			if (e.getCode() == Control.LANE2.getKey()) { -				checkNote(lanes[2].lane, lanes[2].target); -			} -			if (e.getCode() == Control.LANE3.getKey()) { -				checkNote(lanes[3].lane, lanes[3].target); -			} -			if (e.getCode() == Control.LANE4.getKey()) { -				checkNote(lanes[4].lane, lanes[4].target); +			for (int i = 0; i < lanes.length; i++) { +				if (e.getCode() == Control.lanes[i].getKey()) { +					checkNote(lanes[i]); +				}  			}  			if (e.getCode() == Control.LEGACY_PRINT.getKey()) { -				System.out.println("" + timer.time()); +				System.out.println("" + timeline.getCurrentTime());  			}  			e.consume();  		};  		Driver.primaryStage.addEventFilter(KeyEvent.KEY_PRESSED, eventHandler); -		buttonBox.setAlignment(Pos.CENTER);		//puts the buttons in the center of the screen -		for (KeyLane lane : lanes) { //places the buttons in the correct row order -			buttonBox.getChildren().add(lane.target); +		// layout +		HBox buttonBox = new HBox(); +		buttonBox.setAlignment(Pos.BOTTOM_CENTER);		//puts the buttons in the center of the screen +		for (Lane lane : lanes) { //places the buttons in the correct row order +			Line line = new Line(); +			line.setStroke(lane.target.getFillColor()); +			line.setStrokeWidth(2); +			line.setStartY(0); +			line.endYProperty().bind(lane.target.layoutYProperty().subtract(2)); +			VBox back = new VBox(line, lane.target); +			back.setAlignment(Pos.BOTTOM_CENTER); +			StackPane stackPane = new StackPane(back, lane.pane); +			buttonBox.getChildren().add(stackPane);  		} -		buttonBox.setSpacing(10); //sets the space between each button - -		place.prefWidthProperty().bind(super.widthProperty());		//Sets the height and with of the scene -		place.prefHeightProperty().bind(super.heightProperty());	//to natch the window -		place.getChildren().addAll(buttonBox);		//adds the buttonBox to the screen -		place.setAlignment(Pos.BOTTOM_CENTER);		//sets the alignment of the pane -		place.setSpacing(10);	 - -		StackPane root = new StackPane(); -		root.getChildren().addAll(place);	//aligns the components within the pane - -		super.getChildren().addAll(root);	//puts all of the combonents in the pane to be rendered +		buttonBox.spacingProperty().bind(super.heightProperty().multiply(20/1080.0)); +		super.getChildren().add(buttonBox); +		super.setPadding(new Insets(0, 20, 10, 20)); +		super.setAlignment(Pos.BOTTOM_CENTER);  	}  	/**  	 * Checks if a note should be sent at the current time, and sends the note if it  	 * needs to be -	 *  -	 * @param sends the queue to check -	 * @param lane  the lane to send the note to  	 */ -	public void sendNote(Queue<NoteInfo> sends, ArrayList<Block> lane, Target button) { -		if (sends.peek() != null && timer.time() > sends.peek().getTime()-(1000*(bpm/60000.0))) { -			TranslateTransition anim = new TranslateTransition(Duration.millis(TIME+105)); - -			lane.add(new Block(button.getColor(), 50, 50, 5)); -			int index = lane.size() - 1; -			sends.remove(); -			lane.get(index).setCache(true); //added by tbone to try to improve performance -			lane.get(index).setCacheHint(CacheHint.SPEED); //this too -			lane.get(index).heightProperty().bind(super.widthProperty().divide(8)); -			lane.get(index).widthProperty().bind(super.widthProperty().divide(8)); -			lane.get(index).arcHeightProperty().bind(super.widthProperty().divide(25)); -			lane.get(index).arcWidthProperty().bind(super.widthProperty().divide(25)); -			lane.get(index).setX(button.getLayoutX()); -			lane.get(index).setY(-lane.get(index).getHeight()); -			anim.setInterpolator(Interpolator.LINEAR); -			anim.setByY(super.getHeight() + lane.get(index).getHeight() + 75); -			anim.setCycleCount(1); -			anim.setAutoReverse(false); -			anim.setNode(lane.get(lane.size() - 1)); -			anim.play(); - -			anim.setOnFinished(e -> { -				if (super.getChildren().removeAll(anim.getNode())){ -					scoreCounter.miss(missMute); -					FillTransition ft = new FillTransition(Duration.millis(500), button.rect); -					ft.setFromValue(Color.RED); -					ft.setToValue(button.getFillColor()); -					ft.play(); -				} -			}); -			super.getChildren().add(lane.get(lane.size() - 1)); -		} +	public void sendNote(Note note) { +		Lane lane = lanes[note.lane]; + +		Block block = new Block(lane.target.getColor(), 50, 50, 15); +		block.setCache(true); +		block.setCacheHint(CacheHint.SPEED); +		block.xProperty().bind(lane.pane.widthProperty().subtract(block.widthProperty()).divide(2)); +		block.yProperty().bind(block.heightProperty().negate()); +		bindBlock(block); + +		lane.blocks.add(block); + +		TranslateTransition anim = new TranslateTransition(Duration.seconds(FALL_TIME + 0.105)); +		anim.setInterpolator(Interpolator.LINEAR); +		anim.byYProperty().bind(super.heightProperty().add(block.getHeight()).add(75)); +		anim.setNode(block); +		anim.play(); +		anim.setOnFinished(_ -> { +			if (lane.pane.getChildren().remove(block) && !done) { +				scoreCounter.miss(); +				FillTransition ft = new FillTransition(Duration.millis(500), lane.target.rect); +				ft.setFromValue(Color.RED); +				ft.setToValue(lane.target.getFillColor()); +				ft.play(); +			} +		}); +		lane.pane.getChildren().add(block);  	}  	/** -	 * Sets up the given button -	 *  -	 * @param button +	 * Binds properties of the target to the screen +	 * @param target The target to bind  	 */ -	private void genButton(Target button) { -		button.rect.heightProperty().bind(super.widthProperty().divide(8)); -		button.rect.widthProperty().bind(super.widthProperty().divide(8)); -		button.rect.arcHeightProperty().bind(super.widthProperty().divide(25)); -		button.rect.arcWidthProperty().bind(super.widthProperty().divide(25)); -		button.rect.strokeWidthProperty().bind(super.widthProperty().divide(120)); +	private void bindTarget(Target target) { +		bindBlock(target.rect); +//		target.rect.strokeWidthProperty().bind(super.widthProperty().divide(120)); +	} + +	private void bindBlock(Rectangle block) { +		var sizeBind = super.heightProperty().multiply(87/1080.0); +		block.heightProperty().bind(sizeBind); +		block.widthProperty().bind(sizeBind); +		var arcBind = super.heightProperty().multiply(20/1080.0); +		block.arcHeightProperty().bind(arcBind); +		block.arcWidthProperty().bind(arcBind);  	}  	/** -	 * The background test that is run on every frame of the game +	 * starts the gameLoop, a periodic background task runner that runs the methods within it 60 times every second  	 */ -	AnimationTimer gameLoop = new AnimationTimer() { - -		@Override -		public void handle(long arg0) { -			for (KeyLane lane : lanes) { -				sendNote(lane.sends, lane.lane, lane.target); -			} - -			if (timer.time() > songLength) { -				Driver.setMenu(new GameOver(level, difficulty, pane, scoreCounter.getScore())); -				cancel(); -			} -			if (!songIsPlaying && timer.time() > 0.0) { -				songIsPlaying = true; -				Sound.playSong(song); -			} -		} -	}; - -	//starts the gameLoop, a periodic backround task runner that runs the methods within it 60 times every second -	public void start()  -	{ -		gameLoop.start(); +	public void start() { +		timeline.play();  	}  	/** -	 * Stops the gameloop -	 * @throws LineUnavailableException -	 * @throws IOException -	 * @throws UnsupportedAudioFileException +	 * Stops the gameLoop  	 */  	public void cancel() {  		Driver.primaryStage.removeEventFilter(KeyEvent.KEY_PRESSED, eventHandler); -		missMute = true; +		done = true;  		Sound.stopSong();  		Sound.playSong(Sound.MENU_SONG);  		Driver.setMenuBackground(); -		gameLoop.stop(); +		timeline.stop(); +		timeline.getKeyFrames().clear(); // for some reason other instances of Timeline will have these keyframes if I don't clear.  	}  	/**  	 * returns the pos in the lane array of the closest note to the goal -	 *  -	 * @param searchLane +	 * @param searchLane The list of blocks to search in  	 * @return the position of the note  	 */  	private int getClosestNote(ArrayList<Block> searchLane) {  		int pos = 0;  		for (int i = 0; i < searchLane.size(); i++) { -			if (distanceToGoal(searchLane.get(i)) < distanceToGoal(searchLane.get(pos))) { +			if (distanceToTarget(searchLane.get(i)) < distanceToTarget(searchLane.get(pos))) {  				pos = i;  			}  		} @@ -273,50 +207,49 @@ public class SongPlayer extends Pane {  	/**  	 * Returns the distance to the goal of the given note -	 *  -	 * @param note -	 * @return +	 * @param note Note to check the distance of +	 * @return The distance between the note and the target in pixels  	 */ -	private double distanceToGoal(Block note) { +	private double distanceToTarget(Block note) {  		return Math.abs((super.getHeight() - note.getTranslateY() + note.getHeight()/2) - lanes[0].target.rect.getLayoutY());  	}  	/**  	 * When the player hits the key, checks the quality of the hit  	 * @param lane the lane checking for a hit -	 * @param button the button checking for a hit  	 * @return 2 for a perfect hit, 1 for a good hit, 0 for a miss, and -1 if there are no notes to hit  	 */ -	private int checkNote(ArrayList<Block> lane, Target button) { -		if (lane.size() != 0 && super.isVisible()) -		{ -			double distance = distanceToGoal(lane.get(getClosestNote(lane))); -			if (lane.size() > 0 && distance < super.getHeight() / 3) { - -				FillTransition ft = new FillTransition(Duration.millis(500), button.rect); -				ft.setToValue(button.getFillColor()); - -				super.getChildren().removeAll(lane.get(getClosestNote(lane))); -				lane.remove(lane.get(getClosestNote(lane))); -				if (distance < super.getHeight() / 12) { -					ft.setFromValue(Color.WHITE); -					ft.play(); -					scoreCounter.perfect(); -					return 2; -				} -				if (distance < super.getHeight() / 4) { -					ft.setFromValue(Color.CYAN); -					ft.play(); -					scoreCounter.good(); -					return 1; -				} -				ft.setFromValue(Color.RED); -				ft.play(); -				scoreCounter.miss(false); -				return 0; -			} -		}	 -		return -1; +	private int checkNote(Lane lane) { +		ArrayList<Block> blocks = lane.blocks; +        if (blocks.isEmpty() || done) { +            return -1; +        } +        double distance = distanceToTarget(blocks.get(getClosestNote(blocks))); +        if (distance < super.getHeight() / 3) { + +            FillTransition ft = new FillTransition(Duration.millis(500), lane.target.rect); +            ft.setToValue(lane.target.getFillColor()); + +            lane.pane.getChildren().removeAll(blocks.get(getClosestNote(blocks))); +            blocks.remove(blocks.get(getClosestNote(blocks))); +            if (distance < super.getHeight() / 12) { +                ft.setFromValue(Color.WHITE); +                ft.play(); +                scoreCounter.perfect(); +                return 2; +            } +            if (distance < super.getHeight() / 4) { +                ft.setFromValue(Color.CYAN); +                ft.play(); +                scoreCounter.good(); +                return 1; +            } +            ft.setFromValue(Color.RED); +            ft.play(); +            scoreCounter.miss(); +            return 0; +        } +        return -1;  	}  }
\ No newline at end of file diff --git a/src/main/java/net/sowgro/npehero/gameplay/Target.java b/src/main/java/net/sowgro/npehero/gameplay/Target.java index 229abcb..45907d3 100755 --- a/src/main/java/net/sowgro/npehero/gameplay/Target.java +++ b/src/main/java/net/sowgro/npehero/gameplay/Target.java @@ -30,7 +30,7 @@ public class Target extends StackPane          rect.setArcHeight(r);          rect.setArcWidth(r);          rect.setStroke(col); -        rect.setStrokeWidth(5); +        rect.setStrokeWidth(4);      }      public void setColor(Color c) { diff --git a/src/main/java/net/sowgro/npehero/gameplay/Timer.java b/src/main/java/net/sowgro/npehero/gameplay/Timer.java deleted file mode 100755 index eada237..0000000 --- a/src/main/java/net/sowgro/npehero/gameplay/Timer.java +++ /dev/null @@ -1,28 +0,0 @@ -/*Name:	Guitar Hero Project - *Description: Contains the method used to determine how long the user has been playing,  - *             used to determine when to send notes - */ -package net.sowgro.npehero.gameplay; - - -public class Timer -{ -    private long timeStart = System.currentTimeMillis(); -    private double bpm; - -    public Timer(double newBpm) { -        bpm = newBpm; -    } - -    public Timer() { -        bpm = 60000; -    } - -    public double time() { -        return ((double)(System.currentTimeMillis()-timeStart)-2000)*(bpm/60000.0); -    } - -    public String toString() {       -        return ""+((Math.round(10*(((double)(System.currentTimeMillis()-timeStart))*(bpm/60000.0))))/10.0); -    } -} diff --git a/src/main/java/net/sowgro/npehero/gui/LevelSurround.java b/src/main/java/net/sowgro/npehero/gui/LevelSurround.java index 09eeaa0..4b11c15 100755 --- a/src/main/java/net/sowgro/npehero/gui/LevelSurround.java +++ b/src/main/java/net/sowgro/npehero/gui/LevelSurround.java @@ -1,5 +1,6 @@  package net.sowgro.npehero.gui; +import javafx.animation.AnimationTimer;  import net.sowgro.npehero.Driver;  import net.sowgro.npehero.gameplay.SongPlayer;  import javafx.geometry.Insets; @@ -12,7 +13,6 @@ import javafx.scene.layout.StackPane;  import javafx.scene.layout.VBox;  import javafx.scene.text.Text;  import net.sowgro.npehero.levelapi.Difficulty; -import net.sowgro.npehero.levelapi.Level;  import net.sowgro.npehero.gameplay.ScoreController;  import net.sowgro.npehero.main.Page;  import net.sowgro.npehero.main.Sound; @@ -55,10 +55,10 @@ public class LevelSurround extends Page          AnchorPane topBar = new AnchorPane();          topBar.getChildren().addAll(buttonBox,titleTextBox); -        topBar.setLeftAnchor(buttonBox, 0.0); -        topBar.setRightAnchor(titleTextBox, 0.0); -        topBar.setTopAnchor(buttonBox, 0.0); -        topBar.setTopAnchor(titleTextBox, 0.0); +        AnchorPane.setLeftAnchor(buttonBox, 0.0); +        AnchorPane.setRightAnchor(titleTextBox, 0.0); +        AnchorPane.setTopAnchor(buttonBox, 0.0); +        AnchorPane.setTopAnchor(titleTextBox, 0.0);          topBar.setPadding(new Insets(10)); @@ -79,8 +79,8 @@ public class LevelSurround extends Page          AnchorPane scoreBox = new AnchorPane();          scoreBox.getChildren().add(scoreTextBox); -        scoreBox.setLeftAnchor(scoreTextBox, 0.0); -        scoreBox.setBottomAnchor(scoreTextBox, 0.0); +        AnchorPane.setLeftAnchor(scoreTextBox, 0.0); +        AnchorPane.setBottomAnchor(scoreTextBox, 0.0);          scoreBox.setPadding(new Insets(10));          Text comboLabel = new Text(); @@ -100,17 +100,17 @@ public class LevelSurround extends Page          AnchorPane comboBox = new AnchorPane();          comboBox.getChildren().add(comboTextBox); -        comboBox.setRightAnchor(comboTextBox, 0.0); -        comboBox.setBottomAnchor(comboTextBox, 0.0); +        AnchorPane.setRightAnchor(comboTextBox, 0.0); +        AnchorPane.setBottomAnchor(comboTextBox, 0.0);          comboBox.setPadding(new Insets(10)); -        game.minWidthProperty().bind(content.heightProperty().multiply(0.66)); +        game.minWidthProperty().bind(content.heightProperty().multiply(0.55));          game.minHeightProperty().bind(content.heightProperty());          game.getStyleClass().add("box"); -        comboBox.minWidthProperty().bind(Driver.primaryPane.widthProperty().subtract(game.minWidthProperty()).divide(2)); -        scoreBox.minWidthProperty().bind(Driver.primaryPane.widthProperty().subtract(game.minWidthProperty()).divide(2)); +        comboBox.minWidthProperty().bind(Driver.primaryPane.widthProperty().subtract(game.widthProperty()).divide(2)); +        scoreBox.minWidthProperty().bind(Driver.primaryPane.widthProperty().subtract(game.widthProperty()).divide(2));          HBox centerBox = new HBox();          centerBox.getChildren().addAll(comboBox, game, scoreBox); @@ -121,7 +121,12 @@ public class LevelSurround extends Page          content.getChildren().add(root); -        game.start(); +        new AnimationTimer() { +            @Override +            public void handle(long now) { +                game.start(); +            } +        }.start();      }      @Override diff --git a/src/main/java/net/sowgro/npehero/levelapi/Note.java b/src/main/java/net/sowgro/npehero/levelapi/Note.java index ab93885..4010867 100644 --- a/src/main/java/net/sowgro/npehero/levelapi/Note.java +++ b/src/main/java/net/sowgro/npehero/levelapi/Note.java @@ -31,4 +31,8 @@ public class Note {          this.lane = other.lane;          this.time.set(other.time.get());      } + +    public double getTime() { +        return time.get(); +    }  } diff --git a/src/main/java/net/sowgro/npehero/main/Control.java b/src/main/java/net/sowgro/npehero/main/Control.java index ece88ac..69bf669 100644 --- a/src/main/java/net/sowgro/npehero/main/Control.java +++ b/src/main/java/net/sowgro/npehero/main/Control.java @@ -28,19 +28,46 @@ public enum Control {      LEGACY_PRINT    ("Print Time", KeyCode.Q),      LEGACY_STOP     ("Stop Edit", KeyCode.ESCAPE); -    public final String label; -    public final KeyCode defaultKey; -    public final ObjectProperty<KeyCode> keyProperty = new SimpleObjectProperty<>(); -      public static final List<Map.Entry<String, List<Control>>> sections = List.of(                  entry("Gameplay",      List.of(LANE0, LANE1, LANE2, LANE3, LANE4)),                  entry("Editor",        List.of(DELETE_NOTE, NOTE_UP, NOTE_DOWN, SCROLL_LOCK, PLAY_PAUSE, CLEAR_SELECTION, SELECT_ALL)),                  entry("Legacy Editor", List.of(LEGACY_PRINT, LEGACY_STOP))              ); +    public static final Control[] lanes = { +            LANE0, +            LANE1, +            LANE2, +            LANE3, +            LANE4, +    }; +      private static final File file = new File("controls.json");      private static final Gson json = new GsonBuilder().serializeNulls().setPrettyPrinting().create(); +    public static void writeToFile() throws IOException { +        Map<String, Object> data = new HashMap<>(); +        for (Control control : Control.values()) { +            data.put(control.toString(), control.getKey().toString()); +        } +        FileWriter fileWriter = new FileWriter(file); +        json.toJson(data, fileWriter); +        fileWriter.close(); +    } + +    public static void readFromFile() throws Exception { +        Map<String, Object> data = json.fromJson(new FileReader(file), Map.class); +        for (Control control : Control.values()) { +            if (data.containsKey(control.toString())) { +                control.setKey(KeyCode.valueOf((String) data.getOrDefault(control.toString(), null))); +            } +        } +    } + +    public final String label; +    public final KeyCode defaultKey; +    public final ObjectProperty<KeyCode> keyProperty = new SimpleObjectProperty<>(); +      Control(String label, KeyCode key) {          this.label = label;          this.defaultKey = key; @@ -81,23 +108,4 @@ public enum Control {              }          };      } - -    public static void writeToFile() throws IOException { -        Map<String, Object> data = new HashMap<>(); -        for (Control control : Control.values()) { -            data.put(control.toString(), control.getKey().toString()); -        } -        FileWriter fileWriter = new FileWriter(file); -        json.toJson(data, fileWriter); -        fileWriter.close(); -    } - -    public static void readFromFile() throws Exception { -        Map<String, Object> data = json.fromJson(new FileReader(file), Map.class); -        for (Control control : Control.values()) { -            if (data.containsKey(control.toString())) { -                control.setKey(KeyCode.valueOf((String) data.getOrDefault(control.toString(), null))); -            } -        } -    }  } diff --git a/src/main/java/net/sowgro/npehero/main/Sound.java b/src/main/java/net/sowgro/npehero/main/Sound.java index 088eab6..cf776a6 100755 --- a/src/main/java/net/sowgro/npehero/main/Sound.java +++ b/src/main/java/net/sowgro/npehero/main/Sound.java @@ -28,6 +28,7 @@ public class Sound          songMediaPlayer = new MediaPlayer(song);          if (song == MENU_SONG) {              songMediaPlayer.muteProperty().bind(Settings.enableMenuMusic.not()); +            songMediaPlayer.setCycleCount(MediaPlayer.INDEFINITE);          }          songMediaPlayer.volumeProperty().bind(Settings.musicVol);          songMediaPlayer.play(); | 
