I'm programming a little 2d game. Acutally I'm busy with the jumping-function. I want my player to jump, when i press the up-arrow key. I managed to make him jumping, but there is a delay of at least one second. This dealy is not existing for other actions like moving left or right. Do you know where it comes from?
The code for jumping is in the keyReaction method.
public class John<I> extends AbstractGame<I> {
//lists
List<ImageObject<I>> floor = new ArrayList<>();
//variables
double jumpHeight = 0;
//boolean
boolean jump = false;
//fix values
int blockHeight = 40;
int blockWidth = 40;
public John(double width, double height) {
//getPlayer()
super(new ImageObject<>("player.png", new Vertex(120, height - 200), new Vertex(0, 0)), width, height);
//floor objects
for(int i=0; i<getWidth(); i+=blockWidth)
floor.add(new ImageObject<>("brick.png", new Vertex(i, getHeight() - blockHeight)));
//add arrays to canvas
getGOss().add(floor);
}
#Override
public void doChecks() {
for(ImageObject<I> f:floor) {
//gravity
if(!(jump) && !(getPlayer().touches(f)))
getPlayer().getMotion().y++;
//stop y-motion on ground
if(getPlayer().touches(f)){
getPlayer().getPos().y = getHeight() - blockHeight - getPlayer().getHeight();
getPlayer().getMotion().y = 0;}
}
}
#Override
public boolean isStopped(){
return false;
}
#Override
public void keyReaction(KeyCode keycode){
switch (keycode) {
//move left
case LEFT_ARROW:
getPlayer().getMotion().x = -2;
break;
case VK_A:
getPlayer().getMotion().x = -2;
break;
//move right
case RIGHT_ARROW:
getPlayer().getMotion().x = 2;
break;
case VK_D:
getPlayer().getMotion().x = 2;
break;
//jump
case UP_ARROW:
jump = true;
if(jumpHeight < 100){
jumpHeight += 5;
getPlayer().getPos().y -=5;
} else if (jumpHeight < 200){
jumpHeight +=5;
getPlayer().getPos().y +=5;
}
break;
case VK_W:
break;
case SPACE:
break;
}
}
#Override
public void keyReactionReleased(KeyCode keycode){
switch (keycode) {
//move left
case LEFT_ARROW:
getPlayer().getMotion().x = 0;
break;
case VK_A:
getPlayer().getMotion().x = 0;
break;
//move right
case RIGHT_ARROW:
getPlayer().getMotion().x = 0;
break;
case VK_D:
getPlayer().getMotion().x = 0;
break;
//jump
case UP_ARROW:
jump = false;
jumpHeight = 0;
break;
case VK_W:
jump = false;
break;
case SPACE:
break;
}
}
//test main
public static void main(String[] args) {
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(new SwingScreen(new John<>(1800, 600)));
f.pack();
f.setVisible(true);
}
}
Thank you for your help.
Code with the if:
case UP_ARROW:
if(jumpHeight < 20){
jumpHeight += 5;
getPlayer().getPos().y = -5;
} else if (jumpHeight < 40){
jumpHeight +=5;
getPlayer().getPos().y = 5;
}
break;
Code without the if:
case UP_ARROW:
getPlayer().getPos().y = -5;
break;
KeyReaction:
setOnKeyPressed((ev)->{
logic.keyReaction(KeyCode.fromCode(ev.getCode().impl_getCode()));
ev.consume();
});
setOnKeyReleased((ev)->{
logic.keyReactionReleased(KeyCode.fromCode(ev.getCode().impl_getCode()));
ev.consume();
});
In your jumpheight method you have
jump = true;
if(jumpHeight < 100){
jumpHeight += 5;
getPlayer().getPos().y -=5;
} else if (jumpHeight < 200){
jumpHeight +=5;
getPlayer().getPos().y +=5;
}
break;
On the 4th line there, you have a -=5 for the pos. There is likely another method that prevents the ypos from going under 0. What happens then is you press the up arrow, it gets sent 40 times(200/5), eventually the jumpheight is greater than 200, and only then does the player start moving up.
Related
Here's my code that the error points to:
shipX = shipOne.getX();
EDIT2: Specifically it cannot find shipOne.
The Ship object, shipOne, is initialized inside a Switch statement not ten lines prior to the above code. I'm fairly certain that the error is appearing due to the object being initialized inside the Switch statement, and I don't know what to do about that. There are a total of eight Ship objects that are initialized via a loop and as such the above code needs to either be in a Switch statement or an If statement, both of which I'm sure would cause the same error. Is there an exception I can throw or something that would cause my program to run? The Ship objects do get initialized 100% of the time so there's no worry there.
EDIT: I was asked for the rest of the code so here it be:
(This isn't the entirety of it, as you can't see the return statement but the remainder isn't relevant to my problem).
public static String[][] createFleet()
{
//Initialize Variables
//Ship Variables
boolean isHoriz = true; //Is true if ship is Horizontal, false if Vertical
char ID;
int posX = 0; //Origin of the ship (x coordinate [row])
int posY = 0; //Origin of the ship (y coordinate [column])
int size = 0; //Either 2, 3, or 4
//Associated Variables
Random randomGen = new Random(); //Random number generator
String[][] board = new String[10][10]; //Gameboard, populated with ships
int orientationRand = 0; //If 0, Ship Horizontal. If 1, Ship Vertical
int posRand = 0; //Assigned to posX or posY
int sizeRand = 0; //If 0 <= x < 10, size = 2
//If 10 <= x < 40, size = 3
//If 40 <= x < 100, size = 4
//Create Ships
for (int i = 0; i < 8; i++)
{
//Size
sizeRand = randomGen.nextInt(100);
if (sizeRand < 10)
{
size = 2;
}
else if (sizeRand < 40)
{
size = 3;
}
else size = 4;
//Orientation & Position
orientationRand = randomGen.nextInt(2);
if (orientationRand == 0)
{
//Orientation
isHoriz = true;
//Position (horizontal)
//x position
switch (size)
{
case 2:
posRand = randomGen.nextInt(9);
posX = posRand;
break;
case 3:
posRand = randomGen.nextInt(8);
posX = posRand;
break;
case 4:
posRand = randomGen.nextInt(7);
posX = posRand;
break;
}
//y position
posRand = randomGen.nextInt(10);
posY = posRand;
}
else
{
//Orientation
isHoriz = false;
//Position (vertical)
//x position
posRand = randomGen.nextInt(10);
posX = posRand;
//y position
switch (size)
{
case 2:
posRand = randomGen.nextInt(9);
posY = posRand;
break;
case 3:
posRand = randomGen.nextInt(8);
posY = posRand;
break;
case 4:
posRand = randomGen.nextInt(7);
posY = posRand;
break;
}
}
//Assign Size, Orientation, and Position to each ship
switch (i)
{
case 0:
ID = 'A';
Ship shipOne = new Ship(posX, posY, size, isHoriz, ID);
break;
case 1:
ID = 'B';
Ship shipTwo = new Ship(posX, posY, size, isHoriz, ID);
break;
case 2:
ID = 'C';
Ship shipThree = new Ship(posX, posY, size, isHoriz, ID);
break;
case 3:
ID = 'D';
Ship shipFour = new Ship(posX, posY, size, isHoriz, ID);
break;
case 4:
ID = 'E';
Ship shipFive = new Ship(posX, posY, size, isHoriz, ID);
break;
case 5:
ID = 'F';
Ship shipSix = new Ship(posX, posY, size, isHoriz, ID);
break;
case 6:
ID = 'G';
Ship shipSeven = new Ship(posX, posY, size, isHoriz, ID);
break;
case 7:
ID = 'H';
Ship shipEight = new Ship(posX, posY, size, isHoriz, ID);
break;
}
}
In your code, 'ID' variable is not getting declared anywhere. You must declare variable before using it.
Initialize the objects to null before the switch or if statements. I think this should solve your problem.
It will be possible to provide a better solution if the entire code was posted.
I'm brand new to game development and have chosen to start working on a 2D top-down scroller game. I'm using the Slick2D library for this game.
My question is about best practices for taking multiple direction input for sprite movement (UP + RIGHT = Diagonal)
Currently, I have a rather ugly looking if/elseif chain to read in the input from the keyboard that is then checked in the 'Mob' class to determine how the sprite will move. The current setup works just fine, but my question is if there is another, better way of going about taking multiple inputs for diagonals (or any combo of keys, for that matter)
Here is the main class's update method that reads the input (blooper is the instance of 'Mob'):
public void update(GameContainer container, StateBasedGame arg1, int delta) throws SlickException {
Input input = container.getInput();
if(input.isKeyDown(Input.KEY_RIGHT)) { //RIGHT
if(input.isKeyDown(Input.KEY_UP)){ //RIGHT + UP
blooper.direction = 2;
} else if(input.isKeyDown(Input.KEY_DOWN)){ //RIGHT + DOWN
blooper.direction = 3;
}
else {
blooper.direction = 1;
}
} else if(input.isKeyDown(Input.KEY_LEFT)){ //LEFT
if(input.isKeyDown(Input.KEY_UP)){ //LEFT + UP
blooper.direction = 5;
} else if(input.isKeyDown(Input.KEY_DOWN)){ //LEFT + DOWN
blooper.direction = 6;
} else{
blooper.direction = 4;
}
} else if(input.isKeyDown(Input.KEY_UP)){ //UP
if(input.isKeyDown(Input.KEY_RIGHT)){ //UP + RIGHT
blooper.direction = 8;
} else if(input.isKeyDown(Input.KEY_LEFT)){ //UP + LEFT
blooper.direction = 9;
} else{
blooper.direction = 7;
}
} else if(input.isKeyDown(Input.KEY_DOWN)){ //DOWN
if(input.isKeyDown(Input.KEY_RIGHT)){ //DOWN + RIGHT
blooper.direction = 11;
} else if(input.isKeyDown(Input.KEY_LEFT)){ //DOWN + LEFT
blooper.direction = 12;
} else{
blooper.direction = 10;
}
} else{
blooper.direction = -1;
}
blooper.update(delta);
}
And here is how that input is processed in the Mob class:
public class Mob {
private final int RIGHT = 1;
private final int RIGHTUP = 2;
private final int RIGHTDOWN = 3;
private final int LEFT = 4;
private final int LEFTUP = 5;
private final int LEFTDOWN = 6;
private final int UP = 7;
private final int UPRIGHT = 8;
private final int UPLEFT = 9;
private final int DOWN = 10;
private final int DOWNRIGHT = 11;
private final int DOWNLEFT = 12;
private final int IDLE = -1;
int direction = IDLE;
int x, y;
Image sprite;
public Mob() throws SlickException{
x = 20;
y = 20;
sprite = new Image("res/blooper.png");
}
public void update(int delta){
move();
}
public void draw(){
sprite.draw(x, y);
}
public void move(){
switch(direction){
case RIGHT:
x += 1;
break;
case RIGHTUP:
x += 1;
y -= 1;
break;
case RIGHTDOWN:
x += 1;
y += 1;
break;
case LEFT:
x -= 1;
break;
case LEFTUP:
x -= 1;
y -= 1;
break;
case LEFTDOWN:
x -= 1;
y += 1;
break;
case UP:
y -= 1;
break;
case UPRIGHT:
y -= 1;
x += 1;
break;
case UPLEFT:
y -= 1;
x -= 1;
break;
case DOWN:
y += 1;
break;
case DOWNRIGHT:
y += 1;
x += 1;
break;
case DOWNLEFT:
y += 1;
x -= 1;
break;
case IDLE:
//nothing
}
}
}
Like I said...this works, but doesn't seem like the best way to go about it. Any tips?
Make left/right and up/down movement independent. You (or the framework - I'm unfamiliar with it) seems to work with x/y coordinates, which are mathematically independent.
Thus make one function that treats the up/down movement, and one function that treats the left/right movement, and you can get rid of their 'combinations'. Is there a reason why the directions are positive integers? Try making left = -1, right = 1, and no x-direction movement 0, and then do the same for y. That should hopefully make it more intuitive.
Happy coding
Make a blooper.direction a bitwise, like:
blooper.direction=0;
if(input.isKeyDown(Input.KEY_RIGHT)) blooper.direction|=1;
if(input.isKeyDown(Input.KEY_LEFT)) blooper.direction|=2;
if(input.isKeyDown(Input.KEY_UP)) blooper.direction|=4;
if(input.isKeyDown(Input.KEY_DOWN)) blooper.direction|=8;
then in move do the move, like:
if ((blooper.direction&1)!=0) x+=1;
if ((blooper.direction&2)!=0) x-=1;
if ((blooper.direction&4)!=0) y-=1;
if ((blooper.direction&8)!=0) y+=1;
could you help me to make my sprite walk left and right ? i just cant see where the problem is.
I've spend 3 hours looking at the code but i just cant see where i've made mistake ...
class Player {
PImage playerr;
PVector position;
PVector velocity;
float direction;
float speed;
float ground = 600;
float left;
float right;
Player()
{
playerr = loadImage("sir1.png");
position = new PVector(400, ground);
direction = 1;
speed = 4;
velocity = new PVector(0, 0);
}
void update()
{
velocity.x = speed * (left + right);
PVector nextPosition = new PVector(position.x, position.y);
pushMatrix();
translate(position.x, position.y);
scale(direction, 1);
image(playerr, 0, 0);
popMatrix();
}
void keyPressed()
{
if (key == RIGHT)
{
right += 5;
direction = -1;
}
if (key == LEFT)
{
left -= 5;
direction = 1;
}
}
void keyReleased()
{
if (key == RIGHT)
{
right = 0;
}
if (key == LEFT)
{
left = 0;
}
}
}
and that's the main program
int stage;
PFont startfont;
PFont normalfont;
PImage gameplan;
boolean[] keys = new boolean[526];
ArrayList knight;
void setup()
{
size(800,800);
frameRate(60);
stage = 1;
knight = new ArrayList();
smooth();
}
void draw()
{
switch(stage)
{
case 1:
splash();
break;
case 2:
game();
break;
case 3:
help();
break;
case 4:
help();
break;
}
}
void game()
{
gameplan = loadImage("background.png");
gameplan.resize(800,800);
background(gameplan);
knight.add(new Player());
for(int i = 0; i <knight.size(); i++)
{
Player p = (Player) knight.get(i);
p.update();
}
}
void splash()
{
background(0);
startfont = createFont("start.ttf",40);
normalfont = createFont("start.ttf",25);
textFont(startfont);
text("Zombie Destruction",100,300);
textFont(normalfont);
text("Press Space to start",200,400);
text("Press H for help",250,500);
if(keyPressed)
{
if(key == 'h' || key == 'H')
{
stage = 4;
}
}
if(keyPressed)
{
if(key == ' ')
{
stage = 2;
}
}
}
void help()
{
background(0);
startfont = createFont("start.ttf",40);
normalfont = createFont("start.ttf",25);
textFont(normalfont);
text("Zombie Destruction",100,300);
textFont(normalfont);
text("Press Space to go back",200,400);
if(keyPressed)
{
if(key == 'b')
{
stage = 1;
}
else
{
stage = 4;
}
}
}
I believe the problem is in the Player class's update() method. It looks like you're calculating the updated velocity, but you never add that velocity to the player's position. A simple
position.x += velocity.x;
should do the trick.
I have a java Applet in which I use a Key Listener. When I run it in Eclipse, it runs fine and the way I desire it. I have put it into a webpage, and the Applet behaves differently. I am clueless as to why. I have included my code below, as well as a link to the Applet. I would ideally like to be able to move the small square when I press a button. As it is right now on the webpage, it acts as though I have sticky keys. I do not want this. Also, 'W A S D' do not work to move the square. Only the arrow keys do. I would like both of them to be able to control the rectangle.
Thanks for your help in advance,
~Rane
Key Listener:
public void keyPressed(KeyEvent e) {
// TODO Auto-generated method stub
switch(e.getKeyCode()) {
case KeyEvent.VK_UP:
dy = -1;
break;
case KeyEvent.VK_RIGHT:
dx = 1;
break;
case KeyEvent.VK_DOWN:
dy = 1;
break;
case KeyEvent.VK_LEFT:
dx = -1;
break;
case KeyEvent.VK_W:
dy = -1;
break;
case KeyEvent.VK_D:
dx = 1;
break;
case KeyEvent.VK_S:
dy = 1;
break;
case KeyEvent.VK_A:
dx = -1;
break;
}
}
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub
switch(e.getKeyCode()) {
case KeyEvent.VK_UP:
dy = 0;
break;
case KeyEvent.VK_RIGHT:
dx = 0;
break;
case KeyEvent.VK_DOWN:
dy = 0;
break;
case KeyEvent.VK_LEFT:
dx = 0;
break;
case KeyEvent.VK_W:
dy = 0;
break;
case KeyEvent.VK_D:
dx = 0;
break;
case KeyEvent.VK_S:
dy = 0;
break;
case KeyEvent.VK_A:
dx = 0;
break;
}
}
Moving the square:
if(dy < 0)) {
playerY --;
}
if(dx > 0) {
playerX ++;
}
if(dy > 0 {
playerY ++;
}
if(dx < 0) {
playerX --;
}
Drawing the square:
g.drawRect(playerX, playerY, 20, 20);
Requesting Focus in class that extends Applet:
this.setFocusable(true);
this.requestFocusInWindow();
this.requestFocus();
This question already has an answer here:
Closed 10 years ago.
Possible Duplicate:
memory game graphics java
I'm coding a program that is a 4x4 memory game. Within these 16 boxes will be a pair of integers from 0-7. I have all of that already randomized and coded correctly. Now I'm trying to figure out how to pair the colors with the corresponding integers each time the mouse clicks over the box.
Here most of the code. I know the logic for this game isn't started yet, but I'm more focused on the displayHit method and setColor method right now. Just posting the whole code because maybe I messed up somewhere else.
/*Sets the background of your memory board to black*/
public void init()
{
setSize(400,400);
setBackground(Color.BLACK);
buildBoard(4);
}
/*This is main in java applets
You may need to add (not change) a couple things in this method
*/
public void paint(Graphics canvas)
{
if(firstRun) //for the first run we need to build our random board
{
print2DArray(board);
buildBoard(4);
firstRun = false;
}
else // once our board is built we will display the game
{
displayGame(canvas);
if (mouseClicked) // if the mouse has been clicked
{
displayHit(canvas);//find which box the user clicked
mouseClicked = false;
}
}
}
/*
DO NOT change this method
determines if the mouse has been pressed
sets x and y Mouse to the location of the mouse arrow
redraws the image
*/
public boolean mouseDown(Event e, int x, int y )
{
mouseClicked = true;
xMouse = x;
yMouse = y;
repaint();
return true;
}
/*DO NOT change this method
redraws the scene
*/
public void update ( Graphics g )
{
paint(g);
}
/*
pre: none
post: build an array that holds the memory values for a board of size x size
the board will hold two of each int from 0 to size randomly placed in the array
*/
public void buildBoard(int s)
{
int a = 4;
for (int row = 0; row < a; row++)
for (int column = 0; column < a; column++)
{
board[row][column] = count++ % 8;
}
for(int row = 0; row < 4; row++)
for(int column = 0; column < 4; column ++)
{
int x = (int)Math.floor(Math.random()*4);
int y = (int)Math.floor(Math.random()*4);
temp = board[row][column];
board[row][column] = board[x][y];
board[x][y] = temp;
}
}
public static void print2DArray(int[][] arr)
{
for (int row = 0; row < arr.length; row++)
{
for (int col = 0; col < arr[row].length; col++)
{
System.out.print(arr[row][col] + " ");
}
System.out.println();
}
}
public void displayGame(Graphics canvas)
{
canvas.setColor(Color.WHITE);
for(int i =0; i < 400; i+= WIDTH)
for(int j = 0; j < 400; j+= WIDTH)
canvas.drawRect(i, j, WIDTH, WIDTH);
}
/*
Pre: xMouse and yMouse have been initialized
Post: A circle is displayed in the correct box on the screen
Currently the circle is displayed at the mouse location
*/
public void displayHit(Graphics g)
{
setColor(g);
centerHit(xMouse, xMouse);
g.fillOval(xMouse, yMouse, 40, 40);
}
public void setColor(Graphics g)
{
switch(temp)
{
case 0: g.setColor(Color.RED);
break;
case 1: g.setColor(Color.GREEN);
break;
case 2: g.setColor(Color.BLUE);
break;
case 3: g.setColor(Color.ORANGE);
break;
case 4: g.setColor(Color.CYAN);
break;
case 5: g.setColor(Color.MAGENTA);
break;
case 6: g.setColor(Color.PINK);
break;
case 7: g.setColor(Color.YELLOW);
break;
}
}
public void centerHit(int centerX, int centerY)
{
{
if ((xMouse > 0) && (xMouse <=100))
xMouse = 33;
else if ((xMouse > 100) && (xMouse <=200))
xMouse = 133;
else if ((xMouse > 200) && (xMouse <=300))
xMouse = 233;
else if ((xMouse > 300) && (xMouse <=400))
xMouse = 333;
}
{
if ((yMouse > 0) && (yMouse <=100))
yMouse = 33;
else if ((yMouse > 100) && (yMouse <=200))
yMouse = 133;
else if ((yMouse > 200) && (yMouse <=300))
yMouse = 233;
else if ((yMouse > 300) && (yMouse <=400))
yMouse = 333;
}
}
}
It looks like temp is never changed once buildBoard is called. Which is why you always see the same colour.
this code is fine
public void setColor(Graphics g)
{
switch(temp)
{
case 0: g.setColor(Color.RED);
break;
case 1: g.setColor(Color.GREEN);
break;
case 2: g.setColor(Color.BLUE);
break;
case 3: g.setColor(Color.ORANGE);
break;
case 4: g.setColor(Color.CYAN);
break;
case 5: g.setColor(Color.MAGENTA);
break;
case 6: g.setColor(Color.PINK);
break;
case 7: g.setColor(Color.YELLOW);
break;
}
}
but you are not setting temp anywhere in the code to choose which case/colour you want to use. you need to change temp when you click on a square either by hardcoding it or randomly generating a number between 0-7 to set the colour randomly