Camera following object - actionscript-3

I am fairly new to coding. I am was wondering if there was a way so when I move my object with keys I can get the camera to keep on my object so I can move around a larger world than just my viewport.
I have tried to move the world around instead of my object but for what I am doing it makes my coding a lot more difficult
Here is the code I have.
stage.addEventListener(KeyboardEvent.KEY_DOWN, keydown );
function keydown (event:KeyboardEvent):void{
switch (event.keyCode){
case Keyboard.LEFT :
ball.x -= 10;
break ;
case Keyboard.RIGHT :
ball.x += 10;
break;
case Keyboard.UP :
ball.y -= 10;
break;
case Keyboard.DOWN :
ball.y += 10;
break;
default :
break;
}
}

you could have the world and the character in a holding sprite/movieclip
then as you move the character, you can set the position of the holder in the opposite direction.
you can use global to local to get the position of the ball, and then can even apply some movement smoothing
here's some code that should work easy enough
you need a movieclip called holder inside that is ball , the holder would also have your world and world assets. And as long as there's no scaling you don't need to use globalToLocal
var middlePt:Point = new Point(stage.stageWidth/2, stage.stageHeight/2);
var pt:Point = new Point(holder.ball.x, holder.ball.y);
var destPoint:Point = new Point(-pt.x + middlePt.x, -pt.y + middlePt.y);
addEventListener(Event.ENTER_FRAME,enterFrame);
function enterFrame(e:Event):void{
holder.x = holder.x*0.5 + destPoint.x*0.5;
holder.y = holder.y*0.5 + destPoint.y*0.5;
}
stage.addEventListener(KeyboardEvent.KEY_DOWN, keydown );
function keydown (event:KeyboardEvent):void{
switch (event.keyCode){
case Keyboard.LEFT :
holder.ball.x -= 10;
break ;
case Keyboard.RIGHT :
holder.ball.x += 10;
break;
case Keyboard.UP :
holder.ball.y -= 10;
break;
case Keyboard.DOWN :
holder.ball.y += 10;
break;
default :
break;
}
middlePt = new Point(stage.stageWidth/2, stage.stageHeight/2);
pt = new Point(holder.ball.x, holder.ball.y);
destPoint = new Point(-pt.x + middlePt.x, -pt.y + middlePt.y);
}

Related

AS3 AI barrier detection and movement

