Is there a way to apply an alpha mask to a FlxCamera? - camera

I'm trying to implement this camera but one of the obstacles I'm facing right now, is the merging of two cameras (what he describes here).
At first I tried to make a non-rectangular camera, but I don't think it's possible without changing a lot of things in the way HaxeFlixel renders.
And then I found the alphaMask() function in the FlxSpriteUtil package and I think it would be a better solution.
Not only would it solve my problem, it would actually permit all kinds of funky-shaped cameras, you just have to create the right mask!
But the new problem is that I don't know how to (and again, if it's possible without changing a bit the FlxCamera) apply it to the camera.
Internally, the FlxCamera might use a FlxSprite, but only in blit render mode, and I am in tiles render mode (haven't found how to change, not good enough solution in my opinion), which uses a Flash Sprite instead and I don't know what to do with it.
So in short, do you have an idea how to apply an AlphaMask to a FlxCamera? Or another way to achieve what I'm trying to do?
PS: If you want to have a look at the (ugly and frenchly commented) code, it's over here!

You can render the contents of a FlxCamera to a FlxSprite (though it does require conditional code based on the render mode). The TurnBasedRPG tutorial game uses this for the wave effect in the combat screen, see CombatHUD.hx:
if (FlxG.renderBlit)
screenPixels.copyPixels(FlxG.camera.buffer, FlxG.camera.buffer.rect, new Point());
else
screenPixels.draw(FlxG.camera.canvas, new Matrix(1, 0, 0, 1, 0, 0));
Here's a code example that uses this to create a HaxeFlixel-shaped camera:
package;
import flixel.tweens.FlxTween;
import flash.geom.Matrix;
import flixel.FlxCamera;
import flixel.FlxG;
import flixel.FlxSprite;
import flixel.FlxState;
import flixel.graphics.FlxGraphic;
import flixel.system.FlxAssets;
import flixel.util.FlxColor;
import openfl.geom.Point;
using flixel.util.FlxSpriteUtil;
class PlayState extends FlxState
{
static inline var CAMERA_SIZE = 100;
var maskedCamera:FlxCamera;
var cameraSprite:FlxSprite;
var mask:FlxSprite;
override public function create():Void
{
super.create();
maskedCamera = new FlxCamera(0, 0, CAMERA_SIZE, CAMERA_SIZE);
maskedCamera.bgColor = FlxColor.WHITE;
maskedCamera.scroll.x = 50;
FlxG.cameras.add(maskedCamera);
// this is a bit of a hack - we need this camera to be rendered so we can copy the content
// onto the sprite, but we don't want to actually *see* it, so just move it off-screen
maskedCamera.x = FlxG.width;
cameraSprite = new FlxSprite();
cameraSprite.makeGraphic(CAMERA_SIZE, CAMERA_SIZE, FlxColor.WHITE, true);
cameraSprite.x = 50;
cameraSprite.y = 100;
cameraSprite.cameras = [FlxG.camera];
add(cameraSprite);
mask = new FlxSprite(FlxGraphic.fromClass(GraphicLogo));
var redSquare = new FlxSprite(0, 25);
redSquare.makeGraphic(50, 50, FlxColor.RED);
add(redSquare);
FlxTween.tween(redSquare, {x: 150}, 1, {type: FlxTween.PINGPONG});
}
override public function update(elapsed:Float):Void
{
super.update(elapsed);
var pixels = cameraSprite.pixels;
if (FlxG.renderBlit)
pixels.copyPixels(maskedCamera.buffer, maskedCamera.buffer.rect, new Point());
else
pixels.draw(maskedCamera.canvas);
cameraSprite.alphaMaskFlxSprite(mask, cameraSprite);
}
}

Related

Famo.us/Angular Sticky Background Position ScrollView Sync

I'm trying to create functionality very similar to most websites these days.
The concept is 3 sections the size of the browser, the background images are supposed to be fixed positioned and revealed by the div scrolling up and down.
We need this to function as beautifully on mobile as it does on desktop, and it looks like Famous/angular is the solution.
Here is a pen.
http://codepen.io/LAzzam2/pen/XJrwbo
I'm using famous' Scroll.sync, firing javascript that positions the background image on every start / update / end.
scrollObject.sync.on("update", function (event) {
console.log('update');
test(event);
});
here is the function positioning the backgrounds.
function test(data){
var scroller = document.getElementsByClassName('famous-group');
styles = window.getComputedStyle(scroller[0], null);
tr = styles.getPropertyValue("-webkit-transform").replace('matrix(1, 0, 0, 1, 0,','').replace(')','');
var distanceTop = -(parseInt(tr));
var sections = document.getElementsByClassName('section');
sections[3].style.backgroundPosition="50% "+distanceTop+"px";
sections[4].style.backgroundPosition="50% "+(-(window.innerHeight)+distanceTop)+"px";
sections[5].style.backgroundPosition="50% "+(-(window.innerHeight*2)+distanceTop)+"px";
};
Any input / suggestions / advice would be wonderful, really just looking for a proof of concept with these 3 background images scrolling nicely.
That jittery-ness is unfortunate, I can't tell what would be causing the issue, except maybe the order in which events are fired?
**There are known issues, only works in -webkit browsers as of now
I think your idea to use Famous is good, but probably what I would do, would be taking a different approach to the problem.
You are solving this by touching the DOM, that is exactly what both Angular and Famous are meant to avoid.
If I had to face the same goal, I would probably use a Famous surface for the background instead of changing the property of the main one and synchronize its position with the scrolling view.
So, in your code, it would be something like this:
function test(data){
var scrollViewPosition = scrollObject.getAbsolutePosition();
var newBackgroundPosition = // Calculate the new background position
var newForegroundPosition = // Calculate the new foreground position
var backgroundSurface = backgroundSurface.position.set(newBackgroundPosition);
var foregroundSurface = foregroundSurface.position.set(newForegroundPosition);
};

Updating to latest AIR v3.8 causes SWFs loaded from disk to malfunction

We have an existing application where, if our users auto-update to Adobe AIR v3.8 it causes interactive SWFs that are loaded from the local disk into an HtmlLoader instance to not function properly. The mouse cursor is stuck in the corner of the window and will not move. I have narrowed the problem down to something in the HTML that we are loading. If the wmode property is changed from "opaque" to "window" the mouse works. If left as shown below wmode="opaque" the mouse cursor will not move.
The SWFs that we are loading in have been coded by various people to varying degrees of quality. In order to protect our application from varying coding practices we 'sandbox' them by using an HTMLLoader instance which loads an HTML file which in turn loads the SWF. This prevents the loaded SWF from walking up to the parent app (our AIR app) and doing unpleasant things like messing with the mouse. This has worked just fine for several years. Now, these SWFs do not work correctly.
Below is the code we are using to set up the HTMLLoader, and below that is the HTML.
`
import core.abstract.ICoreFactory;
import core.abstract.ui.IInteractiveRewardPlayer;
import core.concrete.Instances;
import domain.curriculum.Reward;
import flash.display.DisplayObject;
import flash.display.Sprite;
import flash.events.MouseEvent;
import flash.html.HTMLLoader;
import flash.net.URLRequest;
import mx.containers.Canvas;
import mx.containers.VBox;
import mx.core.UIComponent;
import mx.logging.*;
public class InteractiveRewardContainer extends Canvas implements IInteractiveRewardPlayer
{
private static var _logger:ILogger = Log.getLogger("InteractiveRewardContainer");
private var _html:HTMLLoader;
public function InteractiveRewardContainer()
{
super();
}
public function addToDisplay(container:VBox):void
{
container.addChild(this);
}
public function startReward(reward:Reward, width:int, height:int):void
{
_html = new HTMLLoader();
var bitmapHolder:UIComponent = new UIComponent();
var mySprite:Sprite = new Sprite();
var file:String = Instances.coreFactory.resourceLoader.returnHTMLRewardFileName(reward);
_logger.info("File=" + file);
var urlReq:URLRequest = new URLRequest(file);
bitmapHolder.addChild(_html);
_html.width = width;
_html.height = height;
_html.load(urlReq);
mySprite.addChild(_html);
bitmapHolder.addChild(mySprite);
this.addChild(bitmapHolder);
this.width = width;
this.height = height;
}
public function stopReward():void
{
_html.loadString("<html></html>");
}
}
`
and a portion of the HTML. Note the wmode attribute. Changing it to "window" fixes the mouse problem, but then we have a display problem.
<embed src="76381.swf" quality="high" bgcolor="#869ca7" id="RightClickDemo" width="100%" height="100%" name="Bicycle" align="middle" menu="false" play="true" loop="false" quality="high" wmode="opaque" allowScriptAccess="always" type="application/x-shockwave-flash" pluginspage="http://www.adobe.com/go/getflashplayer" />
Any ideas what we can do to fix this issue?
Setting wmode to "direct" in the HTML fixed the problem with the mouse, and also maintained the proper display.

Chart not render correctly when maximizing / restoring window or dragging resize bar (SmartGWT)

I am new to SmartGWT and having this issue for long time and could not fix it.
The charts are not in the right position and not resized after I maximize / restore the window, the same issue exists when I drag the resize bar in the window. However after I drag the edge of the window, even just a little, the charts can be rendered correctly. (looks like there is a delay or something)
I want my charts can render correctly immediately the window is maximized / restored, or when I drag the resize bar. NOT trying to drag the edge of the window every time to correct it.
Please take a look at the below simple case: (I am using HighCharts for charting)
import org.moxieapps.gwt.highcharts.client.Chart;
import org.moxieapps.gwt.highcharts.client.Point;
import org.moxieapps.gwt.highcharts.client.Series;
import org.moxieapps.gwt.highcharts.client.ToolTip;
import org.moxieapps.gwt.highcharts.client.ToolTipData;
import org.moxieapps.gwt.highcharts.client.ToolTipFormatter;
import org.moxieapps.gwt.highcharts.client.labels.PieDataLabels;
import org.moxieapps.gwt.highcharts.client.plotOptions.PiePlotOptions;
import org.moxieapps.gwt.highcharts.client.plotOptions.PlotOptions;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.RootPanel;
import com.smartgwt.client.widgets.layout.HLayout;
import com.smartgwt.client.widgets.layout.VLayout;
public class Test1 implements EntryPoint {
public void onModuleLoad() {
Window.enableScrolling(true);
Window.setMargin("0px");
HLayout mainLayout = new HLayout();
mainLayout.setWidth100();
mainLayout.setHeight100();
VLayout vl1 = new VLayout();
vl1.setWidth(250);
vl1.setHeight100();
vl1.setShowResizeBar(true);
VLayout vl2 = new VLayout();
vl2.setWidth100();
vl2.setHeight100();
HLayout top = new HLayout();
HLayout bottom = new HLayout();
VLayout topLeft = new VLayout();
VLayout topRight = new VLayout();
VLayout bottomLeft = new VLayout();
VLayout bottomRight = new VLayout();
topLeft.addMember(drawCharts());
topRight.addMember(drawCharts());
bottomLeft.addMember(drawCharts());
bottomRight.addMember(drawCharts());
top.setMembers(topLeft, topRight);
bottom.setMembers(bottomLeft, bottomRight);
vl2.setMembers(top, bottom);
mainLayout.setMembers(vl1, vl2);
RootPanel.get().add(mainLayout);
}
private Chart drawCharts() {
final Chart chart = new Chart()
.setType(Series.Type.PIE)
.setPlotBackgroundColor((String) null)
.setPlotBorderWidth(null)
.setPlotShadow(false)
.setOption("/chart/marginTop", 0)
.setOption("/chart/marginBottom", 10)
.setPiePlotOptions(
new PiePlotOptions()
.setAllowPointSelect(true)
.setCursor(PlotOptions.Cursor.POINTER)
.setPieDataLabels(
new PieDataLabels().setEnabled(false))
.setShowInLegend(true))
.setToolTip(new ToolTip().setFormatter(new ToolTipFormatter() {
public String format(ToolTipData toolTipData) {
return "<b>" + toolTipData.getPointName() + "</b>: "
+ toolTipData.getYAsDouble() + " %";
}
}));
chart.addSeries(chart
.createSeries()
.setName("Browser share")
.setPoints(
new Point[] {
new Point("Firefox", 45.0),
new Point("IE", 26.8),
new Point("Chrome", 12.8).setSliced(true)
.setSelected(true),
new Point("Safari", 8.5),
new Point("Opera", 6.2),
new Point("Others", 0.7) }));
return chart;
}
}
Do I need to add a resize handler to fix this problem?
Or it may be the problem of the charts layout? I divided the area into four parts (top_left, top_right, bottom_left, bottom_right) and put chart into each part.
Anyone knows how to fix this problem which troubles me a long time? Appreciated.
First of all, I believe your browser share is not very accurate (Lol).
Taking a quick look at your code, it seems that you're mixing GWT charts with SmartGWT, which is not fully supported.
You will have to add some manual handling of the resizes events here.
Take a look at this post :
http://forums.smartclient.com/showthread.php?t=8159#aContainer
and the brief explanation is right here :
http://forums.smartclient.com/showthread.php?t=8159#aMix

while I scroll between the layout it takes too long to be able to scroll between the gallerie's pictures. Is there any way to reduce this time?

this is my first question here, though I've being reading this forum for quite a while. Most of the answers to my doubts are from here :)
Getting back on topic. I'm developing an Android application. I'm drawing a dynamic layout that are basically Galleries, inside a LinearLayout, inside a ScrollView, inside a RelativeLayout. The ScrollView is a must, because I'm drawing a dynamic amount of galleries that most probably will not fit on the screen.
When I scroll inside the layout, I have to wait 3/4 seconds until the ScrollView "deactivates" to be able to scroll inside the galleries. What I want to do is to reduce this time to a minimum. Preferably I would like to be able to scroll inside the galleries as soon as I lift my finger from the screen, though anything lower than 2 seconds would be great as well.
I've being googling around for a solution but all I could find until now where layout tutorials that didn't tackle this particular issue. I was hoping someone here knows if this is possible and if so to give me some hints on how to do so.
I would prefer not to do my own ScrollView to solve this. But if that is the only way I would appreciate some help because I'm not really sure how would I solve this issue by doing that.
this is my layout:
public class PicturesL extends Activity implements OnClickListener,
OnItemClickListener, OnItemLongClickListener {
private ArrayList<ImageView> imageView = new ArrayList<ImageView>();
private StringBuilder PicsDate = new StringBuilder();
private CaWaApplication application;
private long ListID;
private ArrayList<Gallery> gallery = new ArrayList<Gallery>();
private ArrayList<Bitmap> Thumbails = new ArrayList<Bitmap>();
private String idioma;
private ArrayList<Long> Days = new ArrayList<Long>();
private long oldDay;
private long oldThumbsLoaded;
private ArrayList<Long> ThumbailsDays = new ArrayList<Long>();
private ArrayList<ArrayList<Long>> IDs = new ArrayList<ArrayList<Long>>();
#Override
public void onCreate(Bundle savedInstancedState) {
super.onCreate(savedInstancedState);
RelativeLayout layout = new RelativeLayout(this);
ScrollView scroll = new ScrollView(this);
LinearLayout realLayout = new LinearLayout(this);
ArrayList<TextView> texts = new ArrayList<TextView>();
Button TakePic = new Button(this);
idioma = com.mateloft.cawa.prefs.getLang(this);
if (idioma.equals("en")) {
TakePic.setText("Take Picture");
} else if (idioma.equals("es")) {
TakePic.setText("Sacar Foto");
}
RelativeLayout.LayoutParams scrollLP = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.FILL_PARENT,
RelativeLayout.LayoutParams.FILL_PARENT);
layout.addView(scroll, scrollLP);
realLayout.setOrientation(LinearLayout.VERTICAL);
realLayout.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT,
LayoutParams.FILL_PARENT));
scroll.addView(realLayout);
TakePic.setId(67);
TakePic.setOnClickListener(this);
application = (CaWaApplication) getApplication();
ListID = getIntent().getExtras().getLong("listid");
getAllThumbailsOfID();
LinearLayout.LayoutParams TakeLP = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT);
realLayout.addView(TakePic);
oldThumbsLoaded = 0;
int galler = 100;
for (int z = 0; z < Days.size(); z++) {
ThumbailsManager croppedThumbs = new ThumbailsManager(Thumbails,
oldThumbsLoaded,
ThumbailsDays.get(z));
oldThumbsLoaded = ThumbailsDays.get(z);
texts.add(new TextView(this));
texts.get(z).setText("Day " + Days.get(z).toString());
gallery.add(new Gallery(this));
gallery.get(z).setAdapter(new ImageAdapter(this, croppedThumbs.getGallery(), 250, 175, true,
ListID));
gallery.get(z).setOnItemClickListener(this);
gallery.get(z).setOnItemLongClickListener(this);
gallery.get(z).setId(galler);
galler++;
realLayout.addView(texts.get(z));
realLayout.addView(gallery.get(z));
}
Log.d("PicturesL", "ListID: " + ListID);
setContentView(layout);
}
private void getAllThumbailsOfID() {
ArrayList<ModelPics> Pictures = new ArrayList<ModelPics>();
ArrayList<String> ThumbailsPath = new ArrayList<String>();
Pictures = application.dataManager.selectAllPics();
long thumbpathloaded = 0;
int currentID = 0;
for (int x = 0; x < Pictures.size(); x++) {
if (Pictures.get(x).walkname == ListID) {
if (Days.size() == 0) { Days.add(Pictures.get(x).day); oldDay = Pictures.get(x).day;
IDs.add(new ArrayList<Long>()); currentID = 0; }
if (oldDay != Pictures.get(x).day) {
oldDay = Pictures.get(x).day;
ThumbailsDays.add(thumbpathloaded);
Days.add(Pictures.get(x).day);
IDs.add(new ArrayList<Long>());
currentID++;
}
StringBuilder tpath = new StringBuilder();
tpath.append(Pictures.get(x).path.substring(0,
Pictures.get(x).path.length() - 4));
tpath.append("-t.jpg");
IDs.get(currentID).add(Pictures.get(x).id);
ThumbailsPath.add(tpath.toString());
thumbpathloaded++;
if (x == Pictures.size() - 1) {
Log.d("PicturesL", "El ultimo de los arrays, tamaƱo: " + Days.size());
ThumbailsDays.add(thumbpathloaded);
}
}
}
for (int y = 0; y < ThumbailsPath.size(); y++) {
Thumbails.add(BitmapFactory.decodeFile(ThumbailsPath.get(y)));
}
}
I had a memory leak on another activity when screen orientation changed that was making it slower, now it is working better. The scroller is not locking up. But sometimes, when it stops scrolling, it takes a few seconds (2/3) to disable itself. I just want it to be a little more dynamic, is there any way to override the listener and make it stop scrolling ON_ACTION_UP or something like that?
I don't want to use the listview because I want to have each gallery separated by other views, now I just have text, but I will probably separate them with images with a different size than the galleries.
I'm not really sure if this is possible with a listadapter and a listview, I assumed that a view can only handle only one type of object, so I'm using a scrollview of a layout, if I'm wrong please correct me :)
Also this activity works as a preview or selecting the pictures you want to view in full size and manage their values. So its working only with thumbnails. Each one weights 40 kb. Guessing that is very unlikely that a user gets more than 1000~1500 pictures in this view, i thought that the activity wouldn't use more than 40~50 mb of ram in this case, adding 10 more if I open the fullsized view. So I guessed as well most devices are able to display this view in full size. If it doesn't work on low-end devices my plan was to add an option in the app preferences to let user chop this view according to some database values.
And a last reason is that during most of this activity "life-cycle" (the app has pics that are relevant to the view, when it ends the value that selects which pictures are displayed has to change and no more pictures are added inside this instance of this activity); the view will be unpopulated, so most of the time showing everything wont cost much, just at the end of its cycle
That was more or less what I thought at the time i created this layout. I'm open to any sort of suggestion or opinion, I just created this layout a few days ago and I'm trying to see if it can work right, because it suits my app needs. Though if there is a better way i would love to hear it
PD: I've being toying to see how much it can actually draw. I managed to draw 530 galleries with 600 thumbnails on the same layout, the app is using 42 mb, and I don't have access to more memory to start my full sized view afterwards :( .I tried to do the same with 1000 but it throws OutOfMemory error, bitmap size exceeds vm budget. Is there any way to make more memory availeable on high-end devices? Or should I try to figure out a way not to draw everything at once? Would the listview work for more than one type of object?
Thanks
Mateo
Why not make your galleries items of a listview? That way you won't have to inflate all of them immediately and can the advantage of the listview recyling mechanism. Some of the slowness you are seeing might be coming from very heavy memory usage. Galleries aren't exactly light widgets so you might be seeing pauses from heavy GC activity once you stop scrolling. ListView with an adapter would also allow you to lazily bind the Galleries to the list, such that during a fling you aren't doing the expensive binding of the galleries.

How to make a MovieClip remove itself in AS3?

What is the equivalent to removeMovieClip() in AS3?
Apparently many have the same question:
StackOverflow:
How to completely remove a movieclip in as3
Remove movie clip as3
How to remove childmovieclip and add to new parent movieclip
Others:
removeMovieClip(this) in AS3?
Destroy/Delete a Movieclip???
Remove movie clip
But none of their solutions seem to work, for me:
Im working on flash CS4 with AS3:
I have a very simple movie with a single button called click. On pressing the button, a new instance of coin is created:
this.click.addEventListener(MouseEvent.CLICK,justclick);
function justclick(e:MouseEvent){
var money=new coin
this.addChild(money)
money.x=e.stageX
money.y=e.stageY
}
It might not be the best code, but it works fine. Now, the coin MovieClip is supposed to show a small animation and remove itself. In good old AS2 I would have added:
this.removeMovieClip()
in the last frame of the animation. But this doesn't exist in AS3.
I have tried, without success:
this.parent.removeChild(this) // 'Cannot access a property or method of nullobject reference'...
this.removeMovieClip() // 'removeMovieClip is not a function'
removeMovieClip(this) //'call to possibly undefined method removeMovieClip'
unloadMovie(this)//'call to possibly undefined method removeMovieClip'
Solutions?
Thanks,
this.parent.removeChild(this);
This one should be working; it's what I use. One problem I had when I switched to AS3 is that sometimes it wouldn't be added as a child right, so you might want to check that. You also have to import flash.display via putting this at the top if you're not already:
import flash.display.*
You should also remove the event listener on it before removing it.
If your animation is ending on frame 20.
note: using 19 because flash count frames from zero(0) similar to array index.
class animatedCloud
{
public function animatedCloud(){
addFrameScript(19, frame20);
}
private function frame20(){
parent.removeChild(this);
}
}
Always ensure that those self removing movieclips can get garbage collected.
This solution wiped away all my instances from a loaded swf's library symbol:
var mc:MovieClip = new definition() as MovieClip;
addChild(mc);
mc.x = 1000 * Math.random();
mc.y = 1000 * Math.random();
mc.addFrameScript(mc.totalFrames - 1, function onLastFrame():void
{
mc.stop();
mc.parent.removeChild(mc);
mc = null;
});
public static function removeDisplayObject(displayObject:DisplayObject):void {
/* normal code
if(displayObject && displayObject.parent){
displayObject.parent.removeChild(displayObject);
}
*/
displayObject ? displayObject.parent ? displayObject.parent.removeChild(displayObject) : null : null;
}
I use, in an extra blank keyframe at the end of the MovieClip which should remove itself:
stop();
MovieClip(parent).removeChild(this);
Found it to be the proper and best solution.