https://stjy.yuque.com/jkpt/inside/db_analyze
天道酬勤,知足常乐
find . -mtime 10 -name "*.php" ! -path "*cache*" ! -path "*think*" ! -path "*runtime*" 搜索最近修改且排除目录 puppeteer 字体没有生效 yum groupinstall "Font" 宝塔防火墙实现反响代理时提取真实IP进行安全验证 宝塔防火墙中本身有CDN设置,开启会识别请求头中信息,有安全问题。识别具体反向服务器IP,再通过提取头部转发IP,才妥当 /www/server/btwaf/httpd.lua function get_client_ip() 最后面补充下列语句 if(client_ip=='反响代理服务器IP' and httpd.headers_in['x-forwarded-for']~= nil and httpd.headers_in['x-forwarded-for'] ~= "") then client_ip= httpd.headers_in['x-forwarded-for']; end lua 使用模块 yum install luarocks luarocks install inspect lua 文件中local inspect = require('inspect')引入 IE卸载 https://www.cnblogs.com/cang12138/p/6707307.html 统计apache 日志某天前100名 cat xxxxx | grep "16/Nov/2020" |awk '{print $1}' | sort | uniq -c | sort -nr | head -100 tail -n 1000000 xxxxxlog | cut -d ' ' -f 1 |sort |uniq -c | sort -nr | awk '{print $0 }' | head -n 10 lodash 按需安装 npm install lodash.debounce ssh 密钥登录 https://toutiao.io/posts/popsg/preview 虚拟机网络不正常 网络编辑器恢复默认 虚拟机VMware设置开机启动 https://blog.51cto.com/4746316/2330911 右键->管理->添加共享 共享->设置->设置开机启动 oralce 触发器拦截插入 IF :NEW.JKPT_UPLOAD_MODE in ('ADD','UPDATE') THEN raise_application_error ( -20101, '不允许 ADD,UPDATE' ); END IF; ubuntu 18 补充/etc/rc.local https://blog.csdn.net/qq_41782149/article/details/89001226 测试/etc/rc.local sudo /etc/rc.local 观察当前会话和启动会话环境差异 echo $PATH(两个地方输出看差异) export $PATH=$PATH:/xxxx(修正差异,避免开机启动时环境异常) mysql 空用户名导致登录密码错误问题 use mysql;delete from user where User=''; #删除账号为空的行 nodejs cluster 原理 https://cnodejs.org/topic/56e84480833b7c8a0492e20c mssql 多转义查询(每个查询后需要补充) where xx like '\_' escape '\' and xx not like '\_' escape '\' nsp内网穿透 https://post.smzdm.com/p/az5emoon/ https://ehang-io.github.io/nps/#/?id=nps firewalld 命令 https://wangchujiang.com/linux-command/c/firewall-cmd.html 端口转发软件(iptables,firewall 没启用...不敢直接开...) socat TCP4-LISTEN:12345,reuseaddr,fork TCP4:192.168.172.131:22 后台运行:nohup xxxxx & 深入分析linux进程 https://blog.csdn.net/FL63Zv9Zou86950w/article/details/105383294 strace php-fpm 输出进程所有执行过程 pstack pid 跟踪进程 vmstat 2 10 输出当前系统状态 pidstat -w 5 查看进程上下文切换次数 iostat -d -k 1 10 -x svn版本 分支合并主线报缺失异常 https://stackoverflow.com/questions/2472249/missing-ranges-error-message-when-reintegrating-a-branch-into-trunk-in-subversio apache 日志分析神器 apachetop 实时分析当前请求情况 apachetop -f xxxx.log -T xxx 保留观察时间,默认30秒(方向键向右可查看地址的IP统计) goaccess 分析并导出日志分析内容, 非常全面 goaccess 1000000.log --log-format=COMBINED -o m.goaccess.html sshfs sftp目录挂载 不补充参数会出现没有权限读取的问题 sshfs -p 22 xxx@xxxxx.com:/ /xxxxx -o allow_other -o reconnect 邮箱原理 https://wiki.ubuntu.org.cn/IRedMail#iRedmail_.E7.BB.84.E4.BB.B6 剪切板过小问题 修改系统虚拟内存. 查询window日志(按类型) https://blog.csdn.net/C_chuxin/article/details/84974207 php sftp 操作 pear install https://techglimpse.com/install-phpseclib-netssh2-netsftp-ppc64le-machine-centos/ Net_SFTP 也可直接下载放到扩展,无需安装依赖. http://phpseclib.sourceforge.net/sftp/examples.html phpstudy 新版本redis找不到, extention里后面少了.dll导致读取不到文件 phpstudy 默认开启了opcache,需要关闭 mysql 复制表报错 Specified key was too long, 索引键使用了utf8mb4导致 puppeteer 安装 Failed to download Chromium r cmd:set PUPPETEER_SKIP_DOWNLOAD=1 // 跳过chrome下载 node ./node_modules/puppeteer/install.js // 单独下载谷歌 record脚本:https://www.stefanjudis.com/blog/how-to-record-screen-actions-as-a-puppeteer-script/ 屏蔽特征:https://blog.xinshangshangxin.com/2019/01/01/headless-chrome-start/ svn 提交&清理报错 Failed to run the WC DB work queue associated with .svn/wc.db // sqlite3打开 清理WORK_QUEUE表(navicat 等工具直接打开操作即可) redis消息订阅发布 https://www.runoob.com/redis/redis-pub-sub.html 查询订阅状态 https://www.runoob.com/redis/pub-sub-pubsub.html 矩阵乘法证明 http://www.ruanyifeng.com/blog/2015/09/matrix-multiplication.html https://nolaymanleftbehind.wordpress.com/2011/07/10/linear-algebra-what-matrices-actually-are/ pycharm " cv2 You need configured Python 2 SDK to render" file->setting->project->Python interpreter->齿轮->show all->添加python2.x进来(exsits environment)(python 3.x和python 2.0都要一起出现) window 请求转发 打开cmd/powershell 首先安装IPV6(xp下IPV6必须安装,否则端口转发不可用!) netsh interface ipv6 install 添加一个IPV4到IPV4的端口映射 (也可以直接不加listenaddress=0.0.0.0) netsh interface portproxy add v4tov4 listenaddress=0.0.0.0 listenport=7000 connectaddress=目标IP connectport=7000 删除指定监听ip和端口 netsh interface portproxy delete v4tov4 listenaddress=0.0.0.0 listenport=7000 可以查看存在的转发 netsh interface portproxy show all plsql 安装+导出,导入 配置环境变量到oracle_home 指定exp文件 firewall ipset 控制 https://www.cnblogs.com/architectforest/p/12973982.html php 调试 phpstorm:file=>settings=>languages&frameworks=>php=>cli interpreter 添加php路径 interpreter 指定 php 路径时, 下面的xdebug文件也需要指定 对应php.ini配置xdebug为启用 SVN 版本误删除重新找回&合并(包括重命名) 文件浏览器(右边指定浏览到达版本), 可显示该误删除分支原完整提交日志 合并时指定版本范围,可合并原丢失SVN版本 yum socket代理 /etc/yum.conf 追加 socks5h://xxxx gcc 编辑器版本升级 手动编译:https://blog.csdn.net/EI__Nino/article/details/100086157 https://gist.github.com/pablomp/237ee367e4a0ac060ed83d3d40e2285a find / -name "libstdc++.so*" 检查编译后版本:strings /root/local/lib64/libstdc++.so.6.0.23 | grep CXXABI 添加lib至全局:export LD_LIBRARY_PATH=/root/local/lib64/:$LD_LIBRARY_PATH 安装式升级编辑器:https://linuxize.com/post/how-to-install-gcc-compiler-on-centos-7/ 复制文件到 /usr/lib64/xxx下 建立软链接:ln -s libstdc++.so.6.0.25 libstdc++.so.6
eclipse 镜像站
http://www.cnblogs.com/smartdog/archive/2012/11/06/2757372.html
adt 更新镜像
http://tools.android-studio.org/
配置说明
http://mirrors.neusoft.edu.cn/more.we#android
最近搞个东西需要能处理拼音检查功能,不处理英文检查。。
顺便提供一个拼写检查的工具
http://php.freehostingguru.com/group.php-4.php
不过这边要求比较低,只要检查出拼音是否输入错误。
考虑两个问题需要解决。
一:拼音是否强制代入了空格。
二:拼音是否可以不用输入空格。
实现思路
将以下字符串,循环比对,替换。不过需要注意一个东西,长的优先。否则替换会出问题。(自己手动写个正则处理下, 并按长度排序。)
a ai an ang ao ba bai ban bang bao bei ben beng bi bia biao bie bin bing bo bu ca cai can cang cao ce cen ceng cha chai chan chang chao che chen cheng chi chong chou chu chua chuai chuan chuang chui chun chuo ci cong cou cu cuan cui cun cuo da dai dan dang dao de dei den deng di dia dian diao die ding diu dong dou du duan dui dun duo e en eng er fa fan fang fei fen feng fiao fo fou fu ga gai gan gang gao ge gei gen geng gong gou gu gua guai guan guang gui gun guo ha hai han hang hao he hei hen heng hong hou hu hua huai huan huang hui hun huo ji jia jian jiang jiao jie jin jing jiong jiu ju juan jue ka kai kan kang kao ke ken keng kong kou ku kua kuai kuan kuang kui kun kuo la lai lan lang lao le lei leng li lia lian liang liao lie lin ling liu lo long lou lu luan lun luo lv lve ma mai man mang mao me mei men meng mi mian miao mie min ming miu mo mou mu na nai nan nang nao ne nei nen neng ni nian niang niao nie nin ning niu nong nou nu nuan nun nuo nv nve o ou pa pai pan pang pao pei pen peng pi pian piao pie pin ping po pou pu qi qia qian qiang qiao qie qin qing qiong qiu qu quan que qun ran rang rao re ren reng ri rong rou ru rua ruan rui run ruo sa sai san sang sao se sen seng sha shai shan shang shao she shei shen sheng shi shou shu shua shuai shuan shuang shui shun shuo si song sou su suan sui sun suo ta tai tan tang tao te tei teng ti tian tiao tie ting tong tou tu tuan tui tun tuo wa wai wan wang wei wen weng wo wu xi xia xian xiang xiao xie xin xing xiong xiu xu xuan xue xun ya yan yang yao ye yi yin ying yo yong you yu yuan yue yun za zai zan zang zao ze zei zen zeng zha zhai zhan zhang zhao zhe zhei zhen zheng zhi zhong zhou zhu zhua zhuai zhuan zhuang zhui zhun zhuo zi zong zou zu zuan zui zun zuo
其实有时间优化下,调整代码到 snoopy.class.php 用起来会方便点
Wechatext::getCode
/** * @添加验证码抓取. */ public function getCode() { $filename = $this->_cookiename; if (file_exists ( $filename )) { $mtime = filemtime ( $filename ); if ($mtime < time () - $this->_cookieexpired) $data = ''; else $data = file_get_contents ( $filename ); } else $data = ''; $send_snoopy = new Snoopy (); $send_snoopy->rawheaders ['Cookie'] = $data; $send_snoopy->maxredirs = 0; $url = "https://mp.weixin.qq.com/cgi-bin/verifycode?username=" . $this->_account . "&r=1406270984491"; $send_snoopy->fetch ( $url ); $cookie = ''; foreach ( $send_snoopy->headers as $key => $value ) { $value = trim ( $value ); if (preg_match ( '/^set-cookie:[s]+([^=]+)=([^;]+)/i', $value, $match )) $cookie .= $match [1] . '=' . $match [2] . '; '; } $this->saveCookie ( $this->_cookiename, $cookie ); header ( 'Content-Type: image/jpeg' ); echo $send_snoopy->results; exit (); }
补充验证码自动识别工具(不是做广告….)
http://www.uuwise.com/
注:微信对登录次数太多的ip做登录限制,会导致该ip的公众号无法登录。。慎玩。
http://www.ruanyifeng.com/blog/2014/07/database_implementation.html
http://shedingkong.lofter.com/post/302b9d_16dab28
一、网速的测速原理为计算上传某一大小文件和下载某一大小文件时:
速度=大小/时间
二、误差影响多种:
网络环境(包括dns、执行脚本所需时间(包括服务器,客户端)、精细情况下,还包括文件头得相关信息。。。)、本地环境(不解释)
特别需要注意 gzip
三、设计:
1.把文件上传分两步来执行。第一步空上传。得到所需时间.
2.生成指定大小长度的文件,如:1024000长的字符串.
3.进行二次提交。后者时间减去第一次空上传的时间。得到1024000所需的实际时间。估算出上传的速度。
4.因为各种因素干扰。重复提交3~5次。取平均值。即当前客户端相对服务器的网速。
5.gzip解决方式(压缩算法大都是对相同内容进行压缩)
压缩过的文件。本身不容易再压缩,如jpg之类文件,测试下载,可以通过直接输出个定长的jpg文件。测试即可.
四、考虑网络不稳定:
1.剔除负值(头次请求高,二次请求慢,就会出现)
2.设置一个误差值。如 :30% 将多次的结果平均化,超过这误差值的结果剔除。再计算平均。
五、优化
1.使用swfupload 直接解析出上传时间。相对较准。
http://www.php100.com/html/it/mobile/2014/0612/6971.html
玩才是学习的动力
背景分析
//一个圆圈弧度 //用来识别用户可视弧度 等等,绘制skybox时做图片截取处理. var CIRCLE = Math.PI * 2; var MOBILE = /Android|webOS|iPhone|iPad|iPod|BlackBerry/i .test(navigator.userAgent) function Controls() { this.codes = { 37 : 'left', 39 : 'right', 38 : 'forward', 40 : 'backward' }; this.states = { 'left' : false, 'right' : false, 'forward' : false, 'backward' : false }; document.addEventListener('keydown', this.onKey.bind(this, true), false); document.addEventListener('keyup', this.onKey.bind(this, false), false); document.addEventListener('touchstart', this.onTouch.bind(this), false); document.addEventListener('touchmove', this.onTouch.bind(this), false); document.addEventListener('touchend', this.onTouchEnd.bind(this), false); } Controls.prototype.onTouch = function(e) { var t = e.touches[0]; this.onTouchEnd(e); if (t.pageY < window.innerHeight * 0.5) this.onKey(true, { keyCode : 38 }); else if (t.pageX < window.innerWidth * 0.5) this.onKey(true, { keyCode : 37 }); else if (t.pageY > window.innerWidth * 0.5) this.onKey(true, { keyCode : 39 }); }; Controls.prototype.onTouchEnd = function(e) { this.states = { 'left' : false, 'right' : false, 'forward' : false, 'backward' : false }; // 关闭默认事件 e.preventDefault(); // 关闭事件传递 e.stopPropagation(); }; Controls.prototype.onKey = function(val, e) { var state = this.codes[e.keyCode]; if (typeof state === 'undefined') return; this.states[state] = val; e.preventDefault && e.preventDefault(); e.stopPropagation && e.stopPropagation(); }; function Bitmap(src, width, height) { this.image = new Image(); this.image.src = src; this.width = width; this.height = height; } /** * * @param x * 坐标 * @param y * 坐标 * @param direction * 方向 * @returns {Player} */ function Player(x, y, direction) { this.x = x; this.y = y; this.direction = direction; // 武器 this.weapon = new Bitmap('knife_hand.png', 319, 320); this.paces = 0; } /** * 旋转 * * @param angle * 角度 */ Player.prototype.rotate = function(angle) { // 方向 this.direction = (this.direction + angle + CIRCLE) % (CIRCLE); }; /** * @param distance * 距离 */ Player.prototype.walk = function(distance, map) { var dx = Math.cos(this.direction) * distance; var dy = Math.sin(this.direction) * distance; if (map.get(this.x + dx, this.y) <= 0) this.x += dx; if (map.get(this.x, this.y + dy) <= 0) this.y += dy; this.paces += distance; }; Player.prototype.update = function(controls, map, seconds) { if (controls.left) this.rotate(-Math.PI * seconds); if (controls.right) this.rotate(Math.PI * seconds); if (controls.forward) this.walk(3 * seconds, map); if (controls.backward) this.walk(-3 * seconds, map); }; function Map(size) { // 地区大小 this.size = size; // 地区网格大小 this.wallGrid = new Uint8Array(size * size); // 天空画布大小 this.skybox = new Bitmap('deathvalley_panorama_sky.jpg', 4000, 1290); // 墙体画布大小 this.wallTexture = new Bitmap('wall_texture.jpg', 1024, 1024); this.light = 0; } Map.prototype.get = function(x, y) { x = Math.floor(x); y = Math.floor(y); if (x < 0 || x > this.size - 1 || y < 0 || y > this.size - 1) return -1; return this.wallGrid[y * this.size + x]; }; Map.prototype.randomize = function() { for ( var i = 0; i < this.size * this.size; i++) { this.wallGrid[i] = Math.random() < 0.3 ? 1 : 0; } }; /** * @point * @angle * @range 范围 */ Map.prototype.cast = function(point, angle, range) { var self = this; var sin = Math.sin(angle); var cos = Math.cos(angle); var noWall = { length2 : Infinity }; return ray({ x : point.x, y : point.y, height : 0, distance : 0 }); function ray(origin) { var stepX = step(sin, cos, origin.x, origin.y); var stepY = step(cos, sin, origin.y, origin.x, true); var nextStep = stepX.length2 < stepY.length2 ? inspect(stepX, 1, 0, origin.distance, stepX.y) : inspect(stepY, 0, 1, origin.distance, stepY.x); if (nextStep.distance > range) return [ origin ]; return [ origin ].concat(ray(nextStep)); } function step(rise, run, x, y, inverted) { if (run === 0) return noWall; var dx = run > 0 ? Math.floor(x + 1) - x : Math.ceil(x - 1) - x; var dy = dx * (rise / run); return { x : inverted ? y + dy : x + dx, y : inverted ? x + dx : y + dy, length2 : dx * dx + dy * dy }; } function inspect(step, shiftX, shiftY, distance, offset) { var dx = cos < 0 ? shiftX : 0; var dy = sin < 0 ? shiftY : 0; step.height = self.get(step.x - dx, step.y - dy); step.distance = distance + Math.sqrt(step.length2); if (shiftX) step.shading = cos < 0 ? 2 : 0; else step.shading = sin < 0 ? 2 : 1; step.offset = offset - Math.floor(offset); return step; } }; /** * 模拟闪电的时间间隔 this.light 为当前地区的亮度值 */ Map.prototype.update = function(seconds) { return; if (this.light > 0)// 按时间把亮度调低.当为最暗时,用0表示 this.light = Math.max(this.light - 10 * seconds, 0); else if (Math.random() * 5 < seconds) this.light = 2;// 按某概率 出现闪电 }; function Camera(canvas, resolution, fov) { // 画布 this.ctx = canvas.getContext('2d'); // 通过style 将 画面强制放大,填充屏幕。画面越精细,速度越慢,反之则画面模糊,但是速度快。默认大小为0.5 this.width = canvas.width = window.innerWidth * 0.5; this.height = canvas.height = window.innerHeight * 0.5; this.resolution = resolution; this.spacing = this.width / resolution; // 视角 为固定 0.4*pi this.fov = fov; this.range = MOBILE ? 8 : 14; this.lightRange = 5; // this.scale = (this.width + this.height) / 1200; } Camera.prototype.render = function(player, map) { // 单纯只是计算出闭合后。图片的相关特征,做背景 this.drawSky(player.direction, map.skybox, map.light); // 重点计算 // this.drawColumns(player, map); // 玩家武器图,只是 一张晃动的图 // this.drawWeapon(player.weapon, player.paces); }; /** * direction 方向 (摄像头[用户角度方向]) sky 天空元素 (闭合状态下[图,首尾相连,形成的一圈为360度,即2*pi=CIRCLE ]。) * ambient 环境 (遮罩层,用来降低光线) */ Camera.prototype.drawSky = function(direction, sky, ambient) { // 计算出当前背景图的可视范围 this.fov(可视范围) // 不清楚这里的计算原理。 var width = this.width * (CIRCLE / this.fov); // 2/0.4 // 旋转偏角 图片左边的部分偏移 // 宽度 direction 为当前视角弧度 var left = -width * direction / CIRCLE; this.ctx.save(); this.ctx.drawImage(sky.image, left, 0, width, this.height); if (left < width - this.width) { // console.log(left,direction / CIRCLE); this.ctx.drawImage(sky.image, left + width, 0, width, this.height); } // 一个遮罩层。让背景变亮或暗 , 即 map.ligth 配合闪电,做地面的渲染处理 if (ambient > 0) { this.ctx.fillStyle = '#ffffff'; this.ctx.globalAlpha = ambient * 0.1; this.ctx.fillRect(0, this.height * 0.5, this.width, this.height * 0.5); } this.ctx.restore(); }; Camera.prototype.drawColumns = function(player, map) { this.ctx.save(); for ( var column = 0; column < this.resolution; column++) { var angle = this.fov * (column / this.resolution - 0.5); var ray = map.cast(player, player.direction + angle, this.range); this.drawColumn(column, ray, angle, map); } this.ctx.restore(); }; Camera.prototype.drawWeapon = function(weapon, paces) { var bobX = Math.cos(paces * 2) * this.scale * 6; var bobY = Math.sin(paces * 4) * this.scale * 6; var left = this.width * 0.66 + bobX; var top = this.height * 0.6 + bobY; this.ctx.drawImage(weapon.image, left, top, weapon.width * this.scale, weapon.height * this.scale); }; Camera.prototype.drawColumn = function(column, ray, angle, map) { var ctx = this.ctx; var texture = map.wallTexture; var left = Math.floor(column * this.spacing); var width = Math.ceil(this.spacing); var hit = -1; while (++hit < ray.length && ray[hit].height <= 0) ; for ( var s = ray.length - 1; s >= 0; s--) { var step = ray[s]; var rainDrops = Math.pow(Math.random(), 3) * s; var rain = (rainDrops > 0) && this.project(0.1, angle, step.distance); if (s === hit) { var textureX = Math.floor(texture.width * step.offset); var wall = this.project(step.height, angle, step.distance); ctx.globalAlpha = 1; ctx.drawImage(texture.image, textureX, 0, 1, texture.height, left, wall.top, width, wall.height); ctx.fillStyle = '#000000'; ctx.globalAlpha = Math.max((step.distance + step.shading) / this.lightRange - map.light, 0); ctx.fillRect(left, wall.top, width, wall.height); } ctx.fillStyle = '#ffffff'; ctx.globalAlpha = 0.15; while (--rainDrops > 0) ctx.fillRect(left, Math.random() * rain.top, 1, rain.height); } }; Camera.prototype.project = function(height, angle, distance) { var z = distance * Math.cos(angle); var wallHeight = this.height * height / z; var bottom = this.height / 2 * (1 + 1 / z); return { top : bottom - wallHeight, height : wallHeight }; }; function GameLoop() { this.frame = this.frame.bind(this); this.lastTime = 0; this.callback = function() { }; } GameLoop.prototype.start = function(callback) { this.callback = callback; requestAnimationFrame(this.frame); }; GameLoop.prototype.frame = function(time) { var seconds = (time - this.lastTime) / 1000; this.lastTime = time; if (seconds < 0.2) this.callback(seconds); requestAnimationFrame(this.frame); }; var display = document.getElementById('display'); var player = new Player(15.3, -1.2, Math.PI * 0.3); var map = new Map(32); var controls = new Controls(); var camera = new Camera(display, MOBILE ? 160 : 320, Math.PI * 0.4); var loop = new GameLoop(); map.randomize(); // 系统自动循环时,自动调整时间 seconds 时间间隔长度 . loop.start(function frame(seconds) { map.update(seconds); player.update(controls.states, map, seconds); camera.render(player, map); });
武器分析
//一个圆圈弧度 //用来识别用户可视弧度 等等,绘制skybox时做图片截取处理. var CIRCLE = Math.PI * 2; var MOBILE = /Android|webOS|iPhone|iPad|iPod|BlackBerry/i .test(navigator.userAgent) function Controls() { this.codes = { 37 : 'left', 39 : 'right', 38 : 'forward', 40 : 'backward' }; this.states = { 'left' : false, 'right' : false, 'forward' : false, 'backward' : false }; document.addEventListener('keydown', this.onKey.bind(this, true), false); document.addEventListener('keyup', this.onKey.bind(this, false), false); document.addEventListener('touchstart', this.onTouch.bind(this), false); document.addEventListener('touchmove', this.onTouch.bind(this), false); document.addEventListener('touchend', this.onTouchEnd.bind(this), false); } Controls.prototype.onTouch = function(e) { var t = e.touches[0]; this.onTouchEnd(e); if (t.pageY < window.innerHeight * 0.5) this.onKey(true, { keyCode : 38 }); else if (t.pageX < window.innerWidth * 0.5) this.onKey(true, { keyCode : 37 }); else if (t.pageY > window.innerWidth * 0.5) this.onKey(true, { keyCode : 39 }); }; Controls.prototype.onTouchEnd = function(e) { this.states = { 'left' : false, 'right' : false, 'forward' : false, 'backward' : false }; // 关闭默认事件 e.preventDefault(); // 关闭事件传递 e.stopPropagation(); }; Controls.prototype.onKey = function(val, e) { var state = this.codes[e.keyCode]; if (typeof state === 'undefined') return; this.states[state] = val; e.preventDefault && e.preventDefault(); e.stopPropagation && e.stopPropagation(); }; function Bitmap(src, width, height) { this.image = new Image(); this.image.src = src; this.width = width; this.height = height; } /** * * @param x * 坐标 * @param y * 坐标 * @param direction * 方向 * @returns {Player} */ function Player(x, y, direction) { this.x = x; this.y = y; this.direction = direction; // 武器 this.weapon = new Bitmap('knife_hand.png', 319, 320); this.paces = 0; } /** * 旋转 * * @param angle * 角度 */ Player.prototype.rotate = function(angle) { // 方向 this.direction = (this.direction + angle + CIRCLE) % (CIRCLE); }; /** * @param distance * 距离 */ Player.prototype.walk = function(distance, map) { var dx = Math.cos(this.direction) * distance; var dy = Math.sin(this.direction) * distance; if (map.get(this.x + dx, this.y) <= 0) this.x += dx; if (map.get(this.x, this.y + dy) <= 0) this.y += dy; //前进的距离。步数 //旋转不算 this.paces += distance; }; Player.prototype.update = function(controls, map, seconds) { if (controls.left) this.rotate(-Math.PI * seconds); if (controls.right) this.rotate(Math.PI * seconds); if (controls.forward) this.walk(3 * seconds, map); if (controls.backward) this.walk(-3 * seconds, map); }; function Map(size) { // 地区大小 this.size = size; // 地区网格大小 this.wallGrid = new Uint8Array(size * size); // 天空画布大小 this.skybox = new Bitmap('deathvalley_panorama.jpg', 4000, 1290); // 墙体画布大小 this.wallTexture = new Bitmap('wall_texture.jpg', 1024, 1024); this.light = 0; } Map.prototype.get = function(x, y) { x = Math.floor(x); y = Math.floor(y); if (x < 0 || x > this.size - 1 || y < 0 || y > this.size - 1) return -1; return this.wallGrid[y * this.size + x]; }; Map.prototype.randomize = function() { for ( var i = 0; i < this.size * this.size; i++) { this.wallGrid[i] = Math.random() < 0.3 ? 1 : 0; } }; /** * @point * @angle * @range 范围 */ Map.prototype.cast = function(point, angle, range) { var self = this; var sin = Math.sin(angle); var cos = Math.cos(angle); var noWall = { length2 : Infinity }; return ray({ x : point.x, y : point.y, height : 0, distance : 0 }); function ray(origin) { var stepX = step(sin, cos, origin.x, origin.y); var stepY = step(cos, sin, origin.y, origin.x, true); var nextStep = stepX.length2 < stepY.length2 ? inspect(stepX, 1, 0, origin.distance, stepX.y) : inspect(stepY, 0, 1, origin.distance, stepY.x); if (nextStep.distance > range) return [ origin ]; return [ origin ].concat(ray(nextStep)); } function step(rise, run, x, y, inverted) { if (run === 0) return noWall; var dx = run > 0 ? Math.floor(x + 1) - x : Math.ceil(x - 1) - x; var dy = dx * (rise / run); return { x : inverted ? y + dy : x + dx, y : inverted ? x + dx : y + dy, length2 : dx * dx + dy * dy }; } function inspect(step, shiftX, shiftY, distance, offset) { var dx = cos < 0 ? shiftX : 0; var dy = sin < 0 ? shiftY : 0; step.height = self.get(step.x - dx, step.y - dy); step.distance = distance + Math.sqrt(step.length2); if (shiftX) step.shading = cos < 0 ? 2 : 0; else step.shading = sin < 0 ? 2 : 1; step.offset = offset - Math.floor(offset); return step; } }; /** * 模拟闪电的时间间隔 * this.light 为当前地区的亮度值 */ Map.prototype.update = function(seconds) { if (this.light > 0)//按时间把亮度调低.当为最暗时,用0表示 this.light = Math.max(this.light - 10 * seconds, 0); else if (Math.random() * 5 < seconds) this.light = 2;//按某概率 出现闪电 }; function Camera(canvas, resolution, fov) { // 画布 this.ctx = canvas.getContext('2d'); // 通过style 将 画面强制放大,填充屏幕。画面越精细,速度越慢,反之则画面模糊,但是速度快。默认大小为0.5 this.width = canvas.width = window.innerWidth * 0.5; this.height = canvas.height = window.innerHeight * 0.5; //分辨率 this.resolution = resolution; this.spacing = this.width / resolution; // 视角 为固定 0.4*pi this.fov = fov; this.range = MOBILE ? 8 : 14; this.lightRange = 5; //只用来识别武器的分变率。或者说,大小 this.scale = (this.width + this.height) / 1200; } Camera.prototype.render = function(player, map) { // 单纯只是计算出闭合后。图片的相关特征,做背景 this.drawSky(player.direction, map.skybox, map.light); // 重点计算 this.drawColumns(player, map); // 玩家武器图,只是 一张晃动的图 //旋转时不晃动。晃动的幅度根据当前前进的步数或者后腿时的步数 this.drawWeapon(player.weapon, player.paces); }; /** * direction 方向 (摄像头[用户角度方向]) sky 天空元素 (闭合状态下[图,首尾相连,形成的一圈为360度,即2*pi=CIRCLE ]。) * ambient 环境 (遮罩层,用来降低光线) */ Camera.prototype.drawSky = function(direction, sky, ambient) { // 计算出当前背景图的可视范围 this.fov(可视范围) //不清楚这里的计算原理。 var width = this.width * (CIRCLE / this.fov); // 2/0.4 // 旋转偏角 图片左边的部分偏移 // 宽度 direction 为当前视角弧度 var left = -width * direction / CIRCLE; this.ctx.save(); this.ctx.drawImage(sky.image, left, 0, width, this.height); if (left < width - this.width) { //console.log(left,direction / CIRCLE); this.ctx.drawImage(sky.image, left + width, 0, width, this.height); } if (ambient > 0) { this.ctx.fillStyle = '#ffffff'; this.ctx.globalAlpha = ambient * 0.1; this.ctx.fillRect(0, this.height * 0.5, this.width, this.height * 0.5); } this.ctx.restore(); }; Camera.prototype.drawColumns = function(player, map) { this.ctx.save(); for ( var column = 0; column < this.resolution; column++) { var angle = this.fov * (column / this.resolution - 0.5); var ray = map.cast(player, player.direction + angle, this.range); this.drawColumn(column, ray, angle, map); } this.ctx.restore(); }; Camera.prototype.drawWeapon = function(weapon, paces) { //利用cos 的正弦和余弦的波动范围为1至-1,加上对应的识别大小做抖动 //模拟人走动时,摆动的弧度.曲线. var bobX = Math.cos(paces * 2) * this.scale * 6; var bobY = Math.sin(paces * 4) * this.scale * 6; var left = this.width * 0.66 + bobX; var top = this.height * 0.6 + bobY; this.ctx.drawImage(weapon.image, left, top, weapon.width * this.scale, weapon.height * this.scale); }; Camera.prototype.drawColumn = function(column, ray, angle, map) { var ctx = this.ctx; var texture = map.wallTexture; var left = Math.floor(column * this.spacing); var width = Math.ceil(this.spacing); var hit = -1; while (++hit < ray.length && ray[hit].height <= 0) ; for ( var s = ray.length - 1; s >= 0; s--) { var step = ray[s]; var rainDrops = Math.pow(Math.random(), 3) * s; var rain = (rainDrops > 0) && this.project(0.1, angle, step.distance); if (s === hit) { var textureX = Math.floor(texture.width * step.offset); var wall = this.project(step.height, angle, step.distance); ctx.globalAlpha = 1; ctx.drawImage(texture.image, textureX, 0, 1, texture.height, left, wall.top, width, wall.height); ctx.fillStyle = '#000000'; ctx.globalAlpha = Math.max((step.distance + step.shading) / this.lightRange - map.light, 0); ctx.fillRect(left, wall.top, width, wall.height); } ctx.fillStyle = '#ffffff'; ctx.globalAlpha = 0.15; while (--rainDrops > 0) ctx.fillRect(left, Math.random() * rain.top, 1, rain.height); } }; Camera.prototype.project = function(height, angle, distance) { var z = distance * Math.cos(angle); var wallHeight = this.height * height / z; var bottom = this.height / 2 * (1 + 1 / z); return { top : bottom - wallHeight, height : wallHeight }; }; function GameLoop() { this.frame = this.frame.bind(this); this.lastTime = 0; this.callback = function() { }; } GameLoop.prototype.start = function(callback) { this.callback = callback; requestAnimationFrame(this.frame); }; GameLoop.prototype.frame = function(time) { var seconds = (time - this.lastTime) / 1000; this.lastTime = time; if (seconds < 0.2) this.callback(seconds); requestAnimationFrame(this.frame); }; var display = document.getElementById('display'); var player = new Player(15.3, -1.2, Math.PI * 0.3); var map = new Map(32); var controls = new Controls(); var camera = new Camera(display, MOBILE ? 160 : 320, Math.PI * 0.4); var loop = new GameLoop(); map.randomize(); //系统自动循环时,自动调整时间 seconds 时间间隔长度 . loop.start(function frame(seconds) { map.update(seconds); player.update(controls.states, map, seconds); camera.render(player, map); });
首先,需要确保目的程序 ,php能独立执行。能输出。
纯粹只是因为用java写复杂逻辑代码比较蛋疼,或者说,因为有现成的代码是php的,重写需要花大量的时间。所以以java 的命令形式进行调用。
步骤 :
1.php代码一份
2.php运行环境一份
2.1 如果非指定形式调用。默认配置文件需要为 : php.ini ,不能有别名
2.2 配置内部内容需要清理不必要的配置,引用路径调整
2.3 单独执行一个文件,调整到不出问题,能正常执行为止
c:ooxxphp.exe “c:aabbindex.php”
3.用java Swing 绘制一个壳,用myeclipse ,前提需要有java 基础,或类似的winform基础比较容易上手,不然适当进行学习即可.
4.用exe4j 打包
参考:http://blog.martoo.cn/?p=613
补充相关代码:
一、命令调用
try { String php_exe = System.getProperty("user.dir") + "/php/php/php.exe"; String php_file = System.getProperty("user.dir") + "/php/exec.php"; if (!filexists(php_exe)) { JOptionPane.showMessageDialog(null, "The php.exe file is not exist"); System.exit(0); } if (!filexists(php_file)) { JOptionPane .showMessageDialog(null, "The php file is not exist"); System.exit(0); } String shell = php_exe + " "" + php_file + """; Process ps = Runtime.getRuntime().exec(shell); ps.waitFor(); BufferedReader br = new BufferedReader(new InputStreamReader( ps.getInputStream())); StringBuffer sb = new StringBuffer(); String line; String contentempty = ""; while ((line = br.readLine()) != null) { contentempty += line; sb.append(line).append("n"); } String result = sb.toString(); if (!contentempty.isEmpty()) { recordinfo(result); JOptionPane.showMessageDialog(null, result); } } catch (Exception e) { recordinfo(e.getMessage()); }
public static void recordinfo(String log) { String path = System.getProperty("user.dir") + "/php_log.txt"; try { FileWriter fw = new FileWriter(path, true); PrintWriter pw = new PrintWriter(fw); pw.println(log); pw.close(); // bw.close(); fw.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } }
public static boolean filexists(String filename) { return new File(filename).exists(); }
输出信息可直接用于弹出框提示。
也可以记录为日志。
二、通讯操作
使用java properties
properties 保存和读取代码
Properties prop = new Properties(); FileInputStream fis; FileOutputStream fos; try { fis = new FileInputStream(System.getProperty("user.dir") + "/php/prop.properties"); fos = new FileOutputStream(System.getProperty("user.dir") + "/php/prop.properties"); prop.load(fis); prop.setProperty("csvpath", jfc.getSelectedFile() .getAbsolutePath()); prop.save(fos, " config file"); // System.out.println(prop.getProperty("a")); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); }
php 获取代码:
参考:http://blog.martoo.cn/?p=825
三:常用功能代码
文件选择框
JFileChooser jfc = new JFileChooser(); if (jfc.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) { //获取路径 System.out.println(jfc.getSelectedFile().getAbsolutePath()); }
弹出提示框
JOptionPane .showMessageDialog(null, "The php file is not exist");
补充 : 意大利操作系统(win7 64x)关闭不了问题
Process ps; try { ps = Runtime.getRuntime().exec("taskkill /f /im xxx.exe"); ps.waitFor(); BufferedReader br = new BufferedReader(new InputStreamReader( ps.getInputStream())); StringBuffer sb = new StringBuffer(); String line; String contentempty = ""; while ((line = br.readLine()) != null) { contentempty += line; sb.append(line).append("n"); } String result = sb.toString(); if (!contentempty.isEmpty()) { recordinfo(result); JOptionPane.showMessageDialog(null, result); } } catch (IOException e2) { e2.printStackTrace(); } catch (InterruptedException xe) { xe.printStackTrace(); }
转发请注明出处http://blog.martoo.cn
如有漏缺,请联系我 QQ 243008827