[Anfänger] MovieClip vom ActionScript steuern

mamarulez

Mitglied
Hallo,

diesmal hab ich eine etwas simplere Frage als beim letzten Mal. Ich hab mittlerweile das ActionScript soweit ganz gut geblickt, denke ich. Das einzige was mich noch aufhält, ist dass ich mir noch nicht sicher bin, wie ich ein MovieClip-Object zum Beispiel per ActionScript "steuern" kann. Sagen wir mal, ich möchte Bälle malen. Ich würde mir eine Klasse für einen solchen Ball per Konstruktor im ActionScript des Frames erstellen, ungefähr so:

Code:
function _ball ( x, y )
// ball
{
	this.x = x;
	this.y = y;
}

ball = new _ball ( _xmouse, _ymouse );

In der letzten Zeile hätte ich dann eben einen solchen Ball erstellt (und zwar dort, wo die Maus ist). Jetzt will ich den Ball oder die Bälle auch tatsächlich zeichnen. Dafür erstelle ich einen MovieClip mit dem Bild eines Balls drin und füge eine Funktion zum Zeichnen des Balls hinzu.

Die Frage ist, was muss in diese Funktion, damit ich einen und auch mehrere Bälle zeichnen kann und dabei das MovieClip-Objekt benutze? Bis jetzt kann ich nur per "moveTo ( ... )" und "lineTo ( ... )" zeichnen - die beiden Funktion sind selbstverständlich und stellen kein Problem dar, für ein Spiel wäre aber ein wirkliches Bild in einem MovieClip viel schöner (mit vielen Farben, Animation etc.) - bei dem Ganzen kommt natürlich, da ich wirklich eigentlich noch blutiger Flash-Anfänger bin, immer noch eine zweite, kleinere Frage hinzu: ist der Weg, den ich hier so beschrieben habe, überhaupt richtig und gut? Oder gibt es bessere und einfachere andere Möglichkeiten?

Danke im Vorraus!
 
Zuletzt bearbeitet:
Hi,

wenn ich Dich recht verstanden habe, wäre attachMovie das, was Du suchst. Mit dieser Methode lassen sich MovieClips aus der Bibliothek auf die Bühne holen (instanzieren).

Ab Flash 8 dürfte auch die BitmapData-Klasse für Dich interessant sein, wenn es um die Manipulation von Grafiken geht. Deren Handhabung ist aber schon die etwas "höhere" Schule ...

Zu Deinem Ansatz: Wenn Du mit Klassen arbeiten willst und mindestens Flash 7 hast, solltest Du diese in AS2.0-Klassendateien auslagern. Unterhalb von Flash 7 würde ich z.B. Deinen Ball nicht durch eine per Funktion simulierte Klasse beschreiben, sondern den Code direkt in der Zeitleiste des entsprechenden MovieClips setzen.

Gruß
.
 
Ah, vielen Dank. Ich hatte mit "AttachMovie (...)" auch schon rumgespielt, aber war mir nie ganz sicher. Jetzt funktioniert's!

Danke nochmals.
 
So, ich habe noch eine kleine Frage.

Ich hatte mein Projekt schon soweit, dass man den Ball ganz einfach per Mausklick bewegen konnte. Jetzt habe ich das ganze ein bisschen umgeschrieben und es funktioniert nicht mehr.

Hier ist erstmal das ActionScript:

Code:
function _ball ( mc_id, id )
// ball
{
	this.mc_id = mc_id;
	this.id = id;
	
	this.init = function ( )
	// initializes the ball
	{
		attachMovie ( this.mc_id, this.id, 1 );
	}
	
	this.move = function ( x, y )
	// updates the ball
	{
		this.id._x = x;
		this.id._y = y;
	}
}

ball = new _ball ( "obj", "obj1" );
ball.init ( );

this.onMouseDown = function ( ) 
// called when the mouse is clicked
{
	// move ball to mouse
	ball.move ( _xmouse, _ymouse );
}

Der Ball taucht gar nicht auf, er ist nicht zu bewegen per Klick und wenn ich die beiden Werte für "ball.id._x" und "ball.id._y" mir anschaue, dann sind die leer.

