I can scroll the ground left and right, but I can't scroll the ground up and down.
private function scrollStage():void
{
if (lastPosX != lastPosX)
{
canScrollStage = false;
}
else if (lastPosX == lastPosX)
{
canScrollStage = true;
}
if (canScrollStage)
{
if (rightKey)
{
//move background left
//something.x +=(stage.stageWidth * 0.5) - character.x * 2;
}
else if (leftKey)
{
//move backgrounf Roight
}
for (var b:int = 0; b < childrenOnStage; b++)
{
if (getChildAt(b).name == "enemy" || getChildAt(b).name == "enemyRed" || getChildAt(b).name == "knife")
{
getChildAt(b).x += (stage.stageWidth * 0.5) - character.x;
//getChildAt(b).y += - character.y;
}
}
ground.x += (stage.stageWidth * 0.5) - character.x;
//ground.y += (stage.stageHeight * 0.5) - character.y;
//ground.y += (stage.stageHeight) - character.y;
}
else
{
//move the background
}
// do this last, everything moves around object
character.x = stage.stageWidth * 0.5;
lastPosX = character.x;
I have tried doing
character.y = stage.stageHeight * 0.5;
But this just glues the characters y position to the center of the screen.
When the world can scroll I tried implementing this in to my code
//ground.y += (stage.stageHeight * 0.5) - character.y;
but this doesn't really work either.
Can anyone please point me in the same direction or give me tips and advice, I have tried implementing this code
// A 'Camera' is really just a Point within the world we want to center on
// the screen.
var camera:Point = new Point();
// Set the camera coordinates to the char coordinates.
//camera.x = character.x;
camera.y = character.y;
// Adjust the world position on the screen based on the camera position.
// world.x = -camera.x + (stage.stageWidth / 2);
ground.y = -camera.y + (stage.stageHeight / 2);
It does work! But the screen shakes up and down violently
I traced the players y position and it was going up and down
but with out that code the y position stayed the same.
Thank you.
EDIT - GRAVITY
In my main class I have this which stops the player from falling.
for (var c:int = 0; c < childrenOnStage; c++)
{
if (getChildAt(c).name == "player")
{
if (ground.level1Ground.hitTestPoint(getChildAt(c).x + 13, getChildAt(c).y, true) || ground.level1Ground.hitTestPoint(getChildAt(c).x - 13, getChildAt(c).y, true))
{ //if the boundary collides with the player or enemy
while (ground.level1Ground.hitTestPoint(getChildAt(c).x + 13, getChildAt(c).y, true) || ground.level1Ground.hitTestPoint(getChildAt(c).x - 13, getChildAt(c).y, true))
{
OnGround(getChildAt(c)).incrementUp();
//bump up the object until it isn't hitting the boundary;
if (ground.level1Ground.hitTestPoint(getChildAt(c).x + 13, getChildAt(c).y, true) || ground.level1Ground.hitTestPoint(getChildAt(c).x - 13, getChildAt(c).y, true))
{
// do nothing
//touchingGround = false;
}
else
{ // once it isn't hitting the boundary, do this function for keeping the object on the boundary
OnGround(getChildAt(c)).keepOnGround();
touchingGround = true;
}
}
// ends while ( _boundaries.hitTestPoint ( getChildAt(c).x , getChildAt(c).y, true) ) {;
}
else
{
// ends if ( _boundaries.hitTestPoint ( getChildAt(c).x , getChildAt(c).y, true) )
touchingGround = false;
}
this is the the onGround class.
public class OnGround extends MovieClip
{
protected var grav:int = 1;
protected var charIsrunning:Boolean;
protected var isDefending:Boolean;
protected var isJumping:Boolean;
public function OnGround()
{
addEventListener(Event.ADDED_TO_STAGE, init)
charIsrunning = false;
isDefending = false;
//gotoAndStsop("jump");
}
private function init(e:Event):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
grav = 1;
addEventListener(Event.ENTER_FRAME, fall);
}
private function fall(e:Event):void
{
grav ++;
if (grav > 15)
{
grav = 10;
}
this.y += grav;
}
public function incrementUp():void
{
//this.y -= 0.1;
}
public function keepOnGround():void
{
grav = 0;
positionOnLand();
}
public function positionOnLand():void
{
//overide
}
}
}
I fear that camera.y can't keep up with character.y or character.y changes despite the code telling the game "Stop falling, your y axis is being invcremented."
Glancing at the code, I'll throw this out as a possible answer. It would seem that the camera's Y position changes with even the slightest change in the player's Y position. (Why that isn't happening on X beats me.)
The first thing that comes to mind is that we need to make the camera a lot less sensitive. We can do this by forcing the function to use an estimation of the position. (By the way, this will only work as long as the character is NOT glued to the center of the screen.)
Since I don't have the whole project, I can't test this. If this line doesn't fix the problem, play with the concept.
camera.y = Math.round(character.y);
Essentially, I'd be forcing the camera to work with whole Y values, not decimal values. That could theoretically cut down on some of the shaking.
If helps some, but not enough, we could implement this to make it go based off of ten pixels, not one. Again, untested (math could be a little off), but you get the idea.
camera.y = Math.round(character.y/10) * 10;
The one theoretical downside of that second method is that the screen will jump when it readjusts. You may need to do some additional coding to make it smooth.
This is a potential answer, whaT I have done is changed this block of code to...
/*if (ground.level1Ground.hitTestPoint(getChildAt(c).x + 13, getChildAt(c).y, true) || ground.level1Ground.hitTestPoint(getChildAt(c).x - 13, getChildAt(c).y, true))
{ //if the boundary collides with the player or enemy
getChildAt(c).y --;
while (ground.level1Ground.hitTestPoint(getChildAt(c).x + 13, getChildAt(c).y, true) || ground.level1Ground.hitTestPoint(getChildAt(c).x - 13, getChildAt(c).y, true))
{
//bump up the object until it isn't hitting the boundary;
if (ground.level1Ground.hitTestPoint(getChildAt(c).x + 13, getChildAt(c).y, true) || ground.level1Ground.hitTestPoint(getChildAt(c).x - 13, getChildAt(c).y, true))
{
// do nothing
//touchingGround = false;
}
else
{ // once it isn't hitting the boundary, do this function for keeping the object on the boundary
OnGround(getChildAt(c)).keepOnGround();
touchingGround = true;
// getChildAt(c).y --;
}
}
// ends while ( _boundaries.hitTestPoint ( getChildAt(c).x , getChildAt(c).y, true) ) {;
}
else
{
// ends if ( _boundaries.hitTestPoint ( getChildAt(c).x , getChildAt(c).y, true) )
touchingGround = false;
}
*/
This! I removed the while!
if (ground.level1Ground.hitTestPoint(getChildAt(c).x + 13, getChildAt(c).y, true) || ground.level1Ground.hitTestPoint(getChildAt(c).x - 13, getChildAt(c).y, true))
{
getChildAt(c).y --;
//OnGround(getChildAt(c)).incrementUp();
OnGround(getChildAt(c)).keepOnGround();
touchingGround = true;
}
else
{
touchingGround = false;
}
I can't explain why it works, (makes me look like a bad programmer) but it doesn't changed the characters Y position when he is on the ground, thus no more earthquake meaning the dragon can sleep for now.
Credits to JasonMC92 for being there for me each step of the way for helping me realize this is a solution for now.
Related
Using Away3D...I have this array of cubes I generated. This array of cubes are in a "Sector" that contains 50x50x50 cubes. The only thing the sector contains is the cubes coordinates and color. They are stored inside the Cube class. I only want to render the ones that touch air (currently "air" the "color" 0xFFFFFF)
I've tried this...an interesting number of ways...
My current method (slowest) was to make vector3D points for each object, and then use indexOf on a set of Vector3Ds containing the points of all the cubes in my "Sector".
public function renderSector(sector:Sector):void
{
trace("init sector render..");
allCubes = sector.cubes;
//Render only things touching air.
for each (var cube:Cube in sector.cubes)
{
//If the cube is not an air block
if (cube.color != 0xFFFFFF)
{
var topEstimate:Vector3D = new Vector3D(cube.x + 1, cube.y, cube.z);
var bottomEstimate:Vector3D = new Vector3D(cube.x, cube.y +1, cube.z);
var leftEstimate:Vector3D = new Vector3D(cube.x + 1, cube.y, cube.z +1);
var rightEstimate:Vector3D = new Vector3D(cube.x - 1, cube.y, cube.z);
var frontEstimate:Vector3D = new Vector3D(cube.x, cube.y -1, cube.z);
var backEstimate:Vector3D = new Vector3D(cube.x, cube.y, cube.z - 1);
//If the cube is next to an air block
if (checkForAir(topEstimate) || checkForAir(bottomEstimate) || checkForAir(leftEstimate) || checkForAir(rightEstimate) || checkForAir(frontEstimate) || checkForAir(backEstimate))
{
var meshCube:Mesh = new Mesh(new CubeGeometry(10, 10, 10), new ColorMaterial(cube.color));
meshCube.x = (sector.x * 125000) + (10 * cube.x);
meshCube.y = (sector.y * 125000) + (10 * cube.y);
meshCube.z = (sector.z * 125000) + (10 * cube.z);
trace("This cube touches air..rendering");
viewport.scene.addChild(meshCube);
}
}
}
}
private function checkForAir(point:Vector3D):Boolean
{
var returnValue:Boolean = new Boolean(false);
var index:int = allCubes.indexOf(point);
if (index > -1)
{
if (allCubes[index].color == 0xFFFFFF)
{
returnValue = true;
}
}
return returnValue;
}
Nothing happens. I get no cubes (letting it run for about 2 minutes) that have an air block next to them using a 3DVevtor. So, I try iterating through all my cubes again while fetching a list of cubes that are "next" to my current cube. I do this by comparing each cube to each other vs a stored 3DVector in my Sector class.
public function renderSector(sector:Sector):void
{
//Render only things touching air.
for each (var cube:Cube in sector.cubes)
{
//If the cube is next to an air block and is not an air block, render it.
if (cube.color != 0xFFFFFF)
{
var touchesAir:Boolean = new Boolean(false);
//Search touching cubes
var touchingCubes:Vector.<Cube> = new Vector.<Cube>();
for each (var possibleCube:Cube in sector.cubes)
{
if ((possibleCube.x == cube.x + 1 && possibleCube.y == cube.y && possibleCube.z == cube.z) ||
(possibleCube.y == cube.y + 1 && possibleCube.x == cube.x && possibleCube.z == cube.z) ||
(possibleCube.z == cube.z + 1 && possibleCube.x == cube.x && possibleCube.y == cube.y) ||
(possibleCube.x == cube.x - 1 && possibleCube.y == cube.y && possibleCube.z == cube.z) ||
(possibleCube.y == cube.y - 1 && possibleCube.x == cube.x && possibleCube.z == cube.z) ||
(possibleCube.z == cube.z - 1 && possibleCube.x == cube.x && possibleCube.y == cube.y))
{
touchingCubes.push(possibleCube);
}
}
for each (var touchingCube:Cube in touchingCubes)
{
if (touchingCube.color == 0xFFFFFF)
{
touchesAir = true;
}
}
if (touchesAir)
{
var meshCube:Mesh = new Mesh(new CubeGeometry(10, 10, 10), new ColorMaterial(cube.color));
meshCube.x = (sector.x * 125000) + (10 * cube.x);
meshCube.y = (sector.y * 125000) + (10 * cube.y);
meshCube.z = (sector.z * 125000) + (10 * cube.z);
trace("This cube touches air..rendering");
viewport.scene.addChild(meshCube);
}
}
}
It works..but it takes about 15 seconds for it to find one....The current spec of the Sector is a plane of 50x25x50 grass colored blocks. So this would take a while..
My first method (and oh man was this about an hour+ of brainstorming back) was to fetch the positions of each cube that [i]would[/i] be next to my main cube by basing it on the render order in my world generator function. [Seen below]
public static function generateSector(type:String, position:Vector3D):Sector
{
var returnSector:Sector;
var grassArray:Vector.<uint> = new Vector.<uint>();
grassArray.push(new uint(0x56b000));
grassArray.push(new uint(0x63c900));
grassArray.push(new uint(0x6fe300));
grassArray.push(new uint(0x7cfc00));
//Current types...grass field
switch(type)
{
case "grass":
var cubeArray:Vector.<Cube> = new Vector.<Cube>();
for (var x:int = 0; x < 50; x++) //Moving right
{
for (var z:int = 0; z < 50; z++) //Headed out.
{
for (var y:int = 0; y < 50; y++) //From bottom up.
{
if (y < 25)
{
var color:uint = grassArray[Math.floor(Math.random() * 4)];
}
else
{
var color:uint = 0xFFFFFF;
}
cubeArray.push(new Cube(x,y,z,color));
}
}
}
returnSector = new Sector(position.x, position.y, position.z, cubeArray);
break;
}
return returnSector;
}
Y building first (bottom to top)
then X
then Z
So, simple right? Based on the order of the cubes, I should be able to just pull, for example, the cube on top of my current cube by adding 1 to the index of my current cube, right? (Getting the other cubes respectively based on their order of course and catching errors for any cubes that would be outside of my 50x50x50 grid)
public function renderSector(sector:Sector):void
{
//Render only things touching air.
var counter:int = 0;
for each (var cube:Cube in sector.cubes)
{
//If the cube is next to an air block and is not an air block, render it.
if (cube.color != 0xFFFFFF)
{
var touchesAir:Boolean = new Boolean(false);
try
{
var topCube:Cube = sector.cubes[counter + 1];
if (topCube.color == 0xFFFFFF)
{
touchesAir == true;
}
}
catch(rangeError:RangeError)
{
}
//-------
try
{
var bottomCube:Cube = sector.cubes[counter - 1];
if (bottomCube.color == 0xFFFFFF)
{
touchesAir = true;
}
}
catch (rangeError:RangeError)
{
}
//-------
try
{
var leftCube:Cube = sector.cubes[counter - (50 * 50)];
if (leftCube.color == 0xFFFFFF)
{
touchesAir = true;
}
}
catch (rangeError:RangeError)
{
}
//-------
try
{
var rightCube:Cube = sector.cubes[(50 * 50) + counter];
if (rightCube.color == 0xFFFFFF)
{
touchesAir = true;
}
}
catch (rangeError:RangeError)
{
}
//-------
try
{
var frontCube:Cube = sector.cubes[counter - 50];
if (frontCube.color == 0xFFFFFF)
{
touchesAir = true;
}
}
catch (rangeError:RangeError)
{
}
//-------
try
{
var backCube:Cube = sector.cubes[counter + 50];
if (backCube.color == 0xFFFFFF)
{
touchesAir = true;
}
}
catch (rangeError:RangeError)
{
}
if (touchesAir)
{
var meshCube:Mesh = new Mesh(new CubeGeometry(10, 10, 10), new ColorMaterial(cube.color));
meshCube.x = (sector.x * 125000) + (10 * cube.x);
meshCube.y = (sector.y * 125000) + (10 * cube.y);
meshCube.z = (sector.z * 125000) + (10 * cube.z);
trace("This cube touches air..rendering");
viewport.scene.addChild(meshCube);
}
}
}
}
This one renders in about 4 seconds! Though, no cubes actually appear on screen...and the trace statement never fires. I have had no luck finding out why.
TL;DR Let's say you have a grid of cubes. How do you only render the ones that are out in the open?
Or (great alternative) only render mesh's that you can "see". (I need the meshs not merged because I have to have listeners on them to remove them or add new meshes when clicked next to or ontop of them)
You know those moments when you forget to sleep and then you forget to add counters to your for each loops since you're referencing a counter inside of it?
counter = sector.cubes.indexOf(cube);
Need to make sure that the counter (which I should rename indexItem) matched the index of the current cube that I was running through inside my conditional that checks to see if the cube is "air" or not.
Of course, now I'm getting a resource limit error but this can be fixed by reducing the sector size and combining a few meshes.
[Fault] exception, information=Error: Error #3691: Resource limit for this resource type exceeded.
Ok, so I have an object on the stage that moves on the "world" movieclip. I'm trying to make it so that when you're moving right. If the movieclip inside the moving movieclip("dude") called hitD collides with the walls in world, the dude stops moving forward.
Screen shots if it might help.
General stage dude object selected
http://prntscr.com/5bgjfq the world is everything but the ball
http://prntscr.com/5bgjuh
hitD
If anyone has any way they can modify these collision physics since my current code is sketchy as hell, all suggestions and ideas are welcome.
var started:Boolean;
const NUMLEVELS = 3;
var status:String;
stage.focus = stage;
if (! started)
{// Only ever do this once!
status = "falling";
started = true;
var speedX:Number = 5;
var speedY:Number = 0;
var topSpeedY:Number = 50;
var start_x:Number = dude.x;
var start_y:Number = dude.y;
var keysDown:Object = new Object();
stage.addEventListener(KeyboardEvent.KEY_DOWN, keyPressed);
stage.addEventListener(KeyboardEvent.KEY_UP, keyReleased);
stage.addEventListener( Event.DEACTIVATE, appDeactivate );
dude.addEventListener(Event.ENTER_FRAME, moveDude);
var W:Number = 15;
var snows:Array = new Array();
}
for (var b:int = 0; b < 50; b++)
{
var snow:Snow = new Snow();
snows.push(snow);
addChild(snow);
}
function cleanup()
{
stage.removeEventListener(KeyboardEvent.KEY_DOWN, keyPressed);
stage.removeEventListener(KeyboardEvent.KEY_UP, keyReleased);
stage.removeEventListener( Event.DEACTIVATE, appDeactivate );
dude.removeEventListener(Event.ENTER_FRAME, moveDude);
}
function keyIsDown(key:uint):Boolean
{
return Boolean(key in keysDown);
}
function keyPressed(e:KeyboardEvent):void
{
keysDown[e.keyCode] = true;
}
function keyReleased(e:KeyboardEvent):void
{
delete keysDown[e.keyCode];
}
function appDeactivate( event:Event ):void
{
// Get rid of all keypress info when app loses focus
keysDown=new Object();
}
function moveDude(e:Event):void
{
var obj:Object = e.target; //setting dude as object
// for now, if you get off the top of the screen you win
if (obj.y < 0)
{
cleanup();
nextScene();
return;
}
// if character dies, restart
if (obj.y > stage.stageHeight + 100)
{
gotoAndStop(1);
obj.x = start_x;
obj.y = start_y;
}
if (death!=null)
{
if (obj.hitTestObject(death))
{
trace("Dead");
}
}
if (status=="falling")
{
speedY++;
if (speedY>topSpeedY)
{
speedY = topSpeedY;
}
for (i = 0; i<2*speedY; i++)
{
obj.y++;
if (world.hitTestPoint(obj.x - obj.width / 2,obj.y,true) || world.hitTestPoint(obj.x + obj.width / 2,obj.y,true))
{
status = "ground";
break;
}
}
}
else if (status == "jumping")
{
speedY--;
for (i = 0; i<2*speedY; i++)
{
obj.y--;
if (world.hitTestPoint(obj.x - obj.width / 2,obj.y - obj.height,true) || world.hitTestPoint(obj.x + obj.width / 2,obj.y - obj.height,true))
{
speedY = 0;
break;
}
}
if (speedY==0)
{
status = "falling";
}
}
else if (status == "ground")
{
if (! world.hitTestPoint(obj.x - 8,obj.y,true) && ! world.hitTestPoint(obj.x + 8,obj.y + 4,true))
{
speedY = 0;
status = "falling";
}
if (keyIsDown(Keyboard.UP))
{
status = "jumping";
speedY = 10;
}
}
if (keyIsDown(Keyboard.DOWN)&&status=="ground")
{
dude.gotoAndStop("duck");
}
else
{
if (keyIsDown(Keyboard.SHIFT))
{
speedX = 10;
}
else
{
speedX = 5;
}
if (keyIsDown(Keyboard.LEFT))
{
for (i = 0; i<speedX; i++)
{
obj.x--;
dude.ball.rotation--; //dude.ball is a movieclip similar to dude.hitD, it spins when you move.
if (world.hitTestPoint(obj.x - obj.width / 2 + 4,obj.y - 8,true) || world.hitTestPoint(obj.x - obj.width / 2,obj.y - obj.height + 8,true))
{
dude.ball.rotation++;
obj.x++;
break;
}
}
}
else if (keyIsDown(Keyboard.RIGHT))
{
//dude.gotoAndStop("right");
//obj.scaleX = 1;
for (i = 0; i<speedX; i++)
{
obj.x++;
dude.ball.rotation++;
// The number in obj.y-4 affects the climbing ability
if (status == "ground")
{
//dude.height+= 0.1;
//dude.width += 0.1;
}//so here I'm checking if it hits the lower corner or top right corner or hitD
if (world.hitTestPoint(dude.hitD.x + obj.hitD.width/2 , obj.hitD.y,true) || world.hitTestPoint(obj.hitD.x + obj.hitD.width/2,obj.hitD.y - obj.hitD.height ,true))
//if (world.hitTestObject(obj))
{
dude.ball.rotation--;
obj.x--;
break;
}
}
}
dude.gotoAndStop(1);
}
while (status == "ground" && (world.hitTestPoint(obj.x-8, obj.y-1, true) || world.hitTestPoint(obj.x+8, obj.y-1, true)))
{
obj.y--;
}
const BORDER = 50;
var diff:int;
// Check right border:
diff = obj.x + BORDER - stage.stageWidth;
if (diff>0 && world.x>=stage.stageWidth-world.width)
{
obj.x -= diff;
world.x -= diff;
background1.x -= diff;
if (death != null)
{
death.x -= diff;
}
}
// Check left border:
diff = obj.x - BORDER;
if (diff<0 && world.x<=0)
{
obj.x -= diff;
world.x -= diff;
background1.x -= diff;
if (death != null)
{
death.x -= diff;
}
}
// Check bottom border:
diff = obj.y + BORDER - stage.stageHeight;
if (diff>0)
{
obj.y -= diff;
world.y -= diff;
background1.y -= diff;
if (death != null)
{
death.y -= diff;
}
}
// Check top border:
diff = obj.y - BORDER;
if (diff<0)
{
obj.y -= diff;
world.y -= diff;
background1.y -= diff;
if (death != null)
{
death.y -= diff;
}
}
if (obj.x > stage.stageWidth - 25)
{
if (currentFrame<NUMLEVELS)
{
gotoAndStop(currentFrame+1);
obj.x = 25;
}
else
{
obj.x = stage.stageWidth - 25;
}
}
else if (obj.x<25)
{
if (currentFrame>1)
{
gotoAndStop(currentFrame-1);
obj.x = stage.stageWidth - 25;
}
else
{
obj.x = 25;
}
}
}
Thanks in advance for any help you can provide :)
For player physics, it's more clear approach to make a central ENTER_FRAME handler function that just for calculating the transformations to be applied to player.
You can still get information from out, but you just process the final output there. Else, it could be problematic, especially when things gets more complex and when you want to add some more feature.(e.g. Imagine in the future, you wanted to add fans on the ground that blows air up, and player have to rise when on them. There you have a lot to change, and probably with many problems.
For collision detection, this function will provide you this information: to which direction(s) the player can't go with variables 'UpColl', 'DownColl', 'Right Coll' and 'LeftColl'.
Then you can refer to this information from your main function that applies the transformation to your player. I'll give example to that also below.
function collEveryFrame(event:Event):void
{
// capture player positions
player_x = WORLD.player.x;
player_y = WORLD.player.y;
// the movie clip object where you store your solid objects. Remember, ALL MovieClip objets inside this MovieClip will taken as solid objects in your game, and regardless their shape, their boundingBox will be taken as collison. So they will all be square.
collContainer = WORLD.cW;
// your player's collision object
playerColl = WORLD.player;
// RIGHT SQUARE COLLISION DETECTION
for (var i:int; i < collContainer.numChildren; i++)
{
// Check if any collision object colliding with player
if (playerColl.hitTestObject(collContainer.getChildAt(i)))
{
// One collision detected. Check 'from which side' does the player colliding with the object;
if (collContainer.getChildAt(i).y > playerColl.y + playerColl.height - p1MoveSpeed)
{
playerColl.y = collContainer.getChildAt(i).y - playerColl.height;
DownColl = true;
}
else if (collContainer.getChildAt(i).y + collContainer.getChildAt(i).height < playerColl.y + p1MoveSpeed)
{
playerColl.y = collContainer.getChildAt(i).y + collContainer.getChildAt(i).height;
UpColl = true;
}
else if (collContainer.getChildAt(i).x + collContainer.getChildAt(i).width < playerColl.x + p1MoveSpeed)
{
playerColl.x = + collContainer.getChildAt(i).x + collContainer.getChildAt(i).width;
LeftColl = true;
}
else if (collContainer.getChildAt(i).x > playerColl.x + playerColl.width - p1MoveSpeed)
{
playerColl.x = + collContainer.getChildAt(i).x - playerColl.width;
RightColl = true;
}
}
}
// RIGHT SQUARE COLLISION DETECTION [End]
}
Transformation function;
function playerMovement(event:Event):void
{
// (apply this for all sides)
// if nothing keeps player from going right;
if (! RightColl)
{
// Apply everything currently pushing the player to right
if (keyIsDown(Keyboard.RIGHT))
{
movement_Right = 15;
}else{
movement_Right = 0;
}
// example fictional wind function returns wind speed
windSpeed = getWindSpeed();
player.x += movement_Right + windSpeed + etc + etc;
// say windSpeed is -5 (Wind is coming from right, so pushing the player to left)
// so if user pressing right arrow key, player will move to right 10px for every frame, else 5px to left, etc.
}
}
In this way, everything about physics will be easy to implement.
For example, when calculating the movement to down, add gravity and jump etc.
So I would like to add velocity to my swipe gesture. Currently I have it moving 10 px on swipe, but I want it to move with a velocity so the user can toss the object around on the screen. Here's the code I am currently using with the object moving the 10 px.
function onSwipe (e:TransformGestureEvent):void{
player_mc.gotoAndStop(5);
if (e.offsetX == 1) {
//User swiped towards right
player_mc.x += 10;
}
if (e.offsetX == -1) {
//User swiped towards left
player_mc.x -= 10;
}
if (e.offsetY == 1) {
//User swiped towards bottom
player_mc.y += 10;
}
if (e.offsetY == -1) {
//User swiped towards top
player_mc.y -= 10;
}
if(collision(player_mc.cp, level_mc))
{
player_mc.x = player_mc.prevX;
player_mc.y = player_mc.prevY;
}
}
Thanks for the help
Here is a way you can do this: (you'll want to swap the mouse events for touch events if using on mobile)
player_mc.addEventListener(MouseEvent.MOUSE_DOWN,startSwipe);
player_mc.addEventListener(MouseEvent.MOUSE_UP,endSwipe);
var velocity:Point = new Point(); //this stores the current velocity of the object
var previous:Point = new Point(); //this stores the previous frames x/y of the object.
var isDragging:Boolean = false;
var friction:Number = .85; //this how quickly to slow down the object once the mouse is released - smaller the number (must be less than 1) the quicker the object will slow/stop
function startSwipe(e){
isDragging = true;
player_mc.startDrag(false);
this.addEventListener(Event.ENTER_FRAME,enterFrameHandler);
}
function enterFrameHandler(e):void {
if(isDragging){
velocity.x += player_mc.x - previous.x; //we're adding the new velocity to the old one, then dividing in half to average the value - this makes it seem smoother
velocity.y += player_mc.y - previous.y;
velocity.x *= .5; //dividing in half
velocity.y *= .5;
previous.x = player_mc.x;
previous.y = player_mc.y;
}else{
velocity.x *= friction; //gradually slow down the object
velocity.y *= friction;
player_mc.x += velocity.x;
player_mc.y += velocity.y;
if(velocity.x < .05 && velocity.y < .05){ //once it gets slow enough, stop the enter frame handler
this.removeEventListener(Event.ENTER_FRAME,enterFrameHandler);
}
}
trace(velocity);
}
function endSwipe(e){
player_mc.stopDrag();
isDragging = false;
}
I have recently been making a game in dart. In the game, the user controls a space ship sprite with the W, A, S and D keys. These will make the sprite move UP. Left, Right and Down respectively. Space will make a square that represents a projectile, missile bullet etc. move at great speed in the direction the ship is facing.
I have a very bad system that works:
(FOR HANDLING KEY PRESS)
bool drawBull = false;
void handleKeyboard(KeyboardEvent event) {
kevent = event.keyCode;
if (kevent == KeyCode.W || kevent == KeyCode.UP){
direction = 'up';
window.console.log('w / up');
}
else if (kevent == KeyCode.A || kevent == KeyCode.LEFT){
direction = 'left';
window.console.log('a / left');
}
else if (kevent == KeyCode.S || kevent == KeyCode.DOWN){
direction = 'down';
window.console.log('s / down');
}
else if (kevent == KeyCode.D || kevent == KeyCode.RIGHT){
direction = 'right';
window.console.log('d / right');
}
else if (kevent == KeyCode.SPACE) {
shotX = lastX; shotY = lastY;
if (direction == 'right') { shotX = shotX + 400; }
if (direction == 'down') { shotY = shotY + 400; }
drawBull = true;
window.console.log('space');
} else {
return null;
}
}
And the draw function itself:
void draw() {
canvas.width = canvas.width;
switch (direction) {
case 'up':
lastY = lastY - 3;
context.drawImage(shipU, lastX, lastY);
if (drawBull) { shotY = shotY - 30; context.fillRect(lastX + 240, shotY, 20, 20); }
break;
case 'left':
lastX = lastX - 3;
context.drawImage(shipL, lastX, lastY);
if (drawBull) { shotX = shotX - 30; context.fillRect(shotX, lastY + 240, 20, 20); }
break;
case 'down':
lastY = lastY + 3;
context.drawImage(shipD, lastX, lastY);
if (drawBull) { shotY = shotY + 30; context.fillRect(lastX + 240, shotY, 20, 20); }
break;
case 'right':
lastX = lastX + 3;
context.drawImage(shipR, lastX, lastY);
if (drawBull) { shotX = shotX + 30; context.fillRect(shotX, lastY + 240, 20, 20); }
break;
default:
return null;
}
}
As you can see, this is a long untidy and tedious method. However, despite all my brain racking I can't think of a system that avoids these many if/switch statements and the idea of writing out the draw image and shooting code for each one.
My actual game will be heavily object orientated of course, so perhaps an object-orientated solution would be helpful.
The code answer given to this question was quite nice, although doesn't fit my needs exactly. So perhaps an adoption of a class like that would work well How to listen to key press repetitively in Dart for games?
Thank you very much for your help!
-Tom W.
Instead of storing directions as strings, you could store the Velocity and/or Rotation of items, and use that for rendering.
You could then store a map of the key vs the velocity change:
var keyHandlers = {
KeyCode.W: new Point(0, 1),
KeyCode.S: new Point(0, -1),
KeyCode.A: new Point(-1, 0),
KeyCode.D: new Point(1, 0),
}
var spritePosition = new Point(0, 0);
void handleKeyboard(KeyboardEvent event) {
if (keyHandlers[event.keyCode])
spritePosition += keyHandlers[event.keyCode];
}
Ultimately, you probably want to actually store a Velocity for the sprite, and use input to increase the velocity; and then "decay" that velocity each frame (to represent gravity/friction, etc.).
If your sprite needs to be rendered at a particular direction, you should store a rotation as well as position and velocity. There's a simple set of slides here that could be useful; and there are also lots of good XNA tutorials out there that will cover building a "GameObject" class to wrap up this state (although XNA is dead, the tutorials are great, and the C# is not a million miles from Dart).
When your ship shoots, you can copy the position and rotation from the ship to the bullet and calculate it's velocity by applying the ships rotation to the starting velocity of your bullet.
There's also a great website by Bob Nystrom at gameprogrammingpatterns.com that I'd recommend reading as you get more into it.
I've been stuck on this problem for a very long time now, I've searched around alot and tried stuff, but nothing works. Some explanations are just very hard for me to understand as Im pretty new to programming overall and got alot to learn.
I have two problems
1: The ball wont collide with the bricks sometimes when the speed is too fast.
2: The ball is capable of hitting 2 bricks.
Both problems is related to the fact that 60 fps isnt enough for my type of collision detection to work properly.
I just need someone to explain in a simple way as possible what I need to do to make a collision detection that will prevent this from happen.
Here's my current collision code:
private function checkCollision(): void {
grdx = Math.floor((ball.x) / 28);
grdy = Math.floor((ball.y) / 14);
ngrdx = Math.floor((ball.x + dx) / 28);
ngrdy = Math.floor((ball.y + dy) / 14);
var flipX: Boolean = false;
var flipY: Boolean = false;
if ((grdy <= level.length - 1) &&
(ngrdy <= level.length - 1) &&
(grdy >= 0 && ngrdy >= 0)) {
if (testBlock(grdx, ngrdy)) {
flipY = true;
paddleFlag = 1;
}
if (testBlock(ngrdx, grdy)) {
flipX = true;
paddleFlag = 1;
}
if (testBlock(ngrdx, ngrdy)) {
flipX = true;
flipY = true;
paddleFlag = 1;
}
dx *= flipX ? -1 : 1;
dy *= flipY ? -1 : 1;
}
}
private function testBlock(xPos: int, yPos: int): Boolean {
if (level[yPos][xPos] > 0 && level[yPos][xPos] != 13) {
trace("hit on X,Y");
level[yPos][xPos] = 0;
breakBlock("Block_" + yPos + "_" + xPos);
trace("Block: " + totalBreaks + " / " + totalBlocks);
return true;
}
return false;
}
private function breakBlock(blockName: String): void {
if (this.getChildByName(blockName)) {
this.removeChild(this.getChildByName(blockName));
totalBreaks++;
}
}
Thank you and sorry for my bad english, its not my motherlanguage.
One solution is to move the ball in smaller iterations, multiple times in a given frame.
For example, and I am giving this solution assuming that you are moving the ball based on the time elapsed from the last frame.
Suppose that 30 milliseconds have elapsed since the last frame update. In that case you would update the movement/collision twice in that frame using 15 millisecond as your time elapsed.
The higher resolution of collision you want, the more iterations you would do.
Here's an example :
// class declarations
var lastFrame:Number;
var iterationsPerFrame:int;
function startGame():void
{
// lets specify 3 updates per frame
iterationsPerFrame = 3;
// save initial time
lastFrame = getTimer();
// create your listener
addEventListener(Event.ENTER_FRAME, update);
}
function update(e:Event):void
{
var currentFrame:Number = getTimer();
var deltaTime:Number = (currentFrame - lastFrame)/1000;
var iterationDelta:Number = deltaTime/iterationsPerFrame;
for (var index:int = 0;index < iterationsPerFrame;index++)
{
// I'm assuming dx,dy are the velocity of the ball, in pixels per second
ball.x += dx * iterationDelta;
ball.y += dy * iterationDelta;
// check collision
}
// set lastFrame to the currentFrame time, preparing for next frame
lastFrame = currentFrame;
// after this, your frame is going to render
}
You could work out how far the ball travels each frame (A) based on its speed, how far the ball is from the paddle (B) and if A > B manually trigger a collision that frame.
You're essentially checking every bricks X and Y coordinate to the balls X and Y coordinate, so if the bricks are stored in an array this becomes: Sqrt( Sqrd(p2.x - p1.x) + Sqrd(p2.y - p1.y))
for(var i=0; i<brickArray.length; i++)
{
var distance:Number = Math.sqrt((brickArray[i].x - ball.x) * (brickArray[i].x - ball.x) +
(brickArray[i].y - ball.y) * (brickArray[i].y - ball.y));
}
This is a very good tutorial on high speed collison detection:
http://www.newgrounds.com/bbs/topic/1072673