Flash AS3 IF statement - actionscript-3

I have made a flash application in which you need to match an object. So below, I am setting the objects (ship, obj1,obj2,obj3) to targets (t1,t2,t3,t4). I am then setting the score to 0.
private function onAddedToStage(e:Event):void
{
stage.addEventListener(MouseEvent.MOUSE_UP, _check);
removeEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
addEventListener(Event.REMOVED_FROM_STAGE, onRemovedFromStage);
ship.setTarget(t1,shipObject);
obj1.setTarget(t2,1Object);
obj2.setTarget(t3,2Object);
obj3.setTarget(t4,3Object);
score = 0;
scorecounter.text =" SCORE:" + score.toString();
}
next, I created a function which finds out if the object, in this case the ship, has reached the target.
function _check(event:TimerEvent):void
{
if(ship.done)
{
score += 1;
scorecounter.text =" SCORE:" + score.toString();
}
}
This works correctly, because once the user drags the ship to the target, it adds +1 to the score, but then an issue occurs. I have more than one object/target. This means when the user completes moving the ship to the target, any other objects that become moved instantly give a +1 to the score, because the object ship is still at the target.
Anybody got any ideas how to fix this?
Many Thanks.

Hmmm... a little difficult to capture what is going on without the full code, but here is a shot:
I notice that your "ship" object has a property "done", so I am guessing you created a variable/property on the object called "done", which makes me think that you can add another property to the ship like "scored"
so your code might look something like this:
if ((ship.done) && (ship.scored == false)){
ship.scored = true;
score += 1;
scorecounter.text = "SCORE:" + score.toString();
}
Is that possible for you?

Related

AS3 Psuedo 3D Z-Indexing

