Performance issue with "Dive Into SpriteKit" example code - timer

I made a basic SpriteKit game with my son using step-by-step tutorial from Dive Into SpriteKit book by Paul Hudson.
The game is just one SKScene that draws a ship, a bunch of space junk, and provides basic control. When the game is over, we follow instructions from the book and do:
DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
if let scene = GameScene(fileNamed: "GameScene") {
scene.scaleMode = .aspectFill
self.view?.presentScene(scene)
}
}
Unfortunately with each new game scene FPS goes down and after ~20 game overs on my iPad the game is unplayable. I guess something is not properly de-initialized, but I am not sure where to look and how to fix this.
I checked "canonical" implementation form the book and they all have exactly the same issue on iOS 12.
Our complete implementation on GitHub.
I will appreciate advice on how to manage scenes lifecycle to keep performance.

Thank you #0x141E for the solution and the advices!
The issue was with the timer (which is in use to add nodes to the scene). A timer runs in Run Loop and have to be invalidated with:
timer!.invalidate()
Adding the invalidation in GameOver for both timers solved the major performance degradation issue as well as the memory leak.
Following the advice, we learned a bit more about SKAction, and another way of creating space junk on schedule seems to be:
run(SKAction.repeatForever(SKAction.sequence([
SKAction.run(createEnemy),
SKAction.wait(forDuration: 0.45)
])))
In this case we still need to make sure we do stop all the actions in the GameOver.
removeAllActions()

Related

How does one go about creating and accessing a small server with Unity?

I was initially going to write what looked like a four paragraph essay to explain what I'm working on, but it wasn't nessecary. In summary, I'm a rookie at Unity and know very little about how to create a platform in which I can store(send and retrieve from other clients) data in "the cloud". Yet, I need to be able to do so for my project.
using System.Collections.Generic;
using UnityEngine;
public class MultiplayerMoveMe : MonoBehaviour
{
//Note: I am making a retro-style game where all sprites face the camera, so the rotation of the players is not a factor that needs considering here; just the position.
//I have a fleshed-out idea on how I will do all of this, however I am completely foreign in all things server-related on this scale so I need some assistance(not the most prideful circumstances).
public GameObject p2Obj;
void Start()
{
//Anything that I might need to add that the serverGet() function might require
}
void serverGet(int playerNum, string reqType)
{
//On their side, every frame, the second player's X, Y, and Z pos should be packed into a string with seperator char '|' and then filed on the server under playerdata/2/pos/
//Then, this script(on the side of player 1) would(every frame, displaced by +1 frame initially) take the player number and the reqType to find said directory online with THIS function to return the value.
//Funny thing is; I have no idea what I'm doing.
//And no, I haven't connected to a server yet. I also want to stay away from any third party apps for this since this is small-scale and I only wish to learn the ins and outs of all of this.
}
void Update()
{
String p2Position = serverGet(2,"pos");
// String p2Position's value is currently "x|y|z"
String[] sl = p2Position.Split('|');
float xPos = float.parse(sl[0]);
float yPos = float.parse(sl[1]);
float zPos = float.parse(sl[2]);
// Now that all values are floats, we can feed them into the thingamabobber to change the position of the other player from our side.
p2Obj.transform.position = new Vector3(xPos, yPos, zPos);
}
}
Below I have a script which, if the serverGet() function's contents were actually existant(and functional, of course), would set the position of the second player to their position according to the data online, which the instance from their side submits in the first place(every frame as well, -1 frame initial displacement so that everything works). This way, if I move on one computer as "player 2", the computer in which I am playing as "player 1" will show the movement of player 2 as it progresses every frame. In other words, basically all calculation is client-side, but the actual communication is(unavoidably) server-side. That server-side is what I'm clueless about, and would appreciate if anyone here could lead me a step in the right direction.
As for the script that actually submits the terms to the server, that will come with my understanding of all of this; which again, I don't have as of right now.
There seems to have been a number of questions lately: "So I'm gonna write a MP game engine from scratch!" (Example.)
To get some basic grounding in mmp engineering, first spend a few days working with Unity's system https://docs-multiplayer.unity3d.com
Do try to understand the scale of your problem. You're about to embark on a PhD level enterprise that will take months of full-time work at the minimum. It would be insanity to not, first, spend a few days with current systems to gain some basic principles.
Similarly, Photon is very popular for mmp systems, https://www.raywenderlich.com/1142814-introduction-to-multiplayer-games-with-unity-and-photon next spend a few days making toy Photon/Unity systems to learn more.
Finally Mirror networking is the one that is "like Unity's old networking" https://assetstore.unity.com/packages/tools/network/mirror-129321 so really you should try that a little too.
Finally on the face of it to literally answer your question as is, click over to AWS, spin up some ubuntu EC2 instances, and start work on a "simple" game server, so almost certainly you'd use Node/Express/SQL and likely websockets (just to get started, you'd have to move to raw udp communications eventually). It's just not realistic to start doing that though until you familiarize yourself with some basic existing systems.

how do I get an enemy to follow me in a 2D platformer Godot

So I'm making a 2D platformer called "agent 404". I'm right now making the enemy but can't seem to make it. So I looked for a tutorial but couldn't find any tutorials related to a 2D platformer enemy that follows the player I tried all but most of them but all end up wrong. I want to ask if any of you know a way or a tutorial that could help me?
If you're using a tilemap you can use a Navigation2D to do nearly "out-of-the-box" pathfinding.
GDQuest explains some of it in this tutorial:
https://www.youtube.com/watch?v=0fPOt0Jw52s
Since you're making a platformer however, you might run into the same problem where the only tiles with navigation on them are blank and so aren't filled in by the autotiler. If that's the case you can find a workaround here (something I was just stuck on myself :-) ):
navigation tilemaps without placing walkable tiles manually

Does Alpha Beta / minimax require that each node be a full copy of the gameboard?

This is not a language-specific question, but for the sake of conversation, I currently work in C# 7.
Over the years I've successfully implemented the Alpha Beta pruning algorithm (even in PASCAL, 35 years ago :)
Each time, I've created semi-deep-copies (discussed below) of the game state which is recursed for each node. I've often wondered if this is necessary and if perhaps I'm not truly understanding the algorithm.
The interweb is full of requests for help for TicTacToe, which makes me think that this must be a common school assignment question - which kinda clogs searches on this fairly basic topic.
Semi-deep-copies ... it appears to me that each node should know:
the full state of the board
the player whose turn it is
the state of play - ie: { playing, Player1 win, Player2 win, draw }
My question is: does each node need its own copy of the board? ... for example Chess has 8x8 grid ... is there something more subtle to the algorithm, or do these nodes each need their own snap-shot of the board state? Is there some cool way (other than copy and apply-possible-move) that nodes can use to derive their state from their parent?
Perhaps someone can explain or point to a "read this, dummy" post, or just confirm that I need to make these instances, as I've attempted to describe, with each recursive call having its own in-memory copy of the game board.
I realize that over the last few decades, memory has become cheap... but combinatorial-explosion is still the main topic. Cheers.
I am not sure if this answers your question. But could you instead of making a copy each turn do the move, make the recursive call, and then undo the move instead? Something like:
board.make_move(move)
eval = minimax(board, ....)
board.unmake_move(move)

Most difficult programming explanation

Recently I tried to explain some poorly designed code to my project manager. All of the manager classes are singletons ("and that's why I can't easily change this") and the code uses event dispatching everywhere that a function call would have sufficed ("and that's why it's so hard to debug"). Sadly it just came out as a fumbling mess of English.
Whats the most difficult thing you've had to convey to a non-technical person as a programmer? Did you find any analogies or ways of explaining that made it clearer?
Thread Synchronization and Dead-Locking.
Spending time on design, and spending time on refactoring.
Refactoring produces no client-visible work at all, which makes it the hardest thing in the project to justify working on.
As a second "not client-visible" problem, unit testing.
I was asked how the internet worked - I responded with "SYN, ACK, ACK". Keep forgetting it's SYN, SYN-ACK, ACK..
(source: inetdaemon.com)
My most difficult question began innocently enough: my girlfriend asked how text is rendered in Firefox. I answered simply with something along the lines of "rendering engine, Gecko, HTML parser, blah blah blah."
Then it went downhill. "Well how does Gecko know what to display then?"
It spiraled from there quite literally down to the graphics drivers, operating system, compilers, hardware archiectures, and the raw 1s and 0s. I not only realized there were significant gaps in my own knowledge of the layering hierarchy, but also how, in the end, I had left her (and me!) more confused than when I began.
I should've initially answered "turtles all the way down" and stuck with that. :P
I had a fun case of trying to explain why a program wasn't behaving as expected when some records in a database had empty strings and some were NULL. I think their head just about exploded when I told them empty string is just a string with 0 bytes in it while NULL means unknown value and so you can't actually compare it to anything.
Afterward I had one nasty headache.
1.) SQL: Thinking in sets, rather than procedurally (it's hard enough for us programmers to grasp!).
2.) ...and here's a great example of demystifing technical concepts:
How I explained REST to my wife
A lot of statements starting with "It's because in Oracle, ..." come to my mind.
The biggest hurdles are around "technological debt", especially about how the architecture was correct for this version but needs to be changed for next version. This is similar to the problem of explaining "prototype versus production" and "version 1.0 versus version 2.0".
Worst mistake I ever made was doing a UI mockup in NeXT steps UI Builder. It looked exactly like the end product would look and had some behaviour. Trying to explain that there was 6 months of work remaining after that was very difficult.
How recursion works...
Why code like this is bad:
private void button1_Click(object sender, EventArgs e)
{
System.Threading.ThreadStart start =
new System.Threading.ThreadStart(SomeFunction);
System.Threading.Thread thread = new System.Threading.Thread(start);
_SomeFunctionFinished = false;
thread.Start();
while (!_SomeFunctionFinished)
{
System.Threading.Thread.Sleep(1000);
}
// do something else that can only be done after SomeFunction() is finished
}
private bool _SomeFunctionFinished;
private void SomeFunction()
{
// do some elaborate $##%#
_SomeFunctionFinished = true;
}
Update: what this code should be:
private void button1_Click(object sender, EventArgs e)
{
SomeFunction();
// do something else that can only be done after SomeFunction() is finished
}
private void SomeFunction()
{
// do some elaborate $##%#
}
The importance of unit tests.
"Adding a new programmer a month to this late task will make it ship later. Never mind, read this book." (The Mythical Man-Month.) Managers still don't quite get it.
The concept of recursion - some people get it really hard.
I sometimes really have hard time explaining the concept of covariance/contravariance and the problems related to them to fellow programmers.
Convincing a friend that the Facebook application I developed really doesn't store her personal data (e.g. name) even though still displays it.
Why it'll take another four weeks to put this app into production. After all, it only took a week to do the rapid prototype. It "works" (or at least looks like it does) so I should be pretty much finished, shouldn't I?
Explanations that involve security, code quality (maintainability), normalized DB schemas, testing, etc. usually come off as a list of abstractions that don't have any visible effect on the app, so it's hard to explain what they really contribute to the project and why they're necessary. Sometimes analogies can only take you so far.
C pointers
*i
&i
Avoiding Dead-Locking in a multi-threaded environment.
I cleared confusion by explaining it visually on a white-board, drawing out two parallel lines and showing what happens when the reach the same points at the same time.
Also role-playing two threads with the person I was explaining it to, and using physical objects (book, coffee mug, etc) to show what happens when we both try to use something at once.
There's really no right or wrong answer-proper for this... it's all experiences.
The hardest thing I have had to explain to a non-tech person was why he couldn't get to his website when traveling abroad but his family member that lived there (with a totally different provider) could get to it. Somehow, "Fail in Finland" wasn't good enough.
The most difficult concepts to explain to people I would label programmers as opposed to developers are some of the most core paradigms of object orientated design. Most specifically abstraction, encapsulation and the king, polymorphism and how to use them correctly.
Expanding on that is the level of complexity of explaining what Inversion of Control is and why it is an absolute need and not just extra layers of code that doesn't do anything.
I was going to comment on Mikael's post, that some people just take the sequential programming and unfortunately just stay with that.
But that really means: two seriously hard to explain concepts:
monads in haskell (usually starting with: "That's like a function that returns a function that does what you really wanted to do, but ...")
deferreds in twisted/python ("That's like... ehhh... Just use it for a year or so and you'll get it" ;) )
Trying to explain why code was executed sequentially at all. Seemingly this is not at all intuitive for some non-programmers (i.e. my girlfriend).
Why you do not need character correct index handling in most cases when you use UTF-8 strings.
It's hard to explain why most software has bugs. Many non-technical people have no idea how complex software is, and how easy it is to overlook unexpected conditions. They think we are just too lazy to fix stuff that we know is broken.
There are 10 different types of people in the world.
The people who understand Binary and the people who dont....
To put it plainly, why development is the most difficult concept ever exposed to man kind. Not related to any programming language, but in general. And no I am not trying to provide myself or you with an ego boost, the only real limitations to this field is your mind.
Why? We don't work with constants and there are no boundaries, the only reason an AI that thinks like a human being doesn't exist yet is due to our own limitations. All other aspects need to adhere to some sort of law, development doesn't care about the laws of physics or any law for that matter hence the term development... evolution.

