Starling library - When I try and change cursor to image...it doesn't work (and a sprite element dissapears from stage) - actionscript-3

I am using Starling to make a really, really, really easy game - I am just trying to add a stationary sprite to the stage...and make it so that when the mouse touches the sprite...the game "stops" and a score is sent. I haven't tried implementing hitTest yet for the collision, but I have run into a sort of conflict problem where, when I comment out the line(s) that is supposed to change the cursor image (see Startup.as - stage.addEventListener(TouchEvent.TOUCH, touchHandler); and createCustomeCursor), the instance of AvatarEnemy (see enemy in Game.as) does what it should, and is placed in the center of the screen. When I comment in the line that is supposed to change the cursor: a). the cursor doesn't change, and b.) the enemy sprite disappears. When I comment out the same lines - the enemy sprite reappears (but obviously, the cursor doesn't work - not that it was working in the first place). Why is this happening? My code is below - someone mentioned something about not doing things before Starling is initialized here (a question I asked, which is a precursor to this one) - but I'm not sure what they meant because it at least seems like all my code is in the right place.
Game.as
package
{
import Classes.AvatarEnemy;
import starling.display.Sprite;
public class Game extends Sprite
{
//private var juggler:Juggler = Starling.juggler;
private var enemy:AvatarEnemy;
public function Game()
{
enemy = new AvatarEnemy();
addChild(enemy);
}
}
}
Startup.as
package
{
import flash.display.Bitmap;
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.geom.Point;
import starling.core.Starling;
import starling.events.Touch;
import starling.events.TouchEvent;
import starling.display.DisplayObject;
import flash.display.BitmapData;
import flash.ui.MouseCursorData;
import flash.ui.Mouse;
[SWF(width="500", height="500", frameRate="30", backgroundColor="#FFFFFF")]
public class Startup extends Sprite
{
private var mStarling:Starling;
[Embed(source="Classes/Avatarpic.png")]
private const Cursor:Class;
public var cursor:DisplayObject;
public function Startup()
{
// Create a Starling instance that will run the "Game" class
mStarling = new Starling(Game, stage);
mStarling.start();
// These settings are recommended to avoid problems with touch handling
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP_LEFT;
createCustomCursor();
stage.addEventListener(TouchEvent.TOUCH, touchHandler);
}
private function touchHandler(event:TouchEvent):void
{
var touch:Touch = event.getTouch(cursor);
if(touch.phase){
{
var localPos:Point = touch.getLocation(cursor);
trace("Touched object at position: " + localPos);
}
}
}
public function createCustomCursor():void
{
var cursorBitmaps:Vector.<BitmapData> = new Vector.<BitmapData>();
cursorBitmaps.push((new Cursor() as Bitmap).bitmapData);
var mouseCursorData:MouseCursorData = new MouseCursorData();
mouseCursorData.data = cursorBitmaps;
mouseCursorData.frameRate = 30;
mouseCursorData.hotSpot = new Point(0, 0);
Mouse.registerCursor("customCursor", mouseCursorData);
Mouse.cursor = "customCursor";
}
}
}
Any help would be greatly appreciated (if you need a copy of the code (it's an Adobe Flash Builder 4.7 project - I have made a git repo - just comment if you want the link).
UPDATE
I realized I wasn't registering the image as the cursor - I updated my Startup.as file to reflect changes (take a look at createCustomCursor function) - the cursor still isn't working, and the sprite that is supposed to appear is still not appearing.
Also - just in case you want to see where AvatarEnemy is coming from:
AvatarEnemy.as
package Classes
{
import starling.display.Image;
import starling.display.Sprite;
import starling.textures.Texture;
public class AvatarEnemy extends Sprite
{
[Embed(source='Enemypic.png')]
private static var Enemypic:Class;
private var texture:Texture = Texture.fromBitmap(new Enemypic());
private var image:Image = new Image(texture);
public function AvatarEnemy()
{
image.x = 0;
image.y = 200;
addChild(image);
}
}
}
UPDATE
I resolved why the sprite was disappearing - I needed to put the starling initialize code (mStarling.start() and mStarling = new Starling(Game, stage);) above all the stage.something lines. I edited code to reflect what I did in Startup.as. I still need help with the cursor though.

I have been practicing with your code and it all seems fine, but ive been using a different image, so that must be the problem.
Make sure the size of the image is below 32x32, thats the max size of an cursor image, otherwise the OS won't accept it.

Related

Add your Stage in a ScrollWindow ActionScript 3.0

I'm gonna try explaining my situation with images, to make sure that everyone will understand what i want to succeed.
First of all i have 3 files:
GenImage.fla which is linked to class GeneralImage.as
and it only contains the following picture (I tried to make the image Movie Clip but again it's not working):
Pic1
and a file named ScrollUI.as which contains the class ScrollUI.
What i want to succeed is from my GeneralImage class to create a ScrollUi item, pass the stage, and there create a ScrollPane which makes the picture look like this:
Pic2
The center part of the second image is the ScrollPane Component, which i need to make it Scrollable through the whole image. I managed to get it in my screen but i can't put the Stage in it and make it scrollable.
These are my codes :
GeneralImage.as
package {
import flash.display.*;
import flash.events.*;
import flash.display.Stage;
import ScrollUI;
public class GeneralImage extends MovieClip
{
public function GeneralImage()
{
var k = new ScrollUI();
k.ScrollConstructor(this);
}
}
}
ScrollUI.as
package
{
import flash.display.*;
import flash.events.*;
import fl.containers.ScrollPane;
import fl.events.ScrollEvent;
import fl.controls.ScrollPolicy;
public class ScrollUI extends MovieClip
{
private var _mainStage:Stage;
var aBox:MovieClip = new MovieClip();
var aSp:ScrollPane = new ScrollPane();
public function ScrollUI()
{
}
function ScrollConstructor(stage:Object):void
{
_mainStage = (stage as MovieClip).stage;
aBox == stage as MovieClip;
aSp.source == aBox ;
_mainStage.addChild(aBox);
aSp.setSize(300,300);
aSp.move(150, 75);
aSp.scrollDrag = true;
aSp.horizontalScrollPolicy=ScrollPolicy.OFF;
_mainStage.addChild(aSp);
}
}
}
So what i want it to set the Source of the Scroll Pane ( which is named aSp ) to be the _mainStage which is the stage i get from GeneralImage
Your issues is likely these two lines:
aBox == stage as MovieClip;
aSp.source == aBox ;
You're doing a comparison by using two ==, which effectively does nothing in your case. Use a single = to assign a value.
This is how I would suggest you approach this:
In the FlashPro library, find your image asset (I'm going to assume you have it wrapped in a MovieClip), right-click (or command click) and go to it's properties. Check the "export for actionscript" box, and give it a meaningful class name (for my example, I'll assume you called it MyImage)
Then you could do the following:
ScrollUI Class
package
{
import flash.display.Sprite;
import fl.containers.ScrollPane;
import fl.events.ScrollEvent;
import fl.controls.ScrollPolicy;
public class ScrollUI extends Sprite
{
//just declare the variables here, don't assign them new values
private var aBox:MovieClip;
private var aSp:ScrollPane;
public function ScrollUI()
{
//use the actual constructor...
aSp = new ScrollPane(); //instantiate a new scroll pane
addChild(aSp); //add the scroll pane to the display
aBox = new MyImage(); //instantiate an new MyImage from the library
//set the scroll pane properties
aSp.source = aBox; //you had two = signs here before, which doesn't actually assign anything it compares
aSp.setSize(300,300);
aSp.move(150, 75);
aSp.scrollDrag = true;
aSp.horizontalScrollPolicy=ScrollPolicy.OFF;
}
}
}
Document Class
package {
import ScrollUI;
public class GeneralImage extends MovieClip
{
public function GeneralImage()
{
var k:ScrollUI = new ScrollUI(); //create a new instance of the ScrollUI class
addChild(k); //add the scrollUI object to the display;
//OR, you just do this:
//addChild(new ScrollUI());
}
}
}
You could also just set the .source property of the scroll pane to the physical path of your image.
I found the solution, Thanks Batman for his help, I changes some things into my code and the program is working.
First of all as Batman said , In my GenImage.fla i made the logo a MovieClip and i named it "wholemap"
Here are my codes :
GeneralImage.as
package {
import flash.display.*;
import flash.events.*;
import flash.display.Stage;
import ScrollUI;
public class GeneralImage extends MovieClip
{
//as Batman indicated, I should have used the ScrollUI constructor, but
//except for the Stage, i also send the wholemap that is in my GenImage.fla
//<< this.getChildByName("wholemap") as MovieClip) >>
public function GeneralImage()
{
var k = new ScrollUI(this, this.getChildByName("wholemap") as MovieClip);
}
}
}
ScrollUI.as
package
{
import flash.display.*;
import flash.events.*;
import fl.containers.ScrollPane;
import fl.events.ScrollEvent;
import fl.controls.ScrollPolicy;
public class ScrollUI extends MovieClip
{
private var _mainStage:Stage;
var aBox:MovieClip = new MovieClip();
//So our constructor gets 2 items, a Stage, and a MovieClip
public function ScrollUI(stage:Object, pic:MovieClip)
{
//We set the Stage at the variable _mainStage with that way:
_mainStage = (stage as MovieClip).stage;
//We set the Image that we will take at our clip variable :
var clip:MovieClip = pic;
//And we send the Movieclip (clip) in our ScrollConstructor function
ScrollConstructor(clip);
}
function ScrollConstructor(Clip:MovieClip):void
{
var aSp:ScrollPane = new ScrollPane();
aBox = Clip;
_mainStage.addChild(aBox);
aSp.source = aBox ;
aSp.setSize(300,300);
aSp.move(150, 75);
aSp.scrollDrag = true;
aSp.horizontalScrollPolicy=ScrollPolicy.OFF;
aSp.verticalScrollPolicy=ScrollPolicy.OFF;
_mainStage.addChild(aSp);
}
}
}
Thank you very much for your assistance, I hope if someone else come across with this problem to be able to solve it with this Answer

AS3 - How to get current scene name in class

I'm playing around with flash, and I've created multiple scenes for things like menu's, buttons, etc. When trying to add event handlers for buttons that are in one scene, but not others, the compiler complains saying that it can't reference to objects that don't exist.
I figured the solution to be simple... Get the scene name, match that against an if statement and load the event handlers through the if statements...
However, after digging around on the net for far too long, I just can't seem to find a way to do this properly. Does anyone know a way?
I've tried using the following :
var scene:Scene = myflvandclassname.currentScene;
var sName:String = MovieClip.currentScene.name;
Both lead to an error "Access of possibly undefined property Scene through a reference with static type Class".
Omit MovieClip and scenes as source for organising your project, and code on the timeline. Use Document class as entry point. This tutorial should help you to grasp main concept.
package {
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.events.Event;
public class StackOverflow extends Sprite {
public function StackOverflow() {
addEventListener(Event.ADDED_TO_STAGE, onAdded);
}
private function onAdded(e:Event):void {
removeEventListener(Event.ADDED_TO_STAGE, onAdded);
stage.align = StageAlign.TOP_LEFT;
stage.scaleMode = StageScaleMode.NO_SCALE;
setup();
}
private function setup():void {
const padding:int = 20;
//Initiate your UI components and place them in the display list
var menu:MyMenu = new MyMenu();
var buttons:MyFooterButtons = new MyFooterButtons();
var etc:AnotherComponent = new AnotherComponent();
addChild(menu);
addChild(buttons);
addChild(etc);
menu.x = menu.y = padding;
//Place them and initialise with concrete information
}
}
}
For example, MyMenu, MyFooterButtons, AnotherComponent could be MovieClip/Sprite in the library with export settings, where you did all your work with placement, styling, etc
I had a same problem. I wanted to check from an external Class the current scene name and depending on the name (name of the game level) to pass some values in some attributes… So what I did and it worked is that.
//main in 1st frame of the fla
stop();
var myCheckSceneClass: CheckSceneClass = new CheckSceneClass();
myCheckSceneClass.myCurrentScene = currentScene;
myCheckSceneClass.checkScene();
//CheckSceneClass
package {
import flash.events.MouseEvent;
import flash.display.MovieClip;
import flash.display.Scene;
public class CheckSceneClass extends flash.display.MovieClip {
public var myCurrentScene : Scene;
public function CheckSceneClass () {
}
public function checkScene() {
switch (myCurrentScene.name) {
case "Scene 1":
trace("It is the 1st Scene");
break;
default:
trace("Error with Scene Name");
break;
}
}
}
}

Actionscript 3.0 method keeps repeating, cant figure out why

I'm having difficulty debugging my audio slider. I'm pretty sure my problems lies in the fact that one of my methods, changeVolumeRedFireball is just constantly repeating at a very fast rate. I get a glitchy sound every once in a while in my game, so it seems to correlate. I traced "output" inside the method and quickly found out it's repeating at a high rate.
Problem is, I cannot figure out WHERE this is coming from! One other note. This only starts repeating once I hold down my slider, hence activating the changeVolumeRedFireball from dragSliderRedFireball
I do have other methods from other classes referencing methods in this class. They only access playSoundRedFireball and stopSoundRedFireball though, so I don't see why that would have any effect. Also, this class is instantiated by my document class upon start up of the game. I suppose I'll put in the relevant code from the document class if requested, but I just didn't think it would affect this problem at all.
package {
import flash.display.Sprite;
import flash.display.Graphics;
import flash.events.MouseEvent;
import flash.events.Event;
import flash.net.URLRequest;
import flash.media.Sound;
import flash.media.SoundChannel;
import flash.media.SoundTransform;
import flash.geom.Rectangle;
public class VolumeRedFireball extends Sprite {
public var redFireballSnd:Sound = new Sound();
public var redFireballChannel:SoundChannel = new SoundChannel();
//URLRequest=new URLRequest("solitude.wav");
//Make sure you pass URLRequest an audio file on your computer.
public var reqRedFireball:EnemyAppearSound = new EnemyAppearSound();
public var boundaryRedFireball:Rectangle;
public var spriteRedFireball:Sprite;
public var sliderRedFireball:Sprite;
public var xPosRedFireball:Number;
public var yPosRedFireball:Number;
public static var volRedFireball:Number = 1;
public function VolumeRedFireball() {
this.addEventListener(Event.ADDED_TO_STAGE, onStageRedFireball,false,0,true);
volRedFireball=1;
redFireballChannel.soundTransform=new SoundTransform(volRedFireball)
}
public function onStageRedFireball(e:Event):void
{
//We remove it immediately so that it doesn't get called multiple times
//As the instance is added to the display list tree
this.removeEventListener(Event.ADDED_TO_STAGE, onStageRedFireball);
xPosRedFireball = 320;
yPosRedFireball = 170;
initRedFireball();
}
public function initRedFireball():void {
spriteRedFireball = new Sprite();
redFireballChannel.stop();
spriteRedFireball.graphics.beginFill(0x999999);
spriteRedFireball.graphics.drawRect(xPosRedFireball,yPosRedFireball,100,5);
spriteRedFireball.graphics.endFill();
addChild(spriteRedFireball);
spriteRedFireball.x-=spriteRedFireball.width/2;
sliderRedFireball = new Sprite();
sliderRedFireball.graphics.beginFill(0xFF0000);
sliderRedFireball.graphics.drawCircle(xPosRedFireball+50,yPosRedFireball, 15);
sliderRedFireball.graphics.endFill();
addChild(sliderRedFireball);
sliderRedFireball.addEventListener(MouseEvent.MOUSE_DOWN, dragsliderRedFireball);
stage.addEventListener(MouseEvent.MOUSE_UP, stopsliderRedFireball);
boundaryRedFireball=new Rectangle(-100,0,100,0);
}
public function dragsliderRedFireball(event:MouseEvent):void {
sliderRedFireball.startDrag(false,boundaryRedFireball);
sliderRedFireball.removeEventListener(MouseEvent.CLICK, dragsliderRedFireball);
sliderRedFireball.addEventListener(Event.ENTER_FRAME, changeVolumeRedFireball);
}
public function stopsliderRedFireball(event:MouseEvent):void {
sliderRedFireball.stopDrag();
sliderRedFireball.removeEventListener(MouseEvent.MOUSE_UP, stopsliderRedFireball);
}
public function changeVolumeRedFireball(event:Event):void {
volRedFireball=1+Math.round(sliderRedFireball.x)/100;
redFireballChannel.soundTransform=new SoundTransform(volRedFireball);
trace("output");
}
public function playSoundRedFireball():void
{
redFireballChannel = reqRedFireball.play();
}
public function stopSoundRedFireball():void
{
redFireballChannel.stop();
}
}
}
Changing a SoundTransform during every frame isn't good, as you are essentially undermining the audio channel. It's better if you use MouseEvent.MOUSE_MOVE to trigger volume change, as if mouse is moved, and volume slider is being dragged, then the SWF user apparently wants the volume to change. But if a user starts dragging the slider but does not move it, why changing the volume?
public function dragsliderRedFireball(event:MouseEvent):void {
sliderRedFireball.startDrag(false,boundaryRedFireball);
sliderRedFireball.removeEventListener(MouseEvent.MOUSE_DOWN, dragsliderRedFireball);
sliderRedFireball.addEventListener(MouseEvent.MOUSE_MOVE, changeVolumeRedFireball);
sliderRedFireball.removeEventListener(MouseEvent.MOUSE_UP, stopsliderRedFireball);
}
public function stopsliderRedFireball(event:MouseEvent):void {
sliderRedFireball.stopDrag();
sliderRedFireball.removeEventListener(MouseEvent.MOUSE_UP, stopsliderRedFireball);
sliderRedFireball.removeEventListener(MouseEvent.MOUSE_MOVE, changeVolumeRedFireball);
sliderRedFireball.addEventListener(MouseEvent.MOUSE_DOWN, dragsliderRedFireball);
}
Also, you have messed up your listeners. First, you are not removing the enterframe listener after you stop dragging the fireball. Second, you are not adding a start-drag listener back after the fireball has been released. And third, in your initRedFireball you are adding stopsliderRedFireball as listener to stage, for a really strange reason, but you are attempting to remove it from sliderRedFireball. Please pay precise attention on where your listeners go, what do they listen and where do you remove them and from which objects. Misuse of an enterframe listener can build up pretty quickly, and spoil you all the fun.

Starling: Scaling vector sprite for image crops instead of scales

I've got vector sprites in an external SWF. I can draw them onto a Starling image just fine. But when I try to scale the sprite before hand, the resulting image has been cropped instead of scaled.
This works fine outside of starling with plain sprites, but I'm new to Starling so I'm sure I'm missing something basic. Any help would be appreciated. Thanks!
FlashDevelop + AIR + Starling
Main.as
package
{
import flash.display.Sprite;
import starling.core.Starling;
public class Main extends Sprite
{
private var starling:Starling;
public function Main():void
{
starling = new Starling(Game, stage);
starling.start();
}
}
}
Game.as
package
{
import flash.display.BitmapData;
import starling.display.Image;
import starling.display.Sprite;
import starling.textures.Texture;
public class Game extends Sprite
{
[Embed(source = "../assets/Sprites.swf", symbol = "Sprites_Tiger")]
private var Sprites_Tiger:Class;
public var Tiger:flash.display.Sprite = new Sprites_Tiger();
public function Game()
{
Tiger.width = 256;
Tiger.height = 256;
var bitmapdata:BitmapData = new BitmapData(Tiger.width, Tiger.height);
bitmapdata.draw(Tiger);
var texture:Texture = Texture.fromBitmapData(bitmapdata);
var image:Image = new Image(texture);
addChild(image);
}
}
}
EDIT: I found a work-around by adding a scale matrix to the bitmapdata.draw. But I still don't know why the scaling is converted to cropping without it.
I think i remember similar issue in my last project , try this solution:
bitmapdata.draw(Tiger, Tiger.transform.matrix);

Custom button with image

Hi i'm trying to create a button in actionscript 3 that will be made by a custom image ( a car.jpg from my HDD ). Is it possible to do that with SimpleButton class ( i mean is there a way to load the image and attach it to the button ?) or is there another way?
If i would like to have animation also in the button when let's say i roll over the mouse pointer from the button what do i have to do?
ps: i would like to use only actionscript 3 ( i mean all the project is done as a .as file that is linked to Document class ).
Although George Profenza already pointed the best solution under the comment if feel curious how you could implement the SimpleButton class you might want to take a look into th as3 document reference examples:
adobe livedocs - SimpleButton Example
I have also wrote a simple example that only makes a "simple button" in a "complicated button" but makes use of SimpleButton class, so you can take a look how you can extend the class, and give to each state it's own graphic. Here is the code:
// this goes in your app
var button:MySimpleButton = new MySimpleButton();
addChild(button);
MySimpleButton.as
package
{
import flash.display.DisplayObject;
import flash.display.SimpleButton;
import flash.display.Sprite;
public class MySimpleButton extends SimpleButton
{
private var upAlpha : Number = 1;
private var overAlpha : Number = 0.5;
public function MySimpleButton(upState : DisplayObject = null, overState : DisplayObject = null, downState : DisplayObject = null, hitTestState : DisplayObject = null)
{
upState = new ButtonImgDisplayState( upAlpha);
overState = new ButtonImgDisplayState( overAlpha);
downState = new ButtonImgDisplayState( upAlpha);
hitTestState = new ButtonImgDisplayState( upAlpha);
super(upState, overState, downState, hitTestState);
}
}
}
ButtonImgDisplayState.as
package
{
import flash.display.Loader;
import flash.display.Sprite;
import flash.net.URLRequest;
public class ButtonImgDisplayState extends Sprite
{
public function ButtonImgDisplayState(_alpha:Number)
{
var my_loader : Loader = new Loader();
my_loader.load(new URLRequest("car.jpg"));
addChild(my_loader);
this.alpha = _alpha;
}
}
}
The thing about the SimpleButton is to spare you to set listeners, but you are obligated to go around the states that are separated DisplayObjects making you button a more rigid thing when dealing with transitions between states.
Hope you find this useful.