I am attempting to make a really basic Pseudo 3D game in AS3. When I press certain keys my character moves up and down but what I want to happen is when the characters y position is above an objects y position then the character should appear behind the object.
Here is my code for an objects class at the moment:
package {
import flash.display.MovieClip;
import flash.utils.getTimer
import flash.events.Event;
public class bushMC extends MovieClip {
private var lastFrame:int = new int(0);
private var dt:Number = new Number();
private var main:Main;
public function bushMC(){
main = this.parent as Main;
stage.addEventListener(Event.ENTER_FRAME, update);
trace(main.getChildIndex(this));
}
private function update(e:Event):void{
dt = (getTimer() - lastFrame)/30;
lastFrame = getTimer();
if(main.char.y + 200 < this.y + 55 && main.getChildIndex(main.char) > main.getChildIndex(this)){
main.setChildIndex(this, main.getChildIndex(main.char)+1);
}
else if(main.getChildIndex(main.char) < main.getChildIndex(this)){
main.setChildIndex(this, main.getChildIndex(main.char));
}
}
}
}
I have tried editing loads of the values(+1, -1, equal to) for each calculation but I can't seem to find the right ones. One I tried almost works but instead when the char is supposed to be behind the object it simply flickers in-front and then behind continuously.
Thanks in advance, Kyle.
I just tried a little quick mock script based off your code. I got it working how I assume you are attempting to get it to work:
import flash.events.Event;
import flash.display.MovieClip;
var char:MovieClip = new MovieClip();
var bush:MovieClip = new MovieClip();
char.graphics.beginFill(0xFF0000);
char.graphics.drawCircle(0, 0, 30);
bush.graphics.beginFill(0x00FF00);
bush.graphics.drawEllipse(0, 0, 40, 80);
this.addChild(char);
this.addChild(bush);
bush.x = 100+(Math.random()*350);
bush.y = 100+(Math.random()*200);
this.addEventListener(Event.ENTER_FRAME, updateYPos);
function updateYPos(e:Event):void {
char.x = mouseX;
char.y = mouseY;
if(char.y < bush.y + 30 && this.getChildIndex(char) >= this.getChildIndex(bush)){
this.setChildIndex(bush, this.getChildIndex(char));
}
else if(char.y > bush.y + 30 && this.getChildIndex(char) < this.getChildIndex(bush)){
this.setChildIndex(bush, this.getChildIndex(char));
}
}
I hope this sample is enough to help you. All it needed was an extra condition on the else if and it works. :)
You should have a sorted list of bushes somewhere, which is then added via addChild() in the right order - uppermost bush has lowermost Z-position (child index 0 or the least of bushes, there could be other objects). Then, as your player moves, you track its position relative to list of bushes, so you don't run the full list check for z-ordering of player, but only check "nearest" bushes for possible change, then you set child index of player to found value. Note that if you're setting child index of player to bush's index, if you are moving player forwards (greater indexes), set to -1, as the bush will actually be one position lower because of player occupying a position in the display list, and if you are setting child index to lower values, set to equal. There is a more elegant version of this, using the fact that your bushes are continuous within display list, with only interruption being player, although it will run out of steam once more moving objects will appear.
And yes, you run update on the player or any other moving objects, not on the bush.
function updateZPos(e:Event):void {
// process coordinates change
var p:DisplayObjectContainer=this.parent;
// a bit faster to use function local var to get parent
var ci:int=p.getChildIndex(this); // changeable, get current index
var prev:DisplayObject=null;
if(ci>0) prev=p.getChildAt(ci-1);
var next:DisplayObject=null;
if(ci<p.numChildren-1) next=p.getChildAt(ci+1);
while(prev) {
if (this.y<prev.y) {
ci--;
p.setChildIndex(this,ci);
if (ci>0) prev=p.getChildAt(ci-1); else prev=null;
} else break;
while(next) {
if (this.y>next.y) {
ci++;
p.setChildIndex(this,ci);
if(ci<p.numChildren-1) next=p.getChildAt(ci+1); else next=null;
} else break;
}
}
This function was written with implication of display list of p being pre-sorted, and will maintain sorted state of it after moving of this, and is suitable for any moving object, not just the player. For this to work without messing up your other objects, separate everything moving into one container which will then get referenced as base for sorting display list. Otherwise your player might eventually get above all as the last element to check will be say score textfield with Y of 0. Also you will need to maintain coherent position of register point all over your set of moving objects' classes, so that say the base of a bush will be at Y=0 instead of being at Y=30, as implied in your code. The legs of a player should then also be at Y=0.

ActionScript 3.0 HitTestObject on an Array

Good afternoon everyone!
I have a small problem in ActionScript 3.0 with hitTestObject.
I would like to chechk if my character hits a platform (I'm making a simple platform game.).
I have a platform object exproted for action script , and i add childs frim this to an array.
Until this point everything goes well, i can put them on stage etc.
I have written a cycle to chechk if my caharacter hits the platform but it doesn't works correctly. My character falls throught the first platforms and only stop's falling when it hits the last platform. (So for the last in the array it works well.)
And now here is this part from my code, i hope someone can help me with it. :)
import flash.events.Event;
import flash.geom.Rectangle;
stop();
var vy:Number=0;
var gv:Number=1;
var sebesseg:Number=4;
var jumped:Boolean=false;
var stay:Boolean=false;
var level:Array=new Array ;
var gravity:Number=2;
var velocity:Number=1.1;
var platform0:MovieClip=new platform ;
level.push(addChild(platform0));
level[0].x=200;
level[0].y=450;
var platform1:MovieClip=new platform ;
level.push(addChild(platform1));
level[1].x=700;
level[1].y=650;
var platform2:MovieClip=new platform ;
level.push(addChild(platform2));
level[2].x=1000;
level[2].y=800;
stage.addEventListener(Event.ENTER_FRAME, cameraFollowCharacter);
function cameraFollowCharacter(evt:Event) {
root.scrollRect=new Rectangle(PORK1_mc.x-(stage.stageWidth/2)+320,PORK1_mc.y-(stage.stageHeight/2)-50,stage.stageWidth,stage.stageHeight);
}
stage.addEventListener(KeyboardEvent.KEY_DOWN,gomb);
function gomb(k:KeyboardEvent):void {
trace(k);
if (k.keyCode==37) {
if (sebesseg==2) {
sebesseg=sebesseg+0;
} else {
sebesseg-=1;
}
} else if (k.keyCode==39) {
sebesseg+=1;
} else if (k.keyCode==Keyboard.ESCAPE) {
stop();
root.scrollRect=new Rectangle (stage.x,stage.y,stage.stageWidth,stage.stageHeight);
gotoAndStop(2);
} else if (k.keyCode==Keyboard.F1 && stay==false) {
stage.frameRate=0;
stay=true;
} else if (k.keyCode==Keyboard.F1 && stay==true) {
stage.frameRate=24;
stay=false;
}
}
stage.addEventListener(Event.ENTER_FRAME, megy);
function megy(e:Event):void {
PORK1_mc.x+=sebesseg;
gravity*=velocity;
PORK1_mc.y+=gravity;
//trace(velocity);
}
THIS PART IS THE PROBLEM, HITTESOBJECT ONLY WORKS FOR THE LAST PLATFORM
PORK1_mc.hitPork_mc this is my character (hitPork_mc is an invisible rectangle for better HitTestObject. So as i wrote my char. falls throught the platfroms until the last one, he falls on tha last and stops falling, so for the last platform in the array it works perfectly.
I wouldn't like to change a lot on my code, only on the hitTest part if its possible.
this.addEventListener(Event.ENTER_FRAME, handleEnterFrame);
function handleEnterFrame(e:Event):void {
for (var i:int = 0; i < level.length; i++) {
if (level[i].hitTestObject(PORK1_mc.hitPork_mc)) {
velocity=0;
} else {
velocity=1.1;
gravity=4;
}
}
}
Thanks for every help in advance!
With your original code, you do the following for each platform:
If there is a collision, set velocity to zero.
If not, set velocity to 1.1.
Since you do this in order, here's what happens when you collide with platform 1 but not 2 or 3:
The collision with 1 sets your velocity to zero.
The collision with 2 sets your velocity to 1.1.
The collision with 3 sets your velocity to 1.1.
Since these happen all in a row in the same frame, the end result is that your character never stops unless the collision is with platform 3.
By returning after setting velocity to zero, you are breaking out of the loop, preventing your collision work from being undone. What you are doing will work, but you can also do it another way which is less concise but may make more sense:
function handleEnterFrame(e:Event):void
{
var collided:Boolean = false; //This will record if you collided or not.
for (var i:int = 0; i < level.length; i++)
{
if (level[i].hitTestObject(PORK1_mc.hitPork_mc))
{
collided = true;
}
}
if(collided) velocity = 0;
else
{
velocity=1.1;
gravity=4;
}
}
Note that here we're not applying velocity and gravity inside the for loop because we don't want it to happen for each object we might collide with. Instead, we set it once, after we've determined if we collide with any objects.
This also helps show that you are setting gravity every frame you don't collide even though there doesn't seem to be any point at which you set it to zero; I suspect this is something you want to fix.

Supplied DisplayObject must be a child of the caller

I get this error once in a while for a specific object. For some reason, this issue seems to start when I spawn 2 of this object instead of one. I basically have enemies that drops coins and one enemy drops 2. When I pick them up at the same time I start getting this error.
public function removeCoin(){
removeEventListener(Event.ENTER_FRAME, moveCoin);
if(this.parent){
this.parent.removeChild(this);
}
parentMC.level.spawnedCoins.splice(this, 1);
}
This is the function called by the collision check when there is a collision between the player and the coin. The issue usually starts when I pick up two coins at once from this function.
var dropCoin:Number = Math.random() * 100;
if(dropCoin > 40){
var newCoin1:coin = new coin(parentMC);
var newCoin2:coin = new coin(parentMC);
newCoin1.x = x+7;
newCoin1.y = y;
parentMC.level.levelObjects.addChild(newCoin1);
parentMC.level.spawnedCoins.push(newCoin1);
newCoin2.x = x-7;
newCoin2.y = y;
parentMC.level.levelObjects.addChild(newCoin2);
parentMC.level.spawnedCoins.push(newCoin2);
}
Edited the code.
That error means that the item you're trying to remove from the display list (by calling removechild) either isn't on the display list, or isn't a child of the object your calling removeChild on.
Without analyzing all your code, a quick check can fix your problem likely.
Change you existing chunk of code:
if(this != null){
parentMC.lvl1.levelObjects.removeChild(this);
}
to this:
if(this.parent){
this.parent.removeChild(this);
}
This checks if 'this' has a parent, if so, it removes itself from it's parent.
I think your problem might be:
parentMC.level.spawnedCoins.splice(this, 1);
If spawnedCoins is just an array then splice should take 2 integer args startIndex and deleteCount relevant adobe help page
By passing an object what I think is happening is that it is casting the object to an int, value of '1' (i.e. not null).
What I think you want instead is parentMC.level.spawnedCoins.splice(parentMC.level.spawnedCoin.indexOf(this), 1);

Actionscript 3: Healthbar and Button

So basically I am making a game in which a button is clicked to decrease the amount of health in a healthbar. I have a button on the stage named fortyfivedown_btn, and a healthbar, which is a 101 frame (includes zero) movieclip. The health bar has an instance name of lifebar. On the stage, the button coding is:
fortyfivedown_btn.addEventListener(MouseEvent.CLICK, fortyfivedownClick);
function fortyfivedownClick(event:MouseEvent):void{
lifebar.health = lifebar.health-45;
}
Inside the healthbar movieclip, I have a layer of coding that is:
var health:int = 100;
gotoAndStop(health + 1);
if(health < 0) health = 0;
else if(health > 100) health = 100;
gotoAndStop(health + 1);
So, there is my coding. The thing is, when the button is clicked, the healthbar does not go down. I traced the health variable in the button:
fortyfivedown_btn.addEventListener(MouseEvent.CLICK, fortyfivedownClick);
function fortyfivedownClick(event:MouseEvent):void{
lifebar.health = lifebar.health-45;
}
{
trace(lifebar.health);
}
I saw that the output is 0. For some reason the button believes the health is 0, when I declared it was 100 inside the healthbar movieclip? Any help is appreciated.
(Edit)
Alright, in answer to the trace question, if I don't do it like that, there is no output. I should say I'm a beginner at this all, and am learning as I go, so please bear with me. Here is my fla file:
https://skydrive.live.com/embed?cid=9AB08B59DCCDF9C6&resid=9AB08B59DCCDF9C6%21107&authkey=AGqFHhlHnvOXvuc
Okay so take the code that was in your lifebar movie clip out entirely, you can just delete that layer for now, then replace the code you have in the main scene with this and you should get the result you want:
fortyfivedown_btn.addEventListener(MouseEvent.CLICK, fortyfivedownClick);
var health:int = 100;
lifebar.gotoAndStop(101);
function fortyfivedownClick(event:MouseEvent):void{
health -= 45;
if(health < 0) health = 0;
else if(health > 100) health = 100;
lifebar.gotoAndStop(health + 1);
//Can write this also: lifebar.health += 45;
trace(health);
}
there's other ways to go about doing this but given your current setup this is going to be the least modification to get what you want. Another option is setting the width on a sprite.
I uploaded a modified fla and companion as file for how I would personally go about doing this instead of including things on the timeline so much:
http://www.mediafire.com/?d38hbm32p71x1n8

Detect position?

I'm trying to create a simple game with a boat moving between left and right by the keys. The moving is OK, but when I try to detect the left och right end it doesn't work at all. Below is a part of the code. What could be wrong?
stage.addEventListener(Event.ENTER_FRAME,moveBoat);
function moveBoat(event:Event):void {
if(! boat.x >= 700){
if(moveLeft) {
boat.x -= 5;
boat.scaleX = 1;
}
if (moveRight) {
boat.x += 5;
boat.scaleX = -1;
}
}
}
If you've solved your collisions problem, here's an answer for your dropping bombs problem. Doing it by having 5 boolean variables would be a rather unrefined way of doing it; instead simply use an integer to record how many bombs your boat has left to drop, and each time it drops one, reduce this value by 1. Here's some example code:
//Create a variable to hold the number of bombs left.
var bombsLeft:int = 5;
//Create an event listener to listen for mouse clicks; upon a click, we'll drop a bomb.
addEventListener(MouseEvent.CLICK, dropBomb);
//The function dropBomb:
function dropBomb(event:MouseEvent):void
{
if (bombsLeft > 0)
{
//Create a new instance of the Bomb class; this could be an object in your Library (if you're using the Flash IDE), which has a graphic inside it of a bomb.
var newBomb:Bomb = new Bomb();
//Position the bomb.
newBomb.x = boat.x;
newBomb.y = boat.y;
//Add it to the stage
addChild(newBomb);
//Reduce the number of bombs you have left.
bombsLeft--;
}
//At this point you could check if bombsLeft is equal to zero, and maybe increase it again to some other value.
}
This doesn't include code to then move the bomb downwards, but you can do that fairly simply using an update loop. If you're struggling to do that, let me know and I'll give you another example.
Hope that helps.
debu