0%

准备完了开题答辩,弄完了笔试,又咸鱼了数天、玩了数天《动物森友会》,一下子离上一篇C#杂记过了三个星期。

朔月

所以接下来要填的坑是LINQ和异步。弄完了这个,C#最大的几块拼图才得以完整,大抵能够叫是入了门。

查询表达式

所谓的LINQ,是语言集成查询Language INtegrated Query的缩写。通过引用命名空间System.Linq,可以用可读性极强的、类似SQL查询语句形式的代码对一些数据结构,甚至直接对数据库进行便捷的操作,如查询、排序、分组等,而不必编写大量逻辑复杂的循环代码。尤其是在与异步流式处理相结合时,可以优雅地将C#的性能发挥到极致。LINQ的操作十分高深,这里我仅学习一些基础、常用的LINQ功能。

以下是一个典型的LINQ查询示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
static void Main(string[] args){
//数据源
string[] name = {"Alonso", "Zheng", "Smith", "Jones", "Smythe", "Small", "Ruiz", "Hsieh", "Jorgenson", "Ilyich", "Singh", "Samba", "Fatimah" };

//查询表达式
var queryResults =
from n in names
where n.StartWith("S")
select n;

//迭代查询结果
WriteLine("Name beginning with S:");
foreach(var item in queryResults){
WriteLine(item);
}

Write("Program finished. Press Enter/Return to continue:");
ReadLine();

}
阅读全文 »

对BOSS战的分析,可以从战斗机制的设计和对玩家能力的考验两个方向进行。

战斗机制

何谓战斗机制?

“机制”这个词实在太宽泛。几个月前我曾在这篇笔记里总结过一次。

根据MDA框架,机制是“数据层面上的组件与算法”;形式、戏剧和动态元素框架中,“机制”基本等同于“形式”元素,即交互模式、目标、规则、过程、资源、边界、结局等等。四元法有一元是机制,指的是“玩家与游戏互动的规则”,也是游戏与其他非互动性媒体的区别所在。

不过,我们仍然可以把“机制”换个词,用“规则”来代替。更进一步的,战斗机制即是指,在战斗时,玩家能做什么?

那么《只狼》的战斗中,玩家能做什么?

最大的特色就是“打铁”,即弹反与架势槽。这个机制把传统动作游戏里高难度、高回报、低频率的“弹反”完全逆转成为难度相对偏低、回报不算明显,但使用频率极高的一种主要操作。《只狼》的战斗目标不再是单纯的削血,而主要是以进攻和弹反使敌人的架势槽涨满,此时即可一击必杀(忍杀)。同时架势槽的自然回落速度随剩余血量的减少而变慢,架势槽和血槽成为了相辅相成的两个机制。

第二点是处理敌人的“危”攻击。敌人偶尔发动无法格挡的技能,玩家头顶会浮现出红色的“危”字,这时就需要玩家根据敌人的起手动作,紧急判断下一步的应对措施。所谓的“危”其实也蕴含着“机”,如果处理得当,可以对敌方架势槽造成较大的上升。

主要的“危”攻击有两种类别,一是突刺,无法格挡,可以精准弹反,但正确的处理是在突刺的瞬间向敌人脸上垫步发动“识破”,造成较大的架势条上涨;二是横扫,最佳的处理方法是跳到敌人头上踩踏,亦可以造成较大的架势条上涨。一些BOSS战中能用“雷电奉还”反弹雷电攻击,而少数敌人能使出的擒抱攻击只能靠闪避处理。

阅读全文 »

这一篇虽记于3月4日,但一看日历,明日惊蛰,四舍五入等我写完便也是依照惯例的特殊日随笔了,那就把时间改为明天的第一帧吧。

写这篇的主要目的是作毕业设计工作进度的报告,因为昨天接到10号便要开题答辩的通知,依照要求我应在两天之内联系导师汇报工作进度。回过神来已是晚上八点,再不总结一下就要来不及了。

干了些什么?

太长不看,上列表:

  • 决定转向游戏制作
  • 学习C#和游戏学基础
  • 学习Aseprite和Photoshop
  • TextMesh Pro和UGUI
  • DanmakU类库,弹幕的生成
  • Pixel Perfect效果
  • 实现基本的游戏逻辑
阅读全文 »

昨天费力把上一篇中的“事件”章节给写完了,弄明白的确实不少(发现弄不明白的更多了)。

由于沉迷《饥荒》,并且也因为有点抗拒没听说过的概念,这一篇鸽到了现在。今天还是开始看吧。

协变(Covariance)和逆变(Contravariance)统称为变体(Variance)。

协变

协变是指,对派生程度更大的类型的支持。也就是说,对于某处要求的类型,传入它的派生类也是没关系的。这是很容易理解的,因为子类可以隐式地转换为基类。协变体现的即是面向对象程序设计思想中,所谓的“里氏替换原则”(Liskov Substitution Principle):任何基类可以出现的地方,子类一定可以出现。

逆变

神秘的问题

比较难以理解的是逆变。与协变相反,这是对派生程度更小的类型的支持。比如在要求string的地方支持使用object。什么地方会出现这种看似违反里氏替换原则的“危险”操作呢?

在翻阅了许多文档之后,我反而是在《深入理解 TypeScript》中找到了较为明白的解释,下面我试着用C#的方式叙述一下。

假设Greyhound (灰狗)是 Dog (狗)的子类,而 Dog 则是 Animal (动物)的子类。由于子类型通常是可传递的,因此我们也称 GreyhoundAnimal 的子类。这是显然的。

那么,一个问题出现了:

如果我们有一个委托Func<Dog, Dog>,是不是真的只能分配那些接受Dog为参数,并返回Dog的方法呢?

阅读全文 »