Android游戏开发基础part2--Canvas画布

游戏开发基础part2--Canvas画布

又过了一周才继续做总结,四级结束了,应该可以多点时间学习游戏编程了。

Canvas画布类是一个在游戏当中担当非常重要的角色,它可以绘制出不同的图形和图片,可以说没有了画布就不能做出画面炫丽的游戏。

下面总结一下画布类Canvas封装的常用的函数:

具体说明如下:

1.drawColor(int color)

作用:绘制颜色覆盖画布,常用于刷屏

参数:颜色值,也可用十六进制形式表示(ARGB)

2.drawText(String text,float x,float y,Paint paint)

作用:绘制文本字符

第一个参数:文本内容

第二、三个参数:文本的X,Y坐标

第四个参数:画笔实例

3.drawPoint(float x,float y,Paint paint)

作用:绘制像素点

第一、二个参数:像素的坐标

第三个参数:画笔实例

4.drawPoints(float[] pts,Paint paint)

作用:绘制多个像素点

第一个参数:Float数组,数组中放置的是多个像素点的X,Y坐标

第二个参数:画笔实例

5.drawLine(float startX,float startY,float stopX,float stopY,Paint paint)

作用:绘制一条直线

前两个参数:起点的X,Y坐标

后两个参数:终点的X,Y坐标

最后一个参数:画笔实例

6.drawLines(float[] pts,Paint paint)

作用:绘制多条直线

第一个参数:Float数组,数组中放置的是多个直线的起始点与终点X,Y坐标

第二个参数:画笔实例

7.drawRact(Rect r,Paint paint)

作用:绘制矩形

第一个参数:矩形实例

第二个参数:画笔实例

8.drawRoundRect(RectF rect,float rx,float ry,Paint paint)

作用:绘制圆角矩形

第一个参数:矩形实例

第二个参数:圆角X轴的半径

第三个参数:圆角Y轴的半径

第四个参数:画笔实例

9.drawCircle(float cx,float cy,float radius,Paint paint)

作用:绘制圆形

第一、二个参数:圆形的中心点X,Y坐标

第三个参数:圆形的半径

第四个参数:画笔实例

10.drawArc(RectF oval,float startAngle,float sweepAngle,boolean useCenter,Paint paint)

作用:绘制弧形(扇形)

第一个参数:矩形实例

第二个参数:弧形的起始角度

第三个参数:弧形的终止角度

第四个参数:是否绘制中心点;如果为真,起始点与终止点都会分别连接中心点,从而形成封闭图形;如果为假,则起始点直接连到终止点,从而形成封闭图形。

第五个参数:画笔实例

11.drawOval(RectF oval,Paint paint)

作用:绘制椭圆

第一个参数:矩形实例

第二个参数:画笔实例

12.drawPath(Path path,Paint paint)

作用:绘制指定路径图形

第一个参数:路径实例

第二个参数:画笔实例

13.drawTextOnPath(String text,Path path,float hOffset,float vOffset,Paint paint)

作用:将文本沿着指定路径进行绘制

第一个参数:文本

第二个参数:路径实例

第三个参数:文本距离绘制起点的距离

第四个参数:文本距离路径的距离

第五个参数:画笔实例

创建项目实例:CanvasProject

项目运行效果图:

项目代码:

==>MySurfaceView.java

package com.cp;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PaintFlagsDrawFilter;
import android.graphics.Path;
import android.graphics.Rect;
import android.graphics.RectF;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.SurfaceHolder.Callback;

/**
 * 
 * @author Himi
 *
 */
public class MySurfaceView extends SurfaceView implements Callback, Runnable {
	//用于控制SurfaceView
	private SurfaceHolder sfh;
	//声明一个画笔
	private Paint paint;
	//声明一条线程
	private Thread th;
	//线程消亡的标识位
	private boolean flag;
	//声明一个画布
	private Canvas canvas;
	//声明屏幕的宽高
	private int screenW, screenH;
	//设置画布绘图无锯齿
	private PaintFlagsDrawFilter pfd = new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
	/**
	 * SurfaceView初始化函数
	 */
	public MySurfaceView(Context context) {
		super(context);
		//实例SurfaceHolder
		sfh = this.getHolder();
		//为SurfaceView添加状态监听
		sfh.addCallback(this);
		//实例一个画笔
		paint = new Paint();
		//设置画笔颜色为白色
		paint.setColor(Color.WHITE);
		//设置焦点
		setFocusable(true);
	}

