本博主要是看到github上有TouchScript的基本的文档,想要翻译成中文,加深一下理解,同时写一下自己的想法。

原文博客:https://github.com/TouchScript/TouchScript/wiki/Pointer-Input


Pointer Input

TouchScript can work with many types of input sources, so a touch is generally called pointer in the library. At the moment of writing TouchScript can work with the following pointers: mouse, touch, pen, object.

个人理解:意思其实就是TouchScript可以接收到许多类型的输入源,比如说:鼠标、Windows7/8触摸、手机(ios、Android、Windows Phone)、TUIO。但是不管输入源是什么,TouchScript都会把它们转化成一致的内部数据类型:pointer类  (pointer是基类,继承它的类有mouse、touch、pen、object pointer类)。http://touchscript.github.io/docs/html/N_TouchScript_Pointers.htm

我们可以看到输入源那里,TouchScript把它们变成组件了,Standard Input负责的是普通的输入源,TUIO Input就是负责TUIO输入源了:

同时这里要说一下,mouse pointer应该就是鼠标输入对应的类了,touch pointer应该就是触屏设备的输入对应的类,pen pointer和object pointer不清楚。在TUIO Input里,主要是涉及了touch pointer和object pointer。

Pointers are registered by Input Sources and can come from any type of input device. TouchScript can be used just as an input mechanism for these pointers, ignoring all gesture recognition logic.

个人理解:Pointers是通过Input Sources注册的,Pointers可以来自任何输入设备。TouchScript可以被用来作为这些Pointers的输入机制,不用管手势识别的逻辑。其实就相当于TouchScript把东西都封装好了,可以适应于各种平台,我们只要有TouchScript就不用管输入设备不同这方面的事情了。

Adding pointer input

To enable TouchScript in your scene you generally want to put at least one component from TouchScript package into this scene. It will pull and initialize all the pointer recognition logic at run time.

But the best way to do this is to add TouchManager component to your scene. You can use it to store TouchScript configuration per scene.

Another component you will need is StandardInput which will be added automatically if your scene doesn't contain one. After you have an Input Source in the scene, you can receive pointer input. To do this you need to subscribe to TouchManager's events, like so:

为了在场景中更好的利用TouchScript,一般你会想要往场景中放不止一个组件。在Run的时候,所有的pointer识别逻辑都会被初始化。

但是最好的方式是加上TouchManager组件。另外一个必备的组件是StandardInput。当你在场景中有一个Input Source,你就能获取pointer输入。你需要订阅TouchManager事件,如下:

private void OnEnable()
{if (TouchManager.Instance != null) TouchManager.Instance.PointersPressed += pointersPressedHandler;
}private void OnDisable()
{if (TouchManager.Instance != null) TouchManager.Instance.PointersPressed -= pointersPressedHandler;
}

个人理解:先说一下那个TouchManager组件和StandardInput组件。你可以认为有了StandardInput组件,Unity才能获取你的鼠标输入或者触摸输入。有了TouchManager组件,才能管理一些TouchScript设置(不理解没关系,后面会讲到)

再来看代码,这个代码的意思就是订阅事件,顾名思义,就是将事件处理程序(方法)绑定到事件。先看Enable(),就是把pointersPressedHandler这个处理方法绑定到PointersPressed事件中去,也就是说当PointersPressed事件被触发的时候,会调用pointersPressedHandler这个函数。那么OnDisable()就是解除绑定了。

如果你没看懂,来看这个篇博客:Unity事件

As you can see, current instance of TouchManager singleton can be accessed via TouchManager.Instance property.

When using C#, a script should subscribe to TouchScript events in OnEnable() method and unsubscribe in OnDisable() to prevent memory leaks. Handlers you assign to touch events is where you can extend TouchScript to do the touch interaction that you'd like. Here's an example that implements the pointersPressedHandler above.

个人理解:TouchManager单例的实例化可以通过TouchManager.Instance这个属性来触及到。 不懂单例的童鞋来看这篇博客:Unity单例

当使用c#的时候,一个script应该在OnEnable()中订阅到TouchScript事件中去,并且再OnDisable()中解除绑定来防止内存泄露。下面就可以额看看pointersPressedHandler()的实现:

private void pointersPressedHandler(object sender, PointerEventArgs e)
{foreach (var pointer in e.Pointers) Debug.Log(pointer.Id + " touched down at " + pointer.Position);
}

