How to make a simply game with cocos2d-js
Bài đăng này đã không được cập nhật trong 9 năm
Giới thiệu
Bài viết này tôi sẽ hướng dẫn các bạn thích làm game cách làm 1 game đơn giản nhưng khá thú vị bằng cocos2d-js. Với framework này bạn có thể chạy game đã làm trên cả HTML5, iOS và Android. Khi hoàn thành game bạn làm sẽ có giao diện như sau:
Cài đặt
Để cài đặt bạn truy cập vào địa chỉ: http://www.cocos2d-x.org/download tại đây bạn có thể cài đặt cả framework, IDE cũng như các editor hỗ trợ khác. Chi tiết: http://cocos2d-x.org/docs/tutorial/framework/html5/parkour-game-with-javascript-v3.0/chapter1/en
Tạo project
Sau khi cài đặt xong framework bạn có thể tạo project mới bằng command sau:
cocos new SlideAndSurvive -l js
Lệnh này sẽ tạo 1 project tên là: SlideAndSurvive trong thư mục: SlideAndSurvive.
Resources
- Bạn có thể tự tạo các file resource(ảnh, font, âm thanh) nếu ko có thể tại về tại đây: https://github.com/aron-bordin/Slide-and-Survive/tree/master/res bạn copy các file này vào tư mục res trong project của bạn
- Tiếp theo bạn cần khai báo các resource này trong file src/resource.js
var res = {
Square_png : 'res/bloco.png',
Enemy_png : 'res/inimigo.png',
TitleFont: 'res/fonts/Marker Felt.ttf',
Music: 'res/fundo.mp3'
};
var g_resources = [
res.Square_png,
res.Enemy_png,
res.TitleFont,
res.Music
];
Main
Giờ thì bạn mở file main.js và gõ đoạn code sau vào:
cc.game.onStart = function(){
cc.view.setDesignResolutionSize(800, 450, cc.ResolutionPolicy.SHOW_ALL);
cc.view.resizeWithBrowserSize(true);
//load resources
cc.LoaderScene.preload(g_resources, function () {
cc.director.runScene(new GameScene());//run the GameScene
}, this);
};
cc.game.run();
Đoạn code trên đầu tiên set độ phân giải của game là: 800×450, nhưng bạn đừng bận tâm vì cocos2d sẽ tự động resize tùy theo thiết bị. Tiếp theo đó là set giá trị cho phép trình duyệt resize game theo kích cỡ thích hợp. Tiếp nữa ta load các resource đã khai báo ở trên và cuối cùng là chạy Scene chính của game: GameScene.
Game Scene
Đầu tiên bạn gõ đoạn code sau vào file src/app.js
var Objs = { //global objects
EnemiesDirection: [],
Enemies: [],
Square: null,
Title: null,
gameTime: null,
gameTimeInfo: null,
gameTimeTotal: null,
gameBestInfo: null,
gameBestValue: null,
gameInfo1: null,
gameInfo2: null,
soundInfo: null
}
var timePlayed = 0; //game time
var isAlive = false; //is the game is running
function moveSquare(destination){ //move the green square to destination
}
function gameStart(){//game start, hide texts
}
function gameOver(){//game over, check score
}
var GameLayer = cc.Layer.extend({//main scene
ctor:function () {
},
update: function(dt){//update callback, run every frame
},
checkCollision: function(){
},
onTouchBegan: function(touch, event){//touchbegan callback
},
onTouchMoved: function(touch, event){//touchmoved callback
},
addTexts: function(){//add the texts to the screen
},
SoundClicked: function(){
},
addSquares: function(){//add the squares to the scene
},
generateDirection: function(){//generate a random direction
}
});
var GameScene = cc.Scene.extend({//create the scene and start the game
onEnter:function () {
this._super();
var layer = new GameLayer();
this.addChild(layer);
}
});
Đoạn code này chủ yếu định nghĩa 1 số hàm và biến, chi tiết hơn các hàm và biến này chúng ta sẽ cùng tìm hiểu.
- Constructor: Hàm tạo chủ yếu đăng ký event: touch, move và gọi các hàm khác để tạo text, các hình vuông và tạo random các hướng di chuyển của các hình vuông này
// 1. super init first
this._super();
var eventListener = cc.EventListener.create({//event listener
event: cc.EventListener.TOUCH_ONE_BY_ONE, //one click
swallowTouches: true, //is onTouch return true, stop event propagation
onTouchBegan: this.onTouchBegan, //callbacks
onTouchMoved: this.onTouchMoved});
this.addSquares();//add enemies square
this.addTexts(); //add texts
cc.eventManager.addListener(eventListener, Objs.Square);//start the event listener
for(var i = 0; i < 4; i++)
Objs.EnemiesDirection[i] = this.generateDirection();//generate a random movement direction
this.scheduleUpdate();//runs update() every frame
}
- function addSquares Phần này load các file ảnh của các hình vuông từ resources ra và set vị trí ban đầu cho chúng
addSquares: function(){//add the squares to the scene
Objs.Square = cc.Sprite.create(res.Square_png);
Objs.Square.setPosition(cc.p(400,225));
Objs.Square.setTag(1);
this.addChild(Objs.Square);
var En = Objs.Enemies;
for(var i = 0; i < 4; i++) {
En[i] = cc.Sprite.create(res.Enemy_png);
this.addChild(En[i]);
}
En[0].setPosition(cc.p(100, 100));
En[1].setPosition(cc.p(700, 100));
En[1].setScaleX(1.7);
En[1].setScaleY(0.4);
En[2].setPosition(cc.p(700, 350));
En[2].setScaleX(0.4);
En[2].setScaleY(1.5);
En[3].setPosition(cc.p(100, 350));
En[3].setScale(0.8);
Objs.Enemies = En;
}
- function addTexts Thêm các đoạn text và menu lên màn hình
addTexts: function(){//add the texts to the screen
var bestTime = localStorage.getItem("bestTime");//load the best time from localStorage
Objs.Title = cc.LabelTTF.create("Slide & Survive", res.TitleFont, 40);
Objs.Title.setPosition(cc.p(400, 350));
this.addChild(Objs.Title);
Objs.gameTime = cc.LabelTTF.create("0.000", res.TitleFont, 20);
Objs.gameTime.setPosition(cc.p(50, 10));
this.addChild(Objs.gameTime);
Objs.gameTimeInfo = cc.LabelTTF.create("Time: ", res.TitleFont, 26);
Objs.gameTimeInfo.setPosition(cc.p(200, 225));
this.addChild(Objs.gameTimeInfo);
Objs.gameTimeTotal = cc.LabelTTF.create("0.000", res.TitleFont, 26);
Objs.gameTimeTotal.setPosition(cc.p(300, 225));
this.addChild(Objs.gameTimeTotal);
Objs.gameBestInfo = cc.LabelTTF.create("Best time: ", res.TitleFont, 26);
Objs.gameBestInfo.setPosition(cc.p(540, 225));
this.addChild(Objs.gameBestInfo);
//check if there is a bestTime, if not set the default as 0
Objs.gameBestValue = cc.LabelTTF.create(bestTime ? parseFloat(bestTime).toFixed(3) : "0.000", res.TitleFont, 26);
Objs.gameBestValue.setPosition(cc.p(650, 225));
this.addChild(Objs.gameBestValue);
Objs.gameInfo1 = cc.LabelTTF.create("Move the green square avoiding contact with the red ones!",
res.TitleFont, 20);
Objs.gameInfo1.setPosition(cc.p(400, 310));
this.addChild(Objs.gameInfo1);
Objs.gameInfo2 = cc.LabelTTF.create("Are you able to do it???",
res.TitleFont, 20);
Objs.gameInfo2.setPosition(cc.p(440, 290));
this.addChild(Objs.gameInfo2);
var useSound = localStorage.getItem("Sound");
if(useSound == 1) {
cc.audioEngine.playMusic(res.Music, true);
} else {
if(useSound != 0) {
localStorage.setItem("Sound", 1);
useSound = 1;
}
}
Objs.soundInfo = cc.MenuItemFont.create(useSound == 1 ? "Disable sound" : "Enable Sound", this.SoundClicked, this);
Objs.soundInfo.setFontSize(20);
var Menu = cc.Menu.create(Objs.soundInfo);
Menu.setPosition(680, 20);
this.addChild(Menu);
},
- function generateDirection tạo ra các hướng bay ngẫu nhiên cho các khối hình
generateDirection: function(){//generate a random direction
var i = Math.floor((Math.random() * 3));
var v = 7;
switch (i){
case 0:
return cc.p(v, v);
case 1:
return cc.p(-v, v);
case 2:
return cc.p(-v, -v);
case 3:
return cc.p(v, -v);
}
return cc.p(0, 0);
}
- function update Đây là hàm chính được gọi mỗi lần update frame vì vậy đây sẽ là nơi xử lý các logic chính của game:
update: function(dt){//update callback, run every frame
if(!isAlive)//if is not running, stop
return;
timePlayed += dt; //add dt to game time
Objs.gameTime.setString(timePlayed.toFixed(3));//update game time label
var size = cc.director.getWinSize();//get win size
for(var i = 0; i < 4; i++){//move the enemies
var pos = Objs.Enemies[i].getPosition();
if((pos.x <= 0) || (pos.x >= size.width))//the enemy position will be relative with his direction rect
Objs.EnemiesDirection[i] = cc.p(Objs.EnemiesDirection[i].x * -1, Objs.EnemiesDirection[i].y)
if((pos.y <= 0) || (pos.y >= size.height))
Objs.EnemiesDirection[i] = cc.p(Objs.EnemiesDirection[i].x, Objs.EnemiesDirection[i].y * -1)
Objs.Enemies[i].setPosition(cc.pAdd(Objs.EnemiesDirection[i], pos));
}
this.checkCollision();//check collisionss
},
- function checkCollision để check va chạm và xử lý game over
checkCollision: function(){
//create a rect to represent our green square
var rectHero = cc.rect(Objs.Square.getPositionX() - Objs.Square.getContentSize().width/2*Objs.Square.getScaleX(),
Objs.Square.getPositionY() - Objs.Square.getContentSize().height/2*Objs.Square.getScaleY(),
Objs.Square.getContentSize().width*Objs.Square.getScaleX(),
Objs.Square.getContentSize().height*Objs.Square.getScaleY());
for(var i =0; i < 4; i++){
//create a rect for each enemy
var rectEnemy = cc.rect(Objs.Enemies[i].getPositionX() - Objs.Enemies[i].getContentSize().width/2*Objs.Enemies[i].getScaleX(),
Objs.Enemies[i].getPositionY() - Objs.Enemies[i].getContentSize().height/2*Objs.Enemies[i].getScaleY(),
Objs.Enemies[i].getContentSize().width*Objs.Enemies[i].getScaleX(),
Objs.Enemies[i].getContentSize().height*Objs.Enemies[i].getScaleY());
if(cc.rectIntersectsRect(rectHero, rectEnemy)) {//check collision
gameOver();//if ok, gameover
return;
}
}
},
- function SoundClicked hàm này để chạy file âm thanh khi click menu
SoundClicked: function(){
var enabled = localStorage.getItem('Sound');
if(enabled == 1){
cc.audioEngine.stopMusic(true);
localStorage.setItem('Sound', 0);
Objs.soundInfo.setString('Enable sound');
} else {
cc.audioEngine.playMusic(res.Music, true);
localStorage.setItem('Sound', 1);
Objs.soundInfo.setString('Disable sound');
}
},
- event onTouchBegan Event này xử lý khi click lần đầu, ta sẽ cho start game
onTouchBegan: function(touch, event){//touchbegan callback
var target = event.getCurrentTarget();
var PosInScreen = target.convertToNodeSpace(touch.getLocation());
var Size = target.getContentSize();
var rect = cc.rect(0, 0, Size.width, Size.height);
if(cc.rectContainsPoint(rect, PosInScreen)){ //check if i'm clicking in the green square
switch(target.getTag()){
case 1:
if(!isAlive){//if the game is not running
gameStart();//start it
moveSquare(cc.p(400, 225));//make sure to start the game at the center of the screen
}
return true;
}
}
return false;
},
- event onTouchMoved Event này xảy ra khi ta di chuột, ta sẽ di chuyển khối hình chính theo vị trí di
onTouchMoved: function(touch, event){//touchmoved callback
var target = event.getCurrentTarget();
var PosInScreen = target.convertToNodeSpace(touch.getLocation());
var Size = target.getContentSize();
var rect = cc.rect(0, 0, Size.width, Size.height);
if(!isAlive)//if is not running, go away
return;
if(cc.rectContainsPoint(rect, PosInScreen)){//check if clicked in the green square
switch(target.getTag()){
case 1:
moveSquare(touch._point);//move the square
return true;
}
}
return false;
},
- function moveSquare Hàm này sẽ thực hiện việc di chuyển khối hình chính
function moveSquare(destination){ //move the green square to destination
var size = cc.director.getWinSize();
if((destination.x > 0 ) && (destination.x < size.width)) //check if square is inside the screen
if((destination.y > 0) && (destination.y < size.height))
Objs.Square.setPosition(destination); //if ok, move it
}
- function gameStart Hàm này xử lý start game, bắt đầu cho di chuyển các khối hình và bắt đầu tính thời gian
function gameStart(){//game start, hide texts
isAlive = true;
timePlayed = 0;
Objs.Title.setVisible(false);
Objs.gameTimeInfo.setVisible(false);
Objs.gameTimeTotal.setVisible(false);
Objs.gameBestInfo.setVisible(false);
Objs.gameBestValue.setVisible(false);
Objs.gameInfo1.setVisible(false);
Objs.gameInfo2.setVisible(false);
}
- function gameOver Hàm cuối cùng này xử lý khi có va chạm và gameOver, ta sẽ hiện thông báo và dừng game.
function gameOver(){//game over, check score
isAlive = false;
Objs.Title.setVisible(true);
Objs.gameTimeInfo.setVisible(true);
Objs.gameTimeTotal.setVisible(true);
Objs.gameBestInfo.setVisible(true);
Objs.gameBestValue.setVisible(true);
Objs.gameInfo1.setVisible(true);
Objs.gameInfo2.setVisible(true);
Objs.gameTimeTotal.setString(timePlayed.toFixed(3));
Objs.Square.setPosition(cc.p(400, 225));//move enemies to default location
Objs.Enemies[0].setPosition(cc.p(100, 100));
Objs.Enemies[1].setPosition(cc.p(700, 100));
Objs.Enemies[2].setPosition(cc.p(700, 350));
Objs.Enemies[3].setPosition(cc.p(100, 350));
var bestTime = parseFloat(Objs.gameBestValue.getString()); //get best time
if(timePlayed > bestTime){ //check the game time
localStorage.setItem('bestTime', timePlayed); //if is a new best time, save it
Objs.gameBestValue.setString(timePlayed.toFixed(3)); //and show it
}
}
Kết
Vậy là chúng ta đã hoàn thành game, chúc các bạn thành công
All rights reserved