Reputation: 315
I'm making a game that involves Tetris, but I'm having trouble with getting the blocks to land. For some reason, the blocks are stopping just short of the long, clear sprite that I'm using as the ground.
The Code I'm using is as follows:
In the Create method:
this.active = false;
this.activeBlock = null;
In the Update method:
if (this.active == false){
this.cube = Math.floor((Math.random()* 7));
this.testblock = this.physics.add.sprite(608, 32, this.blocks[this.cube]);
this.testblock.body.immovable = true;
this.testblock.body.allowGravity = false;
this.physics.add.collider(this.testblock, this.walls);
this.physics.add.collider(this.p1, this.testblock);
this.activeBlock = this.testblock;
this.active = true;
}
this.activeBlock.y = this.testblock.y + 0.1;
if(Phaser.Input.Keyboard.JustDown(this.keyA) && this.activeBlock.x != 352) {
this.activeBlock.x = this.activeBlock.x - 64;
}
if(Phaser.Input.Keyboard.JustDown(this.keyD) && this.activeBlock.x != 928) {
this.activeBlock.x = this.activeBlock.x + 64;
}
if (this.checkCollision(this.activeBlock, this.ground)){
this.activeBlock = null;
this.active = false;
}
And this is the checkCollision method I regularly use:
checkCollision(a, b) {
// simple AABB checking
if ((a.x < b.x + b.width &&
a.x + a.width > b.x &&
a.y < b.y + b.height &&
a.height + a.y > b.y) ) {
return true;
}
else {
return false;
}
}
I'm not sure what I did wrong. Can someone tell?
If it helps, I'm using Phaser 3 in VSCode employing arcade physics.
Update:
if (this.active == false){
this.cube = Math.floor((Math.random()* 7));
this.testblock = this.physics.add.sprite(608, 32, this.blocks[this.cube]);
this.testblock.body.immovable = true;
//this.testblock.body.allowGravity = false;
this.testblock.body.setGravity(0.1);
this.physics.add.collider(this.walls, this.testblock, this.callbackOnCollision, null, this);
this.physics.add.collider(this.p1, this.testblock);
this.activeBlock = this.testblock;
this.active = true;
}
//this.activeBlock.y = this.activeBlock.y + 0.1;
callbackOnCollision(floor, block){
this.physics.world.disable( block)
this.activeBlock = null;
this.active = false;
}
This is the code I added after reading the suggestion.
It did get the blocks closer to the ground, but it still didn't reach the bottom. Also, the new line to control the block's gravity didn't work, as the blocks are now just affected by normal gravity.
Did I mess up in adding the code?
Upvotes: 2
Views: 249
Reputation: 14785
The problem is, the checkCollision
function, since it only checks for hits by considering: x
,y
,width
and height
, it doesn't take other properties like for example origin
. (See in the example below, on the right)
I would recommend just using the builtin collider
function, of the physics engine, seen also in following example
btw.: moving the objects yourself, by setting
x
ory
, like thisthis.activeBlock.y = this.testblock.y + 0.1;
, will cause the collision system of the physics engine not to function correctly, if the gravity is to slow/fast just set a different value globaly in the config, or if you only need different gravity for some objects, set it directly, withsetGravityY
(link to documenation).
Short Demo:
document.body.style = 'margin:0;';
var config = {
type: Phaser.AUTO,
width: 536,
height: 183,
physics: {
default: 'arcade',
arcade: {
gravity:{ y: 100 },
debug: true
}
},
scene: {
create,
update
},
banner: false
};
let blockCustomCollision;
let floor;
let label;
let blockCollision2;
function create () {
label = this.add.text(10,10, 'Left physics collision /"
+ " Right custom collision (+ slow gravity)')
.setScale(1)
.setOrigin(0)
.setStyle({fontStyle: 'bold', fontFamily: 'Arial'});
let graphics = this.make.graphics();
graphics.fillStyle(0xffffff);
graphics.fillRect(0, 0, 10, 10);
graphics.generateTexture('img', 10, 10);
let blockCollision = this.physics.add.image(50, 10, 'img');
blockCustomCollision = this.physics.add.image(200, 10, 'img')
.setOrigin(1)
.setGravityY(-50);
this.add.text(90, 95, '<- Stop mid Air ')
.setScale(1)
.setOrigin(0, .5)
.setStyle({fontStyle: 'bold', fontFamily: 'Arial'});
blockCollision2 = this.physics.add.image(80, 10, 'img')
.setGravityY(100);
floor = this.add.rectangle(0, config.height-10, config.width, 20, 0xcdcdcd)
.setOrigin(0, 0);
this.physics.add.existing(floor, true);
this.physics.add.collider(floor, blockCollision, onCollision, null, this);
this.physics.add.collider(floor, blockCollision2, onCollision, null, this);
}
function onCollision(floor, block){
label.setText(' Executes on Collision');
this.physics.world.disable( block)
}
function update(){
if (checkCollision(blockCustomCollision, floor)){
this.physics.world.disable( blockCustomCollision)
}
if(blockCollision2.body.velocity.y > 1 && blockCollision2.body.y >= 90){
blockCollision2.body.setAllowGravity(false);
blockCollision2.body.setVelocity(0);
}
}
function checkCollision(a, b) {
// simple AABB checking
if ((a.x < b.x + b.width &&
a.x + a.width > b.x &&
a.y < b.y + b.height &&
a.height + a.y > b.y) ) {
return true;
}
else {
return false;
}
}
new Phaser.Game(config);
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/phaser.js"></script>
Update:
if you want to trigger function on collision, you can use the callback function fo the collider
function (parameter 3). The example above was updated, also
this.physics.add.collider(floor, blockCollision, callbackOnCollision);
Update 2:
Demo Code was update to show stopping in midair, with a defined
y
height in theupdate
function.
Upvotes: 2