Phaser 3: Matter physics detect collision - javascript

I am trying to detect when two object collide with each other, but I am not sure how to do it.
I have the following scene, which adds two physics images to the scene. I just need a way to detect when the two collide.
export class MainGame extends Scene {
public create() {
// Create the player
this.player = this.matter.add.image(300, 100, 'player')
// Create a pillar
let pillar = this.matter.add.image(500, 0, 'pillar1', null, { isStatic: true })
// Somehow detect collision between the two...
}
}
What I cannot figure out is how to detect when the player collides with the pillar. Everything I have searched for is how to do this using arcade physics, but I am using matter physics.
I cannot find any information on how to detect collision and then run a function.

After looking at examples here,
To call a function on collision, use the 'oncollisionStart' event like in this example.
this.matter.world.on('collisionstart', function (event, bodyA, bodyB) {
console.log('collision');
});

Another way to do this is to add the collision event callback to the object itself.
var paddle = this.matter.add.image(400, 550, 'assets', 'paddle.png');
var paddle.setOnCollide(pair => {
// pair.bodyA
// pair.bodyB
});
See the documentation under enableCollisionEventsPlugin(): https://photonstorm.github.io/phaser3-docs/Phaser.Physics.Matter.MatterPhysics.html and also what a pair looks like: https://brm.io/matter-js/docs/files/src_collision_Pair.js.html#
You can also listen for specific collisions.
var paddle.setOnCollideWith(ball, pair => {
// Do something
});

Related

HTML5 Canvas: Setting context on resize

I have a project using HTML5 Canvas (createjs) and I've had issues with spikes on text strokes, meaning I have to set the miterlimit of the 2d context. However, the parent (which I have no control over) scales the canvas when the window is resized, which obviously resets the canvas context.
Now, I want to avoid putting an onresize event inside the client - my first thought is just to use the createjs Ticker thus:
createjs.Ticker.addEventListener("tick", handleTick);
function handleTick(event) {
var ctx = canvas.getContext('2d');
ctx.miterLimit = 2;
}
Though this seems a little wasteful, is there a more efficient way of doing this, without using DOM events?
Your approach might work, but its definitely a hack, since you can't expect that context properties will be maintained, or that they won't be applied in the wrong place.
If you do want to patch the display list to update the context, you can use the "drawstart" event, which fires before the display list is drawn:
stage.on("drawstart", function(e) {
var ctx = stage.canvas.getContext("2d");
ctx.miterLimit = 2;
});
However if you want a better approach that is instance-specific, you can extend the Text class to append any context properties you want. Here is a quick example where miterLimit is stored and applied any time the text is drawn. In this example, you can create multiple instances and set different miter limits on them. Note that you might want to also support other properties such as lineJoin.
http://jsfiddle.net/cr4hmgqp/2/
(function() {
"use strict"
function MiterText(text, font, color, miterLimit) {
this.Text_constructor(text,font,color);
this.miterLimit = miterLimit;
};
var p = createjs.extend(MiterText, createjs.Text);
p.draw = function(ctx, ignoreCache) {
ctx.miterLimit = this.miterLimit;
if (this.Text_draw(ctx, ignoreCache)) { return true; }
return true;
};
p.clone = function() {
return this._cloneProps(new MiterText(this.text, this.font, this.color, this.miterLimit));
};
createjs.MiterText = createjs.promote(MiterText, "Text");
}());
Note that this issue should hopefully be fixed in the next version of EaselJS. Here is the tracked issue: https://github.com/CreateJS/EaselJS/issues/781
Cheers.

OL3 - How to know if drawing or interaction is started

