globaltoLocal in addchild - actionscript-3

I have an enemy that adds an attack movie clip. More specifically, this attack movie (We'll call it masterAttack) clip is a blank movie clip that acts like a super class, that will hold other attacks like a weak and strong attack. So when my enemy attacks using a timer, it adds the masterAttack on a global to local point.
Below is the Enemy timer attacking a tile the player is on:
if (Main.tileset[k].tileMiddle.hitTestObject(Main.player.visionPoint))
{
this.addChild(masterAttack);
var pt:Point = this.enemymagic.globalToLocal(new Point(Main.tileset[k].x, Main.tileset[k].y));
masterAttack.masterEnemyAttackTimer.start();
this.masterAttack.x = (pt.x);
this.masterAttack.y = (pt.y);
}
And Below is the masterAttack timer:
function mastertimer(event:TimerEvent) {
addChild(sludgeball); //This is one of the many attacks pickable by the masterAttack
sludgeball.enemyattackTimer.start();
if (this.sludgeball.currentLabel == "End") {
this.sludgeball.gotoAndPlay(1);
masterEnemyAttackTimer.stop();
if (masterEnemyAttackTimer.running == false)
{
attackStop = true;
this.parent.removeChild(this);
removeChild(sludgeball);
}
}
My problem is, on the first run, the masterAttack will attack the player wherever it is, then remove itself, which is good. Then the next time it runs, the masterAttack is not hitting the player. It's as if the globaltoLocal isn't working after the first run.

this.addChild(masterAttack);
var pt:Point = this.enemymagic.globalToLocal(new Point(Main.tileset[k].x, Main.tileset[k].y));
You add the masterAttack to this, but you got pt using enemymagic's globalToLocal
So change the line like this
var pt:Point = this.globalToLocal(new Point(Main.tileset[k].x, Main.tileset[k].y));

Related

How Can I Make AS3 Var Loop move speed on the Y Axis on repeat my university project

I'm tring to get the car image to move down the screen on the y Axis and make it a repeat and colide with another object
//creates the new Car
for (var c:int=0; c<8; c++){
var newcar = new car();
newcar.x = 55*c;
newcar.y = 100;
EntityArray.push(newcar);
stage.addChild(newcar);
trace("Car Created"+c)
}
How to make it colide with the following and remove it from screen
//creates the new Frog
for (var f:int=0; f<1; f++){
var newfrog = new frog();
newfrog.x = 210;
newfrog.y = 498;
EntityArray.push(newfrog);
stage.addChild(newfrog);
trace("Frog Created"+f)
}
[image][1][1]: https://i.stack.imgur.com/Ihsfx.png
Though I'm quite pleased to hear that today they still tell you about ActionScript at college, it's a bit hard
to give you advice here since I don't know what they've covered yet.
Generally speaking, you could realize this with a simple game loop, that runs periodically and in it's most simple
form:
checks user input (in your case most likely pressing left/right to move the frog)
update game state (move the cars & the frog ; check for collision)
draw everything to screen
For creating the periodical loop, Flash/ActionScript offers a powerful event called ENTER_FRAME. Once started, it
will fire with the framerate of the movie. So if you set your movie to 60fps, it will execute it's callback function
roughly every 17ms.
I assume your instances of Frog and Car extend Flash's Sprite or MovieClip class - so collision detection is also pretty
easy since you can use the inherited hitTestObject() method.
To make things a bit easier though I'd recommend that you don't put the reference to the frog instance inside the EntityArray.
Better use a global reference. (Also, you don't need a for-loop because there's just one frog)
As another sidenote, it's quite common that classnames start with a capital letter.
private var newfrog:frog; // defines a class variable we can access anywhere inside our class
//Later on instantiate new cars and the frog:
for (var c:int=0; c<8; c++){
var newcar = new car();
newcar.x = 55*c;
newcar.y = 100;
EntityArray.push(newcar);
stage.addChild(newcar);
}
newfrog = new frog();
newfrog.x = 210;
newfrog.y = 498;
stage.addChild(newfrog);
addEventListener(Event.ENTER_FRAME, loop); // register an ENTER_FRAME listener for the main game loop
private function loop(e:Event):void
{
var tempCar:car;
for(var a:int=0;a<EntityArray.length;a++)
{
tempCar=EntityArray[a]; // get a car from the EntityArray
tempCar.y++; // move it down on screen
if(tempCar.y>600) // if it's vertical position is greater than 600...
{
tempCar.y=0; // ...move it back to the top
}
if(newfrog.hitTestObject(tempCar)) // evaluates to true, if a car and the frog's bounding boxes overlap
{
trace("there's a collision!"); // do something
}
}
}

AS3: how do i stop two of the same function from playing at once?

i am using AS3 to create a function that will automatically play a movieclip all the way through and then remove it. my project is going to have a lot of animated cutscenes, so id like to be able to call this function, use the cutscene id like as a parameter, and then move on to the next. the problem is, im trying to use the function multiple times in a row to play clips sequentially, but they're all playing at the same time. is there a fix, or a better way to do this altogether?
playClip(new a_walk); //find a way to make these stop playing at the same time
playClip(new a_door);
//a_walk and a_door are the AS linkage class names for the movieclips im referring to
function playClip (clip:MovieClip):void {
addChildAt(clip, 0);
clip.mask = myMask;
clip.x=412.4;
clip.y=244.5;
clip.addEventListener(Event.ENTER_FRAME, checkframes);
function checkframes(event:Event) {
if (clip.currentFrame == clip.totalFrames) {
//trace("wow! youre an idiot!");
if (clip.parent) {
clip.parent.removeChild(clip);
trace (100);
return;
}
}
}
}
Sounds like you want a mechanism to play a queue of MovieClips? If so, here is a way you can accomplish this:
//create an array with the clips you want to play (in order), in my example here, the items can be a MovieClip derived Class, or a MovieClip instance
var playQueue:Array = [a_walk, a_door];
//create a var to store the currently playing clip
var currentClip:MovieClip;
playNext(); //call this when you want the queue of clips to start playing
function playNext():void {
//if there was an item previously playing (currentClip has a value), stop it and remove it/dispose of it
if(currentClip){
currentClip.stop(); //stop it from playing
currentClip.addFrameScript(currentClip.totalFrames-1, null); //remove the frame script that was added
currentClip.parent.removeChild(currentClip); //remove it from the display
currentClip = null;
}
//check if there's anything left to play
if(playQueue.length < 1) return;
var nextItem:* = playQueue.shift(); //shift retrieves and removes the first item in the array;
if(nextItem is Class){
//if it's a class, instantiate it
currentClip = new nextItem();
}else{
currentClip = MovieClip(nextItem);
}
//initialize the movie clip
addChildAt(currentClip, 0);
currentClip.gotoAndPlay(1);
//this is just what you were doing before:
currentClip.mask = myMask;
currentClip.x=412.4;
currentClip.y=244.5;
//add a command on the last frame of the movie clip to play the next item in the queue
currentClip.addFrameScript(currentClip.totalFrames-1, playNext);
//addFrameScript is 0 based, so 0 would refer to the first frame. This is why we subtract 1 to get the last frame
}
I should note, that addFrameScript is an undocumented function. It serves as a nice shortcut so you don't have to have an ENTER_FRAME listener checking currentFrame vs. totalFrames. Being undocumented however, one can not count on it's continued existence in future versions of the Flash/AIR runtimes (though it's been around for a long long time)
note
This answer is a work in progress. I'm waiting on a response from the OP.
// playClip(new a_door); don't call this yet, or they will just both play.
var clipData:CustomClass = new CustomClass(); // add an instance of a custom class to hold the value of the movie
//clip being played (so that you can use this value later in the event handler.)
// it will also hold a value of the next clip
clipData._currentClip = a_walk;
clipData._nextClip = a_door;
playClip(new a_walk);
function playClip (clip:MovieClip):void {
addChildAt(clip, 0);
clip.mask = myMask;
clip.x=412.4;
clip.y=244.5;
clip.addEventListener(Event.ENTER_FRAME, checkframes);
}
function checkframes(event:Event) {
if (clipData._currentClip.currentFrame == clipData._currentClip.totalFrames) {
//trace("wow! youre an idiot!");
if (clipData._currentClip.parent) {
playClip(clipData._nextClip);
clipData._currentClip.parent.removeChild(clipData._currentClip);
clipData._currentClip = clipData._nextClip; // moves the clips down
//clipData._nextClip = here we have
//a problem. Do these clips play in a set
//order, first to last? Or do the play out of
//order jumping back and forth? If so, how
//are you planning on controlling which clip
//plays next?
trace (100);
return;
}
}
}
I haven't checked this in Flash yet to see if it works, but I noticed that you are defining a function inside another function, which I don't think is good practice, so this might clean things up for you. Give it a try and let us know.
I'll try to fix my code above when I get a chance. In the meantime, you answered my question about playing the clips in order, so a simple solution would be to put all the clips in an array and then play them by playClip(clipArray[i]) and then when the clip ends and gets removed, do i++ and call the same function playClip(clipArray[i]) which will play the next clip in the array.

Remove Object when Collision Detected in AS3

I'm making a game where your player (gun) shoots enemies (baddie) to gain score. I've set it up so you have three lives (lives) until it is game over. I am trying to add an addLife function that works by when your player collects an object (waterMelon), it gets a life. I have added a timer event that runs the function addLife, that adds an instance of the Movie clip to the stage every 5 seconds. In that function, ive created another function called checkCollisions, that is meant to check the collision of the player, to the object, remove the object from the stage, then add a life.
var timer2:Timer = new Timer(5000);
timer2.addEventListener(TimerEvent.TIMER, addLife);
timer2.start();
var watermelon:waterMelon = new waterMelon();
function addLife(evt:TimerEvent):void{
watermelon.x = Math.random() * stage.stageWidth;
watermelon.y = Math.random() * stage.stageHeight;
addChild(watermelon);
watermelon.push(waterMelon);
checkCollision();
}
function checkCollision(){
if (gun.hitTestObject(watermelon)){
removeChild(watermelon);
lives++;
livesDisplay.gotoAndStop(livesDisplay.currentFrame-1);
}
}
The only part of the code that works is the adding the watermelon to the stage, but when my player collides with it, it does not remove from the stage. Could someone please tell me how I make my watermelon completely be removed from the stage when the player collides with it, and add a life to my player. Once again, each object equals this; gun = player, waterMelon = object/watermelon, lives = lives, livesDisplay = physical display of lives.
You have tried to delete the array(watermelon) from the stage instead of the object(waterMelon). Although by the looks you are using arrays so you will have to find the index of the object colliding with the gun from the array watermelon. You do this with a for loop.
for (melonCount:int = 0; melonCount>watermelon.length;melonCount--)
{
if (gun.hitTestObject(watermelon[melonCount]))
{
removeChild(watermelon[melonCount])
watermelon.splice(melonCount, 1)
melonCount--
}
}

AS3 how do I control a movieclip in a peer to peer instance swf?

I've made a app using netconnection and netgroup in Flash CS6. I'm trying to build a simple 2-player multiplayer game. When 2 two players are connected I would like to hide a movieclip in one of the instances of the swf but not the other. How is that done?
It's a turn-based game so when player 1 takes his turn player 2 must not be able to click a button (so I want to hide it) and vice-versa.
I think it's working now. In the move function I added ok_mc.visible=false which hides the mc in the "local" instance and the put ok_mc.visible=true in the netstatus event. Like this
function drop(e:MouseEvent):void {
this.stage.removeEventListener(MouseEvent.MOUSE_MOVE, moveMe);
// Save the current movieclip position
var obj:Object = {};
obj.x = mc.x ;
obj.y = mc.y ;
obj.activePlayer=players[aktiv-1]
ok_mc.visible=false;
// Set the peerID to a group address suitable for use with the sendToNearest() method.
obj.sender = group.convertPeerIDToGroupAddress(nc.nearID);
obj.id = new Date().time;
// Sends a message to all members of a group.
group.post(obj);
}
function netStatus(event:NetStatusEvent):void{
switch(event.info.code){
case "NetGroup.Posting.Notify":
mc.x = event.info.message.x;
mc.y = event.info.message.y;
ok_mc.visible=true;
break;
}
}
It seems to work. Now I just have to figure out to show it at init in the first instance. Is there a way to count groupmembers and/or loop through them?

Dispatch event on every frame for MovieClip

I have a Movie Clip, and I need to stop the movie when it's reaches a certain frame. To do this, I need to add an event listener that will dispatch when that specific movie clip enters a new frame (as opposed to the whole animation ENTER_FRAME).
bar.addEventListener(Event.ENTER_FRAME, function(e:Event) {
var b:MovieClip = MovieClip(e.currentTarget);
if(b.currentFrame == mp.getPopularity())
b.stop();
});
Any ideas?
Thanks.
Try this;
A simple function:
function playUntil(target:MovieClip, frame:int):void
{
target.stopFrame = frame; // Works because MovieClip is dynamic.
target.addEventListener(Event.ENTER_FRAME, _checkFrame);
}
With the listening function:
function _checkFrame(e:Event):void
{
var m:MovieClip = e.target as MovieClip;
if(m.currentFrame == m.stopFrame)
{
m.stop();
m.removeEventListener(Event.ENTER_FRAME, _checkFrame);
}
}
Apply it to all your instances:
playUntil(instance1, 15);
playUntil(instance2, 27);
playUntil(instance3, 113);
You should remove the event listener when it's no longer needed, otherwise you risk memory leaks. An anonymous function can make this difficult, though you might be able to do it with arguments.callee.
bar.addEventListener(Event.ENTER_FRAME, function(e:Event) {
var b:MovieClip = MovieClip(e.currentTarget);
if(b.currentFrame == mp.getPopularity()){
b.stop();
b.removeEventListener(e.type, arguments.callee);
// ^^ this may work to remove your anonymous listener.
}
});
There's another way to go about this, though. Does mp.getPopularity() change frequently? If it does not change after bar is told to play() then you could use addFrameScript. Just remember that addFrameScript is 0-indexed, so adding a script to frame 1 means you have to pass 0... so if an action is to happen on mp.getPopularity() then you'll have to pass mp.getPopularity() - 1.
var framescript:Function = function():void{
bar.stop();
bar.addFrameScript(bar.currentFrame-1, null);
// ^^ nulling the framescript after
// ^^ it is no longer needed.
}
bar.stop(); // Generally a good idea to call stop before calling addFrameScript
bar.addFrameScript(mp.getPopularity() - 1, framescript);
bar.gotoAndPlay(1); // or wherever it needs to start from.
This is a more precise solution, but you do have to remember to clean up your framescript after you're done, if you plan to use this same bar instance later with a different mp.getPopularity() value.