个人理解:为什么要在OnEnable()中绑定呢。这个需要了解Unity的运行机制,不懂的同学来看这个博客:Unity函数执行顺序

总之就是放在这个函数里,可以保证事件监听贯彻始终。

来看代码,很明显,这个pointerPressedHandler()就是遍历在PointerPressed事件中接收到的Pointers,然后输出它们的Id和位置。

拓展:

可以研究一下TouchManager.cs的源码,就有这个pointerPressed事件:

/** @author Valentin Simonov / http://va.lent.in/*/using System;
using System.Collections.Generic;
using TouchScript.Core;
using TouchScript.Devices.Display;
using TouchScript.Layers;
using TouchScript.Pointers;
using TouchScript.Utils.Attributes;
using UnityEngine;
using UnityEngine.Events;
using Object = UnityEngine.Object;namespace TouchScript
{/// <summary>/// A facade object to configure and hold parameters for an instance of <see cref="ITouchManager"/>. Contains constants used throughout the library./// <seealso cref="ITouchManager"/>/// </summary>/// <remarks>/// <para>An instance of <see cref="TouchManager"/> may be added to a Unity scene to hold (i.e. serialize them to the scene) parameters needed to configure an instance of <see cref="ITouchManager"/> used in application. Which can be accessed via <see cref="TouchManager.Instance"/> static property.</para>/// <para>Though it's not required it is a convenient way to configure <b>TouchScript</b> for your scene. You can use different configuration options for different scenes.</para>/// </remarks>[AddComponentMenu("TouchScript/Touch Manager")][HelpURL("http://touchscript.github.io/docs/html/T_TouchScript_TouchManager.htm")]public sealed class TouchManager : DebuggableMonoBehaviour{#region Constants#if TOUCHSCRIPT_DEBUGpublic const int DEBUG_GL_START = int.MinValue;public const int DEBUG_GL_TOUCH = DEBUG_GL_START;
#endif/// <summary>/// Event implementation in Unity EventSystem for pointer events./// </summary>[Serializable]public class PointerEvent : UnityEvent<IList<Pointer>> {}/// <summary>/// Event implementation in Unity EventSystem for frame events./// </summary>/// <seealso cref="UnityEngine.Events.UnityEvent" />[Serializable]public class FrameEvent : UnityEvent {}/// <summary>/// Values of a bit-mask representing which Unity messages an instance of <see cref="TouchManager"/> will dispatch./// </summary>[Flags]public enum MessageType{/// <summary>/// Pointer frame started./// </summary>FrameStarted = 1 << 0,/// <summary>/// Pointer frame finished./// </summary>FrameFinished = 1 << 1,/// <summary>/// Some pointers were added during the frame./// </summary>PointersAdded = 1 << 2,/// <summary>/// Some pointers were updated during the frame./// </summary>PointersUpdated = 1 << 3,/// <summary>/// Some pointers have touched the surface during the frame./// </summary>PointersPressed = 1 << 4,/// <summary>/// Some pointers were released during the frame./// </summary>PointersReleased = 1 << 5,/// <summary>/// Some pointers were removed during the frame./// </summary>PointersRemoved = 1 << 6,/// <summary>/// Some pointers were cancelled during the frame./// </summary>PointersCancelled = 1 << 7}/// <summary>/// Names of dispatched Unity messages./// </summary>public enum MessageName{/// <summary>/// Pointer frame started./// </summary>OnFrameStart = MessageType.FrameStarted,/// <summary>/// Pointer frame finished./// </summary>OnFrameFinish = MessageType.FrameFinished,/// <summary>/// Some pointers were added during the frame./// </summary>OnPointersAdd = MessageType.PointersAdded,/// <summary>/// Some pointers have updated during the frame./// </summary>OnPointersUpdate = MessageType.PointersUpdated,/// <summary>/// Some pointers have touched the surface during the frame./// </summary>OnPointersPress = MessageType.PointersPressed,/// <summary>/// Some pointers were released during the frame./// </summary>OnPointersRelease = MessageType.PointersReleased,/// <summary>/// Some pointers were removed during the frame./// </summary>OnPointersRemove = MessageType.PointersRemoved,/// <summary>/// Some pointers were cancelled during the frame./// </summary>OnPointersCancel = MessageType.PointersCancelled}/// <summary>/// Centimeter to inch ratio to be used in DPI calculations./// </summary>public const float CM_TO_INCH = 0.393700787f;/// <summary>/// Inch to centimeter ratio to be used in DPI calculations./// </summary>public const float INCH_TO_CM = 1 / CM_TO_INCH;/// <summary>/// The value used to represent an unknown state of a screen position. Use <see cref="TouchManager.IsInvalidPosition"/> to check if a point has unknown value./// </summary>public static readonly Vector2 INVALID_POSITION = new Vector2(float.NaN, float.NaN);/// <summary>/// TouchScript version./// </summary>public static readonly Version VERSION = new Version(9, 0);/// <summary>/// TouchScript version suffix./// </summary>public static readonly string VERSION_SUFFIX = "";#endregion#region Events/// <summary>/// Occurs when a new frame is started before all other events./// </summary>public FrameEvent OnFrameStart = new FrameEvent();/// <summary>/// Occurs when a frame is finished. After all other events./// </summary>[SerializeField]public FrameEvent OnFrameFinish = new FrameEvent();/// <summary>/// Occurs when new hovering pointers are added./// </summary>[SerializeField]public PointerEvent OnPointersAdd = new PointerEvent();/// <summary>/// Occurs when pointers are updated./// </summary>[SerializeField]public PointerEvent OnPointersUpdate = new PointerEvent();/// <summary>/// Occurs when pointers touch the surface./// </summary>[SerializeField]public PointerEvent OnPointersPress = new PointerEvent();/// <summary>/// Occurs when pointers are released./// </summary>[SerializeField]public PointerEvent OnPointersRelease = new PointerEvent();/// <summary>/// Occurs when pointers are removed from the system./// </summary>[SerializeField]public PointerEvent OnPointersRemove = new PointerEvent();/// <summary>/// Occurs when pointers are cancelled./// </summary>[SerializeField]public PointerEvent OnPointersCancel = new PointerEvent();#endregion#region Public properties/// <summary>/// Gets the instance of <see cref="ITouchManager"/> implementation used in the application./// </summary>/// <value>An instance of <see cref="ITouchManager"/> which is in charge of global pointer input control in the application.</value>public static ITouchManager Instance{get { return TouchManagerInstance.Instance; }}/// <summary>/// Gets or sets current display device./// </summary>/// <value>Object which holds properties of current display device, like DPI and others.</value>/// <remarks>A shortcut for <see cref="ITouchManager.DisplayDevice"/> which is also serialized into scene.</remarks>public IDisplayDevice DisplayDevice{get{if (Instance == null) return displayDevice as IDisplayDevice;return Instance.DisplayDevice;}set{if (Instance == null){displayDevice = value as Object;return;}Instance.DisplayDevice = value;}}/// <summary>/// Indicates if TouchScript should create a CameraLayer for you if no layers present in a scene./// </summary>/// <value><c>true</c> if a CameraLayer should be created on startup; otherwise, <c>false</c>.</value>/// <remarks>This is usually a desired behavior but sometimes you would want to turn this off if you are using TouchScript only to get pointer input from some device.</remarks>public bool ShouldCreateCameraLayer{get { return shouldCreateCameraLayer; }set { shouldCreateCameraLayer = value; }}/// <summary>/// Gets or sets a value indicating whether a <see cref="TouchScript.InputSources.StandardInput"/> should be created in scene if no inputs present./// </summary>/// <value> <c>true</c> if StandardInput should be created; otherwise, <c>false</c>. </value>/// <remarks>This is usually a desired behavior but sometimes you would want to turn this off.</remarks>public bool ShouldCreateStandardInput{get { return shouldCreateStandardInput; }set { shouldCreateStandardInput = value; }}/// <summary>/// Gets or sets a value indicating whether Unity messages are sent when <see cref="ITouchManager"/> dispatches events./// </summary>/// <value><c>true</c> if Unity messages are used; otherwise, <c>false</c>.</value>/// <remarks>If Unity messages are used they are sent to an object set as a value of <see cref="SendMessageTarget"/> property or to TouchManager's GameObject if it's <c>null</c>.</remarks>public bool UseSendMessage{get { return useSendMessage; }set{if (value == useSendMessage) return;useSendMessage = value;updateSendMessageSubscription();}}/// <summary>/// Gets or sets the bit-mask which indicates which events from an instance of <see cref="ITouchManager"/> are sent as Unity messages./// </summary>/// <value>Bit-mask with corresponding bits for used events.</value>public MessageType SendMessageEvents{get { return sendMessageEvents; }set{if (sendMessageEvents == value) return;sendMessageEvents = value;updateSendMessageSubscription();}}/// <summary>/// Gets or sets the SendMessage target GameObject./// </summary>/// <value>Which GameObject to use to dispatch Unity messages. If <c>null</c>, TouchManager's GameObject is used.</value>public GameObject SendMessageTarget{get { return sendMessageTarget; }set{sendMessageTarget = value;if (value == null) sendMessageTarget = gameObject;}}/// <summary>/// Gets or sets a value indicating whether Unity Events should be used./// </summary>/// <value>///   <c>true</c> if TouchManager should use Unity Events; otherwise, <c>false</c>./// </value>public bool UseUnityEvents{get { return useUnityEvents; }set{if (useUnityEvents == value) return;useUnityEvents = value;updateUnityEventsSubscription();}}#if TOUCHSCRIPT_DEBUG/// <inheritdoc />public override bool DebugMode{get { return base.DebugMode; }set{base.DebugMode = value;if (Application.isPlaying) (Instance as TouchManagerInstance).DebugMode = value;}}#endif#endregion#region Public methods/// <summary>/// Determines whether a Vector2 represents an invalid position, i.e. if it is equal to <see cref="INVALID_POSITION"/>./// </summary>/// <param name="position">Screen position.</param>/// <returns><c>true</c> if position is invalid; otherwise, <c>false</c>.</returns>public static bool IsInvalidPosition(Vector2 position){return position.x == INVALID_POSITION.x && position.y == INVALID_POSITION.y;}#endregion#region Private variables#pragma warning disable CS0414[SerializeField][HideInInspector]private bool basicEditor = true;#pragma warning restore CS0414[SerializeField]private Object displayDevice;[SerializeField][ToggleLeft]private bool shouldCreateCameraLayer = true;[SerializeField][ToggleLeft]private bool shouldCreateStandardInput = true;[SerializeField][ToggleLeft]private bool useSendMessage = false;[SerializeField]private MessageType sendMessageEvents = MessageType.PointersPressed | MessageType.PointersCancelled |MessageType.PointersReleased | MessageType.PointersUpdated |MessageType.PointersAdded | MessageType.PointersRemoved;[SerializeField]private GameObject sendMessageTarget;[SerializeField]private bool useUnityEvents = false;[SerializeField]private List<TouchLayer> layers = new List<TouchLayer>();#endregion#region Unityprivate void Awake(){if (Instance == null) return;#if TOUCHSCRIPT_DEBUGif (DebugMode) (Instance as TouchManagerInstance).DebugMode = true;
#endifInstance.DisplayDevice = displayDevice as IDisplayDevice;Instance.ShouldCreateCameraLayer = ShouldCreateCameraLayer;Instance.ShouldCreateStandardInput = ShouldCreateStandardInput;for (var i = 0; i < layers.Count; i++){var layer = layers[i];if (layer != null) LayerManager.Instance.AddLayer(layer, i);}}private void OnEnable(){updateSendMessageSubscription();updateUnityEventsSubscription();}private void OnDisable(){removeSendMessageSubscriptions();removeUnityEventsSubscriptions();}[ContextMenu("Basic Editor")]private void switchToBasicEditor(){basicEditor = true;}#endregion#region Private functionsprivate void updateSendMessageSubscription(){if (!Application.isPlaying) return;if (Instance == null) return;if (sendMessageTarget == null) sendMessageTarget = gameObject;removeSendMessageSubscriptions();if (!useSendMessage) return;if ((SendMessageEvents & MessageType.FrameStarted) != 0) Instance.FrameStarted += frameStartedSendMessageHandler;if ((SendMessageEvents & MessageType.FrameFinished) != 0) Instance.FrameFinished += frameFinishedSendMessageHandler;if ((SendMessageEvents & MessageType.PointersAdded) != 0) Instance.PointersAdded += pointersAddedSendMessageHandler;if ((SendMessageEvents & MessageType.PointersUpdated) != 0) Instance.PointersUpdated += pointersUpdatedSendMessageHandler;if ((SendMessageEvents & MessageType.PointersPressed) != 0) Instance.PointersPressed += pointersPressedSendMessageHandler;if ((SendMessageEvents & MessageType.PointersReleased) != 0) Instance.PointersReleased += pointersReleasedSendMessageHandler;if ((SendMessageEvents & MessageType.PointersRemoved) != 0) Instance.PointersRemoved += pointersRemovedSendMessageHandler;if ((SendMessageEvents & MessageType.PointersCancelled) != 0) Instance.PointersCancelled += pointersCancelledSendMessageHandler;}private void removeSendMessageSubscriptions(){if (!Application.isPlaying) return;if (Instance == null) return;Instance.FrameStarted -= frameStartedSendMessageHandler;Instance.FrameFinished -= frameFinishedSendMessageHandler;Instance.PointersAdded -= pointersAddedSendMessageHandler;Instance.PointersUpdated -= pointersUpdatedSendMessageHandler;Instance.PointersPressed -= pointersPressedSendMessageHandler;Instance.PointersReleased -= pointersReleasedSendMessageHandler;Instance.PointersRemoved -= pointersRemovedSendMessageHandler;Instance.PointersCancelled -= pointersCancelledSendMessageHandler;}private void pointersAddedSendMessageHandler(object sender, PointerEventArgs e){sendMessageTarget.SendMessage(MessageName.OnPointersAdd.ToString(), e.Pointers,SendMessageOptions.DontRequireReceiver);}private void pointersUpdatedSendMessageHandler(object sender, PointerEventArgs e){sendMessageTarget.SendMessage(MessageName.OnPointersUpdate.ToString(), e.Pointers,SendMessageOptions.DontRequireReceiver);}private void pointersPressedSendMessageHandler(object sender, PointerEventArgs e){sendMessageTarget.SendMessage(MessageName.OnPointersPress.ToString(), e.Pointers,SendMessageOptions.DontRequireReceiver);}private void pointersReleasedSendMessageHandler(object sender, PointerEventArgs e){sendMessageTarget.SendMessage(MessageName.OnPointersRelease.ToString(), e.Pointers,SendMessageOptions.DontRequireReceiver);}private void pointersRemovedSendMessageHandler(object sender, PointerEventArgs e){sendMessageTarget.SendMessage(MessageName.OnPointersRemove.ToString(), e.Pointers,SendMessageOptions.DontRequireReceiver);}private void pointersCancelledSendMessageHandler(object sender, PointerEventArgs e){sendMessageTarget.SendMessage(MessageName.OnPointersCancel.ToString(), e.Pointers,SendMessageOptions.DontRequireReceiver);}private void frameStartedSendMessageHandler(object sender, EventArgs e){sendMessageTarget.SendMessage(MessageName.OnFrameStart.ToString(),SendMessageOptions.DontRequireReceiver);}private void frameFinishedSendMessageHandler(object sender, EventArgs e){sendMessageTarget.SendMessage(MessageName.OnFrameFinish.ToString(),SendMessageOptions.DontRequireReceiver);}private void updateUnityEventsSubscription(){if (!Application.isPlaying) return;if (Instance == null) return;removeUnityEventsSubscriptions();if (!useUnityEvents) return;Instance.FrameStarted += frameStartedUnityEventsHandler;Instance.FrameFinished += frameFinishedUnityEventsHandler;Instance.PointersAdded += pointersAddedUnityEventsHandler;Instance.PointersUpdated += pointersUpdatedUnityEventsHandler;Instance.PointersPressed += pointersPressedUnityEventsHandler;Instance.PointersReleased += pointersReleasedUnityEventsHandler;Instance.PointersRemoved += pointersRemovedUnityEventsHandler;Instance.PointersCancelled += pointersCancelledUnityEventsHandler;}private void removeUnityEventsSubscriptions(){if (!Application.isPlaying) return;if (Instance == null) return;Instance.FrameStarted -= frameStartedUnityEventsHandler;Instance.FrameFinished -= frameFinishedUnityEventsHandler;Instance.PointersAdded -= pointersAddedUnityEventsHandler;Instance.PointersUpdated -= pointersUpdatedUnityEventsHandler;Instance.PointersPressed -= pointersPressedUnityEventsHandler;Instance.PointersReleased -= pointersReleasedUnityEventsHandler;Instance.PointersRemoved -= pointersRemovedUnityEventsHandler;Instance.PointersCancelled -= pointersCancelledUnityEventsHandler;}private void pointersAddedUnityEventsHandler(object sender, PointerEventArgs e){OnPointersAdd.Invoke(e.Pointers);}private void pointersUpdatedUnityEventsHandler(object sender, PointerEventArgs e){OnPointersUpdate.Invoke(e.Pointers);}private void pointersPressedUnityEventsHandler(object sender, PointerEventArgs e){OnPointersPress.Invoke(e.Pointers);}private void pointersReleasedUnityEventsHandler(object sender, PointerEventArgs e){OnPointersRelease.Invoke(e.Pointers);}private void pointersRemovedUnityEventsHandler(object sender, PointerEventArgs e){OnPointersRemove.Invoke(e.Pointers);}private void pointersCancelledUnityEventsHandler(object sender, PointerEventArgs e){OnPointersCancel.Invoke(e.Pointers);}private void frameStartedUnityEventsHandler(object sender, EventArgs e){OnFrameStart.Invoke();}private void frameFinishedUnityEventsHandler(object sender, EventArgs e){OnFrameFinish.Invoke();}#endregion}
}

