Splash screen not working for Cocossharp game - c#

I try to write a splash screen in my first cocossharp game as write splash in android application. However, it show a black screen and then directly goto gameplayscene. So what should I change? Thank you very much!
public class SplashScene : CCScene
{
CCSprite splashImage1;
CCSprite splashImage2;
CCLayer splashLayer;
public SplashScene (CCWindow mainWindow) : base(mainWindow)
{
splashLayer = new CCLayer ();
this.AddChild (splashLayer);
splashImage1 = new CCSprite ("Splash1");
splashImage1.Position = ContentSize.Center;
splashImage1.IsAntialiased = false;
splashImage2 = new CCSprite ("Splash2");
splashImage2.Position = ContentSize.Center;
splashImage2.IsAntialiased = false;
}
public void PerformSplash()
{
splashLayer.AddChild (splashImage1);
Thread.Sleep(3000);
splashLayer.RemoveChild(splashImage1);
splashLayer.AddChild (splashImage2);
Thread.Sleep(2000);
splashLayer.RemoveChild (splashImage2);
GameAppDelegate.GoToGameScene ();
}
}

The game loop must be running for, well, any game framework to display and update. Calls to Thread.Sleep pause the execution of the thread.
If you want to display a splash screen for an interval the best way would be to simply create the splash scene as you are, and then schedule an action sequence
Something like this will wait for 2s, then remove the splashLayer and go to the game scene.
auto seq = Sequence::create(
DelayTime::create(2.0),
CallFunc::create([=](){
splashLayer->removeFromParent();
GameAppDelegate.GoToGameScene();
}),
nullptr);
runAction(seq);

Related

How to disable Gameobjects for Screenshot capturing in Unity on Android?

I have a simple goal for my Unity application running on Android: create a function, which disables my GUI, creates a screenshot, stores the image and enables the GUI again.
This is my current code:
The whole UI is stored in a GameObject which my handler class holds as property:
private bool makeScreenshotFlag;
public GameObject UserInterface;
makeScreenshotFlag above is used in the Update function:
// Update is called once per frame
void Update()
{
if (makeScreenshotFlag)
{
// Working with this flag is necessary,
// since we need to wait for the next frame,
// where the gui is not visible;
MakeScreenShot();
}
}
If the corresponding button gets pressed I fire the following Method:
public void OnCreateScreenshotButtonPressed()
{
UserInterface.SetActive(false);
makeScreenshotFlag = true;
}
And at last the method for the screenshot itself:
private void MakeScreenShot()
{
if (UserInterface.activeSelf) return; // wait for the next frame if the gui is still active
try
{
string filename = "screenshot_" + DateTime.Now.ToString("HH-mm-ss--dd-MM-yyyy") + ".png";
ScreenCapture.CaptureScreenshot(filename);
}
catch (Exception e)
{
DebugHelper.NewLog = "Error capturing screenshot: " + e.Message;
}
finally
{
makeScreenshotFlag = false;
UserInterface.SetActive(true);
}
}
In theory this should work, however the documentation for ScreenCapture.CaptureScreenshot() states the following:
The CaptureScreenshot returns immediately on Android. The screen capture continues in the background. The resulting screen shot is saved in the file system after a few seconds.
In practice this means, when my screenshot is made, the GUI is already enabled again. So far I couldn't find any event or similar to get notified as soon as the screenshot is made. The only thing I can think of is to store the screenshot filename and check if the file exists each frame after the screenshot is started.
Is there any other, more practical way?
Most probably, you are capturing the frame with UI itself. It's better to wait till the end of the frame using Coroutine.
public IEnumerator MakeScreenShot()
{
// Wait till the last possible moment before screen rendering to hide the UI
yield return null;
// Disable UI
UserInterface.SetActive(false);
// Wait for screen rendering to complete
yield return new WaitForEndOfFrame();
// Take screenshot
Application.CaptureScreenshot("screenshot.png");
// Show UI after we're done
UserInterface.SetActive(true);
}

AnimationPlayer animations do not play in Godot

