This game uses HTML5 canvas. To run the game, the browser must support HTML5.
This article explains in detail how to use HTML5 to develop a shooting game. Lightning can be said to be a classic in the shooting game. Below we will imitate it.
Let's take a look at the game.
Demo address
Http://fsanguo.comoj.com/html5/barrage2/index.html
Open-source engine: lufylegend. JS is required for game development.
Lufylegend. js Engine
Http://lufylegend.com/lufylegend
The game is expected to use the following files:
Index.html
JS folder | --- main. js
| --- Plain. js // aircraft
| --- Bullet. js // bullet
| --- Global. js // common
Images folder | -- Image
Let me briefly describe the production process. The source code is at the bottom.
First, create the index.html file,
<! Doctype HTML>
Open main. js
Add code in it, read all the images first, and display the progress bar
And add some variables that may be used.
/*** Main ** // set the game speed, screen size, and callback function Init (50, "mylegend", 480,800, main ); /** layer variable * // The layer used to display the progress bar var loadinglayer; // The lowest layer of the game var backlayer; // The control layer var ctrllayer; /** int variable * // read the Image Location var loadindex = 0; // Number of chunks var frames = 0; // boos startvar boosstart = false; // game overvar gameover = false; // game clear var gameclear = false; // score var point = 0;/** object variable * // player var player; // score var pointtext;/** array variable * // image path array var imgdata = new array (); // read the Image array var imglist = {}; // array of bullets var barrage = new array (); // array of bullet velocity var barragespeed = [5, 10]; // array of all enemy planes stored var enemys = new array (); function main () {// prepare to read the image imgdata. push ({name: "back", path :". /images/back.jpg "}); imgdata. push ({name: "enemy", path :". /images/e.png "}); imgdata. push ({name: "Player", path :". /images/player.png "}); imgdata. push ({name: "boss", path :". /images/boss.png "}); imgdata. push ({name: "Ctrl", path :". /images/ctrl.png "}); imgdata. push ({name: "Item1", path :". /images/1.png"}); // instantiate the progress bar layer loadinglayer = new lsprite (); loadinglayer. graphics. drawrect (1, "black", [50,200,200, 20], true, "# ffffff"); addchild (loadinglayer); // start reading the image LoadImage ();} function LoadImage () {// read all the images and start initializing the game if (loadindex> = imgdata. length) {removechild (loadinglayer); legendloadover (); gameinit (); Return ;}// start to read image loader = new lloader (); loader. addeventlistener (Levent. complete, loadcomplete); loader. load (imgdata [loadindex]. path, "bitmapdata");} function loadcomplete (event) {// loadinglayer is displayed on the progress bar. graphics. clear (); loadinglayer. graphics. drawrect (1, "black", [50,200,200, 20], true, "# ffffff"); loadinglayer. graphics. drawrect (1, "black", [50,203,200 * (loadindex/imgdata. length), 14], true, "#000000"); // stores the image data imglist [imgdata [loadindex]. name] = loader. content; // read the next image loadindex ++; LoadImage ();}
Now, all the images used have been loaded. First, add the background to display an image.
It is very easy to use the legend library to display images
Function gameinit (event) {// backlayer = new lsprite (); addchild (backlayer ); // Add the game background bitmapdata = new lbitmapdata (imglist ["back"]); bitmap = new lbitmap (bitmapdata); backlayer. addchild (Bitmap );}
The effect is as follows:
In a shooting game, bullets are the highlights. How to add multiple bullets is the key to the game.
To change a bullet, you must set the angle, acceleration, and other variables.
To achieve these changes, we will create a bullet class
/*** Bullet class **/function bullet (belong, X, Y, angle, xspeed, yspeed, ASpeed, speed) {base (this, lsprite, []); vaR self = This; // self to which the bullet belongs. belong = belong; // The position self appears. X = x; self. y = y; // Angle Self. angle = angle; // The moving speed self. speed = speed; // XY axis speed self. xspeed = xspeed; self. yspeed = yspeed; // Rotation Angle addition self. ASpeed = ASpeed; // var bitmapdata, bitmap; bitmapdata = new lbitmapdata (imglist ["Item1"]); bitmap = new lbitmap (bitmapdata); self. bitmap = bitmap; // display self. addchild (Bitmap );}
Then, various transformations are implemented based on these variables during bullet movement.
Add a bullet array to the common class to differentiate various bullets.
/*** Array of bullet types ** [Starting angle, adding angle, bullet speed, angle acceleration, total number of bullets, starting frequency, and muzzle rotation] **/global. bulletlist = new array ({startangle: 0, angle: 20, speed: 5, ASpeed: 0, Count: 1, shootspeed: 10, sspeed: 0 }, // 1 );
The most basic bullet in the game is, of course, one bullet each time.
Create a function for launching bullets in a common class
/*** Launch a bullet * @ Param aircraft **/global. setbullet = function (plainobject) {var I, j, OBJ, xspeed, yspeed, Kaku; // obtain the bullet attribute var bullet = Global. bulletlist [0]; // start to launch for (I = 0; I <bullet. count; I ++) {// emission angle Kaku = I * bullet. angle + bullet. startangle; // the X axis speed of the bullet X axis. xspeed = bullet. speed * Math. sin (Kaku * Math. PI/180); yspeed = barragespeed [0] * Math. cos (Kaku * Math. PI/180); // bullet instantiation OBJ = new bullet (0,210,300, Kaku, xspeed, yspeed, Bullet. ASpeed, Bullet. speed); // display the backlayer. addchild (OBJ); Barrage. push (OBJ );}};
Here, the final difference depends on the aircraft to be launched, so I added the parameter aircraft.
Now we have set up the aircraft class as follows:
/*** Airplane **/function plain (name, belong, X, Y, bullets) {base (this, lsprite, []); var self = this; // aircraft name self. name = Name; // aircraft position self. X = x; self. y = y; // The self of the plane. belong = belong; // array of bullets self. bullets = bullets; // initial bullet self. bullet = self. bullets [math. floor (math. random () * self. bullets. length)]; self. shootspeed = Global. bulletlist [self. bullet]. shootspeed; // muzzle Rotation Angle Self. sspeed = 0; // self. shootctrl = 0; // get aircraft attributes self. list = Global. getplainstatus (Self); // airplane image self. bitmap = self. list [0]; // display self. addchild (self. bitmap); // The muzzle position self. shootx = self. list [1]; self. shooty = self. list [2]; // The moving speed self. speed = self. list [3]; // aircraft hpself. HP = self. list [4]; // move self. move = [0, 0]; // Number of fired bullets self. shootcount = 0; // whether the bullet self is fired. canshoot = true; If (name = "Player") self. canshoot = false;}/***** loop **/plain. prototype. onframe = function () {var self = This; // move self. X + = self. move [0] * self. speed; self. Y + = self. move [1] * self. speed; Switch (self. name) {Case "Player": // If (self. x <0) self. X = 0; else if (self. X + self. bitmap. getwidth ()> lglobal. width) self. X = lglobal. width-self.bitmap.getWidth (); If (self. Y <0) self. y = 0; else if (self. Y + self. bitmap. getheight ()> lglobal. height) self. y = lglobal. height-self.bitmap.getHeight (); break; Case "boss": // enemy Boss move if (self. Y <0) {self. y = 0; self. move [1] = 1;} else if (self. Y + self. bitmap. getheight ()> lglobal. height) {self. y = lglobal. height-self.bitmap.getHeight (); self. move [1] =-1;} // collision detection self. hittest (); break; Case "enemy": Default: // collision detection self. hittest ();} // shot if (self. canshoot) self. shoot () ;};/*** collision detection ***/plain. prototype. hittest = function () {var self = This; var disx, DISY, SW, ew; Sw = (self. bitmap. getwidth () + self. bitmap. getheight ()/4; ew = (player. bitmap. getwidth () + player. bitmap. getheight ()/4; disx = self. X + Sw-(player. X + EW); DISY = self. Y + self. bitmap. getheight ()/2-(player. Y + player. bitmap. getheight ()/2); If (disx * disx + DISY * DISY <(SW + EW) * (SW + EW) {player. visible = false; gameover = true ;};/*** shot **/plain. prototype. shoot = function () {var self = this; if (self. shootctrl ++ <self. shootspeed) return; self. shootctrl = 0; If (self. name = "boss") {If (self. shootcount ++ % 20> 5) return;} else {If (self. shootcount ++ % 10> 5) return;} Global. setbullet (Self); If (self. name = "boss") {If (self. shootcount % 20 <5) return;} else {If (self. shootcount % 10 <5) return;} If (self. bullets. length <= 1) return; self. bullet = self. bullets [math. floor (math. random () * self. bullets. length)]; self. shootspeed = Global. bulletlist [self. bullet]. shootspeed ;};
The Code has been added with detailed comments, which is not difficult to understand.
The improved bullet categories are as follows:
/*** Bullet class **/function bullet (belong, X, Y, angle, xspeed, yspeed, ASpeed, speed) {base (this, lsprite, []); vaR self = This; // self to which the bullet belongs. belong = belong; // The position self appears. X = x; self. y = y; // Angle Self. angle = angle; // The moving speed self. speed = speed; // XY axis speed self. xspeed = xspeed; self. yspeed = yspeed; // Rotation Angle addition self. ASpeed = ASpeed; // var bitmapdata, bitmap; bitmapdata = new lbitmapdata (imglist ["Item1"]); bitmap = new lbitmap (bitmapdata); Self. bitmap = bitmap; // display self. addchild (Bitmap);}/*** cycle * @ Param bullet number **/bullet. prototype. onframe = function (INDEX) {var self = This; // The bullet moves self. X + = self. xspeed; self. Y + = self. yspeed; // If (self. ASpeed! = 0) {self. angle + = self. ASpeed; // after the bullet angle is changed, recalculate the XY axis speed self. xspeed = self. speed * Math. sin (self. angle * Math. PI/180); self. yspeed = self. speed * Math. cos (self. angle * Math. PI/180);} // If (self. x <0 | self. x> lglobal. width | self. Y <0 | self. y> lglobal. height) {// remove the backlayer from the screen. removechild (Self); // remove barrage from the bullet array. splice (index, 1);} else {self. hittest (INDEX) ;}};/*** bullet collision detection ** @ Param bullet serial number **/bullet. prototype. hittest = function (INDEX) {var self = This; var disx, DISY, SW, ew, OBJ, I; If (self. belong = player. belong) {// self-built bullet for (I = 0; I <enemys. length; I ++) {OBJ = enemys [I]; Sw = self. bitmap. getwidth ()/2; ew = obj. bitmap. getwidth ()/2; disx = self. X + Sw-(obj. X + EW); DISY = self. Y + self. bitmap. getheight ()/2-(obj. Y + obj. bitmap. getheight ()/2); // distance detection if (disx * disx + DISY * DISY <EW * EW) {obj. HP --; If (obj. HP = 0) {point + = 1; pointtext. TEXT = point; // remove the backlayer from the screen. removechild (OBJ); // remove enemys from the enemy array. splice (I, 1); If (obj. name = "boss") {gameclear = true ;}// remove the backlayer from the screen. removechild (Self); // remove barrage from the bullet array. splice (index, 1) ;}}else {// enemy bullet OBJ = player; Sw = self. bitmap. getwidth ()/2; ew = obj. bitmap. getwidth ()/2; disx = self. X + Sw-(obj. X + EW); DISY = self. Y + self. bitmap. getheight ()/2-(obj. Y + obj. bitmap. getheight ()/2); // distance detection if (disx * disx + DISY * DISY <EW * ew-10) {obj. visible = false; gameover = true; // remove the backlayer from the screen. removechild (Self); // remove barrage from the bullet array. splice (index, 1 );}}};
Modify the bullet emission function as follows:
/*** Launch a bullet * @ Param aircraft **/global. setbullet = function (plainobject) {var I, j, OBJ, xspeed, yspeed, Kaku; // obtain the bullet attribute var bullet = Global. bulletlist [plainobject. bullet]; // sets the rotation of plainobject at the gun port. sspeed + = bullet. sspeed; // start to launch for (I = 0; I <bullet. count; I ++) {// emission angle Kaku = I * bullet. angle + bullet. startangle + plainobject. sspeed; // bullet XY axis speed xspeed = bullet. speed * Math. sin (Kaku * Math. PI/180); yspeed = barragespeed [0] * Math. cos (Kaku * Math. PI/180); // The Bullet instantiation OBJ = new bullet (plainobject. belong, plainobject. X + plainobject. shootx, plainobject. Y + plainobject. shooty, Kaku, xspeed, yspeed, Bullet. ASpeed, Bullet. speed); // display the backlayer. addchild (OBJ); Barrage. push (OBJ );}};
Add a loop in the main file
/*** Loop **/function onframe () {var I; // loop bullet for (I = 0; I <barrage. length; I ++) {barrage [I]. onframe (I) ;}// cyclic enemy server for (I = 0; I <enemys. length; I ++) {enemys [I]. onframe ();}}
Now, I only need to add planes to launch bullets.
plain = new Plain("enemy",1,200,300,[0]);
View results
Modify the parameters of the bullet as follows:
/*** Array of bullet types ** [Starting angle, adding angle, bullet speed, angle acceleration, total number of bullets, starting frequency, and muzzle rotation] **/global. bulletlist = new array ({startangle: 0, angle: 20, speed: 5, ASpeed: 0, Count: 1, shootspeed: 10, sspeed: 0 }, // 1 {startangle:-20, angle: 20, speed: 5, ASpeed: 0, Count: 3, shootspeed: 10, sspeed: 0 }, // 3 {startangle: 0, angle: 20, speed: 5, ASpeed: 0, Count: 1, shootspeed: 1, sspeed: 20 }, // 1 hair rotation {startangle: 0, angle: 20, speed: 5, ASpeed: 0, Count: 18, shootspeed: 3, sspeed: 0 }, // loop {startangle: 0, angle: 20, speed: 5, ASpeed: 1, Count: 18, shootspeed: 3, sspeed: 0}, // loop rotation {startangle: 180, angle: 20, speed: 5, ASpeed: 0, Count: 1, shootspeed: 5, sspeed: 0}, // 1 up {startangle: 160, angle: 20, speed: 5, ASpeed: 0, Count: 3, shootspeed: 5, sspeed: 0} // 3 up );
The results are as follows:
The lufylegend. js engine package contains this demo. Please download the lufylegend. js engine directly to view the source code in the engine package
Lufylegend. js Engine
Http://lufylegend.com/lufylegend