Libgdx - Using Tween engine to change alpha on screen using shaders - libgdx

So I have a peculiar problem when trying to change the visibility of an actor using tween engine. Below is my render method. It works if i remove the shader so i know its not a problem with my Tween class. Has anyone encountered this before, or knows a work around?
#Override
public void render(float delta) {
shader.begin();
batch.setProjectionMatrix(stage.getCamera().combined);
stage.getBatch().setShader(shader);
manager.update(delta);
stage.draw();
stage.act();
}

Related

Libgdx; dispose() Box2D World and Renderer

Could someone please help me understand how I can properly dispose a Box2D World and Debug Renderer?
I have a playscreen that has a world and renderer and I would like to dispose of these when I change to another screen as I do not need them anymore. I have included in my playscreen dispose with the following, and called this manually when an event has been triggered to change screen. At the moment by calling these dispose() methods my game is crashing. Must a game have to have a Box2D world and renderer at all times? What would 'EXCEPTION_ACCESS_VIOLATION' mean?
#Override
public void dispose() {
System.out.println("PlayScreen disposed.");
world.dispose();
b2dr.dispose();
...
}
From my experience there are (at least) two situations where you can get an EXCEPTION_ACCESS_VIOLATION in libGDX-box2d:
world.dispose is called during world.step
world.dispose is called from a different thread

LibGdx when and how should I dispose assets using an AssetManager?

Say I have a method that loads all my assets for a Screen, this method is called in that Screens constructor:
public void load(){
manager.load(pd_bg, Texture.class, textureParams);
}
Now when I exit that Screen, I have e method that unloads all these assets:
public void unLoad(){
manager.unload(pd_bg);
}
Inside my Screen I might use this asset for a Sprite, like so:
Sprite bg = new Sprite(GdxAssetManager.manager.get(GdxAssetManager.pd_bg, Texture.class));
Finally, do I need to dispose of the texture used in this sprite even though I call the unLoad() method? i.e:
public void dispose(){
GdxAssetManager.unLoad();
bg.getTexture.dispose(); //Is this line needed?
}
I am also wondering, if I load all resources when I start the app, should I then unload resources when I exit a Screen? How will they be loaded up next time then (since I only load the on launch)?.
I am using a Sprite as an example, but I guess the answer will be true for any asset.
No, you don't have to (and must not) dispose it when you unload it. In general, the rule of thumb goes: if you create it, you destroy it. So if you create a Texture (by using the new keyword) then you own that texture and are responsible for destroying it (calling its dispose method). In the case of AssetManager, it is the AssetManager who owns the resource and is responsible for destroying it.
To keep track of which resources needs to be created and destroyed, AssetManager uses reference counting. So it is important that you eventually call unload for everytime you call load.
And because you created the AssetManager using the new keyword, you own it and you are responsible for calling its dispose method:
public class MyGame extends ApplicationAdapter {
public AssetManager assetManager;
#Override public void create() {
assetManager = new AssetManager();
...
}
...
#Override public void create() {
assetManager.dispose();
assetManager = null;
...
}
}
Have a look at the documentation: https://github.com/libgdx/libgdx/wiki/Managing-your-assets
Btw, in your code it looks like you are using a static AssetManager. Although not related to your question, be aware that will lead to issues. So I'd advice you to implement a proper object oriented design instead of making things static.
As for your second question, it is unclear what you mean. If you mean when you should call AssetManager#unload, then the answer is whenever the class that called the corresponding AssetManager#load method no longer needs it.
For example, if you have an asset named "image.png" and you call the assetManager.load("image.png", Texture.class) in both your MyGame and MyScreen classes then you should call assetManager.unload("image.png") also in both your MyGame and MyScreen class.
To answer your last two questions:
In your launcher class, you should load every texture you need from all screens.
Then in your screens you aceess the images you need and you dont unload them and you also don't dispose them nor do you dispose the assetmanager.
Then in your launcher class in the
dispose(){}
method you first unload evereything and then call
assetmanager.dispose();

