libGDX bullet position logic - libgdx

My game has a update method which handles the fire ability of my chracter.
my problem is the logic of my game, the bullet should fire from the position of my chracter, upon game start(not moving the character) fire bullet come from the position of the character, but when i move my character the start position of bullet is not same with the position of character.
The direction of the bullet depends on the direction of the player.
private void update() {
Vector2 direction = new Vector2(0, 0);
if (Gdx.input.isKeyPressed(Keys.D)) {
direction.x = 1f ;
}
if (Gdx.input.isKeyPressed(Keys.A)) {
direction.x = -1f ;
}
if (Gdx.input.isKeyPressed(Keys.W)) {
direction.y = 1f ;
}
if (Gdx.input.isKeyPressed(Keys.S)) {
direction.y = -1f;
}
if (direction.x != 0 || direction.y != 0) {
playerDirection.set(direction);
System.out.println("player x: " +playerDirection.x + "\t" +"player y:"+playerDirection.y);
}
if (Gdx.input.isKeyPressed(Keys.F)) {
bulletPos = new Vector2(startPos);
bulletDirection.set(playerDirection);
}
if (bulletPos != null) {
bulletPos.x += direction.x;
bulletPos.y +=direction.y;
if (bulletPos.x < 0 || bulletPos.x > mapPixelWidth
|| bulletPos.y < 0 || bulletPos.y > mapPixelHeight) {
bulletPos = null;
}
}
}
can anyone knows the logic error, or anyone there can provide simple logic of shooting that fire on a direction?

From what i see, you're always firing button from players start position (startPos), and then, when the bullet is moving, you update its position according to player direction (direction.x, .y)? But when player changes direction, bullet is starting to move other way as well. Thats wrong.
After its created, bullet should be always moved independent from your player. So when you create it, it has to have own start position (taken from current player position), and own direction (based on current player position). Your player movement cannot change bullet position anymore.
Something like:
if (Gdx.input.isKeyPressed(Keys.F)) {
bulletPos.set(currentPlayerPosition);
bulletDirection.set(currentPlayerDirection);
}
//and then in update()
bulletPos.x+=bulletDirection.x;
bulletPos.y+=bulletDirection.y;
//until it goes out of screen, or passes given distance,
//or new bullet is created, or whatever condition you like

Related

as3 - How do you stop moving when touching an object?

How can I make the player stop when it's collding with an object but when it's touching the x side of an object, it can still slide up and down, and when it's touching the y side of an object, it can still slide side to side while colliding.
Here is my code for player movement.
public function onKeyDown(event: KeyboardEvent): void
{
if (event.keyCode == Keyboard.D)
{
isRight = true;
}
if (event.keyCode == Keyboard.A)
{
isLeft = true;
}
if (event.keyCode == Keyboard.W)
{
isUp = true;
}
if (event.keyCode == Keyboard.S)
{
isDown = true;
}
}
public function onEnterFrame(event: Event): void
{
if (isRight)
{
x += 5;
}
if (isLeft)
{
x -= 5;
}
if (isUp)
{
y -= 5;
}
if (isDown)
{
y += 5;
}
}
On each tick of movement (OnEnterFrame in your case) you should perform the following basic steps:
Save player's x and y into variables
Calculate new position
Check if player overlaps any objects or level boundaries in his new position. This can be done in a variety of ways; it's not possible to elaborate without knowing the structure of your level, shape of player, shapes of obstacles, how you store the information about them.
For every overlapping object calculate how much the player overlaps the object and solve the collision by moving player back in its track so that he doesn't collide. You have the previous and the next coordinates, so, you have a vector along which to move the player back.
The difficulty of these steps depends greatly on shapes of objects in question, on maximum relative velocity of colliding objects, on required accuracy of collision solving. If you are dealing with primitives like rectangles and circles that can be relatively easy to implement, albeit there still will be difficult cases like collisions with several objects. Here are some basic tools you may want to look at:
getBounds
hitTestPoint
hitTestObject
Rectangle.intersects
Detecting and solving collisions is one of the most common problems in game development, so you may easily find tons of material on the subject on the net. For instance:
N Tutorial A - Collision Detection and Response
N Tutorial B - Broad-Phase Collision

Repeat a Function when it meets the condition

