Compare commits

...

13 commits

Author SHA1 Message Date
RandomityGuy
e496a5f879 Merge branch 'mbu-android' of https://github.com/RandomityGuy/MBHaxe into mbu-android 2025-06-30 17:46:18 +05:30
RandomityGuy
072d6af956 version update and fix this one bug 2025-06-30 17:46:00 +05:30
RandomityGuy
b766e1002e these fixes 2025-06-28 11:56:19 +05:30
RandomityGuy
3a06cee202 more gamepad fixes 2025-06-23 18:29:18 +05:30
RandomityGuy
d880cdd0ee fix this 2025-06-23 18:25:05 +05:30
RandomityGuy
7f1e57ba4f android fixes 2025-06-21 20:52:13 +05:30
RandomityGuy
6e461a6125 global player leaderboards and update the rating curves locally 2025-06-21 20:47:46 +05:30
RandomityGuy
7d0c0ac096 push gamepad support for textlistctrl 2025-06-21 20:47:41 +05:30
RandomityGuy
bb47690dc0 preserve leaderboards view state on exit
attempt fix case sensitivity issue (web)
add controller bindings ui
2025-06-21 20:47:32 +05:30
RandomityGuy
350f24036d fix these crashes 2025-06-21 20:45:25 +05:30
RandomityGuy
6d286c722d fix this weird replay timer bug and also fix friction_high 2025-06-21 20:45:22 +05:30
RandomityGuy
35f3983dcd make camera curve better 2025-06-21 20:45:18 +05:30
RandomityGuy
7f1b39609f allow emulation of modded controller 2025-06-21 20:41:52 +05:30
100 changed files with 972 additions and 193 deletions

View file

@ -9,7 +9,7 @@ new SimGroup(MissionGroup) {
type = "advanced";
include = "1";
level = "49";
difficulty = "9";
difficulty = "10";
name = $Text::LevelName79;
};
new Sky(Sky) {

View file

@ -4,7 +4,7 @@ new SimGroup(MissionGroup) {
new ScriptObject(MissionInfo) {
artist = "Alex Swanson";
include = "1";
difficulty = "9";
difficulty = "6";
type = "advanced";
time = "120000";
level = "47";

View file

@ -3,7 +3,7 @@ new SimGroup(MissionGroup) {
new ScriptObject(MissionInfo) {
include = "1";
difficulty = "8";
difficulty = "10";
type = "advanced";
time = "180000";
level = "44";

View file

@ -7,7 +7,7 @@ new SimGroup(MissionGroup) {
level = "41";
artist = "Alex Swanson";
include = "1";
difficulty = "8";
difficulty = "7";
desc = "divergence";
name = $Text::LevelName104;
gameType = "SinglePlayer";

View file

@ -7,7 +7,7 @@ new SimGroup(MissionGroup) {
level = "50";
type = "advanced";
name = $Text::LevelName106;
difficulty = "9";
difficulty = "7";
time = "70000";
artist = "Alex Swanson";
};

View file

@ -9,7 +9,7 @@ new SimGroup(MissionGroup) {
level = "56";
include = "1";
artist = "Alex Swanson";
difficulty = "10";
difficulty = "9";
name = $Text::LevelName75;
};
new Sky(Sky) {

View file

@ -2,7 +2,7 @@
new SimGroup(MissionGroup) {
new ScriptObject(MissionInfo) {
difficulty = "9";
difficulty = "7";
type = "advanced";
level = "53";
gameType = "SinglePlayer";

View file

@ -9,7 +9,7 @@ new SimGroup(MissionGroup) {
type = "advanced";
artist = "Alex Swanson";
gameType = "SinglePlayer";
difficulty = "10";
difficulty = "11";
level = "58";
hasEggIndex = "16";
};

View file

@ -8,7 +8,7 @@ new SimGroup(MissionGroup) {
name = $Text::LevelName58;
include = "1";
time = "75000";
difficulty = "10";
difficulty = "9";
type = "advanced";
artist = "Alex Swanson";
hasEggIndex = "20";

View file

@ -18,7 +18,7 @@ new SimGroup(MissionGroup) {
new ScriptObject(MissionInfo) {
artist = "Alex Swanson";
include = "1";
difficulty = "8";
difficulty = "9";
type = "advanced";
time = "70000";
level = "43";

View file

@ -2,7 +2,7 @@
new SimGroup(MissionGroup) {
new ScriptObject(MissionInfo) {
difficulty = "8";
difficulty = "9";
artist = "Alex Swanson";
type = "advanced";
gameType = "SinglePlayer";

View file

@ -6,7 +6,7 @@ new SimGroup(MissionGroup) {
time = "60000";
level = "48";
include = "1";
difficulty = "9";
difficulty = "8";
gameType = "SinglePlayer";
name = $Text::LevelName83;
artist = "Alex Swanson";

View file

@ -7,7 +7,7 @@ new SimGroup(MissionGroup) {
level = "42";
artist = "Alex Swanson";
include = "1";
difficulty = "8";
difficulty = "7";
name = $Text::LevelName59;
gameType = "SinglePlayer";
};

View file

@ -7,7 +7,7 @@ new SimGroup(MissionGroup) {
level = "45";
artist = "Alex Swanson";
include = "1";
difficulty = "8";
difficulty = "7";
name = $Text::LevelName72;
gameType = "SinglePlayer";
};

View file

@ -8,7 +8,7 @@ new SimGroup(MissionGroup) {
include = "1";
type = "advanced";
time = "180000";
difficulty = "9";
difficulty = "10";
level = "52";
name = $Text::LevelName57;
hasEggIndex = "19";

View file

@ -7,7 +7,7 @@ new SimGroup(MissionGroup) {
level = "55";
artist = "Alex Swanson";
include = "1";
difficulty = "10";
difficulty = "8";
name = $Text::LevelName97;
gameType = "SinglePlayer";
};

View file

@ -7,7 +7,7 @@ new SimGroup(MissionGroup) {
time = "105000";
level = "54";
include = "1";
difficulty = "10";
difficulty = "11";
name = $Text::LevelName70;
artist = "Alex Swanson";
hasEggIndex = "18";

View file

@ -4,7 +4,7 @@ new SimGroup(MissionGroup) {
new ScriptObject(MissionInfo) {
type = "beginner";
include = "1";
difficulty = "3";
difficulty = "6";
time = "30000";
level = "14";
name = $Text::LevelName34;

View file

@ -3,7 +3,7 @@ new SimGroup(MissionGroup) {
new ScriptObject(MissionInfo) {
include = "1";
difficulty = "1";
difficulty = "5";
time = "45000";
type = "beginner";
level = "4";

View file

@ -9,7 +9,7 @@ new SimGroup(MissionGroup) {
level = "12";
include = "1";
artist = "Alex Swanson";
difficulty = "2";
difficulty = "5";
desc = "Change gravity to solve this puzzle.";
};
new MissionArea(MissionArea) {

View file

@ -3,7 +3,7 @@ new SimGroup(MissionGroup) {
new ScriptObject(MissionInfo) {
include = "1";
difficulty = "2";
difficulty = "5";
time = "45000";
level = "9";
type = "beginner";

View file

@ -4,7 +4,7 @@ new SimGroup(MissionGroup) {
new ScriptObject(MissionInfo) {
include = "1";
artist = "Alex Swanson";
difficulty = "4";
difficulty = "5";
time = "60000";
type = "beginner";
level = "18";

View file

@ -8,7 +8,7 @@ new SimGroup(MissionGroup) {
level = "8";
time = "100000";
include = "1";
difficulty = "3";
difficulty = "6";
name = $Text::LevelName9;
artist = "Alex Swanson";
};

View file

@ -3,7 +3,7 @@ new SimGroup(MissionGroup) {
new ScriptObject(MissionInfo) {
include = "1";
difficulty = "3";
difficulty = "6";
time = "20000";
level = "19";
type = "Beginner";

View file

@ -7,7 +7,7 @@ new SimGroup(MissionGroup) {
type = "Beginner";
name = $Text::LevelName7;
time = "45000";
difficulty = "2";
difficulty = "5";
include = "1";
gameType = "SinglePlayer";
artist = "Alex Swanson";

View file

@ -3,7 +3,7 @@ new SimGroup(MissionGroup) {
new ScriptObject(MissionInfo) {
include = "1";
difficulty = "2";
difficulty = "4";
time = "45000";
type = "beginner";
level = "6";

View file

@ -11,7 +11,7 @@ new SimGroup(MissionGroup) {
level = "1";
artist = "Alex Swanson";
name = $Text::LevelName1;
difficulty = "1";
difficulty = "4";
hasEggIndex = "1";
goldTime = "7000";
proTime = "16000";

View file

@ -3,7 +3,7 @@ new SimGroup(MissionGroup) {
new ScriptObject(MissionInfo) {
include = "1";
difficulty = "1";
difficulty = "4";
time = "45000";
isInDemoMode = "1";
type = "beginner";

View file

@ -3,7 +3,7 @@ new SimGroup(MissionGroup) {
new ScriptObject(MissionInfo) {
include = "1";
difficulty = "1";
difficulty = "4";
time = "70000";
isInDemoMode = "1";
level = "3";

View file

@ -4,7 +4,7 @@ new SimGroup(MissionGroup) {
new ScriptObject(MissionInfo) {
include = "1";
artist = "Alex Swanson";
difficulty = "1";
difficulty = "3";
time = "45000";
type = "beginner";
level = "2";

View file

@ -2,7 +2,7 @@
new SimGroup(MissionGroup) {
new ScriptObject(MissionInfo) {
difficulty = "2";
difficulty = "5";
type = "beginner";
level = "10";
isInDemoMode = "1";

View file

@ -7,7 +7,7 @@ new SimGroup(MissionGroup) {
desc = "Be careful crossing these bridges.";
level = "11";
time = "60000";
difficulty = "2";
difficulty = "5";
name = $Text::LevelName21;
gameType = "SinglePlayer";
include = true;

View file

@ -7,7 +7,7 @@ new SimGroup(MissionGroup) {
level = "13";
name = $Text::LevelName22;
time = "60000";
difficulty = "3";
difficulty = "5";
gameType = "SinglePlayer";
artist = "Alex Swanson";
desc = "Practice with moving platforms.";

View file

@ -10,7 +10,7 @@ new SimGroup(MissionGroup) {
artist = "Alex Swanson";
include = "1";
name = $Text::LevelName28;
difficulty = "3";
difficulty = "6";
hasEggIndex = "4";
};
new MissionArea(MissionArea) {

View file

@ -3,7 +3,7 @@ new SimGroup(MissionGroup) {
new ScriptObject(MissionInfo) {
include = "1";
difficulty = "3";
difficulty = "6";
artist = "Kevin Ryan & Tim Aste";
type = "beginner";
time = "90000";

View file

@ -9,7 +9,7 @@ new SimGroup(MissionGroup) {
artist = "Alex Swanson";
type = "beginner";
level = "20";
difficulty = "4";
difficulty = "6";
name = $Text::LevelName48;
hasEggIndex = "5";
};

View file

@ -6,7 +6,7 @@ new SimGroup(MissionGroup) {
level = "15";
name = $Text::LevelName23;
time = "80000";
difficulty = "3";
difficulty = "5";
gameType = "SinglePlayer";
artist = "Alex Swanson";
desc = "Follow the path and fly to the goal.";

View file

@ -4,7 +4,7 @@ new SimGroup(MissionGroup) {
new ScriptObject(MissionInfo) {
gameType = "SinglePlayer";
include = "1";
difficulty = "5";
difficulty = "7";
type = "Intermediate";
artist = "Kevin Ryan and Tim Aste";
time = "30000";

View file

@ -4,7 +4,7 @@ new SimGroup(MissionGroup) {
gameType = "SinglePlayer";
desc = "Gather all the gems around the globe in less than 30 seconds.";
include = "1";
difficulty = "4";
difficulty = "7";
type = "Intermediate";
artist = "Kevin Ryan";
time = "30000";

View file

@ -5,7 +5,7 @@ new SimGroup(MissionGroup) {
type = "Intermediate";
include = "1";
level = "35";
difficulty = "6";
difficulty = "8";
name = $Text::LevelName103;
desc = "Black Diamond";
gameType = "SinglePlayer";

View file

@ -5,7 +5,7 @@ new SimGroup(MissionGroup) {
level = "27";
name = $Text::LevelName86;
time = "30000";
difficulty = "4";
difficulty = "6";
gameType = "SinglePlayer";
artist = "Alex Swanson";
type = "intermediate";

View file

@ -4,7 +4,7 @@ new SimGroup(MissionGroup) {
new ScriptObject(MissionInfo) {
time = "120000";
include = "1";
difficulty = "5";
difficulty = "7";
type = "Intermediate";
level = "23";
artist = "Alex Swanson";

View file

@ -7,7 +7,7 @@ new SimGroup(MissionGroup) {
include = "1";
time = "60000";
artist = "Alex Swanson";
difficulty = "7";
difficulty = "6";
type = "Intermediate";
level = "39";
name = $Text::LevelName36;

View file

@ -3,7 +3,7 @@ new SimGroup(MissionGroup) {
new ScriptObject(MissionInfo) {
time = "50000";
include = "1";
difficulty = "4";
difficulty = "7";
type = "Intermediate";
level = "21";
isInDemoMode = "1";

View file

@ -9,7 +9,7 @@ new SimGroup(MissionGroup) {
gameType = "SinglePlayer";
time = "50000";
include = "1";
difficulty = "5";
difficulty = "6";
artist = "Alex Swanson";
};
new MissionArea(MissionArea) {

View file

@ -48,7 +48,7 @@ new SimGroup(MissionGroup) {
artist = "Alex Swanson";
include = "1";
name = $Text::LevelName101;
difficulty = "5";
difficulty = "7";
isInDemoMode = "1";
};
new MissionArea(MissionArea) {

View file

@ -2,7 +2,7 @@
new SimGroup(MissionGroup) {
new ScriptObject(MissionInfo) {
difficulty = "7";
difficulty = "6";
type = "Intermediate";
level = "36";
desc = "Careful, its slippery!";

View file

@ -6,7 +6,7 @@ new SimGroup(MissionGroup) {
level = "33";
name = $Text::LevelName37;
time = "120000";
difficulty = "6";
difficulty = "7";
gameType = "SinglePlayer";
artist = "Kevin Ryan";
desc = "Find the gems in the maze of roads!";

View file

@ -6,7 +6,7 @@ new SimGroup(MissionGroup) {
level = "22";
name = $Text::LevelName107;
time = "120000";
difficulty = "4";
difficulty = "8";
gameType = "SinglePlayer";
desc = "Its a jungle out there!";
type = "Intermediate";

View file

@ -6,7 +6,7 @@ new SimGroup(MissionGroup) {
include = "1";
artist = "Alex Swanson";
level = "38";
difficulty = "7";
difficulty = "6";
startHelpTest = "Climb to the top!";
desc = "Climb to the top!";
name = $Text::LevelName80;

View file

@ -4,7 +4,7 @@ new SimGroup(MissionGroup) {
new ScriptObject(MissionInfo) {
type = "intermediate";
include = "1";
difficulty = "6";
difficulty = "8";
level = "37";
time = "120000";
name = $Text::LevelName73;

View file

@ -12,7 +12,7 @@ new SimGroup(MissionGroup) {
type = "advanced";
gameMode = "Scrum";
name = $Text::LevelNameMP21;
difficulty = "8";
difficulty = "9";
numgems = "1";
goldTime = "0";
guid = "{3DCFC6EE-A2DE-465F-B040-6FC31D5C0B6E}";

View file

@ -11,7 +11,7 @@ new SimGroup(MissionGroup) {
type = "beginner";
gameMode = "Scrum";
name = $Text::LevelNameMP18;
difficulty = "4";
difficulty = "6";
gemGroupRadius = "25";
goldTime = "0";
numgems = "1";

View file

@ -4,7 +4,7 @@ new SimGroup(MissionGroup) {
new ScriptObject(MissionInfo) {
gameMode = "Scrum";
level = "84";
difficulty = "9";
difficulty = "7";
maxGemsPerGroup = "6";
time = "300000";
type = "intermediate";

View file

@ -64,6 +64,8 @@ class CameraController extends Object {
var _ignoreCursor:Bool = false;
var wasLastGamepadInput:Bool = false;
public function new(marble:Marble) {
super();
this.marble = marble;
@ -141,6 +143,11 @@ class CameraController extends Object {
// CameraPitch += deltaposY * factor;
// CameraYaw += deltaposX * factor;
if (!isTouch)
wasLastGamepadInput = false;
else
wasLastGamepadInput = true;
nextCameraPitch = CameraPitch + deltaposY * factor;
nextCameraYaw = CameraYaw + deltaposX * factor;
@ -176,7 +183,7 @@ class CameraController extends Object {
}
function applyNonlinearScale(value:Float) {
return Math.pow(Math.abs(value), 3.2) * (value >= 0 ? 1 : -1);
return Math.pow(Math.abs(value), 1.6) * (value >= 0 ? 1 : -1);
}
public function startCenterCamera() {
@ -206,8 +213,12 @@ class CameraController extends Object {
var lerpt = Math.pow(0.5, dt / 0.032); // Math.min(1, 1 - Math.pow(0.6, dt / 0.032)); // hxd.Math.min(1, 1 - Math.pow(0.6, dt * 600));
var gamepadX = applyNonlinearScale(rescaleDeadZone(Gamepad.getAxis(Settings.gamepadSettings.cameraXAxis), 0.25));
var gamepadY = applyNonlinearScale(rescaleDeadZone(Gamepad.getAxis(Settings.gamepadSettings.cameraYAxis), 0.25));
var gamepadX = applyNonlinearScale(rescaleDeadZone(Gamepad.getAxis(Settings.gamepadSettings.cameraXAxis), Settings.gamepadSettings.axisDeadzone));
var gamepadY = rescaleDeadZone(Gamepad.getAxis(Settings.gamepadSettings.cameraYAxis), Settings.gamepadSettings.axisDeadzone);
if (gamepadX != 0.0 || gamepadY != 0.0) {
wasLastGamepadInput = true;
}
var cameraPitchDelta = (Key.isDown(Settings.controlsSettings.camBackward) ? 1 : 0)
- (Key.isDown(Settings.controlsSettings.camForward) ? 1 : 0)
@ -223,8 +234,13 @@ class CameraController extends Object {
cameraPitchDelta = 0;
}
var deltaX = 0.75 * 5 * cameraYawDelta * dt * Settings.gamepadSettings.cameraSensitivity;
var deltaY = 0.75 * 5 * cameraPitchDelta * dt * Settings.gamepadSettings.cameraSensitivity;
var gamePadSensitivity = 1.0;
if (wasLastGamepadInput) {
gamePadSensitivity = (1.6 - Settings.controlsSettings.cameraSensitivity); // It defaults to 0.6
}
var deltaX = 0.75 * 5 * cameraYawDelta * dt * gamePadSensitivity;
var deltaY = 0.75 * 5 * cameraPitchDelta * dt * gamePadSensitivity;
var deltaNew = deltaX;

View file

@ -118,7 +118,11 @@ class DifBuilder {
restitution: 0.5
},
"friction_high" => {
friction: 1.5,
friction: 4.5,
restitution: 0.5
},
"friction_high_shadow" => {
friction: 4.5,
restitution: 0.5
},
"friction_ramp_yellow" => {
@ -210,10 +214,6 @@ class DifBuilder {
friction: 6,
restitution: 0.3
},
"friction_high_shadow" => {
friction: 6,
restitution: 0.3
},
"friction_bouncy" => {
friction: 0.2,
restitution: 2.0,

View file

@ -12,6 +12,13 @@ typedef LBScore = {
score:Float,
platform:Int,
rewind:Int,
rating:Int,
}
typedef LBPlayer = {
uid:String,
name:String,
rating:Int,
}
enum abstract LeaderboardsKind(Int) {
@ -59,6 +66,17 @@ class Leaderboards {
});
}
public static function getTopPlayers(kind:LeaderboardsKind, cb:Array<LBPlayer>->Void) {
return Http.get('${host}/api/players?&game=${game}&view=${kind}', (b) -> {
var s = b.toString();
var players:Array<LBPlayer> = Json.parse(s).players;
cb(players);
}, (e) -> {
Console.log("Failed to get players: " + e);
cb([]);
});
}
public static function submitReplay(ref:Int, replay:haxe.io.Bytes) {
return Http.uploadFile('${host}/api/record?ref=${ref}', replay, (b) -> {
Console.log("Replay submitted");

View file

@ -382,6 +382,7 @@ class Marble extends GameObject {
this.lastRenderPos = new Vector();
this.netSmoothOffset = new Vector();
this.netCorrected = false;
this.lastContactNormal = new Vector(0, 0, 1);
var marbleDts = new DtsObject();
var marbleShader = "";
@ -2147,6 +2148,25 @@ class Marble extends GameObject {
move.d = new Vector();
move.d.x = Gamepad.getAxis(Settings.gamepadSettings.moveYAxis);
move.d.y = -Gamepad.getAxis(Settings.gamepadSettings.moveXAxis);
if (Settings.controlsSettings.moddedController) {
// we need to scale the moves to square instead of circle
var moveLen = Math.sqrt(move.d.x * move.d.x + move.d.y * move.d.y);
if (moveLen > 0.00001) {
// Normalize the vector
var normalizedX = move.d.x / moveLen;
var normalizedY = move.d.y / moveLen;
// Scale to square - this allows diagonal movements to reach the corners
var scaleFactor = Math.max(Math.abs(normalizedX), Math.abs(normalizedY));
if (scaleFactor > 0) {
// Apply square mapping while preserving the original magnitude
move.d.x = normalizedX / scaleFactor * moveLen;
move.d.y = normalizedY / scaleFactor * moveLen;
}
}
}
if (@:privateAccess !MarbleGame.instance.world.playGui.isChatFocused()) {
if (Key.isDown(Settings.controlsSettings.forward)) {
move.d.x -= 1;

View file

@ -42,7 +42,7 @@ class MarbleGame {
static var canvas:Canvas;
static var instance:MarbleGame;
static var currentVersion = "1.2.2";
static var currentVersion = "1.2.3";
var world:MarbleWorld;
var previewWorld:PreviewWorld;

View file

@ -52,6 +52,7 @@ class ReplayFrame {
var t = (time - this.time) / (next.time - this.time);
var dt = time - this.time;
var clockDt = next.clockTime - this.clockTime;
var interpFrame = new ReplayFrame();
@ -59,18 +60,20 @@ class ReplayFrame {
interpFrame.time = time;
interpFrame.bonusTime = this.bonusTime;
interpFrame.clockTime = this.clockTime;
if (interpFrame.bonusTime != 0 && time >= 3.5) {
if (dt <= this.bonusTime) {
interpFrame.bonusTime -= dt;
if (clockDt > 0) {
if (interpFrame.bonusTime != 0 && time >= 3.5) {
if (dt <= this.bonusTime) {
interpFrame.bonusTime -= dt;
} else {
interpFrame.clockTime += dt - this.bonusTime;
interpFrame.bonusTime = 0;
}
} else {
interpFrame.clockTime += dt - this.bonusTime;
interpFrame.bonusTime = 0;
}
} else {
if (this.time >= 3.5)
interpFrame.clockTime += dt;
else if (this.time + dt >= 3.5) {
interpFrame.clockTime += (this.time + dt) - 3.5;
if (this.time >= 3.5)
interpFrame.clockTime += dt;
else if (this.time + dt >= 3.5) {
interpFrame.clockTime += (this.time + dt) - 3.5;
}
}
}

View file

@ -51,6 +51,7 @@ typedef OptionsSettings = {
var maxPixelRatio:Float;
var huntRandom:Bool;
var fastLoad:Bool;
var currentView:Int;
}
typedef ControlsSettings = {
@ -72,6 +73,7 @@ typedef ControlsSettings = {
var blast:Int;
var rewind:Int;
var chat:Int;
var moddedController:Bool;
}
typedef TouchSettings = {
@ -105,6 +107,10 @@ typedef GamepadSettings = {
var respawn:Array<String>;
var blast:Array<String>;
var rewind:Array<String>;
var ok:String;
var back:String;
var alt1:String;
var alt2:String;
}
typedef PlayStatistics = {
@ -143,7 +149,8 @@ class Settings {
maxPixelRatio: 1,
vsync: false,
huntRandom: false,
fastLoad: false
fastLoad: false,
currentView: 0
};
public static var controlsSettings:ControlsSettings = {
@ -164,7 +171,8 @@ class Settings {
respawn: Key.BACKSPACE,
blast: Key.MOUSE_RIGHT,
rewind: Key.R,
chat: Key.T
chat: Key.T,
moddedController: false
};
public static var touchSettings:TouchSettings = {
@ -198,6 +206,10 @@ class Settings {
respawn: ["back"],
blast: ["X", "LB", "RB"],
rewind: ["Y"],
ok: "A",
back: "B",
alt1: "X",
alt2: "Y"
}
public static var playStatistics:PlayStatistics = {
@ -416,6 +428,8 @@ class Settings {
controlsSettings.huntRandom = false;
if (controlsSettings.fastLoad == null)
controlsSettings.fastLoad = false;
if (optionsSettings.currentView == null)
optionsSettings.currentView = 0;
#end
if (optionsSettings.maxPixelRatio == 0 #if js || optionsSettings.maxPixelRatio == null #end)
optionsSettings.maxPixelRatio = 1;
@ -463,6 +477,18 @@ class Settings {
if (gamepadSettings.rewind == null) {
gamepadSettings.rewind = ["Y"];
}
if (gamepadSettings.ok == null) {
gamepadSettings.ok = "A";
}
if (gamepadSettings.back == null) {
gamepadSettings.back = "B";
}
if (gamepadSettings.alt1 == null) {
gamepadSettings.alt1 = "X";
}
if (gamepadSettings.alt2 == null) {
gamepadSettings.alt2 = "Y";
}
if (optionsSettings.rewindTimescale == 0)
optionsSettings.rewindTimescale = 1;
if (json.stats != null) {
@ -500,6 +526,9 @@ class Settings {
if (controlsSettings.chat == null) {
controlsSettings.chat = Key.T;
}
if (controlsSettings.moddedController == null) {
controlsSettings.moddedController = false;
}
if (optionsSettings.rewindEnabled == null) {
optionsSettings.rewindEnabled = false;
}

View file

@ -140,6 +140,16 @@ class ManifestEntry extends FileEntry {
bytes = Bytes.ofData(buf);
if (onReady != null)
onReady();
}).catchError((e) -> {
// Try the original file path
js.Browser.window.fetch('data/' + originalFile).then((res:js.html.Response) -> {
return res.arrayBuffer();
}).then((buf:js.lib.ArrayBuffer) -> {
loaded = true;
bytes = Bytes.ofData(buf);
if (onReady != null)
onReady();
});
});
}
#else

View file

@ -108,7 +108,7 @@ class AboutMenuOptionsGui extends GuiImage {
backButton.position = new Vector(400, 0);
backButton.vertSizing = Bottom;
backButton.horizSizing = Right;
backButton.gamepadAccelerator = ["B"];
backButton.gamepadAccelerator = [Settings.gamepadSettings.back];
backButton.accelerators = [Key.ESCAPE, Key.BACKSPACE];
if (pauseGui)
backButton.pressedAction = (e) -> {

View file

@ -138,7 +138,7 @@ class AchievementsGui extends GuiImage {
backButton.position = new Vector(400, 0);
backButton.vertSizing = Bottom;
backButton.horizSizing = Right;
backButton.gamepadAccelerator = ["B"];
backButton.gamepadAccelerator = [Settings.gamepadSettings.back];
backButton.accelerators = [hxd.Key.ESCAPE, hxd.Key.BACKSPACE];
if (isPause)
backButton.pressedAction = (e) -> {
@ -154,7 +154,7 @@ class AchievementsGui extends GuiImage {
nextButton.vertSizing = Bottom;
nextButton.horizSizing = Right;
nextButton.accelerators = [hxd.Key.ENTER];
nextButton.gamepadAccelerator = ["X"];
nextButton.gamepadAccelerator = [Settings.gamepadSettings.alt1];
nextButton.pressedAction = (e) -> {
var desc = "Select an achievement from the list.";
var selection = curSelection;

View file

@ -0,0 +1,272 @@
package gui;
import src.Gamepad;
import gui.GuiControl.MouseState;
import hxd.Key;
import src.MarbleGame;
import hxd.res.BitmapFont;
import h3d.Vector;
import src.ResourceLoader;
import src.Settings;
import src.Util;
class ControllerBindingsGui extends GuiImage {
var innerCtrl:GuiControl;
var btnListLeft:GuiXboxList;
var btnListRight:GuiXboxList;
var selectedColumn = 0;
var _prevMousePosition:Vector;
public function new(pauseGui:Bool = false) {
var res = ResourceLoader.getImage("data/ui/xbox/BG_fadeOutSoftEdge.png").resource.toTile();
super(res);
var domcasual32fontdata = ResourceLoader.getFileEntry("data/font/DomCasualD.fnt");
var domcasual32b = new BitmapFont(domcasual32fontdata.entry);
@:privateAccess domcasual32b.loader = ResourceLoader.loader;
var domcasual32 = domcasual32b.toSdfFont(cast 42 * Settings.uiScale, MultiChannel);
this.horizSizing = Width;
this.vertSizing = Height;
this.position = new Vector();
this.extent = new Vector(640, 480);
function getConflictingBinding(bindingName:String, key:String) {
// For menu bindings, it's independent of the game stuff
if (["Menu OK", "Menu Back", "Menu Alt 1", "Menu Alt 2"].indexOf(bindingName) != -1) {
if (Settings.gamepadSettings.ok == key && bindingName != "Menu OK")
return "Menu OK";
if (Settings.gamepadSettings.back == key && bindingName != "Menu Back")
return "Menu Back";
if (Settings.gamepadSettings.alt1 == key && bindingName != "Menu Alt 1")
return "Menu Alt 1";
if (Settings.gamepadSettings.alt2 == key && bindingName != "Menu Alt 2")
return "Menu Alt 2";
} else {
if (Settings.gamepadSettings.jump[0] == key && bindingName != "Jump")
return "Jump";
if (Settings.gamepadSettings.jump[1] == key && bindingName != "Jump")
return "Jump";
if (Settings.gamepadSettings.blast[0] == key && bindingName != "Blast")
return "Blast";
if (Settings.gamepadSettings.blast[1] == key && bindingName != "Blast")
return "Blast";
if (Settings.gamepadSettings.powerup[0] == key && bindingName != "Use Powerup")
return "Use Powerup";
if (Settings.gamepadSettings.powerup[1] == key && bindingName != "Use Powerup")
return "Use Powerup";
if (Settings.gamepadSettings.rewind[0] == key && bindingName != "Rewind")
return "Rewind";
if (Settings.gamepadSettings.rewind[1] == key && bindingName != "Rewind")
return "Rewind";
}
return null;
}
function remapFunc(bindingName:String, bindingFunc:String->Void, ctrl:GuiXboxListButton) {
var remapDlg = new RemapDlg(bindingName, true);
MarbleGame.canvas.pushDialog(remapDlg);
remapDlg.controllerRemapCallback = (key) -> {
MarbleGame.canvas.popDialog(remapDlg);
if (key == "escape")
return;
var conflicting = getConflictingBinding(bindingName, key);
if (conflicting == null) {
ctrl.buttonText.text.text = '${bindingName}: ${key}';
bindingFunc(key);
} else {
var yesNoDlg = new MessageBoxYesNoDlg('"${key}" is already bound to "${conflicting}"!<br/>Do you want to undo this mapping?', () -> {
ctrl.buttonText.text.text = '${bindingName}: ${key}';
bindingFunc(key);
}, () -> {});
MarbleGame.canvas.pushDialog(yesNoDlg);
}
}
}
var scene2d = MarbleGame.instance.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 coliseumfontdata = ResourceLoader.getFileEntry("data/font/ColiseumRR.fnt");
var coliseumb = new BitmapFont(coliseumfontdata.entry);
@:privateAccess coliseumb.loader = ResourceLoader.loader;
var coliseum = coliseumb.toSdfFont(cast 44 * Settings.uiScale, MultiChannel);
var rootTitle = new GuiText(coliseum);
rootTitle.position = new Vector(100, 30);
rootTitle.extent = new Vector(1120, 80);
rootTitle.text.textColor = 0xFFFFFF;
rootTitle.text.text = "CONTROLLER BINDINGS";
rootTitle.text.alpha = 0.5;
innerCtrl.addChild(rootTitle);
btnListLeft = new GuiXboxList();
btnListLeft.position = new Vector(70 - offsetX, 135);
btnListLeft.horizSizing = Left;
btnListLeft.extent = new Vector(502, 500);
btnListLeft.active = false;
innerCtrl.addChild(btnListLeft);
btnListRight = new GuiXboxList();
btnListRight.position = new Vector(-400 - offsetX, 135);
btnListRight.horizSizing = Left;
btnListRight.extent = new Vector(502, 500);
innerCtrl.addChild(btnListRight);
var b1 = btnListRight.addButton(0, 'Menu OK: ${Settings.gamepadSettings.ok}', (e) -> {});
b1.pressedAction = (e) -> {
remapFunc("Menu OK", (key) -> Settings.gamepadSettings.ok = key, b1);
};
var b2 = btnListLeft.addButton(0, 'Menu Back: ${Settings.gamepadSettings.back}', (e) -> {});
b2.pressedAction = (e) -> {
remapFunc("Menu Back", (key) -> Settings.gamepadSettings.back = key, b2);
};
var b3 = btnListRight.addButton(0, 'Menu Alt 1: ${Settings.gamepadSettings.alt1}', (e) -> {});
b3.pressedAction = (e) -> {
remapFunc("Menu Alt 1", (key) -> Settings.gamepadSettings.alt1 = key, b3);
};
var b4 = btnListLeft.addButton(0, 'Menu Alt 2: ${Settings.gamepadSettings.alt2}', (e) -> {});
b4.pressedAction = (e) -> {
remapFunc("Move Right", (key) -> Settings.gamepadSettings.alt2 = key, b4);
}
var b5 = btnListRight.addButton(0, 'Jump: ${Settings.gamepadSettings.jump[0]}', (e) -> {});
b5.pressedAction = (e) -> {
remapFunc("Jump", (key) -> Settings.gamepadSettings.jump[0] = key, b5);
};
var b5 = btnListLeft.addButton(0, 'Jump: ${Settings.gamepadSettings.jump[1]}', (e) -> {});
b5.pressedAction = (e) -> {
remapFunc("Jump", (key) -> Settings.gamepadSettings.jump[1] = key, b5);
};
var b6 = btnListRight.addButton(0, 'Blast: ${Settings.gamepadSettings.blast[0]}', (e) -> {});
b6.pressedAction = (e) -> {
remapFunc("Blast", (key) -> Settings.gamepadSettings.blast[0] = key, b6);
}
var b6 = btnListLeft.addButton(0, 'Blast: ${Settings.gamepadSettings.blast[1]}', (e) -> {});
b6.pressedAction = (e) -> {
remapFunc("Blast", (key) -> Settings.gamepadSettings.blast[1] = key, b6);
}
var b11 = btnListRight.addButton(0, 'Use Powerup: ${Settings.gamepadSettings.powerup[0]}', (e) -> {});
b11.pressedAction = (e) -> {
remapFunc("Use Powerup", (key) -> Settings.gamepadSettings.powerup[0] = key, b11);
}
var b11 = btnListLeft.addButton(0, 'Use Powerup: ${Settings.gamepadSettings.powerup[1]}', (e) -> {});
b11.pressedAction = (e) -> {
remapFunc("Use Powerup", (key) -> Settings.gamepadSettings.powerup[1] = key, b11);
}
var b12 = btnListRight.addButton(0, 'Rewind: ${Settings.gamepadSettings.rewind[0]}', (e) -> {});
b12.pressedAction = (e) -> {
remapFunc("Rewind", (key) -> Settings.gamepadSettings.rewind[0] = key, b12);
}
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);
var backButton = new GuiXboxButton("Back", 160);
backButton.position = new Vector(400, 0);
backButton.vertSizing = Bottom;
backButton.horizSizing = Right;
backButton.gamepadAccelerator = ["B"];
backButton.accelerators = [hxd.Key.ESCAPE, hxd.Key.BACKSPACE];
if (pauseGui)
backButton.pressedAction = (e) -> {
MarbleGame.canvas.popDialog(this);
MarbleGame.canvas.pushDialog(new InputSelectGui(true));
}
else
backButton.pressedAction = (e) -> MarbleGame.canvas.setContent(new InputSelectGui());
bottomBar.addChild(backButton);
}
override function update(dt:Float, mouseState:MouseState) {
super.update(dt, mouseState);
var prevSelected = selectedColumn;
if (Key.isPressed(Key.RIGHT) || Gamepad.isPressed(["dpadRight"]))
selectedColumn++;
if (Key.isPressed(Key.LEFT) || Gamepad.isPressed(["dpadLeft"]))
selectedColumn++;
if (selectedColumn < 0)
selectedColumn = 1;
if (selectedColumn > 1)
selectedColumn = 0;
if (selectedColumn == 1) {
btnListLeft.active = true;
btnListRight.active = false;
} else {
btnListLeft.active = false;
btnListRight.active = true;
}
if (prevSelected == 0 && selectedColumn == 1) {
btnListLeft.selected = btnListRight.selected;
if (btnListLeft.selected > btnListLeft.buttons.length - 1)
btnListLeft.selected = btnListLeft.buttons.length - 1;
}
if (prevSelected == 1 && selectedColumn == 0) {
btnListRight.selected = btnListLeft.selected;
if (btnListRight.selected > btnListRight.buttons.length - 1)
btnListRight.selected = btnListRight.buttons.length - 1;
}
if (_prevMousePosition == null || !_prevMousePosition.equals(mouseState.position)) {
for (i in 0...btnListLeft.buttons.length) {
var btn = btnListLeft.buttons[i];
var renderRect = btn.getHitTestRect();
renderRect.position = renderRect.position.add(new Vector(24, 20)); // Offset
renderRect.extent.set(439, 53);
if (renderRect.inRect(mouseState.position)) {
selectedColumn = 1;
btnListLeft.selected = i;
btnListLeft.active = true;
btnListRight.active = false;
break;
}
}
for (i in 0...btnListRight.buttons.length) {
var btn = btnListRight.buttons[i];
var renderRect = btn.getHitTestRect();
renderRect.position = renderRect.position.add(new Vector(24, 20)); // Offset
renderRect.extent.set(439, 53);
if (renderRect.inRect(mouseState.position)) {
selectedColumn = 0;
btnListRight.selected = i;
btnListRight.active = true;
btnListLeft.active = false;
break;
}
}
_prevMousePosition = mouseState.position.clone();
}
}
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);
btnListLeft.position = new Vector(70 - offsetX, 135);
btnListLeft.position = new Vector(-400 - offsetX, 135);
super.onResize(width, height);
}
}

View file

@ -103,7 +103,7 @@ class CreateMatchGui extends GuiImage {
backButton.position = new Vector(400, 0);
backButton.vertSizing = Bottom;
backButton.horizSizing = Right;
backButton.gamepadAccelerator = ["B"];
backButton.gamepadAccelerator = [Settings.gamepadSettings.back];
backButton.accelerators = [hxd.Key.ESCAPE, hxd.Key.BACKSPACE];
backButton.pressedAction = (e) -> MarbleGame.canvas.setContent(new MultiplayerGui());
bottomBar.addChild(backButton);
@ -112,7 +112,7 @@ class CreateMatchGui extends GuiImage {
nextButton.position = new Vector(960, 0);
nextButton.vertSizing = Bottom;
nextButton.horizSizing = Right;
nextButton.gamepadAccelerator = ["A"];
nextButton.gamepadAccelerator = [Settings.gamepadSettings.ok];
nextButton.accelerators = [hxd.Key.ENTER];
nextButton.pressedAction = (e) -> {
Net.hostServer('${Settings.highscoreName}\'s Server', maxPlayers, privateSlots, privateGame, () -> {

View file

@ -83,7 +83,7 @@ class DifficultySelectGui extends GuiImage {
backButton.position = new Vector(400, 0);
backButton.vertSizing = Bottom;
backButton.horizSizing = Right;
backButton.gamepadAccelerator = ["B"];
backButton.gamepadAccelerator = [Settings.gamepadSettings.back];
backButton.accelerators = [hxd.Key.ESCAPE, hxd.Key.BACKSPACE];
backButton.pressedAction = (e) -> MarbleGame.canvas.setContent(new MainMenuGui());
bottomBar.addChild(backButton);

View file

@ -118,9 +118,9 @@ class EndGameGui extends GuiImage {
var completionBonus = 1000;
var timeBonus = 0;
if (t < parTime)
timeBonus = Math.floor(parTime / t) * 1000;
timeBonus = Math.floor((parTime / t) * 1000);
else
timeBonus = Math.floor(parTime / t) * 500;
timeBonus = Math.floor((parTime / t) * 500);
return (completionBonus + timeBonus) * difficulty;
}
@ -162,7 +162,7 @@ class EndGameGui extends GuiImage {
retryButton.position = new Vector(400, 0);
retryButton.vertSizing = Bottom;
retryButton.horizSizing = Right;
retryButton.gamepadAccelerator = ["B"];
retryButton.gamepadAccelerator = [Settings.gamepadSettings.back];
retryButton.accelerators = [hxd.Key.ESCAPE, hxd.Key.BACKSPACE];
retryButton.pressedAction = (e) -> {
if (MarbleGame.canvas.children.length == 1)
@ -182,18 +182,19 @@ class EndGameGui extends GuiImage {
nextButton.position = new Vector(960, 0);
nextButton.vertSizing = Bottom;
nextButton.horizSizing = Right;
nextButton.gamepadAccelerator = ["A"];
nextButton.gamepadAccelerator = [Settings.gamepadSettings.ok];
nextButton.accelerators = [hxd.Key.ENTER];
nextButton.pressedAction = (e) -> {
if (MarbleGame.canvas.children.length == 1)
continueFunc(nextButton);
}
bottomBar.addChild(nextButton);
var rewindUsed = MarbleGame.instance.world.rewindUsed;
var submitScore = () -> {
var lbScoreValue = score;
if (scoreType == Score)
lbScoreValue = 1000 - score;
Leaderboards.submitScore(mission.path, lbScoreValue, MarbleGame.instance.world.rewindUsed, (needsReplay, ref) -> {
Leaderboards.submitScore(mission.path, lbScoreValue, rewindUsed, (needsReplay, ref) -> {
if (needsReplay) {
Leaderboards.submitReplay(ref, replayData);
}
@ -210,7 +211,11 @@ class EndGameGui extends GuiImage {
submitScore();
}
} else {
Leaderboards.getScores(mission.path, All, lbscores -> {
Leaderboards.getScores(mission.path, rewindUsed ? Rewind : NoRewind, lbscores -> {
// Score submission criteria
// If it is better than our non-rewind score, or better than the top non-rewind score, and we are non rewind, submit it
// If it is better than our rewind score, or better than the top rewind score, and we are rewind, submit it
var foundScore = false;
var foundLBScore:Float = 0;
for (lb in lbscores) {

View file

@ -73,7 +73,7 @@ class EnterNameDlg extends GuiImage {
okButton.extent = new Vector(120, 94);
okButton.vertSizing = Top;
okButton.accelerators = [hxd.Key.ENTER];
okButton.gamepadAccelerator = ["A"];
okButton.gamepadAccelerator = [Settings.gamepadSettings.ok];
okButton.pressedAction = (sender) -> {
Settings.highscoreName = textInput.text.text.substr(0, 15); // Max 15 pls
Settings.save();
@ -86,7 +86,7 @@ class EnterNameDlg extends GuiImage {
cancelButton.extent = new Vector(120, 94);
cancelButton.vertSizing = Top;
cancelButton.accelerators = [hxd.Key.ENTER];
cancelButton.gamepadAccelerator = ["A"];
cancelButton.gamepadAccelerator = [Settings.gamepadSettings.ok];
cancelButton.pressedAction = (sender) -> {
MarbleGame.canvas.setContent(new MultiplayerGui());
}

View file

@ -63,7 +63,7 @@ class EnterNamePopupDlg extends GuiImage {
okButton.extent = new Vector(120, 94);
okButton.vertSizing = Top;
okButton.accelerators = [hxd.Key.ENTER];
okButton.gamepadAccelerator = ["A"];
okButton.gamepadAccelerator = [Settings.gamepadSettings.ok];
okButton.pressedAction = (sender) -> {
Settings.highscoreName = textInput.text.text.substr(0, 15); // Max 15 pls
Settings.save();

View file

@ -1,5 +1,6 @@
package gui;
import hxd.Key;
import h2d.filter.Filter;
import h2d.HtmlText;
import h2d.Flow;
@ -15,6 +16,7 @@ import h2d.Text;
import h2d.Font;
import src.MarbleGame;
import src.Settings;
import src.Gamepad;
class GuiMLTextListCtrl extends GuiControl {
public var texts:Array<String>;
@ -39,6 +41,8 @@ class GuiMLTextListCtrl extends GuiControl {
var flow:Flow;
var _imageLoader:String->Tile;
var usedGamepad:Bool = false;
public function new(font:Font, texts:Array<String>, imageLoader:String->Tile, ?filter:Filter = null) {
super();
this.font = font;
@ -282,4 +286,51 @@ class GuiMLTextListCtrl extends GuiControl {
}
redrawSelectionRect(hittestrect);
}
public override function update(dt:Float, mouseState:MouseState) {
super.update(dt, mouseState);
var ps = _prevSelected;
if (Key.isPressed(Key.DOWN) || Gamepad.isPressed(["dpadDown"]) || (Gamepad.getAxis('analogY') > 0.75 && !usedGamepad)) {
_prevSelected++;
if (_prevSelected >= this.texts.length) {
_prevSelected = 0;
}
}
if (Key.isPressed(Key.UP) || Gamepad.isPressed(["dpadUp"]) || (Gamepad.getAxis('analogY') < -0.75 && !usedGamepad)) {
_prevSelected--;
if (_prevSelected < 0) {
_prevSelected = this.texts.length - 1;
}
}
if (ps != _prevSelected) {
// check if we need to scroll
var y = 2 * Settings.uiScale + (_prevSelected * (font.size + 4 * Settings.uiScale)) + g.y;
var renderRect = this.getRenderRectangle();
redrawSelectionRect(renderRect);
if (onSelectedFunc != null) {
onSelectedFunc(_prevSelected);
}
var hittestrect = this.getHitTestRect();
if (y < 0) {
// Scroll up
this.scroll = (font.size + 4 * Settings.uiScale) * _prevSelected;
this.onScroll(0, this.scroll);
} else if (y + font.size + 4 * Settings.uiScale > hittestrect.extent.y) {
// Scroll down
this.scroll = (font.size + 4 * Settings.uiScale) * _prevSelected;
this.onScroll(0, this.scroll);
}
}
if (Math.abs(Gamepad.getAxis('analogY')) > 0.75)
usedGamepad = true;
else
usedGamepad = false;
}
}

View file

@ -1,5 +1,7 @@
package gui;
import src.Gamepad;
import hxd.Key;
import h2d.Flow;
import h3d.Engine;
import h2d.Tile;
@ -33,6 +35,8 @@ class GuiTextListCtrl extends GuiControl {
public var scrollable:Bool = false;
var usedGamepad:Bool = false;
var flow:Flow;
public function new(font:Font, texts:Array<String>, textColor:Int = 0) {
@ -270,4 +274,51 @@ class GuiTextListCtrl extends GuiControl {
}
redrawSelectionRect(hittestrect);
}
public override function update(dt:Float, mouseState:MouseState) {
super.update(dt, mouseState);
var ps = _prevSelected;
if (Key.isPressed(Key.DOWN) || Gamepad.isPressed(["dpadDown"]) || (Gamepad.getAxis('analogY') > 0.75 && !usedGamepad)) {
_prevSelected++;
if (_prevSelected >= this.texts.length) {
_prevSelected = 0;
}
}
if (Key.isPressed(Key.UP) || Gamepad.isPressed(["dpadUp"]) || (Gamepad.getAxis('analogY') < -0.75 && !usedGamepad)) {
_prevSelected--;
if (_prevSelected < 0) {
_prevSelected = this.texts.length - 1;
}
}
if (ps != _prevSelected) {
// check if we need to scroll
var y = 2 * Settings.uiScale + (_prevSelected * (font.size + 4 * Settings.uiScale)) + g.y;
var renderRect = this.getRenderRectangle();
redrawSelectionRect(renderRect);
if (onSelectedFunc != null) {
onSelectedFunc(_prevSelected);
}
var hittestrect = this.getHitTestRect();
if (y < 0) {
// Scroll up
this.scroll = (font.size + 4 * Settings.uiScale) * _prevSelected;
this.onScroll(0, this.scroll);
} else if (y + font.size + 4 * Settings.uiScale > hittestrect.extent.y) {
// Scroll down
this.scroll = (font.size + 4 * Settings.uiScale) * _prevSelected;
this.onScroll(0, this.scroll);
}
}
if (Math.abs(Gamepad.getAxis('analogY')) > 0.75)
usedGamepad = true;
else
usedGamepad = false;
}
}

View file

@ -142,7 +142,7 @@ class HelpCreditsGui extends GuiImage {
backButton.position = new Vector(960, 0);
backButton.vertSizing = Bottom;
backButton.horizSizing = Right;
backButton.gamepadAccelerator = ["A"];
backButton.gamepadAccelerator = [Settings.gamepadSettings.ok];
backButton.accelerators = [hxd.Key.ENTER];
if (pauseGui)
if (index == 5)

View file

@ -106,7 +106,7 @@ class InputOptionsGui extends GuiImage {
backButton.position = new Vector(960, 0);
backButton.vertSizing = Bottom;
backButton.horizSizing = Right;
backButton.gamepadAccelerator = ["A"];
backButton.gamepadAccelerator = [Settings.gamepadSettings.ok];
backButton.accelerators = [hxd.Key.ENTER];
if (pauseGui)
backButton.pressedAction = (e) -> {

103
src/gui/InputSelectGui.hx Normal file
View file

@ -0,0 +1,103 @@
package gui;
import h2d.filter.DropShadow;
import src.MarbleGame;
import gui.GuiControl.MouseState;
import hxd.res.BitmapFont;
import h3d.Vector;
import src.ResourceLoader;
import src.Settings;
class InputSelectGui extends GuiImage {
var innerCtrl:GuiControl;
var btnList:GuiXboxList;
public function new(pauseGui:Bool = false) {
var res = ResourceLoader.getImage("data/ui/xbox/BG_fadeOutSoftEdge.png").resource.toTile();
super(res);
var domcasual32fontdata = ResourceLoader.getFileEntry("data/font/DomCasualD.fnt");
var domcasual32b = new BitmapFont(domcasual32fontdata.entry);
@:privateAccess domcasual32b.loader = ResourceLoader.loader;
var domcasual32 = domcasual32b.toSdfFont(cast 42 * Settings.uiScale, MultiChannel);
this.horizSizing = Width;
this.vertSizing = Height;
this.position = new Vector();
this.extent = new Vector(640, 480);
var scene2d = MarbleGame.instance.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 coliseumfontdata = ResourceLoader.getFileEntry("data/font/ColiseumRR.fnt");
var coliseumb = new BitmapFont(coliseumfontdata.entry);
@:privateAccess coliseumb.loader = ResourceLoader.loader;
var coliseum = coliseumb.toSdfFont(cast 44 * Settings.uiScale, MultiChannel);
var rootTitle = new GuiText(coliseum);
rootTitle.position = new Vector(100, 30);
rootTitle.extent = new Vector(1120, 80);
rootTitle.text.textColor = 0xFFFFFF;
rootTitle.text.text = "SELECT CONTROLS";
rootTitle.text.alpha = 0.5;
innerCtrl.addChild(rootTitle);
btnList = new GuiXboxList();
btnList.position = new Vector(70 - offsetX, 165);
btnList.horizSizing = Left;
btnList.extent = new Vector(502, 500);
innerCtrl.addChild(btnList);
btnList.addButton(0, 'Touch Controls', (e) -> {
MarbleGame.canvas.setContent(new TouchOptionsGui(pauseGui));
});
btnList.addButton(0, 'Gamepad Controls', (e) -> {
MarbleGame.canvas.setContent(new ControllerBindingsGui(pauseGui));
});
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);
var backButton = new GuiXboxButton("Back", 160);
backButton.position = new Vector(400, 0);
backButton.vertSizing = Bottom;
backButton.horizSizing = Right;
backButton.gamepadAccelerator = [Settings.gamepadSettings.back];
backButton.accelerators = [hxd.Key.ESCAPE, hxd.Key.BACKSPACE];
if (pauseGui)
backButton.pressedAction = (e) -> {
MarbleGame.canvas.popDialog(this);
MarbleGame.canvas.pushDialog(new OptionsListGui(pauseGui));
}
else
backButton.pressedAction = (e) -> MarbleGame.canvas.setContent(new OptionsListGui(pauseGui));
bottomBar.addChild(backButton);
}
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);
btnList.position = new Vector(70 - offsetX, 165);
super.onResize(width, height);
}
}

View file

@ -191,7 +191,7 @@ class JoinServerGui extends GuiImage {
backButton.position = new Vector(400, 0);
backButton.vertSizing = Bottom;
backButton.horizSizing = Right;
backButton.gamepadAccelerator = ["B"];
backButton.gamepadAccelerator = [Settings.gamepadSettings.back];
backButton.accelerators = [hxd.Key.ESCAPE, hxd.Key.BACKSPACE];
backButton.pressedAction = (e) -> {
MarbleGame.canvas.setContent(new MultiplayerGui());
@ -202,7 +202,7 @@ class JoinServerGui extends GuiImage {
goButton.position = new Vector(960, 0);
goButton.vertSizing = Bottom;
goButton.horizSizing = Right;
goButton.gamepadAccelerator = ["A"];
goButton.gamepadAccelerator = [Settings.gamepadSettings.ok];
goButton.accelerators = [hxd.Key.ENTER];
goButton.pressedAction = (e) -> joinFunc();
bottomBar.addChild(goButton);

View file

@ -192,15 +192,15 @@ class KeyBindingsGui extends GuiImage {
backButton.position = new Vector(400, 0);
backButton.vertSizing = Bottom;
backButton.horizSizing = Right;
backButton.gamepadAccelerator = ["B"];
backButton.gamepadAccelerator = [Settings.gamepadSettings.back];
backButton.accelerators = [hxd.Key.ESCAPE, hxd.Key.BACKSPACE];
if (pauseGui)
backButton.pressedAction = (e) -> {
MarbleGame.canvas.popDialog(this);
MarbleGame.canvas.pushDialog(new OptionsListGui(true));
MarbleGame.canvas.pushDialog(new InputSelectGui(true));
}
else
backButton.pressedAction = (e) -> MarbleGame.canvas.setContent(new OptionsListGui());
backButton.pressedAction = (e) -> MarbleGame.canvas.setContent(new InputSelectGui());
bottomBar.addChild(backButton);
}

View file

@ -17,7 +17,7 @@ import gui.HtmlText;
class LeaderboardsGui extends GuiImage {
var innerCtrl:GuiControl;
public function new(index:Int, levelSelectDifficulty:String, levelSelectGui:Bool = false,) {
public function new(index:Int, levelSelectDifficulty:String, levelSelectGui:Bool = false) {
var res = ResourceLoader.getImage("data/ui/xbox/BG_fadeOutSoftEdge.png").resource.toTile();
super(res);
var domcasual32fontdata = ResourceLoader.getFileEntry("data/font/DomCasualD.fnt");
@ -116,7 +116,8 @@ class LeaderboardsGui extends GuiImage {
return null;
}
var headerText = '<font face="arial12">Rank<offset value="50">Name</offset><offset value="500">Score</offset><offset value="600">Platform</offset></font>';
var headerText = '<font face="arial12">Rank<offset value="50">Name</offset><offset value="400">Score</offset><offset value="500">Rating</offset><offset value="600">Platform</offset></font>';
var playerHeaderText = '<font face="arial12">Rank<offset value="50">Name</offset><offset value="575">Rating</offset></font>';
var scores = [
'<offset value="10">1. </offset><offset value="50">Nardo Polo</offset><offset value="500">99:59:999</offset><offset value="625"><img src="unknown"/></offset>',
@ -145,14 +146,18 @@ class LeaderboardsGui extends GuiImage {
.concat(MissionList.missionList.get('ultra').get('advanced'))
.concat(MissionList.missionList.get('ultra').get('multiplayer'));
var actualIndex = allMissions.indexOf(MissionList.missionList.get('ultra').get(levelSelectDifficulty)[index]);
var actualIndex = levelSelectDifficulty != "players" ? allMissions.indexOf(MissionList.missionList.get('ultra').get(levelSelectDifficulty)[index]) : 0;
levelTitle.text.text = 'Level ${actualIndex + 1}';
var levelNames = allMissions.map(x -> x.title);
var scoreCategories = ["Overall", "Rewind", "Non-Rewind"];
var scoreView:LeaderboardsKind = All;
var scoreView:LeaderboardsKind = cast Settings.optionsSettings.currentView;
if (levelSelectDifficulty == "players") {
levelTitle.text.text = 'Top Players: ${scoreCategories[cast scoreView]}';
}
var currentMission = allMissions[actualIndex];
@ -171,8 +176,9 @@ class LeaderboardsGui extends GuiImage {
for (score in scoreList) {
var scoreText = '<offset value="10">${i}. </offset>
<offset value="50">${score.name}</offset>
<offset value="475">${score.rewind > 0 ? "<img src='rewind'/>" : ""}</offset>
<offset value="500">${isHuntScore ? Std.string(1000 - score.score) : Util.formatTime(score.score)}</offset>
<offset value="375">${score.rewind > 0 ? "<img src='rewind'/>" : ""}</offset>
<offset value="400">${isHuntScore ? Std.string(1000 - score.score) : Util.formatTime(score.score)}</offset>
<offset value="500">${score.rating}</offset>
<offset value="625"><img src="${platformToString(score.platform)}"/></offset>';
scoreTexts.push(scoreText);
i++;
@ -187,6 +193,31 @@ class LeaderboardsGui extends GuiImage {
scoreCtrl.text.text = headerText + "<br/><br/><br/><br/><br/>" + '<p align="center">Loading...</p>';
}
function fetchPlayers() {
var ourToken = scoreTok++;
Leaderboards.getTopPlayers(scoreView, (scoreList) -> {
if (ourToken + 1 != scoreTok)
return;
var scoreTexts = [];
var i = 1;
for (score in scoreList) {
var scoreText = '<offset value="10">${i}. </offset>
<offset value="50">${score.name}</offset>
<offset value="575">${score.rating}</offset>';
scoreTexts.push(scoreText);
i++;
}
while (i <= 10) {
var scoreText = '<offset value="10">${i}. </offset><offset value="475">10000</offset>';
scoreTexts.push(scoreText);
i++;
}
scoreCtrl.text.text = playerHeaderText + "<br/>" + scoreTexts.join('<br/>');
});
scoreCtrl.text.text = playerHeaderText + "<br/><br/><br/><br/><br/>" + '<p align="center">Loading...</p>';
}
var levelSelectOpts = new GuiXboxOptionsList(2, "Overall", levelNames);
levelSelectOpts.position = new Vector(380, 485);
levelSelectOpts.extent = new Vector(815, 94);
@ -194,13 +225,20 @@ class LeaderboardsGui extends GuiImage {
levelSelectOpts.horizSizing = Right;
levelSelectOpts.alwaysActive = true;
levelSelectOpts.onChangeFunc = (l) -> {
if (levelSelectDifficulty == "players") {
fetchPlayers();
levelTitle.text.text = 'Top Players: ${scoreCategories[cast scoreView]}';
return true;
}
levelTitle.text.text = 'Level ${l + 1}';
currentMission = allMissions[l];
fetchScores();
return true;
}
levelSelectOpts.setCurrentOption(actualIndex);
innerCtrl.addChild(levelSelectOpts);
if (levelSelectDifficulty != "players")
innerCtrl.addChild(levelSelectOpts);
var bottomBar = new GuiControl();
bottomBar.position = new Vector(0, 590);
@ -213,12 +251,12 @@ class LeaderboardsGui extends GuiImage {
backButton.position = new Vector(400, 0);
backButton.vertSizing = Bottom;
backButton.horizSizing = Right;
backButton.gamepadAccelerator = ["B"];
backButton.gamepadAccelerator = [Settings.gamepadSettings.back];
backButton.accelerators = [hxd.Key.ESCAPE, hxd.Key.BACKSPACE];
if (levelSelectGui)
backButton.pressedAction = (e) -> MarbleGame.canvas.setContent(new LevelSelectGui(levelSelectDifficulty));
else {
backButton.pressedAction = (e) -> MarbleGame.canvas.setContent(new MainMenuGui());
backButton.pressedAction = (e) -> MarbleGame.canvas.setContent(new LeaderboardsSelectGui());
}
bottomBar.addChild(backButton);
@ -226,51 +264,61 @@ class LeaderboardsGui extends GuiImage {
changeViewButton.position = new Vector(560, 0);
changeViewButton.vertSizing = Bottom;
changeViewButton.horizSizing = Right;
changeViewButton.gamepadAccelerator = ["X"];
changeViewButton.gamepadAccelerator = [Settings.gamepadSettings.alt1];
changeViewButton.pressedAction = (e) -> {
scoreView = scoreView == All ? Rewind : (scoreView == Rewind ? NoRewind : All);
Settings.optionsSettings.currentView = cast scoreView;
levelSelectOpts.labelText.text.text = scoreCategories[cast(scoreView, Int)];
fetchScores();
if (levelSelectDifficulty == "players") {
levelTitle.text.text = 'Top Players: ${scoreCategories[cast scoreView]}';
fetchPlayers();
} else
fetchScores();
}
bottomBar.addChild(changeViewButton);
var replayButton = new GuiXboxButton("Watch Replay", 220);
replayButton.position = new Vector(750, 0);
replayButton.vertSizing = Bottom;
replayButton.gamepadAccelerator = ["Y"];
replayButton.horizSizing = Right;
replayButton.pressedAction = (e) -> {
Leaderboards.watchTopReplay(currentMission.path, scoreView, (b) -> {
if (b != null) {
var replayF = new Replay("");
if (replayF.read(b)) {
var repmis = replayF.mission;
// Strip data/ from the mission name
if (StringTools.startsWith(repmis, "data/")) {
repmis = repmis.substr(5);
if (levelSelectDifficulty != "players") {
var replayButton = new GuiXboxButton("Watch Replay", 220);
replayButton.position = new Vector(750, 0);
replayButton.vertSizing = Bottom;
replayButton.gamepadAccelerator = [Settings.gamepadSettings.alt2];
replayButton.horizSizing = Right;
replayButton.pressedAction = (e) -> {
Leaderboards.watchTopReplay(currentMission.path, scoreView, (b) -> {
if (b != null) {
var replayF = new Replay("");
if (replayF.read(b)) {
var repmis = replayF.mission;
// Strip data/ from the mission name
if (StringTools.startsWith(repmis, "data/")) {
repmis = repmis.substr(5);
}
var mi = MissionList.missions.get(repmis);
// try with data/ added
if (mi == null) {
if (!StringTools.contains(repmis, "data/"))
repmis = "data/" + repmis;
mi = MissionList.missions.get(repmis);
}
MarbleGame.instance.watchMissionReplay(mi, replayF, DifficultySelectGui);
} else {
MarbleGame.canvas.pushDialog(new MessageBoxOkDlg("Could not load replay for this level."));
}
var mi = MissionList.missions.get(repmis);
// try with data/ added
if (mi == null) {
if (!StringTools.contains(repmis, "data/"))
repmis = "data/" + repmis;
mi = MissionList.missions.get(repmis);
}
MarbleGame.instance.watchMissionReplay(mi, replayF, DifficultySelectGui);
} else {
MarbleGame.canvas.pushDialog(new MessageBoxOkDlg("Could not load replay for this level."));
MarbleGame.canvas.pushDialog(new MessageBoxOkDlg("No top replay found for this level."));
}
} else {
MarbleGame.canvas.pushDialog(new MessageBoxOkDlg("No top replay found for this level."));
}
});
});
}
bottomBar.addChild(replayButton);
}
bottomBar.addChild(replayButton);
fetchScores();
if (levelSelectDifficulty == "players") {
fetchPlayers();
} else
fetchScores();
}
override function onResize(width:Int, height:Int) {

View file

@ -0,0 +1,98 @@
package gui;
import h2d.filter.DropShadow;
import src.MarbleGame;
import gui.GuiControl.MouseState;
import hxd.res.BitmapFont;
import h3d.Vector;
import src.ResourceLoader;
import src.Settings;
class LeaderboardsSelectGui extends GuiImage {
var innerCtrl:GuiControl;
var btnList:GuiXboxList;
public function new() {
var res = ResourceLoader.getImage("data/ui/xbox/BG_fadeOutSoftEdge.png").resource.toTile();
super(res);
var domcasual32fontdata = ResourceLoader.getFileEntry("data/font/DomCasualD.fnt");
var domcasual32b = new BitmapFont(domcasual32fontdata.entry);
@:privateAccess domcasual32b.loader = ResourceLoader.loader;
var domcasual32 = domcasual32b.toSdfFont(cast 42 * Settings.uiScale, MultiChannel);
this.horizSizing = Width;
this.vertSizing = Height;
this.position = new Vector();
this.extent = new Vector(640, 480);
var scene2d = MarbleGame.instance.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 coliseumfontdata = ResourceLoader.getFileEntry("data/font/ColiseumRR.fnt");
var coliseumb = new BitmapFont(coliseumfontdata.entry);
@:privateAccess coliseumb.loader = ResourceLoader.loader;
var coliseum = coliseumb.toSdfFont(cast 44 * Settings.uiScale, MultiChannel);
var rootTitle = new GuiText(coliseum);
rootTitle.position = new Vector(100, 30);
rootTitle.extent = new Vector(1120, 80);
rootTitle.text.textColor = 0xFFFFFF;
rootTitle.text.text = "SELECT LEADERBOARDS";
rootTitle.text.alpha = 0.5;
innerCtrl.addChild(rootTitle);
btnList = new GuiXboxList();
btnList.position = new Vector(70 - offsetX, 165);
btnList.horizSizing = Left;
btnList.extent = new Vector(502, 500);
innerCtrl.addChild(btnList);
btnList.addButton(0, 'Level Leaderboards', (e) -> {
MarbleGame.canvas.setContent(new LeaderboardsGui(0, "beginner", false));
});
btnList.addButton(0, 'Player Leaderboards', (e) -> {
MarbleGame.canvas.setContent(new LeaderboardsGui(0, "players", false));
});
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);
var backButton = new GuiXboxButton("Back", 160);
backButton.position = new Vector(400, 0);
backButton.vertSizing = Bottom;
backButton.horizSizing = Right;
backButton.gamepadAccelerator = [Settings.gamepadSettings.back];
backButton.accelerators = [hxd.Key.ESCAPE, hxd.Key.BACKSPACE];
backButton.pressedAction = (e) -> MarbleGame.canvas.setContent(new MainMenuGui());
bottomBar.addChild(backButton);
}
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);
btnList.position = new Vector(70 - offsetX, 165);
super.onResize(width, height);
}
}

View file

@ -139,7 +139,7 @@ class LevelSelectGui extends GuiImage {
backButton.position = new Vector(400, 0);
backButton.vertSizing = Bottom;
backButton.horizSizing = Right;
backButton.gamepadAccelerator = ["B"];
backButton.gamepadAccelerator = [Settings.gamepadSettings.back];
backButton.accelerators = [hxd.Key.ESCAPE, hxd.Key.BACKSPACE];
backButton.pressedAction = (e) -> MarbleGame.canvas.setContent(new DifficultySelectGui());
bottomBar.addChild(backButton);
@ -148,7 +148,7 @@ class LevelSelectGui extends GuiImage {
recordButton.position = new Vector(560, 0);
recordButton.vertSizing = Bottom;
recordButton.horizSizing = Right;
recordButton.gamepadAccelerator = ["X"];
recordButton.gamepadAccelerator = [Settings.gamepadSettings.alt1];
recordButton.pressedAction = (e) -> {
MarbleGame.instance.toRecord = true;
MarbleGame.canvas.pushDialog(new MessageBoxOkDlg("The next mission you play will be recorded."));
@ -159,7 +159,7 @@ class LevelSelectGui extends GuiImage {
var lbButton = new GuiXboxButton("Leaderboard", 220);
lbButton.position = new Vector(750, 0);
lbButton.vertSizing = Bottom;
lbButton.gamepadAccelerator = ["Y"];
lbButton.gamepadAccelerator = [Settings.gamepadSettings.alt2];
lbButton.horizSizing = Right;
lbButton.pressedAction = (e) -> MarbleGame.canvas.setContent(new LeaderboardsGui(currentSelectionStatic, currentDifficultyStatic, true));
bottomBar.addChild(lbButton);
@ -169,7 +169,7 @@ class LevelSelectGui extends GuiImage {
nextButton.position = new Vector(960, 0);
nextButton.vertSizing = Bottom;
nextButton.horizSizing = Right;
nextButton.gamepadAccelerator = ["A"];
nextButton.gamepadAccelerator = [Settings.gamepadSettings.ok];
nextButton.accelerators = [hxd.Key.ENTER];
nextButton.pressedAction = (e) -> {
MarbleGame.instance.playMission(curMission);

View file

@ -135,7 +135,7 @@ class MPServerListGui extends GuiImage {
backButton.position = new Vector(400, 0);
backButton.vertSizing = Bottom;
backButton.horizSizing = Right;
backButton.gamepadAccelerator = ["B"];
backButton.gamepadAccelerator = [Settings.gamepadSettings.back];
backButton.accelerators = [hxd.Key.ESCAPE, hxd.Key.BACKSPACE];
backButton.pressedAction = (e) -> MarbleGame.canvas.setContent(new MainMenuGui());
bottomBar.addChild(backButton);
@ -178,7 +178,7 @@ class MPServerListGui extends GuiImage {
nextButton.vertSizing = Bottom;
nextButton.horizSizing = Right;
nextButton.accelerators = [hxd.Key.ENTER];
nextButton.gamepadAccelerator = ["X"];
nextButton.gamepadAccelerator = [Settings.gamepadSettings.alt1];
nextButton.pressedAction = (e) -> {
if (curSelection != -1) {
var selectedServerVersion = ourServerList[curSelection].version;

View file

@ -80,7 +80,7 @@ class MainMenuGui extends GuiImage {
}
});
btnList.addButton(2, "Leaderboards", (e) -> {
cast(this.parent, Canvas).setContent(new LeaderboardsGui(0, "beginner", false));
cast(this.parent, Canvas).setContent(new LeaderboardsSelectGui());
}, 20);
btnList.addButton(2, "Achievements", (e) -> {
cast(this.parent, Canvas).setContent(new AchievementsGui());

View file

@ -339,7 +339,7 @@ class MarblePickerGui extends GuiImage {
backButton.position = new Vector(960, 0);
backButton.vertSizing = Bottom;
backButton.horizSizing = Right;
backButton.gamepadAccelerator = ["A"];
backButton.gamepadAccelerator = [Settings.gamepadSettings.ok];
backButton.accelerators = [hxd.Key.ENTER];
backButton.pressedAction = (e) -> {
this.bmp.visible = true;

View file

@ -39,7 +39,7 @@ class MessageBoxOkDlg extends GuiImage {
okButton.extent = new Vector(120, 94);
okButton.vertSizing = Top;
okButton.accelerators = [hxd.Key.ENTER];
okButton.gamepadAccelerator = ["A"];
okButton.gamepadAccelerator = [Settings.gamepadSettings.ok];
okButton.pressedAction = (sender) -> {
MarbleGame.canvas.popDialog(this);
}

View file

@ -39,7 +39,7 @@ class MessageBoxYesNoDlg extends GuiImage {
okButton.extent = new Vector(120, 94);
okButton.vertSizing = Top;
okButton.accelerators = [hxd.Key.ENTER];
okButton.gamepadAccelerator = ["A"];
okButton.gamepadAccelerator = [Settings.gamepadSettings.ok];
okButton.pressedAction = (sender) -> {
MarbleGame.canvas.popDialog(this);
yesFunc();
@ -51,7 +51,7 @@ class MessageBoxYesNoDlg extends GuiImage {
cancelButton.extent = new Vector(120, 94);
cancelButton.vertSizing = Top;
cancelButton.accelerators = [hxd.Key.ESCAPE, hxd.Key.BACKSPACE];
cancelButton.gamepadAccelerator = ["B"];
cancelButton.gamepadAccelerator = [Settings.gamepadSettings.back];
cancelButton.pressedAction = (sender) -> {
MarbleGame.canvas.popDialog(this);
noFunc();

View file

@ -91,6 +91,12 @@ class MiscOptionsGui extends GuiImage {
flOpt.setCurrentOption(Settings.optionsSettings.fastLoad ? 1 : 0);
// #end
var moddedOpt = optionCollection.addOption(1, "Emulate Modded Controller", ["No", "Yes"], (idx) -> {
Settings.controlsSettings.moddedController = (idx == 1);
return true;
}, 0.5, 118);
moddedOpt.setCurrentOption(Settings.controlsSettings.moddedController ? 1 : 0);
var bottomBar = new GuiControl();
bottomBar.position = new Vector(0, 590);
bottomBar.extent = new Vector(640, 200);
@ -102,7 +108,7 @@ class MiscOptionsGui extends GuiImage {
backButton.position = new Vector(960, 0);
backButton.vertSizing = Bottom;
backButton.horizSizing = Right;
backButton.gamepadAccelerator = ["A"];
backButton.gamepadAccelerator = [Settings.gamepadSettings.ok];
backButton.accelerators = [hxd.Key.ENTER];
if (pauseGui)
backButton.pressedAction = (e) -> {

View file

@ -103,7 +103,7 @@ class MultiplayerGui extends GuiImage {
backButton.position = new Vector(400, 0);
backButton.vertSizing = Bottom;
backButton.horizSizing = Right;
backButton.gamepadAccelerator = ["B"];
backButton.gamepadAccelerator = [Settings.gamepadSettings.back];
backButton.accelerators = [hxd.Key.ESCAPE, hxd.Key.BACKSPACE];
backButton.pressedAction = (e) -> MarbleGame.canvas.setContent(new MainMenuGui());
bottomBar.addChild(backButton);

View file

@ -266,7 +266,7 @@ class MultiplayerLevelSelectGui extends GuiImage {
backButton.position = new Vector(400, 0);
backButton.vertSizing = Bottom;
backButton.horizSizing = Right;
backButton.gamepadAccelerator = ["B"];
backButton.gamepadAccelerator = [Settings.gamepadSettings.back];
backButton.accelerators = [hxd.Key.ESCAPE, hxd.Key.BACKSPACE];
backButton.pressedAction = (e) -> {
Net.disconnect();
@ -283,7 +283,7 @@ class MultiplayerLevelSelectGui extends GuiImage {
customsButton.position = new Vector(560, 0);
customsButton.vertSizing = Bottom;
customsButton.horizSizing = Right;
customsButton.gamepadAccelerator = ["X"];
customsButton.gamepadAccelerator = [Settings.gamepadSettings.alt1];
customsButton.pressedAction = (e) -> {
showingCustoms = !showingCustoms;
if (showingCustoms) {
@ -302,7 +302,7 @@ class MultiplayerLevelSelectGui extends GuiImage {
inviteButton.position = new Vector(750, 0);
inviteButton.vertSizing = Bottom;
inviteButton.horizSizing = Right;
inviteButton.gamepadAccelerator = ["Y"];
inviteButton.gamepadAccelerator = [Settings.gamepadSettings.alt2];
inviteButton.pressedAction = (e) -> {
inviteVisibility = !inviteVisibility;
updateLobbyNames();
@ -314,7 +314,7 @@ class MultiplayerLevelSelectGui extends GuiImage {
nextButton.position = new Vector(960, 0);
nextButton.vertSizing = Bottom;
nextButton.horizSizing = Right;
nextButton.gamepadAccelerator = ["A"];
nextButton.gamepadAccelerator = [Settings.gamepadSettings.ok];
nextButton.accelerators = [hxd.Key.ENTER];
nextButton.pressedAction = (e) -> {
NetCommands.toggleReadiness(Net.isClient ? Net.clientId : 0);

View file

@ -89,7 +89,7 @@ class MultiplayerLoadingGui extends GuiImage {
backButton.position = new Vector(960, 0);
backButton.vertSizing = Bottom;
backButton.horizSizing = Right;
backButton.gamepadAccelerator = ["A"];
backButton.gamepadAccelerator = [Settings.gamepadSettings.ok];
backButton.accelerators = [hxd.Key.ENTER];
backButton.pressedAction = (e) -> {
Net.disconnect();

View file

@ -65,17 +65,11 @@ class OptionsListGui extends GuiImage {
btnList.addButton(3, 'Input and Sound Options', (e) -> {
MarbleGame.canvas.setContent(new InputOptionsGui(pauseGui));
});
if (Util.isTouchDevice()) {
if (!pauseGui) {
btnList.addButton(3, 'Touch Controls', (e) -> {
MarbleGame.canvas.setContent(new TouchOptionsGui(pauseGui));
});
}
} else {
btnList.addButton(3, 'Key Bindings', (e) -> {
MarbleGame.canvas.setContent(new KeyBindingsGui(pauseGui));
});
}
btnList.addButton(3, 'Input Controls', (e) -> {
MarbleGame.canvas.setContent(new InputSelectGui(pauseGui));
});
btnList.addButton(3, 'Video Options', (e) -> {
MarbleGame.canvas.setContent(new VideoOptionsGui(pauseGui));
});
@ -102,7 +96,7 @@ class OptionsListGui extends GuiImage {
backButton.position = new Vector(400, 0);
backButton.vertSizing = Bottom;
backButton.horizSizing = Right;
backButton.gamepadAccelerator = ["B"];
backButton.gamepadAccelerator = [Settings.gamepadSettings.back];
backButton.accelerators = [hxd.Key.ESCAPE, hxd.Key.BACKSPACE];
if (pauseGui)
backButton.pressedAction = (e) -> {

View file

@ -181,7 +181,7 @@ class PlayMissionGui extends GuiImage {
pmMenuButton.position = new Vector(119, 325);
pmMenuButton.extent = new Vector(92, 43);
pmMenuButton.accelerator = hxd.Key.ESCAPE;
pmMenuButton.gamepadAccelerator = ["B"];
pmMenuButton.gamepadAccelerator = [Settings.gamepadSettings.back];
pmMenuButton.pressedAction = (sender) -> {
cast(this.parent, Canvas).setContent(new MainMenuGui());
};
@ -217,7 +217,7 @@ class PlayMissionGui extends GuiImage {
var pmPlay = new GuiButton(loadButtonImages("data/ui/play/play"));
pmPlay.position = new Vector(510, 325);
pmPlay.extent = new Vector(92, 43);
pmPlay.gamepadAccelerator = ["A"];
pmPlay.gamepadAccelerator = [Settings.gamepadSettings.ok];
pmPlay.pressedAction = (sender) -> {
// Wacky hacks
currentList[currentSelection].index = currentSelection;

View file

@ -6,13 +6,18 @@ import hxd.res.BitmapFont;
import h3d.Vector;
import src.ResourceLoader;
import src.Settings;
import src.Gamepad;
class RemapDlg extends GuiImage {
var remapCallback:Int->Void;
var controllerRemapCallback:String->Void;
var controller:Bool;
public function new(bindingName:String) {
public function new(bindingName:String, controller:Bool = false) {
var res = ResourceLoader.getImage("data/ui/xbox/roundedBG.png").resource.toTile();
super(res);
this.controller = controller;
this.horizSizing = Width;
this.vertSizing = Height;
this.position = new Vector();
@ -40,11 +45,41 @@ class RemapDlg extends GuiImage {
public override function update(dt:Float, mouseState:MouseState) {
super.update(dt, mouseState);
for (i in 0...1024) {
if (i == Key.MOUSE_WHEEL_DOWN || i == Key.MOUSE_WHEEL_UP)
continue;
if (Key.isPressed(i)) {
remapCallback(i);
if (controller) {
var controllerKeys = [
"A",
"B",
"X",
"Y",
"LB",
"RB",
"LT",
"RT",
"start",
"back",
"analogClick",
"ranalogClick",
"dpadUp",
"dpadDown",
"dpadLeft",
"dpadRight"
];
for (key in controllerKeys) {
if (Gamepad.isPressed([key])) {
controllerRemapCallback(key);
return;
}
}
if (Key.isPressed(Key.ESCAPE))
controllerRemapCallback("escape");
} else {
for (i in 0...1024) {
if (i == Key.MOUSE_WHEEL_DOWN || i == Key.MOUSE_WHEEL_UP)
continue;
if (Key.isPressed(i)) {
remapCallback(i);
}
}
}
}

View file

@ -130,7 +130,7 @@ class ReplayCenterGui extends GuiImage {
backButton.position = new Vector(400, 0);
backButton.vertSizing = Bottom;
backButton.horizSizing = Right;
backButton.gamepadAccelerator = ["B"];
backButton.gamepadAccelerator = [Settings.gamepadSettings.back];
backButton.accelerators = [hxd.Key.ESCAPE, hxd.Key.BACKSPACE];
backButton.pressedAction = (e) -> MarbleGame.canvas.setContent(new MainMenuGui());
bottomBar.addChild(backButton);
@ -139,7 +139,7 @@ class ReplayCenterGui extends GuiImage {
nextButton.position = new Vector(960, 0);
nextButton.vertSizing = Bottom;
nextButton.horizSizing = Right;
nextButton.gamepadAccelerator = ["A"];
nextButton.gamepadAccelerator = [Settings.gamepadSettings.ok];
nextButton.accelerators = [hxd.Key.ENTER];
nextButton.pressedAction = (e) -> {
if (selectedIdx != -1) {

View file

@ -65,7 +65,7 @@ class ReplayNameDlg extends GuiImage {
okButton.extent = new Vector(120, 94);
okButton.vertSizing = Top;
okButton.accelerators = [hxd.Key.ENTER];
okButton.gamepadAccelerator = ["A"];
okButton.gamepadAccelerator = [Settings.gamepadSettings.ok];
okButton.pressedAction = (sender) -> {
if (StringTools.trim(textInput.text.text) != "") {
MarbleGame.instance.recordingName = textInput.text.text;
@ -81,7 +81,7 @@ class ReplayNameDlg extends GuiImage {
cancelButton.extent = new Vector(120, 94);
cancelButton.vertSizing = Top;
cancelButton.accelerators = [hxd.Key.ENTER];
cancelButton.gamepadAccelerator = ["A"];
cancelButton.gamepadAccelerator = [Settings.gamepadSettings.ok];
cancelButton.pressedAction = (sender) -> {
MarbleGame.canvas.popDialog(this);
callback();

View file

@ -60,7 +60,7 @@ class TouchCtrlsEditGui extends GuiImage {
nextButton.position = new Vector(960, 100);
nextButton.vertSizing = Bottom;
nextButton.horizSizing = Right;
nextButton.gamepadAccelerator = ["A"];
nextButton.gamepadAccelerator = [Settings.gamepadSettings.ok];
nextButton.accelerators = [hxd.Key.ENTER];
nextButton.pressedAction = (e) -> {
if (paused) {

View file

@ -108,18 +108,18 @@ class TouchOptionsGui extends GuiImage {
backButton.position = new Vector(960, 0);
backButton.vertSizing = Bottom;
backButton.horizSizing = Right;
backButton.gamepadAccelerator = ["A"];
backButton.gamepadAccelerator = [Settings.gamepadSettings.ok];
backButton.accelerators = [hxd.Key.ENTER];
if (pauseGui)
backButton.pressedAction = (e) -> {
Settings.applySettings();
MarbleGame.canvas.popDialog(this);
MarbleGame.canvas.pushDialog(new OptionsListGui(true));
MarbleGame.canvas.pushDialog(new InputSelectGui(true));
}
else
backButton.pressedAction = (e) -> {
Settings.applySettings();
MarbleGame.canvas.setContent(new OptionsListGui());
MarbleGame.canvas.setContent(new InputSelectGui());
};
bottomBar.addChild(backButton);
@ -128,7 +128,7 @@ class TouchOptionsGui extends GuiImage {
ctrlButton.position = new Vector(750, 0);
ctrlButton.vertSizing = Bottom;
ctrlButton.horizSizing = Right;
ctrlButton.gamepadAccelerator = ["Y"];
ctrlButton.gamepadAccelerator = [Settings.gamepadSettings.alt2];
ctrlButton.pressedAction = (e) -> {
MarbleGame.canvas.setContent(new TouchCtrlsEditGui(pauseGui));
}

View file

@ -72,7 +72,7 @@ class VersionGui extends GuiImage {
backButton.position = new Vector(960, 0);
backButton.vertSizing = Bottom;
backButton.horizSizing = Right;
backButton.gamepadAccelerator = ["A"];
backButton.gamepadAccelerator = [Settings.gamepadSettings.ok];
backButton.accelerators = [hxd.Key.ENTER];
backButton.pressedAction = (e) -> MarbleGame.canvas.setContent(new MainMenuGui());
bottomBar.addChild(backButton);

View file

@ -187,7 +187,7 @@ class VideoOptionsGui extends GuiImage {
backButton.position = new Vector(960, 0);
backButton.vertSizing = Bottom;
backButton.horizSizing = Right;
backButton.gamepadAccelerator = ["A"];
backButton.gamepadAccelerator = [Settings.gamepadSettings.ok];
backButton.accelerators = [hxd.Key.ENTER];
if (pauseGui)
backButton.pressedAction = (e) -> {

View file

@ -76,6 +76,25 @@ class MoveManager {
if (!MarbleGame.instance.paused) {
move.d.x = Gamepad.getAxis(Settings.gamepadSettings.moveYAxis);
move.d.y = -Gamepad.getAxis(Settings.gamepadSettings.moveXAxis);
if (Settings.controlsSettings.moddedController) {
// we need to scale the moves to square instead of circle
var moveLen = Math.sqrt(move.d.x * move.d.x + move.d.y * move.d.y);
if (moveLen > 0.00001) {
// Normalize the vector
var normalizedX = move.d.x / moveLen;
var normalizedY = move.d.y / moveLen;
// Scale to square - this allows diagonal movements to reach the corners
var scaleFactor = Math.max(Math.abs(normalizedX), Math.abs(normalizedY));
if (scaleFactor > 0) {
// Apply square mapping while preserving the original magnitude
move.d.x = normalizedX / scaleFactor * moveLen;
move.d.y = normalizedY / scaleFactor * moveLen;
}
}
}
if (@:privateAccess !MarbleGame.instance.world.playGui.isChatFocused()) {
if (Key.isDown(Settings.controlsSettings.forward)) {
move.d.x -= 1;
@ -89,6 +108,8 @@ class MoveManager {
if (Key.isDown(Settings.controlsSettings.right)) {
move.d.y -= 1;
}
move.d.x = Util.clamp(move.d.x, -1, 1);
move.d.y = Util.clamp(move.d.y, -1, 1);
if (Key.isDown(Settings.controlsSettings.jump)
|| MarbleGame.instance.touchInput.jumpButton.pressed
|| Gamepad.isDown(Settings.gamepadSettings.jump)) {

View file

@ -524,7 +524,6 @@ class Net {
serverInfo.players++;
}
serverInfo.players++;
MasterServerClient.instance.sendServerInfo(serverInfo); // notify the server of the new player
if (MarbleGame.canvas.content is MultiplayerLevelSelectGui) {