Micro channel games have been launched for a few days, this function of small programs and small games to promote the impact of needless to say, we quickly rub our hands to lift it. How to develop the official documentation has been explained, this article is the official masturbating demo some minor modifications.
Development preparation
- Download the latest version
Wechat developer tools
(v1.02.1712280) - Public registration is not currently available, according to the official documentation. Therefore, you can only play in non-AppID mode
- In order to make
HTML5
Easy access to the game, officially providedAdapter
. What this does is provideHTML5
Writing andwx
Global transformation layer of notation.
Masturbation game
After creating a small wechat game with no AppID mode, you can see the official demo with entry files and configuration files: game.js and game.json. Game.js introduces and initializes main.js that contains the entire masturbating scene, the actors (player planes and enemy planes), and the main functions of the game logic. In main.js we can see that the code is no different from what we would normally write, thanks to the Adapter. The main logic of the game looks like this:
In the loop, the player shoots every 20 frames and generates new enemy planes every 60 frames. Each frame checks whether the player and enemy aircraft are dead, the game ends when the player dies, and the enemy aircraft death score +1. Only the player can shoot, in a fixed way, and survive by evading enemy aircraft. We then adapted these to make the game more playable and challenging.
Player upgrade Plan
- The player starts at level 1 and can level up by killing enemy planes, every 30 enemy planes shot down
- Each time you level up, you gain an additional firing port
- Players can upgrade up to two times
Start by opening Player /index.js with an editor and adding rank logic to the player’s class.
export default class Player extends Sprite {
constructor() { super(PLAYER_IMG_SRC, PLAYER_WIDTH, This. x = screenWidth / 2 - this.width / 2 this.y = screenheight-this. height-30 // Used to indicate whether the finger is on an airplane when it moves. This. touch =falseThis.bullets = [] // Initialize the event on this.initEvent() this.playerLevel = 1; } getlevel () {
return this.playerLevel;
}
set level (level) {
this.playerLevel = Math.min(level, 3);
}
Copy the code
Next add the upgrade logic to the update function in main.js.
// Other code...update() { this.bg.update(); databus.bullets.concat(databus.enemys).forEach(item => { item.update(); }); this.enemyGenerate(); this.player.level = Math.max(1, Math.ceil(databus.score / 30)); this.collisionDetection(); } // Other code...Copy the code
Ok, players can level up normally at this point. Then it’s time to give the player a reward. We modify the shooting logic in the player/index.js shoot function. At level 1, the player has only the middle opening, level 2 has left and middle opening, and level 3 has left, middle and right opening.
/ /... Other code /** * player shooting operation * shooting timing determined externally */shoot() {
for(let i = 0; i < this.level; i++) {
const bullet = databus.pool.getItemByClass('bullet', Bullet); const middle = this.x + this.width / 2 - bullet.width / 2; const x = ! i ? middle : (i % 2 === 0 ? middle + 30 : middle - 30); bullet.init( x, this.y - 10, 10 ) databus.bullets.push(bullet) } } // ... Other codeCopy the code
The final shape of the weapon is shown here, at which point the player can do whatever he wants, and doesn’t actually need to dodge… :
The enemy’s counter horn
In order to fight against the ignorant players, do not let them do whatever they want, finally no interest in playing ~ ~, the enemy aircraft equipped with weapons, the counterattack began.
First of all, the enemy bullet is down, so make a copy of images/bullet. PNG and save it upside down as images/bullet-down. PNG. Then we reuse js/player/bullet.js, add the enemy bullet configuration item in the constructor, and modify the enemy bullet update logic.
const BULLET_IMG_SRC = 'images/bullet.png'
const BULLET_DOWN_IMG_SRC = 'images/bullet-down.png'
const BULLET_WIDTH = 16
const BULLET_HEIGHT = 30
const __ = {
speed: Symbol('speed')}let databus = new DataBus()
export default class Bullet extends Sprite {
constructor({ direction } = { direction: 'up' }) {
super(direction === 'up'? BULLET_IMG_SRC : BULLET_DOWN_IMG_SRC, BULLET_WIDTH, BULLET_HEIGHT) this.direction = direction; // Other code... // Update bullet position every frameupdate() {
if (this.direction === 'up') {this.y -= this[__.speed] // Out of screen reclaim itselfif ( this.y < -this.height )
databus.removeBullets(this)
} else{this.y += this[__.speed] // Recycle itself out of screenif ( this.y > window.innerHeight + this.height )
databus.removeBullets(this)
}
}
}
Copy the code
Then equip the enemy with weapons at the end of js/ NPC /enemy.js, and the bullet speed is the enemy’s own speed +5
import Animation from '.. /base/animation'
import DataBus from '.. /databus'
import Bullet from '.. /player/bullet';
const ENEMY_IMG_SRC = 'images/enemy.png'// Other code...update() {this.y += this[__.speed] // Object collectionif(this.y > window.innerheight + this.height) databus.removeenemey (this)shoot() {
const bullet = databus.pool.getItemByClass('bullet', Bullet); bullet.init( this.x + this.width / 2 - bullet.width / 2, this.y + 10, this[__.speed] + 5 ); databus.bullets.push(bullet); }}Copy the code
Next, add the enemy’s firing logic to js/main.js and design when the enemy moves 5 times and 60 times.
// Other code...let ctx = canvas.getContext("2d");
letdatabus = new DataBus(); const ENEMY_SPEED = 6; // Other code... */ enemyGenerate(playerLevel) {/ enemyGenerate(playerLevel) {if (databus.frame % 60 === 0) {
let enemy = databus.pool.getItemByClass("enemy", Enemy); enemy.init(ENEMY_SPEED); databus.enemys.push(enemy); }} // Other code... // Implement the game frame looploop() {
databus.frame++;
this.update();
this.render();
if (databus.frame % 20 === 0) {
this.player.shoot();
this.music.playShoot();
}
databus.enemys.forEach(enemy => {
const enemyShootPositions = [
-enemy.height + ENEMY_SPEED * 5,
-enemy.height + ENEMY_SPEED * 60
];
if(enemyShootPositions.indexOf(enemy.y) ! == -1) { enemy.shoot(); this.music.playShoot(); }}); // The game ends and stops the frame loopif (databus.gameOver) {
this.touchHandler = this.touchEventHandler.bind(this);
canvas.addEventListener("touchstart", this.touchHandler);
this.gameinfo.renderGameOver(ctx, databus.score);
return;
}
window.requestAnimationFrame(this.loop.bind(this), canvas);
}
Copy the code
At this point we discover that player and enemy bullets are flying uncontrollably due to an unknown cosmic interference ray. Let us restore order to the world;
After detection, it was found that the acquisition logic of the object pool caused the problem of uncontrolled bullets. We need to separate the acquisition of bullets from the player and each enemy plane
First, the object gets the judgment of the object attributes we added. When an object attribute is passed in, we get the reclaimed object with the same value for all the attributes. If none is found or the object pool is empty, we create a new object with the attribute
GetItemByClass (name, className, properties) {getItemByClass(name, className, properties) {let pool = this.getPoolBySign(name)
if (pool.length === 0) return new className(properties);
if(! properties)return pool.shift();
const index = pool.findIndex(item => {
return Object.keys(properties).every(property => {
return item[property] === properties[property];
});
});
return index !== -1 ? pool.splice(index, 1)[0] : new className(properties)
}
Copy the code
To do this, we need to assign each bullet to the constructor class bullet in js/player/bullet.js
export default class Bullet extends Sprite {
constructor({ direction, owner } = { direction: 'up' }) {
super(direction === 'up' ? BULLET_IMG_SRC : BULLET_DOWN_IMG_SRC, BULLET_WIDTH, BULLET_HEIGHT)
this.direction = direction;
this.owner = owner;
}
Copy the code
Then change the js/player/index.js shoot to give the bullets created in it a home
/** * Player shooting operation * shooting timing is determined externally */shoot() {
for(let i = 0; i < this.level; i++) {
const bullet = databus.pool.getItemByClass('bullet', Bullet, { direction: 'up', owner: this });
Copy the code
Do the same with js/ NPC /enemy.js shoot
/** * Enemy firing operation * firing timing determined externally */shoot() {
const bullet = databus.pool.getItemByClass('bullet', Bullet, { direction: 'down', owner: this });
Copy the code
Finally, we need to process the logic of removeBullets in js/databus.js
/** * Bullets(bullet) {const index = this.bullets. FindIndex (b => b === bullet); bullet.visible =false
this.bullets.splice(index, 1);
this.pool.recover('bullet', bullet)
}
}
Copy the code
At this point, the enemy and my bullets will return to normal. The player will not Die if shot, so let the player Go Die. In the js/main.js collisionDetection, we add each bullet if it is an enemy bullet and determine whether it hit the player or not. If so, the game is over. The player’s bullet judgment remains the same.
// Global collision detectioncollisionDetection() {
let that = this;
databus.bullets.forEach(bullet => {
for (let i = 0, il = databus.enemys.length; i < il; i++) {
let enemy = databus.enemys[i];
if (bullet.owner instanceof Enemy) {
databus.gameOver = this.player.isCollideWith(bullet);
} else if(! enemy.isPlaying && enemy.isCollideWith(bullet)) { enemy.playAnimation(); that.music.playExplosion(); bullet.visible =false;
databus.score += 1;
break; }}});Copy the code
That’s the end of the simple transformation plan, and you can add weapon systems, boss battles, and so on. The following is the modified game animated record screen
This article was originally posted on my official account: Maple Leaf. Qr code of official account