有一个类似最后一站的游戏这样的游戏不是Charles

使用代理软件Charles替换远程文件进行本地调试 - wlo_o的小花园
作者:admin
时间:February 13, 2015
在玩高德地图的推广游戏时发现,用Http代理,可以轻松把远程文件,替换成本地文件,修改本地文件内的逻辑就能作弊了。当然测试后,发现后端写的很严谨,分数后台有限制根本做不了弊-.,-
Charles是一个非常棒的代理工具,windows,mac和linux都可以用(不过要收费的 ^-^ )
我主要是用来做本地文件代理,来方便地调试网页,还有查看各种请求数据,包括用作移动设备的代理,来方便地调试移动web页面。
注:基本所有的charles设置都可以使用通配符,有部分可以使用正则表达式(一般需勾选Regex框)
设置全局代理
Proxy - Mac OS X Proxy
MAC下是这个勾选项,还有一个是Mozilla Firfox Proxy
一般直接勾选全局代理就好了。不要忘记勾选了,不然刷新半天木有记录,可能还找不到原因。。
然后点击第一个带+的图标,开启一个session,界面上那个红点图标在选中态才是正在记录中,否则该session就是空闲状态哦。
弱弱说一句,Charles这些体验有一点点复杂了,新手容易进来找不到方向,半天不明白为什么没有记录到请求~
所以在这就啰嗦了几句。
设定需要被记录的请求/响应的匹配规则
Proxy - Recording Settings
用Include和Exclude设置匹配,只有include包含了且未被exclude包含的请求才会被记录到Session中,若include空,则记录所有请求
设置include
设定始终不用缓存
Tools - No Caching
勾选Enable No Caching,这个一般大家默认都会用到的吧
个性规则配置
设定文件本地替换
Tools - Map Local
勾选enable map local,charles就可以按照规则,把请求的对应目录(或文件)换成本地的目录(或文件)
小tip:弹出的编辑窗里不用麻烦地挨个填,把整个网址输到host,它会自动帮你把网址解析成host、path、query等几部分的
我做了一个整个目录的替换示例:
本地替换规则
设定重写请求/响应规则
Tools - Rewrite
这个是我认为Charles里比较重要的一个功能,和 Map Local配合非常好用。
先设定好规则组,需要用的时候勾选Enable Rewrite,再勾选需要用到规则组就好了。
我工作中的需求是本地替换,就是把请求js文件替换成本地对应的文件,这样就可以:编辑-保存-刷新 三步调试了。
这里不能只用map local,是因为js文件在被上传到服务器的时候会自动加上日期后缀,还有可能有a-z每日版本后缀。这样是为了保证版本更新迭代不会受到缓存的影响。当然也方便回退版本等,这种加后缀应该很多网站都有用到。所以,替换要求是这样的:
需要被替换成对应的本地文件 (workDir)/js/mi.js
现在就来开始设置吧:
先在左边add一个规则分组
右边修改分组名字,可选只对某些固定地址才使用,最下面是添加需要的重写规则,可以写多条。
我把url进行了重写,见图:
设置请求修改规则
这样设置之后
这个请求就会变成
然后,由于刚才设置了Map Local本地替换
所以这个被修改后的请求,会被指向本地的 (workDir)/js/mi.js
这就完成了稍微复杂一点的替换功能了
Rewrite功能很强大的,包括header的增删改和param的增删改,还有body修改等。
大家可以尽情发挥修改请求和替换文件目录的创意~
为其他设备做代理
proxy - proxy setting
charles的另外一个比较常用的功能,就是为同一个局域网内的其他设备做代理,这样,就可以方便移动设备的调试了。
只需要勾选Enable transparent HTTP proxying,默认使用8888端口
然后在移动设备上设置代理地址:电脑的ip:8888 就可以了
现在就可以通过charles查看移动设备的所有请求了,同样可以对请求进行规则重写。
电脑本地编辑,保存,刷新移动设备,这样调试很简单吧!
其他偶尔用到的功能
Proxy - Throttle Setting
这是网络延迟功能,可以测试慢网速下的体验效果
Tool - Map Remote
类似Map Local,只是替换成的是一个另网址,而不是本地路径
Charles还有很多其他的功能,比较反向代理,断点,保存完整请求什么的,只是lz木有用过,所以就只有大家自己去体验吧~
另外,Charles缺少一个我很需要的功能,就是host切换,这倒是有一点点小小的遗憾。
楼主是blog新手,如有错误请见谅and请告诉我,Thanks~~游戏开发(3)
软件开发(2)
& & &时间:日-7月30日
& & &耗时:2天
& & & &此前一直在玩OpenGL,做的都是三维世界的东西,已经好久没有写过2D类的小游戏了。上学期,玩了《charles》之后,就一直想要写一款类似的射击类小游戏,只是前段时间有很多跟图形学有关的程序还要填坑,而且还要忙着参加夏令营。到现在终于闲了下来,就开始着手做一下这款小游戏《Hori Miona》吧。(在家一周也没见体重长回去多少)
& & & &这篇博文,可能更多的涉及到“游戏开发架构”。这俩天对于我自己来讲,也算是是摸索出了比较不错的架构。不管是3D还是2D游戏,render和modeling虽然不同,但是架构应该是个可以通用的模式。
& & & &在正文开始之前,还是惯例上一下我的实现结果。
射击游戏《Hori Miona》
一、下载链接:
二、游戏截图:
本游戏的部分设计细节
& & & 程序的可视化界面为GameWidget类,并进行游戏循环,利用计时器Timer更新游戏状态。玩家Player类,用于记录玩家的状态信息;同时,玩家的所有操作由状态控制,每次游戏循环中,根据玩家当前所处的行为状态(攻击、移动?),更新玩家的信息。在Player类中,还有一个攻击管理器AttackManager,用于对玩家的攻击进行处理,包括:攻击的渲染、攻击模式的转化、攻击的碰撞检测等等。此外,在GameWidget中,还有一个成员EnemyManager,用于对游戏中的AI单位进行控制,根据玩家的当前位置,更新敌人的状态。
& & & 如下是简化的类图(在进行大致设计时采用):
二、基于四叉树的场景管理。
& & & &在游戏中的敌人的数目,这里采取了基于四叉树的场景管理的方法。虽然前面的类图在设计阶段是list&Enemy&来代替的。但是为了提高检索效率还是必须要引入四叉树进行场景对象的管理。
四叉树并不仅仅针对二维的游戏场景上,这里所指的二维是因为四叉树本身仅仅考虑了两个维度。在三维的游戏场景中,我们也可以使用四叉树,因为在四叉树应用最广泛的室外地形场景中,z轴往往只代表地形高度信息,或者说它的信息相比起xy轴而言,并没有特别重要。这是我们在场景管理中可以适当忽略的部分。
& & & 四叉树有很多变种,先谈一个简单的情况,就是假设所有物体是一个点,这样比较容易理解。在后面可以利用AABB包围盒进行碰撞检测。
& & & 把每个点放到正方形空间里,若该正方形内含有超过1个点(2个或2个以上的点),就把该正方形分割,直至每个小正方形(叶节点)仅含有一个点,就可以得出以下的分割结果:
& & & &这个做法是可以调整的,也就是说当空间分割到一定大小就不能继续分割(如最多只能对一个结点分割4层,因为层数太多也会影响检索效率)。关于四叉树节点的数据结构可按如下进行定义:
struct treeNode {
//是否是叶节点
// 四个子树
treeNode* upL
treeNode* upR
treeNode* downL
treeNode* downR
int objectN //包含对象个数
List&Object& //包含的对象
//所在的AABB包围盒
}& & & & & 了解了最基本四叉树后,可把问题从质点扩充到占有一定体积的物体。虽然我们可以每次比较场景物体和正方形的相交,但是为了提高性能,一般使用物体的包围盒进行碰撞检测:
& & & & & &这里推荐我的另外一篇文章《对Obj模型的AABB包围盒加载器》:
三、状态图在游戏中的应用:
& & & & 相比起一般的软件开发,游戏开发对状态图的依赖应该是比较强的了。因为游戏中通常会涉及很多复杂的状态转换过程。比如:实现飞机移动的状态转换。这里也简单拿这个例子来进行一下说明:在程序中,飞机的非战斗状态主要包括以下几种行为(用枚举类型表示):
class Player
// 飞机运动状态
enum STATE
// 静止左转
// 静止右转
_RUN_LEFT,
// 运动左转
_RUN_RIGHT
// 运动右转
short m_curS
// 飞机当前运行状态
void setCurrentState(short state);
// 设置飞机的当前状态
short getCurrentState();
// 获取飞机的当前状态
void updateStates();
void render(QPainter* painter);
& & &这是玩家类Player的简化代码,预设了6种非战斗的状态。为了能理顺完整的状态转换,因此设计了如下的状态图(为了方便绘制,没有体现左转的情况,但是可以对称得到):
& & & &在有了上面的状态图的情况下,便可以非常轻松地写出相应的状态转换代码:
void GameWidget::keyPressEvent(QKeyEvent *event)
if(event-&isAutoRepeat())
switch(event-&key())
case Qt::Key_W:
if(m_player.getCurrentState()==Player::_STOP)
m_player.setCurrentState(Player::_RUN);
if(m_player.getCurrentState()==Player::_LEFT)
m_player.setCurrentState(Player::_RUN_LEFT);
if(m_player.getCurrentState()==Player::_RIGHT)
m_player.setCurrentState(Player::_RUN_RIGHT);
case Qt::Key_A:
if(m_player.getCurrentState()==Player::_STOP)
m_player.setCurrentState(Player::_LEFT);
if(m_player.getCurrentState()==Player::_RIGHT)
m_player.setCurrentState(Player::_LEFT);
if(m_player.getCurrentState()==Player::_RUN || m_player.getCurrentState()==Player::_RUN_RIGHT)
m_player.setCurrentState(Player::_RUN_LEFT);
case Qt::Key_D:
if(m_player.getCurrentState()==Player::_STOP)
m_player.setCurrentState(Player::_RIGHT);
if(m_player.getCurrentState()==Player::_LEFT)
m_player.setCurrentState(Player::_RIGHT);
if(m_player.getCurrentState()==Player::_RUN || m_player.getCurrentState()==Player::_RUN_LEFT)
m_player.setCurrentState(Player::_RUN_RIGHT);
case Qt::Key_J:
m_attackManager.setAttacked(true);
case Qt::Key_Space:
// 切换攻击模式
m_attackManager.changeAttackMode();
ui-&lblAttackMode-&setText(m_attackManager.getAttackMode());
case Qt::Key_R:
if(m_timer.isActive())
m_timer.stop();
m_timer.start();
case Qt::Key_Escape:
m_timer.stop();
emit sig_closeGameWidget();
void GameWidget::keyReleaseEvent(QKeyEvent *event)
if(event-&isAutoRepeat())
switch(event-&key())
case Qt::Key_W:
if(m_player.getCurrentState()==Player::_RUN)
m_player.setCurrentState(Player::_STOP);
if(m_player.getCurrentState()==Player::_RUN_LEFT)
m_player.setCurrentState(Player::_LEFT);
if(m_player.getCurrentState()==Player::_RUN_RIGHT)
m_player.setCurrentState(Player::_RIGHT);
case Qt::Key_A:
if(m_player.getCurrentState() == Player::_RUN_LEFT && !bD)
m_player.setCurrentState(Player::_RUN);
if(m_player.getCurrentState() == Player::_LEFT && !bD)
m_player.setCurrentState(Player::_STOP);
if(m_player.getCurrentState() == Player::_RUN_LEFT && bD)
m_player.setCurrentState(Player::_RUN_RIGHT);
if(m_player.getCurrentState() == Player::_LEFT && bD)
m_player.setCurrentState(Player::_RIGHT);
case Qt::Key_D:
if(m_player.getCurrentState() == Player::_RUN_RIGHT && !bA)
m_player.setCurrentState(Player::_RUN);
if(m_player.getCurrentState() == Player::_RIGHT && !bA)
m_player.setCurrentState(Player::_STOP);
if(m_player.getCurrentState() == Player::_RUN_RIGHT && bA)
m_player.setCurrentState(Player::_RUN_LEFT);
if(m_player.getCurrentState() == Player::_RIGHT && bA)
m_player.setCurrentState(Player::_LEFT);
case Qt::Key_J:
m_attackManager.setAttacked(false);
四、火焰碰撞的矩阵计算:
& & & &在2D游戏的开发中,其实会发现和3D游戏有很多相似之处。用到的主要数学方法有:
& & & &变换矩阵、 插值、图像遮罩等等。
& & & &这里介绍其中一个处理方法:火焰跟随飞机旋转的效果——借助变换矩阵去实现。
& & & & 这个和OpenGL中三维变换矩阵的计算类似,只是相应的转换成了2维,但是为了方便计算,我们还是要使用齐次坐标。火焰虽然在视觉上看到的是不规则且不断变化的图形,但是在游戏中,我是用的是一个凸多边形作为一个检测区域,如下图:
& & & & & & & & &
& & & 已知玩家的坐标pos(Vec3),和倾斜角度dir(float)。那么我们可以首先确定一个原始的菱形(顶点坐标pi已知,为齐次坐标x,y,w),再计算相应的三维变换矩阵matrix(3*3),将顶点坐标pi乘以三维变换矩阵matrix便可求出火焰的范围。
& & &计算的数学过程如下:
& & & & & & (1) 已知火焰顶点pi(x,y,w),和变换角度dir,
& & & & & & (2) 计算pi到火焰中心位置的平移矩阵mat1;
& & & & & & & & & & & 计算绕火焰中心位置旋转dir角度的旋转矩阵mat2;
& & & & & & & & & & & 计算从火焰中心到原位置pi的平移助阵Mat3;
& & & & & & (3) 得到三维变换矩阵matrix = mat3* mat2*mat1;
& & & & & & (4) 由点pi* matrix即可得出变换后的坐标pi'。
可以用如下代码得到:
// 将 pos从玩家中心移动到火焰中心
pos.setX(pos.x()+sin(3.14*dir/180.0)*90);
pos.setY(pos.y()-cos(3.14*dir/180.0)*90);
// 未变换的多边形
polygon&&QPointF(pos.x(),pos.y()-50)
&&QPointF(pos.x()-35,pos.y()+35)
&&QPointF(pos.x(),pos.y()+75)
&&QPointF(pos.x()+35,pos.y()+35);
// 计算旋转矩阵matrix
matrix.translate(pos.x(),pos.y());
// 平移到火焰中心
matrix.rotate(dir);
matrix.translate(-pos.x(),-pos.y());
// 平移回原位置
polygon = polygon*
// 多边形的坐标
& & & & &整体来说,这个项目的代码量要在2天时间内完成,还算是比较多的。想要在博客里面完全阐述所有的设计细节,真的是不太可能,但是欢迎交流。本程序是个娱乐工作,所以代码在整理完成后,会抽时间全部上传。
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:32841次
排名:千里之外
原创:43篇
评论:77条
(2)(3)(1)(4)(11)(4)(4)(4)(2)(7)(4)

我要回帖

更多关于 类似一起睡吗的游戏 的文章

 

随机推荐