How drag a Sprite smoothly on-screen in actionscript

First of all, my question is basically the same as this one:
How to drag an image to move it smoothly on screen, with ActionScript?
I want my dragged Sprites to keep up with the mouse on-screen, smoothly, without lagging behind.
And I notice that in the old ActionScript 3 Cookbook from way-back-when that they used a similar solution for their DraggableSprite as was used in the above link. Namely, use the stage instance to listen for the MouseMove event and then read from the event.stageX and stageY properties.
I've done that.
But my Sprite still doesn't stay locked with the mouse cursor. It lags behind. I feel like I must be missing something. However, if the solution posted above (ie listen for stage's MouseMove and use event.stageX/Y) is still current and the problem I'm describing should not be occurring, please also let me know. Even though it's not supposed to work, I've tried event.updateAfterEvent() and it also doesn't seem to have any positive effect.
Any help or advice would be greatly appreciated.
Here's a simple example of how I've written the handlers. It should work as-is if pasted into a new project.
I should also add that I'm compiling this as a desktop application using Adobe AIR. Would the run time be a factor???
package {
import flash.display.Sprite;
import flash.events.MouseEvent;
[SWF(width="1280", height="720", frameRate="30")]
public class test_drag extends Sprite {
private var testDragSprite:TestDragSprite;
public function test_drag() {
super();
graphics.clear();
graphics.beginFill(0x0000FF);
graphics.drawRect(0, 0, 1280, 720);
graphics.endFill();
testDragSprite = new TestDragSprite();
addChild(testDragSprite);
testDragSprite.addEventListener(MouseEvent.MOUSE_DOWN, testDragSprite_mouseHandler);
testDragSprite.addEventListener(MouseEvent.MOUSE_UP, testDragSprite_mouseHandler);
}
private function testDragSprite_mouseHandler(e:MouseEvent):void {
switch (e.type) {
case MouseEvent.MOUSE_DOWN: {
stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
break;
}
case MouseEvent.MOUSE_UP: {
stage.removeEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
break;
}
}
}
private function mouseMoveHandler(e:MouseEvent):void {
//-20 to keep the sprite centered on the mouse
testDragSprite.x = e.stageX - 20;
testDragSprite.y = e.stageY - 20;
//e.updateAfterEvent(); //strange effect, but doesn't solve the problem.
}
}
}
import flash.display.Sprite;
internal class TestDragSprite extends Sprite {
public function TestDragSprite() {
super();
graphics.lineStyle(1, 0xDDDDDD);
graphics.beginFill(0xFF0000);
graphics.drawRoundRect(0, 0, 40, 40, 12);
graphics.endFill();
}
}
There is always going to be a little lag, but:
The first two suggestions will make the most noticeable change to your code/performance.
Enable hardware graphics acceleration; edit your AIR application
descriptor file (xml) and set renderMode to Direct (or GPU). Consult
the Adobe Air help for details.
<!-- The render mode for the app (either auto, cpu, gpu, or direct). Optional. Default auto -->
<renderMode>direct</renderMode>
Use startDrag and endDrag to bypass your manual assignments in your mouseMoveHandler.
Replace :
testDragSprite.addEventListener(MouseEvent.MOUSE_DOWN, testDragSprite_mouseHandler);
testDragSprite.addEventListener(MouseEvent.MOUSE_UP, testDragSprite_mouseHandler);
With :
testDragSprite.addEventListener(MouseEvent.MOUSE_DOWN, mouseDown);
testDragSprite.addEventListener(MouseEvent.MOUSE_UP, mouseUp);
Add the new handlers:
private function mouseDown(e:MouseEvent):void {
testDragSprite.startDrag();
}
private function mouseUp(e:MouseEvent):void {
testDragSprite.stopDrag();
}
Increase your frame rate, but watch your CPU usage as your application/game becomes more complicated as you may need to lower it to allow your game logic enough time to complete between frames (otherwise you end up with what is called long frames, you can use the free Adobe Scout profiling tool to watch for these and lots of other things).
Add a frame rate HUD to your display so you can monitor when your actual framerate is lower than the requested framerate (this is for debugging)
If your game is 2d based, consider using the open-source Starling framework as all content is rendered directly by the GPU vs Flash's standard display list objects.
Just try the member function startDrag.
The Feathers UI library includes a drag-and-drop module. The answers above all use the 'old' display list which is not mobile-ready. If you want your code to work cross-platform you need a GPU framework (most popular is Starling on which Feathers is based, as well as most Adobe AIR games and Apps).

