How to programmatically assign a random sprite to game object? - unity3d

I have a function that generates a game object on screen every 100 frames:
var trash : Transform ;
function Update()
{
if(count == 1)
{
Instantiate(trash,new Vector3(UnityEngine.Random.Range(-3f,3f),UnityEngine.Random.Range(-3f,3f),UnityEngine.Random.Range(-3f,3f)), Quaternion.identity);
}
else if(count == 100)
{
count = 0;
}
}
Now, I want each of those generated objects to pick a random sprite from my assets. I thought about making a sprite array and picking from that, but I'm not sure how to go about doing so or how to assign the sprite to the object.
Anu help would be much appreciated!

I know it's late, but I just did it for myself, so I'm sharing.
Basically - put your assets in a folder and choose randomly from them to assign to the object you're duplicating.
Create a Resources folder under Assets.
Create another sub-folder for your relevant sprite assets, under Resources, lets call it CookiesImages.
Create your prefab object, and locate it under Assets/Prefabs/Resources (this is the object that you want to duplicate multiple times with different assets).
Create a script for this prefab object.
Create a static Object array (will hold the sprites).
In your Awake() method, init this Object array by loading all the resources from your assets folder:
if (objectsArray == null)
{
objectsArray= Resources.LoadAll("CookiesImages", typeof(Sprite));
}
In the Start() method, get a random index 0 --> objectsArray.Length and call Instantiate to create a sprite to assign to your prefab object.
this.GetComponent<SpriteRenderer>().sprite = Instantiate(objectsArray[index]) as Sprite;
At the beginning, I tried assigning them to an array variable from the unity UI, but I realized that in the way I described it's much more flexible.

