Suck the cat with code! This article is participating in [Cat essay Activity]
🍕 introduction
- I have one for you today
To protect the kitten
Small game source sharing Complete project source code
At the end of the article can be directly downloaded to experience!- The following to this small game project source, a simple analysis, here is not step by step to demonstrate, mainly to share the source ~
- Plus the
Soundnet's audio SDK
Voice chat function, also very practical oh ~
🎄 [small game] protect the cat effect display + complete project source code
Let’s take a look at the game effect first
Game effect display:
The core gameplay is to use the mouse to control a block to protect the kitten from obstacles
The kitten will keep climbing to score points, and the race will be over when it hits an obstacle!
Very test player reaction and hand speed oh ha ha, anyway I play for a while GG ~
😻 Game pictures
Let’s take a look at some in-game screenshots from the beginning of the game, during and after the game
As follows:
😺 Project analysis
The project directory structure is as follows:
- _Prefabs: indicates the prefab
- _Scenes: Scene folder
- _Scripts: folder for storing scripts
- _Sprites: folder for Sprite images
- Animations: Animation controller folder
- Common: Folder for Common materials and scripts
- Music_Sound: Folder for storing audio
- Plugins: folders where plug-ins are stored
- Resources: folder for loading files
Preforms are mainly UI elements in the game, because this is a 2D game, so the materials used in the UI, preforms and so on are UI
There is only one main scene, because the game is very simple, so both the start screen and the game screen are completed in the same scene!
Script words have a dozen, control the game of a running logic process!
Sprite
There are many, in the course of the game will be constantly switching to achieve a visual effect ~
Also,Audio folder
Basically, there is a background music, a start and end sound effects
What’s in the Resources folder is important because one of the core elements of the game we’re playing is that the scene is treated randomly
There are many prefabricated models that are randomly generated during the game to increase the gameplay
That’s what this little game is all aboutGameplay mechanics
If the obstacles are the same every time, then this little game is really not fun haha ~
😹 core code explanation
This project has two game controllers, the MainController and the HomeController
The content in HomeController is relatively simple
The MainController is a core controller that controls how the game runs, how the core obstacles are loaded, how the background images are switched and loaded
As well as new level loading, start, pause, continue, end game logic processing and real-time UI updates and other functions
Is the core script of the entire game operation, part of the code is as follows:
public class MainController : BaseController {
public Transform backRegion, spawnRegion;
public BackItem backPrefab;
public List<GroupObstacle> obstaclePrefabs;
private int colorIndex = 0, backCount = 0;
private BackItem lastBack = null;
public enum GameState {START, LOADED, PLAYING, GAME_OVER, COMPLETED, GUIDE, SHOP, PAUSED};
public static GameState gameState = GameState.START, lastState = GameState.START;
public GameObject startFrame, guideFrame, shopFrame, gameTitle;
public Protection protection;
public ChallengeController challengeController;
public ClassicController classicController;
public static MainController instance;
public ContinueFrame continueFrame;
public MyPlayer player;
private int spawnLevel = 1, passedLevel = 0, currentLevel = 0;
private int savedObstacleIndex, lastObstacleIndex;
public Animator flash;
private List<BackItem> backs = new List<BackItem>();
protected override void Awake()
{
base.Awake();
instance = this;
}
protected override void Start()
{
base.Start();
SetupBackground();
LoadAllObstacles();
}
private void LoadAllObstacles()
{
obstaclePrefabs = Resources.LoadAll<GroupObstacle>("GroupObstacles").ToList();
obstaclePrefabs.Sort((x, y) => Utils.GetGroupObIndex(x.name).CompareTo(Utils.GetGroupObIndex(y.name)));
}
private void SetupBackground()
{
lastBack = SpawnNewBackground(Vector3.zero);
lastBack.SetUp(0.5.true.true.0);
backs.Add(lastBack);
colorIndex = Random.Range(1.5);
float canvasHeight = backRegion.parent.GetComponent<RectTransform>().sizeDelta.y;
for (int i = 0; i < 2; i++)
{
Vector3 pos = new Vector3(0, lastBack.rect.anchoredPosition.y + (i == 0 ? canvasHeight : Const.BACK_HEIGHT));
lastBack = SpawnNewBackground(pos);
lastBack.SetUp(colorIndex, colorIndex, i == 0.false.1); backs.Add(lastBack); }}}Copy the code
The MyPlayer script is mounted to our cat and controls the switch of ICONS and the logic associated with collisions on the cat
When encountering obstacles trigger the end of the game event, related logic processing!
public SpriteRenderer icon;
public Sprite[] iconSprites;
public GameObject playerIconPrefab;
public GameObject bubble;
public GameObject[] bubbleParts;
void Start()
{
UpdateSprite();
}
public void UpdateSprite()
{
int selectedType = CUtils.GetPlayerType();
icon.sprite = iconSprites[selectedType];
}
void OnCollisionEnter2D(Collision2D collision)
{
if (collision.collider.tag == "Obstacle" && MainController.IsPlaying())
{
MainController.instance.CollideWithObstacle();
MainController.instance.CheckAndShowContinue();
icon.gameObject.SetActive(false);
GetComponent<CircleCollider2D>().isTrigger = true;
bubble.SetActive(false);
foreach (GameObject p in bubbleParts)
{
p.SetActive(true);
}
GetComponent<Animator>().SetTrigger("Break");
Sound.instance.Play(Sound.Others.Break);
Timer.Schedule(this.0.5 f, () => { Sound.instance.Play(Sound.Others.Die); }); SpawnIcon(); }}private void SpawnIcon()
{
GameObject obj = (GameObject)Instantiate(playerIconPrefab);
obj.transform.localPosition = icon.transform.position;
obj.GetComponent< SpriteRenderer>().sprite = iconSprites[CUtils.GetPlayerType()];
obj.transform.localScale = Vector3.one * 0.5 f;
}
public void Reset()
{
icon.gameObject.SetActive(true);
GetComponent<CircleCollider2D>().isTrigger = false;
bubble.SetActive(true);
foreach(GameObject p in bubbleParts)
{
p.SetActive(false); }}Copy the code
I won’t go through the rest of the code. Like this little game can download the source code project entertainment
Although it is a small game, a total of a dozen scripts, but still quite playable!
😼 Access the audio SDK of sonnet
The core gameplay of the small game is solved, and we will add the audio SDK to achieve a voice chat function for him!
The access code is very simple, just download the SDK of audio call on Sonnet, and create a project to get the APP ID!
This is the place where to download the SDK: docs. Agora. IO/cn/All/down…
And then we findUnity's audio SDK
To downloadThen go toThe consoleCreate a projectDirect selectionDebug mode
, and click WillAPP ID
Copy that, and we’ll use it later!
Now we have got the SDK of sonnet audio and the APP ID of the project. The next step is to add this SDK into our small game
Access to the method is also very simple, we download the SDK directly copy into our small game project!
This folder is directly copied into our small game project!
Then add voice chat function, the core code is as follows:
private InputField mChannelNameInputField;/ / channel number
public Text mShownMessage;/ / hint
public Button joinChannel;// Join the room
public Button leaveChannel;// Leave the room
private IRtcEngine mRtcEngine = null;
// After entering the App ID, delete ## outside the App ID
[SerializeField]
private string AppID = "app_id";
void Awake()
{
QualitySettings.vSyncCount = 0;
Application.targetFrameRate = 30;
CheckAppId();
}
// Initialize
void Start()
{
#if (UNITY_2018_3_OR_NEWER)
// Check whether you have microphone permission. If not, apply for permission
if(! Permission.HasUserAuthorizedPermission(Permission.Microphone)) { Permission.RequestUserPermission(Permission.Microphone); }#endif
joinChannel.onClick.AddListener(JoinChannel);
leaveChannel.onClick.AddListener(LeaveChannel);
mRtcEngine = IRtcEngine.GetEngine(AppID);
// Join channel callback after success
mRtcEngine.OnJoinChannelSuccess += (string channelName, uint uid, int elapsed) =>
{
string joinSuccessMessage = string.Format(Uid: {0}, channel: {1}, version: {2}, uid, channelName, getSdkVersion());
Debug.Log(joinSuccessMessage);
mShownMessage.GetComponent<Text>().text = (joinSuccessMessage);
//muteButton.enabled = true;
};
// Leave channel callback.
mRtcEngine.OnLeaveChannel += (RtcStats stats) =>
{
string leaveChannelMessage = string.Format({0} "left channel callback time, tx: {1}, rx: {2}, tx KBPS: {3}, rx KBPS: {4}", stats.duration, stats.txBytes, stats.rxBytes, stats.txKBitRate, stats.rxKBitRate);
Debug.Log(leaveChannelMessage);
mShownMessage.GetComponent<Text>().text = (leaveChannelMessage);
};
/// <summary>
///Join channel
/// </summary>
public void JoinChannel()
{
// Get the channel name from the input box on the interface
string channelName = "666666";
// Get the channel name from the input box on the interface
//string channelNameOld = mChannelNameInputField.text.Trim();
Debug.Log(string.Format("Get channel name {0} from interface input box", channelName));
if (string.IsNullOrEmpty(channelName))
{
return;
}
// Join the channel
// channelKey: dynamic key, we did not select the Token mode, here can pass null; Otherwise, you need to pass in the tokens generated by the server
// channelName: indicates the channelName
// info: developer attached information (not necessary), not passed to other users in the channel
// uid: indicates the user ID. 0 is automatically assigned
mRtcEngine.JoinChannelByKey(channelKey: null, channelName: channelName, info: "extra", uid: 0);
// Join the channel and set the publish and subscribe status.
//mRtcEngine.JoinChannel(channelName, "extra", 0);
}
/// <summary>
///Leave the channel
/// </summary>
public void LeaveChannel()
{
// Leave the channel
mRtcEngine.LeaveChannel();
string channelName = "abc666";
Debug.Log(string.Format("left channel name {0}", channelName));
}
void OnApplicationQuit()
{
if(mRtcEngine ! =null)
{
/ / destroy IRtcEngineIRtcEngine.Destroy(); }}Copy the code
Just mount the script code into our scenario and add two buttons to control joining and leaving the voice channel
Then assign the APP ID of the project we created in sonnet to it and it can be used normally!
The access to audio SDK part of this article is not particularly detailed, you can also go to see how to access the audio network SDK article, specifically learn about it!
🎁 game source download
In this article the protection of the cat source project download link is here!
【 Cat protection 】 small game download
Interested partners can download experience ~
💬 summary
-
This article shares a puzzle game [cat protection] game source code and a simple analysis of the game structure and code part
-
Combined with the SDK of sonnet, a simple voice chat function is realized, although the access function is not very complete
-
But still can satisfy our one voice chat function!
-
Later, I will try to make more functions for soundnet SDK to play ~ powerful