I want to pass my varible from the GameScene.swift to the CoinScene.swift. I know i can use struct but i don't know how to use it. Everytime i try it, it doesn't work. In the GameScene.swift i have the variable coins:
var coins = Int()
in the CoinScene.swift i use iAP and if the User buy 100 Coins it has to update.
There i use the function:
func addCoins100() {
coins + 100
}
but this wouldn't work because theres no connection between this two "coins".
Where and how should i use the struct or is there an other way to do this?
I set this code in the top of GameScene.swift:
struct coins {
static var coinVariable = "coins"
}
And then this in the CoinsScene.swift:
let coins = coins.coinVarible
This is not working. Do anyone have an Idea to fix that?
Im a beginner and not very good but hungry to learn. Thank you very much.
You can use also:
in GameScene.swift:
static var coins = Int()
in CoinsScene.swift
func addCoins100() {
GameScene.coins + 100
}
Be careful with this approach
You are setting coinVariable to the string coins, not the variable coins. Here's what I would do:
struct coins{
var coinCount = 0
}
Then when you want to set coins in CoinScene.swift use
func addCoins100() {
coins.coinCount += 100
}
Whenever you want to access the coins just use coins.coinCount
Related
Does someone know how I can fix this problem?
var Arguments [2003,1002,3932,10203,2030,1828912,12912]
var Argument = Arguments[Math.floor(Math.random() * Arguments.length)]
Because of these variables, a random argument is always chosen at the beginning. However, if you are in the program and switch from page to page, it will keep the random value it had at the beginning. I want him to be constantly creating new values.
In the draw function I call the argument like this:
text(Argument, 300,180);
If I understand your question and the comments correctly, you need re-assign Argument to be a different random value each time you switch pages, such as this line every time it switchs:
Argument = Arguments[Math.floor(Math.random() * Arguments.length)];
You don't put var there every time. Give it a value in setup(), then re-assign it when you need another value.
Unless, of course, I completely missed your problem.
In p5.js there is a helpful function called random
so you could use it like this
var Arguments [2003,1002,3932,10203,2030,1828912,12912]
var Argument = Arguments[random(0, Arguments.length - 1)]
you can read more about it here
Make argument into a function.
var Arguments [2003,1002,3932,10203,2030,1828912,12912];
var Argument = function(){
return Arguments[ Math.floor( Math.random() * Arguments.length ) ];
}
text(Argument(), 300,180);
If you make a random selection in setup() it will only happen once in your whole script. Also, Don't choose variable names that might already be used by the system (I suspect "arguments" might be.
let args = [2003,1002,3932,10203,2030,1828912,12912];
let a;
function setup() {
createCanvas(400, 400);
a = random(args);
}
function draw() {
background(220);
textSize(30);
text(a,50,70);
}
function mousePressed() {
a = random(args);
}
I'm developing a game that involves a number of Sprite Arrays and I want to detect collisions between them and specify functions depending on which etc.
So say I have an array of 16 balls ballArray[I] and 16 blocks blockaArray[I] which I can easily iterate through using the index number I.
I have given the balls a Physics Category - Balls and similar to for Blocks. Then I have 16 ID Physics categories say ID1, ID2, ID3, ID4
So I can detect a collision, know that is was a Ball hitting a Block but I then need to know which ball and which block.
What the best or easiest way to do this? I'm reading about enumerateChildNodes(withName) function but have not used it. Or can I create array of PhysicsCategories which I could iterate through along with the SpriteArray to compare and identify.
EDIT:
Thanks Everyone for the help. I have finally cracked it. Surprisingly in the end the code a lot simpler than I first thought. Still not fully understanding where the bits are sitting in my categories but have it working .
I'll try to post my final working code - you may have suggestions to improve. Many thanks again and apologies for my poor StackFlow etiquette - I am new here :-)
So my Physics Categories were defined.
struct PhysicsCategories {
static let BoxCategoryMask = UInt32(1<<7)
static let BallCategoryMask = UInt32(1<<8)
}
and then in my function to build an array of Sprites
boxBloqArray[i].physicsBody?.categoryBitMask = PhysicsCategories.BoxCategoryMask | UInt32(i)
boxBloqArray[i].physicsBody!.contactTestBitMask = PhysicsCategories.BallCategoryMask
and the same for the ball array but just the categoryBitMask
ballBloqArray[i].physicsBody?.categoryBitMask = PhysicsCategories.BallCategoryMask | UInt32(i)
I'm still not really sure why it has to be this way round but that was the final problem this evening that I had the two bodies the wrong way round in the && comparison in the final working detection code:
var body1 = SKPhysicsBody()
var body2 = SKPhysicsBody()
if contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask {
body1 = contact.bodyA
body2 = contact.bodyB
}
else {
body1 = contact.bodyB
body2 = contact.bodyA
}
// Check node collisions
for n in 0...15 {
for i in 0...15 {
if body2.categoryBitMask == PhysicsCategories.BallCategoryMask | UInt32(n) && body1.categoryBitMask == PhysicsCategories.BoxCategoryMask | UInt32(i) {
//if body1.node != nil {
print("Ball\(n) hit Box\(i)")
//}
}
}
}
and that is now printing the correct collisions.... lovely!... onwards to
the next step... thanks again
Once you have the two nodes involved in the collision as discussed in the answer by #Luca Angeletti, you can turn those into an index in various ways.
If you've made each type of node a specialized subclass and you have the appropriate indexes stored as class members, then you can convert to the appropriate class and look at the index fields, e.g.,
if let block = nodeA as? BlockNode, let ball = nodeB as? BallNode {
print("block \(block.blockIndex) hit ball \(ball.ballIndex)")
}
Nodes are hashable, so you can have dictionaries to map them back to indexes:
if let blockIndex = blockIndexes[nodeA], let ballIndex = ballIndexes[nodeB] {
print("block \(blockIndex) hit ball \(ballIndex)")
}
You can use the userData property of nodes to store whatever you like, including the indexes. The mucking around with NS things gets kind of ugly though.
https://developer.apple.com/documentation/spritekit/sknode/1483121-userdata
You can do the linear scan through each array.
if let blockIndex = blocks.firstIndex(of: nodeA), let ballIndex = balls.firstIndex(of: nodeB) {
print("block \(blockIndex) hit ball \(ballIndex)")
}
It sounds like from your question that you might have a separate category bit mask for each individual block and each individual ball. Or if you don't, that is possible if there are at most 16 of each. Anyway, if that's the case, then you can do some bit flicking to take the categoryBitMask from the physics bodies, shift the ball/block one by 16 bits (whichever is using the high bits gets shifted), and then take log2 of the bit masks to get your indexes. You can find various bit flicking techniques for log2 here:
https://graphics.stanford.edu/~seander/bithacks.html#IntegerLogObvious
Given 16 things of each type, I'd say just do #4. If you already have subclass nodes, #1 is fine. Number 2 is spreading state around a bit, so I'm not such a fan of that. Number 3 I would not really recommend because of the NS stuff. Number 5 is too cute for its own good.
Edit: Now that I read again, it sounds like maybe you've got separate ID's for categories 1...16, so your block category bit masks are like:
blockCategoryMask | ID1, blockCategoryMask | ID2, etc. That can also work (basically a variant of #5). If you're going down that route though, you may as well just stick the index directly into the category masks:
let blockCategoryMask = UInt32(1<<4)
let ballCategoryMask = UInt32(1<<5)
Then the physics body for a block gets mask blockCategoryMask | UInt32(index), and similarly for a ball. In that case the index extraction is just categoryBitMask & UInt32(0xf). Or if you put the block and ball categories in bits 0 and 1 and the indexes in bits 2-5, then right shift by 2 to get the index.
Edit in response to comment:
OK, so let's take the case of 6 distinct categories of objects, and each object can fall into one of 16 distinct subcategories. To be able to control which contacts are reported, you'd assign a bit mask to each of the 6 main categories:
enum Category: UInt32 {
// Basic categories
case block = 0b000001
case ball = 0b000010
case shot = 0b000100
case obstacle = 0b001000
case wizard = 0b010000
case food = 0b100000
}
Since you've used 6 bits for the main category, you have 26 bits remaining. To encode the 16 subcategories needs 4 bits. You can put those in the category bit mask above the main 6 bits. Example manipulations:
func encodeObject(category: Category, subcategory: Int) -> UInt32 {
return category.rawValue | (UInt32(subcategory) << 6)
}
func nodeIsA(node: SKNode, category: Category) -> Bool {
guard let body = node.physicsBody else { return false }
return (body.categoryBitMask & category.rawValue) != 0
}
func subcategory(node: SKNode) -> Int {
guard let body = node.physicsBody else { fatalError("missing physicsbody") }
return Int(body.categoryBitMask >> 6)
}
Note that the subcategories are just sort of tagging along for the ride; all your contactBitMasks would deal only to the main categories.
Essentially you're using the fact that you've got some extra bits in the physics body category bit masks to just store random information. I've done that before with simple sprites. But if the information needed is going to get any more complex that a simple number or index, I'd recommend making subclasses of nodes rather than trying to squirrel stuff away in the unused bits.
Using contact.bodyA.node and contact.bodyB.node you can get the SKNode(s) which are involved in the contact
extension GameScene: SKPhysicsContactDelegate {
func didBegin(_ contact: SKPhysicsContact) {
switch (contact.bodyA.node, contact.bodyB.node) {
case (let ball as Ball, let block as Block):
didBeginContactBetween(ball: ball, andBlock: block)
case (let block as Block, let ball as Ball):
didBeginContactBetween(ball: ball, andBlock: block)
default:
break
}
}
func didBeginContactBetween(ball: Ball, andBlock block: Block) {
// TODO: put your code here
}
}
Is there a better way to show interstitial ads than just picking a random number between 0-4 and if its 3 show the ad?
This method has its downsides because sometimes ads wont show for awhile and other times they will show 3 times in a row which is very annoying. Any help would be appreciated!
Why generate a random number at all? There is no requirement for you to implement your interstitials in this manner. How often do you want to show your ads? You can just increment an index and show your interstitial once it reaches a certain amount. For example:
// Create an Int to increment
var index = 0
// Call this func after an event
func showInterstitial() {
index++
if (index == 5) {
// Show ad
// Reset index
index = 0
}
}
I have this game where the user collects coins and I want them to be able to save them and use the coins for in app purchaces. How would I do this? Could I use NSUserDefaults for this or is it something else? Thanks! I used this for saving the highScore:
EDITED
var coinDefaults = NSUserDefaults()
var coinScore = defaults.integerForKey("coinScore")
if(coins > 0)
{
coinDefaults.setInteger(coins, forKey: "coinScore")
}
var showCoins = coinDefaults.integerForKey("coinScore")
coinLabel.text = String(showCoins)
}
Reseting the coinScore
NSUserDefaults.standardUserDefaults().removeObjectForKey("coinScore")
loading the saved score
var coinScore = NSUserDefaults.standardUserDefaults().integerForKey("coinScore")
var coins = 5
updating the coinScore
if coins > coinScore {
coinScore = coins
NSUserDefaults().setInteger(coinScore, forKey: "coinScore")
}
println( NSUserDefaults().integerForKey("coinScore").description )
coins += 20
if coins > coinScore {
coinScore = coins
NSUserDefaults().setInteger(coinScore, forKey: "coinScore")
}
println( NSUserDefaults().integerForKey("coinScore").description )
yes, you have different options to save data : nsuserdefaults, write to a file and store the file, coredata, or use a webserver with a database.
If someone knows how to hack your app, he will use what is inside your app (the 3 first methods), this is why many big games use internet (webserver) to check against what was bought by the user.
But, it is not so often that someone hack your game, if he does though, he would never pay anyway. So stay with nsuserdefaults, it is simple and good enough in my opinion.
I am trying to learn LINQ but it is quite confusing at first!
I have a collection of items that have a color property (MyColor). I have another collection of all colors (called AvailableColors - lets say 10 for example).
I want to get a random color from the AvailableColors that does not already exist in my collection.
My current C# code just gets a random color but I would like to rewrite this in LINQ to take in the current color collection and exclude those from the possible options:
public MyColor GetRandomColour()
{
return AvailableColors[new Random().Next(0, AvailableColors.Count)];
}
so it would take in the existing collection:
public MyColor GetRandomColour(ListOfSomethingWithColorProperty)
Thanks for any pointers!
Excluding already-used colors implies saving of state. You might be better off writing an iterator and using yield return to return the next random color in the sequence. This allows you to "remember" which colors have already been used.
Once you have that, you can call it using Take(1) from Linq, if you wish.
// assumes Random object is available, preferrably a re-used instance
Color color = AvailableColors
.Except(myItems.Select(item => item.Color).Distinct())
.OrderBy(c => random.Next())
.FirstOrDefault();
Probably not terribly efficient, but also probably not a concern given a small number of items.
Another approach is to randomly order the available colors once beforehand, therefore you can go in order. Use a List<Color> so you can remove elements as you use them, or save the current index with each pull. Once the list is depleted or the index exceeds the length of the array, notify your user that you're all out of colors.
var rnd = new Random(); // don't keep recreating a Random object.
public MyColor GetRandomColour(List<Something> coll)
{
var len = rnd.Next(0, AvailableColors.Count- coll.Count);
return AvailableColors.Except(coll.Select(s=>s.MyColor)).Skip(len).First();
}
I'm going to suggest that you be Linq-minded and create a good, general purpose IEnumerable<T> extension method that does the heavy lifting you require and then your GetRandomColor functions are simpler and you can use the extension method for other similar tasks.
So, first, define this extension method:
public static IEnumerable<T> SelectRandom<T>(this IEnumerable<T> #this, int take)
{
if (#this == null)
{
return null;
}
var count = #this.Count();
if (count == 0)
{
return Enumerable.Empty<T>();
}
var rnd = new Random();
return from _ in Enumerable.Range(0, take)
let index = rnd.Next(0, count)
select #this.ElementAt(index);
}
This function allows you to select zero or more randomly chosen elements from any IEnumerable<T>.
Now your GetRandomColor functions are as follows:
public static MyColor GetRandomColour()
{
return AvailableColors.SelectRandom(1).First();
}
public static MyColor GetRandomColour(IEnumerable<MyColor> except)
{
return AvailableColors.Except(except).SelectRandom(1).First();
}
The second function accepts an IEnumerable<MyColor> to exclude from your available colors so to call this function you need to select the MyColor property from your collection of items. Since you did not specify the type of this collection I felt it was better to use IEnumerable<MyColor> rather than to make up a type or to define an unnecessary interface.
So, the calling code looks like this now:
var myRandomColor = GetRandomColour(collectionOfItems.Select(o => o.MyColor));
Alternatively, you could just directly rely on Linq and the newly created extension method and do this:
var myRandomColor =
AvailableColors
.Except(collectionOfItems.Select(o => o.MyColor))
.SelectRandom(1)
.First();
This alternative is more readable and understandable and will aid maintainability of your code. Enjoy.
There's a nifty way to select a random element from a sequence. Here it's implemented as an extention method:
public static T Random<T>(this IEnumerable<T> enumerable)
{
var rng = new Random(Guid.NewGuid().GetHashCode());
int totalCount = 0;
T selected = default(T);
foreach (var data in enumerable)
{
int r = rng.Next(totalCount + 1);
if (r >= totalCount)
selected = data;
totalCount++;
}
return selected;
}
This method uses the fact that probability to choose n-th element over m-th when iterating is 1/n.
With this method, you can select your colour in one line:
var color = AvailableColors.Except(UsedColors).Random();