Immer noch ein iPad-Spiel in Actionscript 3 programmierend, stoße ich auf ein Problem, das mich davon abhält, weiter voranzukommen. Ich benutze Blitting für die Animation und verwende daher alle meine Objekte zum Rendern. Alle Objekte sind Kinder einer Spielklasse mit einer BitmapData-Leinwand, auf der die Spielelemente gerendert werden.Actionscript 3: Benutzereingabenereignisse, die nicht von Kindern ausgelöst werden Blit-Sprite-Objekte
Das ist, wie es funktionieren sollte. Bis jetzt gibt es keine Kompilierungs- oder Laufzeitfehler, aber aus irgendeinem Grund kann ich kein Benutzereingabeereignis von einem Objekt abgesehen vom Spiel selbst erhalten. Ich habe sowohl den Ereignisfluss als auch die Überlagerung der Objekte überprüft, aber bisher konnte ich nur herausfinden, dass der Haupt-Canvas das einzige Element ist, das für Ereignisse verwendet werden kann. Da Spieler in der Lage sein müssen, sie zu berühren, sind zwei Spielelemente betroffen: Twinkys und Tennisschläger.
Ich habe versucht, die Schichtung der Elemente in der Reihenfolge Instanciation und Rendering zu ändern, einige zu verstecken, Ereignistypen zu ändern (Mausereignis statt Berührungsereignisse) und die mouseEnabled
Eigenschaft der Spielklasse ohne positives Ergebnis zu wechseln. Ich kann mir nur sicher sein, dass die Spielklasse alle auf ihre Kinder ausgerichteten Ereignisse abfängt, so dass es unmöglich ist, sie zu spielen. Ich hoffe, dass jemand sehen kann, was ich falsch gemacht habe.
Spielklasse:
package Game
{
import Game.*;
import Game.Worlds.Level1.Level1;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Sprite;
import flash.display3D.IndexBuffer3D;
import flash.events.Event;
import flash.events.TouchEvent;
import flash.ui.Multitouch;
import flash.ui.MultitouchInputMode;
public class Game extends Sprite
{
/** Hold each racquet so as to retrieve them when collision detection is needed. **/
internal var racquetList:Vector.<Racquet>= new Vector.<Racquet>(2,true);
/** Hold each Zwig so as to retrieve them when collision detection is needed. **/
internal var zwigColliderList:Vector.<Collider>= new Vector.<Collider>(2,true);
/** Object that contains the coordinates for the Twinkys in the counter. **/
internal var twinkyScore0:Object= {firstX:727,firstY:950,secondX:710,secondY:911,
thirdX:690,thirdY:872,fourthX:674,fourthY:840,
fifthX:657,fifthY:808};
internal var twinkyScore1:Object= {firstX:41,firstY:74,secondX:58,secondY:113,
thirdX:78,thirdY:152,fourthX:94,fourthY:184,
fifthX:111,fifthY:216};
/** Speed decay coefficient. The closer to 1 the less speed decays. **/
private var friction:Number= .96;
/** Maximum speed cap for twinkys. The higher the number the grater the maximal speed. **/
private var speedMax:Number= 10;
/** Important positions for the placement of game elements.
* LianaHeight is the height at which the liana on the players' HUDs is ending their zone and on which the racquet travels.
* TwinkyHeight is the height at which the players stop controlling their Twinkys.
* YMargin is the vertical margin for the Twinkys. Used to place them at the end of the tube when added.
* XMargin is the horizontal margin for the Twinkys. Used to place them at the end of the tube when added. **/
private var positions:Object= {LianaHeight:165,TwinkyHeight:265,YMargin:8.0,XMargin:200.0};
private var _mRef:ZwigsIpad;
Multitouch.inputMode= MultitouchInputMode.TOUCH_POINT;
private var _Canvas:BitmapData= new BitmapData(ZwigsIpad.BORDERS.right,ZwigsIpad.BORDERS.bottom,false);
private var _Background:Background;
private var _HUD1:HUD;
private var _HUD2:HUD;
private var _Score:Score;
private var _Zwig1:Zwig;
private var _Zwig2:Zwig;
private var _Racquet1:Racquet;
private var _Racquet2:Racquet;
private var _Twinky1:Twinky;
private var _Twinky2:Twinky;
/** Create the first level. It will create the stage and add the background, HUDs, Zwigs, Racquets and Twinkys, and manages the game until the end. **/
public function Game(m:ZwigsIpad)
{
this._mRef= m;
this.addEventListener(Event.ADDED_TO_STAGE,init);
}
private function init(e:Event):void
{
this.removeEventListener(Event.ADDED_TO_STAGE,init);
// Add game canvas on which all assets are rendered
addChild(new Bitmap(this._Canvas));
// Get informations from Level1
// LATER make it dependant from what level was chosen (switch case)
this.positions.LianaHeight= Level1.LIANA_HEIGHT;
this.positions.TwinkyHeight= Level1.TWINKY_HEIGHT;
this.positions.YMargin= Level1.TWINKY_MARGIN_Y;
this.positions.XMargin= Level1.TWINKY_MARGIN_X;
this.friction= Level1.TWINKY_FRICTION;
this.speedMax= Level1.TWINKY_SPEED_MAX;
// Add background
this._Background= new Background(this._Canvas,0);
addChild(this._Background);
// Add HUD
this._HUD1= new HUD(this._Canvas);
this._HUD2= new HUD(this._Canvas,true,1);
addChild(this._HUD1);
addChild(this._HUD2);
// Add scoring
this._Score= new Score(this,this._mRef);
addChild(this._Score);
// Add zwigs
this._Zwig1= new Zwig(this._Canvas);
this._Zwig2= new Zwig(this._Canvas,true,1);
addChild(this._Zwig1);
addChild(this._Zwig2);
// Add zwigs' colliders to vector
this.zwigColliderList[0]= this._Zwig1.collider;
this.zwigColliderList[1]= this._Zwig2.collider;
// Add racquets
this._Racquet1= new Racquet(this.positions,this._Canvas);
this._Racquet2= new Racquet(this.positions,this._Canvas,false,1);
addChild(this._Racquet1);
addChild(this._Racquet2);
// Add racquets to vector
this.racquetList[0]= this._Racquet1;
this.racquetList[1]= this._Racquet2;
// Add twinkys
this._Twinky1= new Twinky(this,this._Score,this,this.positions,this.friction,this.speedMax,this._Canvas,0);
this._Twinky2= new Twinky(this,this._Score,this,this.positions,this.friction,this.speedMax,this._Canvas,1,false,1);
addChild(this._Twinky1);
addChild(this._Twinky2);
this.addEventListener(Event.ENTER_FRAME,renderLevel);
}
private function renderLevel(e:Event):void
{
this._Canvas.lock();
this._Background.render();
this._HUD1.render();
this._HUD2.render();
this._Score.render();
this._Zwig1.render();
this._Zwig2.render();
this._Racquet1.render();
this._Racquet2.render();
this._Twinky1.render();
this._Twinky2.render();
this._Canvas.unlock();
}
}
}
Twinky Klasse:
package Game
{
import Game.Game;
import Game.Score;
import com.greensock.TweenMax;
import com.greensock.easing.*;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.TouchEvent;
import flash.geom.Point;
import flash.geom.Rectangle;
import flash.ui.Multitouch;
import flash.ui.MultitouchInputMode;
/** The Twinky is the main player controlled class. **/
internal class Twinky extends Sprite
{
private var _mRef:Game;
private var _sRef:Score;
private var player:uint;
Multitouch.inputMode= MultitouchInputMode.TOUCH_POINT;
private var _touchMoveID:int= 0;
private var _speedX:Number= 0;
private var _speedY:Number= 0;
private var xOffset:Number;
private var yOffset:Number;
private var currentX:Number;
private var currentY:Number;
private var oldX:Number;
private var oldY:Number;
private var dragging:Boolean= false;
private var launched:Boolean= false;
private var _point:Point= new Point();
private var positions:Object;
private var friction:Number;
private var speedMax:Number;
private var canvas:BitmapData;
private var isAtBottom:Boolean;
private var skin:uint;
private var _image:BitmapData;
private var _idleArray:Array= new Array();
private var i:uint= 0;
// Yellow twinky
[Embed (source= "Assets/Players/twinky1.png")]
private const Twinky1idle:Class;
private var _twinky1idleArray:Array;
// Red twinky
[Embed (source= "Assets/Players/twinky2.png")]
private const Twinky2idle:Class;
private var _twinky2idleArray:Array;
private const twinkyWidth:uint= 64;
private const twinkyHeight:uint= 64;
private var t1i001:Rectangle= new Rectangle(0,0,twinkyWidth,twinkyHeight);
private var t2i001:Rectangle= new Rectangle(0,0,twinkyWidth,twinkyHeight);
/** Create Twinky. Twinkys must be flicked to the same colored Zwig to
* feed it and die when they lost momentum. **/
public function Twinky(daddy:Game,score:Score,m:Game,positions:Object,friction:Number,speedMax:Number,canvas:BitmapData,player:uint,isAtBottom:Boolean=true,skin:uint=0)
{
// Get score and game object reference
this._sRef= score;
this._mRef= daddy;
this.positions= positions;
this.friction= friction;
this.speedMax= speedMax;
this.canvas= canvas;
this.player= player;
this.isAtBottom= isAtBottom;
this.skin= skin;
this._twinky1idleArray= [t1i001];
this._twinky2idleArray= [t2i001];
this.addEventListener(Event.ADDED_TO_STAGE,init,false,0,true);
}
private function init(e:Event):void
{
this.removeEventListener(Event.ADDED_TO_STAGE,init);
// Get skin
switch (this.skin)
{
case 0:
this._image= new this.Twinky1idle().bitmapData;
this._idleArray= this._twinky1idleArray;
break;
case 1:
this._image= new this.Twinky2idle().bitmapData;
this._idleArray= this._twinky2idleArray;
break;
default:
this._image= new this.Twinky1idle().bitmapData;
this._idleArray= this._twinky1idleArray;
break;
}
// Give position
if (this.isAtBottom)
{
this.x= this.positions.XMargin;
this.y= ZwigsIpad.BORDERS.bottom - this.positions.YMargin;
// Animate entrance
TweenMax.from(this,1,{x:this.x-70,y:this.y-12,rotation:-180,alpha:.5});
}
else
{
this.x= ZwigsIpad.BORDERS.right - this.positions.XMargin;
this.y= this.positions.YMargin;
// Animate entrance
TweenMax.from(this,1,{x:this.x+70,y:this.y+12,rotation:-180,alpha:.5});
}
this._point.x= this.x;
this._point.y= this.y;
aText.appendText("\n position: "+this.x+" "+this.y);
// Detect touched
this.addEventListener(TouchEvent.TOUCH_BEGIN,touchDown);
// Always detect untouched
this._mRef.addEventListener(TouchEvent.TOUCH_END,touchUp);
// Always do kinetics
this._mRef.addEventListener(Event.ENTER_FRAME,freeMove);
}
/** Render the Twinky at its current coordinates by redrawing it. **/
internal function render():void
{
this._point.x= this.x - this._idleArray[i].width * .5;
this._point.y= this.y - this._idleArray[i].height * .5;
this.canvas.copyPixels(this._image,this._idleArray[0/*i*/],this._point);
// When idle finished restart, else pursue with animation
/*if (i==this._idleArray.length - 1)
i= 0;
else
i++;*/
}
// TWINKY AND RACQUET DO NOT DETECT TOUCH EVENTS because the main canvas covers them
// Start dragging when touched
private function touchDown(e:TouchEvent):void
{
aText.appendText("\n Twinky touched!");
if (this._touchMoveID != 0)
return;
this._touchMoveID= e.touchPointID;
this.dragging= true;
// Get the mouse's offset on the object
this.xOffset= e.localX;
this.yOffset= e.localY;
this._mRef.addEventListener(TouchEvent.TOUCH_MOVE,touchMove);
}
private function touchMove(e:TouchEvent):void
{
if (e.touchPointID != this._touchMoveID)
return;
// Move twinky to where the mouse is
this.x= e.stageX - this.xOffset;
this.y= e.stageY - this.yOffset;
// Don't go farther than borders
if (this.x <= this.width * .5)
{
this.x= (this.width * .5) + .1;
}
if (this.x >= ZwigsIpad.BORDERS.right - (this.width * .5))
{
this.x= ZwigsIpad.BORDERS.right - (this.width * .5) - .1;
}
if (this.y <= this.height * .5)
{
this.y= (this.height * .5) + .1;
}
if (this.y >= ZwigsIpad.BORDERS.bottom - (this.height * .5))
{
this.y= ZwigsIpad.BORDERS.bottom - (this.height * .5) - .1;
}
// Be undraggable if zone is left
if (this.isAtBottom)
{
if (this.y < (ZwigsIpad.BORDERS.bottom - this.positions.TwinkyHeight))
{
this._touchMoveID= 0;
this.dragging= false;
this._mRef.removeEventListener(TouchEvent.TOUCH_MOVE,touchMove);
return;
}
}
else
{
if (this.y > this.positions.TwinkyHeight)
{
this._touchMoveID= 0;
this.dragging= false;
this._mRef.removeEventListener(TouchEvent.TOUCH_MOVE,touchMove);
return;
}
}
// Refresh coordinates for display
this._point.x= this.x;
this._point.y= this.y;
e.updateAfterEvent();
}
private function touchUp(e:TouchEvent):void
{
if (e.touchPointID != this._touchMoveID)
return;
this._touchMoveID= 0;
this.dragging= false;
this._mRef.removeEventListener(TouchEvent.TOUCH_MOVE,touchMove);
}
private function freeMove(e:Event):void
{
// Be undraggable if liana crossed
if (this.isAtBottom)
{
if (this.y < (ZwigsIpad.BORDERS.bottom - this.positions.TwinkyHeight))
{
this.removeEventListener(TouchEvent.TOUCH_BEGIN,touchDown);
this._mRef.removeEventListener(Event.ENTER_FRAME,touchUp);
this.dragging= false;
this.launched= true;
}
}
else
{
if (this.y > this.positions.TwinkyHeight)
{
this.removeEventListener(TouchEvent.TOUCH_BEGIN,touchDown);
this._mRef.removeEventListener(Event.ENTER_FRAME,touchUp);
this.dragging= false;
this.launched= true;
}
}
// Move the twinky and calculate its speed if player is dragging it
if (this.dragging)
{
aText.appendText("\n Twinky dragged!");
this.oldX= currentX;
this.oldY= currentY;
currentX= this.x;
currentY= this.y;
// Calculate speed in X and Y axis
this._speedX= this.currentX - this.oldX;
this._speedY= this.currentY - this.oldY;
// Cap maximal speed
if (this._speedX > this.speedMax)
this._speedX= this.speedMax;
if (this._speedY > this.speedMax)
this._speedY= this.speedMax;
}
// Otherwise move the twinky using its speed
else
{
this.x+= this._speedX;
this.y+= this._speedY;
}
// Detect collision with zwigs
for (i= 0 ; i < this._mRef.zwigColliderList.length ; i++)
{
var cemp:Collider= this._mRef.zwigColliderList[i] as Collider;
if (this.hitTestObject(cemp))
{
this.removeEventListener(TouchEvent.TOUCH_BEGIN,touchDown);
this._mRef.removeEventListener(TouchEvent.TOUCH_END,touchUp);
this._mRef.removeEventListener(Event.ENTER_FRAME,freeMove);
this._sRef.die(this,this.player,true,i);
return;
}
}
// Detect collision with borders: left border
if (this.x <= this.width/2)
{
// Don't go any further
this.x= (this.width/2) + .1;
// Reverse speed to bounce
this._speedX*= -1;
}
// Right border
if (this.x >= ZwigsIpad.BORDERS.right - (this.width/2))
{
this.x= ZwigsIpad.BORDERS.right - (this.width/2) - .1;
this._speedX*= -1;
}
// Top border
if (this.y <= this.height/2)
{
this.y= (this.height/2) + .1;
this._speedY*= -1;
}
// Bottom border
if (this.y >= ZwigsIpad.BORDERS.bottom - (this.height/2))
{
this.y= ZwigsIpad.BORDERS.bottom - (this.height/2) - .1;
this._speedY*= -1;
}
// Detect collision with racquets
for (var i:uint= 0 ; i < this._mRef.racquetList.length ; i++)
{
var temp:Racquet= this._mRef.racquetList[i] as Racquet;
if (this.hitTestObject(temp))
{
this._speedY*= -1;
this.y+= this._speedY;
}
}
// Speed decay
this._speedX*= this.friction;
this._speedY*= this.friction;
// Set speed to 0 if speed is smaller than .5
if (Math.abs(this._speedX) < .5) this._speedX= 0;
if (Math.abs(this._speedY) < .5) this._speedY= 0;
// If speed is null and it has been launched, kill twinky
if (this._speedX == 0 && this._speedY == 0 && this.launched)
{
this.removeEventListener(TouchEvent.TOUCH_BEGIN,touchDown);
this._mRef.removeEventListener(TouchEvent.TOUCH_END,touchUp);
this._mRef.removeEventListener(Event.ENTER_FRAME,freeMove);
TweenMax.to(this, 1.5, {alpha:0, ease:Linear.easeNone});
this._sRef.die(this,this.player);
return;
}
// Refresh coordinates for display
this._point.x= this.x;
this._point.y= this.y;
}
}
}
Schläger Klasse:
package Game
{
import Game.Worlds.Level1.Level1;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.TouchEvent;
import flash.geom.Point;
import flash.ui.Multitouch;
import flash.ui.MultitouchInputMode;
internal class Racquet extends Sprite
{
Multitouch.inputMode= MultitouchInputMode.TOUCH_POINT;
private var _touchMoveID:int= 0;
private var xOffset:Number;
private var dragging:Boolean= false;
private var positions:Object;
private var canvas:BitmapData;
private var isAtBottom:Boolean;
private var skin:uint;
private var _image:BitmapData;
private var _point:Point= new Point();
// Yellow racquet
[Embed (source= "Assets/Players/racq1.png")]
private const Racquet1:Class;
// Red racquet
[Embed (source= "Assets/Players/racq2.png")]
private const Racquet2:Class;
public function Racquet(positions:Object,canvas:BitmapData,isAtBottom:Boolean=true,skin:uint=0)
{
this.positions= positions;
this.canvas= canvas;
this.isAtBottom= isAtBottom;
this.skin= skin;
this.addEventListener(Event.ADDED_TO_STAGE,init,false,0,true);
}
private function init(e:Event):void
{
this.removeEventListener(Event.ADDED_TO_STAGE,init);
// Get skin
switch (this.skin)
{
case 0:
//this._image= new R.Racquet1().bitmapData;
this._image= new this.Racquet1().bitmapData;
break;
case 1:
//this._image= new R.Racquet2().bitmapData;
this._image= new this.Racquet2().bitmapData;
break;
default:
this._image= new this.Racquet1().bitmapData;
break;
}
// Give position
if (this.isAtBottom)
{
this.x= ZwigsIpad.BORDERS.centerX;
this.y= ZwigsIpad.BORDERS.bottom - this.positions.LianaHeight;
}
else
{
this.x= ZwigsIpad.BORDERS.centerX;
this.y= this.positions.LianaHeight;
}
this._point.x= this.x;
this._point.y= this.y;
this.addEventListener(TouchEvent.TOUCH_BEGIN,touchDown,false,0,true);
this.parent.addEventListener(TouchEvent.TOUCH_END,touchUp,false,0,true);
}
internal function render():void
{
this._point.x= this.x - this._image.rect.width * .5;
this._point.y= this.y - this._image.rect.height * .5;
this.canvas.copyPixels(this._image,this._image.rect,this._point);
}
private function touchDown(e:TouchEvent):void
{
aText.appendText("\n Racquet touched!");
if(this._touchMoveID != 0)
return;
this._touchMoveID= e.touchPointID;
this.xOffset= e.localX;
this.parent.addEventListener(TouchEvent.TOUCH_MOVE,touchMove,false,0,true);
}
private function touchMove(e:TouchEvent):void
{
if(e.touchPointID != this._touchMoveID)
return;
Multitouch.inputMode= MultitouchInputMode.TOUCH_POINT;
this._point.x= e.stageX - this.xOffset;
if (this._point.x <= ZwigsIpad.BORDERS.left + (this._image.width*.5))
this._point.x= ZwigsIpad.BORDERS.left + (this._image.width*.5);
else if (this._point.x >= ZwigsIpad.BORDERS.right - (this._image.width*.5))
this._point.x= ZwigsIpad.BORDERS.right - (this._image.width*.5);
}
private function touchUp(e:TouchEvent):void
{
if(e.touchPointID != this._touchMoveID)
return;
this._touchMoveID= 0;
this.parent.removeEventListener(TouchEvent.TOUCH_MOVE,touchMove);
}
}
}
Natürlich ... Vielen Dank für die Hilfe, ich Beim nächsten Mal werde ich aufmerksamer sein. – Yokai