Commit 7306b5d0 authored by 邱旭's avatar 邱旭

06.面向对象

parent 965964dc
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"/>
<title>06.面向对象</title>
<style>
html, body {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
overflow: hidden;
}
</style>
<script src="../lib/lib.js"></script>
</head>
<body>
<img id="bird" src="../images/bird/bird_01.png">
</body>
<script>
class Bird extends GameObject {
speed; // bird的速度 每次移动多少距离
constructor(id, speed) {
super(id);
this.speed = speed; // 保存speed
this.setPosition(150, 150); // 给个默认位置
}
update() {
super.update();
const { top, left } = this.getPosition();
const speed = this.speed;
// 计算新的top
if (top !== clickPos.top) {
const dis = clickPos.top - top; // 计算差值
const dir = dis > 0 ? 1 : -1; // 计算在top上移动的方向 1 正向移动 或 -1 反向移动;
// 如果速度过快,本次移动直接过头了(即差值<速度),就直接移动到指定top
if (Math.abs(dis) < speed) {
this.transform.position.top = clickPos.top;
} else {
this.transform.position.top = top + dir * speed; // 计算新的top,新的位置 = 之前的位置 + 方向 * 速度
}
}
// 用相同的方式计算left
if (left !== clickPos.left) {
const dis = clickPos.left - left;
const dir = dis > 0 ? 1 : -1;
if (Math.abs(dis) < speed) {
this.transform.position.left = clickPos.left;
} else {
this.transform.position.left = left + dir * speed;
}
}
}
}
</script>
<script>
const clickPos = { // 鼠标点击的位置 bird将要的到达的位置
top: 150,
left: 150,
}
const bird = new Bird("bird", 15);
// 使用mousedown监听鼠标按下,并获得鼠标点击的位置
const mouseDown = (e) => {
// 记录bird将要到达的位置,使用动画慢慢到达
clickPos.top = e.clientY;
clickPos.left = e.clientX;
}
document.addEventListener('mousedown', mouseDown);
/**
* 计算Bird的位置(数据更新)
*/
function update() {
bird.update();
}
/**
* 更新显示对象位置(渲染)
*/
function render() {
bird.render();
}
function loop() {
requestAnimationFrame(loop); // 循环调用requestAnimationFrame
update(); // 先数据更新
render(); // 后渲染更新
}
loop();
</script>
</html>
# 面向对象
引入概念:`面向对象` `游戏对象` `生命周期`
经过上一节的操作,我们已经得到了一只有头有脸的Bird
按这样的方式写代码,写一个小游戏那要多麻烦
所以本节我们要将游戏中通用的东西抽离出来抽象为一个游戏对象,之后所有对象的创建都继承于这个基本的游戏对象
## GameObject
- 1.创建一个js并引入,在这个js中写入如下代码
下面的代码抽象了一个简单的GameObject
```javascript
/**
* 抽象了一个简单的GameObject
*/
class GameObject {
id; // 绑定的dom元素的id
dom; // 绑定的dom元素
/**
* transform 表示显示对象的变换
* @type {{rotate: number, scale: {x: number, y: number}, position: {top: number, left: number}}}
*/
transform = {
position: { top: 0, left: 0 }, // 位置
scale: { x: 1, y: 1 }, // 缩放
rotate: 0, // 旋转
}
constructor(id) {
this.id = id;
this.dom = document.getElementById(id); // 在构造函数中绑定dom元素
this.dom.style.position = "absolute";
this.dom.style.transformOrigin = "center";
}
/**
* 设置Position
* @param top
* @param left
*/
setPosition(top = this.transform.position.top, left = this.transform.position.left) {
this.transform.position.top = top;
this.transform.position.left = left;
}
/**
* 设置Scale
* @param x
* @param y
*/
setScale(x = this.transform.scale.x, y = this.transform.scale.y) {
this.transform.scale.x = x;
this.transform.scale.y = y;
}
/**
* 设置Rotate
* @param rotate
*/
setRotate(rotate = this.transform.rotate) {
this.transform.rotate = rotate;
}
/**
* 获得Position
* @returns {{top: number, left: number}}
*/
getPosition() {
return {
top: this.transform.position.top,
left: this.transform.position.left,
}
}
/**
* 获得Scale
* @returns {{x: number, y: number}}
*/
getScale() {
return {
x: this.transform.scale.x,
y: this.transform.scale.y,
}
}
/**
* 获得Rotate
* @returns {number}
*/
getRotate() {
return this.transform.rotate;
}
/**
* 抽离数据更新部分
*/
update() {
}
/**
* 抽离渲染部分
*/
render() {
const { top, left } = this.getPosition();
const { x: scaleX, y: scaleY } = this.getScale();
const rotate = this.getRotate();
this.dom.style.top = top + "px";
this.dom.style.left = left + "px";
this.dom.style.transform = `translate(-50%, -50%) scale(${scaleX}, ${scaleY}) rotate(${rotate}deg)`;
}
/**
* 抽离销毁部分
*/
destroy() {
}
}
```
- 2.用面向对象的方式创建鸟的class
```javascript
class Bird extends GameObject {
speed; // bird的速度 每次移动多少距离
constructor(id, speed = 15) {
super(id);
this.speed = speed; // 保存speed
this.setPosition(150, 150); // 给个默认位置
}
update() {
super.update();
const { top, left } = this.getPosition();
const speed = this.speed;
// 计算新的top
if (top !== clickPos.top) {
const dis = clickPos.top - top; // 计算差值
const dir = dis > 0 ? 1 : -1; // 计算在top上移动的方向 1 正向移动 或 -1 反向移动;
// 如果速度过快,本次移动直接过头了(即差值<速度),就直接移动到指定top
if (Math.abs(dis) < speed) {
this.transform.position.top = clickPos.top;
} else {
this.transform.position.top = top + dir * speed; // 计算新的top,新的位置 = 之前的位置 + 方向 * 速度
}
}
// 用相同的方式计算left
if (left !== clickPos.left) {
const dis = clickPos.left - left;
const dir = dis > 0 ? 1 : -1;
if (Math.abs(dis) < speed) {
this.transform.position.left = clickPos.left;
} else {
this.transform.position.left = left + dir * speed;
}
}
}
}
```
- 3.创建鸟的实例
```javascript
const bird = new Bird("bird", 15);
```
- 4.加入到循环中
```javascript
/**
* 计算Bird的位置(数据更新)
*/
function update() {
bird.update();
}
/**
* 更新显示对象位置(渲染)
*/
function render() {
bird.render();
}
```
再次运行案例,效果一样,但是代码维护更方便,更容易懂,且每个对象有独立的生命周期,更易于组件化,可视化
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment