android自定义游戏闯关图,Android自定义View(四) -- Canvas

本文计划根据HenCoder系列文章进行学习,所以代码风格及博文素材可能会摘自其中。

1 范围裁切

范围裁切有两个方法: clipRect() 和 clipPath()。裁切方法之后的绘制代码,都会被限制在裁切范围内。

1.1 clipRect()

使用很简单,直接应用:

canvas.clipRect(100,100,400,400);

Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.snoopy);

canvas.drawBitmap(bitmap,100,100,paint);

bef2482c675d

原图 对比 裁切

记得要加上 Canvas.save() 和 Canvas.restore() 来及时恢复绘制范围。

1.2 clipPath()

其实和 clipRect() 用法完全一样,只是把参数换成了 Path ,所以能裁切的形状更多一些:

canvas.save();

path.addCircle(500,500,400, Path.Direction.CCW);

canvas.clipPath(path);

Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.snoopy);

canvas.drawBitmap(bitmap,100,100,paint);

canvas.restore();

bef2482c675d

image.png

2. 几何变换

几何变换的使用大概分为三类:

使用 Canvas 来做常见的二维变换;

使用 Matrix 来做常见和不常见的二维变换;

使用 Camera 来做三维变换。

2.1 使用 Canvas 来做常见的二维变换:

2.1.1 Canvas.translate(float dx, float dy) 平移

参数里的 dx 和 dy 表示横向和纵向的位移。

canvas.save();

canvas.translate(300,100);

canvas.drawBitmap(bitmap,100,100,paint);

canvas.restore();

bef2482c675d

image.png

2.1.2 Canvas.rotate(float degrees, float px, float py) 旋转

参数里的 degrees 是旋转角度,单位是度(也就是一周有 360° 的那个单位),方向是顺时针为正向; px 和 py 是轴心的位置。

canvas.save();

canvas.rotate(200);

canvas.drawBitmap(bitmap,100,100,paint);

canvas.restore();

bef2482c675d

2.1.3 Canvas.scale(float sx, float sy, float px, float py) 放缩

参数里的 sx sy 是横向和纵向的放缩倍数; px py 是放缩的轴心。

canvas.save();

canvas.scale(1.5f,0.8f,100,100);

canvas.drawBitmap(bitmap,100,100,paint);

canvas.restore();

bef2482c675d

2.1.4 skew(float sx, float sy) 错切

参数里的 sx 和 sy 是 x 方向和 y 方向的错切系数。

canvas.save();

canvas.skew(0.3f,0.3f);

canvas.drawBitmap(bitmap,100,100,paint);

canvas.restore();

bef2482c675d

2.2 使用 Matrix 来做变换

2.2.1 使用 Matrix 来做常见变换

Matrix 做常见变换的方式:

创建 Matrix 对象;

调用 Matrix 的 pre/postTranslate/Rotate/Scale/Skew() 方法来设置几何变换;

使用 Canvas.setMatrix(matrix) 或 Canvas.concat(matrix) 来把几何变换应用到 Canvas。

平移

matrix.reset();

matrix.postTranslate(300,300);

canvas.save();

canvas.concat(matrix);

canvas.drawBitmap(bitmap,100,100,paint);

canvas.restore();

bef2482c675d

.png

其他效果就不一一展示,和Canvas方法一样。

把 Matrix 应用到 Canvas 有两个方法: Canvas.setMatrix(matrix) 和 Canvas.concat(matrix)。

Canvas.setMatrix(matrix):用 Matrix 直接替换 Canvas 当前的变换矩阵,即抛弃 Canvas 当前的变换,改用 Matrix 的变换(注:根据下面评论里以及我在微信公众号中收到的反馈,不同的系统中 setMatrix(matrix) 的行为可能不一致,所以还是尽量用 concat(matrix) 吧);

Canvas.concat(matrix):用 Canvas 当前的变换矩阵和 Matrix 相乘,即基于 Canvas 当前的变换,叠加上 Matrix 中的变换。

