This site requires JavaScript, please enable it in your browser!
Greenfoot back
SushiLlama
SushiLlama wrote ...

2019/10/9

Tank Game Turret Rotation and Tank Movement Problem

1
2
SushiLlama SushiLlama

2019/10/9

#
Hello, i wanted to create a Wii Play Tanks like game. For this, i need a tank which has a body and a turnable turret on top. Sadly my gun barrel is long so that the center of the turret image isnt the desired center for the turning dependent of the mouse icon position. I´ve read some articles on this topic but the solutions didnt really work out sadly. Also the turret is pointing -90 degrees relative to the mouse (if the mouse is on the right hand side of the tank, the barrel points to the top rather than to the right). Also i cant figure out how to move my tank in its direction (forward and backward) (without turning the image!). Can i somehow have the Turret and Tank in one class with two independent images? Or is this already as clean it can get? Heres my code:
import greenfoot.*;  
public class Tank extends Actor
{
    protected int rotation;
    protected Turret turret;
    protected TankWorld world;
    private GreenfootImage tankImage = new GreenfootImage("Tank_Blue_Base_Idle.png");
    public Tank() {
        setImage(tankImage);
        getImage().scale(40,70);
        rotation = 0;
        setRotation(rotation);
        this.world = (TankWorld) getWorld();
    }
    public TankWorld getTankWorld() {
        return this.world;
    }
    public void act() {
        if(Greenfoot.isKeyDown("w")) {
            //Move forward 
        } else if(Greenfoot.isKeyDown("a")) {
            turn(-1);
        } else if(Greenfoot.isKeyDown("s")) {
            //Move backward   
        } else if(Greenfoot.isKeyDown("d")) {
            turn(1);  
        }        
    }
}


import greenfoot.*; 
public class Turret extends Actor
{
    private Tank tank;
    private GreenfootImage turretImage = new GreenfootImage("Tank_Blue_Turret_Idle.png");
    public Turret(Tank tank) {
        setImage(turretImage);
        getImage().scale(30,60);
        this.tank = tank;
    }
    public void act() {
        setLocation(tank.getX(), tank.getY()); 
        turnTowards(Greenfoot.getMouseInfo().getX(),Greenfoot.getMouseInfo().getY());
    }    
}
Thank you in advance!
danpost danpost

2019/10/10

#
SushiLlama wrote...
my gun barrel is long so that the center of the turret image isnt the desired center for the turning dependent of the mouse icon position.
Make the turning point the center of the image. In the barrel constructor, draw the image onto the a new image of proper length (2 times the distance from wanted center to image edge at barrel end).
the turret is pointing -90 degrees relative to the mouse (if the mouse is on the right hand side of the tank, the barrel points to the top rather than to the right).
Either add:
turn(90);
after your turnTowards to the mouse or create an image with the barrel initially pointing to the right.
how to move my tank in its direction (forward and backward) (without turning the image!).
Use the setLocation method for moving instead of rotating the tank and using the move method.
Can i somehow have the Turret and Tank in one class with two independent images?
Actually, you can. My Tank Target Practice scenario has the Turret class within the Tank class. You are supposed to be able to look at the code at game over when logged onto the site. I noticed (just now), however, that the code is not showing. I will try to find, fix and upload it to work properly.
danpost danpost

2019/10/10

#
I was mistaken. There is no Turret class in that scenario. An anonymous class was used to create the turret within the Tank class. Interestingly enough, there are a Shot and a Track class within the class. The code should be able to be viewed now. Log onto the site and click Run on the scenario. Wait about 15-20 seconds without shooting (until game over). When high scores show, you will have some buttons across the bottom to show the various class codes.
SushiLlama SushiLlama

2019/10/10

#
 public TurretGun()

    {

        int wide = getImage().getWidth();  

        int high = getImage().getHeight();  

        GreenfootImage base;  

        base = new GreenfootImage(wide, high+56);  

        base.drawImage(getImage(), 0, 56);

        setImage(base);

    }

I found this in an older thread. Sadly this does not work because the "base" Image then isnt my specific TurretImage for the game but the standard greenfoot logo, which gets really stretched. How is this happening? Can i have a really large world (1920×1080 pixels ) and shrink it to my 14 inch screen? Because above 1100×600 i must scroll to view every part of the scenario. Thanks!
SushiLlama SushiLlama

2019/10/10

