I have create a simple animation screen using phaser and its rendering perfect and invoking all pointer events like pointerover, pointerout, pointerup and pointerdown on button btn as expected for browser. But when I render same game using WebView its rendering screen but its not invoking any pointer events. To confirm JavaScript is working I have tested by adding eventlistner on window and it was working.
var config = {
type: Phaser.CANVAS,
width: 650,
height: 900,
canvas: document.getElementById('myCustomCanvas'),
scale: {
mode: Phaser.Scale.FIT,
width: 750,
height: 1334,
parent: 'game'
},
physics: {
default: 'arcade',
arcade: {
gravity: { y: 0 }
}
},
scene : {
preload: function(){game.preload(this, 'asset_url');},
create: function(){game.create(this);},
update: function(){game.update(this);},
}
};
function game(config) {
this.start = function(config)
{
this.phaserGame = new Phaser.Game(config);
};
this.create = function()
{
var btn = this.scene.add.sprite(375, 665, 'btn');
btn.setInteractive()
.on('pointerover', () => {
console.log('pointerover');
})
.on('pointerout', () => {
console.log('pointerout');
})
.on('pointerdown', () => {
console.log('pointerdown');
})
.on('pointerup', () => {
console.log('pointerup');
});
};
}
I am using Xamarin Forms WebView to render game in mobile. My setting for WebView is as follow.
var webView = CreateNativeControl();
webView.SetWebViewClient(new HTMLGameWebClient(this));
webView.Settings.LightTouchEnabled = true;
webView.Settings.JavaScriptEnabled = true;
webView.Settings.DomStorageEnabled = true;
webView.Settings.MediaPlaybackRequiresUserGesture = false;
SetNativeControl(webView);
I also have conditional CSS which is used only if canvas is rendering in mobile.
canvas {
width: 100vw !important;
height: unset;
}
Thanks in advance for any helps or suggestions.
Related
I'm trying to fire a Phaser 3 event from DOM like I read on this example I found on internet:
"The game instance is accessible when you create the game, with something like
const game = new Phaser.Game(config);
And you can access everything from your desired scene from this instance
const scene = game.scene.keys.sceneName
And do something like
textareaElement.addEventListener("change", function(event) {
const text = textareaElement.value;
scene.updateGameTextFromTextarea(text);
});
This is my project config:
const config = {
// Phaser.AUTO, intenta usar WebGL y si el navegador no lo tiene, usa canva.
type: Phaser.AUTO,
parent: 'game-container',
width: 650,
height: 522,
scene: [MainScene],
scale: {
mode: Phaser.Scale.FIT
},
dom: {
createContainer: true
},
physics: {
default: 'arcade',
arcade: {
// debug: true,
// gravity: { y: 350 }
}
}
}
// Inicializacion del objeto
game = new Phaser.Game(config)`
I actually can access to game from console, but canĀ“t fire events.
const scene = game.scene.keys.MainScene
scene.greeting()
get:
Uncaught TypeError: Cannot read properties of undefined (reading 'greeting')
at :1:7
Code:
https://github.com/Neffer2/bull-rompecabezas.git
There are two issues:
The first issue is, that the name of the scene is gameScene not MainScene , this is the value from the constructor.
The second issue is the Scene/Game Instance is not populated right away, you would have to wait abit. I simulated this in the demo with the setTimeout, or you can also click the Button to call the same function from the scene.
Here a short Demo:
document.body.style = 'margin:0;';
class MainScene extends Phaser.Scene {
constructor(){
super('gameScene');
}
test(){
console.info('Hello From Scene');
}
}
var config = {
type: Phaser.AUTO,
width: 536,
height: 183,
physics: {
default: 'arcade',
arcade: {
gravity:{ y: 100 },
debug: true
}
},
scene: [ MainScene ],
banner: false
};
var game = new Phaser.Game(config);
setTimeout( () => game.scene.keys.gameScene.test(), 1000); // Wait for generation
document.querySelector('button').addEventListener('click', () => game.scene.keys.gameScene.test())
<script src="//cdn.jsdelivr.net/npm/phaser#3.55.2/dist/phaser.js"></script>
<button id="button"> Fire from the DOM </button><br>
I'm trying to disable Swiper JS (https://github.com/nolimits4web/swiper) on anything other than mobile using the destroy() function, but I get the error Uncaught TypeError: swiper.destroy is not a function.
I've tried various different things, but I can't get it to work.
import Swiper from 'swiper';
const ImageCarousel = $el => {
let swiper = Swiper;
let init = false;
function swiperMode() {
let mobile = window.matchMedia('(min-width: 0px) and (max-width: 768px)');
let tablet = window.matchMedia('(min-width: 769px) and (max-width: 1024px)');
let desktop = window.matchMedia('(min-width: 1025px)');
// Enable (for mobile)
if (mobile.matches) {
if (!init) {
init = true;
const MySwiper = new Swiper('.swiper-container-cta', {
direction: 'horizontal',
loop: false,
speed: 1000,
grabCursor: true,
watchSlidesProgress: false,
mousewheelControl: true,
keyboardControl: true,
width: 280,
spaceBetween: 16,
});
}
}
// Disable (for tablet)
else if (tablet.matches) {
swiper.destroy();
init = false;
}
// Disable (for desktop)
else if (desktop.matches) {
swiper.destroy();
init = false;
}
}
// console.log(swiper);
window.addEventListener('load', () => {
swiperMode();
});
window.addEventListener('resize', () => {
swiperMode();
});
};
export default ImageCarousel;
Did you try MySwiper.destroy(); instead of swiper.destroy();
so I'm writing on a electron application at the moment.
To make my application a bit smoother I created a BrowserWindow and loaded just the menubar and the background.
After that I added a BrowserView to show the acutal content.
Code for my BrowserWindow:
function createWindow() {
win = new BrowserWindow({
width: 800,
height: 600,
show: false,
frame: false,
webPreferences: {
nodeIntegration: true
}
})
win.loadFile(path.join(__dirname, 'views/index.pug'));
win.on('closed', () => {
win = null;
})
win.once('ready-to-show', () => {
win.show();
})
}
Code for my BrowserView:
function createViews() {
contentView = new BrowserView({ webPreferences: { nodeIntegration: true } });
win.addBrowserView(contentView);
contentView.setBounds({ x: 0, y: 23, width: win.getBounds().width, height: win.getBounds().height - 23 });
contentView.setAutoResize({ width: true, height: true });
contentView.webContents.loadFile(path.join(__dirname, 'views/imageGallery.pug'));
}
(If there is a spoiler function to hide the code: I'm sorry, I didn't find any)
Once I create the window it works like intended, also the normal resize via mouse-drag works perfectly.
Now my problem is, as soon as I maximize or unmaximize my window with the functions win.maximize() and win.unmaximize() my BrowserView gets resized. But the resize doesn't fit the BrowserWindow anymore. The content of the BrowserView is being cutted on the right side.
Window after being maximized:
Window after being unmaximized:
function createWindow() {
// Create the browser window.
const mainWindow = new BrowserWindow({ useContentSize: true });
const view = new BrowserView();
mainWindow.setBrowserView(view);
view.setBounds({ x: 0, y: 0, width: 800, height: 600 });
view.setAutoResize({ width: true, height: true });
view.webContents.loadURL("https://youtube.com");
}
I have a BrowserView inside a BrowserWindow (I need both indeed):
const { app, BrowserWindow, BrowserView } = require('electron');
app.on('ready', () => {
browserWindow = new BrowserWindow({ width: 800, height: 500, frame: false });
bv = new BrowserView({ webPreferences: { nodeIntegration: false }});
bv.setBounds({ x: 0, y: 30, width: 800, height: 470});
bv.webContents.loadURL('https://old.reddit.com');
browserWindow.setBrowserView(bv);
});
Doing a right-click on web pages doesn't do anything. How to enable right-click to have "Back", "Forward", "Reload", "Copy", "Paste", etc. as usual with Chrome?
Electron has some sample menus up on their docs located at https://electronjs.org/docs/api/menu
// Importing this adds a right-click menu with 'Inspect Element' option
const remote = require('remote')
const Menu = remote.require('menu')
const MenuItem = remote.require('menu-item')
let rightClickPosition = null
const menu = new Menu()
const menuItem = new MenuItem({
label: 'Inspect Element',
click: () => {
remote.getCurrentWindow().inspectElement(rightClickPosition.x, rightClickPosition.y)
}
})
menu.append(menuItem)
window.addEventListener('contextmenu', (e) => {
e.preventDefault()
rightClickPosition = {x: e.x, y: e.y}
menu.popup(remote.getCurrentWindow())
}, false)
Following this template you could set up custom roles like Back, Forward, Reload, etc. using custom javascript like this:
Back
const backMenuItem = new MenuItem({
label: 'Back',
click: () => {
window.history.back();
}
})
menu.append(backMenuItem)
Forward
const forwardMenuItem = new MenuItem({
label: 'Forward',
click: () => {
window.history.forward();
}
})
menu.append(forwardMenuItem)
I have the following minimal code, using Phaser.js 3.11.0 and Javascript ES6:
class Ship extends Phaser.Physics.Arcade.Image {
constructor(scene, x, y) {
super(scene, x, y, 'ship');
}
}
class Scene extends Phaser.Scene {
preload() {
this.load.image('ship', require('../assets/ship.png'));
}
create() {
this.ship1 = this.physics.add.existing(new Ship(this, 50, 70));
this.ship2 = this.physics.add.image(150, 70, 'ship');
}
}
new Phaser.Game({
type: Phaser.AUTO,
width: 200,
height: 150,
scene: Scene,
physics: {
default: 'arcade',
arcade: {
debug: true,
},
},
});
Using this.physics.add.existing(new Ship(this, 50, 70)) doesn't work: the sprite is not displayed, even if the debug bounding box is shown, with the right size.
Here is the rendered output:
If I don't use physics, the sprite displays correctly:
class Ship extends Phaser.GameObjects.Image {
...
}
class Scene extends Phaser.Scene {
...
create() {
this.ship1 = this.add.existing(new Ship(this, 50, 70));
...
}
}
What am I missing?
I was able to fix the problem by changing the create() method:
create() {
this.ship1 = this.add.existing(new Ship(this, 50, 70));
this.physics.world.enable([ this.ship1 ]);
}
Indeed, you can read in the API documentation, about the Phaser.Physics.Arcade.World#enable() method:
Calling factory methods encapsulates the creation of a Game Object and
the creation of its body at the same time. If you are creating custom
classes then you can pass them to this method to have their bodies
created.
Why don't you call the Arcade physics in the config main.js?ie:
const config = {
type: Phaser.AUTO,
width: window.innerWidth,
height: window.innerHeight,
physics: {
default: 'arcade',
arcade: {
debug: true
}
},
scene: [
BootScene,
LevelScene,
]
}