Skip to content

Instantly share code, notes, and snippets.

@hyzhak
Last active December 17, 2015 04:59
Show Gist options
  • Save hyzhak/5554317 to your computer and use it in GitHub Desktop.
Save hyzhak/5554317 to your computer and use it in GitHub Desktop.
Implementation of cyclic behaviour on darlingjs game engine
var m = darlingjs.m('ngCyclic');
/**
* Marker for entity with cyclic pattern behaviour
*/
m.$c('ngCyclic', {
/**
* PatternWidth, if value <= 0.0 that pattern doesn't cyclic in that direction
*/
patternWidth: 0.0,
/**
* PatternHeight, if value <= 0.0 that pattern doesn't cyclic in that direction
*/
patternHeight: 0.0
});
/**
* Mark entity by component if it outside the ViewPort
*/
m.$c('ngMarkIfOutsideOfTheViewPortVertical2D', {
/**
* handler callback get $entity and top/bottom edge
*/
handler: null,
/**
* apply component-markers for any $entity that goes outside
* can be {string} name of component, or object with key, value
* where key is component name, value is config of component
*/
marker: null,
/**
* auto-remove current component
*/
autoRemove: true
});
/**
* Mark entity by component if it outside the ViewPort
*/
m.$c('ngMarkIfOutsideOfTheViewPortHorizontal2D', {
/**
* handler callback get $entity and top/bottom edge
*/
handler: null,
/**
* apply component-markers for any $entity that goes outside
* can be {string} name of component, or object with key, value
* where key is component name, value is config of component
*/
marker: null,
/**
* auto-remove current component
*/
autoRemove: true
});
/**
* Mark entity by component if it outside the ViewPort
*/
m.$c('ngMarkIfInsideOfTheViewPortVertical2D', {
/**
* handler callback get $entity and top/bottom edge
*/
handler: null,
/**
* apply component-markers for any $entity that goes inside
* can be {string} name of component, or object with key, value
* where key is component name, value is config of component
*/
marker: null,
/**
* auto-remove current component
*/
autoRemove: true
});
/**
* Mark entity by component if it outside the ViewPort
*/
m.$c('ngMarkIfInsideOfTheViewPortHorizontal2D', {
/**
* handler callback get $entity and top/bottom edge
*/
handler: null,
/**
* apply component-markers for any $entity that goes inside
* can be {string} name of component, or object with key, value
* where key is component name, value is config of component
*/
marker: null,
/**
* auto-remove current component
*/
autoRemove: true
});
/**
* System that implement 2D cyclic layer
*/
m.$s('ng2DCyclicLayer', {
$require: ['ngCyclic', 'ng2D'],
$addEntity: ['$entity', function($entity) {
if ($entity.ngCyclic.patternWidth) {
insideConfigHorizontal2D.minWidth = $entity.ngCyclic.patternWidth;
$entity.$add('ngMarkIfInsideOfTheViewPortHorizontal2D',
insideConfigHorizontal2D);
outsideConfigHorizontal2D.minWidth = $entity.ngCyclic.patternWidth;
$entity.$add('ngMarkIfOutsideOfTheViewPortHorizontal2D',
outsideConfigHorizontal2D);
}
if ($entity.ngCyclic.patternHeight) {
insideConfigVertical2D.minHeight = $entity.ngCyclic.patternHeight;
$entity.$add('ngMarkIfInsideOfTheViewPortVertical2D',
insideConfigVertical2D);
outsideConfigVertical2D.minHeight = $entity.ngCyclic.patternHeight;
$entity.$add('ngMarkIfOutsideOfTheViewPortVertical2D',
outsideConfigVertical2D);
}
}]
});
/**
* Define handler for entity that goes outside
*
* @private
* @ignore
* @type {{handler: Function}}
*/
var outsideConfigHorizontal2D = {
handler: function($entity, lowerEdge, higherEdge) {
if (lowerEdge) {
//if goes left place to right side
$entity.ng2D.x += $entity.ngCyclic.patternWidth;
} else if (higherEdge) {
//if goes right place to left side
$entity.ng2D.x -= $entity.ngCyclic.patternWidth;
}
//handle of returning to the viewport
if (!$entity.ngMarkIfInsideOfTheViewPortHorizontal2D) {
$entity.$add('ngMarkIfInsideOfTheViewPortHorizontal2D',
insideConfigHorizontal2D);
}
//stop handling of goes outside
$entity.$remove('ngMarkIfOutsideOfTheViewPortHorizontal2D');
}
};
/**
* Define handler for entity that goes outside
*
* @private
* @ignore
* @type {{handler: Function}}
*/
var outsideConfigVertical2D = {
handler: function($entity, lowerEdge, higherEdge) {
if (lowerEdge) {
$entity.ng2D.y += $entity.ngCyclic.patternHeight;
} else if (higherEdge) {
$entity.ng2D.y -= $entity.ngCyclic.patternHeight;
}
//handle of returning to the viewport
if (!$entity.ngMarkIfInsideOfTheViewPortVertical2D) {
$entity.$add('ngMarkIfInsideOfTheViewPortVertical2D',
insideConfigVertical2D);
}
//stop handling of goes outside
$entity.$remove('ngMarkIfOutsideOfTheViewPortVertical2D');
}
};
/**
* Start handle again if goes inside of viewPort
*
* @private
* @ignore
* @type {{marker: {ngMarkIfOutsideOfTheViewPortHorizontal2D: {handler: Function}}}}
*/
var insideConfigHorizontal2D = {
marker: {
ngMarkIfOutsideOfTheViewPortHorizontal2D: outsideConfigHorizontal2D
}
};
/**
* Start handle again if goes inside of viewPort
*
* @private
* @ignore
* @type {{marker: {ngMarkIfOutsideOfTheViewPortVertical2D: {handler: Function}}}}
*/
var insideConfigVertical2D = {
marker: {
ngMarkIfOutsideOfTheViewPortVertical2D: outsideConfigVertical2D
}
};
/**
* System that waits for entity goes outside of viewport in vertical dimension
* and handle that situation
*/
m.$s('ngMarkIfOutsideOfTheViewPortVertical2D', {
$require: ['ng2D', 'ngMarkIfOutsideOfTheViewPortVertical2D'],
$update: ['$entity', 'ng2DViewPort', function($entity, ng2DViewPort) {
var component = $entity.ngMarkIfOutsideOfTheViewPortVertical2D;
var viewPortHeight = component.viewPortHeight ||
0.5 * Math.max(ng2DViewPort.height, component.minHeight);
component.viewPortHeight = viewPortHeight;
outsideOf($entity,
'ngMarkIfOutsideOfTheViewPortVertical2D',
component,
$entity.ng2D.y,
ng2DViewPort.lookAt.y,
viewPortHeight
);
}]
});
/**
* System that waits for entity goes outside of viewport in horizontal dimension
* and handle that situation
*/
m.$s('ngMarkIfOutsideOfTheViewPortHorizontal2D', {
$require: ['ng2D', 'ngMarkIfOutsideOfTheViewPortHorizontal2D'],
$update: ['$entity', 'ng2DViewPort', function($entity, ng2DViewPort) {
var component = $entity.ngMarkIfOutsideOfTheViewPortHorizontal2D;
var viewPortWidth = component.viewPortWidth ||
0.5 * Math.max(ng2DViewPort.width, component.minWidth);
component.viewPortWidth = viewPortWidth;
outsideOf($entity,
'ngMarkIfOutsideOfTheViewPortVertical2D',
component,
$entity.ng2D.x,
ng2DViewPort.lookAt.x,
viewPortWidth
);
}]
});
/**
* System that waits for entity goes inside of viewport in vertical dimension
* and handle that situation
*/
m.$s('ngMarkIfInsideOfTheViewPortVertical2D', {
$require: ['ng2D', 'ngMarkIfInsideOfTheViewPortVertical2D'],
$update: ['$entity', 'ng2DViewPort', function($entity, ng2DViewPort) {
var component = $entity.ngMarkIfInsideOfTheViewPortVertical2D;
var viewPortHeight = component.viewPortHeight ||
0.5 * Math.max(ng2DViewPort.height, component.minHeight);
component.viewPortHeight = viewPortHeight;
insideOf($entity,
'ngMarkIfOutsideOfTheViewPortVertical',
component,
$entity.ng2D.y,
ng2DViewPort.lookAt.y,
viewPortHeight
);
}]
});
/**
* System that waits for entity goes inside of viewport in horizontal dimension
* and handle that situation
*/
m.$s('ngMarkIfInsideOfTheViewPortHorizontal2D', {
$require: ['ng2D', 'ngMarkIfInsideOfTheViewPortHorizontal2D'],
$update: ['$entity', 'ng2DViewPort', function($entity, ng2DViewPort) {
var component = $entity.ngMarkIfInsideOfTheViewPortHorizontal2D;
var viewPortWidth = component.viewPortWidth ||
0.5 * Math.max(ng2DViewPort.width, component.minWidth);
component.viewPortWidth = viewPortWidth;
insideOf($entity,
'ngMarkIfInsideOfTheViewPortHorizontal2D',
component,
$entity.ng2D.x,
ng2DViewPort.lookAt.x,
viewPortWidth
);
}]
});
/**
* check is $entity is outside of viewPort
*
* @private
* @ignore
*
* @param $entity
* @param componentName
* @param component
* @param componentPosition
* @param viewPortPosition
* @param viewPortSize
*/
function outsideOf($entity, componentName, component,
componentPosition, viewPortPosition, viewPortSize) {
var crossBottom = viewPortPosition + viewPortSize < componentPosition,
crossTop = componentPosition < viewPortPosition - viewPortSize;
if (crossTop || crossBottom) {
var handler = component.handler;
applyMarker($entity, component.marker);
if (component.autoRemove) {
$entity.$remove(componentName);
}
callIfHasHandler(handler, $entity, crossTop, crossBottom);
}
}
/**
* check is $entity is inside of viewPort
*
* @ignore
*
* @private
*
* @param $entity
* @param componentName
* @param component
* @param componentPosition
* @param viewPortPosition
* @param viewPortSize
*/
function insideOf($entity, componentName, component,
componentPosition, viewPortPosition, viewPortSize) {
var crossBottom = viewPortPosition + viewPortSize >= componentPosition,
crossTop = componentPosition >= viewPortPosition - viewPortSize;
if (crossTop && crossBottom) {
var handler = component.handler;
applyMarker($entity, component.marker);
if (component.autoRemove) {
$entity.$remove(componentName);
}
callIfHasHandler(handler, $entity, crossTop, crossBottom);
}
}
/**
* Execute handle if has it defined
*
* @private
* @ignore
* @param handler
* @param $entity
* @param lowerEdge
* @param higherEdge
*/
function callIfHasHandler(handler, $entity, lowerEdge, higherEdge) {
if (handler) {
handler($entity, lowerEdge, higherEdge);
}
}
/**
* apply markers from component
*
* @ignore
*
* @private
*
* @param $entity
* @param marker
*/
function applyMarker($entity, marker) {
if (darlingutil.isString(marker)) {
if (!$entity[marker]) {
$entity.$add(marker);
}
} else if (darlingutil.isObject(marker)) {
for (var key in marker) {
if (!$entity[key]) {
$entity.$add(key, marker[key]);
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment