John's Epic Megathread Of Confusion & Tomfoolery


(John Andersson) #1

Hi.

I wanna make it so that when I touch a weapon with my hero, he picks it up. I’ve gone back and forth on how to do this, and I even made a topic called “Colliding with a TYPE, make that TYPE run a function? [SOLVED]”, but that only covers while it is actually colliding.

I want to make it so that if it collides once, then it runs a function forever.

I have this in my hero:

private var weapon:Weapons = new Weapons();
public static var isHoldingWeapon:Boolean = false;

and then in his update code:

			if (isHoldingWeapon == true)
		{
			weapon.updatePosition(wepHotspotX, wepHotspotY);
		}

And then in the weapon on the stage:

public function Weapon_Sword(xt:Number, yt:Number) 
	{
		layer = 1;

		x = xt;
		y = yt;

		setHitbox(112, 112);
		
		sprSword.add("idle", [], 0, false);
		sprSword.add("attack", [0, 1, 2, 3], 20, false);
		
		graphic = sprSword;
		
		Input.define("Attack", Key.X);
		_held = false;
	}
	
	override public function update():void 
	{
		if (!_held)
		{
			var hero:Hero = Hero(collide("hero", x, y));

			if (hero != null)
			{
				Hero.isHoldingWeapon = true;
				_held = true;
			}
		}
		
		super.update();
	}
	
	override public function updatePosition(wepx:Number, wepy:Number):void
	{
		if (Hero.isFacingLeft)
		{
			x = wepx - 200;
			sprSword.flipped = true;
		}
		else
		{
			x = wepx;
			sprSword.flipped = false;
		}
		
		this.y = wepy;

		//Attack
		if (Input.pressed("Attack")) 
		{
			if (HeroStats.currentStamina == HeroStats.stamina)
			{
				HeroStats.currentStamina = 0;
				attacking = true;
			}
		}
		
		if (attacking)
		{
			sprSword.play("attack");
			var enemy:Enemies = collide("enemy", x, y) as Enemies;
			
			if (enemy) enemy.takeDamage(damage);
		}
		
		if (sprSword.currentAnim == "attack")
		{
			if (sprSword.index == 3)
			{
				attacking = false;
				sprSword.play("idle");
			}
		}
	}

And here is the weapons class:

public class Weapons extends Entity 
{
	
	public function Weapons(x:Number=0, y:Number=0, graphic:Graphic=null, mask:Mask=null) 
	{
		super(x, y, graphic, mask);	
		
		type = "weapon"
	}
	
	public function updatePosition(wepx:Number, wepy:Number):void
	{
		
	}
	
	public function dealDamage(damageTaken:Number):void
	{
		
	}
}

If I change the hero update code to this:

var weaponhold:Weapons = collide("weapon", x, y) as Weapons;
if(wepaonhold)
{
    weaponhold.updatePosition(blablabla)
}

Then it works, but then sometimes the hero “drops” the weapon if I move too fast. Which means it isn’t a viable option.

Thanks


Flash Develop - Build Failed [SOLVED]
(Ultima2876) #3

Make a class variable called ‘holdingWeapon’, of type Weapons. Only set this the first time the weapon collides in your Hero update function;

var weaponCollide: Weapons = collide("weapon", x, y) as Weapons;
if(weaponCollide != null && holdingWeapon == null)
{
  //only do this the first time
  holdingWeapon = weaponCollide; //set the weapon to be held
}

//now use the holdingWeapon to update position, call functions etc
if(holdingWeapon != null)
{
  holdingWeapon.x = this.x + 30; //blah blah
  myFunkyTion();
}

(John Andersson) #4

You mean

"public var holdingWeapon:Class;" 

in the Weapons.as class?

Do you also know how to make it so that the sword doesn’t “follow” the hero. It’s as if when I run with the hero, the sword is a bit behind. Only when I stop, is the sword in the hand properly. Otherwise it “catches” up whilst running