	/**
	 * SurfaceView视图创建,响应此函数
	 */
	@Override
	public void surfaceCreated(SurfaceHolder holder) {
		screenW = this.getWidth();
		screenH = this.getHeight();
		flag = true;
		//实例线程
		th = new Thread(this);
		//启动线程
		th.start();
	}

	/**
	 * 游戏绘图
	 */
public void myDraw() {
	try {
		canvas = sfh.lockCanvas();
		if (canvas != null) {
			//----设置画布绘图无锯齿
			canvas.setDrawFilter(pfd);
			//----利用填充画布,刷屏
			canvas.drawColor(Color.BLACK);
			//----绘制文本
			canvas.drawText("drawText", 10, 10, paint);
			//----绘制像素点
			canvas.drawPoint(10, 20, paint);
			//----绘制多个像素点
			canvas.drawPoints(new float[] { 10, 30, 30, 30 }, paint);
			//----绘制直线
			canvas.drawLine(10, 40, 50, 40, paint);
			//----绘制多条直线
			canvas.drawLines(new float[] { 10, 50, 50, 50, 70, 50, 110, 50 }, paint);
			//----绘制矩形
			canvas.drawRect(10, 60, 40, 100, paint);
			//----绘制矩形2
			Rect rect = new Rect(10, 110, 60, 130);
			canvas.drawRect(rect, paint);
			canvas.drawRect(rect, paint);
			//----绘制圆角矩形
			RectF rectF = new RectF(10, 140, 60, 170);
			canvas.drawRoundRect(rectF, 20, 20, paint);
			//----绘制圆形
			canvas.drawCircle(20, 200, 20, paint);
			//----绘制弧形
			canvas.drawArc(new RectF(150, 20, 200, 70), 0, 230, true, paint);
			//----绘制椭圆
			canvas.drawOval(new RectF(150, 80, 180, 100), paint);
			//----绘制指定路径图形
			Path path = new Path();
			//设置路径起点
			path.moveTo(160, 150);
			//路线1
			path.lineTo(200, 150);
			//路线2
			path.lineTo(180, 200);
			//路径结束
			path.close();
			canvas.drawPath(path, paint);
			//----绘制指定路径图形
			Path pathCircle = new Path();
			//添加一个圆形的路径
			pathCircle.addCircle(130, 260, 20, Path.Direction.CCW);
			//----绘制带圆形的路径文本
			canvas.drawTextOnPath("PathText", pathCircle, 10, 20, paint);
		}
	} catch (Exception e) {
		// TODO: handle exception
	} finally {
		if (canvas != null)
			sfh.unlockCanvasAndPost(canvas);
	}
}

	/**
	 * 触屏事件监听
	 */
	@Override
	public boolean onTouchEvent(MotionEvent event) {
		return true;
	}

	/**
	 * 按键事件监听
	 */
	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event) {
		return super.onKeyDown(keyCode, event);
	}

	/**
	 * 游戏逻辑
	 */
	private void logic() {
	}

	@Override
	public void run() {
		while (flag) {
			long start = System.currentTimeMillis();
			myDraw();
			logic();
			long end = System.currentTimeMillis();
			try {
				if (end - start < 50) {
					Thread.sleep(50 - (end - start));
				}
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * SurfaceView视图状态发生改变,响应此函数
	 */
	@Override
	public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
	}

	/**
	 * SurfaceView视图消亡时,响应此函数
	 */
	@Override
	public void surfaceDestroyed(SurfaceHolder holder) {
		flag = false;
	}
}


==>MainActivity.java

package com.cp;

import android.app.Activity;
import android.os.Bundle;
import android.view.Window;
import android.view.WindowManager;

public class MainActivity extends Activity {
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		//设置全屏
		this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
		requestWindowFeature(Window.FEATURE_NO_TITLE);
		//显示自定义的SurfaceView视图
		setContentView(new MySurfaceView(this));
	}
}