I'm using flash CC for school and i am making a top down RPG which i am making using action script 3.
the problem that i am having is multi layered; i need the AI i made to detect the set boundaries, and i need them to change direction when they hit these boundaries. at the moment i have used trace functions to find out when the AI is hitting the boundaries, so i know that that is working. however then it doesn't run the code after that. the map at the moment is a maze so the barriers are a movie clip that have rectangles going over the walls within the maze. it works for the player that the user controls so why won't it work here? below is the code for the AI movement:
switch (guyFacing) { // which way the AI has turned (left, right, up, down) (this is randomly generated below
case 0:
OverworldMC.guyMC.gotoAndStop("walk back frame");
OverworldMC.guyMC.y -= guySpeed;
break;
case 1:
OverworldMC.guyMC.gotoAndStop("walk front frame");
OverworldMC.guyMC.y += guySpeed;
break;
case 2:
OverworldMC.guyMC.gotoAndStop("walk left frame");
OverworldMC.guyMC.x -= guySpeed;
break;
case 3:
OverworldMC.guyMC.gotoAndStop("walk right frame");
OverworldMC.guyMC.x += guySpeed;
break;
}
guyTimer++; //duration that the AI is moving around the screen
} else {
guyWalkDur = Math.random() * 75;
guyFacing = Math.floor(Math.random() * 4);
guyTimer = 0;
}
}
if (OverworldMC.collisionMC.hitTestPoint(OverworldMC.guyMC.x + GleftBumpPoint.x, OverworldMC.guyMC.y + GleftBumpPoint.y, true)) {
trace("GleftBumping");
GleftBumping = true;
} else {
GleftBumping = false;
}
if (OverworldMC.collisionMC.hitTestPoint(OverworldMC.guyMC.x + GrightBumpPoint.x, OverworldMC.guyMC.y + GrightBumpPoint.y, true)) {
trace("GrightBumping");
GrightBumping = true;
} else {
GrightBumping = false;
}
if (OverworldMC.collisionMC.hitTestPoint(OverworldMC.guyMC.x + GupBumpPoint.x, OverworldMC.guyMC.y + GupBumpPoint.y, true)) {
trace("GupBumping");
GupBumping = true;
} else {
GupBumping = false;
}
if (OverworldMC.collisionMC.hitTestPoint(OverworldMC.guyMC.x + GdownBumpPoint.x, OverworldMC.guyMC.y + GdownBumpPoint.y, true)) {
trace("GdownBumping");
GdownBumping = true;
} else {
GdownBumping = false;
}
if (GleftBumping) {
OverworldMC.guyMC.gotoAndStop("walk right frame");
OverworldMC.guyMC.x -= guySpeed;
trace("hitting is true");
}
if (GrightBumping) {
OverworldMC.guyMC.gotoAndStop("walk left frame");
OverworldMC.guyMC.x += guySpeed;
}
if (GupBumping) {
OverworldMC.guyMC.gotoAndStop("walk front frame");
OverworldMC.guyMC.y -= guySpeed;
}
if (GdownBumping) {
OverworldMC.guyMC.gotoAndStop("walk back frame");
OverworldMC.guyMC.y += guySpeed;
}
The aim of this code is to randomly generate an action (which it does), detect when it is hitting the barrier and then act according to how it is interacting with the barrier only i am having some trouble with the last part. Any and all help is appreciated.
Regards.

AS3 game development: attack movements not following suit of movement direction

I'm making a top-down RPG style game, very much a throwback to zelda. This is my code for the movement controls based on keyboard controls. The movement itself is pretty solid, no stutter-key syndrome, all animations are triggered correctly.
However, when the attack button (SPACE in this case) is pressed it triggers the appropriate frame but when the key is released the corresponding frame is still visible, until another direction key is pressed. So, when you attack it looks like he keeps his sword extended until another movement is made, and so on. This should only happen when the key is held down not when simply pressed. This is not the expected result. The result I'm looking for is an attack that triggers every time the key is pressed, creating the normal buttondown=attacking, buttonup = not attacking.
The attacks and movement now are based on a variable moving:int = 4; That way I can switch the attack position to the corresponding movement direction.
Any ideas on how to correct this issue?
import flash.events.Event;
import flash.events.KeyboardEvent;
character.stop();
stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyPress);// when key is pressed
stage.addEventListener(KeyboardEvent.KEY_UP, onKeyRelease);//when key is released
stage.addEventListener(Event.ENTER_FRAME, MainLoop);
var moving:int = 4;
var movingDown:Boolean = false;
var movingUp:Boolean = false;
var movingRight:Boolean = false;
var movingLeft:Boolean = false;
function onKeyPress(e:KeyboardEvent):void
{
switch (e.keyCode)
{
case Keyboard.DOWN : movingDown = true; moving = 1; break;
case Keyboard.UP : movingUp = true; moving = 2; break;
case Keyboard.RIGHT : movingRight = true; moving = 3; break;
case Keyboard.LEFT : movingLeft = true; moving = 4; break;
case Keyboard.SPACE : handleAttack(); break;
}
}
function onKeyRelease(e:KeyboardEvent):void
{
switch (e.keyCode)
{
case Keyboard.DOWN: character.gotoAndStop(1); movingDown=false; moving = 1; break;
case Keyboard.UP: character.gotoAndStop(3);movingUp=false; moving = 2; break;
case Keyboard.LEFT: character.gotoAndStop(5);movingLeft=false; moving = 3; break;
case Keyboard.RIGHT: character.gotoAndStop(7);movingRight=false; moving = 4; break;
case Keyboard.SPACE: handleAttack(); break;
}
}
function handleAttack():void
{
switch (moving)
{
case 1: character.gotoAndStop(9); movingDown = false; break; //down
case 2: character.gotoAndStop(10); movingUp = false; break; //up
case 3: character.gotoAndStop(11); movingLeft = false; break; //left attacks
case 4: character.gotoAndStop(12); movingRight = false; break; //right
}
}
function MainLoop(e:Event):void
{
switch (true)
{
case movingDown: character.gotoAndStop(2); character.y+=4.5; break;
case movingUp: character.gotoAndStop(4); character.y-=4.5; break;
case movingLeft: character.gotoAndStop(6); character.x-=4.5; break;
case movingRight: character.gotoAndStop(8); character.x+=4.5; break;
}
}
I am kinda new myself but i think it's because both onKeyPress() and onKeyRelease() point to the same function handleAttack() and as such point to the same frame even when you release. Try making two seperate attack functions for each one.
e.g
attackPressed() for onKeyPress()
function attackPressed():void
{
switch (moving)
{
case 1: character.gotoAndStop(9); movingDown = false; break;
case 2: character.gotoAndStop(10); movingUp = false; break;
case 3: character.gotoAndStop(11); movingLeft = false; break;
case 4: character.gotoAndStop(12); movingRight = false; break;
}
}
and attackRelease() for onKeyRelease()
function attackRelease():void
{
switch (moving)
{
case 1:character.gotoAndStop(1); movingDown = false; break;
case 2:character.gotoAndStop(3); movingUp = false; break;
case 3: character.gotoAndStop(5); movingLeft = false; break;
case 4: character.gotoAndStop(7); movingRight = false; break;
}
}
Hope this helps.