Forewords
Firstly, I know posting graphical resources for codes is not encouraged in this platform. I will also post the code but, in this particular case, I think posting a video about it is much more helpful than just posting some arbitrary code because the structuring of game projects really vary depending on their requirements. However, I still respect the platform's rules so if a mod asks me to format my question according to the community rules, I can do that or they also can simply delete my question. I respect that.
The Issue
It's actually a simple issue but it's driving me crazy because of its simplicity. I just want to fade in when I load a scene and then fade out whenever I click a button. As to how I do that, this is the video about it.
To sum up, I load another scene called "Fader" which contains a ColorRect with a black color and AnimationPlayer to change ColorRect's alpha value.
The code is below with extra comments on relevant parts:
using Godot;
using System;
public class TitleScreen : Control
{
private Button[] buttons;
private Control fader; // the scene that I inject
public override void _Ready() // when title screen gets ready
{
GD.Print("Preparing TitleScreen...");
InitButtons();
InitFader(); // initialize fader
FadeIn(); // do fade in animation
}
private void InitFader() // initializing fader
{
GD.Print("Initializing fader...");
var faderScene = (PackedScene)ResourceLoader.Load("res://components/Fader.tscn"); // load external fader scene
fader = (Control)faderScene.Instance(); // instantiate the scene
fader.SetSize(OS.WindowSize); // set the size of fader scene to the game window, just in case
var rect = (ColorRect)fader.GetNode("rect"); // get "rect" child from fader scene
rect.SetSize(OS.WindowSize); // set "rect" size to the game window as well, just in case
fader.Visible = false; // set the visibility to false
AddChild(fader); // add initialized fader scene as a child of title screen
}
private void InitButtons()
{
GD.Print("Initializing buttons...");
buttons = new Button[3]{
(Button)GetNode("menu_container/leftmenu_container/menu/start_button"),
(Button)GetNode("menu_container/leftmenu_container/menu/continue_button"),
(Button)GetNode("menu_container/leftmenu_container/menu/exit_button"),
};
GD.Print("Adding events to buttons...");
buttons[0].Connect("pressed", this, "_StartGame");
buttons[2].Connect("pressed", this, "_QuitGame");
}
private void FadeIn()
{
GD.Print("Fading in...");
fader.Visible = true; // set visibility of fader to true
var player = (AnimationPlayer)fader.GetNode("player"); // get animation player
player.Play("FadeIn"); // play FadeIn animation
fader.Visible = false; // set visibility of fader to false
}
private void FadeOut()
{
// similar to FadeIn
GD.Print("Fading out...");
fader.Visible = true;
var player = (AnimationPlayer)fader.GetNode("player");
player.Play("FadeOut");
fader.Visible = false;
}
public void _StartGame() // whenever I click start game button
{
FadeOut(); // fade out
GetTree().ChangeScene("res://stages/Demo01.tscn");
}
public void _QuitGame() // whenever I click quit game button
{
FadeOut(); // fade out
GetTree().Quit();
}
}
Seems like I can't see something. Why does it not fade in and out?
Environment
Manjaro 19.0.2
Mono JIT Compiler 6.4.0 (if it is relevant)
Godot 3.2
So, the issue was Play method on AnimationPlayer object kinda runs like async (dunno if this is the correct term for it).
Luckily, there is a feature called signals in Godot. There are animation_started and animation_finished signals on AnimationPlayer objects. Basically, I created a C# script for Fader scene, hooked the signals from player to fader as in:
animation_started to _FaderAnimationStart
animation_finished to _FaderAnimationEnd
At the end, my script looks like below:
using Godot;
using System;
public class Fader : Control
{
private ColorRect rect;
private AnimationPlayer player;
public override void _Ready()
{
GD.Print("Initializing Fader...");
rect = (ColorRect)GetNode("rect");
player = (AnimationPlayer)GetNode("player");
SetSize(OS.WindowSize);
rect.SetSize(OS.WindowSize);
Visible = false;
}
private void _FaderAnimationStart(String anim_name)
{
Visible = true;
}
private void _FaderAnimationEnd(String anim_name)
{
Visible = false;
}
}
I solved it thanks to njamster's answer and Hans Passant's comment.
However, this only solves half of the problem. Yes, the scene now fades in when it loads but it does not fade out. Given that it executes kinda-async (again, I'm not sure if this is the correct term), changing scene interrupts while running the animation. I will update the answer when I solve that problem as well.
Update
Well, I cannot seem to solve the fade out part because it requires to access parent node from initialized child scene. There are some methods I can think of.
First one is to somehow parameterize "Fader" scene. This can be done in many ways but at the end, when you initialize it from another scene, you need to cast it to Fader and I don't know if this is a valid way to do it. Another concern is standardizing this in the codebase. A similar method is discussed in here.
Second one is to write it as a plugin which has it benefits and drawbacks. C# is not really battle-tested in this particular area.
Third one is to use a state management system. Here is a redux implementation for Godot. And you need to somehow integrate it for signals, which seems like a hassle.
So, overall, I still do not know how to fade out.

How can I reduce memory used by WebCameraTexture in unity on windows phone?

I made a demo application with two simple view in unity3d for windows phone platform.On first view I have a button and a text, from inspector I assign to button one event ( on Click) to open second view. In this view I have a raw image in a panel used to assign mainTexture to webCamTexture for to Start camera on phone.
var webCamTexture = new WebCamTexture();
rawImage.material.mainTexture = webCamTexture;
webCamTexture.Play();
In second View I have a button where I close camera and show first view ( closing current) webCameraTexture.Stop();
If I do that many times Play() and Stop() memory on my phone looks like:
How can I clear memory, when I stop the camera, because sometimes give me an error "Not enought storage to complete this operation" and exit from application.
Code Start Stop Camera:
//call onClick Button (next)
public void StartMyCamera()
{
webCamTexture = new WebCamTexture();
rawImage.material.mainTexture = webCamTexture;
webCamTexture.Play();
}
//call onClick btn (back - close camera)
public void StopMyCamera()
{
//to stop camera need only this line
webCamTexture.Stop();
//----try to clear
/*GL.Clear(false, true, Color.clear);
GC.Collect();
GC.WaitForPendingFinalizers();
rawImage.StopAllCoroutines();*/
//----
}
Currently you play the video with:
var webCamTexture = new WebCamTexture();
rawImage.material.mainTexture = webCamTexture;
webCamTexture.Play();
and stop it with
webCameraTexture.Stop();
This is doing exactly what your code is telling it to do. The new WebCamTexture() line of code is expected to allocate memory each time it is called. You are suppose to do this only once in the Start() function and then you can play and stop camera without memory allocation.
public RawImage rawImage;
WebCamTexture webCamTexture;
void Start()
{
intCam(); //Do this once. Only once
}
void intCam()
{
webCamTexture = new WebCamTexture();
rawImage.material.mainTexture = webCamTexture;
}
public void StartMyCamera()
{
webCamTexture.Play();
}
public void StopMyCamera()
{
//to stop camera need only this line
webCamTexture.Stop();
}
"Resources.UnloadUnusedAssets()" is helpful for your problem.
public void StopMyCamera()
{
webCamTexture.Stop();
Resources.UnloadUnusedAssets();
}

Calling admob only once

im having issues with admob for unity, I got the ads working and displaying after a player dies in the game, however if you die very quickly many times in a row the game crashes and I suspect it has to do with requesting ads to fast.
Requesting the ads:
private const string AD_UNIT_ID = "hidden_for_privacy";
private AdMobPlugin admob;
void Start () {
admob = GetComponent<AdMobPlugin> ();
admob.CreateBanner (AD_UNIT_ID, AdMobPlugin.AdSize.SMART_BANNER, true);
admob.RequestAd ();
admob.HideBanner ();
print ("loaded");
}
If you die, ads are shown via
public void showAds(){ print ("showing ads"); admob.ShowBanner(); }
and a gui comes up, when you click the button the level reloads and so does the entire script and start function and thus another request gets made.
void OnGUI() {
if (show) {
GUI.Box (new Rect (0, 0, Screen.width, Screen.height), "");
if (GUI.Button(new Rect(100, 150, 600, 300), "Play again")){
Application.LoadLevel("level1");
show = false;
hideAds(); }
}
Problem being that everytime the player dies this start function gets called over and over (and as i stated earlier the games slows down and crashes if this is done to rapidly), surely I should somehow be able to only request the ad once per "session" and then just hide/show the ads as i please during that session. It seems heavy to request ads so frequently.
Regards,
Emil
Take full control of your ads. Please don't request on every start. To do that you can use DontDestroyOnLoad(). It will not be destroyed and start again when your scene changes. Also check for any duplicates. Long story short-
private static bool created = false;
.....
void Start () {
admob = GetComponent<AdMobPlugin> ();
admob.CreateBanner (AD_UNIT_ID, AdMobPlugin.AdSize.SMART_BANNER, true);
admob.RequestAd ();
admob.HideBanner ();
print ("loaded");
}
void Awake(){
if(!created){
DontDestroyOnLoad(gameObject);
created = true;
} else {
Destroy(gameObject);
}
}
Use a timer function (your session), so that after a basic period of time, if the player die, you show the ads by your code. And don't request the ads if the player die earlier. Hope it helps.

Why is my background music not looping?

Dose anyone have any idae why this code is not working for my background music to constantly loop??
In load Content:
backgroundMusic.Play(0.3f, 0.0f, 0.0f); //play background music (first float number is for volume)
In update:
SoundEffectInstance instance = backgroundMusic.CreateInstance(); //creates instance for backgroundMusic
instance.IsLooped = true; //states that instance should loop meaning background music loops and never stops
Thanks in advance
Edit: I now have this:
Content Load:
Song backgroundMusic = Content.Load<Song>("backgroundMusic");
and then seperately:
public void PlayMusicRepeat(Song backgroundMusic)
{
MediaPlayer.Play(backgroundMusic);
MediaPlayer.IsRepeating = true;
}
If you need to manage the backgroud music you should use the Song class, SoundEffect should be used only for sound effects.
Something like this:
public void PlayMusicRepeat(Song song)
{
MediaPlayer.Play(song);
MediaPlayer.IsRepeating = true;
}
Of course the loading should be like this:
Song music = Game.Content.Load<Song>("background");
You are playing the SoundEffect, but looping the SoundEffectInstance, that won't work.
And following this article from Microsoft (http://msdn.microsoft.com/en-us/library/dd940203.aspx), you have to set the IsLooped property BEFORE playing the sound.
So your code should look like this:
In LoadContent:
instance = backgroundMusic.CreateInstance();
instance.IsLooped = true;
In Update:
if(instance.State == SoundState.Stopped)
instance.Play();

Categories