2.2.2 使用 Matrix 来做自定义变换

Matrix 的自定义变换使用的是 setPolyToPoly() 方法。

2.2.2.1 Matrix.setPolyToPoly(float[] src, int srcIndex, float[] dst, int dstIndex, int pointCount) 用点对点映射的方式设置变换

private float[] pointSrc = {20,50,200,400, 80,90,300,50};

private float[] pointsDst = {10, 70, 320, 310, 200, 100, 310, 200};

matrix.reset();

matrix.setPolyToPoly(pointSrc , 0,pointsDst,0,3);

canvas.save();

canvas.concat(matrix);

canvas.drawBitmap(bitmap,100,100,paint);

canvas.restore();

bef2482c675d

image.png

参数里,src 和 dst 是源点集合目标点集;srcIndex 和 dstIndex 是第一个点的偏移;pointCount 是采集的点的个数(个数不能大于 4,因为大于 4 个点就无法计算变换了)。

2.3 使用 Camera 来做三维变换

Camera 的三维变换有三类:旋转、平移、移动相机。

2.3.1 Camera.rotate*() 三维旋转

Camera.rotate*() 一共有四个方法: rotateX(deg) rotateY(deg) rotateZ(deg) rotate(x, y, z)。这四个方法的区别不用我说了吧?

canvas.save();

camera.save();

camera.rotate(0,0,20);

camera.applyToCanvas(canvas);

camera.restore();

canvas.drawBitmap(bitmap,100,100,paint);

canvas.restore();

bef2482c675d

image.png

如果你需要图形左右对称,需要配合上 Canvas.translate(),在三维旋转之前把绘制内容的中心点移动到原点,即旋转的轴心,然后在三维旋转后再把投影移动回来:

canvas.save();

canvas.translate(100,100);

camera.save();

camera.rotate(-20,0,20);

camera.applyToCanvas(canvas);

camera.restore();

canvas.translate(-100,-100);

canvas.drawBitmap(bitmap,100,100,paint);

canvas.restore();

bef2482c675d

Canvas 的几何变换顺序是反的,所以要把移动到中心的代码写在下面,把从中心移动回来的代码写在上面。

2.3.2 Camera.translate(float x, float y, float z) 移动

它的使用方式和 Camera.rotate*() 相同,而且我在项目中没有用过它,所以就不贴代码和效果图了。

2.3.3 Camera.setLocation(x, y, z) 设置虚拟相机的位置

注意!这个方法有点奇葩,它的参数的单位不是像素,而是 inch,英寸。

bef2482c675d

image

我 TM 的真没逗你,我也没有胡说八道,它的单位就。是。英。寸。

这种设计源自 Android 底层的图像引擎 Skia 。在 Skia 中,Camera 的位置单位是英寸,英寸和像素的换算单位在 Skia 中被写死为了 72 像素,而 Android 中把这个换算单位照搬了过来。是的,它。写。死。了。

bef2482c675d

image

吐槽到此为止,俗话说看透不说透,还是好朋友。

在 Camera 中,相机的默认位置是 (0, 0, -8)(英寸)。8 x 72 = 576,所以它的默认位置是 (0, 0, -576)(像素)。

如果绘制的内容过大,当它翻转起来的时候,就有可能出现图像投影过大的「糊脸」效果。而且由于换算单位被写死成了 72 像素,而不是和设备 dpi 相关的,所以在像素越大的手机上,这种「糊脸」效果会越明显。

bef2482c675d

image

而使用 setLocation() 方法来把相机往后移动,就可以修复这种问题。

camera.setLocation(0, 0, newZ);

bef2482c675d

image

Camera.setLocation(x, y, z) 的 x 和 y 参数一般不会改变,直接填 0 就好。

好了,上面这些就是本期的内容:范围裁切和几何变换。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/244295.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python打印菱形星号代码_Python打印“菱形”星号代码

