I am a complete newbie in PhaserJS. I am trying to develop a game in PhaserJS where tapping the screen once should make the user avatar move on the screen and double-tapping should make it jump. However, I am not being able to figure out how to catch the double tap event. I have seen this tutorial in their official documentation, but that didn't work. When I am putting this line
game.input.onTap.add(onTap, this);
in the
function create(){
.....
}
function, it is showing this error
Uncaught TypeError: Cannot read property 'add' of undefined
I am being able to detect single tap events using this code:
if(game.input.onTap && player.body.touching.down){
player.setVelocity(-530);
}
I've read another thread where the members have commented that to detect double click, one should start a timer and check both the clicks are coming within a threshold value. However, I think this is not a fool-proof method and there must be a better way of doing it. Can anyone please help?
Edit:
Relevant code:
<script type="text/javascript">
var width = 800;
var height = 600;
var config = {
type: Phaser.AUTO,
width: width,
height: height,
physics: {
default: 'arcade',
arcade: {
gravity: { y:300 },
debug: false
}
},
scene: {
preload: preload,
create: create,
update: update
}
};
var game = new Phaser.Game(config);
function preload (){
this.load.image("sky", "{% static 'task_scheduler/assets/sky.png' %}");
this.load.image("ground", "{% static 'task_scheduler/assets/platform.png' %}");
this.load.image("star", "{% static 'task_scheduler/assets/star.png' %}");
this.load.image("bomb", "{% static 'task_scheduler/assets/bomb.png' %}");
this.load.spritesheet("dude", "{% static 'task_scheduler/assets/dude.png' %}", {frameWidth: 32, frameHeight: 48});
}
var platforms;
var player;
var cursors;
var stars;
var bombs;
var score = 0;
var scoreText;
function create (){
//some other code here
//mouse and touch
this.input.onTap.add(onTap, this);
}
function onTap(pointer, doubleTap){
if (doubleTap){
player.setVelocityY(-530);
}else{
player.setVelocityX(160);
player.anims.play('right', true);
}
}
function create (){
//some other code here
//mouse and touch
this.input.onTap.add(onTap, this);
}
Here you should use game.input.onTap.add(onTap, this);
because this would reference to context from which create function is called. So, this wouldn't have property add and other properties that are available with game variable.
As far as the Double Tap is concerned that would be detected by phaser. I don't think you need to write any explicit code for that. onTap function would work just fine.
Related
I have been trying to get the per pixel drag and drop feature working using images with fabric.js like in example on their website: http://fabricjs.com/per-pixel-drag-drop/. I would like the object to be detected when a non transparent part is moused over but if I set perpixeltargetfind to true nothing is detected. I have tried for a while now and even copying the example verbatim while using my own images has not worked. Would really appreciate some help figuring out what I am doing wrong if anyone has experience using this. Thanks.
Here is a link to a js fiddle I have been using: http://jsfiddle.net/ahalbleib/bdofdbqg/
and the code:
var canvas =this.__canvas = new fabric.Canvas('c1',{hoverCursor: 'pointer',
selection: false});
var urls=['https://dl.dropboxusercontent.com/s/ix6mvv49wnx226a/Central-Richmon_clipped_rev_1.png?dl=0' ,
'https://dl.dropboxusercontent.com/s/jjp2l0kgdw8iitb/Laurel-Heights.png?dl=0',
'https://dl.dropboxusercontent.com/s/wdk02w40z1466g5/LoneMountain.png?dl=0',
'https://dl.dropboxusercontent.com/s/t6tnptndu2k22xr/OuterRichmond.png?dl=0',
'https://dl.dropboxusercontent.com/s/tv4rhwjc0nw35iz/Presidio-Heights.png?dl=0' ,
'https://dl.dropboxusercontent.com/s/ttbf390w2vdx4id/Inner-richmond.png?dl=0'];
for (var i=0; i<urls.length; i++){
fabric.Image.fromURL( urls[i], function(img){
img.perPixelTargetFind = true;
img.targetFindTolerance = 4;
img.hasControls = img.hasBorders = false;
canvas.add(img);
});
}
canvas.findTarget = (function (originalFn) {
return function () {
var target = originalFn.apply(this, arguments);
if (target) {
if (this._hoveredTarget !== target) {
canvas.fire('object:over', { target: target });
if (this._hoveredTarget) {
canvas.fire('object:out', { target: this._hoveredTarget });
}
this._hoveredTarget = target;
}
}
else if (this._hoveredTarget) {
canvas.fire('object:out', { target: this._hoveredTarget });
this._hoveredTarget = null;
}
return target;
};
})(canvas.findTarget);
};
init();
That is because you don't take images from your own server and you'll get a Security error about tainted canvas. You need to set crossOrigin: 'Anonymous' to images. I made you a jsFiddle
I'm a Vala/Gtk newbie and I'm trying to change the font size of a Gtk.Label, but I can't find a good way to do it.
I find out that I can use the markup like this :
var welcome_message = new Gtk.Label ("<span size='17000'>Hello</span>");
welcome_message.set_use_markup (true);
But it seems a little hackish.
What is the right way to do it ?
Thanks lethalman and nemequ.
I think it might help someone so here is a little example of how to use css with Vala.
using Gtk;
public class StyleApp1 : Gtk.Window
{
public StyleApp1()
{
this.title = "Style app example";
this.set_border_width (10);
this.set_position (Gtk.WindowPosition.CENTER);
this.set_default_size (350, 200);
this.destroy.connect (Gtk.main_quit);
var screen = this.get_screen ();
var css_provider = new Gtk.CssProvider();
string path = "styleapp1.css";
// test if the css file exist
if (FileUtils.test (path, FileTest.EXISTS))
{
try {
css_provider.load_from_path(path);
Gtk.StyleContext.add_provider_for_screen(screen, css_provider, Gtk.STYLE_PROVIDER_PRIORITY_USER);
} catch (Error e) {
error ("Cannot load CSS stylesheet: %s", e.message);
}
}
var box = new Gtk.Box (Gtk.Orientation.VERTICAL, 10);
this.add (box);
var label = new Gtk.Label ("Thank you");
box.add (label);
var label2 = new Gtk.Label ("Stackoverflow");
label2.get_style_context().add_class("my_class");
box.add (label2);
}
}
static int main(string[] args) {
Gtk.init(ref args);
StyleApp1 win = new StyleApp1();
win.show_all();
Gtk.main();
return 0;
}
and the styleapp1.css file :
GtkWindow {
font-size: 17px;
}
.my_class {
color: pink;
}
NB : if you use add_provider instead of add_provider_for_screen. You have to use add_provider for every widget that you want to customize.
You could try with css, I think lately this is the preferred way. Give your label a class, then load a css. If you are going to change the font size of a label, I bet you are also going to customize other things so the css may be useful for you.
In my update() function, I use pointerOver() to detect when the pointer is over a sprite. This normally works fine. However, if I happen to be dragging another sprite at the time, the pointerOver() function always returns false.
I thought I'd work around it by getting the location of the pointer and comparing it with the location and bounds of my sprite, but the pointer location is always (-1, -1).
Here's some example code to demonstrate the problem:
var game = new Phaser.Game( 800, 600, Phaser.AUTO, '', { preload: preload, create: create, update: update, render: render });
var triangle;
var square;
var isOver;
var pointerX;
var pointerY;
function preload()
{
game.load.image( 'triangle', 'assets/triangle.png' );
game.load.image( 'square', 'assets/square.png' );
}
function create()
{
triangle = game.add.sprite( 100, 100, "triangle" );
triangle.inputEnabled = true;
triangle.input.enableDrag( false, true );
square = game.add.sprite( 100, 200, "square" );
square.inputEnabled = true;
}
function update()
{
isOver = square.input.pointerOver() ? "Yes" : "No";
}
function render()
{
game.debug.text( "Mouse over square: " + isOver, 200, 100 );
game.debug.text( "Pointer: (" + game.input.pointer1.x + ", " + game.input.pointer1.y + ")", 200, 116 );
}
I found this post about using a sprite's input.priorityID: Phaser JS how to stop event Propagation(firing) from textButton.events.onInputDown event to game.input.onDown event?
Using the priorityID fixed it for when the triangle is on top the square and the triangle is not being dragged, but the problem remains when it's being dragged.
How do I detect when the pointer is over a sprite, even when I'm dragging another sprite?
Thanks.
I had a similar issue recently and I hope this will still be of help to you.
I found out that upon initiating a drag, the input on all sprites except for the one you're dragging becomes disabled. That probably happens internally and I couldn't find a way to override it.
What I did is the following: all the objects (in my case instances of Tile) I want to be draggable are held within a Board object, which in turn holds a reference to my Game state. In the Game state I have a flag dragIsActive. In the object class itself I have (TypeScript)
this.tileSprite.events.onDragStart.add(() => {
this.parentBoard.gameState.dragIsActive = true;
});
this.tileSprite.events.onDragStop.add(() => {
this.parentBoard.gameState.dragIsActive = false;
});
The equivalent JavaScript would be
this.tileSprite.events.onDragStart.add(function() {
this.parentBoard.gameState.dragIsActive = true;
});
this.tileSprite.events.onDragStop.add(function() {
this.parentBoard.gameState.dragIsActive = false;
});
called from the object's constructor.
In Game I have the following:
update() {
if (this.dragIsActive) {
var firstTile : Tile = this.game.input.activePointer.targetObject.sprite.parent;
this.board.tiles.forEach((t : Tile) => {
if (firstTile.tileSprite.overlap(t.tileSprite)) {
this.board.tilesToSlide.push(t);
}
});
this.board.tilesToSlide.forEach((tileToSlide) => {
// Do the processing on that array here.
});
}
}
JavaScript (just the forEach loop):
this.board.tiles.forEach(fucntion(t) {
if (firstTile.tileSprite.overlap(t.tileSprite)) {
this.board.tilesToSlide.push(t);
}
});
In my case the check is for two sprites overlapping, but in your case you can check if one just point of interest (e.g. the position of the sprite you're dragging) is inside the bounds of another sprite:
if (secondSprite.getBounds().containsPoint(firstSprite.position)) {
// This should be equivalent to pointerOver() while dragging something.
}
P.S. I hope you're aware that a sprite's position is at the top left of its bounding box unless explicitly set to something else. Set via sprite.anchor.set(x, y) - (0, 0) being top left (the default) and (1, 1) - bottom right.
you can also use this method to see if the point is contained within the sprite bounds.
if( Phaser.Rectangle.contains( sprite.body, this.game.input.x, this.game.input.y) ){
console.log('collide')
}
I am trying to perform a special action whenever the user double clicks any object located inside the canvas. I have read the docs and not found any mouse:dblclick-like event in the documentation. I tried doing something like:
fabric.util.addListener(fabric.document, 'dblclick', callback);
Which does trigger the dblclick event but does not give specific information about the actual object that is being clicked on the canvas.
Any ideas of the most FabricJS-y way of doing this?
The more elegant way is to override fabric.Canvas._initEventListeners to add the dblclick support
_initEventListeners: function() {
var self = this;
self.callSuper('_initEventListeners');
addListener(self.upperCanvasEl, 'dblclick', self._onDoubleClick);
}
_onDoubleClick: function(e) {
var self = this;
var target = self.findTarget(e);
self.fire('mouse:dblclick', {
target: target,
e: e
});
if (target && !self.isDrawingMode) {
// To unify the behavior, the object's double click event does not fire on drawing mode.
target.fire('object:dblclick', {
e: e
});
}
}
I've also developed a library to implement more events missed in fabricjs : https://github.com/mazong1123/fabric.ext
This is similar to #LeoCreer's answer but actually gets access to the targeted object
fabric.util.addListener(canvas.upperCanvasEl, 'dblclick', function (e) {
var target = canvas.findTarget(e);
});
The Correct way to add custom events to Fabric.js
window.fabric.util.addListener(canvas.upperCanvasEl, 'dblclick', function (event, self) {
yourFunction(event);
});
or use fabric.ext
I'm using this workaround:
var timer = 0;
canvas.item(0).on('mouseup', function() {
var d = new Date();
timer = d.getTime();
});
canvas.item(0).on('mousedown', function() {
var d = new Date();
if ((d.getTime() - timer) < 300) {
console.log('double click')
}
});
Here is a quick and easy way to add a double click event handler to Fabric JS -
Include following code snippet to your html file. Just ensure this is loaded after the main fabric.js library
<script type="text/javascript">
fabric = (function(f) { var nativeOn = f.on; var dblClickSubscribers = []; var nativeCanvas = f.Canvas; f.Canvas = (function(domId, options) { var canvasDomElement = document.getElementById(domId); var c = new nativeCanvas(domId, options); c.dblclick = function(handler) { dblClickSubscribers.push(handler) }; canvasDomElement.nextSibling.ondblclick = function(ev){ for(var i = 0; i < dblClickSubscribers.length; i++) { console.log(ev); dblClickSubscribers[i]({ e :ev }); } }; return c; }); return f; }(fabric));
</script>
Then add this code to listen a double click event:
canvas.dblclick(function(e) {
});
To get information about the actual object that is being clicked on the canvas, use following method -
canvas.getActiveObject();
eg.
canvas.dblclick(function(e) {
activeObject = canvas.getActiveObject();
});
I am late but now fabricjs has mousedblclick event.
Listed at: http://fabricjs.com/docs/fabric.Object.html
See all events:
http://fabricjs.com/events
I'm starting to work only with YUI3. I include component scrollView, but it did not work mousewheel event, in the options I have not found how to turn on it. I would appreciate any help.
var scrollView = new Y.ScrollView({
id: "scrollview",
srcNode: '.scrollview-item',
height: 375,
flick: {
minDistance: 10,
minVelocity: 0.3,
axis: "y"
}
});
scrollView.render();
I stumbled upon this as well, after some trial and error, I managed to get that working(note, that it is just plain scrolling, without an easing).
var DOM_MOUSE_SCROLL = 'DOMMouseScroll',
fixArgs = function(args) {
var a = Y.Array(args, 0, true), target;
if (Y.UA.gecko) {
a[0] = DOM_MOUSE_SCROLL;
// target = Y.config.win;
} else {
// target = Y.config.doc;
}
if (a.length < 3) {
// a[2] = target;
} else {
// a.splice(2, 0, target);
}
return a;
};
Y.Env.evt.plugins.mousewheel = {
on: function() {
return Y.Event._attach(fixArgs(arguments));
},
detach: function() {
return Y.Event.detach.apply(Y.Event, fixArgs(arguments));
}
};
This is the YUI mousewheel event, but it's changed a bit. The biggest issue was, that originally, either the window or document elements, which makes no sense(for example when you mousewheel over the #myelement you want that to be the returned target..)
Bellow is the code used to initialize the ScrollView and the function that handles the mousewheel event:
// ScrollView
var scrollView = new Y.ScrollView({
id: "scrollview",
srcNode: '#mycontainer',
height: 490,
flick: {
minDistance:10,
minVelocity:0.3,
axis: "y"
}
});
scrollView.render();
var content = scrollView.get("contentBox");
var scroll_modifier = 10; // 10px per Delta
var current_scroll_y, scroll_to;
content.on("mousewheel", function(e) {
// check whether this is the scrollview container
if ( e.currentTarget.hasClass('container') ) {
current_scroll_y = scrollView.get('scrollY');
scroll_to = current_scroll_y - ( scroll_modifier * e.wheelDelta );
// trying to scroll above top of the container - scroll to start
if ( scroll_to <= scrollView._minScrollY ) {
// in my case, this made the scrollbars plugin to move, but I'm quite sure it's important for other stuff as well :)
scrollView._uiDimensionsChange();
scrollView.scrollTo(0, scrollView._minScrollY);
} else if ( scroll_to >= scrollView._maxScrollY ) { // trying to scroll beneath the end of the container - scroll to end
scrollView._uiDimensionsChange();
scrollView.scrollTo(0, scrollView._maxScrollY);
} else { // otherwise just scroll to the calculated Y
scrollView._uiDimensionsChange();
scrollView.scrollTo(0, scroll_to);
};
// if we have scrollbars plugin, flash the scrollbar
if ( scrollView.scrollbars ) {
scrollView.scrollbars.flash();
};
// prevent browser default behavior on mouse scroll
e.preventDefault();
};
});
So basically that's how I managed to that, but my next challenge is to get the scrollbar work like regular scrollbar(when you drag it, the container should move correspondingly...)
Hope this helps anyone :)