I have a question about action script 3.
I am making a game, the basic rule of the game is:
an object falls from the top
the hero(user) has to avoid the object
if the object hits the ground or the hero: the hero dies or the object falls again from the top.
I am using the add child method for the object, and timer function for the fall.
the problem is:
when the object hits the ground, the function does not loop. it ends just like that. so there wont be any falling objects anymore.
please help me. thanks :)
stage.addEventListener(Event.ENTER_FRAME, addfire1);
function addfire1(e:Event):void
{
if (api1==false)//if object is not on the stage
{
randomx = randomRange();//generate random X
addChild(api);
api.x = randomx;//set x
api1 = true;//object is now on stage
}
if (api.hitTestObject(hero) || api.hitTestObject(ground))
{
falltimer.stop();
//stop timer;
falltimer.reset();
//reset fall Count to zero ;
removeChild(api);//object removed
api1=false;
}
}
function firefall(Event:TimerEvent):void
{
if (api1)
{
api.y += 20;//set speed y
}
}
Just separate the two cases: hero and floor.
if (api.hitTestObject(hero))
{
falltimer.stop();
//stop timer;
falltimer.reset();
//reset fall Count to zero ;
removeChild(api);//object removed
api1=false;
}
else if (api.hitTestObject(ground))
{
//reset object's position
api.y = -20;
}
Assuming there is only one object falling at the time I'd not remove the object but instead just move it to the original y position and a new x position. And instead of having the timer i'd create an update-function that runs every time you enter a frame.
stage.addEventListener(Event.ENTER_FRAME, update);
private function update(e:Event):void
{
if(!api1) //if object is not on the stage (same as api1==false)
{
addfire1();
}
if(api1) //if object if on stage (same as api1==true)
{
firefall();
}
}
private function addfire1(e:Event):void
{
randomx = randomRange();//generate random X
addChild(api);
api.x = randomx;//set x
api1 = true;//object is now on stage
if (api.hitTestObject(hero))
{
hitHero(); //execute what should happen to the hero when the he is hit
resetFire();
}
else if(api.hitTestObject(ground))
{
resetFire();
}
}
private function firefall(Event:TimerEvent):void
{
api.y += 20;//set speed y
}
private function resetFire():void
{
api.x = randomRange();
api.y = 0;
}
If you write it like this you don't have to mix stuff up. Try to keep everything seperated, one function does one thing. If you are making a big game try to seperate everything in classes.
Hopefully this fixes the problem and makes it easier for you to finish the game :)

how to stop a movieclip on the Y-axis with buttons?

I have two buttons that moves a movieclip up/down the Y-axis. How do I get the movieclip to stop at a certain height, and still be able to move it in the opposite direction?
I need this to work like this:
When you press the down-button, the movieclip goes downwards, but not past Y=500.
When you press the up-button, the movieclip goes upwards, but not past Y= 300.
I get the movieclip to stop at the correct point (500), but when it reaches this point it's stuck..
so it won't go upwards again if I press the up-button.
can someone help me please?:)
here's my code so far:
1) decrease = the down-button
2) increase = up-button
3) stempel = the movieclip I want to stop on the Y-axis
var moveStempel = 0;
decrease.addEventListener(MouseEvent.MOUSE_DOWN, decreasePressed);
decrease.addEventListener(MouseEvent.MOUSE_UP, removeEnterFrame);
increase.addEventListener(MouseEvent.MOUSE_DOWN, increasePressed);
increase.addEventListener(MouseEvent.MOUSE_UP, removeEnterFrame);
function decreasePressed(e:MouseEvent):void
{
moveStempel = 2;
addEnterFrame();
}
function increasePressed(e:MouseEvent):void
{
moveStempel = -2;
addEnterFrame();
}
// ADD ENTER FRAME
function addEnterFrame():void
{
this.addEventListener(Event.ENTER_FRAME, update);
}
function removeEnterFrame(e:MouseEvent):void
{
this.removeEventListener(Event.ENTER_FRAME, update);
}
function update(e:Event):void
{
if (stempel.y < 500)
{
stempel.y += moveStempel;
trace("inside");
}
else if (stempel.y > 500)
{
stempel.stop();
trace("outside");
}
In your code right now, once stempel has a y value greater than 500, it will never be able to move again.
There are two conditions when stempel can move: if it's moving down, it can't be at the bottom of the allowed area, and if it's moving up, it can't be at the top of the allowed area.
if ((stempel.y < 500 && moveStempel == 2) || (stempel.y > 300 && moveStempel == -2))
{
stempel.y += moveStempel;
trace("inside");
}
else
{
stempel.stop();
trace("outside");
}

AS3 Determining what object overlaps it?

I'm current building a game in as3; the proplem I have right now is when I roll the virtual dice, the player(marker) moves accross the board but what I need to know is: is there a way to find the instance name of the object(box) that the player lands on?
And Sorry my english isn't good.
It depends a lot on how your board is laid out. One way is to put all of the objects your player can land on into an array, then check the player's x and y coordinates to see if they fall inside of each object's box.
For example:
var boardObjects:Array; // This would contain references to all the objects the
// player object might land on. Initialize it, then use boardObjects.add(object)
// on each one until they're all in the array.
// once the player has moved:
for(var i:int = 0; i < boardObjects.size; i++) {
var obj:* = boardObjects[i];
if (player.x >= obj.x && player.x <= obj.x + obj.width) {
if (player.y >= obj.y && player.y <= obj.y + obj.height) {
// If these if statements are all true, the Player's top-left corner
// is inside the object's bounding box. If this is a function,
// here is a good spot to put a return statement.
}
}
}
You may want to calculate it based on the middle of the player rather than their top-left corner, in which case just add half the player's width to their x position and half their height to their y position.
For performance (and avoiding unnecessary code), if it's tile based / dice why not do something like this
private function rollDice(){
var results:Array = [Math.ceil(Math.random() * 6), Math.ceil(Math.random() * 6)] //Accurately simulates two 6 sided dice
dice1.rollAnimation(results[0]);
dice2.rollAnimation(results[1]);
player.position += results[0] + results[1];
}
The board would be an array, and in Player you can use getters/setters to 'wrap' the board like this
private var _position:int = 0;
public function get position():int{
return _position;
}
public function set position(value:int){
_position = value;
while(_position > GameBoard.TILES){
_position -= GameBoard.TILES;
}
x = //Whatever you determine the positioning of the player..
}

AS3: How to make this mouse position detection work properly?

I'm new to AS3 so please bare with my basic questions.
What I want to do is have a left arrow MC on the left side of the stage and right arrow MC on the right side of stage. When the mouse is over the left 1/3 of the stage, the left arrow appears, on the right 1/3 of the stage, the right arrow appears, but the middle 1/3 the arrows fade out.
I do NOT want to make large invisible MCs and detect the mouse movement that way. I just want it to be relative to the mouse position on the stage.
I thought it would be very easy, but the eventListener fires everytime the mouse moves, so the left and right arrow MC animation is constantly being triggered, and they look like they are "shaking" for a lack of a better word.
What I have so far is the following. Could someone please give me some help with this?
var stagePos:int = stage.width/3;
addEventListener(MouseEvent.MOUSE_MOVE, arrowDetectHandler);
function arrowDetectHandler(e:MouseEvent) {
var mouseArrow:int = mouseX;
if (mouseArrow<stagePos) {
arrowLeft_mc.gotoAndPlay("Show");
trace ("left arrow show");
} else if (mouseArrow>stagePos && mouseArrow<stagePos*2) {
arrowLeft_mc.gotoAndPlay("Hide");
arrowRight_mc.gotoAndPlay("Hide");
trace ("nothing happens");
} else if (mouseArrow>stagePos*2) {
arrowRight_mc.gotoAndPlay("Show");
trace ("right arrow show");
}
}
if...else seem to be ok. The only thing which may couse the problem is mc.gotoAndPlay. Try to use alpha property instead:
var stagePos:int = stage.width/3;
addEventListener(MouseEvent.MOUSE_MOVE, arrowDetectHandler);
function arrowDetectHandler(e:MouseEvent) {
var mouseArrow:int = mouseX;
if (mouseArrow<stagePos) {
arrowLeft_mc.alpha = 1; //alpha is 1, arrow is shown
trace ("left arrow show");
} else if (mouseArrow>stagePos && mouseArrow<stagePos*2) {
arrowLeft_mc.alpha = 0; //alpha is 0, arrow is hidden
arrowRight_mc.alpha = 0;
trace ("nothing happens");
} else if (mouseArrow>stagePos*2) {
arrowRight_mc.alpha = 1;
trace ("right arrow show");
}
}
The trouble is the speed with which your code is getting called repeatedly.
If you you are listening to MouseEvent.MOUSE_MOVE then it will happen way too fast for any 'gotoAndPlay' business to finish.
Since you don't want to do the invisible MovieClips ( which gives you the very handy MouseEvent.ROLL_OVER and MouseEvent.ROLL_OUT events ) then you are left polling to evaluate coordinates like you have in your code.
You need to remember the last 'answer' your code gave and then ignore the case that is already true next time. You'll have to bear with my preference for switch statements.
var stagePos:int = stage.width/3;
var _arrowShowing : int = 0;
addEventListener(MouseEvent.MOUSE_MOVE, arrowDetectHandler);
function arrowDetectHandler(e:MouseEvent)
{
var mouseArrow:int = mouseX;
switch( true )
{
case ( !_arrowShowing == 1 && mouseArrow < stagePos ) :
_arrowShowing = 1;
arrowLeft_mc.gotoAndPlay("Show");
trace ("left arrow show");
break;
case ( !_arrowShowing == 0 && mouseArrow > stagePos && mouseArrow < stagePos * 2 ) :
_arrowShowing = 0;
arrowLeft_mc.gotoAndPlay("Hide");
arrowRight_mc.gotoAndPlay("Hide");
trace ("nothing happens");
break;
case ( !_arrowShowing == 2 && mouseArrow>stagePos*2 ) :
_arrowShowing = 2;
arrowRight_mc.gotoAndPlay("Show");
trace ("right arrow show");
break;
}
}