尝试用canvas写小游戏

还是习惯直接开门见山,这个游戏是有一个老师抓作弊的学生,老师背身,点学生开始加分,老师会不定时回头,如果老师回头还在点学生在,就会被抓住,游戏game over。

1、写游戏首先是loading条,于是我们就有了以下的一端js代码

function game() {
    var that = this;
    this.isStart = false;
    this.isFlag = true;
    this.percent = 0;

    this.init = function () {

    }

    this.loading = function (percent) {
        this.percent = this.percent + percent;
        $("#progressbarbj").css("width", this.percent + "%");
        $(".game-percent").text(this.percent);
        if (this.percent == 100) {
            $(".game-loading").animate({ top: "-100%" }, 500, function () {
                that.isStart = true;
                that.start();
            });
        }
    };

    this.start = function () {

    };
}

以上代码可以看出,对外开放了一个Init的function,在页面里面调用Init,既可以完成游戏的初始化,因为加载是多段的,所以封装了一个Loading方法,用来加载各类图片资源。

2、游戏里面的角色分为,老师和学生(分左右两个学生),于是我们定义了三段配置。

var role_config = {
    teacher: {
        first: {
            path: "img/10001.png"
        },
        front: {
            imgs: [
               { path: "img/10001.png?v=2" },
               { path: "img/10002.png?v=2" },
               { path: "img/10003.png?v=2" },
               { path: "img/10004.png?v=2" },
               { path: "img/10005.png?v=2" },
               { path: "img/10006.png?v=2" },
               { path: "img/10007.png?v=2" },
               { path: "img/10008.png?v=2" }
                  ],
            time: 50,
            isLoop: true,
            loopTime: 500
        },
        trunback: {
            imgs: [{ path: "img/20001.png" }, { path: "img/20002.png" }, { path: "img/20003.png" }, { path: "img/20004.png"}],
            time: 50
        },
        back: {
            imgs: [
                { path: "img/30001.png?v=2" },
                { path: "img/30002.png?v=2" },
                { path: "img/30003.png?v=2" },
                { path: "img/30004.png?v=2" },
                { path: "img/30005.png?v=2" }
                  ],
            time: 50,
            isLoop: true,
            loopTime: 400
        },
        strun: {
            imgs: [
                { path: "img/40001.png?v=2" },
                { path: "img/40002.png?v=2" },
                { path: "img/40003.png?v=2" },
                { path: "img/40004.png?v=2" },
                { path: "img/40005.png?v=2" },
                { path: "img/40006.png?v=2" },
                { path: "img/40007.png?v=2" }
                ],
            time: 50
        },
        trunfront: {
            imgs: [
                { path: "img/50001.png?v=2" },
                { path: "img/50002.png?v=2" },
                { path: "img/50003.png?v=2" },
                { path: "img/50004.png?v=2" },
                { path: "img/50005.png?v=2" }
                ],
            time: 50
        },
        catchup: {
            imgs: [
                { path: "img/60001.png?v=2" },
                { path: "img/60002.png?v=2" },
                { path: "img/60003.png?v=2" },
                { path: "img/60004.png?v=2" },
                { path: "img/60005.png?v=2" },
                { path: "img/60006.png?v=2" },
                { path: "img/60007.png?v=2" },
                { path: "img/60008.png?v=2" }
             ],
            time: 50
        }
    },
    studentLeft: {
        up: {
            imgs: [{ path: "img/student_10001.png"}],
            time: 100
        },
        bow: {
            imgs: [
                { path: "img/student_10002.png" },
                { path: "img/student_10005.png" },
                { path: "img/student_10006.png" }
             ],
            time: 100,
            isRandom: true
        }
    },
    studentRight: {
        up: {
            imgs: [{ path: "img/student_10003.png"}],
            time: 100
        },
        bow: {
            imgs: [
                { path: "img/student_10004.png" },
                { path: "img/student_10007.png" },
                { path: "img/student_10008.png" }
            ],
            time: 100,
            isRandom: true
        }
    }
};

front、back、trunback、up等,均为动作,其中的time是图片切换的时长,这样就可以调解动画的速度,loopTime,是单轮循环的时长,因为图片切换到最后一张了以后,可能会有停顿。

3、开始写角色类了。

首先我们定义了一个角色的基类,代码如下:

