Smooth graphics in PhaserJS WebGL - javascript

Drawn graphics in a PhaserJS WebGL setup show these pixelated "stairs like" outlines as shown in the picture. How to get them smooth?
Example:
https://phaser.io/examples/v3/view/game-objects/graphics/primitives/line-gradient-stroked
var config = {
width: 800,
height: 600,
type: Phaser.WEBGL,
parent: 'phaser-example',
scene: {
create: create
}
};
var game = new Phaser.Game(config);
function create ()
{
var graphics = this.add.graphics();
graphics.lineGradientStyle(128, 0xff0000, 0xff0000, 0x0000ff, 0x0000ff, 1);
graphics.lineBetween(100, 100, 600, 500);
}

Related

How can I properly scale Phaser sprites?

I have a couple problems with sprite scaling which seem to work fine for other people.
So, this is my game:
As you can see there are 2 big problems: the images are really pixelated and texture bleeding.
This is my config:
var config = {
type: Phaser.AUTO,
parent: 'phaser-example',
width: '100%',
height: '100%',
mode: Phaser.Scale.RESIZE,
autoCenter:Phaser.Scale.CENTER_BOTH,
physics: {
default: 'arcade',
arcade: {
debug: true,
},
pixelArt:true,
render:{
antialias: false,
}
},
scene: {
preload: preload,
create: create,
update: update,
}
};
This is how I preload my assets:
function preload(){
this.load.image("tiles", "assets/turtle_wars_tiles.png");
this.load.tilemapTiledJSON("tutorial_map", "assets/tutorial_map.json");
//preloading player
this.load.spritesheet("player", "assets/characters.png", {
frameWidth: 26,
frameHeight: 36,
});
}
And this is how I create the tilemap:
const map = this.make.tilemap({ key: "tutorial_map", tileWidth:48,tileHeight:48 });
const tileset = map.addTilesetImage("turtle_wars_tiles", "tiles");
for (let i = 0; i < map.layers.length; i++) {
const layer = map.createStaticLayer(i, tileset,0,0)
layer.setDepth(i);
layer.setScale(5)
layer.setCollisionByProperty({ collides: true });
this.physics.add.collider(this.player.collider, layer).collideCallback = () =>{
this.player.collide()
};
}
I tried extruding my tile set of 16x16 tiles but it messes up my whole map and it only solves texture bleeding.
Any idea how can I solve this?
I just tried it on a small demo project, I think the solution is just, to edit your game - config to this (check code below).
Info: You added the correct properties, but only into the physics- Object. I belongs one level higher.
Like this it should work:
var config = {
type: Phaser.AUTO,
parent: 'phaser-example',
width: '100%',
height: '100%',
mode: Phaser.Scale.RESIZE,
autoCenter: Phaser.Scale.CENTER_BOTH,
physics: {
default: 'arcade',
arcade: {
debug: true,
},
},
pixelArt: false,
render: {
antialias: false,
}
...
};

Matter.js — How to prevent mouseConstraint to capture scroll events?

I am trying to enable scrolling into a page that contains a Matter.js canvas. I looked everywhere and the recommendation is to add removeEventListener so the mouse constraint won't hijack the scrolling event. Unfortunately, I am having no success. How can I enable a scroll?
Thank you in advance!
CodeSandbox
Code
import "./styles.css";
import Matter from "matter-js";
//Fetch our canvas
var canvas = document.getElementById("world");
//Setup Matter JS
var engine = Matter.Engine.create();
var world = engine.world;
var render = Matter.Render.create({
canvas: canvas,
engine: engine,
options: {
width: 500,
height: 500,
background: "transparent",
wireframes: false,
showAngleIndicator: false
}
});
//Add a ball
var ball = Matter.Bodies.circle(250, 250, 50, {
density: 0.04,
friction: 0.01,
frictionAir: 0.00001,
restitution: 0.8,
render: {
fillStyle: "#F35e66",
strokeStyle: "black",
lineWidth: 1
}
});
Matter.World.add(world, ball);
//Add a floor
var floor = Matter.Bodies.rectangle(250, 520, 500, 40, {
isStatic: true, //An immovable object
render: {
visible: false
}
});
Matter.World.add(world, floor);
//Make interactive
var mouseConstraint = Matter.MouseConstraint.create(engine, {
//Create Constraint
element: canvas,
constraint: {
render: {
visible: false
},
stiffness: 0.8
}
});
Matter.World.add(world, mouseConstraint);
// Why is this not working?
mouseConstraint.mouse.element.removeEventListener(
"mousewheel",
mouseConstraint.mouse.mousewheel
);
mouseConstraint.mouse.element.removeEventListener(
"DOMMouseScroll",
mouseConstraint.mouse.mousewheel
);
//Start the engine
Matter.Engine.run(engine);
Matter.Render.run(render);
It's a HTML issue. in index.html set the overflow to scroll