silverlight math performance question

Is there some reason that identical math operations would take significantly longer in one Silverlight app than in another?
For example, I have some code that takes a list of points and transforms them (scales and translates them) and populates another list of points. It's important that I keep the original points intact, hence the second list.
Here's the relevant code (scale is a double and origin is a point):
public Point transformPoint(Point point) {
// scale, then translate the x
point.X = (point.X - origin.X) * scale;
// scale, then translate the y
point.Y = (point.Y - origin.Y) * scale;
// return the point
return point;
}
Here's how I'm doing the loop and timing, in case it's important:
DateTime startTime = DateTime.Now;
foreach (Point point in rawPoints) transformedPoints.Add(transformPoint(point));
Debug.Print("ASPX milliseconds: {0}", (DateTime.Now - startTime).Milliseconds);
On a run of 14356 points (don't ask, it's modeled off a real world number in the desktop app), the breakdown is as follows:
Silverlight app #1: 46 ms
Silverlight app #2: 859 ms
The first app is an otherwise empty app that is doing the loop in the MainPage constructor. The second is doing the loop in a method in another class, and the method is called during an event handler in the GUI thread, I think. But should any of that matter, considering that identical operations are happening within the loop itself?
There maybe something huge I'm missing in how threading works or something, but this discrepancy doesn't make sense to me at all.
In addition to the other comments and answers I'm going to read between the lines a little.
In the first app you have pretty much this code in isolation running in the MainPage constructor. IWO you've create a fresh Silverlight app and slapped this code in it and thats it.
In the second app you have more actual real world stuff. At the very least you have this code running as the result of a button click on a rudimentory UI. Therein lies the clue.
Take a blank app and drop a button on it. Run it and click the button, what does the button do? There are animations attached to visual states of the button. This animation (or other animations or loops) are likely running in parrallel with your code when you click the button. Timers (whether you do it properly with StopWatch or not) record elapsed time, not just the time your thread takes. Hence when other threads are doing other things (like animations) your timing will be off.
My first suspicion would be that Silverlight App #2 triggers a garbage collection. Scaling ~15,000 points should be taking a millisecond, not nearly a second.
Try to reduce memory allocations in your code. Can transformedPoints be an array, rather than a dynamically grown data structure?
You can also look at the GC performance counters, but simply reducing the memory allocation may turn out to be simpler.
Could it be possible your code is not being inlined in the CLR by the app that is running slower?
I'm not sure how the CLR in SL handles inlining, but here is a link to some of the prerequisites for inlining in 3.5 SP1.
http://udooz.net/blog/2009/04/clr-improvements-in-net-35-sp1/

Resources