Home Web Front-end H5 Tutorial Use HTML5 Canvas to create a simple masturbation game_html5 tutorial skills

Use HTML5 Canvas to create a simple masturbation game_html5 tutorial skills

May 16, 2016 pm 03:46 PM
canvas html5

I saw a masturbation game in Donnet’s DEMO before, and then I took down its pictures and audio. . . . I re-wrote it just for fun. Just for entertainment. . . . . . I don't use a framework, I write all the js myself. . . . . . So this is a simple tutorial. It may be helpful to those who are new to canvas. The author has not been playing canvas for a long time and his skills are not very good. Please forgive me.

Without further ado, let’s start with the DEMO: Airplane Game. The original poster wrote this just for fun, and didn’t intend to write it into a serious game.

Let’s get into the topic: The masturbation game file includes the index.html entry file, the logic processing file of allSprite.js sprite, the loading.js loading processing file and data.js (some initialized data).

First of all, normal games basically require a loading. The loading page is used to preload data, including sprite sheet images, audio, etc. Because this is a small game, only some audio and images need to be loaded. The loading code inside is mainly the following. The others are for making loading animations. The one is relatively simple, so I won’t post it. If you are interested, just look at the console in the DEMO:

XML/HTML CodeCopy content to clipboard
  1. loadImg:function(datas){   
  2.             var _this = this;   
  3.             var dataIndex = 0;   
  4.             li();   
  5.             function li(){   
  6.                 if(datas[dataIndex].indexOf("mp3")>=0){   
  7.                     var audio = document.createElement("audio");   
  8.                     document.body.appendChild(audio);   
  9.                     audio.preload = "auto";   
  10.                     audio.src = datas[dataIndex];   
  11.                     audio.oncanplaythrough = function(){   
  12.                         this.oncanplaythrough = null;   
  13.                         dataIndex ;   
  14.                         if(dataIndex===datas.length){   
  15.                             _this.percent = 100;   
  16.                         }else {   
  17.                             _this.percent = parseInt(dataIndex/datas.length*100);   
  18.                             li.call(_this);   
  19.                         }   
  20.                     }   
  21.                 }else {   
  22.                     preLoadImg(datas[dataIndex] , function(){   
  23.                         dataIndex ;   
  24.                         if(dataIndex===datas.length){   
  25.                             _this.percent = 100;   
  26.                         } else {   
  27.                             _this.percent = parseInt(dataIndex/datas.length*100);   
  28.                             li.call(_this);   
  29.                         }   
  30.                     })   
  31.                 }   
  32.             }   
  33.         },   
  34.   
  35. //再贴出preLoadImg的方法   
  36. function preLoadImg(src , callback){   
  37.     var img = new Image();   
  38.     img.src = src;   
  39.     if(img.complete){   
  40.         callback.call(img);   
  41.     }else {   
  42.         img.onload = function(){   
  43.             callback.call(img);   
  44.         }   
  45.     }   
  46. }     


I first use an array to save the links to the files in data.js, and then determine whether these links are pictures or audios. If they are pictures, use preLoadImg to load them. The code for preloading pictures is very simple, just create a new picture. Object, then assign the link to it, and call back after loading. Audio is loaded by generating an HTML5 audio dom object and assigning the link to it. Audio has an event "canplaythrough". When the browser expects to be able to continue playing the specified audio/video without stopping for buffering, The canplaythrough event will occur, which means that when canplaythrough is called, the audio has almost been loaded and the next audio can be loaded. Just like this, after everything is loaded, the callback is made and the game starts.

The game started. A game will require many objects, so I unified them into one sprite object. The movement of each frame between different objects can be written separately using behavior.

