Score Multiplier in Swift - swift

I have an application that adds one to the score whenever you tap anywhere on the view. I would like to have a score multiplier that states that whenever the user is tapping faster his or her score will not just increment by one, but by a larger amount depending on how fast and/or how long they have been tapping. I've done a good bit of Googling but I have yet to find anything. Thanks in advance

Without further examples its hard to actually give you help, here is a stab
static let multiplier = 1000
struct Player {
var score: Int
var displayScore: Int {
return score * multiplier
}
}
var player = Player(score: 1)
print(player.displayScore) // 1000
player.score += 1
print(player.displayScore) // 2000

Related

SwiftUI XCTest - How to increase velocity of scrolling?

I wrote a method that allows me to scroll list of elements on the screen for UI testing:
func scrollToElement(element: XCUIElement, maxScrolls: Int = 10) {
var numberOfScrolls = 0
while !element.isHittable, numberOfScrolls < maxScrolls {
app.swipeUp()
numberOfScrolls += 1
}
}
Everything works fine but it takes too much time for the UI test to verify ie. wait until every scrolled view will be checked whether the element is available.
Is there any possible method or way to increase the velocity of scrolling?
Thanks in advance!

GKLeaderboard's localPlayerScore delay after saving a GKScore

I'm trying to get a user's new leaderboard rank after scoring a high score and I found it takes about 5 seconds for the GKLeaderboard scores to update. I've tested the code against a Release build (from Xcode) and the delay is still there.
let score = GKScore(leaderboardIdentifier: leaderboardId)
score.value = Int64(highScore)
GKScore.report([score]) { _ in
// Adding a 5 second delay here solves the problem.
let leaderboard = GKLeaderboard()
leaderboard.identifier = leaderboardId
leaderboard.loadScores { _, _ in
// leaderboard.localPlayerScore shows data from before saving the new score.
}
}
Is there a way around this? The 5-second delay seems flaky. Maybe once the app is in the App Store this delay is no longer there?
I could probably create a workaround by storing the scores before the user plays the game and locally calculate the new rank but the shared code should avoid the need for that, right?

Occasional stuttering with SceneKit when touching the screen

When I interact with the screen the objects in my game start to stutter. My FPS is at 60 and doesn't drop but the stuttering is still prevalent. I believe my problem is how I'm animating the objects on screen(code below).If anybody could help I would appreciate it.
I have an x amount of nodes inside an array called _activePool. In the Update function I am moving the nodes x position inside _activePool, adding new nodes when the last node in _activePool position is <= 25 and removing the first node in _activePool if it's position is <= -25.
if _cycleIsActive{
for obj in _activePool{
//move the obj in _activePool
obj.position.x += Float(dt * self.speedConstant);
}
let lastObj = _activePool.last;
if (lastObj?.position.x)! + getWidthOfNode(node: lastObj!) + Float(random(min: 15, max: 20)) <= 25{
// get new obj(pattern) and add to _activePool
self.getPatternData(sequencePassedIn: selectedSeq, level: self._currentLevel, randomPattern: randomPattern());
}
let firstObj = _activePool.first;
if (firstObj?.position.x)! + getWidthOfNode(node: firstObj!) <= -25{
// remove object and return to specific pool
firstObj?.removeFromParentNode();
returnItems(item: firstObj!);
_activePool.removeFirst();
}
}
I create several arrays and add them to a dictionary
func activatePools(){
temp1Pool = ObjectPool(tag: 1, data: []);
dictPool[(temp1Pool?.tag)!] = temp1Pool;
temp2Pool = ObjectPool(tag: 2, data: []);
dictPool[(temp2Pool?.tag)!] = temp2Pool;
for i in 0... dictPool.count {
obstacleCreationFactory(factorySwitch: i);
}
}
Creating my obstacles(enemies)
func obstacleCreationFactory(factorySwitch: Int){
Enemies = Enemy();
switch factorySwitch {
case 0:
for _ in 0...100{
let blueEnemy = Enemies?.makeCopy() as! Enemy
blueEnemy.geometry = (Enemies?.geometry?.copy() as! SCNGeometry);
blueEnemy.geometry?.firstMaterial?.diffuse.contents = UIColor.blue;
blueEnemy.tag = 1;
temp1Pool?.addItemToPool(item: blueEnemy);
}
case 1:
for _ in 0...100{
let redEnemy = Enemies?.makeCopy() as! Enemy
redEnemy.geometry = (Enemies?.geometry?.copy() as! SCNGeometry);
redEnemy.geometry?.firstMaterial?.diffuse.contents = UIColor.red;
redEnemy.tag = 2;
temp2Pool?.addItemToPool(item: redEnemy);
}
default:
print("factory error");
}
}
Without being able to look at the rest of your code base it’s really difficult to guess what would be causing your issue.
If somewhere you are creating a ton of temporary objects in a loop somewhere, you might consider creating a local autorelease pool to prevent memory spikes. Here is a good article that describes why in some situations it’s a good idea.
You could also be calling some particularly expensive functions on a timer or something. It’s difficult to say.
In short, you should consider using Xcode’s Profiling tools (called Instruments). Specifically I would recommend using Time Profiler to examine what functions are taking the most time and causing those spikes.
Here is a great WWDC session video that shows how you can use the time profiler, I’d recommend regularly profiling your app, especially when you have an issue like this.