(Jacob Albano) #5

I think he meant a member variable; i.e. one that persists across frames, not a variable of type Class.

public class Hero // ...
{
    private var holdingWeapon:Weapons;
    //  ...
}


(John Andersson) #6

Okay thanks, it works! But the “floating behind” still is a problem. I think it might have to do with the hero positioning code.

I have this at the end of the hero code.

adjustXPosition(); adjustYPosition();

private function adjustXPosition():void { //Perception speed var perception_speed:Number = speed * 0.25;

		//If not in dark
		if (5 != 4)	finalSpeed = xSpeed + (speed / 10);

		//If in dark
		if (agility_perception_active && 5 == 4) finalSpeed = (xSpeed * 0.25) + (speed / 10)
		
		for (var i:int=0; i<Math.abs(xSpeed); i++) {
            if (! collide("ground",x+FP.sign(finalSpeed),y)) {
                x+=FP.sign(xSpeed);
            } else {
                xSpeed=0;
                break;
            }
        }
	}
	
	private function adjustYPosition():void {
		for (var i:int=0; i<Math.abs(ySpeed); i++) {
			if (! collide("ground",x,y+FP.sign(ySpeed))) {
				y+=FP.sign(ySpeed);
			} else {
				ySpeed=0;
				break;
			}
		}
	}

How should I insert the weapon holding code into this? :stuck_out_tongue: thanks


(Ultima2876) #7

Sorry, I’m an old schooler and we used to call 'em class variables before all this newfangled member and method stuff came along :slight_smile:


(Jacob Albano) #8

I use them interchangeably, but in this case it was a wee bit confusing. :stuck_out_tongue:


(John Andersson) #9

Can you help me with the floating problem? :stuck_out_tongue:


(azrafe7) #10

As hinted by someone in one of your other topics (which I can’t track down right now), the weapon lagging behind the player is probably an issue of updating/rendering order.

Ideally what you want to happen is:

  1. Update player position
  2. Update weapon position
  3. Render player
  4. Render weapon

So you should recheck your code and ensure that your weapon updating code runs after the player one (in FlashDevelop you can set some breakpoints in the relevant update() functions and step through code from there).

(We seriously need a sticky tutorial/link for some basic/intermediate debugging with FlashDevelop, it would really help!.. in the meanwhile you can consult Google if you don’t know how to do it, or insert traces to find out what the order is)

Also… your adjust_() functions seem to do exactly what moveBy() in combination with moveCollide_() do. So you could replace them with something like:

override public function update():void
{
  moveBy(xSpeed, ySpeed, "ground", true);
}

override public function moveCollideX(e:Entity):Boolean
{
  xSpeed = 0;
  return true;
}

override public function moveCollideY(e:Entity):Boolean
{
  ySpeed = 0;
  return true;
}

This would basically translate to:

  1. Try to move player by xSpeed and ySpeed (1 pixel at a time specified by the true param) and watch out for collisions with “ground”
  2. If collides horizontally with “ground” moveCollideX() gets called and you reset the xSpeed
  3. If collides vertically with “ground” moveCollideY() gets called and you reset the ySpeed

(Jacob Albano) #11

You can also position the weapon in your player’s update() function instead of its own.


(billy2000) #12

As far as i can see in your code after your weapon collide once with the player, it will collide every time with it. In this case u can take advantage of moveCollideX (or Y) like this:

override public function moveCollideX(e:Entity):Boolean
{
  xSpeed = 0;

 if(e.type=="TheSpecificWeapon"){
   e.x=x;
   e.y=y;
 }

 return true;
}

or you can even do something like this also in Hero’s class:

var Weap_:YourWeapon = collide("TheSpecificWeapon", x, y) as YourWeapon;
Weap_.x=x;
Weap_.y=y;

(John Andersson) #13

Oh. My. God.

I found the real reason why it didn’t work -.-

