end game and level select for hunt

This commit is contained in:
RandomityGuy 2023-07-02 23:19:01 +05:30
parent a7d5472088
commit a0990054ea
11 changed files with 122 additions and 22 deletions

View file

@ -249,13 +249,15 @@ class CameraController extends Object {
if (this.finish) {
// Move the target to the centre of the finish
var padMat = @:privateAccess this.level.endPad.getAbsPos();
var offset = padMat.up();
var padPos = padMat.getPosition();
var focusPos = padPos.add(offset);
focusPos.scale(0.025);
focusPos = focusPos.add(lastTargetPos.multiply(0.975));
marblePosition = focusPos;
if (@:privateAccess this.level.endPad != null) {
var padMat = @:privateAccess this.level.endPad.getAbsPos();
var offset = padMat.up();
var padPos = padMat.getPosition();
var focusPos = padPos.add(offset);
focusPos.scale(0.025);
focusPos = focusPos.add(lastTargetPos.multiply(0.975));
marblePosition = focusPos;
}
}
var up = new Vector(0, 0, 1);

View file

@ -1165,6 +1165,8 @@ class MarbleWorld extends Scheduler {
} else if (this.timeState.currentAttemptTime + dt >= 3.5) {
this.timeState.gameplayClock += ((this.timeState.currentAttemptTime + dt) - 3.5) * timeMultiplier;
}
if (this.timeState.gameplayClock < 0)
this.gameMode.onTimeExpire();
}
this.timeState.currentAttemptTime += dt;
} else {
@ -1493,7 +1495,7 @@ class MarbleWorld extends Scheduler {
} else {
nextLevelCode();
}
}, mission, finishTime);
}, mission, this.gameMode.getFinishScore(), this.gameMode.getScoreType());
MarbleGame.canvas.pushDialog(egg);
this.setCursorLock(false);
return 0;

View file