XML/HTML CodeCopy content to clipboard
  1. W.Sprite = function(name , painter , behaviors , args){   
  2.     if(name !== undefined) this.name = name;   
  3.     if(painter !== undefined) this.painter = painter;   
  4.     this.top = 0;   
  5.     this.left = 0;   
  6.     this.width = 0;   
  7.     this.height = 0;   
  8.     this.velocityX = 3;   
  9.     this.velocityY = 2;   
  10.     this.visible = true;   
  11.     this.animating = false;   
  12.     this.behaviors = behaviors;   
  13.     this.rotateAngle = 0;   
  14.     this.blood = 50;   
  15.     this.fullBlood = 50;   
  16.     if(name==="plan"){   
  17.         this.rotateSpeed = 0.05;   
  18.         this.rotateLeft = false;   
  19.         this.rotateRight = false;   
  20.         this.fire = false;   
  21.         this.firePerFrame = 10;   
  22.         this.fireLevel = 1;   
  23.     }else if(name==="star"){   
  24.         this.width = Math.random()*2;   
  25.         this.speed = 1*this.width/2;   
  26.         this.lightLength = 5;   
  27.         this.cacheCanvas = document.createElement("canvas");   
  28.         thisthis.cacheCtx = this.cacheCanvas.getContext('2d');   
  29.         thisthis.cacheCanvas.width = this.width this.lightLength*2;   
  30.         thisthis.cacheCanvas.height = this.width this.lightLength*2;   
  31.         this.painter.cache(this);   
  32.     }else if(name==="badPlan"){   
  33.         this.badKind = 1;   
  34.         this.speed = 2;   
  35.         this.rotateAngle = Math.PI;   
  36.     }else if(name==="missle"){   
  37.         this.width = missleWidth;   
  38.     }else if(name==="boom"){   
  39.         this.width = boomWidth;   
  40.     }else if(name==="food"){   
  41.         this.width = 40;   
  42.         this.speed = 3;   
  43.         this.kind = "LevelUP"  
  44.     }  
  45.     this.toLeft = false;   
  46.     this.toTop = false;   
  47.     this.toRight = false;   
  48.     this.toBottom = false;   
  49.   
  50.     this.outArcRadius = Math.sqrt((this.width/2*this.width/2)*2);   
  51.   
  52.     if(args){   
  53.         for(var arg in args){   
  54.             this[arg] = args[arg];   
  55.         }   
  56.     }   
  57. }   
  58. Sprite.prototype = {   
  59.     constructor:Sprite,   
  60.     paint:function(){   
  61.         if(this.name==="badPlan"){this.update();}   
  62.   
  63.         if(this.painter !== undefined && this.visible){   
  64.             if(this.name!=="badPlan") {   
  65.                 this.update();   
  66.             }   
  67.             if(this.name==="plan"||this.name==="missle"||this.name==="badPlan"){   
  68.                 ctx.save();   
  69.                 ctx.translate(this.left , this.top);   
  70.                 ctx.rotate(this.rotateAngle);   
  71.                 this.painter.paint(this);   
  72.                 ctx.restore();   
  73.             }else {   
  74.                 this.painter.paint(this);   
  75.             }   
  76.         }   
  77.     },
  78. update:function(time){
  79. if(this.behaviors){
  80. for(var i=0;i<this.behaviors.length;i ){
  81. this.behaviors[i].execute(this,time);
  82.                                                                 
  83.                                                               
  84. }
  85. }
After writing the elf class, you can generate different objects by writing each painter and behavior. The next step is to write painters. Painters are divided into two types, one is ordinary painter, and the other is sprite sheet painter. Because explosion animations and airplane shooting animations cannot be done with just one picture, so you need to use It’s time to sprite sheet:



2015511181456172.png (168×24)

To draw these, you need to customize a sprite sheet painter for them. The following is the simplest sprite sheet painter. According to the complexity of the game, the sprite sheet writing method can be modified accordingly until it is suitable. However, the principles are similar, that is Just minor modifications:

2015511181533636.png (896×64)

XML/HTML Code

Copy content to clipboard
  1. var SpriteSheetPainter = function(cells){   
  2.             this.cells = cells || [];   
  3.             this.cellIndex = 0;   
  4.         }   
  5.         SpriteSheetPainter.prototype = {   
  6.             advance:function(){   
  7.                 if(this.cellIndex === this.cells.length-1){   
  8.                     this.cellIndex = 0;   
  9.                 }   
  10.                 else this.cellIndex ;   
  11.             },   
  12.             paint:function(sprite){   
  13.                 var cell = this.cells[this.cellIndex];   
  14.                 context.drawImage(spritesheet , cell.x , cell.y , cell.w , cell.h , sprite.left , sprite.top , cell.w , cell.h);   
  15.             }   
  16.         }     

而普通的绘制器就更简单了,直接写一个painter,把要画的什么东西都写进去就行了。

有了精灵类和精灵表绘制器后,我们就可以把星星,飞机,子弹,爆炸对象都写出来了:下面是整个allSprite.js的代码:

JavaScript Code复制内容到剪贴板
  1. (function(W){   
  2.     "use strict"  
  3.     var planWidth = 24,   
  4.         planHeight = 24,   
  5.         missleWidth = 70,   
  6.         missleHeight = 70,   
  7.         boomWidth = 60;   
  8.     //精灵类   
  9.     W.Sprite = function(name , painter , behaviors , args){   
  10.         if(name !== undefined) this.name = name;   
  11.         if(painter !== undefined) this.painter = painter;   
  12.         this.top = 0;   
  13.         this.left = 0;   
  14.         this.width = 0;   
  15.         this.height = 0;   
  16.         this.velocityX = 3;   
  17.         this.velocityY = 2;   
  18.         this.visible = true;   
  19.         this.animating = false;   
  20.         this.behaviors = behaviors;   
  21.         this.rotateAngle = 0;   
  22.         this.blood = 50;   
  23.         this.fullBlood = 50;   
  24.         if(name==="plan"){   
  25.             this.rotateSpeed = 0.05;   
  26.             this.rotateLeft = false;   
  27.             this.rotateRight = false;   
  28.             this.fire = false;   
  29.             this.firePerFrame = 10;   
  30.             this.fireLevel = 1;   
  31.         }else if(name==="star"){   
  32.             this.width = Math.random()*2;   
  33.             this.speed = 1*this.width/2;   
  34.             this.lightLength = 5;   
  35.             this.cacheCanvas = document.createElement("canvas");   
  36.             this.cacheCtx = this.cacheCanvas.getContext('2d');   
  37.             this.cacheCanvas.width = this.width this.lightLength*2;   
  38.             this.cacheCanvas.height = this.width this.lightLength*2;   
  39.             this.painter.cache(this);   
  40.         }else if(name==="badPlan"){   
  41.             this.badKind = 1;   
  42.             this.speed = 2;   
  43.             this.rotateAngle = Math.PI;   
  44.         }else if(name==="missle"){   
  45.             this.width = missleWidth;   
  46.         }else if(name==="boom"){   
  47.             this.width = boomWidth;   
  48.         }else if(name==="food"){   
  49.             this.width = 40;   
  50.             this.speed = 3;   
  51.             this.kind = "LevelUP"  
  52.         }   
  53.         this.toLeft = false;   
  54.         this.toTop = false;   
  55.         this.toRight = false;   
  56.         this.toBottom = false;   
  57.   
  58.         this.outArcRadius = Math.sqrt((this.width/2*this.width/2)*2);   
  59.   
  60.         if(args){   
  61.             for(var arg in args){   
  62.                 this[arg] = args[arg];   
  63.             }   
  64.         }   
  65.     }   
  66.     Sprite.prototype = {   
  67.         constructor:Sprite,   
  68.         paint:function(){   
  69.             if(this.name==="badPlan"){this.update();}   
  70.   
  71.             if(this.painter !== undefined && this.visible){   
  72.                 if(this.name!=="badPlan") {   
  73.                     this.update();   
  74.                 }  
  75.                 if(this.name==="plan"||this.name==="missle"||this.name==="badPlan"){   
  76.                     ctx.save();   
  77.                     ctx.translate(this.left , this.top);   
  78.                     ctx.rotate(this.rotateAngle);   
  79.                     this.painter.paint(this);   
  80.                     ctx.restore();   
  81.                 }else {   
  82.                     this.painter.paint(this);   
  83.                 }   
  84.             }   
  85.         },   
  86.         update:function(time){   
  87.             if(this.behaviors){   
  88.                 for(var i=0;i<this.behaviors.length;i ){   
  89.                     this.behaviors[i].execute(this,time);   
  90.                 }   
  91.             }   
  92.         }   
  93.     }  
  94.   
  95.     // 精灵表绘制器   
  96.     W.SpriteSheetPainter = function(cells , isloop , endCallback , spritesheet){   
  97.         this.cells = cells || [];   
  98.         this.cellIndex = 0;   
  99.         this.dateCount = null;   
  100.         this.isloop = isloop;   
  101.         this.endCallback = endCallback;   
  102.         this.spritesheet = spritesheet;   
  103.     }   
  104.     SpriteSheetPainter.prototype = {   
  105.         advance:function(){   
  106.             this.cellIndex = this.isloop?(this.cellIndex===this.cells.length-1?0:this.cellIndex 1):(this.cellIndex 1);   
  107.         },   
  108.         paint:function(sprite){   
  109.             if(this.dateCount===null){   
  110.                 this.dateCount = new Date();   
  111.             }else {   
  112.                 var newd = new Date();   
  113.                 var tc = newd-this.dateCount;   
  114.                 if(tc>40){   
  115.                     this.advance();   
  116.                     this.dateCount = newd;   
  117.                 }   
  118.             }  
  119.             if(this.cellIndex<this.cells.length || this.isloop){   
  120.                 var cell = this.cells[this.cellIndex];   
  121.                 ctx.drawImage(this.spritesheet , cell.x , cell.y , cell.w , cell.h , sprite.left-sprite.width/2 , sprite.top-sprite.width/2 , cell.w , cell.h);   
  122.             } else if(this.endCallback){   
  123.                 this.endCallback.call(sprite);   
  124.                 this.cellIndex = 0;   
  125.             }   
  126.         }   
  127.     }   
  128.   
  129.     //特制飞机精灵表绘制器   
  130.     W.controllSpriteSheetPainter = function(cells , spritesheet){   
  131.         this.cells = cells || [];   
  132.         this.cellIndex = 0;   
  133.         this.dateCount = null;   
  134.         this.isActive = false;   
  135.         this.derection = true;   
  136.         this.spritesheet = spritesheet;   
  137.     }  
  138.     controllSpriteSheetPainter.prototype = {   
  139.         advance:function(){   
  140.             if(this.isActive){   
  141.                 this.cellIndex ;   
  142.                 if(this.cellIndex === this.cells.length){   
  143.                     this.cellIndex = 0;   
  144.                     this.isActive = false;   
  145.                 }   
  146.             }   
  147.         },   
  148.         paint:function(sprite){   
  149.             if(this.dateCount===null){   
  150.                 this.dateCount = new Date();   
  151.             }else {   
  152.                 var newd = new Date();   
  153.                 var tc = newd-this.dateCount;   
  154.                 if(tc>sprite.firePerFrame){   
  155.                     this.advance();   
  156.                     this.dateCount = newd;   
  157.                 }   
  158.             }   
  159.             var cell = this.cells[this.cellIndex];   
  160.             ctx.drawImage(this.spritesheet , cell.x , cell.y , cell.w , cell.h , -planWidth/2 , -planHeight/2 , cell.w , cell.h);   
  161.         }  
  162.     }   
  163.   
  164.     W.planBehavior = [   
  165.         {execute:function(sprite,time){   
  166.             if(sprite.toTop){   
  167.                 sprite.top = sprite.top
  168.             }   
  169.             if(sprite.toLeft){   
  170.                 sprite.left = sprite.left
  171.             }   
  172.             if(sprite.toRight){   
  173.                 sprite.left = sprite.left>canvas.width-planWidth/2? sprite.left : sprite.left sprite.velocityX;   
  174.             }   
  175.             if(sprite.toBottom){   
  176.                 sprite.top = sprite.top>canvas.height-planHeight/2? sprite.top : sprite.top sprite.velocityY;   
  177.             }   
  178.             if(sprite.rotateLeft){   
  179.                 sprite.rotateAngle -= sprite.rotateSpeed;   
  180.             }   
  181.             if(sprite.rotateRight){   
  182.                 sprite.rotateAngle  = sprite.rotateSpeed;   
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

Table Border in HTML Table Border in HTML Sep 04, 2024 pm 04:49 PM

Guide to Table Border in HTML. Here we discuss multiple ways for defining table-border with examples of the Table Border in HTML.

Nested Table in HTML Nested Table in HTML Sep 04, 2024 pm 04:49 PM

This is a guide to Nested Table in HTML. Here we discuss how to create a table within the table along with the respective examples.

HTML margin-left HTML margin-left Sep 04, 2024 pm 04:48 PM

Guide to HTML margin-left. Here we discuss a brief overview on HTML margin-left and its Examples along with its Code Implementation.

HTML Table Layout HTML Table Layout Sep 04, 2024 pm 04:54 PM

Guide to HTML Table Layout. Here we discuss the Values of HTML Table Layout along with the examples and outputs n detail.

HTML Input Placeholder HTML Input Placeholder Sep 04, 2024 pm 04:54 PM

Guide to HTML Input Placeholder. Here we discuss the Examples of HTML Input Placeholder along with the codes and outputs.

Moving Text in HTML Moving Text in HTML Sep 04, 2024 pm 04:45 PM

Guide to Moving Text in HTML. Here we discuss an introduction, how marquee tag work with syntax and examples to implement.

HTML Ordered List HTML Ordered List Sep 04, 2024 pm 04:43 PM

Guide to the HTML Ordered List. Here we also discuss introduction of HTML Ordered list and types along with their example respectively

HTML onclick Button HTML onclick Button Sep 04, 2024 pm 04:49 PM

Guide to HTML onclick Button. Here we discuss their introduction, working, examples and onclick Event in various events respectively.

See all articles