Only scroll in one direction

I have a infinite vertical scrolling bar in unity and I want to suddenly limit the scrolling (in one direction only) when reaching a (variable) threshold.
public GameObject MyScrollRectContent;
public float limit = 300;
void Update () {
if(MyScrollRectContent.transform.localPosition.y >= limit){
//make it ONLY possible to scroll backwards or not beyond the limit and stop elasticity
}
Any ideas how to limit the infinite scrolling?
The simplest thing would be to use the existing ScrollRect. It allows scroll in a defined rectangle. You would have to simulate infinity by setting a really big size in one direction, or find a way to seamlessly reset the position if the user goes too far (difficult to do without seeing the jump but might be possible depending on your content).
If this is not an acceptable solution:
To limit the scrolling, you can just set the position to the limit if the user goes too high:
void Update ()
{
if(MyScrollRectContent.transform.localPosition.y >= limit)
{
var currentPos = MyScrollRectContent.transform.localPosition;
MyScrollRectContent.transform.localPosition = new Vector3(currentPos.x, limit, currentPos.z);
}
}
Now if on top of that you want elasticity, it is a bit more tricky: Somewhere, your script must currently set MyScrollRectContent.transform.localPosition. Instead of doing that, set a targetYPosition. You can imagine this as a point that moves, on which the scrollrect is linked by an elastic. This targetYPosition is contrained by your limit. Then in your update you make the ScrollRectContent follow.
public void OnUserInput(float y) // I don't know how you actually do this. this is an example
{
_targetYposition = y;
if(_targetYposition > limit)
{
_targetYPosition = limit;
}
}
private void Update()
{
var currentPos = MyScrollRectContent.transform.localPosition;
var y =
Vector3.Lerp(currentPos.y,
_targetYPosition, Time.deltaTime*_speed);
MyScrollRectContent.transform.localPosition = new Vector3(currentPos.x, y, currentPos.z);
}
Note that this is a simple example aiming at hinting you in the right direction. You'll have to adapt it to your code. The elasticity will likely not look as you want either, so you might want to modify the Update function to create other effects

High Scores logic in Unity using PlayerPrefsX

I've created a fairly basic 2d scrolling game in Unity, and one of the game modes is survival. When you die, this screen will load and allow you to input your high score, which will be saved into a high scores table once the button is pressed.
However, while I can replace the score it is higher than, I cannot for the life of me think of the logic that would instead put the score that was replaced into the position below it, then that score would drop by one, then the next score etc.
The stage I'm at is below, with the code that simply replaces all of the high scores lower than the current store deleted, because it isn't what needs to be done. I currently have five generic scores saved to the playerprefsX int array so i know all of the below code is working, its just the dropping all the scores down one and deleting the final score that is proving problematic for me
public class high_score_input : Game_Over {
private string name = "highscores";
private int score;
public int[] highscores = new int[5];
// Use this for initialization
void Start () {
GameObject levelcontroller = GameObject.Find ("levelcontroller");
survival_mode survival = levelcontroller.GetComponent<survival_mode> ();
score = survival.setScore();
highscores = PlayerPrefsX.GetIntArray(name);}
void OnGUI()
{
base.OnGUI ();
if (GUI.Button (new Rect (Screen.width/10, 250, 120, 30), "Save High Score"))
{
for(int i = 0;i<highscores.Length;i++)
{
if(score>highscores[i])
{
}
}
PlayerPrefsX.SetIntArray(name, highscores);
}
}
Given that it's a small array and this isn't performance-critical code, I'd go for something that's simple and avoids errors:
Make sure that your score array is sorted.
Does the new score beat the score in the last slot? If so, replace it.
Make sure that your score array is sorted.
Given helper functions such as Array.Sort, this should be pretty quick.