Kann man das nicht so machen oder ist da oben nur ein dummer Fehler drin?
 
Hi,

1.
wird nicht funktionieren, denn "this.id" enthält einen String (in Deinem Beispiel die Zeichenkette "obj1", die Du dem Konstruktor übergeben hast) und keine Objektreferenz.

Wenn Du den "attachten" MovieClip über seinen Instanznamen (der in "id" steht) ansprechen willst, musst Du zumindest den Array-Zugriffsoperator verwenden:
Code:
irgendeine_zeitleiste[this.id]._x = x;

2. Du solltest die attachMovie-Methode des MovieClip-Objektes verwenden - wo wird sonst definiert, wo (sprich: auf welcher Zeitleiste) dieser MC instanziert wird? Eine Referenz auf die jeweilige Zeitleiste brauchst Du sowieso, um den MC anzusprechen.

Ich würde die Referenz, die die attachMovie-Methode zurückgibt, im Objekt speichern - dann kannst Du sie zum Bewegen weiterverwenden:
Code:
function _ball (tl, mc)
// ball
{
	this.timeline = tl; // Zeitleiste
	this.mc_ref = mc; // Objektbezeichner
	
	this.init = function( )
	// initializes the ball
	{
		this.sprite = this.timeline.attachMovie(this.mc_ref, "sprite", this.timeline.getNextHighestDepth());
	}
	
	this.move = function (x, y)
	// updates the ball
	{
		this.sprite._x = x;
		this.sprite._y = y;
	}
}
Code:
var b = new _ball(this, "kugel");
b.init();
b.move(320, 240);

Generell würde ich nicht auf diese Weise herangehen, wenn ein dynamischer Sprite erstellt werden soll, sondern den Code dem MC, der per attachMovie instanziert werden soll, zuordnen. Initialisierungen etc. können dann direkt nach dem attachMovie direkt ausgeführt werden:
Code:
// Code im ersten Frame des Sprite-MC ("sprite");:

var sym = null;

// Warten, bis ein Symbol (MC mit Bitmap) übergeben wird:
this.onEnterFrame = function() {
    if (_symbol != undefined) {
        sym = this.attachMovie(_symbol, "sym", 1);
        delete this.onEnterFrame;
    }
}

function rePos(dx, dy) {
    this._x = dx;
    this._y = dy;
}
Dann kann "von aussen" auf diese Weise ein Sprite erstellt werden:
Code:
var s1 = this.attachMovie("sprite", "s1", 100);
s1._symbol = "_ball"; // In der Bibliothek existiert
// ein MC mit diesem Verknüpfungsbezeichnerm,
// der nur das Bild enthält

this.onEnterFrame = function() {
    s1.rePos(_xmouse, _ymouse); // Bewegen
}

Gruß
.
 
Super, hat problemlos funktioniert und ich versteh mal wieder ein Stückchen mehr von Flash und seinen Funktionsweisen.

Vielen Dank! :)
 
Schon wieder ein wenig zu früh geposted. Hier ist noch eine letzte, kleine Frage:

Es geht jetzt um mehrere Bälle. Ich habe also ein Array aus Bällen definiert (erstmal nur zwei). Das hier ist das ActionScript:

Code:
var index = 0;

function _ball ( timeline, mc )
// ball
{
		this.timeline = timeline;
		this.mc = mc;

		this.init = function ( )
		// initializes the ball
		{
			this.sprite = this.timeline.attachMovie ( this.mc, "sprite", this.timeline.getNextHighestDepth ( ) );
		}

		this.move = function ( x, y )
		// moves the ball
		{
			this.sprite._x = x;
			this.sprite._y = y;
		}
}

function new_ball ( timeline, mc )
// creates a new ball
{
	return new _ball ( timeline, mc );
}

balls = [ new_ball ( this, "green_ball" ), new_ball ( this, "orange_ball" ) ];

for ( i in balls )
// init all balls
{
	balls[i].init ( );
}

this.onMouseDown = function ( ) 
// called when the mouse is clicked
{
	// move ball to mouse
	balls[index].move ( _xmouse, _ymouse );
	
	if ( index < 1 )
		index++;
	else
		index = 0;
}

