Macromedia Flash ActionScript 2.0 és ActionScript 3.0

A jövő

Flash AS3 Billiárd

Letöltés

Téma: Flash alapú biliárd-program tervezése és fejlesztése ActionScript 3.0 környezetben

Eredetileg szakdolgozatként készült egy nem-programozói diplomához, ami célra meg is felelt. A szakdolgozat egésze letölthető dokumentummal együtt.

Készítette: Vojsánszky Szabolcs (2005)

A készítés során főbb szempontok a következők voltak

Felhasznált eszközök

A végleges megoldás különösebb tervmintákat nélkülöző, erős jóindulattal XP módszereket követ. Ennek talán részben köszönhető a párhuzamosság hiánya AS3-ban, ami előnyben részesíti a szuperosztályok használatát.

Példák - a leginkább újrahasznosítható részek

KeyObject.as:

import flash.display.MovieClip;
import flash.display.Stage;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.ui.Keyboard;
import flash.utils.Proxy;

public class keyObject extends MovieClip
{
	private var keysDown:Array = new Array();
	
	public function keyObject()
	{
		addEventListener(Event.ADDED_TO_STAGE, onStage, false, 0, true);
	}
	private function onStage(event:Event)
	{
		stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyPress, false, 0, true);
		stage.addEventListener(KeyboardEvent.KEY_UP, onKeyRelease, false, 0, true);
	}
	private function onKeyPress(key:KeyboardEvent)
	{
		keysDown[key.keyCode] = true;
	}
	private function onKeyRelease(key:KeyboardEvent)
	{
		keysDown[key.keyCode] = null;
		clearKeys();
	}
	private function clearKeys()
	{
		var last:Number = keysDown.length;
		while (keysDown[last] != true && last >= 0)
			last --;
		keysDown.splice(last + 1, keysDown.length - last - 1);
	}
	public function isDown(keyCode):Boolean 
	{
		return keysDown[keyCode];
	}
}	
	

perPixelHitTest.as:

import flash.display.BitmapData;
import flash.display.BitmapDataChannel;
import flash.display.BlendMode;
import flash.display.DisplayObject;
import flash.display.DisplayObjectContainer;
import flash.geom.Matrix;
import flash.geom.Point;
import flash.geom.Rectangle;	

public class perPixelHitTest
{
	public static function hitTestPixel(object1, object2, parent):Boolean
	{
		var collision:Rectangle;
		collision = getRectangle(object1, object2, parent);
		if (collision != null && collision.size.length > 0)
			return true;
		else
			return false;
	}
	public static function hitPointPixel(object1, object2, parent):Point
	{
		var collision:Rectangle;
		collision = getRectangle(object1, object2, parent);
		if (collision != null && collision.size.length > 0)
		{
			var returnPoint:Point;
			returnPoint = getCenter(collision);
			return returnPoint;
		}
		else
		return null;
	}		
	public static function getRectangle(object1, object2, parent):Rectangle 
	{
		var rectangle1 = object1.getBounds(parent);
		var rectangle2 = object2.getBounds(parent);
		
		var intersection = rectangle1.intersection(rectangle2);
		
		if (intersection.size.length > 0)
		{
			intersection.width = Math.ceil(intersection.width);
			intersection.height = Math.ceil(intersection.height);
			
			var alpha1 = getAlpha(object1, intersection, BitmapDataChannel.RED, parent);
			var alpha2 = getAlpha(object2, intersection, BitmapDataChannel.GREEN, parent);
			
			alpha1.draw(alpha2, null, null, BlendMode.LIGHTEN);
			
			var collision = alpha1.getColorBoundsRect(0xffff00, 0xffff00);
			
			collision.x += intersection.x;
			collision.y += intersection.y;
			
			return collision;
		}
		else
			return null;
	}
	private static function getAlpha(object, rectangle, channel, parent):BitmapData
	{
		var parentXformInvert:Matrix = parent.transform.concatenatedMatrix.clone();
		parentXformInvert.invert();
		var objectXform:Matrix = object.transform.concatenatedMatrix.clone();
		objectXform.concat(parentXformInvert);

		objectXform.translate( -rectangle.x, -rectangle.y);
		
		var bitmapData:BitmapData = new BitmapData(rectangle.width, rectangle.height, true, 0);
		bitmapData.draw(object, objectXform);

		var alphaChannel:BitmapData = new BitmapData(rectangle.width, rectangle.height, false, 0);
		
		alphaChannel.copyChannel(bitmapData, bitmapData.rect, new Point(0, 0), BitmapDataChannel.ALPHA, channel);
		
		return alphaChannel;
	}				
	
	public static function getCenter(inputRectangle):Point 
	{
		var returnPoint:Point = new Point();
		returnPoint.x = inputRectangle.x + inputRectangle.width / 2;
		returnPoint.y = inputRectangle.y + inputRectangle.height / 2;
		return returnPoint;
	}
}	
	

Flash AS3 Ping-pong

Letöltés

Feladat:

Valósítsunk meg egy egyszerű „ping-pong” játékot Flash környezetben AS3 segítségével.

A ping-pong játék lényege:

Megoldás:

Hozzunk létre egy-egy egyéni osztályt a Sprite-ból leszármaztatva mind az ütőknek, mind a labdának. Segédosztályként vezessük be a Direction (irány) osztályt.

Főprogram:

import Ball;
import Pad;
import Direction;
// Hozzuk létre, majd helyezzük el az ütőket és labdát a pályán
var pad1:Pad = new Pad(stage, true, true);
var pad2:Pad = new Pad(stage, false, false);
var ball:Ball = new Ball(stage);
addChild(pad1);
addChild(pad2);
addChild(ball);

// Állítsuk be a játék gyorsaságát
const startfrequency:Number = 10;
var frequency:Number = startfrequency;

// Segédváltozók visszaszámláláshoz
// (mikor valaki épp pontot veszített, kicsit álljon le a labda)
var counting:Boolean = true;
var counter:Number = 0;
var countdown:Number = 3;

// Játsszunk le kis csipogást, mikor egy ütő eltalálja a labdát
function playbeep() {
	var beep:Beep = new Beep();
	beep.play();
}

// Hozzunk létre egy eseményfigyelőt, ami ütemezi a játékot
var moverFunction:Function = function() {
	// Ha épp nem visszaszámlálunk, akkor mozgassuk a labdát
	if(!counting) {
		ball.move();
	// Amúgy egy szövegdobozba írjuk ki a hátralévő időt
	} else {
		countdownText.text = String(Math.ceil(countdown-counter/1000));
		counter+=frequency;
		// Ha végeztünk, állítsuk le a számlálót.
		if(counter/1000>=countdown) {
			counter = 0;
			counting = false;
			countdownText.text = "";
			ball.setTarget();
		}
	}
	
	// Mozgassuk az ütőket
	pad1.move(ball);
	pad2.move(ball);
	
	// Ellenőrizzük, ütésben van-e a labda valamelyik ütővel
	// ha igen, csipogjunk és kezeljük le
	if(pad1.hitTestObject(ball)) {
		ball.hit(pad1);
		playbeep();
	}
	if(pad2.hitTestObject(ball)) {
		ball.hit(pad2);
		playbeep();
	}
	// Ellenőrizzük, hogy leesett-e a labda a pályáról.
	// ha igen, növeljük a megfelelő számlálót, és állítsuk vissza
	if(ball.over(pad1)) {
		ball.reset();		
		counting = true;
		gate1counter.text=String(Number(gate1counter.text)+1);
	}
	if(ball.over(pad2)) {
		ball.reset();		
		counting = true;
		gate2counter.text=String(Number(gate2counter.text)+1);
	}
}

//Regisztráljuk az eseményfigyelőnket egy Timerhez és indítsuk el azt
var mover:Timer = new Timer(frequency, 0);
mover.addEventListener("timer", moverFunction);
mover.start();

Direction.as:

package {
// Egy 2D vektor, amely megadja, hogy a labda melyik irányba halad
public class Direction {
public var x:Number = 0;
public var y:Number = 0;
public function Direction(p_x:int, p_y:int) {
x = p_x;
y = p_y;
}
// Visszaadja az 1-re normált x komponenst.
public function normX():Number {
return x/Math.sqrt(x*x+y*y);
}
// Visszaadja az 1-re normált y komponenst.
public function normY():Number {
return y/Math.sqrt(x*x+y*y);
}
// Lekezeli az ütő és labda összeütközését
public function hit(pad:Pad, ball:Ball) {
if(y<0&&pad.onTop || y>0&&!pad.onTop) y*=-1;
x=(x+(ball.x-pad.x)*10)/pad.width;
}
}
}

Pad.as:

