Trying to make "smart" crosshair in unity (using javascript) - user-interface

This is my script:
var ctexture : Texture2D;
function Update() {
var ray = Camera.main.ScreenPointToRay (Vector3(Screen.width/2,Screen.height/2,0));
var hit : RaycastHit;
if (Physics.Raycast (ray, hit, 100)) {
var pointVec=Camera.main.WorldToScreenPoint(hit.point);
GUI.Label(Rect(pointVec.x,pointVec.y,145,93),ctexture);
Debug.DrawRay (ray.origin, ray.direction * 10, Color.yellow);
Debug.Log(hit.point);}}
I can see Debug.DrawRay ray and it's just how i wanted it to be. The problem is that i can't see result of GUI.Label. The ctexture is assigned and Debug.Log prints out correct info.
Thanks in advance.

Put the code in the OnGUI() function:
var ctexture : Texture2D;
function OnGUI() {
var ray = Camera.main.ScreenPointToRay (Vector3(Screen.width/2,Screen.height/2,0));
var hit : RaycastHit;
if (Physics.Raycast (ray, hit, 100)) {
var pointVec=Camera.main.WorldToScreenPoint(hit.point);
GUI.Label(Rect(pointVec.x,pointVec.y,145,93),ctexture);
Debug.DrawRay (ray.origin, ray.direction * 10, Color.yellow);
Debug.Log(hit.point);
}
}

Related

d3fc - Crosshair with snapping using latest version 14

In previous version of d3fc my code was using fc.util.seriesPointSnapXOnly for snapping the crosshair.
This appears to be gone in the latest version of d3fc (or maybe I'm missing it in one of the standalone packages?).
I'm using the canvas implementation (annotationCanvasCrosshair) and it seems to also be missing the "snap" function where it was previously used like so:
fc.tool.crosshair()
.snap(fc.util.seriesPointSnapXOnly(line, series))
Additionally, "on" is also not available, so I can't attach events like trackingstart, trackingend, etc.
How can I implement a snapping crosshair now? The canvas version of the components are badly lacking examples. Does anyone have an example showing a snapping crosshair in the latest version of d3fc via canvas rendering?
Here's what I have so far https://codepen.io/parliament718/pen/xxbQGgp
I understand you've raised the issue with d3fc github, therefore I'll assume you are aware that util/snap.js is been deprecated.
Since this functionality unsupported now, it seems that the only feasible way to work around it will be to implement your own.
I took your pen and original snap.js code as starting point and applied the method outlined in Simple Crosshair example from the documentation.
I ended up having to add missing functions and their dependencies verbatim (surely you can refactor and package it up into a separate module):
function defined() {
var outerArguments = arguments;
return function(d, i) {
for (var c = 0, j = outerArguments.length; c < j; c++) {
if (outerArguments[c](d, i) == null) {
return false;
}
}
return true;
};
}
function minimum(data, accessor) {
return data.map(function(dataPoint, index) {
return [accessor(dataPoint, index), dataPoint, index];
}).reduce(function(accumulator, dataPoint) {
return accumulator[0] > dataPoint[0] ? dataPoint : accumulator;
}, [Number.MAX_VALUE, null, -1]);
}
function pointSnap(xScale, yScale, xValue, yValue, data, objectiveFunction) {
// a default function that computes the distance between two points
objectiveFunction = objectiveFunction || function(x, y, cx, cy) {
var dx = x - cx,
dy = y - cy;
return dx * dx + dy * dy;
};
return function(point) {
var filtered = data.filter(function(d, i) {
return defined(xValue, yValue)(d, i);
});
var nearest = minimum(filtered, function(d) {
return objectiveFunction(point.x, point.y, xScale(xValue(d)), yScale(yValue(d)));
})[1];
return [{
datum: nearest,
x: nearest ? xScale(xValue(nearest)) : point.x,
y: nearest ? yScale(yValue(nearest)) : point.y
}];
};
}
function seriesPointSnap(series, data, objectiveFunction) {
return function(point) {
var xScale = series.xScale(),
yScale = series.yScale(),
xValue = series.crossValue(),
yValue = (series.openValue).call(series);
return pointSnap(xScale, yScale, xValue, yValue, data, objectiveFunction)(point);
};
};
function seriesPointSnapXOnly(series, data) {
function objectiveFunction(x, y, cx, cy) {
var dx = x - cx;
return Math.abs(dx);
}
return seriesPointSnap(series, data, objectiveFunction);
}
The working end result can be seen here: https://codepen.io/timur_kh/pen/YzXXOOG. I basically defined two series and used a pointer component to update that second series data and trigger a re-render:
const data = {
series: stream.take(50), // your candle stick chart
crosshair: [] // second series to hold the crosshair position
};
.............
const crosshair = fc.annotationCanvasCrosshair() // define your crosshair
const multichart = fc.seriesCanvasMulti()
.series([candlesticks, crosshair]) // we've got two series now
.mapping((data, index, series) => {
switch(series[index]) {
case candlesticks:
return data.series;
case crosshair:
return data.crosshair;
}
});
.............
function render() {
d3.select('#zoom-chart')
.datum(data)
.call(chart);
// add the pointer component to the plot-area, re-rendering each time the event fires.
var pointer = fc.pointer()
.on('point', (event) => {
data.crosshair = seriesPointSnapXOnly(candlesticks, data.series)(event[0]);// and when we update the crosshair position - we snap it to the other series using the old library code.
render();
});
d3.select('#zoom-chart .plot-area')
.call(pointer);
}
UPD:
the functionality can be simplified like so, i also updated the pen:
function minimum(data, accessor) {
return data.map(function(dataPoint, index) {
return [accessor(dataPoint, index), dataPoint, index];
}).reduce(function(accumulator, dataPoint) {
return accumulator[0] > dataPoint[0] ? dataPoint : accumulator;
}, [Number.MAX_VALUE, null, -1]);
}
function seriesPointSnapXOnly(series, data, point) {
if (point == undefined) return []; // short circuit if data point was empty
var xScale = series.xScale(),
xValue = series.crossValue();
var filtered = data.filter((d) => (xValue(d) != null));
var nearest = minimum(filtered, (d) => Math.abs(point.x - xScale(xValue(d))))[1];
return [{
x: xScale(xValue(nearest)),
y: point.y
}];
};
This is far from polished, but I'm hoping it conveys the general idea.

How to add countdown timer to Phaser game

I am trying to add a simple countdown timer to a Phaser game. When the timer ends I want the game to restart. After adding the relevant code there are no errors in the console but I can't get the timer to appear on the screen. I am new to Phaser and am still learning Javascript. Where I am going wrong please? I have posted only the relevant code below, and the code used for already existing text in the game that is working fine (text to count coins collected).
PlayState = {};
PlayState.init = function () {
//....
};
PlayState.preload = function () {
this.game.load.image('font:numbers', 'images/numbers.png'); //for the
//HUD coin count - not the timer
};
PlayState.create = function () {
//TIMER CODE:
this.timeInSeconds = 120;
this.timeText = this.game.add.text(this.game.world.centerX,
this.game.world.centerY, "0:00",{font: '15px Arial', fill: '#FFFFFF', align:
'center'});
this.timeText.anchor.set(0.5, 0.5);
this.timer = this.game.time.events.loop(Phaser.Timer.SECOND,
this.updateTimer, this);
};
PlayState.update = function () {
this.coinFont.text = `x${this.coinPickupCount}`; //for HUD coin count not
//the timer
};
//TIMER CODE:
PlayState.updateTimer = function() {
this.timeInSeconds--;
var minutes = Math.floor(this.timeInSeconds / 60);
var seconds = this.timeInSeconds - (minutes * 60);
var timeString = this.addZeros(minutes) + ":" + this.addZeros(seconds);
this.timeText.text = timeString;
if (this.timeInSeconds == 0) {
this.game.state.restart();
}
};
//add leading zeros to any number less than 10
//for example turn 1 to 01
PlayState.addZeros = function(num) {
if (num < 10) {
num = "0" + num;
}
return num;
};
//BELOW IS CODE FOR THE COIN COUNT NOT THE TIMER
PlayState._createHud = function () {
this.keyIcon = this.game.make.image(0, 30, 'icon:key');
this.keyIcon.anchor.set(0, 0.5);
const NUMBERS_STR = '0123456789X ';
this.coinFont = this.game.add.retroFont('font:numbers', 20,
26,NUMBERS_STR, 6);
let coinIcon = this.game.make.image(this.keyIcon.width + 7,
0, 'icon:coin');
let coinScoreImg = this.game.make.image(coinIcon.x +
coinIcon.width, coinIcon.height / 2, this.coinFont);
coinScoreImg.anchor.set(0, 0.5);
this.hud = this.game.add.group();
this.hud.add(coinIcon);
this.hud.position.set(10, 10);
this.hud.add(coinScoreImg);
this.hud.add(this.keyIcon);
this.hud.fixedToCamera = true;
};
window.onload = function () {
let game = new Phaser.Game(1280, 800, Phaser.CANVAS, 'game');
game.state.add('play', PlayState);
game.state.start('play');
};
I have finally solved the issue. The text was not showing because it was being rendered AFTER the background image in create. So it was there but being hidden by the background image. I simply moved the timer code to the end of create and it now works.
PlayState.create = function () {
this.game.world.setBounds(0, 0, 2560, 800);
background1 = this.game.add.sprite(0, 0, 'background');
background2 = this.game.add.sprite(1280, 0, 'background2');
this.game.scale.scaleMode = Phaser.ScaleManager.SHOW_ALL;
this.game.scale.setMinMax(480,320,1280,800);
this.game.scale.windowConstraints.bottom = 'visual';
this.game.add.image(0, 0, 'background');
this._loadLevel(this.game.cache.getJSON('level:1'));
this._createHud();
//TIMER CODE SHOULD GO HERE AND NOT AT THE BEGINNING OF CREATE
this.timeInSeconds = 120;
this.timeText = this.game.add.text(220, 30, "0:00",{font: '30px Arial', fill:
'#FFFFFF', align: 'center'});
this.timeText.anchor.set(0.5, 0.5);
this.timer = this.game.time.events.loop(Phaser.Timer.SECOND, this.updateTimer,
this);
};
You set the initial text to "0:00" and even that doesn't show on screen? First thing I would do is look at the coordinates where the text is located, maybe it's not visible off screen. Instead of this.game.world.centerX, this.game.world.centerY try something like 100,100, does it show up then? Also try to set very long initial text, so something like "blah test ABC 123" instead of "0:00" maybe makes some difference.
Secondly, maybe the Arial font is not available for some reason. If you leave out the {font: '15px..'center'} part it will use a default font, does that change anything?
Thirdly, you say you didn't post all your code here, but maybe you accidentally overwrite the variable this.timeText somewhere in you code? So check that you don't set that variable to be something else.
Finally, I would add a console.log to the updateTimer function, just to see if it is being called. so:
PlayState.updateTimer = function() {
console.log('updateTimer was called: ' + this.timeInSeconds);
this.timeInSeconds--;
// etc.

WebGL THREE: changing position of obj, but the object doesn't move

I am working with an object which i loaded like this (I save it as a global variable such that I can change it later):
model1 = null;
var mtlLoader = new THREE.MTLLoader();
mtlLoader.load("http://blabla.mtl", function(materials) {
materials.preload();
var objLoader = new THREE.OBJLoader();
objLoader.setMaterials(materials);
objLoader.load("http://blabla.obj", function(object) {
object.scale.x = 0.0004;
object.scale.y = 0.0004;
object.scale.z = 0.0004;
object.rotateX(Math.PI / 2);
object.rotateZ(Math.PI / 2);
object.add(new THREE.AxisHelper(2))
model1 = object; //save in global variables
scene.add(model1);
});
});
When I am rendering I want to change the position of the model, based on a box's change in position:
function render(ms: number) {
if (lastTime) {
update((ms-lastTime)/1000)
}
lastTime = ms
requestAnimationFrame(render)
renderer.render( scene, camera )
}
var pos_current;
var pos_new;
var trans;
function update(dt: number) {
if (pause.on) return
//save position of box before it is transformed
pos_current = box.position.clone();
box.updatePosition()
//save new position of box
pos_new = box.position.clone();
//transform the 3D-model according to the box's transformation
trans = pos_current.sub(pos_new);
model1.position.add(trans);
console.log(model1.position)
I can in the console see that the position of model1 changes, but the object just doesn't move at all, and I can't really figure out why.
Any help is very appreciated :)
Got it to work - the problem was that I was trying to update the position of model1, before it was actually done loading in the obj-loader :D
I have a query. I too made a global variable and equaled it to object when loading. but it says in console log that variable in null. Is there a something I am missing.
Update:-
I understood the part where I am making the humanModel equal to object before it loaded but then how to handle it then?
let humanModel = null;
OBJLoader.load(
// resource URL
"/Models/Model_1(Malequins)/1/Cadnav.com_B0426014.obj",
// called when resource is loaded
function(object) {
scene.add(object);
humanModel = object; //adding the humanModel to the global variable
camera.lookAt(object.position);
console.log(object.position);
console.log(camera.position);
},
// called when loading is in progresses
function(xhr) {
console.log((xhr.loaded / xhr.total) * 100 + "% loaded");
},
// called when loading has errors
function(error) {
console.log("An error happened " + error);
}
);
console.log(humanModel.position);
Thanks
you can keep the object(obj file) in x,y or z direction, for it you need to set its position as:
var loader = new THREE.OBJLoader();
loader.load(
'/models/female.obj',
function(object){
object.position.y=-20;
scene.add(object);
}
)

EaselJS: Using updateCache() with AlphaMaskFilter When Dragging Mask

I'm using an imported png with an alpha gradient that I'm setting as a mask that reveals the bitmap it is assigned to. The mask object is draggable (kind of like a flashlight). I know I'm supposed to use an AlphaMaskFilter as one of the filters, and I know I'm supposed to use .updateCache()... I'm just not sure I'm using them correctly?
var stage;
var assetQueue;
var bg;
var bgMask;
var container;
var amf;
$(document).ready(function(){
loadImages();
});
function loadImages()
{
// Set up preload queue
assetQueue = new createjs.LoadQueue();
assetQueue.addEventListener("complete", preloadComplete);
assetQueue.loadManifest([{id:"img_bg",src:"images/Nintendo-logo-red.jpg"}, {id:"img_bg_mask",src:"images/background_mask.png"}]);
}
function preloadComplete()
{
assetQueue.removeEventListener("complete", preloadComplete);
init();
}
function init()
{
stage = new createjs.Stage("stage_canvas");
setBackgrounds();
sizeStage();
$(document).mousemove(function(evt){
trackMouse(evt);
});
}
function trackMouse(evt)
{
var mouseX = evt.pageX;
var mouseY = evt.pageY;
// Move the containing clip around
container.x = mouseX - (bgMask.image.width / 2);
container.y = mouseY - (bgMask.image.height / 2);
// Offset the position of the masked image.
bg.x = -container.x;
bg.y = -container.y;
container.updateCache();
stage.update();
}
function setBackgrounds()
{
bg = new createjs.Bitmap(assetQueue.getResult("img_bg"));
bgMask = new createjs.Bitmap(assetQueue.getResult("img_bg_mask"));
container = new createjs.Container();
container.addChild(bg);
amf = new createjs.AlphaMaskFilter(bgMask.image)
container.filters = [amf];
container.cache(0, 0, bg.image.width, bg.image.height);
stage.addChild(container);
stage.update();
}
function sizeStage()
{
var windowW = 600;
var windowH = 600;
stage.canvas.width = windowW;
stage.canvas.height = windowH;
stage.update();
}
Solution found (for anyone interested). The key is to add the image you want to mask to a container. Move the container to any position you want, then offset the contained image within the container. The code has been updated to reflect this.

Animating D3 globe (d3.geo.azimuthal)

I have question about the d3 javascript libarary. I want to use the azimuthal globe and I want to insert points from longitude and lattitude coordinates on the globe and make the globe be animated without ever using the mouse events.
Do you think this is possible? Can you give me some good tips on how to do this?
Cheers
Thor
To make the example rotate on its own I implemented:
var newX = 185;
var newY = -200;
function setupRotate() {
m0= [0,0];
o0 = projection.origin();
}
function rotate() {
if (m0) {
var m1 = [newX, newY];//d3.event.pageX, d3.event.pageY],
o1 = [o0[0] + (m0[0] - m1[0]) / 8, o0[1] + (m1[1] - m0[1]) / 8];
projection.origin(o1);
//console.log(m1);
circle.origin(o1)
refresh();
//console.log("rotate");
//console.log("newX: "+newX+" newY: "+newY);
}
}
function rotateInterval() {
var theRotationInterval = setInterval(rotateAndIncrement,1);
function rotateAndIncrement(){
//console.log("rotateAndIncrement");
if (newX === 3)//3065) {
{
//console.warn("!!Reset Rotation!!");
clearInterval(theRotationInterval);
newX = 185;
rotateInterval();
}
//console.log("newX: "+newX+" newY: "+newY);
else {
newX++;
rotate();
}
}
}
I'm working on adding points to the map, it's much more complicated. If I cant get it working I'll post back here.

Resources