I'm playing around with box2djs. I'm trying to find a way to write an 'onCollision()' callback function, but the documentation is sparse and I can't find an obvious way to do it.
Thanks!
Call back for box2djs is actually referenced as a collision "filter." Here is how you can implement it. I'll also show what I'm doing instead which maybe is a little slower but since my other approach is outside the step() I can destroy objects and stuff:
// Called whenever a collision occurs in the world
//
var JellyCollisionCallback = function()
{
// Required function - this is the function the gets called when b2ContactManager registers a collision between two bodies
//
this.ShouldCollide = function( shape1, shape2 )
{
// These are the two bodies…
//
var cBody1 = shape1.m_body;
var cBody2 = shape2.m_body;
// I'm setting userData when I create the body object
//
var jellyObject1 = cBody1.GetUserData();
var jellyObject2 = cBody2.GetUserData();
// This is the code from the default collision filter
//
if (shape1.m_groupIndex == shape2.m_groupIndex && shape1.m_groupIndex != 0)
{
return shape1.m_groupIndex > 0;
}
var collide = (shape1.m_maskBits & shape2.m_categoryBits) != 0 && (shape1.m_categoryBits & shape2.m_maskBits) != 0;
return collide;
}
return this;
}
function createWorld()
{
var world = new b2World(worldAABB, gravity, doSleep);
myCollisionCallback = new JellyCollisionCallback();
world.SetFilter(myCollisionCallback );
}
probably not as nice as a true callback, but I had originally had trouble trying to get a callback to work so I wrote this approach and ended up keeping it instead. I do this in my main loop that calls the world.step()
// Find collisions between selected objects
//
// (world is the main b2World object)
//
var aContact;
for ( aContact = world.m_contactList; aContact != null; aContact = aContact.m_next )
{
var cBody1 = aContact.m_shape1.m_body;
var cBody2 = aContact.m_shape2.m_body;
// I'm setting userData when I create the body object
//
var jellyObject1 = cBody1.GetUserData();
var jellyObject2 = cBody2.GetUserData();
// Not one of my controlled Objects
//
if ( typeof(jellyObject1) != "object" || jellyObject1 == null )
continue;
if ( typeof(jellyObject2) != "object" || jellyObject2 == null )
continue;
// Call my collision event for the colliding objects
//
jellyObject1.dink();
jellyObject2.dink();
}
documentation is pretty much unavailable from what I found, but I really like box2djs and have finally figured out everything I need to accomplish some simple hobby projects. Here are some examples that extend the original box2djs demo jellyrobotics box2djs project
Related
I would like to get inputs values of a form and place in an object (for an offer).
So i tried to place this code on submit :
$(document).ready(function(){
$('#formOffre').on('submit', function(e) {
e.preventDefault();
console.log(Offre); // give undefined in console
if ( typeof Offre == 'undefined'){
// if undefined, create object
var Offre = {
BuyerID: 1, //I will handle this later
Total: 0,
OffreItem: [] //array with json objects
};
Offre.OffreItem.id = 0;
console.log("object created");
for (i=0; i > Offre.OffreItem.id ; i++) {
Offre.OffreItem.modele = formOffre.modele.value;
Offre.OffreItem.longueur = formOffre.longueur.value;
Offre.OffreItem.hauteur = formOffre.hauteur.value;
Offre.OffreItem.qte = formOffre.qte.value;
Offre.OffreItem.rix = formOffre.prix.value;
console.log("getting parameters of inputs to offer");
}
} else {
//if object exists ony get informations of inputs
Offre.OffreItem.id = 0;
for (i=0; Offre.OffreItem.id < i; i++){
Offre.OffreItem.modele = formOffre.modele.value;
Offre.OffreItem.longueur = formOffre.longueur.value;
Offre.OffreItem.hauteur = formOffre.hauteur.value;
Offre.OffreItem.qte = formOffre.qte.value;
Offre.OffreItem.rix = formOffre.prix.value;
}
}
this is my code. when i click on submit for the first time, it go to the if statement and create the object. But when i click again, I go through the if statement like the object is not set.
i put a console log and in every case the object is undefined.
Can you someone help me please?
Thanks
You are checking Offre out side of scope in which it is defined .
enter coconsole.log(Offre); // give undefined in console
if ( typeof Offre == 'undefined'){
// if undefined, create object
var Offre = { //here is issue this should be above submit function
BuyerID: 1, //I will handle this later
Total: 0,
OffreItem: [] //array with json objects
};
Also make sure your page is maintaining state.
For you I have created example give a look. here
Hoping this will solve your problem.
Fiddle
The problem here is that you're defining your variable inside the function.
To simplify your code:
$('#formOffre').on('submit', function(e) {
if ( typeof Offre == 'undefined'){
var Offre = { }; // This variable is only accessible inside this function
} else {
//
}
}
The var Offre will define a variable within the scope of the function, the next time you run the function, a new variable with that name will be created (Meaning it will always be undefined initially)
To get around this, you can define your variable outside of the function:
var Offre;
$('#formOffre').on('submit', function(e) {
if ( typeof Offre == 'undefined'){
Offre = { }; // Notice that we're not creating a new variable here, just accessing the one defined above
} else {
//
}
}
My solution works well if the starting node is passed to the function correctly. I want to know if my solution is good and efficient. I should be able to return true if the cycle exists via function to which first node is passed as parameter. I would like to know if my solution is efficient especially for an interview setting. My comments in the code are self explanatory. Im using a variable track to traverse through the list and checking for a null or head as the next. If i encounter any of them traversal ends and then individually i check for null or head condition and based on that i return the appropriate boolean value.
function SLLNode(elem) {
this.value=elem;
this.next=null;
}
var hasCycle=function(node){
var track=node;
//traverse thru list till next node is either null or back to first node
while(track.next!==null && track.next!==this.head){
track=track.next;
}
if(track.next === null){ //if next node null then no cycle
return false;
}
if(track.next===this.head){ //if next node head then there is cycle
return true;
}
}
var my_node1=new SLLNode(3);
var my_node2=new SLLNode(5);
var my_node3=new SLLNode(19);
//assigning head
var head=my_node1;
//connecting linked list
my_node1.next=my_node2;
my_node2.next=my_node3;
my_node3.next=my_node1; //cycle
console.log("Has cycle?: "+hasCycle(my_node1)); //outputs true as expected
var node1=new SLLNode(3);
var node2=new SLLNode(5);
var node3=new SLLNode(19);
//assigning head
var head1=node1;
node1.next=node2;
node2.next=node3;
console.log("Has cycle?: "+hasCycle(node1)); //outputs false as expected
JSON.stringify() can be used to detect cyclic linked lists. CircularDetector returns true if the linked list is cyclic.
function CircularDetector (head) {
try {
JSON.stringify(head);
return false;
} catch (e) {
return true;
}
}
You can read more on cycle detection at https://en.wikipedia.org/wiki/Cycle_detection but the main takeaway is that if you move one pointer twice as fast as another pointer then a loop would be identifiable as the fast pointer will eventually catch up with the other. Here's a possible solution in js.
function hasCycle(head) {
var slow, fast;
if(!head || !head.next) return false;
slow = head;
fast = head;
if(head.next === head) return true;
while(fast.next.next) {
slow = slow.next;
fast = fast.next.next;
if(slow === fast) return true;
}
return false;
}
Not a very efficient solution as I am using map but if you don't want to use two pointers this solution is easy to understand
// Preparation code:
class Node {
constructor(value) {
this.value = value;
this.next = null;
}
}
function hasCycle(head) {
let node = head;
let map={};
while(node){
if(map[node.value]){
//return node or true
return {"Found":node}
}
else{
map[node.value] = true;
}
node = node.next;
}
return "Not found";
}
const nodeA = new Node('A');
const nodeB = nodeA.next = new Node('B');
const nodeC = nodeB.next = new Node('C');
const nodeD = nodeC.next = new Node('D');
const nodeE = nodeD.next = new Node('E');
console.log(hasCycle(nodeA)); // => null
nodeE.next = nodeB;
console.log(hasCycle(nodeA))
To avoid overlapping events, I use this function:
function isOverlapping(event){
var array = $('#calendar').fullCalendar('clientEvents');
for(i in array){
if(array[i].id != event.id){
if(array[i].allDay || event.allDay){
if(array[i].start.getDate() == event.start.getDate()){
if(array[i].start.getMonth() == event.start.getMonth()){
return true;
}
}
}
else{
if(event.end > array[i].start && event.start < array[i].end){ return true;}
}
}
}
return false;
}
If my calendar has lots of events, the function is quite slow, so as to increase the speed, i thought it would be nice to compare only the events in the current view, so I wished I could use the clientEvents filter function like this:
var array = $('#calendar').fullCalendar('clientEvents', function(events){ return (event.start >= view_start && view_end > event.start)});
But this returns all the events.
Note:
I have declared view_start & view_end as global variables and calculated them in the ViewDisplay like this:
view_start = view.visStart;
view_end = view.visEnd;
How can I get the events which are visible in the current view.
The problem with the oneliner you wanted to use is that the event.start is actually an object. I was able to use something similar like this:
moment(calEvent.start).format('YYYY-MM-DD')
So for your case try:
var array = $('#calendar').fullCalendar('clientEvents', function(events){ return (moment(events.start).format('YYYY-MM-DD') >= view_start && view_end > moment(events.start).format('YYYY-MM-DD'))});
There are no built in filter in fullcalendar, you have to make them by yourself. The only thing you can do is to do what you are doing :) ...using your own filter functions.
This is what i do to filter them, but this is made client side, so the filtering will be made client side... This can be a problem, but for my particular solution its enought.
This is my example:
function getCalendarEvents(filter){
var events = new Array();
if(filter == null)
{
events = calendar.fullCalendar('clientEvents');
}
else
{
events = getEventsByFilter(filter);
}
return events;
}
The filter events function:
function getEventsByFilter(filter){
var allevents = new Array();
var filterevents = new Array();
allevents = getCalendarEvents(null);
for(var j in allevents){
if(allevents[j].eventtype === filter)
{
filterevents.push(allevents[j]);
}
}
return filterevents;
}
Most functions in fullCalendar use filters.
These filters may be a number and gets filtered by ID or can be functions that return true or false depending on what are you filtering.
var array = $('#calendar').fullCalendar('clientEvents',function(event)
if(event.start > '1111-11-11')return true;
else return false;
);
I have a question. We all know the power of closures in Javascript and I want to use this power. Lets say I have a an object named "BRB". WHat I wanted to is whenever user calls the method getBrowser() for the very first time it will find out browser version/name whatever and return it and also store it inside itself as static when getBrowser() called second time it should return the same value without calculation since it is already statically stored somewhere. This can be done in many different ways, we can just store a property in the object and in the first call we can set some values for it and use it later, we can run getBrowser method directly when object is created in the syntax as
(function()(
...
))()
However, this is not what I want. All I want is getBrowser() method to calculate the value only once and use it all the time, I dont want to store the value inside the object somewhere else and I dont want to run this method right away when object is created, I'm allowed to use only and only this method and all action must take place in this one method. I put here an example, as you see it will always print out "0" but what I want is it prints 0,1,2,3 for each console.log request. I hope I made myself clear. Thanks.
(
function(window){
if(window.BRB) return;
var BRB = function(){}
BRB.prototype.getBrowser = function(){
var browser = null;
return function(){
if(browser === null){
browser = 0;
}
return browser++;
}
}
window.BRB = new BRB();
})(window);
console.log(BRB.getBrowser()());
console.log(BRB.getBrowser()());
console.log(BRB.getBrowser()());
console.log(BRB.getBrowser()());
Your requirements are kinda strange. Is this what you're looking for? It works by creating a property on the getBrowser function itself:
(function(window){
if(window.BRB) return;
var BRB = function(){}
BRB.prototype.getBrowser = function(){
if(typeof this.getBrowser.browser == "undefined"){
return this.getBrowser.browser = 0;
} else {
return ++this.getBrowser.browser;
}
}
window.BRB = new BRB();
})(window);
console.log(BRB.getBrowser());
console.log(BRB.getBrowser());
console.log(BRB.getBrowser());
console.log(BRB.getBrowser());
http://jsfiddle.net/5DheZ/
You should define the browser variable in another place:
(
function(window){
if(window.BRB) return;
var browser = null;
var BRB = function(){}
BRB.prototype.getBrowser = function(){
if(browser === null){
browser = 0;
}
return browser++;
}
window.BRB = new BRB();
})(window);
console.log(BRB.getBrowser());
console.log(BRB.getBrowser());
console.log(BRB.getBrowser());
console.log(BRB.getBrowser());
jsfiddle http://jsfiddle.net/5ByYR/1/
And if you are able to assign an object instead of function to getBrowser:
(
function(window){
if(window.BRB) return;
var BRB = function(){}
BRB.prototype.getBrowser = {
browser: null,
get: function() {
if(this.browser === null){
this.browser = 0;
}
return this.browser++;
}
}
window.BRB = new BRB();
})(window);
console.log(BRB.getBrowser.get());
console.log(BRB.getBrowser.get());
console.log(BRB.getBrowser.get());
console.log(BRB.getBrowser.get());
You probably intended for the getBrowser method to be an IIFE closure for the result:
BRB.prototype.getBrowser = (function(){
var browser = null;
return function(){
if(browser === null){
browser = 0;
}
return browser++;
}
})();
This way the browservariable is not reinitialized on each function call.
UPDATE
You could use a property instead of a variable scoped in a closure for the browser value:
BRB.prototype.getBrowser = function() {
if(!this.browser){
this.browser = 0;
}
return this.browser++;
}
I have a weird quirk in ActionScript. I need to pass the index to a callback function.
Here is my code
for (var i:Number = 0; ((i < arrayQueue.length) && uploading); i++)
{
var lid:ListItemData=ListItemData(arrayQueue[i]);
var localI:Number= new Number(i); // to copy?
var errorCallback:Function = function():void { OnUploadError(localI); };
var progressCallback:Function = function(e:ProgressEvent):void { lid.progress = e; OnUploadProgress(localI); };
var completeCallback:Function = function():void { Alert.show('callback'+localI.toString()); OnUploadComplete(localI); }; // localI == arrayQueue.length - 1 (when called)
Alert.show(localI.toString()); // shows current i as expected
lid.fileRef.addEventListener(Event.COMPLETE, completeCallback);
lid.fileRef.addEventListener(ProgressEvent.PROGRESS, progressCallback);
lid.fileRef.addEventListener(HTTPStatusEvent.HTTP_STATUS, errorCallback);
lid.fileRef.addEventListener(IOErrorEvent.IO_ERROR, errorCallback);
lid.fileRef.addEventListener(SecurityErrorEvent.SECURITY_ERROR, errorCallback);
lid.fileRef.upload(url, 'File');
}
Any idea on how to pass in the index to my callbacks? .upload does not block.
Passing additional parameters for your callbacks is possible via some kind of delegate function or closure. However it is often considered a bad practice. You may use event target property instead to determine your index based on FileReference.
Edit: here is a sample of using closures:
function getTimerClosure(ind : int) : Function {
return function(event : TimerEvent) {
trace(ind);
};
}
for (var i = 0; i < 10; i++) {
var tm : Timer = new Timer(100*i+1, 1);
tm.addEventListener(TimerEvent.TIMER, getTimerClosure(i));
tm.start();
}
This will continuously trace numbers from 0 to 9.
Edit2: here is a sample of creating a delegate based on a function closure:
function timerHandler(event : Event, ...rest) : void {
trace(event, rest);
}
function Delegate(scope : Object, func : Function, ...rest) : Function {
return function(...args) : void {
func.apply(scope, args.concat(rest));
}
}
var tm : Timer = new Timer(1000, 1);
tm.addEventListener(TimerEvent.TIMER, Delegate(this, this.timerHandler, 1, 2, 3));
tm.start();
However this is a bad approach since unsubscribing for such a listener is a hell pain. This in turn will probably cause some memory leakages, which will decrease overall performance of your application. So, use with caution!
Bottom line: if you know how to work with closures, use them - it is a wonderful thing! If you don't care about your application performance in a long perspective, use closures - it's simple!
But if you are unsure about closures, use a more conventional approach. E.g. in your case you could create a Dictionary that matches your FileReference objects to appropriate indices. Something like that:
var frToInd : Dictionary = new Dictionary(false);
// false here wouldn't prevent garbage collection of FileReference objects
for (var i : int = 0; i < 10; i++) {
// blah-blah stuff with `lib` objects
frToInd[lib.fileRef] = i;
// another weird stuff and subscription
}
function eventListener(event : Event) : void {
// in the event listener just look up target in the dictionary
if (frToInd[event.target]) {
var ind : int = frToInd[event.target];
} else {
// Shouldn't happen since all FileReferences should be in
// the Dictionary. But if this happens - it's an error.
}
}
-- Happy coding!
I have a weird quirk in ActionScript
It's not a quirk, it's variable scope. You should read this article: http://help.adobe.com/en_US/ActionScript/3.0_ProgrammingAS3/WS5b3ccc516d4fbf351e63e3d118a9b90204-7f9d.html#WS5b3ccc516d4fbf351e63e3d118a9b90204-7f8c
And you really shouldn't use anonymous, it just makes everything more confusing. You're actually making multiple copies of the same object.
If the arrayQueue is in scope, you can use this code to get the index:
GetArrayIndex(e.currentTarget);
function GetArrayIndex(object:Object):Number
{
for(var i:Number = 0; 0 < arrayQueue.length; i++)
{
if(object === arrayQueue[i])
return i;
}
}
You should consider using an uint for the index.