Starling AS3 IOS Splash Screen

I have developed an app in AS3 and Starling to be ported to IOS. I have updated the Default.png image and this works great however my app takes a while to load and a black screen is shown for about 3-4 seconds.
I have looked everywhere for a solution but couldn't find any that work. Does someone have a working solution?
Many thanks
I'm not sure if there is a neater solution at the moment but what I do is add a bitmap of the default screen to the native flash stage. Then when Starling is ready I remove the bitmap.
So before you instantiate Starling, add the bitmap image to the stage (this will be the Flash stage)
public static var _splash:Bitmap;
//load or embed your bitmap//
addChild(_splash);
Then instantiate and start Starling. e.g.
myStarling = new Starling(Main, stage, null, null, Context3DRenderMode.AUTO, Context3DProfile.BASELINE);
myStarling.stage3D.addEventListener(starling.events.Event.CONTEXT3D_CREATE, function(e:flash.events.Event):void {
// Starling is ready!
myStarling.start();
});
In your root Starling class (in this example it's Main), use an ADDED_TO_STAGE listener and when this is triggered, remove the bitmap.
public function Main() {
addEventListener(starling.events.Event.ADDED_TO_STAGE, onAdded);
}
private function onAdded ( e:starling.events.Event ):void {
StartUp._splash.parent.removeChild(StartUp._splash);
StartUp._splash = null;
}
In the example above the root document class is called 'StartUp'.
As described by docs there is Default.png used as splash screen in iOS.

Simulating a MovieClip in pure as3

I am looking for a way to make a Flash movie clip (animation, like the ones created with Flash Pro CS), but purely in as3 - so I can import them into Prezi.
I have done a lot of as3 programming in Flash Builder with Flex projects and I have no background in how MovieClips work.
What I have already tried is extending a MovieClip class and trying to base the animation on Timers, this failed so I tried with ENTER_FRAME event (because flash animations are based on frames - so I thought...). But all this fails, only graphics drawn in the constructor are displayed - no animation happens. (As I wrote in the first paragraph I am testing this importing the swf into Prezi, opening it in a browser works as expected)
Is there any way to do it? Like listening to specific events?
Give sprite sheet a try. It's the best solution for animation in AS3, and also pretty simple to implement. for changing drawing, there are Timer and ENTER_FRAME event to do this.
Funny thing happened. I wanted to show you a sample code I was trying out (I already tried Sprite with ENTER_FRAME), that was not working. By accident I found a solution. It looks like you need to draw something in the first frame, or else the other frames won't work (in Prezi at least).
So here is the working code:
public class PreziTest extends Sprite{
private var radius:uint = 10;
public function PreziTest(){
addEventListener(Event.ENTER_FRAME, onEnterFrame);
onEnterFrame(null); // WITHOUT THIS IT WON'T WORK - YOU NEED TO DRAW SOMTHING IN THE FIRST FRAME
}
private function onEnterFrame(event:Event):void{
radius += 10;
if(radius > 200)
radius = 10;
graphics.clear();
graphics.beginFill(0xff0000);
graphics.drawCircle(radius, radius, radius);
}
}
Thanks for all your help!