How to change the hitbox's shape of a image in Phaser 3?

I am creating a skateboarding game in JavaScript using the Phaser 3 framework. I have loaded the ramp image onto the screen, and I am currently using the "arcade" physics engine in my file. I know I have to use the matter physics engine to have a non-rectangular hitbox. How do I implement it with the triangular hitbox?
I have the .png image file of the ramp, along with the .json file for its hitbox.
I tried following a tutorial off of a website on how to create new hitboxes for the matter physics engine. Everything ended up falling off the screen and I couldn't figure out how to use the .json file for the ramp.
//Configurations for the physics engine
var physicsConfig = {
default: 'arcade',
arcade : {
debug : true //CHANGE THIS TO TRUE TO SEE LINES
}
}
//Game configurations
var config = {
type: Phaser.AUTO,
width: 1200 ,
height: 600,
physics: physicsConfig,
scene: {
preload: preload,
create: create,
update: update
}
}
//Start the game
var game = new Phaser.Game(config);
function preload() {
//Images
this.load.image('sky', 'archery_assets/images/sky.png');
this.load.image('ground', 'skate_assets/images/ground.png');
this.load.image('up_ramp', 'skate_assets/images/up_ramp.png')
//Spritesheets
this.load.spritesheet('player', 'skate_assets/spritesheets/skater.png', {frameWidth: 160, frameHeight: 160});
}
function create() {
//Background
skyImg = this.add.image(600, 300, 'sky');
//Scale the images
skyImg.setDisplaySize(1200, 600);
groundImg = this.add.image(600, 600, 'ground');
groundImg.setDisplaySize(1200, 250);
//Create the player
this.player = this.physics.add.sprite(100, 410, 'player');
this.player.setCollideWorldBounds(true);
//Rolling animation
this.anims.create({
key: 'move',
frames: this.anims.generateFrameNumbers('player', {start: 0, end: 3}),
frameRate: 16,
repeat: -1 // <-- keeps the rolling animation going
});
//Pushing animation
this.anims.create({
key: 'push',
frames: this.anims.generateFrameNumbers('player', {start: 4, end: 8}),
frameRate: 16
});
//Start and keep the rolling animation going
this.player.anims.play('move', true);
//Up ramp (1st ramp)
this.upRamp = this.physics.add.sprite(700, 330, 'up_ramp');
this.upRamp.setSize(320, 150).setOffset(0, 175);
this.upRamp.enableBody = true;
this.upRamp.setImmovable();
this.upRamp.body.angle = 150;
//Input
this.cursors = this.input.keyboard.createCursorKeys();
//Spacebar
this.spacebar = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.SPACE);
this.physics.add.collider(this.player, this.upRamp);
}
function update() {
//Set variable for push speed
var playerPushSpeed = 0;
//If the spacebar is pressed
if (this.spacebar.isDown) {
//Play the push animation
this.player.anims.play('push', true);
//Push speed
playerPushSpeed += 175;
//Move player
this.player.setVelocityX(playerPushSpeed);
}
if (this.upRamp.body.touching.left) {
this.player.setVelocityY(-200);
}
}
I need to know how to implement the .png image of the ramp along with its .json hitbox file, so that the player can properly "ride" up the ramp.
You'll have to use the physics: { default: 'matter' } in order to change the hitbox's shape. Use this code snippet for reference:
var config = {
type: Phaser.AUTO,
width: 800,
height: 600,
backgroundColor: '#000000',
parent: 'phaser-example',
physics: {
default: 'matter',
matter: {
gravity: {
y: 0
},
debug: true
}
},
scene: {
create: create
}
};
var game = new Phaser.Game(config);
function create ()
{
this.matter.world.setBounds();
this.matter.add.rectangle(200, 200, 200, 200, {
chamfer: { radius: [230, 0, 200, 0 ] }
});
this.matter.add.mouseSpring();
}
You could also use a PhysicsEditor, you can check this tutorial on how to implement different shapes.
EDIT:
You can use console.log(this.matter.bodies) to check other available shapes to implement.

