The code address is as follows:
Http://www.demodashi.com/demo/12755.html
Project Introduction
This project is the use of native JS implementation of the H5 games-Plants vs Zombies, the main combination of their understanding of H5 games, combined with object-oriented programming ideas for development, in the implementation of the use of some ES6 syntax, for ES6 grammar is not familiar with the small partners can first consult the relevant information to understand.
If necessary, according to their own needs to modify the source code style, source configuration property codes, to achieve personalized customization.
The following is the file directory structure, the core code in js
the folder of four common.js
,, main.js
game.js
, scene.js
js file
Source : https://github.com/yangyunhe369/h5-game-plantsVSzombies
Demonstrate
Demo: Https://yangyunhe369.github.io/jQuery-Yys-Slider
Implementation features
- Draw a game scene: background, Sun Scoreboard, plant card (for plant), plants (6 species), Zombies (1)
- Plant and Zombie attack determination, death determination
- Character animation is a frame-by-frame picture without stopping the drawing implementation, can draw the smooth animation effect
- Character animations automatically switch depending on the status of the character, including (normal form, attack pattern), zombie animations (normal, moving, attacking, dying, dead)
- Sunlight is generated automatically, plants are placed to be consumed by sunlight, zombies spawn randomly
- Game contains zombies, plants independent victory condition determination
- Game Status: Loading, game run, game paused, game over (player wins), game over (zombie victory)
Directory structure
.├─ index.html // 首页html│ ├─ css // css样式资源文件├─ images // 图片资源文件 └─ js ├─ common.js // 公共方法 ├─ scene.js // 游戏场景相关类 ├─ game.js // 游戏主要运行逻辑 └─ main.js // 游戏运行主函数
Core Code Game engine
Game Core code is an abstract game-related function based on the ES6 class approach
Class Game {constructor () {... state:0,//game state value, initial default is 0 state_loading:0,//preparation stage state_start:1, Game start State_running:2,//game run State_stop: 3,//game pause State_plantwon:4, Game over, player wins State_zombiewon:5,//Game over, zombie victory Canvas:document.getE Lementbyid ("Canvas"),//Canvas element context:document.getElementById ("Canvas"). GetContext ("2d"),// Canvas Canvas timer:null,//Polling timer Fps:window._main.fps, Animation frame Number} init () {//initialization function Let G = this ...//set polling timer G.timer = Setinterva L (function () {//Depending on the game state, draw different game scenes in canvas}, 1000/g.fps) ...}}
In fact, the core logic is very simple, is to define a game engine main function, to generate a timer at 60 frames per second constantly canvas
drawing the game scene related elements on the canvas, and then in the timer function according to the current game state ( 游戏准备
, 游戏开始
游戏运行
游戏暂停
游戏结束
,,, ) to draw the corresponding game scene.
loading
Game state: The game engine draws a page load picture and adds a start Game button
start
Game Status: The game starts reading the countdown, reminding the user that the game is about to begin
running
Game status: Draw all the game scene footage needed to run the game
stop
Game status: The game enters the pause stage, the game in the Generation Sun, the zombie timer will clear, the character animation is in the static state
gameover
Game state: Divided into the player to win the victory and the zombie to win two cases, and draw different game billing screen
Game scene
Here I have all the controllable elements of the game in the game scene, and these elements are abstracted into classes, easy to manage, including:,,, 植物类
, 僵尸类
阳光计分板类
植物卡片类
动画类
, 子弹类
.
The two most important classes in the game scene are plant, zombie, but the animation classes are used in both of these core classes, which I'll introduce first.
Animation Class (Animation)
class Animation{ constructor (role, action, fps) { let a = { type: role.type, // 动画类型(植物、僵尸等等) section: role.section, // 植物或者僵尸类别 action: action, // 根据传入动作生成不同动画对象数组 images: [], // 当前引入动画图片对象数组 img: null, // 当前显示动画图片 imgIdx: 0, // 当前角色图片序列号 count: 0, // 计数器,控制动画运行 fps: fps, // 角色动画运行速度系数,值越小,速度越快 } Object.assign(this, a) }}
The images used here is the animation sequence that is generated and added to the images by means of the new Image ():
Where type and section are used to determine which animation sequence is currently required to load plants or zombies, which action, count and FPS are used to control the playback speed of the current animation, and IMG is used to represent the currently displayed picture object, i.e. Images[imgidx], Its relationship is similar to the following code:
// 在全局定时器中每1/60秒计算一次// 获取动画序列长度let animateLen = images.length// 计数器自增count++// 设置当前显示动画序列号imgIdx = Math.floor(count / fps)// 当一整套动画完成后重置动画计数器imgIdx === animateLen - 1 ? count = 0 : count = count// 设置当前显示动画图片img = images[imgIdx]
Character Class (role)
class role{Constructor (obj) {Let R = {id:Math.random (). toFixed (6) * MATH.POW (10, 6),//randomly generated ID value To set the current role ID, differentiate between different role type:obj.type,//role type (plant or zombie) section:obj.section, Character category (Pea shooter, double launcher ... ) x:obj.x,//x-axis coordinate y:obj.y, Y-Axis coordinates w:0,//Role picture width h:0, Character image height Row:obj.row,//character initialization line coordinate col:obj.col, Role initialization column coordinates isanimelenmax:false,//Whether in the last frame of the animation, used to determine the animation Whether to perform a round of isdel:false,//To determine if death and remove the current role Ishurt:false, Determine if you are injured} object.assign (this, R)}}
The role classes here are mainly used to abstract the common properties of plant and zombie classes, and basic properties include,,,,,,, type
section
x
y
w
h
row
col
row
and col
Properties are used to control the horizontal ordinate that the character draws on the lawn (that is, the x
axes and y
axes are located in the first squares), and section
attributes are used to distinguish between the current character, such as the Pea shooter, the Double launcher, the Gatling shooter, and the normal zombie.
Plant Class (Plant)
Class plant{Constructor (obj) {Let p = {life:3,//role Blood Volume idle : null,//Stand animated Object Attack:null,//attack Animated object bullets: [],//Bullet object array state:1, Save the current status value, default to 1 state_idle:1,//Standing state_attack:2 status, Attack Status} object.assign (this, p)}//Draw method Draw (CXT) {///according to the state of the current plant, respectively, draw positive Constant state animation, as well as the translucent state animation at the time of the injury let itself = this cxt.drawimage (self[statename].img, self.x, SELF.Y)}//update the current Plant state update () {//Animation counter to calculate the current plant display animation sequence of pictures}//To determine whether the current plant can enter the attack state Canattack () {//By polling the Zombie object array, judging the zombies in the current plant counterparts, and enter the lawn, that is, start attacking zombies There are currently only three types of Sagittarius can use bullets, cherry bombs belong to the range of damage plants (judging range of its surrounding eight lattice)//attack success, reduce the corresponding zombie blood, and when the zombie blood reaches a special value, switch its animation (such as dying state, death state), in the blood volume of 0 o'clock, from the zombie Remove current Zombie from Object array}//Shooting method Shoot () {///Current plant attack, bullets array add bullet object Let self = this self.bullets[self.bullets.length] = bullet.new (self ) }}
The private properties of the plant class include,,, and idel
attack
bullets
state
idel
attack
are animated objects, and I believe that the small partners who have seen the introduction of the animation class above should be able to understand its role, bullets
that is, to save all the bullets of the current plant (the same animation class, Bullets also have properties, method configurations, which are not described in detail here.
About the state control attributes of the plant, such as the isHurt
attribute will switch to when the plant is injured, true
and thus add a transparency to the animation, simulating the injury effect; isDel
The property removes the plant from the plant object array when the plant's blood volume drops to 0 o'clock, i.e. no longer draws the current plant; state
The property is used for the plant to switch between the two forms, that is, 普通形态
攻击形态
the current state value of which form, that is, play the corresponding morphological animation, the corresponding relationship is as follows:
state === state_IDLE => // 播放植物普通形态动画 idlestate === state_ATTACK => // 播放植物攻击形态动画 attack
The switching of attack patterns involves the need to loop through an array of current plant objects and all zombie objects to determine if zombies are within range of the current plant object (i.e., on the same row of lawn, and on screen display range).
This paper mainly introduces the related properties of plant class, including initializing Plant object, plant drawing, plant shooting, updating plant state, detecting whether the plant can attack zombies ...
Zombie Class (Zombie)
Class zombie{Constructor (obj) {let z = {life:10,//Role amount IDL E:null,//Stand animated Object Run:null,//Ben Run Animated Object Attack:null,//Attack animated object Dying:null, Near death animated Object Die:null,//Death animation object State:1, Saves the current state value, default is 1 state_idle:1,//standing motionless State State_r Un:2,//Run status State_attack:3,//attack status State_dying:4,//dying state State_die:5, Death state Canmove:true,//Determine if the current role can be moved attackplantid:0, CurrentAttack Plant Object ID Speed:3,//Move Speed} object.assign (this, z)}//Drawing method Dr AW () {///based on the status of the current zombie, draw a normal state animation, and a translucent state animation at the time of the injury let self = this cxt.drawimage (self[statename].img, self.x, sel F.Y)}//update current zombie status update () {//Animation counter calculates the picture of the current plant display animation sequence}//To determine whether the current zombie can enter the attack state Canattack () {//By polling the plant object array, judging The current zombie Canmove property will be false, recording its Attackplantid, which is the attack plant ID value, and reducing the corresponding plant blood amount when the plant is in the current zombie companion and is in the range of its attack, when the attack plant//attack succeeds. The amount of blood is 0 o'clock, switch its animation (into the death state), and remove the plant from the plant object array, and//The state of all the zombies attacking the plant to move state, Canmove attribute value to True}}
Here you can see that many of the zombie class properties are similar to plant classes, not too much to describe, because currently only one zombie has been developed, so the section
attribute is a fixed value.
Animated objects about zombies may be a little more complex than plants, containing,,,, and idle
run
attack
dying
die
Five forms of animation sequences, dying
which die
correspond to zombies ' lower blood volume ( 濒死状态
) and blood volume 0
( 死亡状态
) When the animation is played.
In the Zombie control attribute, the same as the plant, where the zombie's five animated objects also correspond to five state values, and switch with the state value of the switch.
This article mainly introduces the related properties of the zombie class, including initialization,,,, 实例化僵尸对象
绘制僵尸
僵尸攻击
更新僵尸状态
检测僵尸是否可攻击植物
...
Game Main function
In the main function of the game, will be all the previously used game related classes, to be instantiated, and saved in Main类
, here call start game start function, will open the game engine, start to draw the game scene, so the game startup function will be called immediately after the page loading.
Class Main {constructor () {Let m = {allsunval:200,///Sunshine Total Quantity Loading:null, Loading animated object Sunnum:null,//Sunshine Instance Object cars: [], instance of the Weed Cart object array Cars_info: {//Initialize parameter x:170, X-axis coordinate y:102,//y-axis coordinate position: [{row:1}, {Row:2}, {Row:3}, {Row:4}, {Row:5},],}, cards: [], Instantiate a plant Card object array Cards_info: {//Initialize parameters x:0, y:0, Position: [{name: ' Peashooter ', Row:1, sun_val:100}, {name: ' Repeater ', Row:2, sun_val:150}, {name: ' Gatlingpea ', Row:3, sun_val:200},]}, Plants: [],//Instantiate the number of plant objects Group Zombies: [], Instantiate an array of zombie objects Plants_info: {//Initialize parameter type: ' Plant ', Role type x:250,//initial x-axis coordinates, recursive increment of y:92, Initial y-coordinate, recursive increment of len:0, Position: []//section: Plant category, row: Rampage Coordinates (min. 5), col: vertical column coordinates (max. 9)}, Zombies_info: {//Initialize parameter type: ' Zombie ', Role type x:250,//x-axis coordinate y:15, Y-Axis coordinates position: []//section: Zombie category, row: Traverse coordinates (min. 9), col: vertical column coordinates (max. 13)}, zombies_idx:0,//randomly spawn zombie idx zombies_row:0,//random spawn of zombie line coordinates ZOMBIES_IMAX:50,//random spawn limit suntimer:null,//global timer, for control Global Timing Generation Sun Suntimer_dIFFERENCE:20,//Timed Daylight Time difference (in seconds) zombietimer:null,//global timer, for controlling global timing spawn Zombies Zombietimer_difference:12,//timed Spawn Zombie time difference (in seconds) game:null,//game Engine Object Fps:60,} object.assign (this, M)}//Here omit some functions introduced ...//game start function Start () {//Instantiate all classes in the game scenario chapter}}win Dow._main = new Main () Window._main.start ()
Here is a brief introduction to the plants
zombies
object array, and when the game is running, all the plants that are planted and the zombies that spawn are matched with their associated initialization parameters plants_info
, instantiated, and zombies_info
then stored in plants
zombies
an array of objects.
Native JS implementation of H5 games-Plants vs Zombies
The code address is as follows:
Http://www.demodashi.com/demo/12755.html
Note: This copyright belongs to the author, by the demo master, refused to reprint, reprint need the author authorization
Native JS implementation of H5 games-Plants vs Zombies