function role(target) {
    var that = this;
    this.target = target;
    this.actionHandler;
    this.clearHandler;
    this.index = 0;
    this.load = function (array, holder, point, total, callback) {
        var index = 0;
        for (var i = 0; i < array.length; i++) {
            var img = new Image();
            img.src = array[i].path;
            var p = {
                img: img,
                x: point.x,
                y: point.y,
                w: point.w,
                h: point.h
            };
            holder.push(p);
            img.onload = function () {
                index++;
                if (index == total - 1) {
                    that.invoke(callback);
                }
            };
        }
    };
    this.animate = function (points, model, callback) {
        var loopTime = model.loopTime || 1000;
        if (this.clearHandler) {
            clearInterval(this.clearHandler);
        }
        if (model.isRandom) {
            var random = Math.random();
            var index = Math.floor(random * points.length);
            var p = [];
            p.push(points[index]);
            this.action(p, model.time, callback);
        } else {
            this.action(points, model.time, callback);
        }
        if (model.isLoop) {
            this.clearHandler = setInterval(function () {
                that.action(points, model.time, callback);
            }, loopTime);
        }
    };

    this.action = function (points, time, callback) {
        var i = 0;
        if (this.actionHandler) {
            clearInterval(this.actionHandler);
        }
        var point = points[i];
        this.draw(point);
        i++;
        this.actionHandler = setInterval(function () {
            if (i == points.length) {
                clearInterval(that.actionHandler);
                that.invoke(callback);
                return;
            }
            point = points[i];
            that.draw(point);
            i++;
        }, time);
    };
    this.draw = function (point) {
        this.target.clearRect(point.x, point.y, point.w, point.h);
        this.target.beginPath();
        this.target.drawImage(point.img, point.x, point.y, point.w, point.h);
        this.target.fill();
    };
    this.invoke = function (callback) {
        if (typeof callback == "function") {
            callback();
        }
    };
    this.stop = function (callback) {
        if (this.actionHandler) {
            clearInterval(this.actionHandler);
        }
        if (this.clearHandler) {
            clearInterval(this.clearHandler);
        }
        this.invoke(callback);
    };
};

我们有个draw方法用来绘制,有个action方法用来连续绘制形成动画,有个animate则是根据逻辑进行动画播放了。

接着我们开始写teacher类和Student类,代码如下:

function teacher(target) {
    role.call(this, target);
    var that = this;
    this.model;
    this.first = {};
    this.imgs = {
        front: [],
        trunback: [],
        back: [],
        strun: [],
        trunfront: [],
        catchup:[]
    };
    this.init = function (point, callback) {
        this.model = role_config.teacher;
        this.load(this.model.front.imgs, this.imgs.front, point, this.model.front.imgs.length, callback);
    };
    this.loadtrunback = function (point, callback) {
        this.load(this.model.trunback.imgs, this.imgs.trunback, point, this.model.trunback.imgs.length, callback);
    };
    this.loadback = function (point, callback) {
        this.load(this.model.back.imgs, this.imgs.back, point, this.model.back.imgs.length, callback);
    };
    this.loadstrun = function (point, callback) {
        this.load(this.model.strun.imgs, this.imgs.strun, point, this.model.strun.imgs.length, callback);
    };
    this.loadtrunfront = function (point, callback) {
        this.load(this.model.trunfront.imgs, this.imgs.trunfront, point, this.model.trunfront.imgs.length, callback);
    };
    this.loadcatchup = function (point, callback) {
        this.load(this.model.catchup.imgs, this.imgs.catchup, point, this.model.catchup.imgs.length, callback);
    };
    this.front = function (callback) {
        this.animate(this.imgs.front, this.model.front, callback);
    };
    this.trunback = function (callback) {
        this.animate(this.imgs.trunback, this.model.trunback, callback);
    };
    this.back = function (callback) {
        this.animate(this.imgs.back, this.model.back, callback);
    };
    this.strun = function (callback) {
        this.animate(this.imgs.strun, this.model.strun, callback);
    };
    this.trunfront = function (callback) {
        this.animate(this.imgs.trunfront, this.model.trunfront, callback);
    };
    this.catchup = function (callback) {
        this.animate(this.imgs.catchup, this.model.catchup, callback);
    };
}

function studentLeft(target) {
    role.call(this, target);
    var that = this;
    this.model;
    this.first = {};
    this.imgs = {
        bow: [],
        up: []
    };
    this.init = function (point, callback) {
        this.model = role_config.studentLeft;
        this.load(this.model.up.imgs, this.imgs.up, point, this.model.bow.imgs.length);
        this.load(this.model.bow.imgs, this.imgs.bow, point, this.model.bow.imgs.length, callback);
    };
    this.bow = function (callback) {
        this.animate(this.imgs.bow, this.model.bow, callback);
    };
    this.up = function (callback) {
        this.animate(this.imgs.up, this.model.up, callback);
    };
}