In OpenLayer 3 I create a Draw interaction using the 'draw-feature' sample code they have on their website.
The only difference is that I supply my own condition function to the Draw constructor.
I would like to know if there is a way to determine within the condition function if the interaction/drawing has started?
Basically my goal is to change the behavior slightly so drawing a box is initiated with a CTRL-click rather than a click. But ending the drawing can be done with a simple click. So my approach would be something like this (in TypeScript)
var condition = (e: ol.MapBrowserEvent): boolean => {
return (myDraw.isStarted() ? true : e.originalEvent['ctrlKey']);
}
As far as I can see there's nothing like an isStarted() method in OL Draw class. If I had access to internal members I would resolve it by checking the length of myDraw.sketchCoords_ (haven't checked this but if 0 the drawing is not started yet). But I don't want to rely on private members, furthermore I'm using the minified version of OL where members names are transformed.
Try something like this:
var start_drawing = false;
function drawCondition(evt){
var ctrl = ol.events.condition.platformModifierKeyOnly(evt);
// this should be ol.events.condition.click
// but for some reason always returns false
var click = evt.type == 'pointerdown';
// to finish draw with click
if(start_drawing) return click;
// start drawing only with Ctrl + click
return ctrl && click;
}
// draw is a reference to ol.interaction.Draw
draw.on('drawstart', function(evt){
start_drawing = true;
});
draw.on('drawend', function(evt){
start_drawing = false;
});

cocos2d js 3.7 runScene issue

So i am porting my game from cocos2d c++ to js and sorted lots of js related differences already, but can not understand nor find online the solution to particular problem involving switching of the scenes with the cc.director.runScene().
So i have a complex game scene which i load like that:
cc.LoaderScene.preload(gameplay_resources, function () {
cc.director.runScene(new GameScene(level, epoch));
}, this);
Which takes stage and level params and returns the scene object which contains all the gameplay elements.
Fragment of Game scene looks like this:
var GameNode = cc.Node.extend({
levelID:null,
epoch:null,
platforms:null,
boardSize:null,
numberOfMovesLeft:null,
numberOfMovesAllowed:null,
sessionInfo:null,
ctor:function (levelID, epochID)
{
this._super();
this.levelID = levelID;
this.setEpoch(Epoch.epochForNumber(epochID));
this.platforms = [];
var self = this;
var gameplayUI = ccs.load(gameplayRes.GameplayUI, "res/");
this.addChild(gameplayUI.node);
var replayButton = gameplayUI.node.getChildByName("replay");
cc.assert(cc.sys.isObjectValid(replayButton), "Replay button not valid");
replayButton.addTouchEventListener(function (sender, type) {
if(type != ccui.Widget.TOUCH_ENDED) return;
cc.LoaderScene.preload(gameplay_resources, function () {
cc.director.runScene(new GameScene(self.levelID, self.epoch.ID));
}, this);
}, this);
return true;
}
//... Other methods
});
var GameScene = cc.Scene.extend({
ctor:function (levelID, epochID) {
this._super();
var gameNode = new GameNode(levelID, epochID);
this.addChild(gameNode);
}
});
All works fine in the end in the scene itself, but say if i change the scene by the same method to main menu, and then go to gameplay again, it seems as the 'new' game scene object has previous (supposed to be released) object`s values. So if i press 'Replay' button, it uses the old game scenes values as well.
I mean in C++ when you replace scenes, old scene`s memory is released by cocos engine. And if you go to that scene by creating new object - its new.
So my question is why is that happening i js? Maybe i do not know something about cocos2d js memory management so i need to do something extra to release old scene?
What i have ensured:
When i extend the engines classes all my added variables a null'ed and objects values are assigned in ctor's using this.value = ...; not to have static values for all objects in that way.
There are no children retaining the Gameplay scene (or it seems not to be) so i am assuming it should be released when i replace scene?
I am not using retain()/release(), and all children are added to the gamescene to be retained.
Any suggestions would be appreciated.
Cheers!
So i have solved it - i was using event manager therefore sending events and game scene with its children have been registered for some of them. I was assuming that eventManager retains nodes on a 'weak' basis, but it seems you have to call removeListeners() for each registered node in its onExit method to remove listeners manually. So now it seems to be working fine.

Unresponsive charCode statements

I am currently watching a bunch of introductory videos about using the canvas tag in HTML5 to create simple 2d games.
As I was following the video code - precisely - there was an error somewhere along the way. I tried to draw a rectangle in the canvas that would respond to the navigation buttons and move accordingly.
Here is the main game code:
function game() {
update();
render();
}
function update() {
//This is the code that I think is causing an error
if(keys[38]) player.y--;
if(keys[40]) player.y++;
if(keys[37]) player.x--;
if(keys[39]) player.x++;
}
function render() {
context.fillRect(player.x, player.y, player.width, player.height);
}
setInterval(function(){
game();
}, 1000/30);
The site runs perfectly fine when I load it, but it doesn't respond to the user clicks. Thanks for any help in advance.
Below is the keys array that adds an indexed value every-time a the navigation keys are pressed:
var keys = [];
window.addEventListener('keydown', function(e){
keys[e.keycode] = true;
}, false);
window.addEventListener('keyup', function(e){
delete keys[e.keycode]
}, false);
It seems like you're using the .keycode property, all lower case, in your event handlers. That property doesn't exist. Instead, try using the .keyCode property, with a capital C.
Using a nonexistent property returns undefined, so that would always execute keys[undefined] = true and keys[undefined] = false.
It doesnt respond to mouse interactions because you just assigned key codes. i assume you can control the rectangle with the arrow keys?
which framework are you using?