Well, you can generate an array of sprites of the length of your choosing with:
Sprite[] _sprites = new Sprite[quantity desired]
Then using the resources folder and the Resources.Load method (found here: http://docs.unity3d.com/ScriptReference/Resources.Load.html), you could load all your sprites into the array one after the other. Then using your random number generator, you can access sprites at random from it.
Still probably not the best way of doing it, but I would imagine it is considerably better and easier to maintain than the prefab method, but different situations call for different approaches.

Related

Using one scene for infinite levels

I am trying to make a game where there is a single scene, which will be used for an infinite number of levels until the player loses. All of my code is currently in a GameController script, and I have it so that when the level is completed, the player will press a key and integer for the level will be incremented, and the same scene will be loaded.
void Start()
{
gamePlaying = false;
currLevel = 0;
BeginGame();
}
void Update()
{
if (Input.GetKeyUp(KeyCode.Return))
{
currLevel++;
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
}
}
I have this script and a DontDestroyOnLoad script attached to the GameController gameObject.
This currLevel variable is staying at 0 when printing to the console; however, it is updating in the inspector. What am I doing incorrectly, and is this a good way of setting up this project? Thank you!
There are some ways to implement this but I would recommend to not reload the scene but have a list or container with the objects you want to destroy and when loading the next scene you destroy these and create new. You can easly make a loading screen in this time and even better pre buffer the new scene when you notice the old one is comming to an end.
So instead of reloading the scene, destroy unnecessary objects and create the onse you need. Depending on your needs you may even reuse some as the floor for example and just change the color for your level. As said that all depents on your usecase.

pygame-create multiple different instances of sprites [duplicate]

I'm having trouble with getting new sprites to be added. I'm looking for something along the lines of:
def duplicate(sprites):
for d in sprites:
if d.energy >= d.max_energy * 0.9:
d.energy = d.energy / 2
new_d = d.duplicate()
so if 1 sprite had its 'energy' above 90% of its 'max_energy', its energy would be cut in half and now there would be a second sprite that was identical to the first. I'm not sure how to pull that off though.
In general, you need to implement the duplicate method and construct a new instance of the Sprite object in the method.
Another solution is to use the Python copy module. deepcopy can create a deep copy of an object. Unfortunately this cannot be used for pygame.sprite.Sprite objects, as theimage attribute is a pygame.Surface, which cannot be copied deeply. Therefore, a deepcopy of a Sprite will cause an error.
Unless you have nor any other attribute that needs to be copied deeply, you can make a shallow copy of the Sprite. The rect attribute is a pygame.Rect object. The copy of the Sprite needs its own rectangle, so you have to generate a new rectangle instance. Fortunately a pygame.Rect object can be copied by pygame.Rect.copy:
import copy
new_d = copy.copy(d)
new_d.rect = d.rect.copy()

Creating a class to run a single action on multiple sprites

I'm trying to rotate numerous sprites (about 48 different ones) around an arbitrary point (using this article: http://indiedevstories.com/2012/08/14/custom-cocos2d-action-rotating-sprite-around-arbitrary-point/ ) and I managed to create the custom category for it, but it only works on a single sprite. I've looked around on the site and tried to use runAction:[action copy] but it makes the copies rotating points crazy numbers for some reason. Then I tried to create a method for the actions and just call the method, but I keep getting errors for that as well. I've tried so many different solutions but no luck.
So my question is, is there a way I can create another class that holds all of my sprites, and then run a single method to run an action on all of the sprites of the class?
Assuming you have an array called spriteArray containing all sprites you wish to rotate, it's as simple as:
for(CCSprite *sprite in spriteArray)
{
CCRotateAroundBy *rotateAround = [CCRotateAroundBy actionWithDuration:1.0 angle:90 rotationPoint:screenCenter];
[sprite runAction:rotateAround];
}

unity moving to another scene with current scene being paused

I'm making a turn-based battle game in Unity3D and I have 2 scenes (a town scene and a battle scene). Whenever the character meets a monster, the game jumps to the battle scene where the character does battle and go back to the town scene after defeating or losing.
The problem is how to return to the town scene with the same state as when the character enters the battle scene (character position, statuses, etc.)
if I use
Application.LoadLevel('battlescene');
then
Application.loadLevel('townScene');
then the townscene will start from the first time. How to make the townscene continue from where we left off?
There are two ways that I think you can accomplish this. It all depends on your target platform and how important resources are but here we go:
1) If resources aren't an issue
You could put all your normal scene and battle scene objects in one scene.
Create two empty game objects (One for Town Scene objects and the other for Battle Scene Objects). You can then either have two versions
of your game character(s) or one. Then write a script that simply
switches the camera(s) from the town scene to the battle scene when
a battle is triggered and back to the town scene when the battle is
over.
If you have one version of each character you could simply add a script that changes the behaviour of your game character controller
to/from battle mode and normal/town mode.
If you have two versions of each character then you would simply need to write the appropriate character controller scripts and
activate/deactivate the game characters according to which one you are
using. This is how games like Final Fantasy 7,8,9 achieved the same
effect. There were two versions of the game characters: one for battle mode and the other for normal mode.
2) If resources ARE an issue
(and I think a more efficient way)
You could use the Application.LoadLevelAdditive function. This function allows you to load a different scene and rather than destroy everything in the current scene, it takes the new scene and all it's objects and adds them to the current scene.
So basically you can use it something like this:
Create a separate battlescene and within your scene, create an empty game object to hold every object in your scene.
In your noraml scene do the same.
When you need to go to battle mode use:
Application.LoadLevelAdditive ('battlescene');
And when/if you want to unload your battlescene after that you can do so by simply writing code to destroy the battlescene game object
since it contains everything from your battle scene.
As with the first method you can decide whether you want to have two different versions of your characters or not. One of the pros of having two versions is that if you want to save time by not going into detail with you game models (especially if your game is really big) you can have save processing power by using scaled down models for the town scene and using polished more detailed models for the battle scene, assuming your battle scene is a small stage representing the place where your characters are fighting. Think final fantasy VII. Just something to consider.
I hope that helps. I've written it all in a rush but lemme know if anything needs clearing up.
You can do it by script in c#
void onYourFunction()
{
Time.timeScale = 0; //pauses the current scene
Application.LoadLevelAdditive("YourNextScene"); //loads your desired other scene
}
And when you want to activate your game back you can use Time.timeScale = 1;
I know this is an old post, but there is one more method that can be used. This would be to save the state of the scene. This comes in handy when you don't expect users to have the resources for loading 2 scenes with the Application.LoadLevelAdditive. That method potentially can use twice the resources.
When you save the state (save all information that can change to a file or DB) you can then load the level at a later time and not have it sitting in memory. You could also use this to save your game.
I know it is on old post. But I have found another, very easy solution for my case. Just deactivating all GameObjects from one scene while the other is active and then reactivate it, as soon I go back to the root scene:
[Button]
public void UnPauseScene()
{
EndlessSceneCamera.gameObject.SetActive(true);
Time.timeScale = 1;
levelStatus = LevelStatus.Running;
foreach (var go in activeGameObjectsBeforeScenePaused)
{
go.SetActive(true);
}
}
[Button]
public void PauseScene()
{
//EndlessSceneCamera.gameObject.SetActive(false);
levelStatus = LevelStatus.Pause;
Time.timeScale = 0;
var allGameObjects = FindObjectsOfType<GameObject>().ToList();
activeGameObjectsBeforeScenePaused = allGameObjects.Where(x => isActiveAndEnabled).ToList();
foreach (var go in activeGameObjectsBeforeScenePaused)
{
go.SetActive(false);
}
}

Creating pointer Attributes in cocos2d iPhone

I am working on a game. There are balls that fall from the top of the screen, and the player has to catch them, as the are caught they stack ontop of one another. I have a method that creates each new ball and adds it to an Array that i use to move the sprites. Problem is that the after they collide I need them to stop moving, since the array is called on to move them they all move. And if i try to make them stop they all stop. So I was hoping to create a pointer attribute if ther is such a think, for example "sprite.position" I need a new attribute that i can check like a boolean. I was hoping to create a attribute like sprite.hasCollided and if it returns YES then the ball should no longer move. Is this possible or is there a better way to do it?
Thanks
Tanner
I would suggest you create a ball object. And add the boolean as as part of the object.
CCNodes (and, by inheritence, CCSprites) have a userData property, which is a void*. You can use this to relate a custom object to a cocos2d object. Keep in mind if you use the userData option, you will, in most cases, need to allocate any memory when you create/assign the sprite, and release it when you are done.
int* myInt = (int*)malloc(sizeof(int));
*myInt = 0;
sprite.userData = myInt;
//some time later, when you are done with the sprite
free(sprite.userData);
As an improvement on the userData property, you can do what xuanweng suggests and create a ball object containing various game-related properties for the balls, and assign an instance of this to each of your ball CCSprites using the method above.