How to call AS3 Switch

I am struggling a bit with my switch statement (I've never used switch before). I have a hit test for when my object reaches the top or bottom of the stage. When this happens, I want to switch states (the game in question is a simple platformer that allows the player to switch the gravity when they hit a new surface. Below is my current code:
{
...
if(player.hitTestObject(bottom)) {
//Switch state to normal
}
if(player.hitTestObject(top)) {
//Switch state to inverted
}
}
switch (myGrav){
case "NORMAL":
trace("Normal")
player.gotoAndPlay(1);
oktoJump = false;
player.y = 376.5;
case "INVERTED":
trace("Inverted")
player.gotoAndPlay(8);
oktoJump = false;
player.y = 12;
}
Thanks!
Cases within your switch statement are missing a break; therefore, code will continue to execute through the switch statement.
This should be:
var myGrav:String = "NORMAL";
if (player.hitTestObject(bottom))
myGrav = "NORMAL";
if (player.hitTestObject(top))
myGrav = "INVERTED";
switch (myGrav)
{
case "NORMAL":
trace("Normal")
player.gotoAndPlay(1);
oktoJump = false;
player.y = 376.5;
break;
case "INVERTED":
trace("Inverted")
player.gotoAndPlay(8);
oktoJump = false;
player.y = 12;
break;
}
I prefer less variables when I can get away with it.
switch (true){
case (player.hitTestObject(bottom)):
trace("Normal")
player.gotoAndPlay(1);
oktoJump = false;
player.y = 376.5;
break;
case (player.hitTestObject(top)):
trace("Inverted")
player.gotoAndPlay(8);
oktoJump = false;
player.y = 12;
break;
}

AS3 Collision Detection through hitTestPoint for a map based game

I am trying to work out the best way to perform a hitTestPoint for a game with a character, enemies and objects that are non-walkable in the map.
I have created a version that works, which can be seen here:
http://www.hosted101.net/hit/mapHitTest.html (arrow keys to move, you're the square).
Using a previously suggested method, I have created a secondary version of all objects on the map, increased by half the size of the player and am running a hitTestPoint from centerX and centerY of the player.
This is great and works fine.
However, I feel it is not optimal and it could be unnessesary to have all these extra "boundry boxes" created, even if the user can't see them.
So, I created a second version. This time without the boundry boxes:
http://www.hosted101.net/hit/mapHitTestNew.html (arrow keys to move).
As this is still running from centerX and centerY of the player, if you approach an object but are below centerX/Y, you will be able to travel through it.
My question is this: to hitTest objects vs players/enemies/anything on a game like this, what is the best method? (with a fixed example for this simple project would be great)
Is it really creating a duplication of the map layer with additional bounding boxes, or can it be done in a more clean way?
My code is below, for mapHitTestNew.
Thanks.
var moveL:Boolean = new Boolean
var moveR:Boolean = new Boolean
var moveU:Boolean = new Boolean
var moveD:Boolean = new Boolean
var moveSpeed:int = 2
stage.addEventListener(KeyboardEvent.KEY_DOWN, updateKeysDown)
stage.addEventListener(KeyboardEvent.KEY_UP, updateKeysUp)
function updateKeysDown(e:KeyboardEvent){
var _keyCode = e.keyCode
switch (_keyCode){
case 37:
moveL = true;
break;
case 38:
moveU = true;
break;
case 39:
moveR = true;
break;
case 40:
moveD = true;
break;
}
collisionCheck()
}
function updateKeysUp(e:KeyboardEvent){
var _keyCode = e.keyCode
switch (_keyCode){
case 37:
moveL = false;
break;
case 38:
moveU = false;
break;
case 39:
moveR = false;
break;
case 40:
moveD = false;
break;
}
}
/**
***
*** Hit Test
***
***
**/
function collisionCheck():void{
var _MC:MovieClip = new MovieClip;
_MC.x = player.x
_MC.y = player.y
_MC.mouseEnabled = false
var centerX:Number = _MC.x + (player.width/2)
var centerY:Number = _MC.y + (player.height/2)
if(moveL){
trace("Stage 1 Move")
centerX -= moveSpeed
if(map.hitTestPoint((centerX-player.width/2), centerY, true)){
trace("Stage 1 HIT TEST!")
moveL = false
}
}
if(moveR){
trace("Stage 2 Move")
centerX += moveSpeed
if(map.hitTestPoint((centerX+player.width/2), centerY, true)){
trace("Stage 2 HIT TEST!")
moveR = false
}
}
if(moveU){
trace("Stage 3 Move")
centerY -= moveSpeed
if(map.hitTestPoint(centerX, (centerY-player.height/2), true)){
trace("Stage 3 HIT TEST!")
moveU = false
}
}
if(moveD){
trace("Stage 4 Move")
centerY += moveSpeed
if(map.hitTestPoint(centerX, (centerY+player.height/2), true)){
trace("Stage 4 HIT TEST!")
moveD = false
}
}
refreshMovement()
}
function refreshMovement():void{
if(moveL){
player.x -= moveSpeed
}
if(moveR){
player.x += moveSpeed
}
if(moveU){
player.y -= moveSpeed
}
if(moveD){
player.y += moveSpeed
}
}
It sounds like you're doing a kind of over-head view (considering you have the box moving in X and Y). I would have an 2D array with 0's and 1's in it (true/falses). When your character moves around, look up your characters hit box for the tiles that it occupies, which will generally be 1 to 4 tiles.
If there is a TRUE in any of thoses spots, he is hitting something. This way you only need hit boxes on objects that are active (they move etc)
I would also check out this article, and implement the solution that seems to work best for you:
http://higherorderfun.com/blog/2012/05/20/the-guide-to-implementing-2d-platformers/

ActionScript 3 - Walls don't collide properly

For several weeks I'm been trying to make my topdown game. It went well for some time, but then at some point I wanted to create a scrolling map with walls everywhere. Now, to make it easy to create the map (and add more later) I made a class called "Wall" which I will hit test. This works, when it hits, the map must stop scrolling. It does, so good so far.
Now, when the player moves away from the object, I want the map to be able to scroll again, this works too, but now the player can't move to the side the player came from. I know this is because I need to define the sides, where the player enters, in order tell the game which movement must be set to zero at that point.
You can see the code here:
public function AddWalls(player:MovieClip)
{
WallObjects = new Array();
for (var i:int = 0; i < this.numChildren; i++)
{
var mc = this.getChildAt(i);
if (mc is Wall)
{
var wallobj:Object = new Object();
wallobj.mc = mc;
wallobj.leftside = mc.x;
wallobj.rightside = mc.x + mc.width;
wallobj.topside = mc.y;
wallobj.bottomside = mc.y + mc.height;
wallobj.width = mc.width;
wallobj.height = mc.height;
WallObjects.push(wallobj);
}
}
}
public function EnableCollisionWithWalls():void
{
for (var k:int = 0; k < WallObjects.length; k++)
{
//if (player.y > WallObjects[k].topside && player.y < WallObjects[k].bottomside && player.x > WallObjects[k].leftside && player.x < WallObjects[k].rightside)
if (player.hitTestObject(WallObjects[k].mc))
{
if (player.x > WallObjects[k].leftside && player.x < WallObjects[k].leftside+15)
{
Lefthit = true;
trace(DebugVar);
DebugVar++;
player.x = WallObjects[k].leftside;
Scroll_x = 0;
}
else
if ( player.x < WallObjects[k].leftside -1 || (player.y > WallObjects[k].leftside ))
{
Lefthit = false;
}
if (player.hitTestObject(derp))
{
Lefthit = false;
}
}
}
}
public function EnableMovement():void
{
map.x += Scroll_x;
map.y += Scroll_y;
for (var i:int = 0; i < this.numChildren; i++)
{
var mc = this.getChildAt(i);
if (mc is Wall)
{
mc.x += Scroll_x;
mc.y += Scroll_y;
}
}
}
public function MovementKeysDown(move:KeyboardEvent):void
{
var Speed:int = -5;
switch (move.keyCode)
{
case 37: // venstre knap
Scroll_x = -Speed;
break;
case 38: // op
Scroll_y = -Speed;
break;
case 39: // højre knap
Scroll_x = Speed;
if (Lefthit)
{
Scroll_x = 0;
}
break;
case 40: // ned
Scroll_y = Speed;
break;
default:
}
}
public function MovementKeysUp(move:KeyboardEvent):void
{
switch (move.keyCode)
{
case 37:
Scroll_x = 0;
break;
case 38:
Scroll_y = 0;
break;
case 39:
Scroll_x = 0;
break;
case 40:
Scroll_y = 0;
break;
default:
}
}
Might be some syntax errors (since I removed some code in this editor).
You can see the current version here.
In this version the scroll keeps on going. I did come up with a "fix" for it, by check if the player was 1 pixel away from the movieclip, inside the hit test (which for some reason works, which I guess it shouldn't since it doesn't hit anymore) and then setting the Lefthit to false. However this is not a good solution and if you continue up or down away from the movieclip, you are still not able to go right anymore...
I've been baffled by this for a long time, so I thought it was about time I asked for help. I couldn't find anything on how to control movement in a top-down game, with a scrolling map + wall :/
The simplest (but not most resource friendly) solution (if you anyway have a single storage for walls) is iterating through the walls and instead of using the Flash default hitTest (I don't like the way it works since ActionScript 2) - just check the coordinates and if you see that there's going to be a collision on the next simulation step - handle it according to the game logic.
The most useful optimization for this algorithm is creating a filter/data structure for getting only walls that are near to the player and so can be affected to the test for collisions.