package {
import flash.display.Sprite;
import flash.events.KeyboardEvent;
import Direction;
public class Pad extends Sprite {
// Az ütő mozgása időközönként
var rate:Number = 2;
// Le van-e nyomva a bal kurzorbillentyű
var leftDown:Boolean;
// Le van-e nyomva a jobb kurzorbillentyű
var rightDown:Boolean;
// Mesterséges intelligencia irányítja-e az ütőt
var AI:Boolean = true;
// Felül van-e az ütő.
var onTop:Boolean = false;
public function Pad(stage, p_onTop = true, p_AI = true) {
AI = p_AI;
onTop = p_onTop;
// Az ellenfél ütőjét lassítsuk kicsit le.
if(AI) rate*=0.8;
// Rajzoljuk ki az ütőt
graphics.beginFill(0xFFFFFF);
graphics.drawRect(-40, -3, 80, 6);
graphics.endFill();
// Helyezzük el az ütőt a pályán
this.x = stage.stageWidth/2;
this.y = onTop?3:stage.stageHeight-3;
// Figyeljük a billentyűket
stage.addEventListener(KeyboardEvent.KEY_UP,key_Up);
stage.addEventListener(KeyboardEvent.KEY_DOWN,key_Down);
}
// A mozgást kezelő függvény
public function move(ball:Ball) {
// Mi van, ha nem MI a játékos
if(!AI) {
// ha a bal le van nyomva, és nincs túl balra
if(leftDown && this.x>=this.width/2) {
// vigyük balra az ütőt rate pixellel
this.x-=rate;
// ha a jobb le van nyomva, és nincs túl jobbra
} else if(rightDown
&& this.x+this.width/2<=stage.stageWidth) {
// vigyük jobbra az ütőt rate pixellel
this.x+=rate;
}
// Mi van, ha MI a játékos
} else {
// vigyük a labda beütközési helye felé az ütőt
if(ball.getTarget()-rate>x
&& x+width/2<=stage.stageWidth) {
x+=rate;
} else if(ball.getTarget()+rate<x && x>=width/2) {
x-=rate;
}
}
}
// Keyboard eseményfigyelők, amik a bal-jobb gombokat kezelik
private function key_Up(event:KeyboardEvent) {
switch (event.keyCode) {
case 37 :
leftDown = false;
break;
case 39 :
rightDown = false;
break;
}
}
private function key_Down(event:KeyboardEvent) {
switch (event.keyCode) {
case 37 :
leftDown = true;
break;
case 39 :
rightDown = true;
break;
}
}
}
}

Ball.as:

package {
import flash.display.Sprite;
import Direction;
import Pad;
public class Ball extends Sprite {
// Az labda mozgása időközönként pixelekben
const rate:Number = 3;
// Az labda iránya
public var dir:Direction = new Direction(Math.random()*2-1, -4);
// A labda következő beütközési helye
private var targetPosition:Number;
public function Ball(stage) {
// Rajzoljuk meg a labdát
graphics.beginFill(0xFFFFFF);
graphics.drawEllipse(-3, -3, 6, 6);
graphics.endFill();
// Pozicionáljuk
this.x = stage.stageWidth/2;
this.y = stage.stageHeight/2;
}
// A labda mozgását kezelő függvény
public function move() {
// Ha kimenne a pályáról, fordítsuk meg az irányát
if((y+height/2>=stage.stageHeight && dir.y>0)
|| (y-height/2<=0 && dir.y<0)) {
dir.y*=-1;
}
if((x+width/2>=stage.stageWidth && dir.x>0)
|| (x-width/2<=0 && dir.x<0)) {
dir.x*=-1;
}
// Amúgy növeljük mindként koordinátáját az adott
// iránykomponens 1-re normáltjának a rate-szeresével
x+=rate*dir.normX();
y+=rate*dir.normY();
}
// Kezeljük le, ha az ütővel ütközik
public function hit(pad:Pad) {
dir.hit(pad, this);
// Változni fog a becsapódás helye, számoljuk ki újra
setTarget();
}
// Számoljuk ki a becsapódás helyét
public function setTarget() {
// Számoljuk ki a becsapódás abszolút helyét
if(dir.y<0) {
targetPosition = x-y*(dir.x/dir.y);
} else {
targetPosition = x+(stage.stageHeight-y)*(dir.x/dir.y);
}
// Vegyük hozzá a falakról való visszapattanást
if(targetPosition<0) {
targetPosition *= -1;
} else if(targetPosition>stage.stageWidth) {
targetPosition = stage.stageWidth*2-targetPosition;
}
}
// Visszaadja a becsapódás helyét
public function getTarget():Number {
return targetPosition;
}
// Visszaadja, hogy elkerülte-e a labda az ütőt.
public function over(pad:Pad):Boolean {
return pad.onTop?y-height/2<=pad.y:y+height/2>=pad.y;
}
// Berakja a labdát a pálya közepére (mikor valaki pontot veszít)
public function reset() {
x = stage.stageWidth/2;
y = stage.stageHeight/2;
dir.x = Math.random()*2-1;
setTarget();
}
}
}

Flex bemutató

Megtekintés új oldalon

A program a flex újdonságainak bemutatására szolgál. Segítségével online kipróbálhatjuk a Flex újdonságait. A fent linken meg lehet tekinteni a programot, letöltéshez pedig a program jobb egérgombos menüjében válasszuk a "Show source" opciót! Ezen a képernyőn belül már megjelenik a download source link.