How to detect collision between a graphic and a Sprite in phaser 3?

In my game I want to implement a range sort of feature that would restrict players area. I tried to draw a graphic circle and assign it physics properties. Then I setup collision detection between sprite and graphic. The code shows no errors but the collision is not detected.
I followed the following tutorial.
Graphic and Sprite
var config = {
type: Phaser.AUTO,
parent: 'phaser-example',
loader: {
baseURL: 'https://cdn.jsdelivr.net/gh/samme/phaser-examples-assets#v2.0.0/assets/',
crossOrigin: 'anonymous'
},
width: 800,
height: 600,
physics: {
default: 'arcade'
},
scene: {
preload: preload,
create: create,
update:update
}
};
var game = new Phaser.Game(config);
var player;
function preload()
{
this.load.image('dude', 'sprites/phaser-dude.png')
}
function create ()
{
player = this.physics.add.sprite(100, 100, 'dude');
player.setCollideWorldBounds(true);
var graphics = this.add.graphics({ fillStyle: { color: 0xff0000 } });
var circle = new Phaser.Geom.Circle(50, 50, 25);
graphics.fillCircleShape(circle);
this.physics.add.existing(graphics);
cursors = this.input.keyboard.createCursorKeys();
this.physics.add.collider(player, graphics);
}
function update()
{
if (cursors.left.isDown)
{
player.setVelocityX(-160);
}
else if (cursors.right.isDown)
{
player.setVelocityX(160);
}
else if (cursors.down.isDown)
{
player.setVelocityY(160);
}
else if (cursors.up.isDown)
{
player.setVelocityY(-160);
}
}
<script src="//cdn.jsdelivr.net/npm/phaser#3.17.0/dist/phaser.min.js"></script>

How to prevent sprites to be moved by mouse in Matter.js?

