HitTestObject issues - actionscript-3

I have a bit of a problem with hitTestObject in Flash.
I have these tiles generated on the screen and I have a player added to the tiles. I created an invisible square bitmap for the player, which is the size of the tile so it can register whether it is hitting the tile completely. The problem is, it is registering hit test from tiles that aren't even next to the player. The link below, My mouse is over the tile that is highlighted, and I have a trace that checks the hitTest between the player and the current Tile that it's on.
http://postimg.org/image/6so3npm19/
Here is the code for the bitmap. I've been playing around with the x and y position and the size of it.
visionArea.graphics.beginFill(0x00FF00, 1.0);
visionArea.graphics.drawRect(0, 0, 85, 85);
visionArea.graphics.endFill();
var matrix:Matrix = new Matrix();
matrix.rotate(Math.PI / 4);
matrix.scale(1, 0.5);
visionArea.transform.matrix = matrix;
addChild(visionArea);
visionArea.mouseEnabled = false;
visionArea.visible = false;
visionArea.x = 4;
visionArea.y = -21;
When I click a tile and the player is next to it, I move it to that tile.
if (player.visionArea.hitTestObject(event.currentTarget as Tile))
{
player.x = (event.currentTarget.x)+55;
player.y = (event.currentTarget.y)+20;
}
I also have an enemy on the screen (the green tile). I'm trying to have the player not be able to go on the tile that the enemy is on, but sometimes it would work, sometimes it wouldn't.
if (enemy.enemyVisionArea.hitTestObject(event.currentTarget as Tile))
{
player.x != (event.currentTarget.x)+55;
player.y != (event.currentTarget.y)+20;
}

if (player.visionArea.hitTestObject(event.currentTarget as Tile) && !enemy.enemyVisionArea.hitTestObject(event.currentTarget as Tile))
{
player.x = (event.currentTarget.x)+55;
player.y = (event.currentTarget.y)+20;
}
I've never seen anyone use != as an assignment operator.

Related

How to create smooth motion for a mouse follower along a predefined path?

I want to make a tracing game. I want my circle to follow the path as the user traces the letter (path of the letter). The user can not go back to the area which is already traced
import flash.events.Event;
import flash.geom.Point;
var i: Number;
var size: int = 80;
var down: Boolean = false;
var up: Boolean = true;
var inside: Boolean = true;
var outside: Boolean = true;
var circle: Shape = new Shape();
stage.addEventListener(Event.ENTER_FRAME, loop);
stage.addEventListener(MouseEvent.MOUSE_UP, mouseup);
char.addEventListener(MouseEvent.MOUSE_DOWN, mousedown);
function loop(e: Event) {
if (down == true) {
// Checks if mouse pointer is on path i.e 'S' alphabet
if (s.hitTestPoint(stage.mouseX, stage.mouseY, true)) {
inside = true;
outside = true;
var point: Point = maskobj.globalToLocal(new Point(stage.mouseX, stage.mouseY));
var point2: Point = new Point();
//Checks if mouse pointer is completely outside of drawn area
for (i = 0; i < 2 * Math.PI; i += (2 * Math.PI) / 10) {
point2.x = stage.mouseX + (size / 3) * Math.cos(i);
point2.y = stage.mouseY + (size / 3) * Math.sin(i);
if ((maskobj.hitTestPoint(point2.x, point2.y, true))) {
outside = false;
break;
}
}
//Checks if mouse pointer is completely inside drawn area
for (i = 0; i < 2 * Math.PI; i += (2 * Math.PI) / 10) {
point2.x = stage.mouseX + (size / 3) * Math.cos(i);
point2.y = stage.mouseY + (size / 3) * Math.sin(i);
if (!(maskobj.hitTestPoint(point2.x, point2.y, true))) {
inside = false;
break;
}
}
//Character will be moved only if mouse position not to far from current position
if (outside == false) {
if (inside == false) {
//Increases drawn area by drawing a circle shape in 'maskobj' MovieClip
circle.graphics.beginFill(0x0000ff);
circle.graphics.drawCircle(point.x, point.y, size);
circle.graphics.endFill();
maskobj.addChild(circle);
//Moves character to new position
char.x = stage.mouseX;
char.y = stage.mouseY;
}
}
}
}
}
function mouseup(e: MouseEvent): void {
up = true;
down = false;
}
function mousedown(e: MouseEvent): void {
down = true;
up = false;
}
When I trace the path,the motion is not smooth. Can someone please suggest a way to make the motion smooth OR suggest another way to achieve the same. Thank you in advance.
I've created a drawing game before that allowed the user to draw a path.
Not sure why Wicked's answer was down-voted, as the first thing you need to do is to use the highest frame rate that you can get away with. The higher the frame rate, the smoother your curve.
I see that your code draws a circle at the current position if the conditions are met. It might be better to draw a line from the last point.x/point.y to the current one instead of just a circle, so that you don't have any holes in your path.
I couldn't get around the fact that the line was jagged (a series of straight lines) as it was being drawn, but as soon as the user lifted their finger I was able to take the points along the line they had drawn and replace them with a smooth bezier Path (a series of simple bezier curves), which worked well. You could also do this on-the-fly once you have 3 points (you need 3 points to draw a curve).
Here is a good reference on how to achieve this, with theory and code samples. See further down the page for bezier paths. You'll need to convert to AS3, but it shouldn't be difficult.
Another tip is to do as little calculation as possible within the ENTER_FRAME. You could pre-calculate the two values used by your loops (2 * Math.PI) and ((2 * Math.PI) / 10) as these are constants. You could also calculate (size/3) once at the top of the function, and especially pre-calculate the 10 values for Math.sin(i) and Math.cos(i) and store them in an Array (basically a LUT - Look Up Table) as these are the heaviest math ops you're doing.
My final tip is that your code doesn't check if the point being drawn is very close to the last point that was drawn. I would recommend you do this, and only draw a point after the mouse has moved a minimum distance (e.g. 2 pixels). Otherwise you could get the mouse sitting still in one spot and your code is drawing circle upon circle on top of itself needlessly.
Try increasing the FPS in your document to atleast double what you currently have
Modify>Document...>Frame Rate

Collision with Bitmap AS3

So I created a nice collision system shown here. Now I have my own character sprite, which has messed up the collision on all sides.
edit: because people are misunderstand what I want, I WANT it to overlap on the bottom and top, it gives it a 3D effect. My problem is that it's colliding incorrectly with the bitmap
I've tried using the pixel perfect collision system but I have a problem with it:
It only detects collision right at the edge, as you can see in the video, the ball can go slightly in front and behind the wall like it wasn't just a flat plane.
code responsible for the current collision (it did have some other stuff but that's been removed):
for each (var wall in Walls)
{
if (wall.hitTestPoint(Character.x, Character.y, true)) //col right
{
Character.x+=CharacterSpeed;
}
if (wall.hitTestPoint(Character.x, Character.y, true)) //col left
{
Character.x-=CharacterSpeed;
}
if (wall.hitTestPoint(Character.x , Character.y, true)) //col bottom
{
Character.y+=CharacterSpeed;
}
if (wall.hitTestPoint(Character.x, Character.y, true)) //col top
{
Character.y -= CharacterSpeed;
}
}
That is correct (and I mean that's what the code does) and that effect depends on framerate as well.
The principle is easy to understand. ex: You move an object by 5 pixels, the colliding object is 3 pixels away, when you test for collision you have an overlap of 2 pixels. To correct this you need what's called a TOI (time of impact) algorithm.
As of right now there's no fixing your code because you apply a motion is the inverse way it's supposed to work. You move first then you test while the correct way is you test then you move. For example:
you are about to move the object by x pixels.
test if the object + x pixels will collide.
if it will collide calculate by how much you should move it then move it by x pixels - corrected pixels.
if it will not collide then move it by x pixels.
As you see you do the opposite:
move by x pixels.
test for collision.
The result is overlapping objects.
What you can do as a hack without changing your code is calculate the overlapping and then correct the object position.
you can try draw your objects to a BitmapData using BitmapData.draw method, and than use BitmapData.hittest, here a sample:
import flash.display.BitmapData;
import flash.geom.Point;
var myBitmapData:BitmapData = new BitmapData(100, 80, false, 0x00CCCCCC);
var mc_1:MovieClip = this.createEmptyMovieClip("mc", this.getNextHighestDepth());
mc_1.attachBitmap(myBitmapData, this.getNextHighestDepth());
var mc_2:MovieClip = createRectangle(20, 20, 0xFF0000);
var destPoint:Point = new Point(myBitmapData.rectangle.x, myBitmapData.rectangle.y);
var currPoint:Point = new Point();
mc_1.onEnterFrame = function() {
currPoint.x = mc_2._x;
currPoint.y = mc_2._y;
if(myBitmapData.hitTest(destPoint, 255, currPoint)) {
trace(">> Collision at x:" + currPoint.x + " and y:" + currPoint.y);
}
}
mc_2.startDrag(true);
function createRectangle(width:Number, height:Number, color:Number):MovieClip {
var depth:Number = this.getNextHighestDepth();
var mc:MovieClip = this.createEmptyMovieClip("mc_" + depth, depth);
mc.beginFill(color);
mc.lineTo(0, height);
mc.lineTo(width, height);
mc.lineTo(width, 0);
mc.lineTo(0, 0);
return mc;
}

Camera Movement with Character - AS3

So I'm creating a simple 2d game in the vein of bitrunner, with character moving to the right. And I'm having trouble getting the camera to stick to the character.
I'm very much in the beginning of learning as3 and have never done this kind of thing before. I've looked up for examples of this, but so far I haven't found any simple code that I understood enough to put into my game. And quite a few say it is so simple, that I shouldn't need code to do it...but I do.
I'm better at learning from code I can see, than someone explaining it to me.
//stop/start animations
Player.stop();
rocket_1.play();
//variables
var gravity = 5;
var speedy = 20;
var speedx = 5;
//event listeners
stage.addEventListener(KeyboardEvent.KEY_DOWN,charMove);
stage.addEventListener(KeyboardEvent.KEY_UP, stand);
stage.addEventListener(Event.ENTER_FRAME, grav);
function grav(event:Event): void{
Player.y += gravity;
}
//functions
function charMove(event:KeyboardEvent): void{
switch (event.keyCode){
case Keyboard.RIGHT:
trace("I've been pressed right");
Player.x += speedx;
Player.play();
break;
case Keyboard.SPACE:
trace("space");
Player.y -= speedy;
break;
}
}
function stand(event:KeyboardEvent): void{
Player.gotoAndStop(1);
}
In Flash there is no default Camera,
there is a stage, with a size, width and height,
so if you character move outside the stage, you canĀ“t see it anymore.
so you have to make everything move on x axis, but not your character..

Sounds still playing in another frame

Hey I am still getting some unwanted sound effects still playing in another frame, for example when I click my left mouse button which is also my jump button it will play the jump sound as well as playing the collect coins sound wierdly even though i remove each child from the stage when going to the game over screen.
Now im a bit unfamiliar with the sound channel so if its needed to be used please be kind and explain :)
In Frame 1:
var myMusic1:Sound = new Game_Over_Noise();
var myMusic2:Sound = new Jump_Noise();
var myMusic3:Sound = new Coin_Noise();
var myMusic4:Sound = new Power_Up_Noise();
var myMusic5:Sound = new Theme();
var channel:SoundChannel = myMusic5.play();
In Frame 8, Game Screen:
function doJump(evt:MouseEvent):void
{
if(!isJumping) //If the player is jumping.
{
jumpPower = 30; //Jump power is equal to 30.
isJumping = true; //isJumping variable is also equal to true.
var channel:SoundChannel = myMusic2.play(); //Play sound effect.
}
}
function update(evt:Event):void
{
if(isJumping) //If the player is jumping.
{
MainChar.y -= jumpPower; //Subtract the value of jumpPower from the player's y co-ordinate.
jumpPower -= 2; //Decrease the value of jumppower by 2.
}
if(MainChar.y + gravity < ground) //If the value of the player's Y co-ordinate and gravity is less than ground.
MainChar.y += gravity; //Then add the value of gravity to the player's Y co-ordinates.
else //else
{
MainChar.y = ground; //The players Y co-ordinate is equal to ground.
isJumping = false; //Make isJumping equal to false.
}
}
in Frame 5, Game Over Screen:
SoundMixer.stopAll();
Now this stops the theme music and not the sound effects, now i actually dont mind the theme tune playing all the time but i would like ALL sound effects (game sounds) to only play in the game.
I know my coding isnt the best and efficient but its easily readible to me, I appreciate the help! :D
Looks to me like you need to remove your event listeners (they're active even when something is off-stage).

Zooming and translate in as3 AIR Android

I am developing an android app with Adobe Flash cs6 and actionscript3. I have multiple moviclips at various locations on stage. Now I need to add a zoom feature that will zoom all movieclips as one movieclip. I cannot combine all movieclips together into one movieclip. My zoom feature works but it does not translate the movieclips to a new position. (Meaning they zoom at their original positions only) How can I accomplish this? Following is my zooming code :
/* ZOOM FEATURE */
Multitouch.inputMode = MultitouchInputMode.GESTURE;
zoomer.addEventListener(TransformGestureEvent.GESTURE_ZOOM , onZoom);
function onZoom (e:TransformGestureEvent):void{
mc1.scaleX *= (e.scaleX+e.scaleY)/2;
mc1.scaleY *= (e.scaleX+e.scaleY)/2;
mc2.scaleX *= (e.scaleX+e.scaleY)/2;
mc2.scaleY *= (e.scaleX+e.scaleY)/2;
mc3.scaleX *= (e.scaleX+e.scaleY)/2;
mc3.scaleY *= (e.scaleX+e.scaleY)/2;
}
Not the cleanest code I've written, but it should do the trick. scaleInPlace() accepts 4 arguments, 2 required, two optional:
obj: the display object you want to scale
scaleFactor: just as it sounds, how big/small do you want it?
fromX: the X coordinate where you want to scale from. Left, middle, right? If omitted, it operates from the middle of the compiled stage size.
fromY: same as the previous, but for top, middle, bottom.
This will preserve your DisplayList hierarchy while allowing you to scale to your heart's desire. If you had a lot of objects to scale, I'd probably parent all of them to the container first, and then run the scale and reparenting operations. While it works, this is the reason I feel it's not the "cleanest" solution. In my own classes, I've written a purely mathematical solution that doesn't include adding/removing DisplayObjects, but it's fairly tied up in my own classes I couldn't pull it out here and have it work.
Cheers!
// Let's scale myObject to 50% of its original size.
scaleInPlace(myObject, 0.5);
function scaleInPlace(obj:DisplayObject, scaleFactor:Number, fromX:Number = NaN, fromY:Number = NaN):void {
// If no coordinates from where to scale the image are provided, start at the middle of the screen
if (isNaN(fromX)) { fromX = loaderInfo.width/2; }
if (isNaN(fromY)) { fromY = loaderInfo.height/2; }
var father:DisplayObjectContainer = obj.parent;
var rect:Rectangle; // Coordinates for tracking our object
var index:int = getChildIndex(obj) // Where this object should go when we put it back
// Create the container
var container:Sprite = new Sprite();
father.addChild(container);
// Place the origin of the scale operation
container.x = fromX;
container.y = fromY;
// Get the coordinates of our object relative to our container
rect = obj.getRect(container);
// Parent and move into place
container.addChild(obj);
obj.x = rect.x;
obj.y = rect.y;
// Scale
container.scaleX = container.scaleY = scaleFactor;
// Get the coordinates and size of our scaled object relative to our father
rect = obj.getRect(father);
// Cleanup the display list
father.addChildAt(obj, index);
father.removeChild(container)
// Apply the new coordinates and size
obj.x = rect.x;
obj.y = rect.y;
obj.width = rect.width;
obj.height = rect.height;
}