achievement check stuff

This commit is contained in:
RandomityGuy 2023-06-30 20:05:29 +05:30
parent 23d249ceee
commit 05f257f0c8
28 changed files with 639 additions and 166 deletions

BIN
data/ui/achievement/1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

BIN
data/ui/achievement/10.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

BIN
data/ui/achievement/11.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

BIN
data/ui/achievement/12.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

BIN
data/ui/achievement/2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

BIN
data/ui/achievement/3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

BIN
data/ui/achievement/4.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

BIN
data/ui/achievement/5.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

BIN
data/ui/achievement/6.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

BIN
data/ui/achievement/7.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

BIN
data/ui/achievement/8.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

BIN
data/ui/achievement/9.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

BIN
data/ui/achievement/all.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 747 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

View file

@ -1,5 +1,6 @@
package src;
import gui.AchievementsGui;
import src.Radar;
import gui.LevelSelectGui;
import h3d.scene.fwd.Light;
@ -1389,8 +1390,18 @@ class MarbleWorld extends Scheduler {
this.finishYaw = this.marble.camera.CameraYaw;
this.finishPitch = this.marble.camera.CameraPitch;
displayAlert("Congratulations! You've finished!");
if (!this.isWatching)
this.schedule(this.timeState.currentAttemptTime + 5, () -> cast showFinishScreen());
if (!this.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;
this.schedule(this.timeState.currentAttemptTime + Math.max(delay, achDelay), () -> cast showFinishScreen());
}
// Stop the ongoing sounds
if (timeTravelSound != null) {
timeTravelSound.stop();

View file

@ -191,6 +191,8 @@ class Settings {
public static var levelStatistics:Map<String, PlayStatistics> = [];
public static var achievementProgression:Int;
public static var highscoreName = "";
public static var uiScale = 1.0;
@ -250,6 +252,7 @@ class Settings {
marbleModel: optionsSettings.marbleModel,
marbleCategoryIndex: optionsSettings.marbleCategoryIndex,
marbleShader: optionsSettings.marbleShader,
achievementProgression: achievementProgression
};
var scoreCount = 0;
var eggCount = 0;
@ -379,6 +382,7 @@ class Settings {
if (json.stats != null) {
playStatistics = json.stats;
}
achievementProgression = json.achievementProgression;
if (json.levelStatistics != null) {
var levelStatData:DynamicAccess<PlayStatistics> = json.levelStatistics;
for (key => value in levelStatData) {
@ -409,6 +413,8 @@ class Settings {
if (optionsSettings.rewindTimescale == null) {
optionsSettings.rewindTimescale = 1;
}
if (achievementProgression == null)
achievementProgression = 0;
#end
highscoreName = json.highscoreName;
} else {

View file

@ -0,0 +1,36 @@
package gui;
import gui.GuiControl.MouseState;
import h3d.Vector;
import src.ResourceLoader;
import src.MarbleGame;
class AchievementPopupDlg extends GuiControl {
var lifetime:Float = 0;
var onFinish:() -> Void;
public function new(id:Int) {
super();
this.extent = new Vector(640, 480);
this.position = new Vector();
this.horizSizing = Width;
this.vertSizing = Height;
var popup = new GuiImage(ResourceLoader.getResource('data/ui/achievement/${id}.png', ResourceLoader.getImage, this.imageResources).toTile());
popup.horizSizing = Center;
popup.vertSizing = Bottom;
popup.position = new Vector(70, 465);
popup.extent = new Vector(477, 90);
this.addChild(popup);
}
override function update(dt:Float, mouseState:MouseState) {
super.update(dt, mouseState);
lifetime += dt;
if (lifetime > 3) {
MarbleGame.canvas.popDialog(this);
if (onFinish != null)
onFinish();
}
}
}

View file

@ -9,184 +9,309 @@ import src.Mission;
import src.MissionList;
class AchievementsGui extends GuiImage {
public function new() {
var img = ResourceLoader.getImage("data/ui/achiev/window.png");
super(img.resource.toTile());
this.horizSizing = Center;
this.vertSizing = Center;
this.position = new Vector(73, -21);
this.extent = new Vector(493, 512);
var innerCtrl:GuiControl;
var btnList:GuiXboxList;
var achiev = new GuiImage(ResourceLoader.getResource("data/ui/achiev/achiev.png", ResourceLoader.getImage, this.imageResources).toTile());
achiev.position = new Vector(152, 26);
achiev.extent = new Vector(176, 50);
this.addChild(achiev);
public function new(isPause:Bool = false) {
var res = ResourceLoader.getImage("data/ui/xbox/BG_fadeOutSoftEdge.png").resource.toTile();
super(res);
var arial14fontdata = ResourceLoader.getFileEntry("data/font/Arial Bold.fnt");
var arial14b = new BitmapFont(arial14fontdata.entry);
@:privateAccess arial14b.loader = ResourceLoader.loader;
var arial14 = arial14b.toSdfFont(cast 12 * Settings.uiScale, MultiChannel);
var arial14 = arial14b.toSdfFont(cast 21 * Settings.uiScale, h2d.Font.SDFChannel.MultiChannel);
var domcasual32fontdata = ResourceLoader.getFileEntry("data/font/DomCasualD.fnt");
var domcasual32b = new BitmapFont(domcasual32fontdata.entry);
@:privateAccess domcasual32b.loader = ResourceLoader.loader;
var domcasual32 = domcasual32b.toSdfFont(cast 26 * Settings.uiScale, MultiChannel);
var domcasual64 = domcasual32b.toSdfFont(cast 58 * Settings.uiScale, MultiChannel);
var domcasual24 = domcasual32b.toSdfFont(cast 20 * Settings.uiScale, MultiChannel);
this.horizSizing = Width;
this.vertSizing = Height;
this.position = new Vector();
this.extent = new Vector(640, 480);
function mlFontLoader(text:String) {
switch (text) {
case "DomCasual24":
return domcasual24;
case "Arial14":
return arial14;
default:
return null;
var scene2d = MarbleGame.canvas.scene2d;
var offsetX = (scene2d.width - 1280) / 2;
var offsetY = (scene2d.height - 720) / 2;
var subX = 640 - (scene2d.width - offsetX) * 640 / scene2d.width;
var subY = 480 - (scene2d.height - offsetY) * 480 / scene2d.height;
innerCtrl = new GuiControl();
innerCtrl.position = new Vector(offsetX, offsetY);
innerCtrl.extent = new Vector(640 - subX, 480 - subY);
innerCtrl.horizSizing = Width;
innerCtrl.vertSizing = Height;
this.addChild(innerCtrl);
var achievementsWnd = new GuiImage(ResourceLoader.getResource("data/ui/xbox/achievementWindow.png", ResourceLoader.getImage, this.imageResources)
.toTile());
achievementsWnd.horizSizing = Center;
achievementsWnd.vertSizing = Center;
achievementsWnd.position = new Vector(25, 58);
achievementsWnd.extent = new Vector(600, 480);
innerCtrl.addChild(achievementsWnd);
function imgLoader(path:String) {
switch (path) {
case "locked":
return ResourceLoader.getResource("data/ui/xbox/DemoOutOfTimeIcon.png", ResourceLoader.getImage, this.imageResources).toTile();
case "unlocked":
return ResourceLoader.getResource("data/ui/xbox/Ready.png", ResourceLoader.getImage, this.imageResources).toTile();
}
return null;
}
function loadButtonImages(path:String) {
var normal = ResourceLoader.getResource('${path}_n.png', ResourceLoader.getImage, this.imageResources).toTile();
var hover = ResourceLoader.getResource('${path}_h.png', ResourceLoader.getImage, this.imageResources).toTile();
var pressed = ResourceLoader.getResource('${path}_d.png', ResourceLoader.getImage, this.imageResources).toTile();
var disabled = ResourceLoader.getResource('${path}_i.png', ResourceLoader.getImage, this.imageResources).toTile();
return [normal, hover, pressed, disabled];
var curSelection = -1;
check(); // Check achievements
var achNameDisplays = [
"<img src='locked'></img>Timely Marble",
"<img src='locked'></img>Apprentice's Badge",
"<img src='locked'></img>Journeyman's Badge",
"<img src='locked'></img>Adept's Badge",
"<img src='locked'></img>Marble-fu Initiate",
"<img src='locked'></img>Marble-fu Master",
"<img src='locked'></img>Marble-fu Transcendent",
"<img src='locked'></img>Egg Seeker",
"<img src='locked'></img>Egg Basket"
];
if (Settings.achievementProgression & 1 == 1)
achNameDisplays[0] = "<img src='unlocked'></img>Timely Marble";
if (Settings.achievementProgression & 2 == 2)
achNameDisplays[1] = "<img src='unlocked'></img>Apprentice's Badge";
if (Settings.achievementProgression & 4 == 4)
achNameDisplays[2] = "<img src='unlocked'></img>Journeyman's Badge";
if (Settings.achievementProgression & 8 == 8)
achNameDisplays[3] = "<img src='unlocked'></img>Adept's Badge";
if (Settings.achievementProgression & 16 == 16)
achNameDisplays[4] = "<img src='unlocked'></img>Marble-fu Initiate";
if (Settings.achievementProgression & 32 == 32)
achNameDisplays[5] = "<img src='unlocked'></img>Marble-fu Master";
if (Settings.achievementProgression & 64 == 64)
achNameDisplays[6] = "<img src='unlocked'></img>Marble-fu Transcendent";
if (Settings.achievementProgression & 128 == 128)
achNameDisplays[7] = "<img src='unlocked'></img>Egg Seeker";
if (Settings.achievementProgression & 256 == 256)
achNameDisplays[8] = "<img src='unlocked'></img>Egg Basket";
var achievementsList = new GuiMLTextListCtrl(arial14, achNameDisplays, imgLoader);
achievementsList.selectedColor = 0xF29515;
achievementsList.selectedFillColor = 0xEBEBEB;
achievementsList.position = new Vector(25, 22);
achievementsList.extent = new Vector(550, 480);
achievementsList.scrollable = true;
achievementsList.onSelectedFunc = (sel) -> {
curSelection = sel;
}
achievementsWnd.addChild(achievementsList);
var achievText = new GuiMLText(domcasual32, mlFontLoader);
achievText.position = new Vector(156, 60);
achievText.extent = new Vector(262, 410);
achievText.text.textColor = 0;
achievText.text.text = '<font face="DomCasual24">Amateur Marbler</font><br/><font face="Arial14">Beat all Beginner levels.</font><br/>
<font face="DomCasual24">Experienced Marbler</font><br/><font face="Arial14">Beat all Intermediate levels.</font><br/>
<font face="DomCasual24">Pro Marbler</font><br/><font face="Arial14">Beat all Advanced levels.</font><br/>
<font face="DomCasual24">Skilled Marbler</font><br/><font face="Arial14">Beat all Expert Levels</font><br/>
<font face="DomCasual24">Marble Master</font><br/><font face="Arial14">Beat all of the Platinum Times.</font><br/>
<font face="DomCasual24">Legendary Marbler</font><br/><font face="Arial14">Beat all of the Ultimate Times.</font><br/>
<font face="DomCasual24">Egg Seeker</font><br/><font face="Arial14">Find any Easter Egg.</font><br/>
<font face="DomCasual24">Easter Bunny</font><br/><font face="Arial14">Find all of the Easter Eggs.</font>';
var bottomBar = new GuiControl();
bottomBar.position = new Vector(0, 590);
bottomBar.extent = new Vector(640, 200);
bottomBar.horizSizing = Width;
bottomBar.vertSizing = Bottom;
innerCtrl.addChild(bottomBar);
this.addChild(achievText);
var backButton = new GuiXboxButton("Back", 160);
backButton.position = new Vector(400, 0);
backButton.vertSizing = Bottom;
backButton.horizSizing = Right;
backButton.gamepadAccelerator = ["B"];
if (isPause)
backButton.pressedAction = (e) -> {
MarbleGame.canvas.popDialog(this);
MarbleGame.instance.showPauseUI();
}
else
backButton.pressedAction = (e) -> MarbleGame.canvas.setContent(new MainMenuGui());
bottomBar.addChild(backButton);
var bmp1 = new GuiImage(ResourceLoader.getResource("data/ui/achiev/nonachiev.png", ResourceLoader.getImage, this.imageResources).toTile());
bmp1.position = new Vector(39, 62);
bmp1.extent = new Vector(113, 44);
this.addChild(bmp1);
var bmp2 = new GuiImage(ResourceLoader.getResource("data/ui/achiev/nonachiev.png", ResourceLoader.getImage, this.imageResources).toTile());
bmp2.position = new Vector(35, 115);
bmp2.extent = new Vector(117, 44);
this.addChild(bmp2);
var bmp3 = new GuiImage(ResourceLoader.getResource("data/ui/achiev/nonachiev.png", ResourceLoader.getImage, this.imageResources).toTile());
bmp3.position = new Vector(30, 168);
bmp3.extent = new Vector(122, 44);
this.addChild(bmp3);
var bmp4 = new GuiImage(ResourceLoader.getResource("data/ui/achiev/nonachiev.png", ResourceLoader.getImage, this.imageResources).toTile());
bmp4.position = new Vector(30, 221);
bmp4.extent = new Vector(122, 44);
this.addChild(bmp4);
var bmp5 = new GuiImage(ResourceLoader.getResource("data/ui/achiev/nonachiev.png", ResourceLoader.getImage, this.imageResources).toTile());
bmp5.position = new Vector(36, 274);
bmp5.extent = new Vector(116, 44);
this.addChild(bmp5);
var bmp6 = new GuiImage(ResourceLoader.getResource("data/ui/achiev/nonachiev.png", ResourceLoader.getImage, this.imageResources).toTile());
bmp6.position = new Vector(37, 327);
bmp6.extent = new Vector(115, 44);
this.addChild(bmp6);
var bmp7 = new GuiImage(ResourceLoader.getResource("data/ui/achiev/nonachiev.png", ResourceLoader.getImage, this.imageResources).toTile());
bmp7.position = new Vector(38, 380);
bmp7.extent = new Vector(114, 44);
this.addChild(bmp7);
var bmp8 = new GuiImage(ResourceLoader.getResource("data/ui/achiev/nonachiev.png", ResourceLoader.getImage, this.imageResources).toTile());
bmp8.position = new Vector(39, 433);
bmp8.extent = new Vector(113, 44);
this.addChild(bmp8);
var closeButton = new GuiButton(loadButtonImages("data/ui/achiev/close"));
closeButton.position = new Vector(355, 426);
closeButton.extent = new Vector(95, 45);
closeButton.pressedAction = (e) -> {
MarbleGame.canvas.popDialog(this);
}
this.addChild(closeButton);
var nextButton = new GuiXboxButton("Details", 160);
nextButton.position = new Vector(960, 0);
nextButton.vertSizing = Bottom;
nextButton.horizSizing = Right;
nextButton.pressedAction = (e) -> {
var desc = "Select an achievement from the list.";
var selection = curSelection;
switch (selection) {
case 0: desc = "Finish any level under par time.";
case 1: desc = "Complete all Beginner levels.";
case 2: desc = "Complete all Intermediate levels.";
case 3: desc = "Complete all Advanced levels.";
case 4: desc = "Finish all Beginner levels under par time.";
case 5: desc = "Finish all Intermediate levels under par time.";
case 6: desc = "Finish all Advanced levels under par time.";
case 7: desc = "Find any hidden easter egg.";
case 8: desc = "Find all twenty easter eggs.";
case 9: desc = "Get first place in a multiplayer match.";
case 10: desc = "Get 75 points in a multiplayer match.";
case 11: desc = "Collect 2,000 total points in multiplayer.";
case 12: desc = "Complete all Bonus levels.";
case 13: desc = "Finish all Bonus levels under par time.";
}
MarbleGame.canvas.pushDialog(new MessageBoxOkDlg(desc));
};
bottomBar.addChild(nextButton);
}
public static function check() {
// Now do the actual achievement check logic
var completions:Map<String, Array<{
mission:Mission,
beatPar:Bool,
beatPlatinum:Bool,
beatUltimate:Bool,
beaten:Bool
}>> = [];
var totalPlatinums = 0;
var totalUltimates = 0;
var totalEggs = 0;
var totalPars = 0;
for (difficulty => missions in MissionList.missionList["platinum"]) {
var notifies = 0;
for (difficulty => missions in MissionList.missionList["ultra"]) {
completions.set(difficulty, missions.map(mis -> {
var misScores = Settings.getScores(mis.path);
if (misScores.length == 0) {
return {
mission: mis,
beatPar: false,
beatPlatinum: false,
beatUltimate: false,
beaten: false
}
}
var bestTime = misScores[0];
var beatPar = bestTime.time < mis.qualifyTime;
var beatPlatinum = bestTime.time < mis.goldTime;
var beatUltimate = bestTime.time < mis.ultimateTime;
var beaten = beatPar || beatPlatinum || beatUltimate;
if (beatPar)
totalPars++;
var beaten = true;
if (beatPlatinum)
totalPlatinums++;
if (beatUltimate)
totalUltimates++;
if (Settings.easterEggs.exists(mis.path))
totalEggs++;
return {
mission: mis,
beatPar: beatPar,
beatPlatinum: beatPlatinum,
beatUltimate: beatUltimate,
beaten: beaten
};
}));
}
var beginnerFinishAchiev = completions["beginner"].filter(x -> !x.beatPar).length == 0;
var intermediateFinishAchiev = completions["intermediate"].filter(x -> !x.beatPar).length == 0;
var advancedFinishAchiev = completions["advanced"].filter(x -> !x.beatPar).length == 0;
var expertFinishAchiev = completions["expert"].filter(x -> !x.beatPar).length == 0;
var beatPlatinumAchiev = totalPlatinums == 120;
var beatUltimateAchiev = totalUltimates == 120;
var easterEggAny = totalEggs != 0;
var easterEggAll = totalEggs == 96;
// Timely marble
if (Settings.achievementProgression & 1 != 1) {
if (totalPars > 0) {
Settings.achievementProgression |= 1;
notifies |= 1;
}
}
if (beginnerFinishAchiev)
bmp1.bmp.tile = ResourceLoader.getResource("data/ui/achiev/n1.png", ResourceLoader.getImage, this.imageResources).toTile();
if (intermediateFinishAchiev)
bmp2.bmp.tile = ResourceLoader.getResource("data/ui/achiev/n2.png", ResourceLoader.getImage, this.imageResources).toTile();
if (advancedFinishAchiev)
bmp3.bmp.tile = ResourceLoader.getResource("data/ui/achiev/n3.png", ResourceLoader.getImage, this.imageResources).toTile();
if (expertFinishAchiev)
bmp4.bmp.tile = ResourceLoader.getResource("data/ui/achiev/n4.png", ResourceLoader.getImage, this.imageResources).toTile();
if (beatPlatinumAchiev)
bmp5.bmp.tile = ResourceLoader.getResource("data/ui/achiev/n6.png", ResourceLoader.getImage, this.imageResources).toTile();
if (beatUltimateAchiev)
bmp6.bmp.tile = ResourceLoader.getResource("data/ui/achiev/n5.png", ResourceLoader.getImage, this.imageResources).toTile();
if (easterEggAny)
bmp7.bmp.tile = ResourceLoader.getResource("data/ui/achiev/1.png", ResourceLoader.getImage, this.imageResources).toTile();
if (easterEggAll)
bmp8.bmp.tile = ResourceLoader.getResource("data/ui/achiev/2.png", ResourceLoader.getImage, this.imageResources).toTile();
// All Beginners
if (Settings.achievementProgression & 2 != 2) {
if (completions.get("beginner")
.filter(x -> x.beaten)
.length == completions.get("beginner")
.length) {
Settings.achievementProgression |= 2;
notifies |= 2;
}
}
// All Intermediates
if (Settings.achievementProgression & 4 != 4) {
if (completions.get("intermediate")
.filter(x -> x.beaten)
.length == completions.get("intermediate")
.length) {
Settings.achievementProgression |= 4;
notifies |= 4;
}
}
// All Advanced
if (Settings.achievementProgression & 8 != 8) {
if (completions.get("advanced")
.filter(x -> x.beaten)
.length == completions.get("advanced")
.length) {
Settings.achievementProgression |= 8;
notifies |= 8;
}
}
// All Beginner pars
if (Settings.achievementProgression & 16 != 16) {
if (completions.get("beginner")
.filter(x -> x.beatPar)
.length == completions.get("beginner")
.length) {
Settings.achievementProgression |= 16;
notifies |= 16;
}
}
// All Intermediate pars
if (Settings.achievementProgression & 32 != 32) {
if (completions.get("intermediate")
.filter(x -> x.beatPar)
.length == completions.get("intermediate")
.length) {
Settings.achievementProgression |= 32;
notifies |= 32;
}
}
// All Advanced pars
if (Settings.achievementProgression & 64 != 64) {
if (completions.get("advanced")
.filter(x -> x.beatPar)
.length == completions.get("advanced")
.length) {
Settings.achievementProgression |= 64;
notifies |= 64;
}
}
// Egg Seeker
if (Settings.achievementProgression & 128 != 128) {
if (totalEggs >= 1) {
Settings.achievementProgression |= 128;
notifies |= 128;
}
}
// Egg Basket
if (Settings.achievementProgression & 256 != 256) {
if (totalEggs >= 20) {
Settings.achievementProgression |= 256;
notifies |= 256;
}
}
var showdlgs = [];
for (i in 0...9) {
if (notifies & (1 << i) > 0) {
var popup = new AchievementPopupDlg(i + 1);
showdlgs.push(popup);
}
}
if (showdlgs.length > 1) {
for (i in 0...showdlgs.length - 1) {
showdlgs[i].onFinish = () -> {
MarbleGame.canvas.pushDialog(showdlgs[i + 1]);
}
}
}
if (showdlgs.length != 0)
MarbleGame.canvas.pushDialog(showdlgs[0]); // Start off!
return notifies;
}
override function onResize(width:Int, height:Int) {
var offsetX = (width - 1280) / 2;
var offsetY = (height - 720) / 2;
var subX = 640 - (width - offsetX) * 640 / width;
var subY = 480 - (height - offsetY) * 480 / height;
innerCtrl.position = new Vector(offsetX, offsetY);
innerCtrl.extent = new Vector(640 - subX, 480 - subY);
super.onResize(width, height);
}
}

View file

@ -36,7 +36,8 @@ class Canvas extends GuiControl {
public function pushDialog(content:GuiControl) {
this.addChild(content);
this.render(scene2d);
content.render(scene2d, @:privateAccess this._flow);
// this.render(scene2d);
}
public function popDialog(content:GuiControl, dispose:Bool = true) {

View file

@ -81,7 +81,10 @@ class ExitGameDlg extends GuiImage {
MarbleGame.canvas.pushDialog(new OptionsListGui(true));
}, 20);
btnList.addButton(2, "Leaderboards", (evt) -> {});
btnList.addButton(2, "Achievements", (evt) -> {});
btnList.addButton(2, "Achievements", (evt) -> {
MarbleGame.canvas.popDialog(this);
MarbleGame.canvas.pushDialog(new AchievementsGui(true));
});
btnList.addButton(4, "Main Menu", (evt) -> {
yesFunc(btnList);
MarbleGame.canvas.setContent(new MainMenuGui());

View file

@ -0,0 +1,295 @@
package gui;
import h2d.HtmlText;
import h2d.Flow;
import h3d.Engine;
import h2d.Tile;
import h2d.Bitmap;
import h3d.mat.Texture;
import shaders.GuiClipFilter;
import h2d.Graphics;
import gui.GuiControl.MouseState;
import h2d.Scene;
import h2d.Text;
import h2d.Font;
import src.MarbleGame;
import src.Settings;
class GuiMLTextListCtrl extends GuiControl {
public var texts:Array<String>;
public var onSelectedFunc:Int->Void;
var font:Font;
var textObjs:Array<Text>;
var g:Graphics;
var _prevSelected:Int = -1;
public var selectedColor:Int = 0x206464;
public var selectedFillColor:Int = 0xC8C8C8;
public var textYOffset:Int = 0;
public var scroll:Float = 0;
public var scrollable:Bool = false;
var flow:Flow;
var _imageLoader:String->Tile;
public function new(font:Font, texts:Array<String>, imageLoader:String->Tile) {
super();
this.font = font;
this.texts = texts;
this._manualScroll = true;
this.textObjs = [];
this._imageLoader = imageLoader;
for (text in texts) {
var tobj = new HtmlText(font);
tobj.lineHeightMode = TextOnly;
tobj.loadImage = imageLoader;
tobj.text = text;
tobj.textColor = 0;
textObjs.push(tobj);
}
this.g = new Graphics();
}
public function setTexts(texts:Array<String>) {
var renderRect = this.getRenderRectangle();
for (textObj in this.textObjs) {
textObj.remove();
}
this.textObjs = [];
for (text in texts) {
var tobj = new HtmlText(font);
tobj.loadImage = this._imageLoader;
tobj.lineHeightMode = TextOnly;
tobj.text = text;
tobj.textColor = 0;
textObjs.push(tobj);
if (this.scrollable) {
if (this.flow.contains(tobj))
this.flow.removeChild(tobj);
this.flow.addChild(tobj);
this.flow.getProperties(tobj).isAbsolute = true;
}
}
this.texts = texts;
this._prevSelected = -1;
if (this.onSelectedFunc != null)
this.onSelectedFunc(-1);
redrawSelectionRect(renderRect);
for (i in 0...textObjs.length) {
var text = textObjs[i];
text.setPosition(Math.floor((!scrollable ? renderRect.position.x : 0) + 5),
Math.floor((!scrollable ? renderRect.position.y : 0)
+ (i * (text.font.size + 4 * Settings.uiScale) + (5 + textYOffset) * Settings.uiScale - this.scroll)));
if (_prevSelected == i) {
text.textColor = selectedColor;
}
}
}
public override function render(scene2d:Scene, ?parent:h2d.Flow) {
var renderRect = this.getRenderRectangle();
var htr = this.getHitTestRect(false);
if (parent != null) {
if (parent.contains(g))
parent.removeChild(g);
parent.addChild(g);
var off = this.getOffsetFromParent();
parent.getProperties(g).isAbsolute = true;
g.setPosition(off.x, off.y - this.scroll);
}
if (scrollable) {
this.flow = new Flow();
this.flow.maxWidth = cast htr.extent.x;
this.flow.maxHeight = cast htr.extent.y;
this.flow.multiline = true;
this.flow.layout = Stack;
this.flow.overflow = FlowOverflow.Hidden;
if (parent != null) {
if (parent.contains(this.flow)) {
parent.removeChild(this.flow);
}
parent.addChild(this.flow);
var off = this.getOffsetFromParent();
var props = parent.getProperties(this.flow);
props.isAbsolute = true;
this.flow.setPosition(off.x, off.y);
}
}
for (i in 0...textObjs.length) {
var text = textObjs[i];
if (!scrollable) {
if (scene2d.contains(text))
scene2d.removeChild(text);
scene2d.addChild(text);
} else {
if (this.flow.contains(text))
this.flow.removeChild(text);
this.flow.addChild(text);
this.flow.getProperties(text).isAbsolute = true;
}
text.setPosition(Math.floor((!scrollable ? renderRect.position.x : 0) + 5),
Math.floor((!scrollable ? renderRect.position.y : 0)
+ (i * (text.font.size + 4 * Settings.uiScale) + (5 + textYOffset) * Settings.uiScale - this.scroll)));
if (_prevSelected == i) {
text.textColor = selectedColor;
}
}
redrawSelectionRect(htr);
super.render(scene2d, parent);
}
public function calculateFullHeight() {
return (this.texts.length * (font.size + 4 * Settings.uiScale));
}
public override function dispose() {
super.dispose();
for (text in textObjs) {
text.remove();
}
this.g.remove();
if (this.scrollable) {
this.flow.remove();
}
}
public override function onRemove() {
super.onRemove();
for (text in textObjs) {
if (MarbleGame.canvas.scene2d.contains(text)) {
MarbleGame.canvas.scene2d.removeChild(text); // Refresh "layer"
}
text.remove();
}
if (MarbleGame.canvas.scene2d.contains(g))
MarbleGame.canvas.scene2d.removeChild(g);
g.remove();
}
public override function onMouseMove(mouseState:MouseState) {
var mousePos = mouseState.position;
var renderRect = this.getRenderRectangle();
var yStart = renderRect.position.y;
var dy = mousePos.y - yStart;
var hoverIndex = Math.floor(dy / (font.size + 4 * Settings.uiScale));
if (hoverIndex >= this.texts.length) {
hoverIndex = -1;
}
// Update the texts
for (i in 0...textObjs.length) {
var selected = i == hoverIndex || i == this._prevSelected;
var text = textObjs[i];
text.textColor = selected ? selectedColor : 0;
// fill color = 0xC8C8C8
}
// obviously in renderRect
}
public override function onMouseLeave(mouseState:MouseState) {
for (i in 0...textObjs.length) {
if (i == this._prevSelected)
continue;
var text = textObjs[i];
text.textColor = 0;
// fill color = 0xC8C8C8
}
}
public override function onMousePress(mouseState:MouseState) {
super.onMousePress(mouseState);
var mousePos = mouseState.position;
var renderRect = this.getRenderRectangle();
var yStart = renderRect.position.y;
var dy = mousePos.y - yStart;
var selectedIndex = Math.floor((dy + this.scroll) / (font.size + 4 * Settings.uiScale));
if (selectedIndex >= this.texts.length) {
selectedIndex = -1;
}
if (_prevSelected != selectedIndex) {
_prevSelected = selectedIndex;
redrawSelectionRect(renderRect);
}
if (onSelectedFunc != null) {
onSelectedFunc(selectedIndex);
}
}
function redrawSelectionRect(renderRect:Rect) {
if (_prevSelected != -1) {
g.clear();
g.beginFill(selectedFillColor);
var off = this.getOffsetFromParent();
// Check if we are between the top and bottom, render normally in that case
var topY = 2 * Settings.uiScale + (_prevSelected * (font.size + 4 * Settings.uiScale)) + g.y;
var bottomY = 2 * Settings.uiScale + (_prevSelected * (font.size + 4 * Settings.uiScale)) + g.y + font.size + 4 * Settings.uiScale;
var topRectY = off.y;
var bottomRectY = off.y + renderRect.extent.y;
if (topY >= topRectY && bottomY <= bottomRectY)
g.drawRect(0, 5 * Settings.uiScale
+ (_prevSelected * (font.size + 4 * Settings.uiScale))
- 3 * Settings.uiScale, renderRect.extent.x,
font.size
+ 4 * Settings.uiScale);
// We need to do math the draw the partially visible top selected
if (topY <= topRectY && bottomY >= topRectY) {
g.drawRect(0, this.scroll, renderRect.extent.x, topY + font.size + 4 * Settings.uiScale - off.y);
}
// Same for the bottom
if (topY <= bottomRectY && bottomY >= bottomRectY) {
g.drawRect(0, this.scroll
+ renderRect.extent.y
- font.size
- 4 * Settings.uiScale
+ (topY + font.size + 4 * Settings.uiScale - bottomRectY),
renderRect.extent.x, off.y
+ renderRect.extent.y
- (topY));
}
g.endFill();
} else {
g.clear();
}
}
public override function onScroll(scrollX:Float, scrollY:Float) {
super.onScroll(scrollX, scrollY);
var renderRect = this.getRenderRectangle();
this.scroll = scrollY;
var hittestrect = this.getHitTestRect(false);
for (i in 0...textObjs.length) {
var text = textObjs[i];
text.y = Math.floor((i * (text.font.size + 4 * Settings.uiScale) + (5 + textYOffset) * Settings.uiScale - scrollY));
g.y = -scrollY;
}
redrawSelectionRect(hittestrect);
}
}

View file

@ -64,7 +64,9 @@ class MainMenuGui extends GuiImage {
cast(this.parent, Canvas).setContent(new DifficultySelectGui());
});
btnList.addButton(2, "Leaderboards", (e) -> {}, 20);
btnList.addButton(2, "Achievements", (e) -> {});
btnList.addButton(2, "Achievements", (e) -> {
cast(this.parent, Canvas).setContent(new AchievementsGui());
});
btnList.addButton(3, "Replays", (sender) -> {
#if hl
MarbleGame.canvas.setContent(new ReplayCenterGui());

View file

@ -6,45 +6,37 @@ import h3d.Vector;
import src.ResourceLoader;
import src.Settings;
class MessageBoxOkDlg extends GuiControl {
class MessageBoxOkDlg extends GuiImage {
public function new(text:String) {
super();
var res = ResourceLoader.getImage("data/ui/xbox/roundedBG.png").resource.toTile();
super(res);
this.horizSizing = Width;
this.vertSizing = Height;
this.position = new Vector();
this.extent = new Vector(640, 480);
var domcasual24fontdata = ResourceLoader.getFileEntry("data/font/DomCasualD.fnt");
var domcasual24b = new BitmapFont(domcasual24fontdata.entry);
@:privateAccess domcasual24b.loader = ResourceLoader.loader;
var domcasual24 = domcasual24b.toSdfFont(cast 20 * Settings.uiScale, MultiChannel);
var arial14fontdata = ResourceLoader.getFileEntry("data/font/Arial Bold.fnt");
var arial14b = new BitmapFont(arial14fontdata.entry);
@:privateAccess arial14b.loader = ResourceLoader.loader;
var arial14 = arial14b.toSdfFont(cast 21 * Settings.uiScale, h2d.Font.SDFChannel.MultiChannel);
function loadButtonImages(path:String) {
var normal = ResourceLoader.getResource('${path}_n.png', ResourceLoader.getImage, this.imageResources).toTile();
var hover = ResourceLoader.getResource('${path}_h.png', ResourceLoader.getImage, this.imageResources).toTile();
var pressed = ResourceLoader.getResource('${path}_d.png', ResourceLoader.getImage, this.imageResources).toTile();
return [normal, hover, pressed];
}
var yesNoFrame = new GuiImage(ResourceLoader.getResource("data/ui/common/dialog.png", ResourceLoader.getImage, this.imageResources).toTile());
var yesNoFrame = new GuiImage(ResourceLoader.getResource("data/ui/xbox/popupGUI.png", ResourceLoader.getImage, this.imageResources).toTile());
yesNoFrame.horizSizing = Center;
yesNoFrame.vertSizing = Center;
yesNoFrame.position = new Vector(187, 156);
yesNoFrame.extent = new Vector(300, 161);
yesNoFrame.position = new Vector(70, 30);
yesNoFrame.extent = new Vector(512, 400);
this.addChild(yesNoFrame);
var yesNoText = new GuiMLText(domcasual24, null);
yesNoText.position = new Vector(33, 46);
yesNoText.horizSizing = Center;
yesNoText.extent = new Vector(198, 23);
var yesNoText = new GuiMLText(arial14, null);
yesNoText.position = new Vector(103, 85);
yesNoText.extent = new Vector(313, 186);
yesNoText.text.text = text;
yesNoText.text.textColor = 0;
yesNoText.text.maxWidth = 198;
yesNoText.text.textColor = 0xEBEBEB;
yesNoFrame.addChild(yesNoText);
var okButton = new GuiButton(loadButtonImages("data/ui/common/ok"));
okButton.position = new Vector(117, 85);
okButton.extent = new Vector(88, 41);
var okButton = new GuiXboxButton("Ok", 120);
okButton.position = new Vector(211, 248);
okButton.extent = new Vector(120, 94);
okButton.vertSizing = Top;
okButton.accelerator = hxd.Key.ENTER;
okButton.gamepadAccelerator = ["A"];

View file

@ -15,7 +15,7 @@ class UVRotAnim extends hxsl.Shader {
var vx = v.x * c - v.y * s;
var vy = v.x * s + v.y * c;
calculatedUV += vec2(offset.x + vx, offset.y + vy);
calculatedUV = vec2(offset.x + vx, offset.y + vy);
}
};

View file

@ -1,5 +1,6 @@
package shapes;
import gui.AchievementsGui;
import src.Settings;
import mis.MissionElement.MissionElementItem;
import src.ResourceLoader;
@ -24,6 +25,7 @@ class EasterEgg extends PowerUp {
Settings.easterEggs.set(this.level.mission.path, this.level.timeState.currentAttemptTime);
this.pickupSound = ResourceLoader.getResource("data/sound/easter_egg.wav", ResourceLoader.getAudio, this.soundResources);
this.customPickupMessage = "You found a new egg! Yeah!";
AchievementsGui.check();
} else {
this.pickupSound = ResourceLoader.getResource("data/sound/pu_easter.wav", ResourceLoader.getAudio, this.soundResources);
this.customPickupMessage = "You already found this egg!";

View file

@ -106,7 +106,7 @@ class EndPad extends DtsObject {
material.mainPass.setPassName("glowPre");
material.mainPass.enableLights = false;
var rotshader = new shaders.UVRotAnim(-0.5, -0.5, 1);
var rotshader = new shaders.UVRotAnim(0.5, 0.5, 1);
material.mainPass.addShader(rotshader);
var thisprops:Dynamic = material.getDefaultProps();

View file

@ -96,7 +96,7 @@ class StartPad extends DtsObject {
material.props = thisprops;
material.shadows = false;
material.receiveShadows = true;
var rotshader = new shaders.UVRotAnim(-0.5, -0.5, 1);
var rotshader = new shaders.UVRotAnim(0.5, 0.5, 1);
material.mainPass.addShader(rotshader);
}
@ -110,7 +110,7 @@ class StartPad extends DtsObject {
material.mainPass.setPassName("glowPre");
material.mainPass.enableLights = false;
var rotshader = new shaders.UVRotAnim(-0.5, -0.5, 1);
var rotshader = new shaders.UVRotAnim(0.5, 0.5, 1);
material.mainPass.addShader(rotshader);
var thisprops:Dynamic = material.getDefaultProps();