צעדים ראשונים עם פייזר - דוגמת כדור קופץ
פייזר הוא ספריה לפיתוח משחקים פשוטים בדפדפן. יש בו כל מה שאפשר לרצות והעבודה היא בקוד לכן לא צריך מיומנות עם כלים גרפיים בשביל להסתדר. בואו נראה איך לבנות איתו פרויקט שמראה כדור מקפץ על המסך.
1. יצירת פרויקט ראשון
לא צריך הרבה בשביל פייזר מספיק פרויקט חדש ב Vite ולבחור Vanilla JavaScript. אין בעיה גם עם טייפסקריפט אם אתם מעדיפים. אחרי יצירת הפרויקט אני מעדכן את הקובץ main.js בתבנית לקוד הבא:
import * as Phaser from 'phaser';
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
pixelArt: true,
transparent: false,
physics: {
default: 'arcade',
arcade: {
debug: false
}
},
scene: []
};
new Phaser.Game(config);
מתקין את פייזר עם:
npm add phaser
ונכנס למסך הפיתוח עם:
npm run dev
ואם הכל הלך כמו שצריך תראו על המסך ריבוע שחור ברוחב 800 פיקסלים וגובה 600. זה לוח המשחק בו פייזר עובד.
2. הוספת הכדור
בשביל לכתוב משהו שיופיע על המסך השחור אנחנו צריכים סצינה. סצינה בפייזר היא בסך הכל מחלקה שמגדירה מספר פונקציות עם שמות שמורים ויורשת ממחלקת הסצינה המובנית של פייזר:
import * as Phaser from 'phaser';
export default class MainScene extends Phaser.Scene {}
השמות שנראה בדוגמה הם:
הפונקציה preload שנקראת לפני שטוענים את הסצינה ונועדה לאתחל רכיבים גרפיים של הסצינה.
הפונקציה create שנקראת כשצריך להפעיל את הסצינה.
הפונקציה update שקורית 24 פעמים בשניה ואחראית על הזזת הפריטים שעל המסך, בדרך כלל בהתבסס על קלט מהמשתמש - למשל אם לוחצים חץ ימינה אז השחקן יזוז ימינה.
בדוגמה שלנו אני רוצה לבנות כדור קטן שיקפוץ על המסך לכן בפונקציה preload אני מייצר את הגרפיקה של הכדור, ב create אני שם אותו על המסך וב update מעדכן את הכיוון שלו. בואו נראה את זה ונבין איך פייזר עוזר לי בכל אחד מהשלבים.
מתחילים עם preload:
preload() {
const graphics = this.add.graphics();
graphics.fillStyle(0x00ff00, 1);
graphics.fillCircle(25, 25, 25);
graphics.generateTexture('greenBall', 50, 50);
graphics.destroy(); // Clean up graphics after texture is created
}
אני מייצר אוביקט גרפי בגודל 50 על 50, מצייר באמצע שלו עיגול ושומר אותו בשם greenBall. הפונקציה fillCircle היא פונקציה שמורה של מנגנון הגרפיקה של פייזר וכמוה גם fillStyle ויש שם עוד הרבה, ובמשחקים אמיתיים בדרך כלל נטען את הגרפיקה מתמונה.
הפונקציה create כבר יותר מעניינת:
create() {
// Now you can safely use the texture
this.ball = this.physics.add.sprite(100, 100, 'greenBall');
this.ball
.setVelocity(200, 200)
.setCollideWorldBounds(true);
}
פה אנחנו עוברים לדבר על פיזיקה - מגדירים ספרייט, שזה דמות במשחק, מתוך אותו כדור ירוק שיצרנו. לספרייט יש מיקום על המסך וזה ה 100,100 שאני מעביר, זו בעצם נקודת ההתחלה של הכדור. לספרייט אפשר לתת גם מהירות ואני מגדיר לו מהירות 200,200 כלומר 200 פיקסלים בשניה ימינה ו 200 פיקסלים בשניה למטה. הפקודה הבאה, setCollideWorldBounds, גורמת לכדור לעצור כשהוא מתנגש באחד הקירות של העולם.
רק עד לפה אפשר להריץ את התוכנית ואנחנו נראה כדור ירוק זז באלכסון למטה, מתנגש בקיר התחתון של המשחק ואז עובר להתגלגל ימינה עד הפינה הימנית תחתונה של העולם. אני מעדיף לתפוס את ההתנגשות בין הכדור לקיר ולשנות לו את הכיוון, ובשביל זה מוסיף את הפונקציה השלישית update:
update() {
const {width, height} = this.game.config;
if (this.ball.body.left <= 0) {
this.ball.body.velocity.x = 200;
}
if (this.ball.body.right >= width) {
this.ball.body.velocity.x = -200;
}
if (this.ball.body.top <= 0) {
this.ball.body.velocity.y = 200;
}
if (this.ball.body.bottom >= height ) {
this.ball.body.velocity.y = -200;
}
}
במשחקים update נקראת עבור כל פריים ותפקידה לעדכן את המידע של הדמויות השונות לקראת ציור הפריים הבא. מאחר ופייזר מטפל לבד בהזזה של פריטים מספיק לי להבין אם הכדור שלי התנגש בקיר ואם כן לשנות לו את המהירות כדי שישנה כיוון, למשל אם הוא פגע בקיר התחתון אז אני משנה את המהירות שלו כך שיתחיל לזוז למעלה.
את הקוד המלא שמרתי בקובץ main-scene.js
:
import * as Phaser from 'phaser';
export default class MainScene extends Phaser.Scene {
constructor() {
super('MainScene');
}
preload() {
const graphics = this.add.graphics();
graphics.fillStyle(0x00ff00, 1);
graphics.fillCircle(25, 25, 25); // Draw circle at the center of a 50x50 texture
graphics.generateTexture('greenBall', 50, 50); // Generate texture
graphics.destroy(); // Clean up graphics after texture is created
}
create() {
// Now you can safely use the texture
this.ball = this.physics.add.sprite(100, 100, 'greenBall');
this.ball
.setVelocity(200, 200)
.setCollideWorldBounds(true);
}
update() {
const {width, height} = this.game.config;
if (this.ball.body.left <= 0) {
this.ball.body.velocity.x = 200;
}
if (this.ball.body.right >= width) {
this.ball.body.velocity.x = -200;
}
if (this.ball.body.top <= 0) {
this.ball.body.velocity.y = 200;
}
if (this.ball.body.bottom >= height ) {
this.ball.body.velocity.y = -200;
}
}
}
ובקובץ main.js אני מעדכן את הקונפיגורציה כדי להציג את הסצינה:
import * as Phaser from 'phaser';
import MainScene from './main-scene';
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
pixelArt: true,
transparent: false,
physics: {
default: 'arcade',
arcade: {
debug: false
}
},
scene: [MainScene]
};
new Phaser.Game(config);
3. מה הלאה
כל הכבוד! כתבתם את המשחק הראשון עם Phaser. נו, לא בדיוק משחק אבל צריך להתחיל איפשהו. הרחבה מתבקשת למשחק הכדור הקופץ היא להוסיף מקל בתחתית המסך שיזוז ימינה ושמאלה עם החצים וצריך לתפוס את הכדור, ואם הכדור נופל למטה אז נפסלים. הרחבה הבאה היא ליצור שני מקלות בשני צידי המסך ולעשות את זה משחק לשני שחקנים ומיטיבי לכת יוכלו לבנות מזה משחק לשני שחקנים על שני מחשבים שונים.
אפשר ללמוד עוד על פייזר דרך אינסוף מדריכים באתר שלהם כאן: https://phaser.io/
ולא לשכוח לשתף משחקים מעניינים שתכתבו איתו.