function studentRight(target) {
    role.call(this, target);
    var that = this;
    this.model;
    this.imgs = {
        bow: [],
        up: []
    };
    this.init = function (point, callback) {
        this.model = role_config.studentRight;
        this.load(this.model.up.imgs, this.imgs.up, point, this.model.bow.imgs.length);
        this.load(this.model.bow.imgs, this.imgs.bow, point, this.model.bow.imgs.length, callback);
    };
    this.bow = function (callback) {
        this.animate(this.imgs.bow, this.model.bow, callback);
    };
    this.up = function (callback) {
        this.animate(this.imgs.up, this.model.up, callback);
    };
}

分别继承于role,然后有一些自己的动作。

4、然后就是拼接了,根据游戏逻辑来拼接各个动作,于是我们最初的game类,就有了充实,代码如下:

function game() {
    var that = this;
    this.teacher;
    this.studentLeft;
    this.studentRight;
    this.isOver = false;
    this.isStart = false;
    this.isFlag = true;
    this.index = 0;
    this.success = false;
    this.username = ‘‘;
    this.percent = 0;
    this.number = 0;
    this.overHandler;
    this.left = {};
    this.right = {};
    this.time = 0;
    this.score = 0;
    this.number = 0;
    this.status = 0;
    this.interval = 0;
    this.sInterval = 0;
    this.level = [3, 2, 1];
    this.difficulty = 0;
    this.gameTime = 1000;
    this.ticket = ‘‘;
    this.totalScore = 0;
    this.totalRankingCount = 0;
    this.init = function () {
        this.left = {
            scoreContainer: ".game-score-left",
            name: "left",
            isPress: false,
            handler: null,
            score: 0,
            step: 5,
            time: 0
        };
        this.right = {
            scoreContainer: ".game-score-right",
            name: "right",
            isPress: false,
            handler: null,
            score: 0,
            step: 5,
            time: 0
        };

        var teacher_board = document.getElementById("gameteacher");
        var studentLeft_board = document.getElementById("gamestudentleft");
        var studentRight_board = document.getElementById("gamestudentright");

        this.teacher = new teacher(teacher_board.getContext("2d"));
        this.studentLeft = new studentLeft(studentLeft_board.getContext("2d"));
        this.studentRight = new studentRight(studentRight_board.getContext("2d"));

        this.teacher.init({ x: 0, y: 0, w: teacher_board.width, h: teacher_board.height }, function () {
            that.loading(10);
        });
        this.teacher.loadtrunback({ x: 0, y: 0, w: teacher_board.width, h: teacher_board.height }, function () {
            that.loading(10);
        });
        this.teacher.loadback({ x: 0, y: 0, w: teacher_board.width, h: teacher_board.height }, function () {
            that.loading(10);
        });
        this.teacher.loadstrun({ x: 0, y: 0, w: teacher_board.width, h: teacher_board.height }, function () {
            that.loading(10);
        });
        this.teacher.loadtrunfront({ x: 0, y: 0, w: teacher_board.width, h: teacher_board.height }, function () {
            that.loading(10);
        });
        this.teacher.loadcatchup({ x: 0, y: 0, w: teacher_board.width, h: teacher_board.height }, function () {
            that.loading(10);
        });
        this.studentLeft.init({ x: 0, y: 0, w: studentLeft_board.width, h: studentLeft_board.height }, function () {
            that.loading(20);
        });
        this.studentRight.init({ x: 0, y: 0, w: studentRight_board.width, h: studentRight_board.height }, function () {
            that.loading(20);
        });
    };
    this.loading = function (percent) {
        this.percent = this.percent + percent;
        $("#progressbarbj").css("width", this.percent + "%");
        $(".game-percent").text(this.percent);
        if (this.percent == 100) {
            $(".game-loading").animate({ top: "-100%" }, 500, function () {
                that.isStart = true;
                that.start();
                that.event();
            });
        }
    };
    this.start = function () {
        this.isFlag = false;
        that.studentLeft.up();
        that.studentRight.up();
        $(".game-time-text").text((this.gameTime - this.time).toFixed(1));
        this.teacher.front(function () {
            that.teacher.trunback(function () {
                that.status = status_config.back;
                that.isFlag = true;
                that.teacher.back();
            });
        });
        this.listen();
    };

    this.listen = function () {
        this.overHandler = setInterval(function () {
            if (that.isStart && !that.isOver) {
                that.isCatch();
                that.startCount();
                if (that.isFlag) {
                    if (that.status == status_config.back) {
                        that.front(that.level[that.difficulty]);
                    } else {
                        that.back();
                    }
                }
            }
        }, 100);
    };

    this.gameOver = function () {
        this.teacher.catchup(function () {
            $(".game-catch-up").show();
        });
    };

    this.timeEnd = function () {
        $(".game-over").show();
    };

    this.gameEnd = function () {
        this.isOver = true;
        if (this.overHandler) {
            clearInterval(this.overHandler);
        }
    };

    this.front = function (intervel) {
        var r = Math.random();
        if (this.time - this.interval >= intervel) {
            if (r < 0.6) {
                this.isFlag = false;
                this.teacher.trunfront(function () {
                    that.interval = that.time;
                    that.status = status_config.front;
                    that.isFlag = true;
                    that.teacher.front();
                });
            }
        } else if (this.time - this.sInterval >= 1) {
            if (r < 0.1) {
                this.isFlag = false;
                that.sInterval = that.time;
                this.teacher.strun(function () {
                    that.isFlag = true;
                    that.teacher.back();
                });
            }
        }
    };

    this.back = function () {
        var r = Math.random();
        if (this.time - this.interval >= 1) {
            if (r < 0.8) {
                this.isFlag = false;
                that.status = status_config.back;
                this.teacher.trunback(function () {
                    that.interval = that.time;
                    that.isFlag = true;
                    that.teacher.back();
                });
            }
        }
    };

    this.isCatch = function () {
        if (!this.isOver) {
            if (this.status == status_config.front) {
                if (this.left.isPress || this.right.isPress) {
                    this.catchUp();
                    return true;
                }
            }
        }
        return false;
    };

    this.catchUp = function () {
        this.gameEnd(that.gameOver());
    };

    this.startCount = function () {
        this.time = this.time + 0.1;
        this.difficulty = parseInt(this.time / 10);
        this.difficulty = this.difficulty >= this.level.length ? this.level.length - 1 : this.difficulty;
        this.score = this.left.score + this.right.score;
        $(".game-score-text").text(this.score);
        if (this.time >= this.gameTime) {
            this.timeEnd(that.gameEnd());
        }
    };

    this.pressDown = function (model) {
        if (model.handler) {
            clearInterval(model.handler);
        }
        if (this.isStart && !this.isOver) {
            model.score = model.score + model.step;
            model.isPress = true;
            this.scoreAction(model.step, model.scoreContainer);
            model.handler = setInterval(function () {
                if (model.isPress) {
                    model.time = model.time + 0.2;
                    if (model.time >= 0.6) {
                        model.step = 10;
                    }
                    if (model.time >= 1.2) {
                        model.step = 50;
                    }
                    if (model.time >= 1.8) {
                        model.step = 100;
                    }
                    model.score = model.score + model.step;
                    that.scoreAction(model.step, model.scoreContainer);
                }
            }, 200);
        }
    };
    this.scoreAction = function (score, container) {
        var img = $(‘<img src="img/‘ + score + ‘.png" />‘);
        $(container).append(img);
        img.animate({ "top": "-60" }, 500, function () {
            setTimeout(function () {
                img.fadeOut(1000, function () {
                    img.remove();
                });
            }, 1000);
        });
    };

    this.pressUp = function (model) {
        clearInterval(model.handler);
        model.isPress = false;
        model.time = 0;
        model.step = 5;
    };

    this.event = function () {
        $(".game-student-left").bind({
            "mousedown": function () {
                that.studentLeft.bow();
                that.pressDown(that.left);
                return false;
            },
            "mouseup": function () {
                that.studentLeft.up();
                that.pressUp(that.left);
                return false;
            },
            "touchstart": function () {
                that.studentLeft.bow();
                that.pressDown(that.left);
                return false;
            },
            "touchend": function () {
                that.studentLeft.up();
                that.pressUp(that.left);
                return false;
            }
        });
        $(".game-student-right").bind({
            "mousedown": function () {
                that.studentRight.bow();
                that.pressDown(that.right);
                return false;
            },
            "mouseup": function () {
                that.studentRight.up();
                that.pressUp(that.right);
                return false;
            },
            "touchstart": function () {
                that.studentRight.bow();
                that.pressDown(that.right);
                return false;
            },
            "touchend": function () {
                that.studentRight.up();
                that.pressUp(that.right);
                return false;
            }
        });
    };
};
var status_config = {
    front: 0,
    back: 1
}