Instead of typing

				if (sprHero.index == 0 || sprHero.index == 3)
					{
						wepHotspotY = y - 24; 
						helmetHotspotY = y - 24;
					}

I had typed

				if (sprHero.index == 0 || sprHero.index == 3)
					{
						wepHotspotY = yPos - 24; 
						helmetHotspotY = yPos - 24;
					}

yPos was the problem here. Since it updated before ANYTHING else.

Thank you all so much. This has been a nightmare, but thanks to you all, I can finally say FAKA YU paperdorring


(John Andersson) #14

OKAY. So it’s ALMOST perfect now.

The problem is that it’s a millisecond (or so, dunno) behind, so you can BARELY see the hero’s bald head before the helmet follows along. It’s 100x better than before, but it’s not quite perfect.

This is the current code:

private function adjustXPosition():void { //Perception speed var perception_speed:Number = speed * 0.25;

		//If not in dark
		if (5 != 4)	finalSpeed = xSpeed + (speed / 10);

		//If in dark
		if (agility_perception_active && 5 == 4) finalSpeed = (xSpeed * 0.25) + (speed / 10)
		
		for (var i:int = 0; i < Math.abs(xSpeed); i++) 
		{
            if (! collide("ground", x + FP.sign(finalSpeed), y)) 
			{
                x+=FP.sign(xSpeed);
            } 
			else 
			{
                xSpeed=0;
                break;
            }
        }
		
		wepHotspotX = x + 104;
		helmetHotspotX = x + 8;
		
		if(holdingWeapon != null)
		{
			if (sprHero.flipped)
			{
				holdingWeapon.flipped = true;
				wepHotspotX = x - 96;
			}
			else holdingWeapon.flipped = false;
			
			holdingWeapon.x = wepHotspotX; 
		}	
		
		if(equippedHelmet != null)
		{
			if (sprHero.flipped)
			{
				equippedHelmet.flipped = true;
				helmetHotspotX = x + 16;
			}
			else equippedHelmet.flipped = false;
			
			equippedHelmet.x = helmetHotspotX; 
		}	
	}
	
	private function adjustYPosition():void 
	{						
		for (var i:int = 0; i < Math.abs(ySpeed); i++) 
		{
			if (! collide("ground", x, y + FP.sign(ySpeed))) 
			{
				y+=FP.sign(ySpeed);
			} 
			else 
			{
				ySpeed=0;
				break;
			}
		}
		
				//Change weapon hotspots, depending on the frame/animation
				if (sprHero.currentAnim == "run")
				{
					if (sprHero.index == 0)
					{
						helmetHotspotY = y - 24;
						wepHotspotY = y - 24; 
					}
					if (sprHero.index == 1)
					{
						helmetHotspotY = y - 32;
						wepHotspotY = y - 32; 
					}
					if (sprHero.index == 2)
					{
						helmetHotspotY = y - 32;
						wepHotspotY = y - 32;
					}
					if (sprHero.index == 3)
					{
						helmetHotspotY = y - 24;
						wepHotspotY = y - 16;
					}
					if (sprHero.index == 4)
					{
						helmetHotspotY = y - 16;
						wepHotspotY = y - 16;
					}
				}
				
				if (sprHero.currentAnim == "stand")
				{
					if (sprHero.index == 0) 
					{
						wepHotspotY = y - 24; 
						helmetHotspotY = y - 24;
					}
				}
				
				if (sprHero.currentAnim == "jump")
				{
					wepHotspotY = y - 24;
					helmetHotspotY = y - 24;
				}
				
		if(holdingWeapon != null)
		{
			holdingWeapon.y = wepHotspotY;
		}
		
		if(equippedHelmet != null)
		{
			equippedHelmet.y = helmetHotspotY;
		}
		
							
				trace("Hero: " + sprHero.index)
		
	}

Now how am I supposed to make it 100% perfect? The problem only appears whilst running with the hero, where the hero bounces up and down.


(John Andersson) #15

Hey man…