Használati utasítás-képpen írok egy-egy sort minden oldalról:

Hunt It Down! - játék

Letöltés

Feladat

A feladat egy repülőgépes lövöldözős játék elkészítése. A játékos oldalnézetből látja a pályát és a repülőgépét a megfelelő módon navigálva minél több ellenséges egységet kell kiiktatnia.

Funkciók

Élet és páncél

A játékosnak kezdetben 3 életegysége van, amely a játék ideje alatt változik. Életegységet veszít a játékos, ha az aktuális páncélja teljesen megrongálódik. Plusz egy életet kap a játékos minden, a pályán véletlenszerűen generált életegységet növelő pont megszerzése után.

A páncél egy életegység elhasználásakor 100%-os állapotba kerül és az ellenség által bevitt találatok folyamatosan rongálják azt. Ha a páncél megsemmisül, a játékos elveszít egy életegységet és a páncél újra megjavul. A pályán véletlenszerűen generált páncéljavító pontok felvételével a játékos páncélja javítható.

Fegyverek

2 féle fegyvertípus létezik. A gépfegyver és a rakéta.

A rakéta nagyobb sebzést okoz, viszont egyszerre csak 1 db rakétát lehet a repülőgépre szerelni. A játéktéren véletlenszerűen generált plusz rakéta pont felvételével a játékos repülőgépére plusz egy rakéta kerül abban az esetben, ha még nincs felszerelve rakéta.

A játékos vadászgépére kezdetben egy gépfegyver kerül. Ennek száma növelhető eggyel, ha a plusz gépfegyver pontot megszerzi a játékos. A gépfegyverek tüzelési sebessége is növelhető a megfelelő tüzelési sebesség pont felvételével. A gépfegyver töltény nincs végtelenítve, így ezzel is ügyesen kell gazdálkodnia a játékosnak. Természetesen a plusz töltény pont megnöveli a muníciót.

Ellenség

A játék során ellenséges repülőgépeket kell levadászni. Az ellenség megpróbál a játékos repülőgépével egy vonalba helyezkedni, így növelve a találati arányt. Egyelőre kizárólag légi egységek vannak betervezve a játékba.

Felhasználói interakciók

A játék indulásánál a főmenü fogadja a játékost. Itt olvashat a játékról, irányításról és innen tudja elindítani a játékot.

A játék során a repülőgépet a kurzormozgató nyilakkal kell irányítani a játékosnak. A gépfegyverekkel való tüzelés a Space billentyűvel történik, míg a rakéták kilövését a CTRL gomb lenyomásával teheti meg a játékos.

Architektúra - MVC

A program architektúráját tekintve követi az MVC tervezési mintát. A nézet maga a Flash-ben megrajzolt objektumokból áll össze. A modell tartalmazza az összes egyedre vonatkozó információkat, például a repülőre, gépfegyverre vagy akár magára a gépfegyver töltényre. A kontroller pedig a nézeten kiváltott interakciókra reagál és közvetíti azt a modell felé.

Animációk

Főbb animációk, melyek nagyobb gondolkodást igényeltek:

Eszközök

A Flash-t kizárólag a rajzolásra használtam. A kódolást már az Eclipse alapú Flash Builder eszközzel végeztem, mivel kezelését tekintve felhasználóbarátabb és okosabb, mint a Flash beépített Action Script Window-ja.

A rajzoláshoz ezen kívül még Photoshop-ot is használtam.

ASCII Art

Letöltés

Szerző neve: Veress Vivien
Készítés éve: 2014

Feladat

A feladat egy népszerű képkonvertáló programot valósít meg. Különböző típusú képekből ASCII karakter sorozatot állít elő a pixelek alapján, és megjeleníti azokat, így kirajzolva az eredeti képet.

Megvalósítás

A program egy Flash tutorial-ra épül (http://help.adobe.com/en_US/ActionScript/3.0_ProgrammingAS3/WS5b3ccc516d4fbf351e63e3d118a9b90204-7eee.html) és az Adobe Flash CS4 nevű fejlesztői környezetében készítettem el. A megvalósításnál sok hasznos beépített könyvtárat felhasználunk.

Először is egy felhasználói felületet hozunk létre (AsciiArtApp.fla). Ezt nagyon egyszerűen, az elemek felületre húzogatásával megtehetjük. Ezután úgynevezett action-öket rendelhetünk a különböző elemekhez, és így megírhatjuk a logikát a felülethez. Eseménykezelőkön keresztül hívjuk meg a szükséget műveleteket, amiket az actionscript fájlokban írunk meg. (AsciiArtBuilder.as, BitmapToAsciiConverter.as, Image.as, ImageInfo.as)