Upload
others
View
5
Download
0
Embed Size (px)
Citation preview
หนา 1
เอกสารประกอบการสอน
วชา 322218 Basics of Game Programming
แบบฝกปฏบต ครงท 4 Shooting Game
โดย อ.ดร.วชราวธ ธรรมวเศษ
วตถประสงค
1. เพอเรยนรการใชงาน Arcade Physics ส าหรบสรางเกมยง
2. การรบ Input จาก Keyboard และ Mouse
3. การใช Sprite, Group, Tween และ Weapon
1. The Game Concept
เนอเรอง
Actions
o กดปมซาย ขวา เลอนยานอวกาศ
o กด Space Bar ยง
GamePlay
o ผเลนควบคมยานอวกาศ หลบ และ ยง ยานของ Alien ทลอยผานมา
o ถายงถก Alien จะหายไป และ ไดคะแนน
o ถายานอวกาศ ของผเลนถก Alien ชนจะแพ
o ถายง Alien ไดหมดจะชนะ
หนา 2
2. The Game Art Work
ออกแบบ Sprite Sheet ของ ยานอวกาศ Player, ยาน Alien และ ลกกระสน
ให น.ศ. ออกแบบใหม โดยใชโปรแกรมทถนด (แนะน า www.piskelapp.com)
ship1.png ยานของผเลน
alien.png ตว alien
bullet.png ลกกระสน
3. The Game Code
3.1. สราง Phaser Project
สรางดวย Template Basic ตงชอเปน GameLab4
3.2. แกไขไฟล assets-pack.json
เพม spritesheet ใน section level และ +spritesheet รปยาน (ship1) เอเรยน (alien) และ กระสน
(bullet) ดงตวอยาง
หนา 3
3.3. แกไข Main.js เพอก าหนดขนาดพนทของเกม
ในแบบฝกหดนจะใชขนาด 360 x 640 เพอจะท าหนาจอใหพอดกบ จอโทรศพทมอแบบแนวตง
window.onload = function() {
var game = new Phaser.Game(360, 640, Phaser.AUTO);
// Add the States your game has.
game.state.add("Boot", Boot);
game.state.add("Menu", Menu);
game.state.add("Preload", Preload);
game.state.add("Level", Level);
// Now start the Boot state.
game.state.start("Boot");
};
3.4. แกไขหนาเมน ในไฟล menu.js
เพม Sprite ยานอวกาศ และ ขอความชอผเขยนโปรแกรม
Menu.prototype.create = function() {
var sprite = this.add.sprite(this.world.centerX, this.world.centerY,
"tap-to-start");
sprite.anchor.set(0.5, 0.5);
var text = this.add.text(10, this.world.height-20, "By Wachirawut Thamviset",
{fill: 'white'}); text.scale.set(0.4);
this.ship = this.add.sprite(this.world.centerX, this.world.height-20,"ship1");
this.ship.animations.add("all").play(12,true);
this.ship.anchor.set(0.5,1);
this.ship.scale.set(3);
this.ship.smoothed = false;
this.input.onDown.active = true;
this.input.onDown.add(this.startLevel, this);
}; ค าสง this.add.text เปนการเพมขอความ ระบต าแหนง x,y, ขอความ และ style
ในสวนนให นศ. ออกแบบ Logo ชอเกม และ ตกแตงหนา Menu ดวย sprite ใหสวยงาม
หนา 4
3.5. เพม effect โดยการแสดง tween กอนจะไปฉากเลนเกม
แกไขthis.input.onDown.add(this.startLevel, this); (ใน Menu.prototype.create )
เปน this.input.onDown.add(this.startGame, this); เพอจะใหมการแสดง tween กอนไปฉากเลน
เพม function Menu.prototype.startGame โดยใหยานเคลอนทขนไปดานบนจนถงจด y=0
ในตวอยางนจะใชการเคลอนทแบบ Elastic.easeIn หลงจากทแสดงเสรจจะไปเรยก this.startLevel เพอให
ฉากเลนเกมท างาน (this.input.onDown.active = false; เพอไมใหกดซ าระหวางทรอใหยานเคลอนไหว)
Menu.prototype.startGame = function() {
this.input.onDown.active = false;
var tw = this.add.tween(this.ship);
tw.to({y:0},2000, "Elastic.easeIn",true);
tw.onComplete.addOnce(this.startLevel, this);
};
Menu.prototype.startLevel = function(){
this.game.state.start("Level");
}
ตาราง EaseMap
Power0 Power1 Power2 Power3 Power4 Quad Cubic Quart Quint Sine Expo Circ Elastic Back Bounce
Quad.easeIn Cubic.easeIn Quart.easeIn Quint.easeIn Sine.easeIn Expo.easeIn Circ.easeIn Elastic.easeIn Back.easeIn Bounce.easeIn
Quad.easeOut Cubic.easeOut Quart.easeOut Quint.easeOut Sine.easeOut Expo.easeOut Circ.easeOut Elastic.easeOut Back.easeOut Bounce.easeOut
Quad.easeInOut Cubic.easeInOut Quart.easeInOut Quint.easeInOut Sine.easeInOut Expo.easeInOut Circ.easeInOut Elastic.easeInOut Back.easeInOut Bounce.easeInOut
Linear เราสามารถใช Mouse ไปวางท String ของ tween กจะมองเหนตวอยางการเคลอนท
หนา 5
4. ฉากเลนเกม Level.js
ในฉากนจะแสดงยานท ดานลาง กลางจอ โดยใช sprite (ship1)
แสดงคะแนนทมมบนซาย
Level.prototype.create = function() {
this.game.score = 0;
this.gameover=false;
this.physics.startSystem(Phaser.Physics.ARCADE);
this.player = this.add.sprite(this.world.centerX,600,"ship1");
this.player.anchor.set(0.5,0.5);
this.player.animations.add("fly");
this.player.play("fly",12,true);
this.player.smoothed=false;
this.player.scale.set(2);
this.physics.enable(this.player, Phaser.Physics.ARCADE);
this.player.body.collideWorldBounds = true;
this.player.body.allowGravity = false;
this.player.body.maxVelocity.setTo(200,2000);
this.createAlien();
this.createWeapon();
this.scoreText = this.add.text(32, 0, ''+this.game.score, { fill: 'white' });
this.scoreText.z = 10;
this.input.keyboard.addKeyCapture([
Phaser.Keyboard.LEFT,
Phaser.Keyboard.RIGHT,
Phaser.Keyboard.SPACEBAR,
Phaser.Keyboard.X
]);
this.player.inputEnabled = true;
this.player.events.onInputDown.add(this.fireWeapon, this);
};
Level.prototype.update = function() { }
Level.prototype.createAlien = function() { }
Level.prototype.createWeapon = function() { }
Level.prototype.fireWeapon = function() { }
ค าอธบาย
this.player = this.add.sprite(this.world.centerX,600,"ship1"); เปนการสราง Sprite คณสมบตของ Sprite ทควรร x, y, position คอ ต าแหนง x,y เปนตวเลข สวน position เปน Object ทม x, y อยขางใน anchor คอ ต าแหนงของสมอ เปน Object ประกอบดวย x,y มคาระหวาง 0-1 animations เปน Animation Manager ของ sprite ใชควบคมการท า animation play( ) คอ ค าสงใหเลน animation ตาม key ทตงไว scale คอ ตวเลขแทนขนาด ถานอยกวา 1 จะเปนการยอภาพ ถามากกวา 1 จะเปนการขยาย
หนา 6
การใช Physic Arcade เบองตน Phaser จะมชดค าสงในการค านวณเกยวกบการจ าลองฟสกสในเกมสอยหลายตว เชน Arcade, P2, Ninja เปนตน ส าหรบแบบฝกหดนจะเปนฝกใช Phaser.Physics.ARCADE แบบพนฐาน หนาทของฟสกสในเกมจะใชจ าลองการเคลอนทของวตถ เกยวของกบ ความเรว ความเรง มม มวล แรงและการชน การตกกระทบ เปนตน Physics.ARCADE จะสามารถใชกบวตถทมรปทรงแบบงายๆ คอ สเหลยม และ วงกลม จงเหมาะกบเกมงายๆ ทไมตองใชการค านวณละเอยด ท าใหมความเรวในการประมวลผลสง การเรมใชงาน this.physics.startSystem(Phaser.Physics.ARCADE);
การระบวา Sprite หรอ Object ใดทจะใชงาน Physics this.physics.enable(this.player, Phaser.Physics.ARCADE);
ในตวอยางก าหนดให player ใชงาน physics
object.body เปนขอมลล าตวของวตถทอยในโลกจ าลอง ซงจะสามารถก าหนดขนาด มวล ความเรว ความเรง ได เชน ก าหนดให sprite เคลอนออกนอก world ไมได (หนาจอเกม เรยกวา World) this.player.body.collideWorldBounds = true;
ก าหนดให sprite ไรแรงดงดด ให allowGravity = false
ถามแรงดงดดยานกจะตกลงไปดานลาง แตในเกมนยานจะลอยจงก าหนดใหเปน false this.player.body.allowGravity = false;
ก าหนดคาความเรวสงสดในแนวแกน x และ y เปน pixels / sec
หมายความวา ยานจะเลอนไปตามแนวแกน x ดวยความเรวไมเกน 200 this.player.body.maxVelocity.setTo(200,2000);
5. ควบคมยานเคลอนท ซาย ขวา เราจะเขยนค าสงส าหรบควบคมยานของผเลนไวท function update
ซงฟงกชนนจะถกเรยกตลอดเวลาเกมท างาน ประมาณ 60 รอบตอวนาท
Level.prototype.update = function(){
if(this.gameover) return;
if(this.input.keyboard.isDown(Phaser.Keyboard.LEFT)){
this.player.body.acceleration.x = -600;
}else if(this.input.keyboard.isDown(Phaser.Keyboard.RIGHT)){
this.player.body.acceleration.x = 600;
}else{
this.player.body.velocity.setTo(0, 0);
this.player.body.acceleration.setTo(0, 0);
}
}
หนา 7
ค าอธบาย
เราจะใหค าสงในฟงกชนนท างานรบคาจะ keyboard เฉพาะเมอเกมยงเลนอย ถา gameover กไมตองท างานจงเขยนค าสงน if(this.gameover) return; body.acceleration คอ คาความเรงของวตถ ภายในจะม x และ y
body.acceleration.x คอ คาความเรงของวตถตามแนวแกน x
body.acceleration.y คอ คาความเรงของวตถตามแนวแกน y
ถากดปมซายใหความเรงแนวแกน x เปน -600 ยานกจะเคลอนไปทางซาย if(this.input.keyboard.isDown(Phaser.Keyboard.LEFT) this.player.body.acceleration.x = -600;
ถากดปมขวาใหความเรงแนวแกน x เปน 600 ยานกจะเคลอนไปทางขวา if(this.input.keyboard.isDown(Phaser.Keyboard.RIGHT) this.player.body.acceleration.x = 600;
ถาปลอยมอยานกจะหยด this.player.body.velocity.setTo(0, 0);
this.player.body.acceleration.setTo(0, 0);
ยานล านจะเคลอนทขนลงไมได
ถาจะใหเคลอนทขนลงดวย กสามารถเพมการควบคม body.acceleration.y
6. การสรางอาวธ อาวธของยานอวกาศในเกมนคอ การยงกระสน ในแตละเกม
อาจจะมอาวธหลากหลายชนดทมการแสดงผล และ วธการเคลอนท
แตกตางกน ซงในกรณนจะท ากระสนแบบงายๆ มการเคลอนทขนใน
แนวตงเทานน
ใน Phaser จะม plugin ชอวา Phaser.Weapon ใช
ส าหรบสรางอาวธส าหรบเกมยงโดยเฉพาะ ซงเราจะน าใชใน
แบบฝกหดน
หนา 8
Level.prototype.createWeapon = function() {
this.weapon1 = this.add.weapon(10,"bullet",1);
this.weapon1.bulletKillType = Phaser.Weapon.KILL_WORLD_BOUNDS;
this.weapon1.trackSprite(this.player,-20,-30);
this.weapon1.bulletSpeed = 500;
this.weapon1.fireAngle = 270;
this.weapon1.rate = 600;
this.weapon2 = this.add.weapon(10,"bullet",2);
this.weapon2.bulletKillType = Phaser.Weapon.KILL_WORLD_BOUNDS;
this.weapon2.trackSprite(this.player,20,-30);
this.weapon2.bulletSpeed = 500;
this.weapon2.fireAngle = 270;
this.weapon2.rate = 600;
}
ในแบบฝกหดน ยานอวกาศมปนตดทปก 2 กระบอก จงตองท า อาวธ 2 อน
ค าสง this.add.weapon(10,"bullet",3); เปนการสรางอาวธ
- ตวเลข 10 คอ จ านวนกระสนทยงไดพรอมกน ไมเกน 10 นด ก าหนดคาไดตงแต 1 ขนไป
- bullet เปนชอ spritesheet ทใชท าภาพกระสน
- ตวเลข 3 คอ หมายเลข frame (ตวอยางนม กระสน 4 แบบ 0-3)
ค าสง weapon1.bulletKillType = Phaser.Weapon.KILL_WORLD_BOUNDS;
เปนการบอกวา ลกกระสนจะลบออกไปเมอใด กรณนคอเมอออกนอกจอ (WORLD)
ค าสง weapon1.trackSprite(this.player,-20,-30);
เปนการก าหนดใหอาวธนตดอยต าแหนง ไหนของตวยาน กรณน 0,0 หมายถงจดศนยกลางยาน ปนกระบอกแรกจะใหอยปกดานซาย จงใหอยแกน x -20 (มาทางซาย 20 pixel) และ y - 30 (ขนดานบนอก 30)
ค าสง this.weapon1.bulletSpeed = 500; เปนการก าหนดความเรวของกระสน
ค าสง this.weapon1.fireAngle = 270; เปนการก าหนดมมยง
ค าสง this.weapon1.rate = 600; เปนความเรวของการยง (Phaser version 2.6)
0,0
-20,-30 20,-30
หนา 9
ค าสง this.weapon1.bulletSpeed = 500; เปนการก าหนดความเรวของกระสน
เพมค าสงยงกระสนใน fireWeapon () เมอ click ทยาน
โดยการเรยก this.weapon1.fire();
Level.prototype.fireWeapon = function(){
this.weapon1.fire(); this.weapon2.fire();
} ค าสง fireWeapon จะถกเรยกใชจาก event input ทตงไวในขอ 4
this.player.events.onInputDown.add(this.fireWeapon, this);
7. สราง aliens
เขยนในฟงกชน createAlien
Level.prototype.createAlien = function() {
this.aliens = this.add.group(this.game.world,'aliens',false,true, Phaser.Physics.ARCADE); this.aliens.z = 100;
for(i=0;i<30;i++){
a = this.aliens.create(Math.random() * 300,-Math.random() * 300,"alien");
a.animations.add("fly").play(12,true);
a.anchor.set(0.5);
a.body.velocity.y = 50;
tw = this.add.tween(a);
var nx=20+Math.random()*300;
var nt=Math.random()*500;
tw.to({x:nx},1000+nt, "Sine",true,0,Number.MAX_VALUE,true);
if(Math.random()>0.5) a.body.angularVelocity = 60
else a.body.angularVelocity = -60;
}
}
ค าสง this.aliens = this.add.group เปนการสรางกลม โดยก าหนดใหสมาชกในกลมนใช การจ าลอง
Physics แบบ Arcade
ค าสง this.aliens.z เปนการก าหนดล าดบการแสดงผลของกลมน ใหอยลาง ตวเลข score (score จะมคา z
= 10) คา z มากกวาจะอยลกกวา
ค าสง for(i=0;i<30;i++) เปนการวนลป 30 รอบ
ค าสง a = this.aliens.create เปนการสราง alien โดยการสมต าแหนง ดวย Math.random()
ค าสง a.animations.add("fly").play(12,true); เปนก าหนดคา animation
ค าสง a.body.velocity.y = 50; จะให alien เคลอนทลงมาดานลางดวยความเรว 50
ค าสง tw = this.add.tween(a); เปนการสรางการเคลอนทดวย tween ซงตวอยางนจะใหเคลอนทไปมา
ซายขวา
หนา 10
เมอรนโปรแกรมจะเหนวา Alien จะเคลอนทไปมา และ คอยๆ เลอนลงไปเรอย และหายออกไปจากจอ
เราจะเพมค าสงเพอให alien ทหายไป กลบขนไปอยดานบน ใหม
โดยจะเขยนในไวใน update ซงจะได update ใหมดงน Level.prototype.update = function(){
if(this.gameover) return;
this.aliens.forEachAlive(function(a){ if(a.y > this.world.height) a.y = -Math.random() * 300; },this);
}
ค าอธบาย this.aliens.forEachAlive(function(a){
if(a.y > this.world.height) a.y = -Math.random() * 300; },this);
เปนการสงใหวนลปประมวลผล alien ทกตวทมชวต (ยงไมถก kill) โดยเขยน code ส าหรบการประมวลผล
ไวใน function ดงตวอยาง ถา a.y หมายถง ต าแหนง y ของ alien ตวใด มากกวา ความสงของจอ ให
กลบไปดานบน โดยการสมต าแหนง
8. ตรวจสอบการชนของกระสนกบ aliens
เมอกระสนถกยงไปชนกบ alien ตวใด alien และ กระสนจะถกก าจดออกจากหนาจอ
จะเขยนดวยค าสง physics.arcade.collide และ เนองจากเรามปน 2 กระบอกดงนนจงตอง
ตรวจสอบกระสนจากปนทง 2 กระบอก ดงตวอยาง
this.physics.arcade.collide(this.aliens,this.weapon1.bullets,this.onCollide,null,this);
this.physics.arcade.collide(this.aliens,this.weapon2.bullets,this.onCollide,null,this);
ซงค าสงนจะเขยนไวใน update() ดงนน ตอนนโปรแกรมใน update จะกลายเปน
if(this.input.keyboard.isDown(Phaser.Keyboard.LEFT)){
this.player.body.acceleration.x = -600;
}else if(this.input.keyboard.isDown(Phaser.Keyboard.RIGHT)){
this.player.body.acceleration.x = 600;
}else{
this.player.body.velocity.setTo(0, 0);
this.player.body.acceleration.setTo(0, 0);
}
if(this.input.keyboard.isDown(Phaser.Keyboard.SPACEBAR)){
this.fireWeapon();
}
หนา 11
เขยน function onCollide เพมเพอท างานเมอเกดการชนกนระหวาง alien และ bullet
ใหก าจด alien และ bullet แลวเพมคะแนน
Level.prototype.onCollide = function(alien,bullet){
alien.kill();
bullet.kill();
this.game.score++;
this.scoreText.text = ''+this.game.score;
};
9. You Win
เกมนผเลนจะชนะเมอยง alien จนหมด ดงนนเราจะเพมค าสงเพอตรวจสอบวา alien หมดหรอยง และเมอ
alien หมดแลวกใหแสดงขอความวา You Win แลวกลบไป หนา Menu โดยค าสงนจะเขยนไวท update
การนบจ านวน alien ทยงอย ท าไดดวยค าสง this.aliens.countLiving() ดงนน โปรแกรมจะเขยน
ไดดงตวอยาง
if(this.aliens.countLiving()==0 ){
this.gameover=true;
win = this.add.text(this.world.centerX,this.world.centerY,"You Win",{ fill: 'Yellow'});
win.anchor.set(0.5,0.5);
win.scale.set(0.1);
var tw = this.add.tween(win.scale);
tw.to({x:2,y:2},1000, "Linear",true,0);
delay = this.add.tween(win);
delay.to({y:100},1000, "Linear",true,2000);
tw.chain(delay);
delay.onComplete.addOnce(this.quitGame, this);
}
ตวอยางนเมอ alien ตายหมด กจะสราง text “You Win” ทกลางจอ แลวใช tween ท าใหตวขยายใหญขน
แลวใช tween.chain ตอดวยเลอนขอความขนดานบน เมอแสดงจบ กเรยกใช this.quitGame กลบไป Menu
Level.prototype.quitGame = function() {
this.game.state.start("Menu");
};
Level.prototype.update = function(){
if(this.gameover) return;
if(this.input.keyboard.isDown(Phaser.Keyboard.LEFT)){
this.player.body.acceleration.x = -600;
}else if(this.input.keyboard.isDown(Phaser.Keyboard.RIGHT)){
this.player.body.acceleration.x = 600;
}else{
this.player.body.velocity.setTo(0, 0);
this.player.body.acceleration.setTo(0, 0);
}
if(this.input.keyboard.isDown(Phaser.Keyboard.SPACEBAR)){
this.fireWeapon();
}
this.aliens.forEachAlive(function(a){
if(a.y > this.world.height) a.y = -Math.random() * 300;
},this);
this.physics.arcade.collide(this.aliens,this.weapon1.bullets,this.onCollide,null,this);
this.physics.arcade.collide(this.aliens,this.weapon2.bullets,this.onCollide,null,this);
}
หนา 12
รวมแลวฟงกชน update จะม code ดงน
10. ตรวจสอบการชนของ aliens กบ player
ใหเขยนโปรแกรมเพมเตม ตรวจสอบการชนระหวาง alien กบ player
เมอชนกนใหลดพลงชวต ถาชนครบ 3 ครงใหตาย และ สรางสวนแสดง Game Over แลวกลบไปหนาเมน
เมอ Player แพ
11. ตกแตงเกม
ออกแบบเนอเรอง ตวละคร (ยาน) และ alien โดยอสระ
แกไขหนาเมน ใสชอเกม พนหลง และ อาจจะใสดนตรประกอบ(ดจากตวอยางในเวบของ phaser)
ในหนาเลนเกมใหเพม image เปนฉากหลงใหสวยงาม
Level.prototype.update = function(){
if(this.gameover) return;
if(this.input.keyboard.isDown(Phaser.Keyboard.LEFT)){
this.player.body.acceleration.x = -600;
}else if(this.input.keyboard.isDown(Phaser.Keyboard.RIGHT)){
this.player.body.acceleration.x = 600;
}else{
this.player.body.velocity.setTo(0, 0);
this.player.body.acceleration.setTo(0, 0);
}
if(this.input.keyboard.isDown(Phaser.Keyboard.SPACEBAR)){
this.fireWeapon();
}
this.aliens.forEachAlive(function(a){
if(a.y > this.world.height) a.y = -Math.random() * 300;
},this);
this.physics.arcade.collide(this.aliens,this.weapon1.bullets,this.onCollide,null,this);
this.physics.arcade.collide(this.aliens,this.weapon2.bullets,this.onCollide,null,this);
if(this.aliens.countLiving()==0 ){
this.gameover=true;
win = this.add.text(this.world.centerX,this.world.centerY,"You Win",{fill:'Yellow'});
win.anchor.set(0.5,0.5);
win.scale.set(0.1);
var tw = this.add.tween(win.scale);
tw.to({x:2,y:2},1000, "Linear",true,0);
delay = this.add.tween(win);
delay.to({y:100},1000, "Linear",true,2000);
tw.chain(delay);
delay.onComplete.addOnce(this.quitGame, this);
}
}