代码到这里就结束了,是不是很简单,欢迎各位大神指正,小弟刚学js,只因C#博文都没人赞,所以试试js看看。

时间: 2024-10-28 14:32:19

尝试用canvas写小游戏的相关文章

JS写小游戏(一):游戏框架

前言 前一阵发现一个不错的网站,都是一些用html5+css+js写的小游戏,于是打算学习一番,写下这个系列博客主要是为了加深理解,当然也有一些个人感悟,如果英文好可以直接Click Here. 概述 一般,小游戏都要关注两个问题:刷新和交互.因为游戏一般是动态的,所以需要不断刷新.JavaScript是单线程,如果用C语言写过贪吃蛇之类的小游戏,应该知道,单线程一般是挂起一个时间来达到动态效果.比如C语言的Sleep(),JS的setInterval()等.但是js还有一种更高性能的方法req

Canvas 2D小游戏开发总结-1

由于需要快速开发 在拿到需求时,并没有时间去学习Cocos2d-JS\Egret\lufy legend这样的H5游戏引擎 于是硬着头皮直接用js建模.响应用户.渲染画面 在此要感谢这篇文章http://www.lostdecadegames.com/how-to-make-a-simple-html5-canvas-game/给我的启发 然后我罗列一下开发过程中遇到的问题,以便更好地完善自己的游戏框架 1.按钮问题dom vs canvas 有时候有代码洁癖,会觉得用canvas做代码看起来干