--------------------END----------------

看不懂没关系,硬钢就完事儿了。

TouchScript中文---Pointer Input相关推荐

  1. TouchScript中文---Gestures

    github英文:https://github.com/TouchScript/TouchScript/wiki/Gestures Gestures In TouchScript all gestur ...

  2. TouchScript中文---The Journey of a Touch Point

    github英文:https://github.com/TouchScript/TouchScript/wiki/The-Journey-of-a-Touch-Point The Journey of ...

  3. input框监听输入法输入中文

    input框监听输入法输入中文 需求 input事件 select为什么不能使用 注意select的onChange和onSearch 需求 想要在input框中进行接口实时查询,但是在使用输入法输入 ...

  4. 限制input 输入框只能输入纯数字/数字/中文/英文

    1.文本框只能输入数字代码(小数点也不能输入) <input onkeyup="this.value=this.value.replace(/\D/g,'')" onafte ...

  5. input禁止键盘及中文输入

    <input>禁止键盘及中文输入,但又不能用readonly 而且还需兼容ie 和 ff , 为了完成这功能费了蛮大功夫,呵呵,在此记录以便日后之用: Html代码   <!DOCT ...

  6. input 限制只能输入英文、中文、字母、小数、表情包等约束

    输入大小写字母.数字.下划线: <input type="text" οnkeyup="this.value=this.value.replace(/[^\w_]/ ...

  7. html input 禁止输入中文

    思路一: html input 禁止输入中文: <input type="text" class="username" οnkeyup="val ...

  8. Unity 触摸插件 TouchScript遇到的坑

    说在前面,我现在的项目使用TouchScript 是因为突然改需求要用触摸屏.原本TouchScript的功能根本不能满足项目用. 网上找到大部分教学都没有说怎么用Script写其他功能,所以只能一步 ...

  9. 最强大,最简洁的【禁止输入中文】

    方法一:禁止中文输入法 <input type="text" style="ime-mode:disabled"> 方法二:禁止黏贴,禁止拖拽,禁止 ...

