记得以前玩过一个很简略的小游戏,一个球在动,而后底下一个板来接,如果没接住撞到底边游戏就完结了,尽管忘了它叫什么名字,但始终心心念念,魂牵梦萦,刚好最近临过年需要不饱和、刚好之前始终想做然而没入手,刚好这两天在学习konvajs,刚好就有了这篇小文章,很简略,只有三步,包你三分钟学会。

konvajs简介

konvajs就像jquery之于DOMSnap.svg之与svg一样之于canvas,能够不便的实现canvas的图形交互成果,应用它,你能够疾速绘制罕用图形,并能不便的给它增加款式、各种事件、动画成果等等,妈妈再也不必放心我本人来检测鼠标地位了。文档:https://konvajs.org/。

应用konvajs基本上也分为三步,第一步是创立一个"舞台":

import { Stage } from 'konva'const stage = new Stage({    container: 'container',// 容器元素的id    width: 500,    height: 500})

第二步是创立一个“图层”,增加到“舞台”里:

import { Layer } from 'konva'const layer = new Layer()stage.add(layer)

一个layer对应着一个canvas元素。

第三步就是创立各种图形增加到“图层里”。

第一步

来一个小球和挡板。

间接复制官网文档上的圆和矩形的示例代码,小球:

import { Circle } from 'konva'createCircle () {    // 小球的核心坐标    this.centerX = this.stage.width() / 2    this.centerY = 100    this.circle = new Circle({        x: this.centerX,        y: this.centerY,        radius: this.radius,        fill: 'red',        stroke: 'black',        strokeWidth: 4    })    this.layer.add(this.circle)    this.layer.draw()// 从新绘制,每次批改后都须要调用该办法}

挡板:

import { Rect } from 'konva'createRect () {    this.rect = new Rect({        x: (this.stage.width() - 100) / 2,        y: this.height - 50,        width: 100,        height: 10,        fill: 'green',        stroke: 'black',        strokeWidth: 4,        draggable: true,// 容许拖动        dragBoundFunc: function (pos) {// 管制只能程度拖动            return {                x: pos.x,                y: this.absolutePosition().y// 获取y的相对地位            }        }    })    this.layer.add(this.rect)    this.layer.draw()}

第二步

让球动起来,给球一个初始速度,一个加速度,撞墙后速度反向,速度逐步放慢,用来减少游戏难度:

this.speedX = Math.random() * 3this.speedY = Math.random() * 3this.speedStep = 0.01runCircle () {    // 批改小球地位    this.centerX += this.speedX    this.centerY += this.speedY    this.circle.x(this.centerX)    this.circle.y(this.centerY)    // 撞墙检测    if (this.centerX - this.radius <= 0 || this.centerX + this.radius >= this.width) {// 左侧和右侧的墙        this.speedX = -this.speedX// 程度速度反向    }    if (this.centerY - this.radius <= 0) {// 只判断顶部的墙,底部的墙用来完结游戏        this.speedY = -this.speedY    }    // 撞板检测,第三步再说    this.collisionCheck()    // 游戏完结检测    if (this.centerY + this.radius >= this.height) {// 撞到底部的墙游戏就完结了        return this.gameOver()    }    // 加速度    // 还没达到最大速度则减少速度    if (Math.abs(this.speedX) < this.maxSpeed) {        this.speedX > 0 ? this.speedX += this.speedStep : this.speedX -= this.speedStep    }    if (Math.abs(this.speedY) < this.maxSpeed) {        this.speedY > 0 ? this.speedY += this.speedStep : this.speedY -= this.speedStep    }}

而后应用requestAnimationFrame来一直刷新:

update () {    window.requestAnimationFrame(() => {        this.runCircle()        this.update()        this.layer.draw()    })}

第三步

检测小球和挡板的是否碰撞,撞到了则速度反向,原理是找到矩形周围离小球的圆心最近的点,而后判断这个点和小球圆心的间隔是否小于小球半径,这个点怎么确定也很简略,如果圆心在矩形的左侧,那么这个点肯定在矩形的左侧边上,点x的值也就是rect.x,如果在矩形的右侧,点x的值肯定在矩形的右侧边上,也就是rect.x + rect.width,如果在矩形之间的话,因为最近的点和圆心的连线必定是重置于矩形的边,所以点x的值就是圆心的x,点y的计算和x一样。

collisionCheck () {![](/img/bVcTPDu)    let minx = 0    let miny = 0    let rectX = this.rect.x()    let rectY = this.rect.y()    let rectWidth = this.rect.width()    let rectHeight = this.rect.height()    // 确定矩形上离小球最近的点的x坐标    if (this.centerX < rectX) {// 在矩形左侧        minx = rectX    } else if (this.centerX > rectX + rectWidth) {// 在矩形右侧        minx = rectX + rectWidth    } else {// 在矩形左右之间        minx = this.centerX    }    // 确定矩形上离小球最近的点的y坐标    if (this.centerY < rectY) {// 在矩形下面        miny = rectY    } else if (this.centerY > rectY + rectHeight) {// 在矩形上面        miny = rectY + rectHeight    } else {// 在矩形高低之间        miny = this.centerY    }    // 如果间隔小于半径则代表产生了碰撞    if (this.getTwoPointDistance(minx, miny, this.centerX, this.centerY) <= this.radius) {        // 撞到了左侧或右侧,那么程度速度x反向        if (minx === rectX || minx === rectX + rectWidth) {            this.speedX = -this.speedX        }        // 撞到了矩形下面则垂直速度y反向        if (miny === rectY) {            this.speedY = -this.speedY        }    }}

到这里就完结了,能够欢快的开玩了:

示例代码:https://github.com/wanglin2/BallGame。