利用canvas制作小游戏的关键点

主要就这四个思路: 游戏图片素材需要全部加载完成后,才初始化游戏 利用new Image(), 将所有数据存放在dataStore.js中,通过单例模式,让全局都可以调用同一个堆内存中的数据 canvas图片素材,是通过将图片剪切,放置在画布上,所以可以写成一个公用JS,ctx.drawImage(img,startX,startY,endX,endY,x,y,width,height) 小游戏绘制的刷新不再是用定时器,而是通过帧率的刷新方法,不停的刷新,给人视觉误差,看起来就像动画一样 let

简单的canvas祖玛小游戏

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Typ

尝试用 Python 写了个病毒传播模拟程序

病毒扩散仿真程序,用 python 也可以. 概述 事情是这样的,B 站 UP 主 @ele 实验室,写了一个简单的疫情传播仿真程序,告诉大家在家待着的重要性,视频相信大家都看过了,并且 UP 主也放出了源码. 因为是 Java 开发的,所以开始我并没有多加关注.后来看到有人解析代码,发现我也能看懂,然后就琢磨用 Python 应该怎么实现. Java 版程序浅析 一个人就是 1 个(x, y)坐标点,并且每个人有一个状态. public class Person extends Point {

1000行代码写小游戏(终)

最后献上完整的1000行代码,基本功能已经完成,可以通过配置小怪和矿的位置和大小控制玩家时长和难度: -------------------------------------------------------------------------------------------- -- Added by ??? ------------------------------------------------------------------------------------------

用原生js写小游戏--Flappy Bird

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> <style type="text/css"> body { margin: 0; padding: 0; } #game { width: 800px; height: 600px; border: 1px

关于第一次用java写小游戏(贪吃蛇)的体会记录

作为一只菜鸡,对于编程的世界还一无所知,但是感觉应该要写点实用的东西.突然发现好像贪吃蛇应该能写出来(那种几乎没有用户界面的),于是就开始了. 1.关于对简单的动画呈现的资料准备 因为只有一些捉襟见肘的知识,所以这些资料还得一步步来. 首先我发现动画呈现和键盘输入这些都可以用 awt/swing + Thread线程类 的组合来搞定.首先是线程类在这方面的应用 2 关于主面板(JFrame 和 JPanel) 和 画图工具Graphics JPanel 和其子类可以被添加到JFrame中 作为一

DOM+CSS3实现小游戏SwingCopters

前些日子看到了一则新闻,flappybird原作者将携新游戏SwingCopters来袭,准备再靠这款姊妹篇游戏引爆大众眼球.就是下面这个小游戏: 前者的传奇故事大家都有耳闻,至于这第二个游戏能否更加火爆那是后话了.不过我看了作者的宣传视频后,蠢蠢欲动,这么简单的小游戏我山寨一个网页版出来如何?简单思索一下,打算用DOM+CSS3来实现一个.一来强化一个下自己的CSS3知识,二来也探索下用原生DOM来做动画的性能到底如何. 三四天后,原作者的SwingCopters貌似没怎么火起来,看来flap