the current code (I temporarily changed it to follow the “ideal” coding way)

Update player position 
Update weapon position
Render player
Render weapon```


			//Adjust positions
			 moveBy(xSpeed, ySpeed, "ground", true);
			 adjustArmorPosition();
			 
			 //Render
			 renderHero();
			 renderEquipment();

And here is the actual code:

                 override public function moveCollideX(e:Entity):Boolean
		{
			 xSpeed = 0;
			 return true;
		}
		
		override public function moveCollideY(e:Entity):Boolean
		{
			 ySpeed = 0;
			 return true;
		}
		
		private function adjustArmorPosition():void
		{
                        //Blabla, x values and stuff
if(holdingWeapon != null)
			{
				holdingWeapon.y = wepHotspotY;
			}
			
			if(equippedHelmet != null)
			{
				equippedHelmet.y = helmetHotspotY;
			}
			
			if(equippedGloves != null)
			{
				equippedGloves.x = x;
				equippedGloves.y = y;
			}
			
			if(equippedPants != null)
			{
				equippedPants.x = x;
				equippedPants.y = y;
			}
			
			if(equippedChest != null)
			{
				equippedChest.x = x;
				equippedChest.y = y;
			}
               }

		private function renderHero():void
		{
			if (Input.check("Left") || Input.check("Right")) sprHero.play("run");
		}
		
		private function renderEquipment():void
		{
			var dwarflet_:Goldstruck_Pants = world.getInstance("goldenpants");
			var dwarflets_:Goldstruck_Chest = world.getInstance("goldenchest");
			
			if(equippedPants != null) dwarflet_.spritemap.play(sprHero.currentAnim);
			if(equippedChest != null) dwarflets_.spritemap.play(sprHero.currentAnim);
		}

Yet it doesn't really work. I can see glimpses of the hero, it's really fast, but I can still see the original hero sprite, since it moves just a bit faster than the armor. Sometimes.

If I pause the game, sometimes I can see that the hero sprite has updated before the armor sprite, resulting in a visual situation of two different sprite animations.

How do I make it so that they update at the same time? I want it to be perfect, like in pretty much every game paperdolling occurs.

Thanks :p

Animating/Moving CHANGEABLE weapons/armor through code? (equipping items) - PAPERDOLLING -
(John Andersson) #16

If I slow down the fps to 1, then I can clearly see that the hero’s sprite always moves one step ahead.


(billy2000) #17

I always had those problems too be4, now when i do this kind of stuff i usually add a new graphic to player.What i would suggest(if you can make this change) is to make a graphiclist in player class,and when he pick up a piece of armor just add it to his graphiclist .If you can do that this problem would be pretty much solved.


(John Andersson) #18

Hmm, that sounds interesting. But I don’t understand the logic. is there any good example you can show me??


(billy2000) #19
public class Hero extends Entity 
{
	private var theGraphic:Graphiclist = new Graphiclist();
	private var heroMap:Spritemap = new Spritemap(HERO, width, height);
	private var armorMap:Spritemap = new Spritemap(ARMOR, width, height);
	private var anim:String = "something";
	
	public function Hero(x:Number, y:Number) 
	{
		this.x = x;
		this.y = y;
		//spritemaps animations and other stuff
		
		graphic = theGraphic;
		theGraphic.add(heroMap);
		
	}
	override public function update():void
	{
		super.update();
		
		//if he collide with the armor on the ground
		if (collide("armor", x, y)) {
			//do something here as example remove the armor on the ground entity
			theGraphic.add(armorMap);
			//now armorMap is part of heros graphic
		}
	}
}

Something like this :smiley:


(John Andersson) #20

Okay nice :smiley: But how would I animate the armor and hero (at the same time, I guess?) with a graphicslist? :smiley:


(billy2000) #21

if u have the graphics stored in a graphic list its pretty much the same as having 1 graphic.So just play your hero spritemap like usually, and with the same animation play the armor animation(if hero has armor equipped).