最新文章

  1. discuz 二次开发
  2. 运行配置文件中指定类的指定方法
  3. Java-进阶:多线程1
  4. 匿名内部类和匿名类_匿名schanonymous
  5. PL/SQL Developer连接Oracle 11g在Win8 64位系统下乱码
  6. android gridview行分割线,Android中控件GridView实现设置行列分割线的方法示例
  7. 大一计算机应用基础答案李小艳,13级幼师班期末考试计算机试题A卷
  8. Codeforces Round #661-C Boats Competition
  9. 对于数据给定范围sql取数_SQL Server中的报表–根据给定日期范围内提取的数据创建图表
  10. Python爬虫错误重试,超时处理
  11. CMS:内容管理系统
  12. 华为数通设备常用命令大全
  13. 中国34个省级行政区2000年-2021年逐月1km植被指数NDVI栅格数据处理及下载
  14. 微信数据清空了怎么办?误删微信聊天记录怎么恢复
  15. 2018北京网络赛B题 Tomb Raider
  16. 发邮件抛异常。no object DCH for MIME type text/plain; charset=UTF-8
  17. 简易计算机在线使用方法,jQuery实现简单在线计算器方法
  18. java中几种读取配置文件的方法
  19. 【三栏式布局、双飞翼布局、圣杯布局】09
  20. Linux操作系统根社区简介

热门文章

  1. 全球与中国测量传声器市场现状及未来发展趋势
  2. 全面认识VCAP,你知道多少?
  3. 串口异或校验字C++代码实现
  4. bcc校验c语言实现,Linux BCC(异或校验)计算命令行工具
  5. 从大一统视角理解扩散模型(Diffusion Models)
  6. Git 分支管理常见三种方式
  7. cocos creator做一个儿童数字答题的微信小游戏(1)
  8. 关于游戏开发的一些思想碰撞
  9. 两台电脑其中一台无法ping通的问题
  10. UML图:类图 --详细介绍