Running multiple jquery functions together

I know this question has been asked a lot of times, and I have seen the solutions to them on SO as well as other forums. Most of the times the solution suggested is to use Web Workers.
A game I'm developing requires me to run multiple functions at the same time. One of them is an on click function and other is a setInterval.
My approach at doing this can be seen here in this JSFiddle. (keep clicking in gray area to make player jump).
The whole idea is to continuously spawn those blue obstacles after an interval of 1000ms.
In my earlier approach the obstacles would spawn only when I click to make player jump, otherwise they wouldn't as expected.
How can I run such two functions side by side in order to achieve
the aim of spawning obstacles while also making player jump.
Secondly, what would be the best approach to carry out this process
in view of game development i.e attaining a certain level of
efficiency so that the animations are not affected.
Here is the HTML and Javascript code I've been working on:
<div class="container">
<div class="player"></div>
<div class="obstacle-container">
<div class="obstacle"></div>
</div>
</div>
$.fn.animator = function () {
var hit_list, done = false;
$(".container").click(function () {
if (!done) {
$(".obstacle").stop().animate({
left: "-=105%"
}, 10000, "linear");
$(".player").stop().animate({
bottom: "+=100px"
}, {
duration: 300,
complete: function () {
$(".player").animate({
bottom: "0"
}, 800);
},
step: function () {
//Test for collision
hit_list = $(".player").collision(".obstacle");
if (hit_list.length !== 0) {
$(function () {
if (!done) {
$(".container").append("Game Over!");
return false;
}
});
done = true;
}
}
});
}
});
};
$(function () {
$('.container').animator();
});
var interval = null;
$(".obstacle-container").obstacle_generator();
$.fn.obstacle_generator = function () {
interval = setInterval(function () {
$(".obstacle-container").append('<div class="obstacle"></div>');
}, 1000);
};
The generic concept you want to investigate is known as a game loop.
Almost every game will be built using some variant of this system:
Initialise game
Loop:
Check for user input
Update any actors
Draw the scene
Wait until it's time to repeat
A game running at 60 frames per second would perform this loop 60 times per second, or about once every 16ms.
Compared to your original question, you wouldn't need to be running multiple execution threads (running multiple functions together) to achieve this.
You are, in a way, already using a similar loop. jQuery maintains its own loop for updating animations. Where you are checking for collisions as part of your animation step, this is the sort of thing you would do in a hypothetical Player.update() method. You want to move this code out of jQuery, and in to a loop that you control.
Since you're running in a browser, the generic game loop becomes a bit more simple:
Check for user input - this can still be handled by event handlers, jQuery or not. Rather than directly changing properties like CSS position, though, they should act upon the state of the game object. For example, by changing the velocity of a Player object.
Update any actors - the important part of your loop. You should check how many milliseconds have passed since you last looped, since the browser doesn't guarantee that your code will be run exactly, or at least, 60 times per second. You should then loop through all of your game objects and update them all. In your Player.update() method, you would want to move it according to its velocity and the time passed, for example.
Draw the scene - if you're using DOM elements, then the browser handles drawing for you, of course. If you were using a <canvas> element, then you would do drawing yourself as part of the loop here.
Wait until it's time to repeat - this will be up to the browser to do for you, as part of normal setInterval/setTimeout behavior.
A simple game loop in JavaScript can look like this:
var gameObjects = [];
// Initialise game, create player objects etc, add them to the array
var gameLoop = function() {
// Loop through gameObjects, and call their respective update methods
};
setInterval(gameLoop, 16); // Try to run the loop 60 times per second.
In a complex game, you wouldn't have just a basic array to hold all game objects, this is just an basic example.

Categories

Resources