摘要
今天想到KUOKUO大佬很早以前分享的“用一次函数来实现瞄准线的反射”的文章链接直达http://www.kuokuo666.com/kk023.html,
并下载了大佬的Demo进行学习,由于数学基础一般在阅读大佬代码时有很多不理解在此进行解析分析,以便以后学习,感谢各位
大佬们的开源精神;
瞄准线分三种:无效果直射、遇墙反射、遇墙与球体反射。今天进行解析了第二种:遇墙反射。
版本说明
使用 CocosCreator 的 2.4.3 版本演示。

一次函数
一次函数是什么:一次函数是函数中的一种,一般形如y=kx+b(k,b是常数,k≠0),其中x是自变量,y是因变量。特别地,当b=0时,y=kx(k为常数,k≠0),y叫做x的正比例函数(direct proportion function)
公式:y=kx+b (注意:k、b是常数,并且k≠0)
变化:k = y/x -b;

你是不是又在疑惑什么是自变量、因变量、常数,下面就给你简单讲解下,了解的朋友请忽略。
假如你去买苹果,苹果4元一斤
- 买一斤为4元
- 买两斤为8元
- 买x斤为y元 即 y = 4x
那么在这个式子中 4 为常量,而你买多少斤苹果的x就为自变量,买苹果花费是钱y这是因变量,他是根据你买的斤数x进行变化

界面搭建脚本挂载
脚本挂载在Canvas上并且在Draw Mgr节点上添加Graphics组件,脚本上定义Graphics组件属性。

全部代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
| let POS = cc.Enum({ LEFT: -360, RIGHT: 360, WIDTH: 720, }); cc.Class({ extends: cc.Component,
properties: { draw: cc.Graphics, },
start () { this.node.on(cc.Node.EventType.TOUCH_START, (e) => { let pos = this.draw.node.convertToNodeSpaceAR(e.getLocation()); this.drawLine(pos); }, this);
this.node.on(cc.Node.EventType.TOUCH_MOVE, (e) => { let pos = this.draw.node.convertToNodeSpaceAR(e.getLocation()); this.drawLine(pos); }, this);
this.node.on(cc.Node.EventType.TOUCH_END, (e) => { this.clearLine(); }, this); }, drawLine (pos) { this.draw.clear(); let k = pos.y / pos.x; let lineLength = 1200; this.draw.moveTo(0,0); let point = cc.v2(0, 0); let b = 0; let x, y; let d_b = (k > 0 ? POS.RIGHT : POS.LEFT) * k; let isRebound = false;
while (true) { x = k > 0 ? POS.RIGHT : POS.LEFT; y = k * x + b; let l = cc.v2(x, y).sub(point).mag(); if ( lineLength > l) { isRebound = true; lineLength -= l; this.dottedDrawLine(point,cc.v2(x, y)) point.x = x; point.y = y; b = y + d_b; k *= -1; } else { if (isRebound) { let l_k = lineLength / l; let r_x = POS.WIDTH * l_k; x = k > 0 ? POS.LEFT + r_x : POS.RIGHT - r_x; y = k * x + b; } else { let l_k = lineLength / l; let r_x = POS.WIDTH / 2 * l_k; x = k > 0 ? r_x : -r_x; y = k * x; if (x > -0.05 && x < 0.05); y = lineLength; } this.dottedDrawLine(point,cc.v2(x, y)) break; } } }, clearLine () { this.draw.clear(); },
dottedDrawLine (start,end) { let com = this.draw let line = end.sub(start) let lineLength = line.mag() let length = 20 let increment = line.normalize().mul(length) let drawingLine = true let pos = start.clone() for(;lineLength > length; lineLength -= length) { if(drawingLine) { com.moveTo(pos.x,pos.y) pos.addSelf(increment) com.lineTo(pos.x,pos.y) com.stroke() } else { pos.addSelf(increment) } drawingLine=!drawingLine } if(drawingLine) { com.moveTo(pos.x,pos.y) com.lineTo(end.x,end.y) com.stroke() } }, });
|
效果展示


难点标注
- 一次函数 y = k * x + b
- 反射线增量即b的位置
- 最后反射线位置
- 向量运算,sub() 、mag()、normalize()、mul()、clone()