mirror of
https://github.com/RandomityGuy/MBHaxe.git
synced 2025-10-30 08:11:25 +00:00
implement radar and fix hunt gem counter color
This commit is contained in:
parent
b3978bb9bb
commit
870474cfed
4 changed files with 284 additions and 9 deletions
|
|
@ -1,5 +1,6 @@
|
|||
package src;
|
||||
|
||||
import src.Radar;
|
||||
import rewind.InputRecorder;
|
||||
import net.NetPacket.ScoreboardPacket;
|
||||
import net.NetPacket.PowerupPickupPacket;
|
||||
|
|
@ -135,6 +136,7 @@ class MarbleWorld extends Scheduler {
|
|||
|
||||
var playGui:PlayGui;
|
||||
var loadingGui:LoadingGui;
|
||||
var radar:Radar;
|
||||
|
||||
public var interiors:Array<InteriorObject> = [];
|
||||
public var pathedInteriors:Array<PathedInterior> = [];
|
||||
|
|
@ -380,6 +382,10 @@ class MarbleWorld extends Scheduler {
|
|||
this.playGui = new PlayGui();
|
||||
this.instanceManager = new InstanceManager(scene);
|
||||
this.particleManager = new ParticleManager(cast this);
|
||||
if (this.isMultiplayer || this.game == "ultra") {
|
||||
this.radar = new Radar(cast this, this.scene2d);
|
||||
radar.init();
|
||||
}
|
||||
|
||||
var worker = new ResourceLoaderWorker(() -> {
|
||||
var renderer = cast(this.scene.renderer, h3d.scene.fwd.Renderer);
|
||||
|
|
@ -647,6 +653,9 @@ class MarbleWorld extends Scheduler {
|
|||
this.playGui.formatGemCounter(this.gemCount, this.totalGems);
|
||||
}
|
||||
|
||||
if (radar != null)
|
||||
radar.reset();
|
||||
|
||||
// Record/Playback trapdoor and landmine states
|
||||
if (full) {
|
||||
var tidx = 0;
|
||||
|
|
@ -1670,6 +1679,8 @@ class MarbleWorld extends Scheduler {
|
|||
}
|
||||
}
|
||||
|
||||
if (radar != null)
|
||||
radar.update(dt);
|
||||
this.updateGameState();
|
||||
if (!this.isMultiplayer)
|
||||
this.updateBlast(this.marble, timeState);
|
||||
|
|
@ -1815,6 +1826,8 @@ class MarbleWorld extends Scheduler {
|
|||
this.marble.cubemapRenderer.render(e, 0.002);
|
||||
}
|
||||
if (_instancesNeedsUpdate) {
|
||||
if (this.radar != null)
|
||||
this.radar.render();
|
||||
_instancesNeedsUpdate = false;
|
||||
this.instanceManager.render();
|
||||
}
|
||||
|
|
@ -2659,6 +2672,11 @@ class MarbleWorld extends Scheduler {
|
|||
this.playGui.dispose();
|
||||
scene.removeChildren();
|
||||
|
||||
if (radar != null) {
|
||||
radar.dispose();
|
||||
radar = null;
|
||||
}
|
||||
|
||||
CollisionPool.freeMemory();
|
||||
|
||||
for (interior in this.interiors) {
|
||||
|
|
|
|||
208
src/Radar.hx
Normal file
208
src/Radar.hx
Normal file
|
|
@ -0,0 +1,208 @@
|
|||
package src;
|
||||
|
||||
import hxd.res.BitmapFont;
|
||||
import h3d.Matrix;
|
||||
import src.DtsObject;
|
||||
import h3d.Vector;
|
||||
import gui.Graphics;
|
||||
import src.GameObject;
|
||||
import h2d.Scene;
|
||||
import src.MarbleWorld;
|
||||
import src.Util;
|
||||
import src.Marble;
|
||||
import src.Settings;
|
||||
import src.ResourceLoader;
|
||||
|
||||
class Radar {
|
||||
var level:MarbleWorld;
|
||||
var scene2d:Scene;
|
||||
|
||||
var g:Graphics;
|
||||
|
||||
var marbleNameTexts:Map<Marble, h2d.Text>;
|
||||
|
||||
public var ellipseScreenFraction = new Vector(0.79, 0.85);
|
||||
public var fullArrowLength = 60.0;
|
||||
public var fullArrowWidth = 40.0;
|
||||
public var maxArrowAlpha = 0.6;
|
||||
public var maxTargetAlpha = 0.4;
|
||||
public var minArrowFraction = 0.4;
|
||||
|
||||
var radarTiles:Array<h2d.Tile>;
|
||||
|
||||
var time:Float = 0.0;
|
||||
|
||||
var _dirty = false;
|
||||
|
||||
public function new(level:MarbleWorld, scene2d:Scene) {
|
||||
this.level = level;
|
||||
this.scene2d = scene2d;
|
||||
this.marbleNameTexts = [];
|
||||
var radarTileRedGem = ResourceLoader.getImage("data/ui/mp/radar/GemItemRed.png").resource.toTile();
|
||||
var radarTileYellowGem = ResourceLoader.getImage("data/ui/mp/radar/GemItemYellow.png").resource.toTile();
|
||||
var radarTileBlueGem = ResourceLoader.getImage("data/ui/mp/radar/GemItemBlue.png").resource.toTile();
|
||||
var radarTileGreenGem = ResourceLoader.getImage("data/ui/mp/radar/GemItemGreen.png").resource.toTile();
|
||||
var radarTileOrangeGem = ResourceLoader.getImage("data/ui/mp/radar/GemItemOrange.png").resource.toTile();
|
||||
var radarTilePinkGem = ResourceLoader.getImage("data/ui/mp/radar/GemItemPink.png").resource.toTile();
|
||||
var radarTilePurpleGem = ResourceLoader.getImage("data/ui/mp/radar/GemItemPurple.png").resource.toTile();
|
||||
var radarTileTurquoiseGem = ResourceLoader.getImage("data/ui/mp/radar/GemItemTurquoise.png").resource.toTile();
|
||||
var radarTileBlackGem = ResourceLoader.getImage("data/ui/mp/radar/GemItemBlack.png").resource.toTile();
|
||||
var radarTilePlatinumGem = ResourceLoader.getImage("data/ui/mp/radar/GemItemPlatinum.png").resource.toTile();
|
||||
var radarTileEndPad = ResourceLoader.getImage("data/ui/mp/radar/EndPad.png").resource.toTile();
|
||||
radarTiles = [
|
||||
radarTileRedGem, radarTileYellowGem, radarTileBlueGem, radarTileGreenGem, radarTileOrangeGem, radarTilePinkGem, radarTilePurpleGem,
|
||||
radarTileTurquoiseGem, radarTileBlackGem, radarTilePlatinumGem, radarTileEndPad
|
||||
];
|
||||
}
|
||||
|
||||
public function init() {
|
||||
g = new Graphics(scene2d);
|
||||
}
|
||||
|
||||
public function update(dt:Float) {
|
||||
time += dt;
|
||||
_dirty = true;
|
||||
}
|
||||
|
||||
public function render() {
|
||||
if (!_dirty)
|
||||
return;
|
||||
g.clear();
|
||||
var gemCount = 0;
|
||||
for (gem in level.gems) {
|
||||
if (!gem.pickedUp) {
|
||||
renderArrow(gem.boundingCollider.boundingBox.getCenter().toVector(), gem.radarGemColor, radarTiles[gem.radarGemIndex]);
|
||||
gemCount++;
|
||||
}
|
||||
}
|
||||
if (@:privateAccess level.endPad != null && gemCount == 0) {
|
||||
renderArrow(@:privateAccess level.endPad.getAbsPos().getPosition(), 0xE6E6E6, radarTiles[10]);
|
||||
}
|
||||
var fadeDistance = level.scene.camera.zFar * 0.1;
|
||||
for (marble => marbleName in marbleNameTexts) {
|
||||
if (marbleName != null)
|
||||
marbleName.alpha = 0;
|
||||
}
|
||||
for (marble in level.marbles) {
|
||||
if (marble != level.marble) {
|
||||
var shapePos = marble.getAbsPos().getPosition();
|
||||
var shapeDir = shapePos.sub(level.scene.camera.pos);
|
||||
var shapeDist = shapeDir.lengthSq();
|
||||
if (shapeDist == 0 || shapeDist > level.scene.camera.zFar * level.scene.camera.zFar) {
|
||||
dontRenderName(marble);
|
||||
continue;
|
||||
}
|
||||
var validProjection = frustumHasPoint(level.scene.camera.frustum, shapePos);
|
||||
if (!validProjection) {
|
||||
dontRenderName(marble);
|
||||
continue;
|
||||
}
|
||||
shapePos.z += 0.5; // Vertical offset
|
||||
|
||||
var projectedPos = level.scene.camera.project(shapePos.x, shapePos.y, shapePos.z, scene2d.width, scene2d.height);
|
||||
var opacity = (shapeDist < fadeDistance) ? 1.0 : (1.0 - (shapeDist - fadeDistance) / (level.scene.camera.zFar - fadeDistance));
|
||||
renderName(projectedPos, marble, opacity);
|
||||
}
|
||||
}
|
||||
_dirty = false;
|
||||
}
|
||||
|
||||
public function blink() {
|
||||
time = 0;
|
||||
}
|
||||
|
||||
public function reset() {
|
||||
time = 0;
|
||||
g.clear();
|
||||
}
|
||||
|
||||
public function dispose() {
|
||||
g.clear();
|
||||
scene2d.removeChild(g);
|
||||
g = null;
|
||||
for (txt in marbleNameTexts) {
|
||||
if (txt != null) {
|
||||
scene2d.removeChild(txt);
|
||||
}
|
||||
}
|
||||
marbleNameTexts = null;
|
||||
}
|
||||
|
||||
inline function planeDistance(plane:h3d.col.Plane, p:Vector) {
|
||||
return @:privateAccess plane.nx * p.x + @:privateAccess plane.ny * p.y + @:privateAccess plane.nz * p.z - @:privateAccess plane.d;
|
||||
}
|
||||
|
||||
function frustumHasPoint(frustum:h3d.col.Frustum, p:Vector) {
|
||||
if (planeDistance(frustum.pleft, p) < 0)
|
||||
return false;
|
||||
if (planeDistance(frustum.pright, p) < 0)
|
||||
return false;
|
||||
if (planeDistance(frustum.ptop, p) < 0)
|
||||
return false;
|
||||
if (planeDistance(frustum.pbottom, p) < 0)
|
||||
return false;
|
||||
if (frustum.checkNearFar) {
|
||||
if (planeDistance(frustum.pnear, p) < 0)
|
||||
return false;
|
||||
if (planeDistance(frustum.pfar, p) < 0)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function renderArrow(pos:Vector, color:Int, tile:h2d.Tile) {
|
||||
var validProjection = frustumHasPoint(level.scene.camera.frustum, pos);
|
||||
var projectedPos = level.scene.camera.project(pos.x, pos.y, pos.z, scene2d.width, scene2d.height);
|
||||
|
||||
if (validProjection && tile != null) {
|
||||
g.lineStyle(0, 0, 0);
|
||||
g.drawTile(projectedPos.x - tile.width / 2, projectedPos.y - tile.height / 2, tile);
|
||||
} else if (!validProjection) {
|
||||
var centerDiff = projectedPos.sub(new Vector(scene2d.width / 2, scene2d.height / 2));
|
||||
|
||||
var theta = Math.atan2(centerDiff.y, centerDiff.x);
|
||||
if (projectedPos.z > 1)
|
||||
theta += Math.PI;
|
||||
|
||||
var ellipsePos = new Vector(scene2d.width * (ellipseScreenFraction.x * Math.cos(theta) + 1) / 2,
|
||||
scene2d.height * (ellipseScreenFraction.y * Math.sin(theta) + 1) / 2);
|
||||
var arrowDir = projectedPos.sub(new Vector(scene2d.width / 2, scene2d.height / 2)).normalized();
|
||||
var arrowDirPerp = new Vector(-arrowDir.y, arrowDir.x);
|
||||
if (projectedPos.z > 1)
|
||||
arrowDir.scale(-1);
|
||||
|
||||
var tipPosition = ellipsePos.add(arrowDir.multiply(fullArrowLength));
|
||||
var tipUpperPosition = ellipsePos.add(arrowDirPerp.multiply(fullArrowWidth / 2));
|
||||
var tipLowerPosition = ellipsePos.add(arrowDirPerp.multiply(-fullArrowWidth / 2));
|
||||
|
||||
g.beginFill(color, 0.6);
|
||||
g.lineStyle(1, 0, 0.6);
|
||||
g.moveTo(tipPosition.x, tipPosition.y);
|
||||
g.lineTo(tipUpperPosition.x, tipUpperPosition.y);
|
||||
g.lineTo(tipLowerPosition.x, tipLowerPosition.y);
|
||||
g.endFill();
|
||||
}
|
||||
}
|
||||
|
||||
function renderName(pos:Vector, marble:Marble, opacity:Float) {
|
||||
if (!marbleNameTexts.exists(marble)) {
|
||||
var arialb14fontdata = ResourceLoader.getFileEntry("data/font/Arial Bold.fnt");
|
||||
var arialb14b = new BitmapFont(arialb14fontdata.entry);
|
||||
@:privateAccess arialb14b.loader = ResourceLoader.loader;
|
||||
var arialBold14 = arialb14b.toSdfFont(cast 16 * Settings.uiScale, MultiChannel);
|
||||
var txt = new h2d.Text(arialBold14, scene2d);
|
||||
marbleNameTexts.set(marble, txt);
|
||||
txt.textColor = 0xFFFF00;
|
||||
}
|
||||
var textObj = marbleNameTexts.get(marble);
|
||||
textObj.text = @:privateAccess marble.connection.getName();
|
||||
textObj.setPosition(pos.x - textObj.textWidth / 2, pos.y - textObj.textHeight);
|
||||
textObj.alpha = opacity;
|
||||
}
|
||||
|
||||
function dontRenderName(marble:Marble) {
|
||||
if (marbleNameTexts.exists(marble)) {
|
||||
marbleNameTexts.get(marble).alpha = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -774,20 +774,26 @@ class PlayGui {
|
|||
}
|
||||
|
||||
public function formatGemHuntCounter(collected:Int) {
|
||||
gemCountNumbers[0].anim.visible = true;
|
||||
gemCountNumbers[1].anim.visible = true;
|
||||
var collectedHundredths = Math.floor(collected / 100);
|
||||
var collectedTenths = Math.floor(collected / 10) % 10;
|
||||
var collectedOnes = collected % 10;
|
||||
|
||||
if (collected >= 100)
|
||||
gemCountNumbers[0].anim.visible = true;
|
||||
else
|
||||
gemCountNumbers[0].anim.visible = false;
|
||||
if (collected >= 10)
|
||||
gemCountNumbers[1].anim.visible = true;
|
||||
else
|
||||
gemCountNumbers[1].anim.visible = false;
|
||||
gemCountNumbers[2].anim.visible = true;
|
||||
gemCountNumbers[3].anim.visible = false;
|
||||
gemCountNumbers[4].anim.visible = false;
|
||||
gemCountNumbers[5].anim.visible = false;
|
||||
|
||||
var collectedHundredths = Math.floor(collected / 100);
|
||||
var collectedTenths = Math.floor(collected / 10) % 10;
|
||||
var collectedOnes = collected % 10;
|
||||
|
||||
gemCountNumbers[0].anim.currentFrame = collectedHundredths;
|
||||
gemCountNumbers[1].anim.currentFrame = collectedTenths;
|
||||
gemCountNumbers[2].anim.currentFrame = collectedOnes;
|
||||
gemCountNumbers[0].anim.currentFrame = 10 + collectedHundredths;
|
||||
gemCountNumbers[1].anim.currentFrame = 10 + collectedTenths;
|
||||
gemCountNumbers[2].anim.currentFrame = 10 + collectedOnes;
|
||||
gemCountSlash.bmp.visible = false;
|
||||
gemImageSceneTargetBitmap.visible = true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,6 +13,8 @@ class Gem extends DtsObject {
|
|||
public var pickedUp:Bool;
|
||||
public var netIndex:Int;
|
||||
public var pickUpClient:Int = -1;
|
||||
public var radarGemColor:Int;
|
||||
public var radarGemIndex:Int;
|
||||
|
||||
var gemColor:String;
|
||||
|
||||
|
|
@ -33,6 +35,47 @@ class Gem extends DtsObject {
|
|||
this.identifier = "Gem" + color;
|
||||
this.matNameOverride.set('base.gem', color + ".gem");
|
||||
gemColor = color + ".gem";
|
||||
var colLower = color.toLowerCase();
|
||||
switch (colLower) {
|
||||
case "red":
|
||||
radarGemColor = 0xFF0000;
|
||||
radarGemIndex = 0;
|
||||
case "blue":
|
||||
radarGemColor = 0x6666E6;
|
||||
radarGemIndex = 2;
|
||||
|
||||
case "yellow":
|
||||
radarGemColor = 0xFEFF00;
|
||||
radarGemIndex = 1;
|
||||
|
||||
case "green":
|
||||
radarGemColor = 0x66E666;
|
||||
radarGemIndex = 3;
|
||||
|
||||
case "orange":
|
||||
radarGemColor = 0xE6BA66;
|
||||
radarGemIndex = 4;
|
||||
|
||||
case "pink":
|
||||
radarGemColor = 0xE666E5;
|
||||
radarGemIndex = 5;
|
||||
|
||||
case "purple":
|
||||
radarGemColor = 0xC566E6;
|
||||
radarGemIndex = 6;
|
||||
|
||||
case "turquoise":
|
||||
radarGemColor = 0x66E5E6;
|
||||
radarGemIndex = 7;
|
||||
|
||||
case "black":
|
||||
radarGemColor = 0x666666;
|
||||
radarGemIndex = 8;
|
||||
|
||||
case "platinum":
|
||||
radarGemColor = 0xA5A5A5;
|
||||
radarGemIndex = 9;
|
||||
}
|
||||
}
|
||||
|
||||
public override function init(level:MarbleWorld, onFinish:Void->Void) {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue