最近依旧在读毛选,这本书是个人的、第一人称的视角,带有个人对当下环境的描写和思辨,与以往看过的第一人称的书不同的是,书中的内容是真实发生的,对人的心灵和引起的思索的影响大很多。

从小到大每个人都知晓100年前的ww1 ww2这段历史,对我们来说,这是我们最近的历史;对毛而言,最近的历史却是袁世凯、康有为、清朝灭亡;对毛而言,当下的境况是外忧内患,是祖国虽有鼎盛的历史但近几百年却是积贫积弱、半殖民地半封建社会。

在这段历史中,毛像穿越了,像拥有剧本,虽然毛选的内容是公开发表给所有民众的,所以按理说毛应该保持乐观积极、目光长远,但对于百年后的我们而言,读到这些胜不骄败不累、从始至终贯穿的对社会主义的追寻,心灵受到了震撼。这本书里,读者跟随作者,重新回到百年前的境遇,面对着那时候的变故和许多重要/灰暗/光明的时刻,以往读书从未有这种极其代入、身临其境的情况,感觉自己的部分变成了毛。

在读了毛选一段时间后,工作日傍晚散步的时候,天色渐暗,夕阳垂落,夕阳下自己穿过桥和道路,看着广东路边葱郁的植被映射余晖,有种自己是毛然后重生于这个时代的感觉。思辨能力强、头脑清晰的毛,看到如今的世界,看到城市高楼林立,看到科技变革接踵而至,会有怎样的思辨,对未来发展的方向有怎样的想法。自己像是活了两段人生,一段便是百年前的战争岁月,另一段即是当下千禧年的时光,当下的高楼林立是真实的,百年前的战争岁月却让我觉得同样真实,当下因此反而显得短暂、虚幻。

1

# smus

## 一 呼吸
* 口鼻同吸。
	* 类似吸烟那种感觉。
	* 也类似受到惊吓
* 最终是要做到快吸慢吐
### 呼吸练习
* 练口鼻同吸。<- 慢吸慢吐,吸完之后尽量数到30。数30的过程就是在慢吐。练习6min左右即可停歇。
* 练 快吸 <- 快吸快吐。快吸之后数1,数1的时候也会吐一点气出来,接着在将剩下的气慢慢吐出来。每次数到5即可,练习总计练习4min左右即可停歇
* 练 快吸慢吐 <- 快吸,接着发出”s“的声音,在发音的过程就是说在慢吐,也是尽量慢吐坚持30s。每次练习6min

### 对应歌时的练习
* 听live的歌曲是在什么时候呼吸的,尽量和live时一样。没有必要比live时更少换气,应追求的是一样。练习时是吹纸巾,吸气时和歌手同时,呼出气时将纸一直吹高直到下次换气 

## 二 腹肌发力
### 练习
* 先持续无声发出"s"的几秒,接着切换到同时有 无声"s" 和 发声的"s",持续更多时间。总共持续20多秒
	* 这个过程中腹肌是发力的;类似与做 躺着时将手脚在空中并拢 时腹部发力那样,不过这里的腹部发力是为了让气流震动喉咙发出声音,有一种感觉自己是个喇叭的感觉。

### 心得
* 唱歌时也是腹部发力,让声音传出,自己像个喷火的喇叭那种。

## 三 锻炼肌肉
### 练习
* 跟着节拍发出"hey“ 的狗喘气,伸出舌头。
	* 这个是练习腹部那个肌肉
	* 跟着有节奏的、快节奏的音乐练习

## 四
### 练习
* 类似 三 的狗喘气,不过是发声,发出"han“的声音

## 五
* 鼻腔发音,鼻子吸气呼气,哼,第一次鼻子要出气,找到鼻子透气气流从鼻子出来发音的感觉
* 练习鼻音内,一边摇头一边内,保持脖子放松。 

## 六
* 咬字,带着咬牙切齿的感觉说话,发'哥',结合气咬字,哥,用鼻腔共鸣唱歌

## 七 假声
* 假声是怎样的呢?发"呜~~~"的尖锐的声音,这就是假声。
	* 这个"呜"声,声调从高到低感受这个假声到真声的切换过程。接着声调从低到高感受真声到假声的切换的过程。
	* 假声的时候,声带是比真声拉长的。 	
* 练习
	* 练张杰的这就是爱的高潮那部分,这就是爱 这句歌词,前三个字声音渐高,第四个字时则用上了假声。练习这个假声、真声自如切换的过程。
	* 同时应努力让声音往后。靠上颚那个肌肉把声音往后。

## 八 混声
###### 改进点
* 气流要足
###### 混声练习
* "wu呜"声,前四个音用假声,最后一个切到真声,但不降那么快。这个处于两个中间地段的就是 混声

## 九 6.3

* 唱歌时要让一个音保持那个调,而不能中途时断时续
* 真声唱高音
 练习 伸出舌头,鼻子出气,发高音
 方法是有点像吸鼻子。鼻子是网上吸的,不是往下拉的。
* 假声能唱出高音,真声才能唱出
* 唱歌时也要心里想着后面那些字怎么唱,这样才能灵活的调整自己的调,而不会卡住的感觉

# ActionRPG

* 播放LevelSequence
	* 在场景中放入level sequence,在beginplay中找到ls,接着play ls.
		* 接着可以bind event on finished
			* niagara particle system也可以这样bind  

* player controller -> Set Virtual Joystick Visibility

* 有个叫做DoOnce的节点
* 有个叫做RemoeAllWidgets的节点
* open level的逻辑写在GameInstance里
* widget animation->GetEndTime(),从而可以在动画播放完后做事

# 虚幻三消

* actor获取gamemode

```
Cast<AMatch3GameMode>(UGameplayStatics::GetGameMode(WorldContextObject))
这个WorldContextObject传AActor this就行了
```

* spawned actor获取spawn自己的actor

```
FActorSpawnParameters SpawnParams;
SpawnParams.Owner = this;
SpawnParams.Instigator = GetInstigator();
SpawnParams.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn;
// Tiles never rotate
FRotator SpawnRotation(0.0f, 0.0f, 0.0f);
// Spawn the tile.
ATile* const NewTile = World->SpawnActor<ATile>(TileToSpawn, SpawnLocation, SpawnRotation, SpawnParams);

然后spawned actor:
Grid = Cast<AGrid>(GetOwner());            
			
```

* GameInstance使用
	* 在Edit->Project Settings->Project->Maps & Modes里配置用自己的GameInstance类
	* GameInstance复写父类方法:
	
    ```
    
	// Called by the game at startup.
	void Init() override;

	// Called by the game as it shuts down.
	void Shutdown() override;
    ```
    在这两个函数实现中,先写自己的自定义实现,最后再调用父类实现Super::F()
    
    * GameInstance有个USaveGame作为成员变量,在其他地方不操作USaveGame,所有有关的操作都通过GameInstance直接或间接进行。
    	* 每个level的slotname都是关卡名 
    	*  有个【TMap FString, int32】记录一些东西,如分数,是否播放音乐(将int32转为bool)

	* GameInstance的init里面,注册了一些事件
	
    ```
    LoginChangedHandle = FCoreDelegates::OnUserLoginChangedEvent.AddUObject(this, &UMatch3GameInstance::OnLoginChanged);
	EnteringForegroundHandle = FCoreDelegates::ApplicationHasEnteredForegroundDelegate.AddUObject(this, &UMatch3GameInstance::OnEnteringForeground);
	EnteringBackgroundHandle = FCoreDelegates::ApplicationWillEnterBackgroundDelegate.AddUObject(this, &UMatch3GameInstance::OnEnteringBackground);
	ViewportHandle = FViewport::ViewportResizedEvent.AddUObject(this, &UMatch3GameInstance::OnViewportResize_Internal);

    ```
    
  * 获取GameInstance
  
  ```
   UGameInstance* GameplayStatics::GetGameInstance(const UObject* WorldContextObject);
  ```
 
 * 游戏的设置(是否播放声音、是否播放音乐等设置)也作为成员变量记录在GameInstance里,接着在对应情况时检查GameInstance的设置。
 
* 获取当前Level的名字

```
/**
	* Get the name of the currently-open level.
	*
	* @param bRemovePrefixString	remove any streaming- or editor- added prefixes from the level name.
	*/
	UFUNCTION(BlueprintCallable, meta = (WorldContext = "WorldContextObject", AdvancedDisplay = "1"), Category = "Game")
	static FString GameplayStatics::GetCurrentLevelName(const UObject* WorldContextObject, bool bRemovePrefixString = true);
```

* 棋盘生成算法

以当前Actor为中心,左下角为0
```
FVector AGrid::GetLocationFromGridAddress(int32 GridAddress) const
{
	FVector Center = GetActorLocation();
	FVector OutLocation = FVector(-(GridWidth * 0.5f) * TileSize.X + (TileSize.X * 0.5f), 0.0f, -(GridHeight * 0.5f) * TileSize.Y + (TileSize.Y * 0.5f));
	check(GridWidth > 0);
	OutLocation.X += TileSize.X * (float)(GridAddress % GridWidth);
	OutLocation.Z += TileSize.Y * (float)(GridAddress / GridWidth);
	OutLocation += Center;

	return OutLocation;
}
```

* GameMode
	* 重启当前关卡

	```
    
	FName LevelName(*UGameplayStatics::GetCurrentLevelName(this, true));
	UGameplayStatics::OpenLevel(this, LevelName);
    ```

	* 实现UserWidget的切换

	```
    void AMatch3GameMode::ChangeMenuWidget(TSubclassOf<UUserWidget> NewWidgetClass)
{
	if (CurrentWidget)
	{
		CurrentWidget->RemoveFromViewport();
		CurrentWidget = nullptr;
	}
	if (NewWidgetClass)
	{
		if (AMatch3PlayerController* PC = Cast<AMatch3PlayerController>(UMatch3BlueprintFunctionLibrary::GetLocalPlayerController(this)))
		{
			CurrentWidget = CreateWidget<UUserWidget>(PC, NewWidgetClass);
			if (CurrentWidget)
			{
				CurrentWidget->AddToViewport();
			}
		}
	}
    ```
	* IsGameActive()

	```
bool AMatch3GameMode::IsGameActive() const
{
	// Game is active whenever time hasn't run out or the timer is paused.
	FTimerManager& WorldTimerManager = GetWorldTimerManager();
	return (WorldTimerManager.IsTimerActive(GameOverTimer) || WorldTimerManager.IsTimerPaused(GameOverTimer));
}
	```

	* GetRemainingTime

	```
GetWorldTimerManager().GetTimerRemaining(GameOverTimer)
	```

	* 给计时器加时间

	```
    重新设置下timer就好
    GetWorldTimerManager().SetTimer(GameOverTimer, this, &AMatch3GameMode::GameOver, StartingTimeValue + (ScoreAwardCount * Reward.TimeAwarded), false);
					
    ```
    
    * GameMode一般和PlayerController打交道

* PlayerController->IsLocalController()
* the network to uniquely identify a player:

```
PlayerController->PlayerState->GetUniqueId()->GetHexEncodedString()
```

* 交换宝石时那种位置移动的动画,通过节点Timeline在两个位置中lerp实现