In my libGDX application I have an actor which needs to create actions programmatically.
At the minute I am adding moveBy actions with incrementing delays in order to get the desired effect but this is very inefficient. Something like below;
actor.addAction(sequence(delay(i * DELAY), moveBy(50, 50));
If possible I would like to programmatically create one single sequence action and add moveBy actions to it as needed. Then I could just invoke a single action without having to continually add actions which is very unresourceful.
I have checked the documentation and could not find anything specific to my particular need.
I was thinking something along the lines of (pseudo code);
addPath(Vector2 path) {
paths.add(path);
}
invokePathAction() {
Action sequence = sequence();
for all paths
sequence.add(moveBy(path.x, path.y, TIME));
addAction(sequence);
}
Is something like this possible with libGDX?
Of course - there is addAction method in the SequenceAction class
MoveToAction action1 = new MoveToAction();
action1.setPosition(0, 0);
action1.setDuration(2);
MoveToAction action2 = new MoveToAction();
action2.setPosition(-500, 0);
action2.setDuration(2);
...
SequenceAction sequence = new SequenceAction();
sequence.addAction(action1);
sequence.addAction(action2);
...
actor.addAction(sequence);
if you want to clear all actions and have "empty" sequence again you can call
sequence.reset();
Related
My process looks like:
select some data 50 rows per select,
do sth with data (set some values)
transform row to object of another table
call batchInsert(myListOfRecords).execute()
My problem is how to set up when data should be inserted ? In my current setup data is only inserted at the end of my loop. This is some kind of problem for me because i want process much more data then i do in my tests. So if i will agree with this then my proccess will end with exception (OutOfMemory). Where i should define max amount of data in batch to call instert?
The important thing here is to not fetch all the rows you want to process into memory in one go. When using jOOQ, this is done using ResultQuery.fetchLazy() (possibly along with ResultQuery.fetchSize(int)). You can then fetch the next 50 rows using Cursor.fetchNext(50) and proceed with your insertion as follows:
try (Cursor<?> cursor = ctx
.select(...)
.from(...)
.fetchSize(50)
.fetchLazy()) {
Result<?> batch;
for (;;) {
batch = cursor.fetchNext(50);
if (batch.isEmpty())
break;
// Do your stuff here
// Do your insertion here
ctx.batchInsert(...);
}
}
SKAction has waiting for duration abilities, for a period of time on a node. And seems to perform actions on nodes. Like moveTo, etc.
If I don't want that, rather I'd prefer to call functions within GameScene after a period of time, how do I do that with SpriteKit in the GameScene, not on a Sprite or other Node?
Are SKActions the way to do this? The only way to do this?
Yes. This question IS that ridiculously simple. I lack the heuristics and terminology to find an answer. Just keep looping around on how SKAction waits are calls on SKSprites for things like scale, rotation, etc, after time. Which isn't want I want/need.
Update:
Desired outcome, inside GameScene
doSetupStuff() // does some stuff...
waitForAWhile() // somehow wait, perhaps do somethings in here, while waiting
doSomethingElse() // does this after the waitForAWhile has waited
UPDATE 2:
What I think happens, again, inside didMove(to view...)
func wait(){
let timeToPause = SKAction.wait(forDuration: 3)
run(timeToPause)
}
let wontwait = SKAction.wait(forDuration: 3)
run(wontwait)
thisFunction(willnot: WAIT"it starts immediately")
wait()
thisFunction(forcedToWait: "for wait()'s nested action to complete")
UPDATE 3:
Found a way to get the delay without using SKActions. It's a little crude and brutal, but makes more sense to me than SKActions, so far:
DispatchQueue.main.asyncAfter(deadline: .now() + 10.0) {
print("I waited ten seconds before printing this!")
}
An option, as you cited, is to manage this externally. The way I typically manage this sort of thing is to have an externally run update cycle. One that
To drive this updater, you could use either CADisplayLink (which is what I use right now with my OpenGL renderer) or a dispatch source timer (which I have used with my SpriteKit engine). When you use an updated, you want to calculate the delta time. The tick handler could look something like:
func tickHandler() {
let currTime = NSDate().timeIntervalSince1970
let dt = lastTime - currTime // lastTime is a data member of the class
// Call all updaters here, pretend "updater" is a known updater class
updater.update(dt)
}
And updater's update method would look something like:
func update(deltaTime:NSTimeInterval) {
// Do your magic
}
I typically have a main overall updater running independent of what people are calling scenes. Example usage would be something like having an attract mode like in old school arcade games. There they show title screen, sample game play, high scores, rinse and repeat. Scenes would be title, game play, high score. Here you can your main updater manage the time and coordinate the construction/destruction/switching of the scenes. Note this implies having an overall scene manager (which is actually quite handy to have).
For your case, you could use this updater to drive the GameScene updater. It's updater could look something like:
func update(deltaTime:NSTimeInterval) {
switch state {
case .SetupState:
// noop?
println("I'm in setup") // Shown just so you can see there is a setup state
case .WaitState:
waitTime += deltaTime
if waitTime >= kWaitTime {
// Do whats you gots to do
doSomethingElse()
state = .NextState
}
case .NextState:
// blah blah blah blah
}
}
So the flow to do this call path from your driver (CADisplayLink or dispatch source) would be something like:
tickHandler -> master updater -> game scene updater
Some will def find this is perhaps a little heavy handed. I, on the other hand, find this very helpful. While there is obviously some time management and the loss of being able to fire and forget, it can help provide more control for orchestrating pieces, as well as arbitrarily changing state without having to worry about killing already queued actions. There is also nothing that says you still cannot mix SKAction. When I did use SpriteKit, I did all my updating this way along with some dispatched items. I only used SKAction to update hierarchy. Keep in mind that I used my own animation and physics system. So at least for me I had a lot less dependency on SpriteKit (it effectively was just a renderer for me).
Note you have to have your own means to handle pause and coming to foreground where your timer will need to be resynced (you only need to worry about tickHandler). Breakpoints also will cause time jumps.
You can use below function
#define ANIM_TIME 2
SKAction *customACtion = [SKAction customActionWithDuration: ANIM_TIME actionBlock:^(SKNode *node, CGFloat elapsedTime) {
// Do Something Here
}];
Another way to make something happen after a certain period of time is to make use of the 'current time' parm passed to update(). The following code will spawn a boss at intervals ranging from 20 to 30 seconds.
In your property definitions:
var timeOfLastBoss: CFTimeInterval = -1 //Indicate no boss yet
var timePerBoss = CFTimeInterval()
.
.
.
didMoveToView() {
...
timePerBoss = CFTimeInterval(Int.random(20...30))
'''
}
.
.
.
func update(currentTime: CFTimeInterval) {
...
spawnBossForUpdate(currentTime)
...
}
'
'
'
func spawnBossForUpdate(currentTime : CFTimeInterval) {
if ( timeOfLastBoss == -1 ) {timeOfLastBoss = currentTime}
if (currentTime - timeOfLastBoss < timePerBoss) {return}
// Rest of 'spawnBoss code
self.timePerBoss = CFTimeInterval(Int.random(20...30))
self.timeOfLastBoss = currentTime
}
One way, using SKActions, in Swift 3.0, looks like this:
DEFINE: aPatientlyWaitingFunction() at the top level of
GameScene class.
To cause a delay to happen before calling the above function, inside
didMove(to view...)
three ways I've found to do this using Actions:
All three ways seem to accomplish the exact same thing:
let timeToWait: TimeInterval = 3 // is seconds in SKAction thinking time
let waitSomeTime = SKAction.wait(forDuration: timeToWait)
// 1st way __________________________________________
// with a completion handler, the function can be called after Action
run(waitSomeTime) {self.aPatientlyWaitingFunction()}
// 2nd way __________________________________________
// as a completion to be done after action, in the run invocation:
run(waitSomeTime, completion: aPatientlyWaitingFunction)
// 3rd way __________________________________________
// alternatively, as part of a sequence of actions...
// Create a sequence, by making a run action from waitSomeTime and...
let thenDoThis = SKAction.run(aPatientlyWaitingFunction)
// then activate sequence, which does one action, then the next
run(SKAction.sequence([waitSomeTime, thenDoThis]))
// OR... for something different ____________________
////////////////////////////////////////////////////////
DispatchQueue.main.asyncAfter(deadline: .now() + timeToWait) {
self.aPatientlyWaitingFunction()
print("DispatchQueue waited for 3 seconds")
}
Working with Arrays. I create objects on a Class base, push them into an Array, I have 2 buttons: one adds a Child and pushes it into the Array, second one Shifts Array and removes the Child. Also a function on my mouse, if I click an object, I define it's Array number, remove the Child and... well, not sure if successful but "delete Array[i];" where i is target's Array number. I can see Array.length in a text field every time I do something. Second button actually does remove an object from Array, the number decreases. But deleting a specified object from the Array, as well as Array.slice(i,1), doesn't reduce the Array length. So I'm afraid it may cause overflow. It's only Array, not sure, maybe it's fine to have over a million cells in an Array? Like if I make a game with meteor shower, meteors are removed from the screen, but the Array still has their cells. And if they appear like 30-50 per sec, it's obvious I may get memory problems in 20 minutes of running it. Well it's 60k so maybe I shouldn't worry as only graphics take much memory?
Still, I could use an advice on how to shift an object in a middle of an Array. Chosen one. How do I delete it as if it never was created, same as Shift does? (it does, right?)
Array.splice() will do most of the tricks. As you remove the meteor off screen, you can splice it out of the array, do like this:
var i:int=meteorArray.indexOf(meteorToRemove);
if (i>=0) meteorArray.splice(i,1);
You should not create a new object as a good practice if you are deleting other. Try recycling, or better said 'object pools'
You should figure out the number max of elements you may use at once. create a property 'active' on each and set it to true or false instead of creating/deleting. Then you can run the update on each object and update it only if necessary
For example:
var meteors:Array = [];
// create 500 meteors
for ( var i:int = 0; i < 500; i++ ) {
var meteor:Meteor = new Meteor();
meteor.active = false;
meteors.push(meteor);
}
// enable one meteor
meteors[0].active = true;
// in your update method:
for each (var meteor in meteors )
if ( meteor.active )
meteor.update();
Hope that helps.
Also you can add a helper method to get a meteor available:
function getMeteorAvailable():Meteor
{
for each (var meteor in meteors )
if ( !meteor.active )
return meteor;
}
I'm trying to create a flash application that will keep track of user generated values. The app should basically allow the user to input the name of the item and it's cost. The total costs should then be added up to show a total value to the user. I can probably figure out how to add the values together, but I'm not really sure how to allow the user to create a list and then allow the user to save it. Can anyone point me towards a tutorial or point me in the right direction?
I am using variables to add user inputed numbers to come up with a total. The first problem is that actionscript 3.0 does not allow variables for texts. I just converted it to 2.0 to fix this. The second problem, is when I test the app and put in my values and click submit, I get NaN in the total values field. Is there a reason why it wouldn't add the values?
Here is the code I used for the submit button:
on (release) {
total = Number(rent) + Number(food) + Number(travel) + Number(entertainment) + Number(bills);
}
Am I missing anything?
Can I give the input text instance names and then give them variables? How are some ways to go about this?
Thanks for the help!
Have an object array, say for example
var stack:Array = new Array();
Then push the item name and it's cost to that array when user inputs, like
stack.push({item:AAA, cost:xx});
So that you can generate the list whenever you want with that array.
You have to see how this works in code. A list in actionscript could be stored inside an array, vector, dictionary or even an Object.
Var myList:Array = [];
myList.push({name: "item 1", cost: 5 });
myList.push({name: "item 2", cost: 7.5 });
If you want to grab the 'product' of "item 1" from the list, you have to create a function for that, lets call it getProductByName
function getProductByName(name:String):Object
{
for each(var product:Object in myList)
{
if (product.name === name) return product;
}
return null; // no match found
}
You can call that function like this:
var product = getProductByName("item 1");
trace(product.cost); // 5
And you can alter the product, so lets make it more expensive
product.cost += 1;
trace(product.cost); // 6
Have fun! If you are using classes, you would create one for the product, with public name and cost, and in that case you'de better use a vector, to ensure working with the right type.
This is what fixed the issue for me in action script 3.0:
myButton.addEventListener(MouseEvent.CLICK, addThem);
function addThem(e:MouseEvent)
{
totalField.text = String ( Number(field1.text) + Number(field2.text) + ....);
}
I also had to name the instances appropriately.
I am trying to sort big array using actionscript 3.
The problem is that i have to use custom sorting function which is painfully slow and leads to flash plugin crash.
Below is a sample code for custom function used to sort array by length of its members:
private function sortByLength():int {
var x:int = arguments[0].length;
var y:int = arguments[1].length;
if (x > y){
return 1;
}else if (x < y){
return -1;
}else{
return 0;
}
}
Which is called like this:
var txt:Array = ["abcde","ab","abc","a"];
txt.sort(sortByLength);
Please advise me how can this be done faster ?
How to change application logic to avoid Flash plugin crashes during sorting ?
try to use strong typing whenever possible, here tell your function that you are waiting two strings.
you could rewrite your function in two way one fastest than the other if you know that all your element are not null:
function sortByLength(a:String, b:String):int {
return a.length-b.length // fastest way not comparison
}
and if you can have null check for it (this one will put null in front of all element):
function sortByLengthWithNull(a:String, b:String):int {
if (a==null) return -1
if (b==null) return 1
return a.length-b.length
}
If you need super-fast sorting, then it might be worthwhile not using an array at all and instead using a linked-list. There are different advantages to each. Primarily, with a linked-list, index-access is slow, while iterating through the list is fast, and linked-lists are not native to AS3 so you'll have to roll your own.
On the upside, you may well be able to use some of Polygonal Labs' code: http://lab.polygonal.de/as3ds/.
Sorting is very, very fast for nearly-sorted data with a linked list, as this article discusses: http://lab.polygonal.de/2007/11/26/data-structures-more-on-linked-lists/.
This solution gives you lots more work, but will eventually give you lots more sort-speed too.
Hope this helps.
-- additional --
I noticed your question in the comments of another answer about "One question however is unanswered - how to perform greedy computations in Flash without hanging it?"
For this, essentially the answer is to break your computation over multiple frames, something like this:
public function sort():void
{
addEventListener(Event.ENTER_FRAME, iterateSort);
}
private function iterateSort():void
{
var time:int = getTimer() + TARGET_MILLISECONDS_PER_FRAME;
var isFinished:Boolean = false;
while (!isFinished && getTimer() < time)
isFinished = continueSort();
if (isFinished)
removeEventListener(Event.ENTER_FRAME, iterateSort);
}
function continueSort():Boolean
{
... implement an 'atom of sort' here, whatever that means ...
}
sortByLength should have two parameters, shouldn't it? I guess that's what you mean by the arguments array...
This looks fine to me, unless arguments is not a local variable, but instead a member variable, and you're just looking at its [0] and [1] elements on each function call. That would at least produce undesired results.