小计本人是一名python初学者,刚刚看到一道有趣的python问题,“用python如何在编译器中打印出菱形图案?”因此决定尝试一下,代码不多,仅供参考。代码def printStar(intNum): # 打印星号s "*"spaceLength in…

android tag的使用方法,Android:如何使用Html.TagHandler?

所以,我终于想出了自己。public class MyHtmlTagHandler implements TagHandler {public void handleTag(boolean opening, String tag, Editable output,XMLReader xmlReader) {if(tag.equalsIgnoreCase("strike") || tag.equals("s")) {proce…

oracle打开scott用户_Oracle 11gR2中启动Scott用户的方法(推荐)

Oracle 中启动 Scott 用户 的方法 , 在 Oracle11gR2, (g 代表‘网络的意思) 数据库中 Scott 这个用户 安装时是被锁定的,安装 Oracle的时候 ,你可以直接选择 给该用户 解锁,如果忘记了解锁, 后期可以使用 s…

android 文件公有存储,如何将文件写入Android中的外部公共存储,以便从Windows中看到它们?...

如何将文件写入Android中的外部公共存储,以便从Windows中看到它们?我的应用程序应该将文件保存到一个地方,当您将手机/平板电脑连接到计算机时,您可以通过系统文件资源管理器看到它们。这就是我实现文件写入的方式:pro…

iPhone记步和Android计步,手机中运动步数是如何计算的?

微信运动每天都记录着你走路的步数,他会形成榜单,走的多收到很多赞,走的少则无人关注,如果你走到第一,你的照片将霸占排行榜封面。所以一段时间,每个人为了霸占封面疯狂走路、刷步,然而有时我们…

智能机器人建房子后房价走势_明后年日照房价走势如何?究竟是“上涨”还是下降...

想要在偌大的城市中拥有一个属于自己的家,那就必须要先有自己的一套房子,因为房子和自己以后的幸福生活密切相关。但是面对着如今格外高昂的房价,让很多人对房子产生了一种遥不可及的感觉。那么明后年日照房价走势如何呢?究竟是会…

android静默卸载,Android实践 -- Android静默安装和卸载

App的静默安装和卸载Android系统本身提供了安装卸载功能,但是api接口是hide的,不是公开的接口,所以在应用级别是无法实现静默安装和卸载的,要实现静默安装和卸载需要是系统应用,要有系统签名和相应的权限简单思路如下&…

outlook邮箱邮件大小限制_Office Outlook 2010、2013附件大小超过了允许的范围限制三种解决方法图解...

在outlook2010、2013中添加附件超过20M,就会提示:“附件大小超出了允许的范围”!outlook2007的附件默认大小是150M,而outlook2010、2013的是20M(有种说法是10M,也许是版本问题,未验证),也许微软…

dota迷你盒子Android5,DOTA:第一批TI7的迷你Aegis复制品已经到货

原标题:DOTA:第一批TI7的迷你Aegis复制品已经到货各地华丽的工艺。节日期间,一些Dota 2粉丝的完美礼物被封顶,他们本周开始收到令人垂涎的“宙斯盾”(Aegis of Champions)的缩影复制品。今年5月4日至10月1日举行的国际7战斗通行证…

oracle unpivot 索引_oracle 11g 行列转换之unpivot、pivot

一、 列 转 行create table STU_ROW2COL(id VARCHAR2(10),intname VARCHAR2(10),subject VARCHAR2(20),grade NUMBER)insert into stu_row2col (ID, INTNAME, SUBJECT, GRADE) values (1, ZORRO, 语文, 70);insert into stu_row2col (ID, INTNAME, SUBJECT, GR…

鸿蒙系统下拉菜单,鸿蒙的js开发部模式17:鸿蒙的系统能力的应用模块

1. 鸿蒙的系统能力主要涉及通知消息模块,在模拟器中也可以实践和获取初始界面:点击发送通知,顶部出现通知消息的图标下拉通知菜单栏,出现通知信息:js的业务逻辑代码:import notification from system.notification;no…

win7开启uasp协议_UASP与USB模式切换工具(SwitchUA官方版下载_UASP与USB模式切换工具(SwitchUASP) v1.0免费版 - Win7旗舰版...

UASP与USB模式切换工具(SwitchUASP)是一款能够帮助用户将系统的USB3.0传输模式切换到UASP模式的软件,利用软件能够有效的提升用户的电脑传输速度,有需要的可以下载使用。功能介绍UASP模式可以让USB的速度增加不少,特别是小文件的处理速度在us…

华为 原生android 6.0,安卓6.0原生桌面轻体验,我的手机从未如此流畅过

本帖最后由 啷个里格弄 于 2016-12-30 13:05 编辑1.png (188.33 KB, 下载次数: 65)2016-4-29 18:21 上传▏写在开头P8的EMUI系统或者称之为桌面在功能性和流畅度上都给我留下不错的印象。但是成天盯着一款桌面难免“七年之痒”,楼主这边就来给大家的P8换换口味&…

大数据职业理解_到底什么是大数据,大数据职业的具体工作内容是什么?

综合网络解释加上自己的理解给出了大数据的定义。大数据就是数据规模达到海量级、极快的速度流转、数据类型和来源多种多样、价值密度低而且能够反映事物真实性的数据就是大数据。大数据的工作内容包括以下几个方面:数据采集调查显示,未被使 用的信息比例…

兼容ios和android的ar,安卓又落后 这几款AR游戏只能iOS玩

近日苹果正式推送iOS 11,很多AR应用也随之上线。iOS 11一个很重要的亮点就是AR增强现实,利用它用户可以实现很多前所未有的体验,比如将室内的环境与游戏融为一体;还能测量距离。想知道你喜欢的明星身高吗?打开Measure这…

群晖如何建php网站_群晖折腾 篇一:群晖Web Station 功能搭建属于自己的照片分享网站...

群晖折腾 篇一:群晖Web Station 功能搭建属于自己的照片分享网站2020-03-03 16:42:1514点赞83收藏11评论小编注:此篇文章来自即可瓜分10万金币,周边好礼达标就有,邀新任务奖励无上限,点击查看活动详情创作立场声明&…

dilink智能网联系统鸿蒙系统,【图】秦Pro DM DiLink智能网联系统实测解读_汽车江湖...

一辆天天接触的车对于车主而言,早已不是一辆车这么简单了,更多时候它还充当我们的“好伙伴”甚至是“知己”,多少人下班停好车以后不愿意下车?因为他们知道这是一个分界点:推开车门你就是柴米油盐、是父亲、是儿子、是…

卓越性能代码_装好win10后,应该这样设置,才能压榨出系统十足的性能

用了这么久win10系统,你知道在win10中有不同的性能模式吗?而使用不同的性能模式会消耗不同的电量,就会为系统提供不同的性能。为了拥有好的性能,我们一般会在电源选项中给系统设置为高性能模式,但你以为这就够了吗&…

html语言中的转行标记是6,网页设计与制作模拟试题

全国2004年7月高等教育自学考试网页设计与制作试题网页设计与制作模拟试题一、 单项选择题(每空1分,共10分)1.目前在Internet上应用最为广泛的服务是( )。A.FTP服务 B.WWW服务 C.Telnet服务 D.Gopher服务2.在域名系统中,域名采用( )。A.树型命名机制 B.星…

swoolephp加密_PHP中给源代码加密的几种方法

商业使用推荐 Swoole Compiler 代码加密以下是如何通过PHP的自定义函数来加密我们的PHP源代码方法一function encode_file_contents($filename) {$typestrtolower(substr(strrchr($filename,.),1));if (php $type && is_file($filename) && is_writable($file…