Home Tutorials Forums Articles Blogs Movies Library Employment Press

Go Back   ActionScript.org Forums > General > Best Practices

Reply
 
Thread Tools Rate Thread Display Modes
Old 04-20-2012, 04:23 PM   #1
Eric_S
Registered User
 
Join Date: Apr 2012
Location: Florida
Posts: 6
Default [AS3] Optimization and Bad Practice Elimination

I've been following two books; Friends of ED: Foundation Game Design with Flash, and O'reilly Learning Actionscript 3.0 in order to learn how to program OOP games and apps correctly and with efficiency. I started months ago piecing together roughly 530 lines of code that animate platformer type movements smoothly and naturally. All the code does is animate a sprite's movements according to 5 keypresses.

up looks up, down ducks, left walks left, right walks right, and Z is a running key which changes the walking animations for each respective direction. I started working on the code about a year ago and put it down until recently and finished it recently. It's part of an ongoing project to make a platformer, so eventually physics will be added to this code.

I'm still consider myself a beginner with AS3 as I can only read and tweak relatively basic code. As of right now I don't know much syntax at all and I wouldn't be able to start coding, something strictly from memory, from scratch. However that is a considerable step forward from wanting others to write my code for me then just copy and pasting it in ;P.

Basically, to put an end to this wall of text, I need help not only optimizing the code, but also finding out what is being optimized and how to not make the same mistakes again. The SWF file is the first file on the list at sites(dot)google(dot)com/site/esiewertjr/flash-games. Apparently I can't post links, so you'll have to replace (dot), and the code will be in the next post, apparently I went over the character limit. ^^;
-----
Just to point out, there are unimplemented things (like physics and the timer which will be used for the idleLong animation and things that won't be there in the final product (like the status testing at the end).

I appreciate any help. And if you are an experienced coder who'd be willing to kind of be a mentor, I'd love you skype info! xD
Eric_S is offline   Reply With Quote
Old 04-20-2012, 04:27 PM   #2
Eric_S
Registered User
 
Join Date: Apr 2012
Location: Florida
Posts: 6
Default

Here's the code, and sorry for any apparent forum/coding noobishness xD. Also I removed the status test code, 'cause it's right enough for my uses and will be removed in the end anyways (and I was 474 characters over still...)

Code:
package {
	import flash.display.MovieClip;
	import flash.events.KeyboardEvent;
	import flash.ui.Keyboard;
	import flash.events.Event;
	import flash.events.TimerEvent;
	import flash.utils.Timer;

	public class CharacterMovements2 extends MovieClip {

		// Variables
		private var _isOnGround:Boolean;
		private var _bBox:MovieClip;
		// Keys
		private var _rightKeyIsDown:Boolean;
		private var _leftKeyIsDown:Boolean;
		private var _upKeyIsDown:Boolean;
		private var _downKeyIsDown:Boolean;
		private var _jumpKeyIsDown:Boolean;
		private var _runKeyIsDown:Boolean;

		private var _isMoving:Boolean;
		private var _facingRight:Boolean;
		private var _isJumping:Boolean;
		private var _isFalling:Boolean;
		private var _isLanding:Boolean;
		private var _isRunning:Boolean;
		private var _isDucking:Boolean;
		private var _isLookingUp:Boolean;
		private var _isGettingUp:Boolean;

		public function CharacterMovements2() {

			_bBox = this.boundBox;
			_rightKeyIsDown = false;
			_leftKeyIsDown = false;
			_upKeyIsDown = false;
			_downKeyIsDown = false;
			_jumpKeyIsDown = false;
			_runKeyIsDown = false;

			_isMoving = undefined;
			_facingRight = true;
			_isJumping = false;
			_isFalling = undefined;
			_isRunning = false;
			_isDucking = undefined;
			_isLookingUp = undefined;
			_isGettingUp = false;
			this.stop();
			this._bBox.visible = false;
			_isOnGround = true;

			// Event Listeners
			stage.addEventListener(KeyboardEvent.KEY_DOWN,onKeyDown);
			stage.addEventListener(KeyboardEvent.KEY_UP,onKeyUp);
			addEventListener(Event.ENTER_FRAME,onEnterFrame);
			addEventListener(Event.ENTER_FRAME,statusTest);
		}

		// onKeyDown
		private function onKeyDown(e: KeyboardEvent):void {

			if (e.keyCode == Keyboard.RIGHT)
			{
				_rightKeyIsDown = true;
				if (_isOnGround)
				{
					if (! _isDucking)
					{
						if (! _isGettingUp)
						{
							if (! _leftKeyIsDown)
							{
								_isMoving = true;
								_facingRight = true;
							}
						}
					}
				}
			}

			if (e.keyCode == Keyboard.LEFT)
			{
				_leftKeyIsDown = true;
				if (_isOnGround)
				{
					if (! _isDucking)
					{
						if (! _isGettingUp)
						{
							if (! _rightKeyIsDown)
							{
								_isMoving = true;
								_facingRight = false;
							}
						}
					}
				}
			}

			if (e.keyCode == Keyboard.UP)
			{
				_upKeyIsDown = true;
				if (_isOnGround)
				{
					if (! _isMoving)
					{
						if (! _isDucking)
						{
							if (! _isGettingUp)
							{
								_isLookingUp = true;
							}
						}
					}
				}
				else
				{
					_isLookingUp = false;
				}
			}

			if (e.keyCode == Keyboard.DOWN)
			{
				_downKeyIsDown = true;
				if (_isOnGround)
				{
					if (! _isMoving)
					{
						_isDucking = true;
						_isGettingUp = false;
						_isLookingUp = false;
					}
				}
			}

			if (e.keyCode == Keyboard.Z)
			{
				_isRunning = true;
			}

			if (e.keyCode == Keyboard.X)
			{
				if (_isOnGround)
				{
					_isJumping = true;
				}
			}
		}

		private function onKeyUp(e: KeyboardEvent):void {

			if (e.keyCode == Keyboard.RIGHT)
			{
				_rightKeyIsDown = false;
				if (_leftKeyIsDown && _isMoving)
				{
					_facingRight = false;
					_isMoving = true;
				}
				if (_upKeyIsDown)
				{
					_isLookingUp = true;
				}
				else if (! _upKeyIsDown)
				{
					_isLookingUp = false;
				}
				if (_downKeyIsDown)
				{
					_isDucking = true;
				}
				else if (! _downKeyIsDown)
				{
					_isDucking = false;
				}
				if (_isOnGround)
				{
					if (_facingRight)
					{
						_isMoving = false;
					}
				}
			}

			if (e.keyCode == Keyboard.LEFT)
			{
				_leftKeyIsDown = false;
				if (_rightKeyIsDown && _isMoving)
				{
					_facingRight = true;
					_isMoving = true;
				}
				if (_upKeyIsDown)
				{
					_isLookingUp = true;
				}
				else if (! _upKeyIsDown)
				{
					_isLookingUp = false;
				}
				if (_downKeyIsDown)
				{
					_isDucking = true;
				}
				else if (! _downKeyIsDown)
				{
					_isDucking = false;
				}
				if (_isOnGround)
				{
					if (! _facingRight)
					{
						_isMoving = false;
					}
				}
			}

			if (e.keyCode == Keyboard.UP)
			{
				_upKeyIsDown = false;
				if (_isLookingUp)
				{
					_isLookingUp = false;
				}
			}

			if (e.keyCode == Keyboard.DOWN)
			{
				_downKeyIsDown = false;
				if (_isOnGround)
				{
					_isDucking = false;
					_isGettingUp = true;
					if (_rightKeyIsDown)
					{
						_facingRight = true;
					}
					if (_leftKeyIsDown)
					{
						_facingRight = false;
					}
				}
			}

			if (e.keyCode == Keyboard.Z)
			{
				if (_isRunning)
				{
					_isRunning = false;
				}
			}

			if (e.keyCode == Keyboard.X)
			{
			}
		}

		private function onEnterFrame(e: Event):void {

			// Local Variables
			var playerHalfWidth:uint = _bBox.width / 2;
			var playerHalfHeight:uint = _bBox.height / 2;

			// Actions
			// Idle
			if (_isOnGround)
			{
				if (! _isGettingUp)
				{
					if (! _isMoving)
					{
						// if (_vx = 0)
						if (! _isLookingUp)
						{
							if (! _isDucking)
							{
								if (_facingRight)
								{
									this.gotoAndStop("IdleRight");
								}
								else if (! _facingRight)
								{
									this.gotoAndStop("IdleLeft");
								}
							}
						}
					}
				}
			}
			// Walking and Running
			if (_isMoving)
			{
				if (_facingRight)
				{
					if (! _isRunning)
					{
						this.gotoAndStop("WalkRight");
					}
					else if (_isRunning)
					{
						this.gotoAndStop("RunRight");
					}
				}
				else if (! _facingRight)
				{
					if (! _isRunning)
					{
						this.gotoAndStop("WalkLeft");
					}
					else if (_isRunning)
					{
						this.gotoAndStop("RunLeft");
					}
				}
			}
			// Ducking
			if (_isOnGround)
			{
				if (! _isMoving)
				{
					if (_isDucking)
					{
						if (_facingRight)
						{
							this.gotoAndStop("DuckRight");
							_isMoving = false;
						}
						else if (! _facingRight)
						{
							this.gotoAndStop("DuckLeft");
							_isMoving = false;
						}
					}
				}
			}
			// Getting Up From Ducking
			if (_isGettingUp && ! _isMoving)
			{
				_isDucking = false;
				_isMoving = false;
				if (_facingRight)
				{
					this.gotoAndStop("DuckUpRight");
				}
				else if (! _facingRight)
				{
					this.gotoAndStop("DuckUpLeft");
				}
			}
			if (Object(DuckUpRight).currentFrame == 6)
			{
				_isGettingUp = false;
				if (! _rightKeyIsDown && ! _leftKeyIsDown)
				{
					this.gotoAndStop("IdleRight");
					_isMoving = false;
				}
				else if (_rightKeyIsDown)
				{
					_isMoving = true;
					_facingRight = true;
					if (! _isRunning)
					{
						this.gotoAndStop("WalkRight");
					}
					else if (_isRunning)
					{
						this.gotoAndStop("RunRight");
					}
				}
				else if (_leftKeyIsDown)
				{
					_isMoving = true;
					_facingRight = false;
					if (! _isRunning)
					{
						this.gotoAndStop("WalkLeft");
					}
					else if (_isRunning)
					{
						this.gotoAndStop("RunLeft");
					}
				}
			}
			if (Object(DuckUpLeft).currentFrame == 6)
			{
				_isGettingUp = false;
				if (! _rightKeyIsDown && ! _leftKeyIsDown)
				{
					this.gotoAndStop("IdleLeft");
					_isMoving = false;
				}
				else if (_rightKeyIsDown)
				{
					_isMoving = true;
					_facingRight = true;
					if (! _isRunning)
					{
						this.gotoAndStop("WalkRight");
					}
					else if (_isRunning)
					{
						this.gotoAndStop("RunRight");
					}
				}
				else if (_leftKeyIsDown)
				{
					_isMoving = true;
					_facingRight = false;
					if (! _isRunning)
					{
						this.gotoAndStop("WalkLeft");
					}
					else if (_isRunning)
					{
						this.gotoAndStop("RunLeft");
					}
				}
			}
			// Looking Up
			if (_isOnGround)
			{
				if (_isLookingUp)
				{
					if (! _isMoving)
					{
						if (! _isDucking)
						{
							if (! _isGettingUp)
							{
								if (_facingRight)
								{
									this.gotoAndStop("UpRight");
								}
								else if (! _facingRight)
								{
									this.gotoAndStop("UpLeft");
								}
							}
						}
					}
				}
			}
			// Physics
		}
	}
}
Eric_S is offline   Reply With Quote
Old 04-21-2012, 03:23 PM   #3
wvxvw
Holosuit User
 
wvxvw's Avatar
 
Join Date: Oct 2006
Location: Tel Aviv
Posts: 4,301
Send a message via ICQ to wvxvw
Default

Few things that you probably want to change:
- no need to initialize the variables to their default values in constructor. You just gave yourself an extra workload for zero profit. Booleans are created with the default value of false, untyped variables have the value of undefined by default.
- you have mutually exclusive conditions spelled as if (x == y) { ... } if (x == z) { ... }. I.e. given that y != z and x is not modified in the first if block, it should be if (x == y) { ... } else if (x == z) { ... }.
- long nesting of if() inside if() - you normally want to avoid it. I.e. you can do if (x) { if (y) { ... }} as if (x && y) { ... } - saves you some work and makes it easier to read.
- it is better to write shorter functions - something you can understand withing a glance. This also helps finding repetitious code and eliminating it. As a general rule, you shouldn't need to scroll in order to read the entire function.
__________________
The .NET open source editor for Flash and web developers
*This would be my contribution to the project*
couchsurfing if you need it
wvxvw is offline   Reply With Quote
Old 04-28-2012, 11:55 PM   #4
Eric_S
Registered User
 
Join Date: Apr 2012
Location: Florida
Posts: 6
Default

I've been hard at work revamping my code to the point where I've pretty much rewrote it from the ground up (maybe twice!). One thing that is very important to me is fluid and natural animation. I've been able to achieve that to a point in my platformer game, but I can't help but think that the way I've achieved it is incredibly inefficient. Here's the updated code abridged for just animation:
Code:
		// onKeyPressed
		private function onKeyPressed(e:KeyboardEvent):void {

			if (e.keyCode == Keyboard.RIGHT)
			{
				_rightKeyIsDown;
				if (! _isDucking && ! _isGettingUp && ! _leftKeyIsDown)
				{
					_isMoving = true;
					_facingRight = true;
					_isLookingUp = false;
				}
			}
			if (e.keyCode == Keyboard.LEFT)
			{
				_leftKeyIsDown = true;
				if (! _isDucking && ! _isGettingUp && ! _rightKeyIsDown)
				{
					_isMoving = true;
					_facingRight = false;
					_isLookingUp = false;
				}
			}

			if (e.keyCode == Keyboard.UP)
			{
				_upKeyIsDown = true;
				if (_isOnGround && ! _isMoving && ! _isDucking && ! _isGettingUp && ! _isLanding)
				{
					_isLookingUp = true;
				}
			}

			if (e.keyCode == Keyboard.DOWN)
			{
				_downKeyIsDown = true;
				if (_isOnGround && ! _isMoving && ! _isLanding)
				{
					_isDucking = true;
					_isLookingUp = false;
					_canJump = false;
					_isMoving = false;
				}
			}

			if (e.keyCode == Keyboard.Z)
			{
				_isRunning = true;
			}

			if (e.keyCode == Keyboard.X)
			{
				if (_isOnGround && _canJump)
				{
					_accelY = _jumpForce;
					_isOnGround = false;
					_canJump = false;
					_isLookingUp = false;
					_isDucking = false;
				}
			}
		}
		//onKeyReleased
		private function onKeyReleased(e:KeyboardEvent):void {

			if (e.keyCode == Keyboard.RIGHT)
			{
				_rightKeyIsDown = false;
				if (_leftKeyIsDown && _isMoving)
				{
					_facingRight = false;
				}
				if (_upKeyIsDown && !_isMoving)
				{
					_isLookingUp = true;
				}
				if (_downKeyIsDown && !_isMoving)
				{
					_isDucking = true;
				}
				if (_facingRight)
				{
					_isMoving = false;
				}
			}

			if (e.keyCode == Keyboard.LEFT)
			{
				_leftKeyIsDown = false;
				if (_rightKeyIsDown && _isMoving)
				{
					_facingRight = true;
				}
				if (_upKeyIsDown && !_isMoving)
				{
					_isLookingUp = true;
				}
				else if (! _upKeyIsDown)
				{
					_isLookingUp = false;
				}
				if (_downKeyIsDown && !_isMoving)
				{
					_isDucking = true;
				}
				else if (! _downKeyIsDown)
				{
					_isDucking = false;
				}
				if (! _facingRight)
				{
					_isMoving = false;
				}
			}

			if (e.keyCode == Keyboard.UP)
			{
				_upKeyIsDown = false;
				if (_isOnGround && _isLookingUp)
				{
					_isLookingUp = false;
				}
			}

			if (e.keyCode == Keyboard.DOWN)
			{
				_downKeyIsDown = false;
				if (_isDucking && _isOnGround)
				{
					_isDucking = false;
					_isGettingUp = true;
					_canJump = true;
					if (_rightKeyIsDown)
					{
						_facingRight = true;
					}
					else if (_leftKeyIsDown)
					{
						_facingRight = false;
					}
				}
			}

			if (e.keyCode == Keyboard.Z)
			{
				_isRunning = false;
			}

			if (e.keyCode == Keyboard.X)
			{
				_vy = _vy / 4;
				if (! _isDucking)
				{
					_canJump = true;
				}
			}
		}
		private function onEnterFrame(e:Event):void {

			// Local Variables
			var playerHalfWidth:uint = _bBox.width * 0.5;
			var playerHalfHeight:uint = _bBox.height * 0.5 + 40;

			// Animations
			// Idle
			if (_isOnGround && ! _isGettingUp && ! _isMoving && ! _isLookingUp && ! _isDucking && ! _isLanding)
			{
				if (_facingRight)
				{
					this.gotoAndStop("IdleRight");
				}
				else if (! _facingRight)
				{
					this.gotoAndStop("IdleLeft");
				}
			}
			// Walking & Running
			if (! _isLanding && _isMoving && _isOnGround)
			{
				if (_facingRight)
				{
					if (! _isRunning)
					{
						this.gotoAndStop("WalkRight");
					}
					else if (_isRunning)
					{
						this.gotoAndStop("RunRight");
					}
				}
				else if (! _facingRight)
				{
					if (! _isRunning)
					{
						this.gotoAndStop("WalkLeft");
					}
					else if (_isRunning)
					{
						this.gotoAndStop("RunLeft");
					}
				}
			}
			//Ducking
			if (_isDucking && ! _isLanding)
			{
				if (_facingRight)
				{
					this.gotoAndStop("DuckRight");
				}
				else if (! _facingRight)
				{
					this.gotoAndStop("DuckLeft");
				}
			}
			//Getting Up From Ducking
			if (_isGettingUp)
			{
				_isDucking = false;
				_isMoving = false;
				_canJump = false;
				if (_facingRight)
				{
					this.gotoAndStop("DuckUpRight");
				}
				else if (! _facingRight)
				{
					this.gotoAndStop("DuckUpLeft");
				}
			}
			if (Object(DuckUpRight).currentFrame == 6)
			{
				_isGettingUp = false;
				_canJump = true;

				if (! _rightKeyIsDown && ! _leftKeyIsDown)
				{
					this.gotoAndStop("IdleRight");
					_isMoving = false;
				}
				else if (_rightKeyIsDown)
				{
					_isMoving = true;
					_facingRight = true;
					if (! _isRunning)
					{
						this.gotoAndStop("WalkRight");
					}
					else if (_isRunning)
					{
						this.gotoAndStop("RunRight");
					}
				}
				else if (_leftKeyIsDown)
				{
					_isMoving = true;
					_facingRight = false;
					if (! _isRunning)
					{
						this.gotoAndStop("WalkLeft");
					}
					else if (_isRunning)
					{
						this.gotoAndStop("RunLeft");
					}
				}
				else if (_upKeyIsDown)
				{
					_isLookingUp = true;
				}
			}
			if (Object(DuckUpLeft).currentFrame == 6)
			{
				_isGettingUp = false;
				_canJump = true;
				if (! _rightKeyIsDown && ! _leftKeyIsDown)
				{
					this.gotoAndStop("IdleLeft");
					_isMoving = false;
				}
				else if (_rightKeyIsDown)
				{
					_isMoving = true;
					_facingRight = true;
					if (! _isRunning)
					{
						this.gotoAndStop("WalkRight");
					}
					else if (_isRunning)
					{
						this.gotoAndStop("RunRight");
					}
				}
				else if (_leftKeyIsDown)
				{
					_isMoving = true;
					_facingRight = false;
					if (! _isRunning)
					{
						this.gotoAndStop("WalkLeft");
					}
					else if (_isRunning)
					{
						this.gotoAndStop("RunLeft");
					}
				}
			}
			// Looking Up
			if (_isLookingUp)
			{
				if (_facingRight)
				{
					this.gotoAndStop("UpRight");
				}
				else if (! _facingRight)
				{
					this.gotoAndStop("UpLeft");
				}
			}
			// Jumping, Falling, and Landing
			if (_isJumping)
			{
				if (_facingRight)
				{
					this.gotoAndStop("JumpRight");
				}
				else if (! _facingRight)
				{
					this.gotoAndStop("JumpLeft");
				}
			}
			if (_isFalling)
			{
				if (_facingRight)
				{
					this.gotoAndStop("FallRight");
				}
				else if (! _facingRight)
				{
					this.gotoAndStop("FallLeft");
				}
			}
			if (_isFalling && _isOnGround)
			{
				_isFalling = false;
			}
This achieves a fluid, fairly constant effect with some few hiccups for less significant movements (eg. getting up from ducking and holding the up key has a pause before the character looks up). Does anyone have any suggestions as to how I can make this code more efficient/easier to read/shorter, while still maintaining the same (or better) level of fluidity in the animation? Thanks in advance.
Eric_S is offline   Reply With Quote
Old 09-30-2013, 01:19 AM   #5
zarmeda
Registered User
 
Join Date: Sep 2013
Posts: 17
Default

In recent updates do not find such problems already
zarmeda is offline   Reply With Quote
Old 09-30-2013, 02:39 PM   #6
rashaeg
Registered User
 
Join Date: Sep 2013
Posts: 3
Default

- it is better to write shorter functions - something you can understand withing a glance. This also helps finding repetitious code and eliminating it. As a general rule, you shouldn't need to scroll in order to read the entire function.[/QUOTE]
i got it , thanks for the explanation
rashaeg is offline   Reply With Quote
Reply


Thread Tools
Display Modes Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT. The time now is 11:52 PM.

///
Follow actionscriptorg on Twitter

 


Powered by vBulletin® Version 3.8.5
Copyright ©2000 - 2014, Jelsoft Enterprises Ltd.
Ad Management plugin by RedTyger
Copyright 2000-2013 ActionScript.org. All Rights Reserved.
Your use of this site is subject to our Privacy Policy and Terms of Use.