Multiple graphic components as public property to render on screen?


(christopf) #1

Hi there Flashpunk community. I’ve already read some threads that sounded kinda the problem i have. also i did some duckduck search for tutorials and maybe solutions but now hours past and i didnt find a way to clear this + im absolute beginner in programming so please have clemency

so my problem is, i would like to put 2 different spritemaps as an entitys graphic property. is there any way?

( my original problem is that i have different moving animations for a entity that depending on which was the last moving animation plays a differnt stopanimation - i guess there is another way around too )


(Bora Kasap) #2

First, you should add your first spritemap by normal ways, Then, for other spritemap, you should create another spritmap variable, then assign your other spritemap file to this variable, then use addGraphic function in entity to add this spritemap variable to your entity’s graphic… i’ven’t used addGraphic before, but you should try it out…

Also, i think the orginal problem you said at the end of your post is not going to be solved with answers of the question you asked in this post. i think… they are different problems… (you don’t need to assing another spritemap to solve your this(orginal) problem, you can put your different stop animations in 1 spritemap file, then just need to check animation index while playing and you need to skip animation index with wished conditions etc., take a look about “spritemap.index”, “spritemap.complete”, “spritemap.frame”)


(christopf) #3

I was just answering your first reply when you updated it (: The direction you gave me first kinda worked and on the other side didnt. but made me think of hitboxes that may solve the problem with the different sizes in the spritesheet.

but what you now mentioned about spritemap.index and friends looks interesting too. maybe this is the more elegant version? i’m pretty tired by now it after midnight here and i guess i get some sleep. i try it tomorrow. thanks anyway so far!


(Ssnyder Coder) #4

Use a Graphiclist which can contain multiple Graphic objects. Set your entity’s graphic to that and add your spritemaps to the Graphiclist. Just keep references to the separate spritesheets and you can modify them independently as you wish. Here’s an example:

package 
{
   //imports not included
   
   public class Hulk extends Entity 
   {
      private var manSprite:Spritemap;
      private var hulkSprite:Spritemap;
      private var anger:int;
      
      public function Hulk(x:Number, y:Number)
      {
        this.x = x;
        this.y = y;
        this.anger = 0;
        this.manSprite = new Spritemap(Assets.MAN, 32, 32);
        this.hulkSprite = new Spritemap(Assets.HULK, 32, 32);
        this.graphic = new Graphiclist(manSprite, hulkSprite);
        appearAsMan();
      }
     
      override public function update():void 
      {
        super.update();
        if(manSprite.visible && anger > 9000) appearAsHulk();
        else if(hulkSprite.visible && anger < 100) appearAsMan();
      }
     
      private function appearAsMan():void 
      {
        hulkSprite.visible = false;
        manSprite.visible = true;
        manSprite.play("transform");
      }
     
      private function appearAsHulk():void 
      {
        manSprite.visible = false;
        hulkSprite.visible = true;
        hulkSprite.play("transform");
      }
   }
}

(Jacob Albano) #5

Worth noting: the addGraphic() function automatically sets the Entity’s graphic to a new Graphiclist, and adds the existing graphic if there is one set.


(christopf) #6

Thanks alot for this. It looks pretty logic and its very educational. But i was wondering whats with that “this” in the public function?

Also i think the way with the one spritesheet is much more comfortable for me in this particular. im not so sure about the memory usage if that may cause unnecessary delays since thats my second project (first were the tutorials from here). but i think i can use this for the switch between walking and running i will try to figure it out on my own so my brain doesnt get to rusty and habituate on asking for every problems solution in here ;D

to make my step to the one spritesheet clear i post my code (i’ve got from another extern tutorial) i think its more comfortable because i need the switch to the standing sprites if the entity is stop running

package
{ // import not included

public class Hero extends Entity
{
	[Embed(source="../assets/sprGehen.png")]private const sprMoriGehen:Class;
	
	public var MoriGehen:Spritemap = new Spritemap(sprMoriGehen, 31, 56);
	
	public var curAnimation:String = "MstehtS";
	public var speedGehen:Number = 30;		
	
	public function Hero() 
	{
		setupSpritesheet();
		
		graphic = MoriGehen;
		
		type = "mori";
		
		Input.define("MoveLeft", Key.A, Key.LEFT);
		Input.define("MoveUp", Key.W, Key.UP);
		Input.define("MoveDown", Key.S, Key.DOWN);
		Input.define("MoveRight", Key.D, Key.RIGHT);
	}
	
	override public function update():void
	{
		var horizontalBewegung:Boolean = true;
		var verticalBewegung:Boolean = true;
		
		MoriGehen.play(curAnimation);
		
		if (Input.check("MoveLeft"))
		{
			x -= speedGehen * FP.elapsed;
			curAnimation = "MgehtW";
		}
		else if (Input.check("MoveRight"))
		{
			x += speedGehen * FP.elapsed;
			curAnimation = "MgehtO";
		}
		else horizontalBewegung = false;
		
		
		if (Input.check("MoveUp"))
		{
			y -= speedGehen * FP.elapsed;
			curAnimation = "MgehtN";
		}
		else if (Input.check("MoveDown"))
		{
			y += speedGehen * FP.elapsed;
			curAnimation = "MgehtS";
		}
		else verticalBewegung = false;
		
		
		if ((!verticalBewegung) && (!horizontalBewegung))
		{
			switch(curAnimation)
			{
				case "MgehtN": curAnimation = "MstehtN"; break;
				case "MgehtS": curAnimation = "MstehtS"; break;
				case "MgehtW": curAnimation = "MstehtW"; break;
				case "MgehtO": curAnimation = "MstehtO"; break;
			}
		}
		
	}
	
	private function setupSpritesheet():void
	{
		MoriGehen.add("MstehtN", [0], 0, false);
		MoriGehen.add("MgehtN", [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], 16, true);
		MoriGehen.add("MstehtS", [17], 0, false);
		MoriGehen.add("MgehtS", [18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33], 16, true);
		MoriGehen.add("MstehtW", [34], 0 , false);
		MoriGehen.add("MgehtW", [35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50], 16, true);
		MoriGehen.add("MstehtO", [51], 0, false);
		MoriGehen.add("MgehtO", [52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67], 16, true);
	}
	
}

}


(Ssnyder Coder) #7

Thanks alot for this. It looks pretty logic and its very educational. But i was wondering whats with that “this” in the public function?

The “this” just identifies the variables as belonging to Hulk class. I actually only needed to do that for the x and y variables since the constructor parameters have the same names, but I guess I got a bit carried away.


(Rick) #8

Was just reading through your code and have always had a question about how efficient this means is. In your code you put the update function to constantly update appearAs___() and so on every frame it will update the play methods. Would it be better to throw in a Boolean to let it know that it shouldn’t continuously call the play function or is that required for it to keep playing?

It’s something that I’m constantly asking myself, so any tips would be great! Thanks! -DerangedMind


(azrafe7) #9

If you look at the code in Spritemap.as you can see that it exits early if the same animation is already playing, so the overhead is quite minimal:

	/**
	 * Plays an animation.
	 * @param	name		Name of the animation to play.
	 * @param	reset		If the animation should force-restart if it is already playing.
	 * @param	frame		Frame of the animation to start from, if restarted.
	 * @return	Anim object representing the played animation.
	 */
	public function play(name:String = "", reset:Boolean = false, frame:int = 0):Anim
	{
		if (!reset && _anim && _anim._name == name) return _anim;
		...

(Rick) #10

Should have just looked that up :stuck_out_tongue: Thanks for clarifying that :slight_smile:


(Ssnyder Coder) #11

If the if statements preceding the appearAs____ method calls only considered the anger variable, then yes, the sprite’s play method would be called every update. However, I included a check to make sure that the opposite sprite was visible before calling the appearAs___ method. The visibility of the two sprites would then be switched so that the other one is visible and the original one is not. Perhaps it would have been clearer with some slight changes:

override public function update():void 
  {
    super.update();
    if(anger > 9000 && !hulkSprite.visible) appearAsHulk();
    else if(anger < 100 && !manSprite.visible) appearAsMan();
  }

If that is still confusing, I suppose clarifying methods might make it more clear:

override public function update():void 
  {
    super.update();
    if(canTransformToHulk()) appearAsHulk();
    else if(canRevertToMan()) appearAsMan();
  }
  
  private function canTransformToHulk():Boolean
  {
    return anger > 9000 && !hulkSprite.visible;
  }
  
  private function canRevertToMan():Boolean
  {
    return anger < 100 && !manSprite.visible;
  }