


Use HTML5 Canvas to create a simple masturbation game_html5 tutorial skills
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:
- loadImg:function(datas){
- var _this = this;
- var dataIndex = 0;
- li();
- function li(){
- if(datas[dataIndex].indexOf("mp3")>=0){
- var audio = document.createElement("audio");
- document.body.appendChild(audio);
- audio.preload = "auto";
- audio.src = datas[dataIndex];
- audio.oncanplaythrough = function(){
- this.oncanplaythrough = null;
- dataIndex ;
- if(dataIndex===datas.length){
- _this.percent = 100;
- }else {
- _this.percent = parseInt(dataIndex/datas.length*100);
- li.call(_this);
- }
- }
- }else {
- preLoadImg(datas[dataIndex] , function(){
- dataIndex ;
- if(dataIndex===datas.length){
- _this.percent = 100;
- } else {
- _this.percent = parseInt(dataIndex/datas.length*100);
- li.call(_this);
- }
- })
- }
- }
- },
- //再贴出preLoadImg的方法
- function preLoadImg(src , callback){
- var img = new Image();
- img.src = src;
- if(img.complete){
- callback.call(img);
- }else {
- img.onload = function(){
- callback.call(img);
- }
- }
- }
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.
- W.Sprite = function(name , painter , behaviors , args){
- if(name !== undefined) this.name = name;
- if(painter !== undefined) this.painter = painter;
- this.top = 0;
- this.left = 0;
- this.width = 0;
- this.height = 0;
- this.velocityX = 3;
- this.velocityY = 2;
- this.visible = true;
- this.animating = false;
- this.behaviors = behaviors;
- this.rotateAngle = 0;
- this.blood = 50;
- this.fullBlood = 50;
- if(name==="plan"){
- this.rotateSpeed = 0.05;
- this.rotateLeft = false;
- this.rotateRight = false;
- this.fire = false;
- this.firePerFrame = 10;
- this.fireLevel = 1;
- }else if(name==="star"){
- this.width = Math.random()*2;
- this.speed = 1*this.width/2;
- this.lightLength = 5;
- this.cacheCanvas = document.createElement("canvas");
- thisthis.cacheCtx = this.cacheCanvas.getContext('2d');
- thisthis.cacheCanvas.width = this.width this.lightLength*2;
- thisthis.cacheCanvas.height = this.width this.lightLength*2;
- this.painter.cache(this);
- }else if(name==="badPlan"){
- this.badKind = 1;
- this.speed = 2;
- this.rotateAngle = Math.PI;
- }else if(name==="missle"){
- this.width = missleWidth;
- }else if(name==="boom"){
- this.width = boomWidth;
- }else if(name==="food"){
- this.width = 40;
- this.speed = 3;
- this.kind = "LevelUP"
- }
- this.toLeft = false;
- this.toTop = false;
- this.toRight = false;
- this.toBottom = false;
- this.outArcRadius = Math.sqrt((this.width/2*this.width/2)*2);
- if(args){
- for(var arg in args){
- this[arg] = args[arg];
- }
- }
- }
- Sprite.prototype = {
- constructor:Sprite,
- paint:function(){
- if(this.name==="badPlan"){this.update();}
- if(this.painter !== undefined && this.visible){
- if(this.name!=="badPlan") {
- this.update();
- }
- if(this.name==="plan"||this.name==="missle"||this.name==="badPlan"){
- ctx.save();
- ctx.translate(this.left , this.top);
- ctx.rotate(this.rotateAngle);
- this.painter.paint(this);
- ctx.restore();
- }else {
- this.painter.paint(this);
- }
- }
- },
- update:function(time){
- if(this.behaviors){
- for(var i=0;i<this.behaviors.length;i ){
- this.behaviors[i].execute(this,time);
- }
- }
XML/HTML Code
- var SpriteSheetPainter = function(cells){
- this.cells = cells || [];
- this.cellIndex = 0;
- }
- SpriteSheetPainter.prototype = {
- advance:function(){
- if(this.cellIndex === this.cells.length-1){
- this.cellIndex = 0;
- }
- else this.cellIndex ;
- },
- paint:function(sprite){
- var cell = this.cells[this.cellIndex];
- context.drawImage(spritesheet , cell.x , cell.y , cell.w , cell.h , sprite.left , sprite.top , cell.w , cell.h);
- }
- }
而普通的绘制器就更简单了,直接写一个painter,把要画的什么东西都写进去就行了。
有了精灵类和精灵表绘制器后,我们就可以把星星,飞机,子弹,爆炸对象都写出来了:下面是整个allSprite.js的代码:
- (function(W){
- "use strict"
- var planWidth = 24,
- planHeight = 24,
- missleWidth = 70,
- missleHeight = 70,
- boomWidth = 60;
- //精灵类
- W.Sprite = function(name , painter , behaviors , args){
- if(name !== undefined) this.name = name;
- if(painter !== undefined) this.painter = painter;
- this.top = 0;
- this.left = 0;
- this.width = 0;
- this.height = 0;
- this.velocityX = 3;
- this.velocityY = 2;
- this.visible = true;
- this.animating = false;
- this.behaviors = behaviors;
- this.rotateAngle = 0;
- this.blood = 50;
- this.fullBlood = 50;
- if(name==="plan"){
- this.rotateSpeed = 0.05;
- this.rotateLeft = false;
- this.rotateRight = false;
- this.fire = false;
- this.firePerFrame = 10;
- this.fireLevel = 1;
- }else if(name==="star"){
- this.width = Math.random()*2;
- this.speed = 1*this.width/2;
- this.lightLength = 5;
- this.cacheCanvas = document.createElement("canvas");
- this.cacheCtx = this.cacheCanvas.getContext('2d');
- this.cacheCanvas.width = this.width this.lightLength*2;
- this.cacheCanvas.height = this.width this.lightLength*2;
- this.painter.cache(this);
- }else if(name==="badPlan"){
- this.badKind = 1;
- this.speed = 2;
- this.rotateAngle = Math.PI;
- }else if(name==="missle"){
- this.width = missleWidth;
- }else if(name==="boom"){
- this.width = boomWidth;
- }else if(name==="food"){
- this.width = 40;
- this.speed = 3;
- this.kind = "LevelUP"
- }
- this.toLeft = false;
- this.toTop = false;
- this.toRight = false;
- this.toBottom = false;
- this.outArcRadius = Math.sqrt((this.width/2*this.width/2)*2);
- if(args){
- for(var arg in args){
- this[arg] = args[arg];
- }
- }
- }
- Sprite.prototype = {
- constructor:Sprite,
- paint:function(){
- if(this.name==="badPlan"){this.update();}
- if(this.painter !== undefined && this.visible){
- if(this.name!=="badPlan") {
- this.update();
- }
- if(this.name==="plan"||this.name==="missle"||this.name==="badPlan"){
- ctx.save();
- ctx.translate(this.left , this.top);
- ctx.rotate(this.rotateAngle);
- this.painter.paint(this);
- ctx.restore();
- }else {
- this.painter.paint(this);
- }
- }
- },
- update:function(time){
- if(this.behaviors){
- for(var i=0;i<this.behaviors.length;i ){
- this.behaviors[i].execute(this,time);
- }
- }
- }
- }
- // 精灵表绘制器
- W.SpriteSheetPainter = function(cells , isloop , endCallback , spritesheet){
- this.cells = cells || [];
- this.cellIndex = 0;
- this.dateCount = null;
- this.isloop = isloop;
- this.endCallback = endCallback;
- this.spritesheet = spritesheet;
- }
- SpriteSheetPainter.prototype = {
- advance:function(){
- this.cellIndex = this.isloop?(this.cellIndex===this.cells.length-1?0:this.cellIndex 1):(this.cellIndex 1);
- },
- paint:function(sprite){
- if(this.dateCount===null){
- this.dateCount = new Date();
- }else {
- var newd = new Date();
- var tc = newd-this.dateCount;
- if(tc>40){
- this.advance();
- this.dateCount = newd;
- }
- }
- if(this.cellIndex<this.cells.length || this.isloop){
- var cell = this.cells[this.cellIndex];
- 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);
- } else if(this.endCallback){
- this.endCallback.call(sprite);
- this.cellIndex = 0;
- }
- }
- }
- //特制飞机精灵表绘制器
- W.controllSpriteSheetPainter = function(cells , spritesheet){
- this.cells = cells || [];
- this.cellIndex = 0;
- this.dateCount = null;
- this.isActive = false;
- this.derection = true;
- this.spritesheet = spritesheet;
- }
- controllSpriteSheetPainter.prototype = {
- advance:function(){
- if(this.isActive){
- this.cellIndex ;
- if(this.cellIndex === this.cells.length){
- this.cellIndex = 0;
- this.isActive = false;
- }
- }
- },
- paint:function(sprite){
- if(this.dateCount===null){
- this.dateCount = new Date();
- }else {
- var newd = new Date();
- var tc = newd-this.dateCount;
- if(tc>sprite.firePerFrame){
- this.advance();
- this.dateCount = newd;
- }
- }
- var cell = this.cells[this.cellIndex];
- ctx.drawImage(this.spritesheet , cell.x , cell.y , cell.w , cell.h , -planWidth/2 , -planHeight/2 , cell.w , cell.h);
- }
- }
- W.planBehavior = [
- {execute:function(sprite,time){
- if(sprite.toTop){
- sprite.top = sprite.top
- }
- if(sprite.toLeft){
- sprite.left = sprite.left
- }
- if(sprite.toRight){
- sprite.left = sprite.left>canvas.width-planWidth/2? sprite.left : sprite.left sprite.velocityX;
- }
- if(sprite.toBottom){
- sprite.top = sprite.top>canvas.height-planHeight/2? sprite.top : sprite.top sprite.velocityY;
- }
- if(sprite.rotateLeft){
- sprite.rotateAngle -= sprite.rotateSpeed;
- }
- if(sprite.rotateRight){
- sprite.rotateAngle = sprite.rotateSpeed;

Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

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

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Hot Topics



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

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.

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

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

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

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

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

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