Der Array funktioniert auch soweit. "index" ist immer entweder 0 oder 1 und wechselt somit zwischen beiden Bällen auf Mausklick. Der Ball bewegt sich auch, nur wird immer nur das "sprite" (also der MovieClip) von dem ersten Ball im Array angezeigt (also in diesem Fall bleibt der Ball immer grün).

Ich sehe noch nicht ganz, wieso das Ball-Objekt nicht mehrfach nebeinander existieren kann mit verschiedenen MovieClips!
 
Hi,

Dein Beispiel funktioniert bei mir (mit zwei entsprechenden MCs in der Bibliothek) fehlerfrei. Bist Du sicher, dass Du nicht versehentlich zwei grüne Bälle in der Bibliothek hast, oder die Verknüpfungsbezeichner durcheinandergebracht?

Gruß

P.S.: Willst Du den Stil, vor und nach jeder Klammer ein Leerzeichen zu setzen, beibehalten? Auch wenn der Flash-Parser es frisst: es ist recht unüblich (sprich: für ungeübte Augen auch recht mühsam zu lesen) und möglicherweise bekommst Du in anderen IDEs Probleme damit ... ;)
.
 
Hmm... Das wundert mich, ich hab alles nochmal gecheckt und beide Bälle sind in der richtigen Farbe (naja, der orange Ball ist wohl eher gelb...) und mit dem richtigen Namen in der Bibliothek. Manuell kann ich den MovieClip auch hinzufügen und es sieht alles richtig aus.

Zur Sicherheit ist die *.fla- und *.swf-Datei einfach im Anhang!

Zum Stil: den hab ich von C++ mitgebracht, ich selbst bin komplett daran gewöhnt - es tut mir Leid wenn sich dadurch die Lesbarkeit meines Codes für andere geringfügig verschlechtert, würde aber trotzdem gerne dabei bleiben. Ich bin mir auch über die Außergewöhnlichkeit dieser Formatierung im Klaren, trotzdem Danke für den Hinweis!
 

Anhänge

  • 26422attachment.zip
    3,8 KB · Aufrufe: 14
Hi,

nun ist der Fehler klar: Du veröffentlichst für Flashplayer 6, wo die Methode "getNextHighestDepth" nocht nicht bekannt war. Um für jeden neuen MC eine eindeutige Tiefenebene zu vergeben, musst Du einen Identifier hochzählen:
Code:
var index = 0;

function _ball ( timeline, mc, depth )
// ball
{
		this.timeline = timeline;
		this.mc = mc;
		this.depth = depth;

		this.init = function ( )
		// initializes the ball
		{
			this.sprite = this.timeline.attachMovie ( this.mc, "sprite", this.depth );
		}

		this.move = function ( x, y )
		// moves the ball
		{
			this.sprite._x = x;
			this.sprite._y = y;
		}
}

function new_ball ( timeline, mc, depth )
// creates a new ball
{
	return new _ball ( timeline, mc, depth );
}

balls = [ new_ball ( this, "orange_ball", 1 ), new_ball ( this, "green_ball", 2 ) ];

for ( i in balls )
// init all balls
{
	balls[i].init ( );
}

this.onEnterFrame = function ( )
// called repeatedly
{
	// print debug information
	debug_label.text = "Ball " + index + " (" + balls[index].sprite._x + ", " + balls[index].sprite._y + ")";
}

this.onMouseDown = function ( ) 
// called when the mouse is clicked
{
	// move ball to mouse
	balls[index].move ( _xmouse, _ymouse );
	
	if ( index < 1 )
		index++;
	else
		index = 0;
}
Damit Deine Sprites nicht mit Objekten in Konflikt kommen, die sich u.U. schon auf der Bühne befinden, solltest Du einen leeren MC erstellen, in den Du diese Sprites (und nur die Sprites) instanzierst. Statt "this" übergibst Du Deinem Konstruktor dann eine Referenz auf diesen leeren "Container".

Gruß

P.S.: Wenn Du von C++ kommst, und OOP gewohnt bist, könnte sich für Dich der Umstieg auf Flash 8 lohnen, wo Du mit "richtigen" Klassen arbeiten kannst.
.
 

Neue Beiträge

Zurück