我如何使用 Phaser3 进行任务?
How can I do a quest with Phaser3?
我在 Phaser3 中搜索但没有找到任何可做的任务。我想做一个类似(例子)的任务。
去和 'Jerry' 谈谈。
拿起一把剑交给'Jerry'。
当你完成对话后,它会打开一扇门或其他东西,但我需要知道如何检查他是否与 PNJ 对话以及如何简单地设置任务
我找到了 rexquestplugin,但我不知道如何使用它,也没有网站或其他网站谈论 RexQuest
我现在的代码,如果你需要了解游戏的一些信息:
class SceneStart extends Phaser.Scene {
constructor() {
super({key: 'sceneStart'})
}
//Chargement des images
preload() {
this.load.plugin('rexquestplugin', 'https://raw.githubusercontent.com/rexrainbow/phaser3-rex-notes/master/dist/rexquestplugin.min.js', true);
this.load.image("player", "javascript/assets/player.png");
this.load.image("run1", "javascript/assets/run1.png");
this.load.image("run2", "javascript/assets/run2.png");
this.load.image("playerLeftRun1", "javascript/assets/playerLeftRun1.png");
this.load.image("playerLeftRun2", "javascript/assets/playerLeftRun2.png");
this.load.image("door", "javascript/assets/doors.png");
this.load.image("wall", "javascript/assets/walls.png");
/**
this.load.image("fireStart1", "javascript/assets/fireStart1.png");
this.load.image("fireStart2", "javascript/assets/fireStart2.png");
this.load.image("fireStart3", "javascript/assets/fireStart3.png");
*/
}
create() {
cursor = this.input.keyboard.createCursorKeys(); //touches des fleches
platforms = this.physics.add.staticGroup();
//Les animations
this.anims.create({
key : "playerWalkUp",
frames : [
{key : "run1"},
{key : "run2"}],
frameRate : 7,
repeat : 0
})
this.anims.create({
key : "playerWalkLeft",
frames : [
{key : "playerLeftRun1"},
{key : "playerLeftRun2"}],
frameRate : 7,
repeat : 0
})
/**
* this.anims.create({
* key : "fireMouvement",
* frames : [
* {key : "fireStart1"},
* {key : "fireStart2"},
* {key : "fireStart3"}],
* framerate : 7,
* repeat : -1
* })
*/
player = this.physics.add.sprite((w / 2), h, "player"); //joueur
player.setScale(1, 1);
player.body.setSize(30, 35);
wall1 = this.add.sprite(200, 146, "wall");
wall1.setScale(0.3);
wall2 = this.add.sprite(200, 445, "wall");
wall2.setFlip(false, true);
wall2.setScale(0.3);
wall3 = this.add.sprite((w - 200), 146, "wall");
wall3.setScale(0.3);
wall4 = this.add.sprite((w - 200), 445, "wall");
wall4.setFlip(false, true);
wall4.setScale(0.3);
doorStart = this.physics.add.staticSprite((w / 2), 28, "door"); //Porte principale
doorStart.setScale(0.3);
doorStart.body.setSize(300, 55);
doorStart.body.setOffset(-56, 472);
doorStart.rotation += -20.42;
platforms.add(wall1);
platforms.add(wall2);
platforms.add(wall3);
platforms.add(wall4);
this.physics.add.collider(platforms, player); //collision
player.setCollideWorldBounds(true); //collision avec la bordure
//Fonction de collision qui éxecute le code dedans quand la fonctions est appelé
function collision() {
this.scene.start("labyrintheStart");
}
this.physics.add.collider(player, doorStart, collision, undefined, this);
}
update() {
// Tous les mouvement sont controler par ce code
if (cursor.left.isDown){
player.setVelocityX(-200); //vitesse de deplacements
player.anims.play("playerWalkLeft", true); //animations du personnage
player.setFlip(false, false); //oriantation de l'image
} else if (cursor.right.isDown){
player.setVelocityX(200);
player.anims.play("playerWalkLeft", true);
player.setFlip(true, false);
} else if (cursor.up.isDown){
player.setVelocityY(-200);
player.anims.play("playerWalkUp", true);
player.setFlip(false, false);
} else if (cursor.down.isDown){
player.setVelocityY(200);
player.anims.play("playerWalkUp", true);
player.setFlip(false, true);
} else {
player.setVelocity(0);
player.setTexture("player");
}
if ((cursor.left.isDown && cursor.up.isDown) || (cursor.left.isDown && cursor.right.isDown) || (cursor.left.isDown && cursor.down.isDown) || (cursor.right.isDown && cursor.up.isDown) || (cursor.right.isDown && cursor.down.isDown)){
player.setVelocity(0);
player.setTexture("player");
}
//--------
}
}
class LabyrintheStart extends Phaser.Scene {
constructor() {
super({key: 'labyrintheStart'});
}
preload() {
this.load.plugin('rexquestplugin', 'https://raw.githubusercontent.com/rexrainbow/phaser3-rex-notes/master/dist/rexquestplugin.min.js', true);
this.load.image("player", "javascript/assets/player.png");
this.load.image("run1", "javascript/assets/run1.png");
this.load.image("run2", "javascript/assets/run2.png");
this.load.image("playerLeftRun1", "javascript/assets/playerLeftRun1.png");
this.load.image("playerLeftRun2", "javascript/assets/playerLeftRun2.png");
this.load.image("wall", "javascript/assets/walls.png");
this.load.image("door", "javascript/assets/doors.png");
}
create() {
cursor = this.input.keyboard.createCursorKeys();
platforms = this.physics.add.staticGroup();
this.anims.create({
key : "playerWalkUp",
frames : [
{key : "run1"},
{key : "run2"}],
frameRate : 7,
repeat : 0
})
this.anims.create({
key : "playerWalkLeft",
frames : [
{key : "playerLeftRun1"},
{key : "playerLeftRun2"}],
frameRate : 7,
repeat : 0
})
player = this.physics.add.sprite(34, h, "player");
player.setScale(1, 1);
player.body.setSize(30, 35);
wall1 = this.add.sprite(9, h - 126, "wall");
wall1.setScale(0.05);
doorDroite = this.physics.add.staticSprite(w - 35, (h / 2) - 20, "door");
doorDroite.setSize(18, 80);
doorDroite.setScale(0.08);
platforms.add(wall1);
this.physics.add.collider(platforms, player);
player.setCollideWorldBounds(true);
function collisionDroite() {
this.scene.start("labyrintheDeux");
}
this.physics.add.collider(player, doorDroite, collisionDroite, undefined, this);
}
update() {
if (cursor.left.isDown){
player.setVelocityX(-200);
player.anims.play("playerWalkLeft", true);
player.setFlip(false, false);
} else if (cursor.right.isDown){
player.setVelocityX(200);
player.anims.play("playerWalkLeft", true);
player.setFlip(true, false);
} else if (cursor.up.isDown){
player.setVelocityY(-200);
player.anims.play("playerWalkUp", true);
player.setFlip(false, false);
} else if (cursor.down.isDown){
player.setVelocityY(200);
player.anims.play("playerWalkUp", true);
player.setFlip(false, true);
} else {
player.setVelocity(0);
player.setTexture("player");
}
if ((cursor.left.isDown && cursor.up.isDown) || (cursor.left.isDown && cursor.right.isDown) || (cursor.left.isDown && cursor.down.isDown) || (cursor.right.isDown && cursor.up.isDown) || (cursor.right.isDown && cursor.down.isDown)){
player.setVelocity(0);
player.setTexture("player");
}
}
}
/**
class LabyrintheDeux extends Phaser.Scene {
constructor() {
super({key: "labyrintheDeux"});
}
preload() {
this.load.plugin('rexquestplugin', 'https://raw.githubusercontent.com/rexrainbow/phaser3-rex-notes/master/dist/rexquestplugin.min.js', true);
this.load.image("player", "javascript/assets/player.png");
this.load.image("run1", "javascript/assets/run1.png");
this.load.image("run2", "javascript/assets/run2.png");
this.load.image("playerLeftRun1", "javascript/assets/playerLeftRun1.png");
this.load.image("playerLeftRun2", "javascript/assets/playerLeftRun2.png");
this.load.image("wall", "javascript/assets/wall.png");
this.load.image("doorStart", "javascript/assets/door.png");
}
create() {
cursor = this.input.keyboard.createCursorKeys();
platforms = this.physics.add.staticGroup();
this.anims.create({
key : "playerWalkUp",
frames : [
{key : "run1"},
{key : "run2"}],
frameRate : 7,
repeat : 0
})
this.anims.create({
key : "playerWalkLeft",
frames : [
{key : "playerLeftRun1"},
{key : "playerLeftRun2"}],
frameRate : 7,
repeat : 0
})
player = this.physics.add.sprite((w - w) + 70, h, "player");
player.setScale(1, 1);
player.body.setSize(30, 35);
wall = this.add.sprite((w - w) + 6, h - 126, "wall");
door = this.physics.add.staticSprite((w / 2) - 20, 30, "door");
door.rotation += 20.42;
door.setSize(50, 10);
platforms.add(wall);
this.physics.add.collider(platforms, player);
player.setCollideWorldBounds(true);
function collision() {
this.scene.start("");
}
this.physics.add.collider(player, door, collision, undefined, this);
}
update() {
if (cursor.left.isDown){
player.setVelocityX(-200);
player.anims.play("playerWalkLeft", true);
player.setFlip(false, false);
} else if (cursor.right.isDown){
player.setVelocityX(200);
player.anims.play("playerWalkLeft", true);
player.setFlip(true, false);
} else if (cursor.up.isDown){
player.setVelocityY(-200);
player.anims.play("playerWalkUp", true);
player.setFlip(false, false);
} else if (cursor.down.isDown){
player.setVelocityY(200);
player.anims.play("playerWalkUp", true);
player.setFlip(false, true);
} else {
player.setVelocity(0);
player.setTexture("player");
}
if ((cursor.left.isDown && cursor.up.isDown) || (cursor.left.isDown && cursor.right.isDown) || (cursor.left.isDown && cursor.down.isDown) || (cursor.right.isDown && cursor.up.isDown) || (cursor.right.isDown && cursor.down.isDown)){
player.setVelocity(0);
player.setTexture("player");
}
}
}
*/
var config = {
type: Phaser.AUTO,
width: window.innerWidth - 20,
height: window.innerHeight - 100,
backgroundColor: "#FFFFFF", //#FFFFFF
physics: {
default : "arcade",
arcade : {
debug : false,
}
},
scene: [SceneStart, LabyrintheStart /**, LabyrintheDeux*/]
};
let game = new Phaser.Game(config);
var h = window.innerHeight;
var w = window.innerWidth;
var platforms;
var cursor;
var player;
var doorGauche;
var doorDroite;
var doorUp;
var doorStart;
var wall1;
var wall2;
var wall3;
var wall4;
// A rajouter plus tard
/**
*
function collisionUp() {
this.scene.start("labyrintheTrois");
}
*
* this.physics.add.collider(player, doorGauche, collisionUp, undefined, this);
*
* doorUp = this.physics.add.staticSprite((w / 2) - 20, 8, "door");
* doorUp.setScale(0.08);
* doorUp.setSize(80, 18);
* doorUp.setOffset(55, 491);
* doorUp.rotation += -20.42;
*/
我从未真正使用过 rexquestplugin
,但听起来很有趣,所以我检查了一下。
Here the Documentation(不详细,但可能有助于清理下面的代码)
The Demo 文档站点上帮助我更好地理解了用法,但不是很清楚。
所以我写了一个小的演示应用程序,来回答这个问题“我将如何使用插件解决你的问题?”
(btw.: 你可以执行下面的代码片段)
// This is the Quest csv File as Array (just for the demo)
// load the csv from a file, if it is bigger
var questString = [
['type', 'key', 'next', 'end'], // Line 1: HEADER
['q', 'Go talk to Jerry', '', ''], // Line 2: Quest1 Part1
['', '', 'Get Sword', ''], // Line 3: First Option for Quest1 Part1 (there could be several option per Quest)
['q', 'Get Sword', '', ''], // Line 4: Quest1 Part2
['', '', 'Give it to Jerry', ''], // Line 5: First Option for Quest1 Part2
['q', 'Give it to Jerry', '', ''], // Line 6: Quest1 Part3
['','', 'DONE', '', ''], // Line 7: First Option for Quest1 Part3
['q', 'DONE', '', '1'], // Line 8: QUEST End
].map(x => x.join(',')).join('\n');
// This is the DemoScene
// Just very simple way to define a Scene, without Class (just for the demo)
var DemoScene = {
preload() {
// Load Plugin
this.load.plugin('rexquestplugin', 'https://raw.githubusercontent.com/rexrainbow/phaser3-rex-notes/master/dist/rexquestplugin.min.js', true);
},
extend: {
// Collision Callback for Jerry
handleMeeting(player, jerry){
if(player._currentQuest ){
// Get all options (in this case only one)
console.info(player._currentQuest.currentQuest)
let options = player._currentQuest.currentQuest.options;
if(options[0].next == 'Get Sword'){
this.sword.visible = true;
player._currentQuest.manager.getNextQuestion(options[0].next);
} else if(options[0].next == 'DONE'){
this.door.fillColor = 0x00ff00;
player._currentQuest.manager.getNextQuestion(options[0].next);
}
}
},
// Collision Callback for Sword
handleSword(player, sword){
if(player._currentQuest ){
sword.destroy();
// Get all options (in this case only one)
let options = player._currentQuest.currentQuest.options;
if(options[0].next == 'Give it to Jerry'){
sword.visible = true;
player._currentQuest.manager.getNextQuestion(options[0].next);
}
}
},
// Collision Check Callback for Sword
checkSwordStatus(player, sword){
// if the sword is visible collide
return sword.visible;
},
// Collision Check Callback for door
checkDoorStatus(player, door){
// if the door is red collide
return door.fillColor == 0xff0000;
}
},
create() {
// Player
this.player = this.add.circle(30, 30, 10, 0xffffff).setOrigin(.5);
this.cursor = this.input.keyboard.createCursorKeys();
this.physics.add.existing(this.player);
this.player.body.setCollideWorldBounds(true);
this.player.body.setCircle(10);
this.player.setDepth(2);
// Jerry
this.jerry = this.add.circle(160, 30, 10, 0x0000ff).setOrigin(.5);
this.physics.add.existing(this.jerry, true);
this.jerry.body.setCircle(10);
// Sword
this.sword = this.add.isotriangle(50, 100, 20, 40, false, 0xffe31f, 0xf2a022, 0xf8d80b).setOrigin(.5);
this.physics.add.existing(this.sword, true);
this.sword.visible = false;
// Door
this.door = this.add.rectangle(190, 0, 20, 200, 0xff0000).setOrigin(0);
this.physics.add.existing(this.door, true);
// colliders
this.physics.add.collider(this.player, this.jerry, this.handleMeeting, undefined, this);
this.physics.add.collider(this.player, this.sword, this.handleSword, this.checkSwordStatus, this);
this.physics.add.collider(this.player, this.door, undefined, this.checkDoorStatus, this );
// Quest List
this.print = this.add.text(380, 180, '', { fontSize: '12px', align: 'right' }).setOrigin(1);
// QUEST SETUP
this.plugins.get('rexquestplugin').add({
questions: questString,
quest: true
})
// EVENT executes on new Quest/Question
.on('quest', function (currentQuest, manager, quest) {
// QUEST has ended
if (currentQuest.end === 1) {
manager.setData('endAt', currentQuest.key);
manager.emit('complete', manager, quest);
} else {
// NEXT Step in the Quest
if(this.player._currentQuest){
this.print.text = this.print.text + 'done\n';
}
this.print.text += `${currentQuest.key}...`;
this.player._currentQuest = { currentQuest, manager}
}
}, this)
// Is emited from `on('quest', ... )`
.on('complete', function (manager, quest) {
delete this.player._currentQuest;
this.print.text = this.print.text + 'done\n';
this.print.text += `\nDoor is unlocked!`;
}, this)
// Get First Quest
.getNextQuestion();
},
update() {
// only player movement
let body = this.player.body;
if (this.cursor.left.isDown) {
body.setVelocityX(-200);
} else if (this.cursor.right.isDown) {
body.setVelocityX(200);
} else if (this.cursor.up.isDown) {
body.setVelocityY(-200);
} else if (this.cursor.down.isDown) {
body.setVelocityY(200);
} else {
body.setVelocity(0);
}
}
}
var config = {
type: Phaser.AUTO,
width: 400,
height: 200,
scene: [DemoScene],
physics: {
default : "arcade"
}
};
var game = new Phaser.Game(config);
<script src="https://cdn.jsdelivr.net/npm/phaser@3.55.2/dist/phaser.js"></script>
播放器 - 使用光标键移动
blue: 是 Jerry
白:是玩家
黄色:是剑
red/gree: closed/open门
One part that was not really clear to me, was the csv
for the quest, here is my interpretation, of the columns:
'type'
column
- if set to
'q'
it is a quest/question
- if empty
''
it is a option
'key'
column
- if is set it is the name of the quest/question
- if empty
''
it is a option
'next'
column
- if it is set this is the name of the next quest/question
- if empty
''
it is a quest
'end'
column
- if is is set it ends the quest/question (in this example it has to be set to
1
)
- if empty
''
, it is not the last quest/question
更新:
根据您正在制作的任务/游戏的大小,框架 ink https://www.inklestudios.com/ink/ 可能是一个选项。它很容易编写,有令人难以置信的文档,但内容非常广泛。
我在 Phaser3 中搜索但没有找到任何可做的任务。我想做一个类似(例子)的任务。
去和 'Jerry' 谈谈。
拿起一把剑交给'Jerry'。
当你完成对话后,它会打开一扇门或其他东西,但我需要知道如何检查他是否与 PNJ 对话以及如何简单地设置任务
我找到了 rexquestplugin,但我不知道如何使用它,也没有网站或其他网站谈论 RexQuest
我现在的代码,如果你需要了解游戏的一些信息:
class SceneStart extends Phaser.Scene {
constructor() {
super({key: 'sceneStart'})
}
//Chargement des images
preload() {
this.load.plugin('rexquestplugin', 'https://raw.githubusercontent.com/rexrainbow/phaser3-rex-notes/master/dist/rexquestplugin.min.js', true);
this.load.image("player", "javascript/assets/player.png");
this.load.image("run1", "javascript/assets/run1.png");
this.load.image("run2", "javascript/assets/run2.png");
this.load.image("playerLeftRun1", "javascript/assets/playerLeftRun1.png");
this.load.image("playerLeftRun2", "javascript/assets/playerLeftRun2.png");
this.load.image("door", "javascript/assets/doors.png");
this.load.image("wall", "javascript/assets/walls.png");
/**
this.load.image("fireStart1", "javascript/assets/fireStart1.png");
this.load.image("fireStart2", "javascript/assets/fireStart2.png");
this.load.image("fireStart3", "javascript/assets/fireStart3.png");
*/
}
create() {
cursor = this.input.keyboard.createCursorKeys(); //touches des fleches
platforms = this.physics.add.staticGroup();
//Les animations
this.anims.create({
key : "playerWalkUp",
frames : [
{key : "run1"},
{key : "run2"}],
frameRate : 7,
repeat : 0
})
this.anims.create({
key : "playerWalkLeft",
frames : [
{key : "playerLeftRun1"},
{key : "playerLeftRun2"}],
frameRate : 7,
repeat : 0
})
/**
* this.anims.create({
* key : "fireMouvement",
* frames : [
* {key : "fireStart1"},
* {key : "fireStart2"},
* {key : "fireStart3"}],
* framerate : 7,
* repeat : -1
* })
*/
player = this.physics.add.sprite((w / 2), h, "player"); //joueur
player.setScale(1, 1);
player.body.setSize(30, 35);
wall1 = this.add.sprite(200, 146, "wall");
wall1.setScale(0.3);
wall2 = this.add.sprite(200, 445, "wall");
wall2.setFlip(false, true);
wall2.setScale(0.3);
wall3 = this.add.sprite((w - 200), 146, "wall");
wall3.setScale(0.3);
wall4 = this.add.sprite((w - 200), 445, "wall");
wall4.setFlip(false, true);
wall4.setScale(0.3);
doorStart = this.physics.add.staticSprite((w / 2), 28, "door"); //Porte principale
doorStart.setScale(0.3);
doorStart.body.setSize(300, 55);
doorStart.body.setOffset(-56, 472);
doorStart.rotation += -20.42;
platforms.add(wall1);
platforms.add(wall2);
platforms.add(wall3);
platforms.add(wall4);
this.physics.add.collider(platforms, player); //collision
player.setCollideWorldBounds(true); //collision avec la bordure
//Fonction de collision qui éxecute le code dedans quand la fonctions est appelé
function collision() {
this.scene.start("labyrintheStart");
}
this.physics.add.collider(player, doorStart, collision, undefined, this);
}
update() {
// Tous les mouvement sont controler par ce code
if (cursor.left.isDown){
player.setVelocityX(-200); //vitesse de deplacements
player.anims.play("playerWalkLeft", true); //animations du personnage
player.setFlip(false, false); //oriantation de l'image
} else if (cursor.right.isDown){
player.setVelocityX(200);
player.anims.play("playerWalkLeft", true);
player.setFlip(true, false);
} else if (cursor.up.isDown){
player.setVelocityY(-200);
player.anims.play("playerWalkUp", true);
player.setFlip(false, false);
} else if (cursor.down.isDown){
player.setVelocityY(200);
player.anims.play("playerWalkUp", true);
player.setFlip(false, true);
} else {
player.setVelocity(0);
player.setTexture("player");
}
if ((cursor.left.isDown && cursor.up.isDown) || (cursor.left.isDown && cursor.right.isDown) || (cursor.left.isDown && cursor.down.isDown) || (cursor.right.isDown && cursor.up.isDown) || (cursor.right.isDown && cursor.down.isDown)){
player.setVelocity(0);
player.setTexture("player");
}
//--------
}
}
class LabyrintheStart extends Phaser.Scene {
constructor() {
super({key: 'labyrintheStart'});
}
preload() {
this.load.plugin('rexquestplugin', 'https://raw.githubusercontent.com/rexrainbow/phaser3-rex-notes/master/dist/rexquestplugin.min.js', true);
this.load.image("player", "javascript/assets/player.png");
this.load.image("run1", "javascript/assets/run1.png");
this.load.image("run2", "javascript/assets/run2.png");
this.load.image("playerLeftRun1", "javascript/assets/playerLeftRun1.png");
this.load.image("playerLeftRun2", "javascript/assets/playerLeftRun2.png");
this.load.image("wall", "javascript/assets/walls.png");
this.load.image("door", "javascript/assets/doors.png");
}
create() {
cursor = this.input.keyboard.createCursorKeys();
platforms = this.physics.add.staticGroup();
this.anims.create({
key : "playerWalkUp",
frames : [
{key : "run1"},
{key : "run2"}],
frameRate : 7,
repeat : 0
})
this.anims.create({
key : "playerWalkLeft",
frames : [
{key : "playerLeftRun1"},
{key : "playerLeftRun2"}],
frameRate : 7,
repeat : 0
})
player = this.physics.add.sprite(34, h, "player");
player.setScale(1, 1);
player.body.setSize(30, 35);
wall1 = this.add.sprite(9, h - 126, "wall");
wall1.setScale(0.05);
doorDroite = this.physics.add.staticSprite(w - 35, (h / 2) - 20, "door");
doorDroite.setSize(18, 80);
doorDroite.setScale(0.08);
platforms.add(wall1);
this.physics.add.collider(platforms, player);
player.setCollideWorldBounds(true);
function collisionDroite() {
this.scene.start("labyrintheDeux");
}
this.physics.add.collider(player, doorDroite, collisionDroite, undefined, this);
}
update() {
if (cursor.left.isDown){
player.setVelocityX(-200);
player.anims.play("playerWalkLeft", true);
player.setFlip(false, false);
} else if (cursor.right.isDown){
player.setVelocityX(200);
player.anims.play("playerWalkLeft", true);
player.setFlip(true, false);
} else if (cursor.up.isDown){
player.setVelocityY(-200);
player.anims.play("playerWalkUp", true);
player.setFlip(false, false);
} else if (cursor.down.isDown){
player.setVelocityY(200);
player.anims.play("playerWalkUp", true);
player.setFlip(false, true);
} else {
player.setVelocity(0);
player.setTexture("player");
}
if ((cursor.left.isDown && cursor.up.isDown) || (cursor.left.isDown && cursor.right.isDown) || (cursor.left.isDown && cursor.down.isDown) || (cursor.right.isDown && cursor.up.isDown) || (cursor.right.isDown && cursor.down.isDown)){
player.setVelocity(0);
player.setTexture("player");
}
}
}
/**
class LabyrintheDeux extends Phaser.Scene {
constructor() {
super({key: "labyrintheDeux"});
}
preload() {
this.load.plugin('rexquestplugin', 'https://raw.githubusercontent.com/rexrainbow/phaser3-rex-notes/master/dist/rexquestplugin.min.js', true);
this.load.image("player", "javascript/assets/player.png");
this.load.image("run1", "javascript/assets/run1.png");
this.load.image("run2", "javascript/assets/run2.png");
this.load.image("playerLeftRun1", "javascript/assets/playerLeftRun1.png");
this.load.image("playerLeftRun2", "javascript/assets/playerLeftRun2.png");
this.load.image("wall", "javascript/assets/wall.png");
this.load.image("doorStart", "javascript/assets/door.png");
}
create() {
cursor = this.input.keyboard.createCursorKeys();
platforms = this.physics.add.staticGroup();
this.anims.create({
key : "playerWalkUp",
frames : [
{key : "run1"},
{key : "run2"}],
frameRate : 7,
repeat : 0
})
this.anims.create({
key : "playerWalkLeft",
frames : [
{key : "playerLeftRun1"},
{key : "playerLeftRun2"}],
frameRate : 7,
repeat : 0
})
player = this.physics.add.sprite((w - w) + 70, h, "player");
player.setScale(1, 1);
player.body.setSize(30, 35);
wall = this.add.sprite((w - w) + 6, h - 126, "wall");
door = this.physics.add.staticSprite((w / 2) - 20, 30, "door");
door.rotation += 20.42;
door.setSize(50, 10);
platforms.add(wall);
this.physics.add.collider(platforms, player);
player.setCollideWorldBounds(true);
function collision() {
this.scene.start("");
}
this.physics.add.collider(player, door, collision, undefined, this);
}
update() {
if (cursor.left.isDown){
player.setVelocityX(-200);
player.anims.play("playerWalkLeft", true);
player.setFlip(false, false);
} else if (cursor.right.isDown){
player.setVelocityX(200);
player.anims.play("playerWalkLeft", true);
player.setFlip(true, false);
} else if (cursor.up.isDown){
player.setVelocityY(-200);
player.anims.play("playerWalkUp", true);
player.setFlip(false, false);
} else if (cursor.down.isDown){
player.setVelocityY(200);
player.anims.play("playerWalkUp", true);
player.setFlip(false, true);
} else {
player.setVelocity(0);
player.setTexture("player");
}
if ((cursor.left.isDown && cursor.up.isDown) || (cursor.left.isDown && cursor.right.isDown) || (cursor.left.isDown && cursor.down.isDown) || (cursor.right.isDown && cursor.up.isDown) || (cursor.right.isDown && cursor.down.isDown)){
player.setVelocity(0);
player.setTexture("player");
}
}
}
*/
var config = {
type: Phaser.AUTO,
width: window.innerWidth - 20,
height: window.innerHeight - 100,
backgroundColor: "#FFFFFF", //#FFFFFF
physics: {
default : "arcade",
arcade : {
debug : false,
}
},
scene: [SceneStart, LabyrintheStart /**, LabyrintheDeux*/]
};
let game = new Phaser.Game(config);
var h = window.innerHeight;
var w = window.innerWidth;
var platforms;
var cursor;
var player;
var doorGauche;
var doorDroite;
var doorUp;
var doorStart;
var wall1;
var wall2;
var wall3;
var wall4;
// A rajouter plus tard
/**
*
function collisionUp() {
this.scene.start("labyrintheTrois");
}
*
* this.physics.add.collider(player, doorGauche, collisionUp, undefined, this);
*
* doorUp = this.physics.add.staticSprite((w / 2) - 20, 8, "door");
* doorUp.setScale(0.08);
* doorUp.setSize(80, 18);
* doorUp.setOffset(55, 491);
* doorUp.rotation += -20.42;
*/
我从未真正使用过 rexquestplugin
,但听起来很有趣,所以我检查了一下。
Here the Documentation(不详细,但可能有助于清理下面的代码)
The Demo 文档站点上帮助我更好地理解了用法,但不是很清楚。
所以我写了一个小的演示应用程序,来回答这个问题“我将如何使用插件解决你的问题?”
(btw.: 你可以执行下面的代码片段)
// This is the Quest csv File as Array (just for the demo)
// load the csv from a file, if it is bigger
var questString = [
['type', 'key', 'next', 'end'], // Line 1: HEADER
['q', 'Go talk to Jerry', '', ''], // Line 2: Quest1 Part1
['', '', 'Get Sword', ''], // Line 3: First Option for Quest1 Part1 (there could be several option per Quest)
['q', 'Get Sword', '', ''], // Line 4: Quest1 Part2
['', '', 'Give it to Jerry', ''], // Line 5: First Option for Quest1 Part2
['q', 'Give it to Jerry', '', ''], // Line 6: Quest1 Part3
['','', 'DONE', '', ''], // Line 7: First Option for Quest1 Part3
['q', 'DONE', '', '1'], // Line 8: QUEST End
].map(x => x.join(',')).join('\n');
// This is the DemoScene
// Just very simple way to define a Scene, without Class (just for the demo)
var DemoScene = {
preload() {
// Load Plugin
this.load.plugin('rexquestplugin', 'https://raw.githubusercontent.com/rexrainbow/phaser3-rex-notes/master/dist/rexquestplugin.min.js', true);
},
extend: {
// Collision Callback for Jerry
handleMeeting(player, jerry){
if(player._currentQuest ){
// Get all options (in this case only one)
console.info(player._currentQuest.currentQuest)
let options = player._currentQuest.currentQuest.options;
if(options[0].next == 'Get Sword'){
this.sword.visible = true;
player._currentQuest.manager.getNextQuestion(options[0].next);
} else if(options[0].next == 'DONE'){
this.door.fillColor = 0x00ff00;
player._currentQuest.manager.getNextQuestion(options[0].next);
}
}
},
// Collision Callback for Sword
handleSword(player, sword){
if(player._currentQuest ){
sword.destroy();
// Get all options (in this case only one)
let options = player._currentQuest.currentQuest.options;
if(options[0].next == 'Give it to Jerry'){
sword.visible = true;
player._currentQuest.manager.getNextQuestion(options[0].next);
}
}
},
// Collision Check Callback for Sword
checkSwordStatus(player, sword){
// if the sword is visible collide
return sword.visible;
},
// Collision Check Callback for door
checkDoorStatus(player, door){
// if the door is red collide
return door.fillColor == 0xff0000;
}
},
create() {
// Player
this.player = this.add.circle(30, 30, 10, 0xffffff).setOrigin(.5);
this.cursor = this.input.keyboard.createCursorKeys();
this.physics.add.existing(this.player);
this.player.body.setCollideWorldBounds(true);
this.player.body.setCircle(10);
this.player.setDepth(2);
// Jerry
this.jerry = this.add.circle(160, 30, 10, 0x0000ff).setOrigin(.5);
this.physics.add.existing(this.jerry, true);
this.jerry.body.setCircle(10);
// Sword
this.sword = this.add.isotriangle(50, 100, 20, 40, false, 0xffe31f, 0xf2a022, 0xf8d80b).setOrigin(.5);
this.physics.add.existing(this.sword, true);
this.sword.visible = false;
// Door
this.door = this.add.rectangle(190, 0, 20, 200, 0xff0000).setOrigin(0);
this.physics.add.existing(this.door, true);
// colliders
this.physics.add.collider(this.player, this.jerry, this.handleMeeting, undefined, this);
this.physics.add.collider(this.player, this.sword, this.handleSword, this.checkSwordStatus, this);
this.physics.add.collider(this.player, this.door, undefined, this.checkDoorStatus, this );
// Quest List
this.print = this.add.text(380, 180, '', { fontSize: '12px', align: 'right' }).setOrigin(1);
// QUEST SETUP
this.plugins.get('rexquestplugin').add({
questions: questString,
quest: true
})
// EVENT executes on new Quest/Question
.on('quest', function (currentQuest, manager, quest) {
// QUEST has ended
if (currentQuest.end === 1) {
manager.setData('endAt', currentQuest.key);
manager.emit('complete', manager, quest);
} else {
// NEXT Step in the Quest
if(this.player._currentQuest){
this.print.text = this.print.text + 'done\n';
}
this.print.text += `${currentQuest.key}...`;
this.player._currentQuest = { currentQuest, manager}
}
}, this)
// Is emited from `on('quest', ... )`
.on('complete', function (manager, quest) {
delete this.player._currentQuest;
this.print.text = this.print.text + 'done\n';
this.print.text += `\nDoor is unlocked!`;
}, this)
// Get First Quest
.getNextQuestion();
},
update() {
// only player movement
let body = this.player.body;
if (this.cursor.left.isDown) {
body.setVelocityX(-200);
} else if (this.cursor.right.isDown) {
body.setVelocityX(200);
} else if (this.cursor.up.isDown) {
body.setVelocityY(-200);
} else if (this.cursor.down.isDown) {
body.setVelocityY(200);
} else {
body.setVelocity(0);
}
}
}
var config = {
type: Phaser.AUTO,
width: 400,
height: 200,
scene: [DemoScene],
physics: {
default : "arcade"
}
};
var game = new Phaser.Game(config);
<script src="https://cdn.jsdelivr.net/npm/phaser@3.55.2/dist/phaser.js"></script>
播放器 - 使用光标键移动
blue: 是 Jerry
白:是玩家
黄色:是剑
red/gree: closed/open门
One part that was not really clear to me, was the
csv
for the quest, here is my interpretation, of the columns:
'type'
column
- if set to
'q'
it is a quest/question- if empty
''
it is a option'key'
column
- if is set it is the name of the quest/question
- if empty
''
it is a option'next'
column
- if it is set this is the name of the next quest/question
- if empty
''
it is a quest'end'
column
- if is is set it ends the quest/question (in this example it has to be set to
1
)- if empty
''
, it is not the last quest/question
更新:
根据您正在制作的任务/游戏的大小,框架 ink https://www.inklestudios.com/ink/ 可能是一个选项。它很容易编写,有令人难以置信的文档,但内容非常广泛。