#
how to move my tank in its direction (forward and backward) (without turning the image!).
danpost wrote...
Use the setLocation method for moving instead of rotating the tank and using the move method
. But using the setLocation method i can only move in for directions (y+,y-,x+,x-) and lets say my tank is at an angle of 30 degrees, i want it to drive forward 30 degrees. :(
danpost danpost

2019/10/10

#
SushiLlama wrote...
<< Code Omitted >> I found this in an older thread. Sadly this does not work because the "base" Image then isnt my specific TurretImage for the game but the standard greenfoot logo, which gets really stretched. How is this happening?
That code was probably specific to the creator of that thread. You new code might have some similarities, but won't be the same.
Can i have a really large world (1920×1080 pixels ) and shrink it to my 14 inch screen? Because above 1100×600 i must scroll to view every part of the scenario.
Worlds of such are large size tend to cause memory issues and should be avoided. My recommendation is generally not to exceed a size of 800 x 600. If you need or want a larger play field, an auto scrolling system would be recommended (a world of nominal size where the main actor stays in view while everything else moves to keep that actor in view, thus allowing for a "larger" world).
SushiLlama wrote...
<< Quotes Omitted >> But using the setLocation method i can only move in for directions (y+,y-,x+,x-) and lets say my tank is at an angle of 30 degrees, i want it to drive forward 30 degrees. :(
Maybe I misunderstood, as there is what seems to be a contradiction between "(without turning the image)" in what I quoted of you and "is at an angle of 30 degrees" in your last post, which requires turning the image. Please clarify your issue more clearly. Wait -- I see. You have not used anything for moving yet (at least in the code previously given).. Use the move method (move(<< speed value >>); for forward and move(<< negative speed value >>); for backward)
SushiLlama SushiLlama

2019/10/10

#
danpost wrote...
SushiLlama wrote...
<< Code Omitted >> I found this in an older thread. Sadly this does not work because the "base" Image then isnt my specific TurretImage for the game but the standard greenfoot logo, which gets really stretched. How is this happening?
That code was probably specific to the creator of that thread. You new code might have some similarities, but won't be the same.
Can i have a really large world (1920×1080 pixels ) and shrink it to my 14 inch screen? Because above 1100×600 i must scroll to view every part of the scenario.
Worlds of such are large size tend to cause memory issues and should be avoided. My recommendation is generally not to exceed a size of 800 x 600. If you need or want a larger play field, an auto scrolling system would be recommended (a world of nominal size where the main actor stays in view while everything else moves to keep that actor in view, thus allowing for a "larger" world).
SushiLlama wrote...
<< Quotes Omitted >> But using the setLocation method i can only move in for directions (y+,y-,x+,x-) and lets say my tank is at an angle of 30 degrees, i want it to drive forward 30 degrees. :(
Maybe I misunderstood, as there is what seems to be a contradiction between "(without turning the image)" in what I quoted of you and "is at an angle of 30 degrees" in your last post, which requires turning the image. Please clarify your issue more clearly. Wait -- I see. You have not used anything for moving yet (at least in the code previously given).. Use the move method (move(<< speed value >>); for forward and move(<< negative speed value >>); for backward)
I want to have the tank turn only when i turn left or right. when moving backwards i dont want to set any rotation but just move in the opposite way of looking. If i am looking to the right i want the tank to go left on s and forward on w. I hope this makes sense. Could you further tell me how to manipulate the turret image so that it doesnt turn weirdly anymore (set my desired location in the center of the image(i only need to effect the height since the new center point is on the same x)) The image size is 194 x 370 and i want 97,273 as the center. Now so the offset is (0|128).
danpost danpost

2019/10/10

#
SushiLlama wrote...
I want to have the tank turn only when i turn left or right. when moving backwards i dont want to set any rotation but just move in the opposite way of looking. If i am looking to the right i want the tank to go left on s and forward on w. I hope this makes sense.
Yes, it makes sense. Use the move method.
Could you further tell me how to manipulate the turret image so that it doesnt turn weirdly anymore (set my desired location in the center of the image(i only need to effect the height since the new center point is on the same x)) The image size is 194 x 370 and i want 97,273 as the center. Now so the offset is (0|128).
Create an image of size 194 x 526. Draw your current image onto it at (0, 0) and set it as the image of the actor.
SushiLlama SushiLlama

2019/10/10

#
Using the move method the rotation is rounded to 45° amount. So i only have 8 instead of 359 directions.
danpost danpost

2019/10/10

#
I just looked over more of your code. In your Tank class, I see the following things: * lines 15 thru 17: the Actor class provides a getWold method (you can remove these lines); * line 13: getWorld will return null at the time this line is exected (you can remove the line); * lines 11 and 12: rotation is initially zero without having to do anything (you can remove these lines); * line 4: the rotation is already tracked by an Actor class field (you can remove the line); * line 6: the world the actor is in is also tracked by an Actor class field (you can remove the line);
danpost danpost

2019/10/10

#
SushiLlama wrote...
Using the move method the rotation is rounded to 45° amount. So i only have 8 instead of 359 directions.
You will need to track the position of the tank more precisely using double values or by scaling up the units (that is, using a smooth moving system). Optionally, you can use the SmoothMover class provided by greenfoot (menubar: Edit>Import class...), or use my QActor class (found in my Asteroids w/Improved QActor class scenario, or create a system of your own. The SmoothMover class only provides for precise positioning using double values; my QActor class uses scaling and will also provide precise rotating.
SushiLlama SushiLlama

2019/10/10

#
danpost wrote...
SushiLlama wrote...
Using the move method the rotation is rounded to 45° amount. So i only have 8 instead of 359 directions.
You will need to track the position of the tank more precisely using double values or by scaling up the units (that is, using a smooth moving system). Optionally, you can use the SmoothMover class provided by greenfoot (menubar: Edit>Import class...), or use my QActor class (found in my Asteroids w/Improved QActor class scenario, or create a system of your own. The SmoothMover class only provides for precise positioning using double values; my QActor class uses scaling and will also provide precise rotating.
And there is no other way of doing this? The SmoothMover seems to be to complicated for me... SmoothMover.move(0.5) didnt work and there is nothing to get or set the Position as Double values. But anyway, i dont understand how keeping track of position and rotation helps to move in my desired 359 directions. Integers should be good enough for that and further i only turn full values (1|-1) why can i only move in 0,45,90,135,180,225,270,315,360(0) direction, even when getRotation() returns the right values? Could you show me how to implement your QActor so that i can turn and move around in any direction? Would make my day!!!
danpost danpost

2019/10/10

#
SushiLlama wrote...
And there is no other way of doing this?
Not really.
The SmoothMover seems to be to complicated for me... SmoothMover.move(0.5) didnt work and there is nothing to get or set the Position as Double values.
Well, first you would have your Tank class extend the support class (whether it is the SmoothMover or my QActor). You would not then use the class name to call a method in that support class and the support class will keep track of the "exact" position for you.
i dont understand how keeping track of position and rotation helps to move in my desired 359 directions. Integers should be good enough for that and further i only turn full values (1|-1) why can i only move in 0,45,90,135,180,225,270,315,360(0) direction, even when getRotation() returns the right values?
The problem is that when moving small distances, there are not many pixels that your actor can move to. When moving one cell at a time, you are limited to the 8 pixels surrounding the current pixel location of the actor. Hence, the 8 directions you have listed (360 being a duplicate of 0, as you have noted).
Could you show me how to implement your QActor so that i can turn and move around in any direction?
First add the QActor class to your project. Do not under any circumstances make any changes to the class. Next, have your Tank class extend the QActor class. Finally, add '*QVAL' to all turn and move calls. For example:
move(1*QVAL);
SushiLlama SushiLlama

2019/10/10

#
danpost wrote...
SushiLlama wrote...
And there is no other way of doing this?
Not really.
The SmoothMover seems to be to complicated for me... SmoothMover.move(0.5) didnt work and there is nothing to get or set the Position as Double values.
Well, first you would have your Tank class extend the support class (whether it is the SmoothMover or my QActor). You would not then use the class name to call a method in that support class and the support class will keep track of the "exact" position for you.
i dont understand how keeping track of position and rotation helps to move in my desired 359 directions. Integers should be good enough for that and further i only turn full values (1|-1) why can i only move in 0,45,90,135,180,225,270,315,360(0) direction, even when getRotation() returns the right values?
The problem is that when moving small distances, there are not many pixels that your actor can move to. When moving one cell at a time, you are limited to the 8 pixels surrounding the current pixel location of the actor. Hence, the 8 directions you have listed (360 being a duplicate of 0, as you have noted).
Could you show me how to implement your QActor so that i can turn and move around in any direction?
First add the QActor class to your project. Do not under any circumstances make any changes to the class. Next, have your Tank class extend the QActor class. Finally, add '*QVAL' to all turn and move calls. For example:
move(1*QVAL);
Wow! Thanks for the explanation for why it does not work as easy as i wanted and also thanks for showing me how to solve it! Got it all done! Works flawlessly!
danpost danpost

2019/10/10

#
SushiLlama wrote...
(deleted) i wonder why i get NullPointerExceptions in line 13 in Turret.class. << Codes Omitted >>
If there is no mouse action, no MouseInfo object is created for that act cycle. Therefore, getMouseInfo may return a null value -- and you cannot call a method (such as getX or getY) on a non-existent object. Make sure the returned value is not null before calling any methods on it.
There are more replies on the next page.
1
2