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
}
}
Related
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
}
}
I am writing an UI test case, in which I need to perform an action, and then on the current page, scroll the only UITableView to the bottom to check if specific text shows up inside the last cell in the UITableView.
Right now the only way I can think of is to scroll it using app.tables.cells.element(boundBy: 0).swipeUp(), but if there are too many cells, it doesn't scroll all the way to the bottom. And the number of cells in the UITableView is not always the same, I cannot swipe up more than once because there might be only one cell in the table.
One way you could go about this is by getting the last cell from the tableView. Then, run a while loop that scrolls and checks to see if the cell isHittable between each scroll. Once it's determined that isHittable == true, the element can then be asserted against.
https://developer.apple.com/documentation/xctest/xcuielement/1500561-ishittable
It would look something like this (Swift answer):
In your XCTestCase file, write a query to identify the table. Then, a subsequent query to identify the last cell.
let tableView = app.descendants(matching: .table).firstMatch
guard let lastCell = tableView.cells.allElementsBoundByIndex.last else { return }
Use a while loop to determine whether or not the cell isHittable/is on screen. Note: isHittable relies on the cell's userInteractionEnabled property being set to true
//Add in a count, so that the loop can escape if it's scrolled too many times
let MAX_SCROLLS = 10
var count = 0
while lastCell.isHittable == false && count < MAX_SCROLLS {
apps.swipeUp()
count += 1
}
Check the cell's text using the label property, and compare it against the expected text.
//If there is only one label within the cell
let textInLastCell = lastCell.descendants(matching: .staticText).firstMatch
XCTAssertTrue(textInLastCell.label == "Expected Text" && textInLastCell.isHittable)
Blaines answer lead me to dig a little bit more into this topic and I found a different solution that worked for me:
func testTheTest() {
let app = XCUIApplication()
app.launch()
// Opens a menu in my app which contains the table view
app.buttons["openMenu"].tap()
// Get a handle for the tableView
let listpagetableviewTable = app.tables["myTableView"]
// Get a handle for the not yet existing cell by its content text
let cell = listpagetableviewTable.staticTexts["This text is from the cell"]
// Swipe down until it is visible
while !cell.exists {
app.swipeUp()
}
// Interact with it when visible
cell.tap()
}
One thing I had to do for this in order to work is set isAccessibilityElement to true and also assign accessibilityLabel as a String to the table view so it can be queried by it within the test code.
This might not be best practice but for what I could see in my test it works very well. I don't know how it would work when the cell has no text, one might be able to reference the cell(which is not really directly referenced here) by an image view or something else. It's obviously missing the counter from Blaines answer but I left it out for simplicity reasons.
Is there a way in Xcode 7 UI Testing to select the 3rd row in a UIPickerView?
I have tried various things like this to identify the rows in each picker but all the requests below return 0 found:
XCUIApplication().pickers.element.cells.count
XCUIApplication().pickers.element.staticTexts.count
Any ideas?
Updated: I am aware of adjustToPickerWheelValue method where you can select a particular value you already know, but I am trying to select the 3rd value (index = 4) when I don't know the values that exist in the picker.
You can use -adjustToPickerWheelValue: to select items on a UIPickerView.
When there is one UIPickerView on the screen you can select the element directly, like so.
let app = XCUIApplication()
app.launch()
app.pickerWheels.element.adjustToPickerWheelValue("Books")
If the picker has multiple wheels you will need to first select the wheel via it's accessibility identifier, then adjust it.
app.pickerWheels["Feet"].adjustToPickerWheelValue("5")
Here's a GitHub repo with a working example. And some more information in a blog post I wrote.
Workaround:
let pickerWheel = XCUIApplication().pickers.pickerWheels.element
let appWindowHeight = XCUIApplication().windows.elementBoundByIndex(0).frame.height
let pickerWheelCellHeight = GFloat(44)
func advancePickerWheelOneValue() -> Self {
let topScrollPoint = Double(pickerWheel.frame.midY/appWindowHeight)
let bottomScrollPoint = Double((pickerWheel.frame.midY + pickerWheelCellHeight)/appWindowHeight)
let topScreenPoint = XCUIApplication().windows.elementBoundByIndex(0).coordinateWithNormalizedOffset(CGVector(dx: 0.5, dy: topScrollPoint))
let bottomScreenPoint = XCUIApplication().windows.elementBoundByIndex(0).coordinateWithNormalizedOffset(CGVector(dx: 0.5, dy: bottomScrollPoint))
bottomScreenPoint.pressForDuration(0, thenDragToCoordinate: topScreenPoint)
return self
}
You may need to adjust the dx value depending on where the picker is.
.coordinateWithNormalizedOffset(CGVector(dx: 0.5,
But 0.5 works if the picker occupies the width of the screen.
With this method you an move the picker on value at a time. Call it multiple times and you get to the value you want.
Its not ideal but it can help if you want to check certain indexes. Hopefully you would have to use it on a picker with hundreds of values ;)
Example with Date picker (UIDatePicker)
XCUIApplication().datePickers.pickerWheels.elementBoundByIndex(0).adjustToPickerWheelValue("March")
XCUIApplication().datePickers.pickerWheels.elementBoundByIndex(1).adjustToPickerWheelValue("24")
XCUIApplication().datePickers.pickerWheels.elementBoundByIndex(2).adjustToPickerWheelValue("2000")
And here is example with Picker view (UIPickerView)
XCUIApplication().pickerWheels.element.adjustToPickerWheelValue("Male")
How do i limit Admob interstitial ads to show only once after my game session has ended three times? I am try to limit amount of the ads annoying players. I am using Xcode, thanks.
Just set a counter that keeps track of the number of time a game is played, then on every 3 times, present it and reset counter
pseudo code
init:
adMobCounter = 3;
gameEnd:
adMobCounter--;
if(adMobCounter == 0)
{
adMobInterstitialPresent();
adMobCounter = 3;
}
What I am trying to do is to have individual star counts per level based on player performance. (1-2-3 star awards.) This will be based on what region the player reaches. I know how to award the stars but keeping track of it all is throwing me problems. First lets say a player plays level 2 and receives 1 star for their performance. Then at a later time, s/he returns to the level and gets a 2 star. I would like the star count for that specific scene to update to two stars, while only adding 1 star ( The one extra s/he got this time) to the totalStarCount.
My initial plan was to have variables:
OldStarCount
NewStarCount
TotalStarCount
Then when a player reaches say region1, and is awarded one star, then NewStarCount would be set to one, then
TotalStarCount = TotalStarCount + (NewStarCount - OldStarCount);
Then update OldStarCount = NewStarCount;
Set NewStarCount = 0;
Move On to next Scene;
Am I approaching this the correct way? Any help would be greatly appreciated.
You could have something like this
int result = 0;
int totalStars = 0;
int[] starCounts = new int[NumberOfRegions};
...
currentRegion = 42;
result = play(currentRegion);
if(result > starCounts[currentRegion]){
totalStars += result - starCounts[currentRegion];
starCounts[currentRegion] = result;
}
This is just an example of what you could do. There are obvious scalability issues with this (what happens when you want to add new regions, etc), but you get the gist.