I am using Matter.js to build games. Starting from one of their examples: Pyramid, I started playing around. The code fro this specific example is as follows:
var Example = Example || {};
Example.pyramid = function() {
var Engine = Matter.Engine,
Render = Matter.Render,
Runner = Matter.Runner,
Composites = Matter.Composites,
MouseConstraint = Matter.MouseConstraint,
Mouse = Matter.Mouse,
World = Matter.World,
Bodies = Matter.Bodies;
// create engine
var engine = Engine.create(),
world = engine.world;
// create renderer
var render = Render.create({
element: document.body,
engine: engine,
options: {
width: 800,
height: 600,
showAngleIndicator: true
}
});
Render.run(render);
// create runner
var runner = Runner.create();
Runner.run(runner, engine);
// add bodies
var stack = Composites.pyramid(100, 258, 15, 10, 0, 0, function(x, y) {
return Bodies.rectangle(x, y, 40, 40);
});
World.add(world, [
stack,
// walls
Bodies.rectangle(400, 0, 800, 50, { isStatic: true }),
Bodies.rectangle(800, 300, 50, 600, { isStatic: true }),
Bodies.rectangle(0, 300, 50, 600, { isStatic: true }),
Bodies.rectangle(400, 605, 800, 50, { isStatic: true })
]);
// add mouse control
var mouse = Mouse.create(render.canvas),
mouseConstraint = MouseConstraint.create(engine, {
mouse: mouse,
constraint: {
stiffness: 0.2,
render: {
visible: false
}
}
});
World.add(world, mouseConstraint);
// keep the mouse in sync with rendering
render.mouse = mouse;
// fit the render viewport to the scene
Render.lookAt(render, {
min: { x: 0, y: 0 },
max: { x: 800, y: 600 }
});
// context for MatterTools.Demo
return {
engine: engine,
runner: runner,
render: render,
canvas: render.canvas,
stop: function() {
Matter.Render.stop(render);
Matter.Runner.stop(runner);
}
};
};
I am trying to modify the code in order to disallow the sprites in the pyramid to be moved by mouse. The part of code responsible for creating those objects is this:
// add bodies
var stack = Composites.pyramid(100, 258, 15, 10, 0, 0,
function(x, y) {
return Bodies.rectangle(x, y, 40, 40);
});
I have tried searching among the options that can be passed to Bodies.rectangle, but found nothing.
How to achieve this?
You can use the collisionFilter property to do this.
Collision filters use groups, masks and categories to determine which bodies collide. I'll ignore groups in this example. By default, bodies belong to category 1 and have all masked enabled:
const objValsToBase = (o, base) =>
Object.fromEntries(Object.entries(o)
.map(([k, v]) => [k, v.toString(base)]));
const circle = Matter.Bodies.circle(200, 100, 50);
// show decimal (base 10)
console.log(circle.collisionFilter);
// show bits (base 2)
console.log(objValsToBase(circle.collisionFilter, 2));
// show hex (base 16)
console.log(objValsToBase(circle.collisionFilter, 16));
<script src="https://cdnjs.cloudflare.com/ajax/libs/matter-js/0.18.0/matter.min.js"></script>
To get two bodies to stop colliding, you can set the category on one group to 0b10, which is 0x2 in hex and 2 in decimal, and set the mask on the other to turn off the 2 bit: 0b01. 0b01 also disables collisions you might have with other categories which are unused by default but might be used in your code sooner or later, so you might prefer 0xfffffd since (0xd).toString(2) => '1101'.
Below is the pyramid example code modified to disable mouse-pyramid collision. I also ran it through prettier and added a circle that collides with everything to show that the mouse still works on that:
var Engine = Matter.Engine,
Render = Matter.Render,
Runner = Matter.Runner,
Composites = Matter.Composites,
MouseConstraint = Matter.MouseConstraint,
Mouse = Matter.Mouse,
World = Matter.World,
Bodies = Matter.Bodies;
// create engine
var engine = Engine.create(),
world = engine.world;
// create renderer
var render = Render.create({
element: document.body,
engine: engine,
options: {
width: 800,
height: 600,
showAngleIndicator: true,
},
});
Render.run(render);
// create runner
var runner = Runner.create();
Runner.run(runner, engine);
// add bodies
var stack = Composites.pyramid(
100,
258,
15,
10,
0,
0,
function (x, y) {
return Bodies.rectangle(x, y, 40, 40, {
collisionFilter: {mask: 0xfffffd}, // <--
});
}
);
World.add(world, [
stack,
// walls
Bodies.circle(200, 100, 50),
Bodies.rectangle(400, 0, 800, 50, {isStatic: true}),
Bodies.rectangle(800, 300, 50, 600, {isStatic: true}),
Bodies.rectangle(0, 300, 50, 600, {isStatic: true}),
Bodies.rectangle(400, 605, 800, 50, {isStatic: true}),
]);
// add mouse control
var mouse = Mouse.create(render.canvas),
mouseConstraint = MouseConstraint.create(engine, {
mouse: mouse,
collisionFilter: {category: 0b10}, // <--
constraint: {
stiffness: 0.2,
render: {
visible: false,
},
},
});
World.add(world, mouseConstraint);
// keep the mouse in sync with rendering
render.mouse = mouse;
// fit the render viewport to the scene
Render.lookAt(render, {
min: {x: 0, y: 0},
max: {x: 800, y: 600},
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/matter-js/0.18.0/matter.min.js"></script>
See also:
How can I change the collisionFilter of an object so it can no longer interact with MouseConstraint (MatterJS)
How to get only a single body to move using Matter-js Mouse
How to prevent sprites to be moved by mouse in Matter.js? #681

Categories

Resources