<think>好的,我现在要解决的问题是如何在Unity中加载包含图片的Word文档,并将其内容(包括图片)转换为图片显示在Unity的画布上。用户之前已经询问过类似的问题,但现在文档中包含图片,需要更详细的代码实现。我需要回顾之前的回答,并在此基础上补充处理图片的部分。 首先,之前的回答提到了使用DocumentFormat.OpenXml库来解析Word文档,然后调用外部工具如LibreOffice进行转换。但现在文档中有图片,需要考虑如何提取这些图片,或者在转换过程中保留图片。可能的问题点包括: 1. **Word文档中的图片如何提取**:需要解析.docx文件中的图片部分,保存到本地,然后在Unity中加载这些图片。 2. **转换工具是否能保留图片**:使用LibreOffice或Microsoft Office转换时,生成的图片是否包含原文档中的图片。 3. **代码如何调整以适应图片处理**:之前的示例代码仅提取了文本,现在需要处理图片的提取和显示。 我需要分步骤思考解决方案: **步骤一:解析Word文档并提取图片** .docx文件实际上是一个ZIP压缩包,包含多个XML文件和资源文件。图片通常存储在word/media目录下。因此,可以通过解压.docx文件并遍历其中的图片文件来提取图片。但直接在代码中处理解压可能较为复杂,使用Open XML SDK是否能更方便地提取图片? 是的,DocumentFormat.OpenXml库提供了访问文档各部分的方法,包括图片部分。需要编写代码来遍历文档中的所有图像元素,并将它们保存为图片文件。 **步骤二:将Word文档转换为图片(包含图片)** 在之前的回答中,使用LibreOffice的命令行转换可能会自动处理图片,但需要确认生成的图片是否包含所有内容。如果转换后的图片包含了原文档的布局和图片,那可能就足够了。但用户可能需要更精确的控制,比如在Unity中重新排版文本和图片,或者单独处理每个图片。 如果选择外部转换工具,可能需要确保转换后的图片质量,以及图片中的内容是否正确。如果用户希望直接在Unity中渲染文本和图片,可能需要更复杂的处理,比如将文本和图片分别处理,然后在Canvas上组合,但这可能会非常复杂。 **步骤三:在Unity中显示处理后的内容** 如果通过外部工具将整个Word文档转换为一张图片,那么之前的加载方法仍然适用。但如果需要分别处理文本和图片,可能需要将它们作为不同的UI元素加载到Canvas中,比如使用Text组件和Image组件组合。 不过,用户的问题可能更倾向于将整个Word文档(包括图片)转换为一张图片,然后在Unity中显示这张图片。因此,重点可能在于如何确保转换后的图片包含所有内容。 现在,我需要详细考虑如何提取Word中的图片,并确保转换后的图片包含这些图片。可能需要分两部分处理:提取图片并保存,转换文档为图片,或者确保转换工具正确处理图片。 可能的代码调整包括: 1. 在C#中解析Word文档,提取图片并保存到临时文件夹。 2. 使用外部工具转换Word文档为图片,此时图片应包含原文档中的内容。 3. 在Unity中加载转换后的图片。 或者,如果转换工具无法正确处理图片,可能需要手动将文本和图片组合在Unity中,但这需要更多的开发工作。 现在,我需要编写具体的代码示例,展示如何提取Word文档中的图片,并将整个文档转换为图片,然后在Unity中显示。需要注意以下几点: - 如何用DocumentFormat.OpenXml提取图片。 - 如何处理转换过程中的外部工具调用。 - Unity中的资源加载和显示。 另外,用户可能需要详细的步骤和代码,因此需要提供完整的示例,包括必要的命名空间引用、代码结构等。 可能遇到的挑战包括: - 提取图片时的路径处理和文件保存。 - 确保外部工具(如LibreOffice)正确安装并配置环境变量。 - 跨平台兼容性,尤其是在不同操作系统上调用命令行工具。 - 处理Word文档中的复杂格式,如多张图片、不同布局等。 需要验证这些步骤的可行性,并在代码中添加必要的错误处理和日志输出,以便用户调试。 总结,解决方案可能包括: 1. 使用Open XML SDK提取Word中的图片并保存。 2. 使用LibreOffice将Word转换为图片(确保包含图片)。 3. 在Unity中加载转换后的图片并显示。 接下来,需要将这个过程分解为详细的代码步骤,并解释每个部分的作用。</think>在 Unity 中加载包含图片的 Word 文档并完整转换为画布上的图像需要分步骤处理。以下是详细实现方案: --- ### **核心步骤** 1. **解析 Word 文档并提取图片**:使用 `DocumentFormat.OpenXml` 库提取嵌入的图片。 2. **将 Word 转换为完整图片**:调用 LibreOffice 命令行工具转换文档为 PNG(保留所有内容)。 3. **Unity 中加载并显示图片**。 --- ### **详细代码实现** #### **1. 安装依赖库** - 在 C# 项目中通过 NuGet 安装: - `DocumentFormat.OpenXml` - `System.IO.Compression`(用于处理 .docx 压缩包) --- #### **2. 提取 Word 中的图片(C# 控制台工具)** ```csharp using DocumentFormat.OpenXml.Packaging; using System.IO; public class WordImageExtractor { public static void ExtractImages(string docPath, string outputDir) { // 创建输出目录 Directory.CreateDirectory(outputDir); // 打开 Word 文档 using (WordprocessingDocument doc = WordprocessingDocument.Open(docPath, false)) { var mainPart = doc.MainDocumentPart; // 遍历所有图片部件 foreach (ImagePart imagePart in mainPart.ImageParts) { // 生成唯一图片名 string imageName = $"image_{Guid.NewGuid()}.png"; string imagePath = Path.Combine(outputDir, imageName); // 保存图片到本地 using (FileStream stream = new FileStream(imagePath, FileMode.Create)) { imagePart.GetStream().CopyTo(stream); } } } } } ``` --- #### **3. 调用 LibreOffice 转换为图片(C# 代码)** ```csharp using System.Diagnostics; public class WordToImageConverter { public static void Convert(string docPath, string outputDir) { // 确保 LibreOffice 路径正确(Windows 示例) string libreOfficePath = @"C:\Program Files\LibreOffice\program\soffice.exe"; ProcessStartInfo psi = new ProcessStartInfo { FileName = libreOfficePath, Arguments = $"--headless --convert-to png --outdir {outputDir} {docPath}", UseShellExecute = false, CreateNoWindow = true }; Process process = new Process { StartInfo = psi }; process.Start(); process.WaitForExit(); // 等待转换完成 } } ``` --- #### **4. Unity 脚本加载图片** ```csharp using UnityEngine; using UnityEngine.UI; using System.IO; public class WordDisplay : MonoBehaviour { public string wordPath = @"D:\document.docx"; // Word 文件路径 public string outputPath = @"D:\ConvertedImages"; // 转换输出目录 void Start() { // 步骤1: 提取图片(需在外部工具中完成) // 步骤2: 转换 Word 为完整图片 // 步骤3: 加载最终生成的 PNG 文件 StartCoroutine(LoadWordAsImage()); } IEnumerator LoadWordAsImage() { // 调用外部转换工具(需提前配置路径) WordToImageConverter.Convert(wordPath, outputPath); // 等待转换完成(根据文件大小调整延迟) yield return new WaitForSeconds(2); // 加载最新生成的图片 string[] pngFiles = Directory.GetFiles(outputPath, "*.png"); if (pngFiles.Length > 0) { string latestImage = pngFiles[pngFiles.Length - 1]; byte[] imageData = File.ReadAllBytes(latestImage); Texture2D texture = new Texture2D(2, 2); texture.LoadImage(imageData); // 创建 Sprite 并显示在 UI Image 上 Sprite sprite = Sprite.Create(texture, new Rect(0, 0, texture.width, texture.height), new Vector2(0.5f, 0.5f)); GetComponent<Image>().sprite = sprite; } } } ``` --- ### **配置步骤** 1. **安装 LibreOffice**: - 下载地址:[https://www.libreoffice.org/](https://www.libreoffice.org/) - 确保命令行路径正确(Windows 默认路径为 `C:\Program Files\LibreOffice\program\soffice.exe`) 2. **Unity 设置**: - 将脚本挂载到 Canvas 的 Image 对象上。 - 确保 Unity 有权限访问 `D:\` 盘。 --- ### **注意事项** 1. **跨平台限制**: - LibreOffice 在 macOS/Linux 路径不同,需调整 `libreOfficePath`。 - iOS/Android 无法直接调用命令行工具,需在编辑器预处理。 2. **性能优化**: - 大文档转换耗时较长,建议在后台线程处理。 - 缓存已转换的图片避免重复生成。 3. **错误处理**: - 添加 `try-catch` 块处理文件权限或路径错误。 - 检查 LibreOffice 是否安装成功。 --- ### **扩展:动态排版(复杂需求)** 如果需要在 Unity 中动态排列文本和图片,需额外步骤: 1. 使用 `DocumentFormat.OpenXml` 解析文本和图片位置。 2. 在 Unity Canvas 中动态生成 `Text` 和 `Image` 组件。 3. 根据坐标信息布局(需复杂计算,适用于固定模板)。 --- 如果需要更具体的某部分代码(如动态布局或错误处理),请进一步说明!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值