@ -49,6 +49,10 @@ class Radar {
}
}
public function blink() {
time = 0;
}
public function reset() {
time = 0;
g.clear();

View file

@ -1,5 +1,6 @@
package src;
import modes.GameMode.ScoreType;
import h3d.Vector;
import haxe.ds.Option;
import gui.Canvas;
@ -241,11 +242,13 @@ class Settings {
save();
}
public static function saveScore(mapPath:String, score:Score) {
public static function saveScore(mapPath:String, score:Score, scoreType:ScoreType = Time) {
if (highScores.exists(mapPath)) {
var scoreList = highScores.get(mapPath);
scoreList.push(score);
scoreList.sort((a, b) -> a.time == b.time ? 0 : (a.time > b.time ? 1 : -1));
if (scoreType == Score)
scoreList.reverse();
} else {
highScores.set(mapPath, [score]);
}

View file

@ -297,6 +297,11 @@ class Util {
return false;
}
public static function formatScore(score:Float) {
var scoreInt = Std.int(Math.round(score));
return '${scoreInt}';
}
public static function formatTime(time:Float) {
var et = time * 1000;
var thousandth = Std.int(et % 10);

View file

@ -1,5 +1,6 @@
package gui;
import modes.GameMode.ScoreType;
import mis.MisParser;
import hxd.BitmapData;
import h2d.Tile;
@ -21,7 +22,8 @@ class EndGameGui extends GuiImage {
var scoreSubmitted:Bool = false;
public function new(continueFunc:GuiControl->Void, restartFunc:GuiControl->Void, nextLevelFunc:GuiControl->Void, mission:Mission, timeState:TimeState) {
public function new(continueFunc:GuiControl->Void, restartFunc:GuiControl->Void, nextLevelFunc:GuiControl->Void, mission:Mission, score:Float,
scoreType:ScoreType) {
var res = ResourceLoader.getImage("data/ui/xbox/BG_fadeOutSoftEdge.png").resource.toTile();
super(res);
this.horizSizing = Width;
@ -86,12 +88,15 @@ class EndGameGui extends GuiImage {
return arial14;
}
var beatPar = timeState.gameplayClock < mission.qualifyTime;
var beatPar = score < mission.qualifyTime;
var egResultLeft = new GuiMLText(arial14, mlFontLoader);
egResultLeft.position = new Vector(28, 26);
egResultLeft.extent = new Vector(180, 100);
egResultLeft.text.text = '<p align="right"><font color="${beatPar ? "#8DFF8D" : "0xFF7575"}">Time:</font><br/><font color="#88BCEE">Par Time:</font><br/><font color="#EBEBEB">Rating:</font><br/><font color="#EBEBEB">My Best Time:</font></p>';
if (scoreType == Time)
egResultLeft.text.text = '<p align="right"><font color="${beatPar ? "#8DFF8D" : "#FF7575"}">Time:</font><br/><font color="#88BCEE">Par Time:</font><br/><font color="#EBEBEB">Rating:</font><br/><font color="#EBEBEB">My Best Time:</font></p>';
if (scoreType == Score)
egResultLeft.text.text = '<p align="right"><font color="#8DFF8D">Score:</font><br/><font color="#EBEBEB">My Best Score:</font></p>';
endGameWnd.addChild(egResultLeft);
var c0 = 0xEBEBEB;
var c1 = 0x8DFF8D;
@ -111,15 +116,17 @@ class EndGameGui extends GuiImage {
return (completionBonus + timeBonus) * difficulty;
}
var rating = calcRating(timeState.gameplayClock * 1000, mission.qualifyTime * 1000, mission.goldTime * 1000,
Std.parseInt(mission.missionInfo.difficulty));
var rating = calcRating(score * 1000, mission.qualifyTime * 1000, mission.goldTime * 1000, Std.parseInt(mission.missionInfo.difficulty));
var myScore = {name: "Player", time: timeState.gameplayClock};
Settings.saveScore(mission.path, myScore);
var myScore = {name: "Player", time: score};
Settings.saveScore(mission.path, myScore, scoreType);
var scoreData:Array<Score> = Settings.getScores(mission.path);
while (scoreData.length < 1) {
scoreData.push({name: "Nardo Polo", time: 5999.999});
if (scoreType == Score)
scoreData.push({name: "Nardo Polo", time: 0});
if (scoreType == Time)
scoreData.push({name: "Nardo Polo", time: 5999.999});
}
var bestScore = scoreData[0];
@ -128,7 +135,10 @@ class EndGameGui extends GuiImage {
egResultRight.position = new Vector(214, 26);
egResultRight.extent = new Vector(180, 100);
egResultRight.text.text = '<font color="${beatPar ? "#8DFF8D" : "0xFF7575"}">${Util.formatTime(timeState.gameplayClock)}</font><br/><font color="#88BCEE">${Util.formatTime(mission.qualifyTime)}</font><br/><font color="#EBEBEB">${rating}</font><br/><font color="#EBEBEB">${Util.formatTime(bestScore.time)}</font>';
if (scoreType == Score)
egResultRight.text.text = '<font color="#8DFF8D">${Util.formatScore(score)}</font><br/><font color="#EBEBEB">${Util.formatScore(bestScore.time)}</font>';
if (scoreType == Time)
egResultRight.text.text = '<font color="${beatPar ? "#8DFF8D" : "0xFF7575"}">${Util.formatTime(score)}</font><br/><font color="#88BCEE">${Util.formatTime(mission.qualifyTime)}</font><br/><font color="#EBEBEB">${rating}</font><br/><font color="#EBEBEB">${Util.formatTime(bestScore.time)}</font>';
endGameWnd.addChild(egResultRight);
var bottomBar = new GuiControl();

View file

@ -1,5 +1,6 @@
package gui;
import modes.GameMode.ScoreType;
import src.Util;
import haxe.io.Path;
import h2d.filter.DropShadow;
@ -223,16 +224,29 @@ class LevelSelectGui extends GuiImage {
loadText.text.visible = false;
loadTextBg.text.visible = false;
});
var scoreType = mis.missionInfo.gamemode != null
&& mis.missionInfo.gamemode.toLowerCase() == 'scrum' ? ScoreType.Score : ScoreType.Time;
var myScore = Settings.getScores(mis.path);
var scoreDisp = "None";
if (myScore.length != 0)
scoreDisp = Util.formatTime(myScore[0].time);
scoreDisp = scoreType == Time ? Util.formatTime(myScore[0].time) : Util.formatScore(myScore[0].time);
var isPar = myScore.length != 0 && myScore[0].time < mis.qualifyTime;
var scoreColor = "#EBEBEB";
if (isPar)
scoreColor = "#8DFF8D";
levelInfoMid.text.text = '<p align="left"><font color="${scoreColor}">${scoreDisp}</font><br/><font color="#88BCEE">${Util.formatTime(mis.qualifyTime)}</font></p>';
levelInfoRight.text.text = '<p align="left"><font color="#EBEBEB">Level ${mis.missionInfo.level}<br/>Difficulty ${mis.missionInfo.difficulty}</font></p>';
if (scoreType == Score && myScore.length == 0)
scoreColor = "#EBEBEB";
if (scoreType == Time) {
levelInfoLeft.text.text = '<p align="right"><font color="#EBEBEB">My Best Time:</font><br/><font color="#EBEBEB">Par Time:</font></p>';
levelInfoMid.text.text = '<p align="left"><font color="${scoreColor}">${scoreDisp}</font><br/><font color="#88BCEE">${Util.formatTime(mis.qualifyTime)}</font></p>';
}
if (scoreType == Score) {
levelInfoLeft.text.text = '<p align="right"><font color="#EBEBEB">My Best Score:</font></p>';
levelInfoMid.text.text = '<p align="left"><font color="${scoreColor}">${scoreDisp}</font></p>';
}
levelInfoRight.text.text = '<p align="left"><font color="#EBEBEB">Level ${mis.missionInfo.level}<br/>Difficulty ${mis.missionInfo.difficulty == null ? "" : mis.missionInfo.difficulty}</font></p>';
return true;
}

View file

@ -718,6 +718,8 @@ class PlayGui {
// 1: green
// 2: red
public function formatTimer(time:Float) {
if (time < 0)
time = 0; // Can't support negatives for now
var et = time * 1000;
var thousandth = et % 10;
var hundredth = Math.floor((et % 1000) / 10);

View file

@ -6,13 +6,20 @@ import h3d.Vector;
import src.MarbleWorld;
import src.Mission;
enum ScoreType {
Time;
Score;
}
interface GameMode {
public function getSpawnTransform():{position:Vector, orientation:Quat, up:Vector};
public function getRespawnTransform():{position:Vector, orientation:Quat, up:Vector};
public function missionScan(mission:Mission):Void;
public function getStartTime():Float;
public function timeMultiplier():Float;
public function getScoreType():ScoreType;
public function getFinishScore():Float;
public function onTimeExpire():Void;
public function onRestart():Void;
public function onGemPickup(gem:Gem):Void;

View file

@ -1,5 +1,7 @@
package modes;
import gui.AchievementsGui;
import modes.GameMode.ScoreType;
import shapes.GemBeam;
import shapes.Gem;
import src.Console;
@ -219,6 +221,7 @@ class HuntMode extends NullMode {
var spawnGroup = pickGemSpawnGroup();
activeGemSpawnGroup = spawnGroup;
fillGemGroup(spawnGroup);
@:privateAccess level.radar.blink();
}
}
@ -312,4 +315,41 @@ class HuntMode extends NullMode {
'sound/gem_collect.wav'
];
}
override function getScoreType():ScoreType {
return Score;
}
override function onTimeExpire() {
if (level.finishTime != null)
return;
AudioManager.playSound(ResourceLoader.getResource('data/sound/finish.wav', ResourceLoader.getAudio, @:privateAccess level.soundResources));
level.finishTime = level.timeState.clone();
level.marble.setMode(Start);
level.marble.camera.finish = true;
level.finishYaw = level.marble.camera.CameraYaw;
level.finishPitch = level.marble.camera.CameraPitch;
level.displayAlert("Congratulations! You've finished!");
if (!level.isWatching) {
var notifies = AchievementsGui.check();
var delay = 5.0;
var achDelay = 0.0;
for (i in 0...9) {
if (notifies & (1 << i) > 0)
achDelay += 3;
}
if (notifies > 0)
achDelay += 0.5;
@:privateAccess level.schedule(level.timeState.currentAttemptTime + Math.max(delay, achDelay), () -> cast level.showFinishScreen());
}
// Stop the ongoing sounds
if (@:privateAccess level.timeTravelSound != null) {
@:privateAccess level.timeTravelSound.stop();
@:privateAccess level.timeTravelSound = null;
}
}
override function getFinishScore():Float {
return points;
}
}

View file

@ -1,5 +1,6 @@
package modes;
import modes.GameMode.ScoreType;
import shapes.Gem;
import h3d.Quat;
import h3d.Vector;
@ -83,4 +84,14 @@ class NullMode implements GameMode {
public function getPreloadFiles() {
return ['data/sound/gem_all.wav'];
}
public function onTimeExpire() {}
public function getScoreType():ScoreType {
return Time;
}
public function getFinishScore():Float {
return level.finishTime.gameplayClock;
}
}