版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Register_man/article/details/78931562
一、建立引擎目录
在主目录下创建名为'lib'的文件夹,存放引擎代码
二、创建所有游戏元素的基类:Node
在'lib'文件夹下创建'node.js'文件;
一个元素,需要坐标去定义位置,长宽来定义范围,还需要能够切换显示状态,添加子元素和获取父元素等等
代码如下:
export default class Node {
constructor(x = 0, y = 0, width = 0, height = 0) {
// 在父元素中的坐标
this.x = x
this.y = y
// 父元素在世界坐标系中的坐标
this.absX = 0
this.absY = 0
// 锚点
this.anchorPointX = 0.5
this.anchorPointY = 0.5
// 宽和高
this.width = width
this.height = height
// 子元素
this.children = []
// 是否显示
this.visible = true
}
/**
* 将当前元素绘制到屏幕中
* @ctx canvas_context
*/
draw(ctx) {
if (this.visible) {
this.children.forEach((child) => {
child.draw(ctx)
})
}
// node本身不进行绘制,需要让子类自行绘制
}
/**
* 增加一个子元素
* @child 子元素
*/
addChild(child) {
child.parent = this
child.absX += this.x
child.y += this.y
this.children.push(child)
console.log("node.addChild")
}
/**
* 获得计算锚点后的全局坐标
*/
getFixedPosition() {
let absPos = this.getAbsPosition()
return {
x: absPos.x - this.anchorPointX * this.width,
y: absPos.y - this.anchorPointY * this.height
}
}
/**
* 设置锚点,值范围在(0, 1)
*/
setAnchorPoint(x, y) {
if (x < 0) x = 0
if (y < 0) y = 0
if (x > 1) x = 1
if (y > 1) y = 1
this.anchorPointX = x
this.anchorPointY = y
}
/**
* 快速设置宽和高
*/
setContentSize(width, height) {
this.width = width
this.height = height
}
/**
* 快速设置坐标,并修改子元素的绝对坐标
*/
setPosition(x, y) {
this.x = x
this.y = y
this.setChildrenAbsPosition(this.getAbsPosition())
}
setPositionX(x) {
this.x = x
this.setChildrenAbsPosition(this.getAbsPosition())
}
setPositionY(y) {
this.y = y
this.setChildrenAbsPosition(this.getAbsPosition())
}
/**
* 获得未计算锚点的全局坐标
*/
getAbsPosition() {
return {
x: this.x + this.absX,
y: this.y + this.absY
}
}
/**
* 修改所有子元素的坐标
*/
setChildrenAbsPosition(absPos) {
this.children.forEach((child) => {
child.setAbsPosition(absPos)
})
}
setAbsPosition(absPos) {
this.absX = absPos.x
this.absY = absPos.y
this.setChildrenAbsPosition(absPos)
}
}
三、实现Label类
在'lib'文件夹下新建'label.js'文件
由于计算文字宽度,必须要获得canvas的context,
所以在'lib'文件夹下新建'warehouse'类作为数据仓库,存储游戏中需要用到的常量
let ctx
function WareHouse() {
this.getCtx = function () {
if (!ctx) {
ctx = canvas.getContext('2d')
}
return ctx
}
}
export default (new WareHouse())
‘lib/label.js’
import Node from './node.js'
import WareHouse from './warehouse.js'
export default class Lable extends Node {
constructor(text = '', x = 0, y = 0, fontSize = "20px", fontFamily = "Courier New") {
super(x, y)
this.fontSize = fontSize
this.fontFamily = fontFamily
this.text = text
}
draw(ctx) {
super.draw(ctx)
if (this.visible) {
ctx.font = this.fontSize + " " + this.fontFamily
let fixedPos = this.getFixedPosition()
ctx.fillText(this.text, fixedPos.x, fixedPos.y)
}
}
/**
* Label的宽度需要通过canvas进行测量,所以要特殊处理
*/
getFixedPosition() {
let ctx = WareHouse.getCtx()
this.width = ctx.measureText(this.text).width
return super.getFixedPosition()
}
setFontSize(fontsize) {
this.fontSize = fontSize
}
setFontFamily(fontFamily) {
this.fontFamily = fontFamily
}
}
四、实现Sprite类
在'lib'文件夹下新建'sprite.js'文件
import Node from './node'
export default class Sprite extends Node {
constructor(imgSrc = '', width = 0, height = 0, x = 0, y = 0) {
super(x, y, width, height)
this.img = new Image()
this.img.src = imgSrc
}
draw(ctx) {
let absPos = this.getFixedPosition()
if (this.visible) {
ctx.drawImage(
this.img,
absPos.x,
absPos.y,
this.width,
this.height
)
}
super.draw(ctx)
}
setImage(imgSrc){
this.img.src = imgSrc
}
}
五、查看效果
在'main.js'中编辑如下代码:
import './js/libs/weapp-adapter'
import './js/libs/symbol'
import Sprite from './lib/sprite.js'
import Label from './lib/label.js'
import WareHouse from './lib/warehouse.js'
// 获取canvas上下文
let ctx = WareHouse.getCtx()
//新建一个Sprite和一个Label
let helloSprite = new Sprite("hello.png")
let helloLable = new Label("hello world")
let worldLable = new Label("world", 0, 50)
helloSprite.addChild(helloLable)
helloLable.addChild(worldLable)
helloSprite.setPosition(150, 50)
helloSprite.setContentSize(50, 50)
helloSprite.setAnchorPoint(0.5,0.5)
helloLable.setAnchorPoint(0.5, 0.5)
// 模拟游戏循环
window.requestAnimationFrame(loop, canvas)
// update中渲染元素
function update() {
//helloSprite.setPositionY(helloSprite.y + 0.1)
helloSprite.draw(ctx)
}
function loop() {
// 清空显示区域
ctx.clearRect(0, 0, canvas.width, canvas.height)
// 渲染元素
update()
// 持续循环调用自身
window.requestAnimationFrame(loop, canvas)
}
可以看到如下效果:
未完待续...