codeSquirrel
01-15-2010, 12:24 AM
Strange stuff. I'm prototyping a spaceship game. It's a bird's-eye-view, a la Escape Velocity. The ship is lagging behind the input though.
When the thrust is pressed, the ship doesn't respond immediately and after it is released, it continues to accelerate for some time.
I'm using double-buffering, a timer for frames, and an FPS monitor, so I'm relatively sure that is not the source of the issue. If I can't resolve this issue, there doesn't seem to be much point in continuing to implement features, like a starmap you can't navigate past the edges of : P
the ship code is called every frame with the booleans for the key presses.
it is basically just computing the X and Y vectors for 1/30 of a second of acceleration, based on the current rotation of the ship and adding those vectors to the current ones. (that all works... it just consistently lags behind the control input)
EDIT: AH, I was adding the old vector twice. Got it. works like a charm now :D
ship code:
var incr:Number = (1/30);
function init():void
{
xVector = 0;
yVector = 0;
shipTheta = this.rotation;
vectorTheta = this.rotation;
accel = .004;
turnRate = 90;
coord = new Point(0,0);
}
function update(accel:Boolean, left:Boolean, right:Boolean, rev:Boolean):void
{
if(left && !right)
{
rotate(turnRate);
}
if(right && !left)
{
rotate(-turnRate);
}
if(rev)
{
//var opp:Number = ((vectorTheta + 180) % 360);
//if((shipTheta > opp) && (shipTheta + (turnRate * incr)) )
}
if(accel) changeVector();
coord.x += xVector;
coord.y += yVector;
}
function changeVector():void
{
var newX:Number = (Math.cos(rad(shipTheta)) * (accel * incr));
var newY:Number = (Math.sin(rad(shipTheta)) * (accel * incr));
xVector += newX;
yVector += newY;
trace('newX: ' + newX);
trace('newY: ' + newY);
var hyp:Number = getVelocity();
vectorTheta = deg((Math.asin(yVector/hyp)));
}
function rotate(rate:Number):void
{
shipTheta += (rate * incr);
}
function getVelocity():Number
{
return Math.sqrt((xVector * xVector) + (yVector * yVector));
}
function rad(deg:Number):Number
{
return (deg * (Math.PI / 180));
}
function deg(rad:Number):Number
{
return (rad * (180 / Math.PI));
}
main code:
import FramerateTracker;
var fps:FramerateTracker = new FramerateTracker();
var buffer1:MovieClip = new MovieClip();
var buffer2:BitmapData = new BitmapData(stage.stageWidth, stage.stageHeight, false, 0xFFFFFF);
var buffer3:BitmapData = new BitmapData(stage.stageWidth, stage.stageHeight, false, 0xFFFFFF);
var bufferContainer:Bitmap = new Bitmap(buffer2);
var starField:MovieClip = new MovieClip();
var ship:Shuttle = new Shuttle();
var display:TextField = new TextField();
var left:Boolean = false;
var right:Boolean = false;
var rev:Boolean = false;
var accel:Boolean = false;
function generateStarField(w:int,h:int):void
{
var buff1:MovieClip = new MovieClip();
var buff2:BitmapData = new BitmapData(w,h,false,0x000000);
var AU:int = 100;
var starsPerAU:int = 2;
var numStars:int = (int)(((w * h) /(AU * AU)) * starsPerAU);
//trace(numStars);
var star:MovieClip;
for(var i:int = 0;i < numStars;i ++)
{
star = new Star();
buff1.addChild(star);
star.x = (int)(Math.random() * w);
star.y = (int)(Math.random() * h);
star.scaleX += Math.random();
star.scaleY += Math.random();
buff1['star' + i] = star;
}
buff1.width = w;
buff1.height = h;
buff2.draw(buff1);
var buff3:Bitmap = new Bitmap(buff2);
starField.addChild(buff3);
}
generateStarField(4000,4000);
ship.init();
ship.scaleX = .5;
ship.scaleY = .5;
buffer1.addChild(starField);
buffer1.addChild(ship);
buffer1.addChild(display);
buffer1.width = stage.stageWidth;
buffer1.height = stage.stageHeight;
starField.x = -((starField.width / 2) - (stage.stageWidth / 2));
starField.y = -((starField.height / 2) - (stage.stageHeight / 2));
display.type = TextFieldType.DYNAMIC;
display.textColor = 0xffffff;
display.x = 10;
display.y = 10;
display.width = 50;
display.height = 80;
ship.x = 400;
ship.y = 400;
addChild(bufferContainer);
addChild(fps);
fps.x = 200;
fps.y = 10;
stage.addEventListener(KeyboardEvent.KEY_DOWN,onKey);
stage.addEventListener(KeyboardEvent.KEY_UP,onKey);
stage.addEventListener(Event.ENTER_FRAME,onFrame);
this.cacheAsBitmap = true;
function onKey(e:KeyboardEvent):void
{
var key:int = e.keyCode;
if(e.type == "keyDown"){
switch(key)
{
case 37 : left = true;
break;
case 38 : accel = true;
break;
case 39 : right = true;
break;
case 40 : rev = true;
break;
}
}
if(e.type == "keyUp"){
switch(key)
{
case 37 : left = false;
break;
case 38 : accel = false;
break;
case 39 : right = false;
break;
case 40 : rev = false;
break;
}
}
//trace(accel + " " + right + " " + left + " " + rev);
}
function onFrame(e:Event):void
{
ship.update(accel,right,left,rev);
starField.x -= ship.coord.x;
starField.y -= ship.coord.y;
ship.rotation = ship.shipTheta;
//trace(ship.coord.x + ", " + ship.coord.y);
var temp:Number = ship.getVelocity();
display.text = " " + temp + " \n" +ship.vectorTheta;
buffer2.lock()
bufferContainer.visible = false;
buffer2.draw(buffer1);
bufferContainer.visible = true;
buffer2.unlock();
//buffer3.draw(buffer1);
}
When the thrust is pressed, the ship doesn't respond immediately and after it is released, it continues to accelerate for some time.
I'm using double-buffering, a timer for frames, and an FPS monitor, so I'm relatively sure that is not the source of the issue. If I can't resolve this issue, there doesn't seem to be much point in continuing to implement features, like a starmap you can't navigate past the edges of : P
the ship code is called every frame with the booleans for the key presses.
it is basically just computing the X and Y vectors for 1/30 of a second of acceleration, based on the current rotation of the ship and adding those vectors to the current ones. (that all works... it just consistently lags behind the control input)
EDIT: AH, I was adding the old vector twice. Got it. works like a charm now :D
ship code:
var incr:Number = (1/30);
function init():void
{
xVector = 0;
yVector = 0;
shipTheta = this.rotation;
vectorTheta = this.rotation;
accel = .004;
turnRate = 90;
coord = new Point(0,0);
}
function update(accel:Boolean, left:Boolean, right:Boolean, rev:Boolean):void
{
if(left && !right)
{
rotate(turnRate);
}
if(right && !left)
{
rotate(-turnRate);
}
if(rev)
{
//var opp:Number = ((vectorTheta + 180) % 360);
//if((shipTheta > opp) && (shipTheta + (turnRate * incr)) )
}
if(accel) changeVector();
coord.x += xVector;
coord.y += yVector;
}
function changeVector():void
{
var newX:Number = (Math.cos(rad(shipTheta)) * (accel * incr));
var newY:Number = (Math.sin(rad(shipTheta)) * (accel * incr));
xVector += newX;
yVector += newY;
trace('newX: ' + newX);
trace('newY: ' + newY);
var hyp:Number = getVelocity();
vectorTheta = deg((Math.asin(yVector/hyp)));
}
function rotate(rate:Number):void
{
shipTheta += (rate * incr);
}
function getVelocity():Number
{
return Math.sqrt((xVector * xVector) + (yVector * yVector));
}
function rad(deg:Number):Number
{
return (deg * (Math.PI / 180));
}
function deg(rad:Number):Number
{
return (rad * (180 / Math.PI));
}
main code:
import FramerateTracker;
var fps:FramerateTracker = new FramerateTracker();
var buffer1:MovieClip = new MovieClip();
var buffer2:BitmapData = new BitmapData(stage.stageWidth, stage.stageHeight, false, 0xFFFFFF);
var buffer3:BitmapData = new BitmapData(stage.stageWidth, stage.stageHeight, false, 0xFFFFFF);
var bufferContainer:Bitmap = new Bitmap(buffer2);
var starField:MovieClip = new MovieClip();
var ship:Shuttle = new Shuttle();
var display:TextField = new TextField();
var left:Boolean = false;
var right:Boolean = false;
var rev:Boolean = false;
var accel:Boolean = false;
function generateStarField(w:int,h:int):void
{
var buff1:MovieClip = new MovieClip();
var buff2:BitmapData = new BitmapData(w,h,false,0x000000);
var AU:int = 100;
var starsPerAU:int = 2;
var numStars:int = (int)(((w * h) /(AU * AU)) * starsPerAU);
//trace(numStars);
var star:MovieClip;
for(var i:int = 0;i < numStars;i ++)
{
star = new Star();
buff1.addChild(star);
star.x = (int)(Math.random() * w);
star.y = (int)(Math.random() * h);
star.scaleX += Math.random();
star.scaleY += Math.random();
buff1['star' + i] = star;
}
buff1.width = w;
buff1.height = h;
buff2.draw(buff1);
var buff3:Bitmap = new Bitmap(buff2);
starField.addChild(buff3);
}
generateStarField(4000,4000);
ship.init();
ship.scaleX = .5;
ship.scaleY = .5;
buffer1.addChild(starField);
buffer1.addChild(ship);
buffer1.addChild(display);
buffer1.width = stage.stageWidth;
buffer1.height = stage.stageHeight;
starField.x = -((starField.width / 2) - (stage.stageWidth / 2));
starField.y = -((starField.height / 2) - (stage.stageHeight / 2));
display.type = TextFieldType.DYNAMIC;
display.textColor = 0xffffff;
display.x = 10;
display.y = 10;
display.width = 50;
display.height = 80;
ship.x = 400;
ship.y = 400;
addChild(bufferContainer);
addChild(fps);
fps.x = 200;
fps.y = 10;
stage.addEventListener(KeyboardEvent.KEY_DOWN,onKey);
stage.addEventListener(KeyboardEvent.KEY_UP,onKey);
stage.addEventListener(Event.ENTER_FRAME,onFrame);
this.cacheAsBitmap = true;
function onKey(e:KeyboardEvent):void
{
var key:int = e.keyCode;
if(e.type == "keyDown"){
switch(key)
{
case 37 : left = true;
break;
case 38 : accel = true;
break;
case 39 : right = true;
break;
case 40 : rev = true;
break;
}
}
if(e.type == "keyUp"){
switch(key)
{
case 37 : left = false;
break;
case 38 : accel = false;
break;
case 39 : right = false;
break;
case 40 : rev = false;
break;
}
}
//trace(accel + " " + right + " " + left + " " + rev);
}
function onFrame(e:Event):void
{
ship.update(accel,right,left,rev);
starField.x -= ship.coord.x;
starField.y -= ship.coord.y;
ship.rotation = ship.shipTheta;
//trace(ship.coord.x + ", " + ship.coord.y);
var temp:Number = ship.getVelocity();
display.text = " " + temp + " \n" +ship.vectorTheta;
buffer2.lock()
bufferContainer.visible = false;
buffer2.draw(buffer1);
bufferContainer.visible = true;
buffer2.unlock();
//buffer3.draw(buffer1);
}